1 /* Copyright (c) 2007, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include <gdk/gdkkeysyms.h>
36 #include <tny-simple-list.h>
38 #include <modest-platform.h>
39 #include <modest-runtime.h>
40 #include <modest-attachment-view.h>
41 #include <modest-attachments-view.h>
42 #include <modest-tny-mime-part.h>
44 static GObjectClass *parent_class = NULL;
52 typedef struct _ModestAttachmentsViewPrivate ModestAttachmentsViewPrivate;
54 struct _ModestAttachmentsViewPrivate
59 GtkWidget *rubber_start;
62 #define MODEST_ATTACHMENTS_VIEW_GET_PRIVATE(o) \
63 (G_TYPE_INSTANCE_GET_PRIVATE ((o), MODEST_TYPE_ATTACHMENTS_VIEW, ModestAttachmentsViewPrivate))
65 static gboolean button_press_event (GtkWidget *widget, GdkEventButton *event, ModestAttachmentsView *atts_view);
66 static gboolean motion_notify_event (GtkWidget *widget, GdkEventMotion *event, ModestAttachmentsView *atts_view);
67 static gboolean button_release_event (GtkWidget *widget, GdkEventButton *event, ModestAttachmentsView *atts_view);
68 static gboolean key_press_event (GtkWidget *widget, GdkEventKey *event, ModestAttachmentsView *atts_view);
69 static gboolean focus_out_event (GtkWidget *widget, GdkEventFocus *event, ModestAttachmentsView *atts_view);
70 static gboolean focus (GtkWidget *widget, GtkDirectionType direction, ModestAttachmentsView *atts_view);
71 static GtkWidget *get_att_view_at_coords (ModestAttachmentsView *atts_view,
72 gdouble x, gdouble y);
73 static void unselect_all (ModestAttachmentsView *atts_view);
74 static void set_selected (ModestAttachmentsView *atts_view, ModestAttachmentView *att_view);
75 static void select_range (ModestAttachmentsView *atts_view, ModestAttachmentView *att1, ModestAttachmentView *att2);
76 static void clipboard_get (GtkClipboard *clipboard, GtkSelectionData *selection_data,
77 guint info, gpointer userdata);
78 static void clipboard_clear (GtkClipboard *clipboard, gpointer userdata);
79 static void own_clipboard (ModestAttachmentsView *atts_view);
81 static guint signals[LAST_SIGNAL] = {0};
84 * modest_attachments_view_new:
87 * Constructor for attachments view widget.
89 * Return value: a new #ModestAttachmentsView instance implemented for Gtk+
92 modest_attachments_view_new (TnyMsg *msg)
94 ModestAttachmentsView *self = g_object_new (MODEST_TYPE_ATTACHMENTS_VIEW,
95 "resize-mode", GTK_RESIZE_PARENT,
98 modest_attachments_view_set_message (self, msg);
100 return GTK_WIDGET (self);
104 modest_attachments_view_set_message (ModestAttachmentsView *attachments_view, TnyMsg *msg)
106 ModestAttachmentsViewPrivate *priv = MODEST_ATTACHMENTS_VIEW_GET_PRIVATE (attachments_view);
109 const gchar *msg_content_type = NULL;
111 if (msg == priv->msg) return;
114 g_object_unref (priv->msg);
116 g_object_ref (G_OBJECT(msg));
120 g_list_free (priv->selected);
121 priv->selected = NULL;
123 gtk_container_foreach (GTK_CONTAINER (priv->box), (GtkCallback) gtk_widget_destroy, NULL);
125 if (priv->msg == NULL) {
129 /* If the top mime part is a multipart/related, we don't show the attachments, as they're
130 * embedded images in body */
131 msg_content_type = tny_mime_part_get_content_type (TNY_MIME_PART (priv->msg));
132 if ((msg_content_type != NULL) && !strcasecmp (msg_content_type, "multipart/related")) {
133 gtk_widget_queue_draw (GTK_WIDGET (attachments_view));
137 parts = TNY_LIST (tny_simple_list_new ());
138 tny_mime_part_get_parts (TNY_MIME_PART (priv->msg), parts);
139 iter = tny_list_create_iterator (parts);
141 while (!tny_iterator_is_done (iter)) {
144 part = TNY_MIME_PART (tny_iterator_get_current (iter));
146 if (part && (modest_tny_mime_part_is_attachment_for_modest (part)))
147 modest_attachments_view_add_attachment (attachments_view, part);
150 g_object_unref (part);
152 tny_iterator_next (iter);
154 g_object_unref (iter);
155 g_object_unref (parts);
158 gtk_widget_queue_draw (GTK_WIDGET (attachments_view));
163 modest_attachments_view_add_attachment (ModestAttachmentsView *attachments_view, TnyMimePart *part)
165 GtkWidget *att_view = NULL;
166 ModestAttachmentsViewPrivate *priv = NULL;
168 g_return_if_fail (MODEST_IS_ATTACHMENTS_VIEW (attachments_view));
169 g_return_if_fail (TNY_IS_MIME_PART (part));
171 priv = MODEST_ATTACHMENTS_VIEW_GET_PRIVATE (attachments_view);
173 att_view = modest_attachment_view_new (part);
174 gtk_box_pack_end (GTK_BOX (priv->box), att_view, FALSE, FALSE, 0);
175 gtk_widget_show_all (att_view);
179 modest_attachments_view_remove_attachment (ModestAttachmentsView *atts_view, TnyMimePart *mime_part)
181 ModestAttachmentsViewPrivate *priv = NULL;
182 GList *box_children = NULL, *node = NULL;
183 ModestAttachmentView *found_att_view = NULL;
185 g_return_if_fail (MODEST_IS_ATTACHMENTS_VIEW (atts_view));
186 g_return_if_fail (TNY_IS_MIME_PART (mime_part));
188 priv = MODEST_ATTACHMENTS_VIEW_GET_PRIVATE (atts_view);
189 box_children = gtk_container_get_children (GTK_CONTAINER (priv->box));
191 for (node = box_children; node != NULL; node = g_list_next (node)) {
192 ModestAttachmentView *att_view = (ModestAttachmentView *) node->data;
193 TnyMimePart *cur_mime_part = tny_mime_part_view_get_part (TNY_MIME_PART_VIEW (att_view));
195 if (mime_part == cur_mime_part)
196 found_att_view = att_view;
198 g_object_unref (cur_mime_part);
200 if (found_att_view != NULL)
204 if (found_att_view) {
206 GtkWidget *next_widget = NULL;
207 GList *box_children = NULL;
209 box_children = gtk_container_get_children (GTK_CONTAINER (priv->box));
210 node = g_list_find (box_children, found_att_view);
212 next_widget = node->next->data;
214 g_list_free (box_children);
216 node = g_list_find (priv->selected, found_att_view);
218 priv->selected = g_list_delete_link (priv->selected, node);
219 gtk_widget_destroy (GTK_WIDGET (found_att_view));
220 if ((priv->selected == NULL) && (next_widget != NULL))
221 set_selected (MODEST_ATTACHMENTS_VIEW (atts_view),
222 MODEST_ATTACHMENT_VIEW (next_widget));
224 own_clipboard (atts_view);
230 modest_attachments_view_remove_attachment_by_id (ModestAttachmentsView *atts_view, const gchar *att_id)
232 ModestAttachmentsViewPrivate *priv = NULL;
233 GList *box_children = NULL, *node = NULL;
235 g_return_if_fail (MODEST_IS_ATTACHMENTS_VIEW (atts_view));
236 g_return_if_fail (att_id != NULL);
238 priv = MODEST_ATTACHMENTS_VIEW_GET_PRIVATE (atts_view);
239 box_children = gtk_container_get_children (GTK_CONTAINER (priv->box));
241 for (node = box_children; node != NULL; node = g_list_next (node)) {
242 ModestAttachmentView *att_view = (ModestAttachmentView *) node->data;
243 TnyMimePart *cur_mime_part = tny_mime_part_view_get_part (TNY_MIME_PART_VIEW (att_view));
244 const gchar *mime_part_id = NULL;
246 mime_part_id = tny_mime_part_get_content_id (cur_mime_part);
247 if ((mime_part_id != NULL) && (strcmp (mime_part_id, att_id) == 0)) {
248 gtk_widget_destroy (GTK_WIDGET (att_view));
249 priv->selected = g_list_remove (priv->selected, att_view);
252 g_object_unref (cur_mime_part);
255 own_clipboard (atts_view);
260 modest_attachments_view_instance_init (GTypeInstance *instance, gpointer g_class)
262 ModestAttachmentsViewPrivate *priv = MODEST_ATTACHMENTS_VIEW_GET_PRIVATE (instance);
265 priv->box = gtk_vbox_new (FALSE, 0);
266 priv->rubber_start = NULL;
267 priv->selected = NULL;
269 gtk_container_add (GTK_CONTAINER (instance), priv->box);
270 gtk_event_box_set_above_child (GTK_EVENT_BOX (instance), TRUE);
272 g_signal_connect (G_OBJECT (instance), "button-press-event", G_CALLBACK (button_press_event), instance);
273 g_signal_connect (G_OBJECT (instance), "button-release-event", G_CALLBACK (button_release_event), instance);
274 g_signal_connect (G_OBJECT (instance), "motion-notify-event", G_CALLBACK (motion_notify_event), instance);
275 g_signal_connect (G_OBJECT (instance), "key-press-event", G_CALLBACK (key_press_event), instance);
276 g_signal_connect (G_OBJECT (instance), "focus-out-event", G_CALLBACK (focus_out_event), instance);
277 g_signal_connect (G_OBJECT (instance), "focus", G_CALLBACK (focus), instance);
279 GTK_WIDGET_SET_FLAGS (instance, GTK_CAN_FOCUS);
285 modest_attachments_view_finalize (GObject *object)
287 ModestAttachmentsViewPrivate *priv = MODEST_ATTACHMENTS_VIEW_GET_PRIVATE (object);
290 g_object_unref (priv->msg);
294 (*parent_class->finalize) (object);
300 modest_attachments_view_class_init (ModestAttachmentsViewClass *klass)
302 GObjectClass *object_class;
303 GtkWidgetClass *widget_class;
305 parent_class = g_type_class_peek_parent (klass);
306 object_class = (GObjectClass*) klass;
307 widget_class = GTK_WIDGET_CLASS (klass);
309 object_class->finalize = modest_attachments_view_finalize;
311 klass->activate = NULL;
313 g_type_class_add_private (object_class, sizeof (ModestAttachmentsViewPrivate));
315 signals[ACTIVATE_SIGNAL] =
316 g_signal_new ("activate",
317 G_TYPE_FROM_CLASS (object_class),
318 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
319 G_STRUCT_OFFSET(ModestAttachmentsViewClass, activate),
321 g_cclosure_marshal_VOID__OBJECT,
322 G_TYPE_NONE, 1, G_TYPE_OBJECT);
328 modest_attachments_view_get_type (void)
330 static GType type = 0;
332 if (G_UNLIKELY(type == 0))
334 static const GTypeInfo info =
336 sizeof (ModestAttachmentsViewClass),
337 NULL, /* base_init */
338 NULL, /* base_finalize */
339 (GClassInitFunc) modest_attachments_view_class_init, /* class_init */
340 NULL, /* class_finalize */
341 NULL, /* class_data */
342 sizeof (ModestAttachmentsView),
344 modest_attachments_view_instance_init /* instance_init */
347 type = g_type_register_static (GTK_TYPE_EVENT_BOX,
348 "ModestAttachmentsView",
356 /* buttons signal events */
358 button_press_event (GtkWidget *widget,
359 GdkEventButton *event,
360 ModestAttachmentsView *atts_view)
362 ModestAttachmentsViewPrivate *priv = MODEST_ATTACHMENTS_VIEW_GET_PRIVATE (atts_view);
363 if (!GTK_WIDGET_HAS_FOCUS (widget))
364 gtk_widget_grab_focus (widget);
366 if (event->button == 1 && event->type == GDK_BUTTON_PRESS) {
367 GtkWidget *att_view = NULL;
369 att_view = get_att_view_at_coords (MODEST_ATTACHMENTS_VIEW (widget),
370 (gint) event->x_root, (gint) event->y_root);
372 if (att_view != NULL) {
373 if (GTK_WIDGET_STATE (att_view) == GTK_STATE_SELECTED && (g_list_length (priv->selected) < 2)) {
374 TnyMimePart *mime_part = tny_mime_part_view_get_part (TNY_MIME_PART_VIEW (att_view));
375 if (TNY_IS_MIME_PART (mime_part)) {
376 g_signal_emit (G_OBJECT (widget), signals[ACTIVATE_SIGNAL], 0, mime_part);
377 g_object_unref (mime_part);
380 set_selected (MODEST_ATTACHMENTS_VIEW (widget), MODEST_ATTACHMENT_VIEW (att_view));
381 priv->rubber_start = att_view;
382 gtk_grab_add (widget);
391 button_release_event (GtkWidget *widget,
392 GdkEventButton *event,
393 ModestAttachmentsView *atts_view)
395 ModestAttachmentsViewPrivate *priv = MODEST_ATTACHMENTS_VIEW_GET_PRIVATE (atts_view);
396 if (widget == gtk_grab_get_current ()) {
397 GtkWidget *att_view = NULL;
399 att_view = get_att_view_at_coords (MODEST_ATTACHMENTS_VIEW (widget),
400 (gint) event->x_root, (gint) event->y_root);
402 if (att_view != NULL) {
403 unselect_all (MODEST_ATTACHMENTS_VIEW (widget));
404 select_range (MODEST_ATTACHMENTS_VIEW (widget),
405 MODEST_ATTACHMENT_VIEW (priv->rubber_start),
406 MODEST_ATTACHMENT_VIEW (att_view));
408 priv->rubber_start = NULL;
409 gtk_grab_remove (widget);
415 motion_notify_event (GtkWidget *widget,
416 GdkEventMotion *event,
417 ModestAttachmentsView *atts_view)
419 ModestAttachmentsViewPrivate *priv = MODEST_ATTACHMENTS_VIEW_GET_PRIVATE (atts_view);
420 if (gtk_grab_get_current () == widget) {
421 GtkWidget *att_view = NULL;
423 att_view = get_att_view_at_coords (MODEST_ATTACHMENTS_VIEW (widget),
424 (gint) event->x_root, (gint) event->y_root);
426 if (att_view != NULL) {
427 unselect_all (MODEST_ATTACHMENTS_VIEW (widget));
428 select_range (MODEST_ATTACHMENTS_VIEW (widget),
429 MODEST_ATTACHMENT_VIEW (priv->rubber_start),
430 MODEST_ATTACHMENT_VIEW (att_view));
437 key_press_event (GtkWidget *widget,
439 ModestAttachmentsView *atts_view)
441 ModestAttachmentsViewPrivate *priv = MODEST_ATTACHMENTS_VIEW_GET_PRIVATE (atts_view);
443 /* If grabbed (for example rubber banding), escape leaves the rubberbanding mode */
444 if (gtk_grab_get_current () == widget) {
445 if (event->keyval == GDK_Escape) {
446 set_selected (MODEST_ATTACHMENTS_VIEW (widget),
447 MODEST_ATTACHMENT_VIEW (priv->rubber_start));
448 priv->rubber_start = NULL;
449 gtk_grab_remove (widget);
455 if (event->keyval == GDK_Up) {
456 ModestAttachmentView *current_sel = NULL;
457 gboolean move_out = FALSE;
458 GList * box_children, *new_sel;
460 box_children = gtk_container_get_children (GTK_CONTAINER (priv->box));
461 if (box_children == NULL)
463 else if ((priv->selected != NULL)&&(priv->selected->data != box_children->data))
464 current_sel = (ModestAttachmentView *) priv->selected->data;
469 GtkWidget *toplevel = NULL;
470 /* move cursor outside */
471 toplevel = gtk_widget_get_toplevel (widget);
472 if (GTK_WIDGET_TOPLEVEL (toplevel) && GTK_IS_WINDOW (toplevel))
473 g_signal_emit_by_name (toplevel, "move-focus", GTK_DIR_UP);
474 unselect_all (atts_view);
476 new_sel = g_list_find (box_children, (gpointer) current_sel);
477 new_sel = g_list_previous (new_sel);
478 set_selected (MODEST_ATTACHMENTS_VIEW (atts_view), MODEST_ATTACHMENT_VIEW (new_sel->data));
480 g_list_free (box_children);
484 if (event->keyval == GDK_Down) {
485 ModestAttachmentView *current_sel = NULL;
486 gboolean move_out = FALSE;
487 GList * box_children, *new_sel, *last_child = NULL;
489 box_children = gtk_container_get_children (GTK_CONTAINER (priv->box));
491 if (box_children == NULL) {
494 last_child = g_list_last (box_children);
495 if (priv->selected != NULL) {
496 GList *last_selected = g_list_last (priv->selected);
497 if (last_selected->data != last_child->data)
498 current_sel = (ModestAttachmentView *) last_selected->data;
507 GtkWidget *toplevel = NULL;
508 /* move cursor outside */
509 toplevel = gtk_widget_get_toplevel (widget);
510 if (GTK_WIDGET_TOPLEVEL (toplevel) && GTK_IS_WINDOW (toplevel))
511 g_signal_emit_by_name (toplevel, "move-focus", GTK_DIR_DOWN);
512 unselect_all (atts_view);
514 new_sel = g_list_find (box_children, (gpointer) current_sel);
515 new_sel = g_list_next (new_sel);
516 set_selected (MODEST_ATTACHMENTS_VIEW (atts_view), MODEST_ATTACHMENT_VIEW (new_sel->data));
518 g_list_free (box_children);
522 /* Activates selected item */
523 if (g_list_length (priv->selected) == 1) {
524 ModestAttachmentView *att_view = (ModestAttachmentView *) priv->selected->data;
525 if ((event->keyval == GDK_Return)) {
526 TnyMimePart *mime_part = tny_mime_part_view_get_part (TNY_MIME_PART_VIEW (att_view));
527 if (TNY_IS_MIME_PART (mime_part)) {
528 g_signal_emit (G_OBJECT (widget), signals[ACTIVATE_SIGNAL], 0, mime_part);
529 g_object_unref (mime_part);
540 get_att_view_at_coords (ModestAttachmentsView *atts_view,
541 gdouble x, gdouble y)
543 ModestAttachmentsViewPrivate *priv = NULL;
544 GList *att_view_list, *node;
545 GtkWidget *result = NULL;
547 priv = MODEST_ATTACHMENTS_VIEW_GET_PRIVATE (atts_view);
548 att_view_list = gtk_container_get_children (GTK_CONTAINER (priv->box));
550 for (node = att_view_list; node != NULL; node = g_list_next (node)) {
551 GtkWidget *att_view = (GtkWidget *) node->data;
552 gint pos_x, pos_y, w, h, int_x, int_y;
553 gint widget_x, widget_y;
555 gdk_window_get_origin (att_view->window, &widget_x, &widget_y);
559 w = att_view->allocation.width;
560 h = att_view->allocation.height;
562 int_x = (gint) x - GTK_WIDGET (atts_view)->allocation.x;
563 int_y = (gint) y - GTK_WIDGET (atts_view)->allocation.y;
565 if ((x >= pos_x) && (x <= (pos_x + w)) && (y >= pos_y) && (y <= (pos_y + h))) {
571 g_list_free (att_view_list);
576 unselect_all (ModestAttachmentsView *atts_view)
578 ModestAttachmentsViewPrivate *priv = NULL;
579 GList *att_view_list, *node;
581 priv = MODEST_ATTACHMENTS_VIEW_GET_PRIVATE (atts_view);
582 att_view_list = gtk_container_get_children (GTK_CONTAINER (priv->box));
584 for (node = att_view_list; node != NULL; node = g_list_next (node)) {
585 GtkWidget *att_view = (GtkWidget *) node->data;
587 if (GTK_WIDGET_STATE (att_view) == GTK_STATE_SELECTED)
588 gtk_widget_set_state (att_view, GTK_STATE_NORMAL);
591 g_list_free (priv->selected);
592 priv->selected = NULL;
594 g_list_free (att_view_list);
598 set_selected (ModestAttachmentsView *atts_view, ModestAttachmentView *att_view)
600 ModestAttachmentsViewPrivate *priv = MODEST_ATTACHMENTS_VIEW_GET_PRIVATE (atts_view);
603 unselect_all (atts_view);
604 part = tny_mime_part_view_get_part (TNY_MIME_PART_VIEW (att_view));
606 g_list_free (priv->selected);
607 priv->selected = NULL;
608 if (TNY_IS_MIME_PART (part) && !tny_mime_part_is_purged (part)) {
609 gtk_widget_set_state (GTK_WIDGET (att_view), GTK_STATE_SELECTED);
610 priv->selected = g_list_append (priv->selected, att_view);
613 g_object_unref (part);
615 own_clipboard (atts_view);
619 select_range (ModestAttachmentsView *atts_view, ModestAttachmentView *att1, ModestAttachmentView *att2)
621 ModestAttachmentsViewPrivate *priv = MODEST_ATTACHMENTS_VIEW_GET_PRIVATE (atts_view);
622 GList *children = NULL;
624 gboolean selecting = FALSE;
627 unselect_all (atts_view);
630 set_selected (atts_view, att1);
634 children = gtk_container_get_children (GTK_CONTAINER (priv->box));
635 g_list_free (priv->selected);
636 priv->selected = NULL;
639 for (node = children; node != NULL; node = g_list_next (node)) {
640 if ((node->data == att1) || (node->data == att2)) {
641 part = tny_mime_part_view_get_part (TNY_MIME_PART_VIEW (node->data));
642 if (!tny_mime_part_is_purged (part)) {
643 gtk_widget_set_state (GTK_WIDGET (node->data), GTK_STATE_SELECTED);
644 priv->selected = g_list_append (priv->selected, node->data);
646 g_object_unref (part);
647 selecting = !selecting;
648 } else if (selecting) {
649 part = tny_mime_part_view_get_part (TNY_MIME_PART_VIEW (node->data));
650 if (!tny_mime_part_is_purged (part)) {
651 gtk_widget_set_state (GTK_WIDGET (node->data), GTK_STATE_SELECTED);
652 priv->selected = g_list_append (priv->selected, node->data);
654 g_object_unref (part);
658 g_list_free (children);
660 own_clipboard (atts_view);
663 static void clipboard_get (GtkClipboard *clipboard, GtkSelectionData *selection_data,
664 guint info, gpointer userdata)
666 ModestAttachmentsView *atts_view = (ModestAttachmentsView *) userdata;
667 ModestAttachmentsViewPrivate *priv = MODEST_ATTACHMENTS_VIEW_GET_PRIVATE (atts_view);
669 if ((priv->selected != NULL)&&(priv->selected->next == NULL)) {
670 if (info == MODEST_ATTACHMENTS_VIEW_CLIPBOARD_TYPE_INDEX) {
671 /* MODEST_ATTACHMENT requested. As the content id is not filled in all the case, we'll
672 * use an internal index. This index is simply the index of the attachment in the vbox */
673 GList *box_children = NULL;
675 box_children = gtk_container_get_children (GTK_CONTAINER (priv->box));
676 index = g_list_index (box_children, priv->selected);
678 gchar *index_str = g_strdup_printf("%d", index);
679 gtk_selection_data_set_text (selection_data, index_str, -1);
686 static void clipboard_clear (GtkClipboard *clipboard, gpointer userdata)
688 ModestAttachmentsView *atts_view = (ModestAttachmentsView *) userdata;
690 unselect_all (atts_view);
694 modest_attachments_view_get_selection (ModestAttachmentsView *atts_view)
696 ModestAttachmentsViewPrivate *priv;
700 g_return_val_if_fail (MODEST_IS_ATTACHMENTS_VIEW (atts_view), NULL);
701 priv = MODEST_ATTACHMENTS_VIEW_GET_PRIVATE (atts_view);
703 selection = tny_simple_list_new ();
704 for (node = priv->selected; node != NULL; node = g_list_next (node)) {
705 ModestAttachmentView *att_view = (ModestAttachmentView *) node->data;
706 TnyMimePart *part = tny_mime_part_view_get_part (TNY_MIME_PART_VIEW (att_view));
707 tny_list_append (selection, (GObject *) part);
708 g_object_unref (part);
715 modest_attachments_view_get_attachments (ModestAttachmentsView *atts_view)
717 ModestAttachmentsViewPrivate *priv;
719 GList *children, *node= NULL;
721 g_return_val_if_fail (MODEST_IS_ATTACHMENTS_VIEW (atts_view), NULL);
722 priv = MODEST_ATTACHMENTS_VIEW_GET_PRIVATE (atts_view);
724 att_list = TNY_LIST (tny_simple_list_new ());
726 children = gtk_container_get_children (GTK_CONTAINER (priv->box));
727 for (node = children; node != NULL; node = g_list_next (node)) {
728 GtkWidget *att_view = GTK_WIDGET (node->data);
729 TnyMimePart *mime_part = tny_mime_part_view_get_part (TNY_MIME_PART_VIEW (att_view));
730 tny_list_append (att_list, (GObject *) mime_part);
731 g_object_unref (mime_part);
733 g_list_free (children);
739 modest_attachments_view_select_all (ModestAttachmentsView *atts_view)
741 ModestAttachmentsViewPrivate *priv = MODEST_ATTACHMENTS_VIEW_GET_PRIVATE (atts_view);
742 GList *children = NULL;
745 unselect_all (atts_view);
747 children = gtk_container_get_children (GTK_CONTAINER (priv->box));
748 g_list_free (priv->selected);
749 priv->selected = NULL;
752 for (node = children; node != NULL; node = g_list_next (node)) {
753 gtk_widget_set_state (GTK_WIDGET (node->data), GTK_STATE_SELECTED);
754 priv->selected = g_list_append (priv->selected, node->data);
756 g_list_free (children);
758 own_clipboard (atts_view);
762 modest_attachments_view_has_attachments (ModestAttachmentsView *atts_view)
764 ModestAttachmentsViewPrivate *priv;
768 g_return_val_if_fail (MODEST_IS_ATTACHMENTS_VIEW (atts_view), FALSE);
769 priv = MODEST_ATTACHMENTS_VIEW_GET_PRIVATE (atts_view);
771 children = gtk_container_get_children (GTK_CONTAINER (priv->box));
772 result = (children != NULL);
773 g_list_free (children);
779 own_clipboard (ModestAttachmentsView *atts_view)
781 GtkTargetEntry targets[] = {
782 {MODEST_ATTACHMENTS_VIEW_CLIPBOARD_TYPE, 0, MODEST_ATTACHMENTS_VIEW_CLIPBOARD_TYPE_INDEX},
785 gtk_clipboard_set_with_owner (gtk_widget_get_clipboard (GTK_WIDGET (atts_view), GDK_SELECTION_PRIMARY),
786 targets, G_N_ELEMENTS (targets),
787 clipboard_get, clipboard_clear, G_OBJECT(atts_view));
792 focus_out_event (GtkWidget *widget, GdkEventFocus *event, ModestAttachmentsView *atts_view)
794 if (!gtk_widget_is_focus (widget))
795 unselect_all (atts_view);
801 focus (GtkWidget *widget, GtkDirectionType direction, ModestAttachmentsView *atts_view)
803 ModestAttachmentsViewPrivate *priv = MODEST_ATTACHMENTS_VIEW_GET_PRIVATE (atts_view);
804 GList *children = NULL;
805 GtkWidget *toplevel = NULL;
807 toplevel = gtk_widget_get_toplevel (widget);
808 if (!gtk_window_has_toplevel_focus (GTK_WINDOW (toplevel)))
811 children = gtk_container_get_children (GTK_CONTAINER (priv->box));
812 if (children != NULL) {
813 set_selected (atts_view, MODEST_ATTACHMENT_VIEW (children->data));
815 g_list_free (children);