Better attachments detection for text/calendar
[modest] / src / widgets / modest-attachments-view.c
index ac8d05b..a83f7d8 100644 (file)
@@ -41,6 +41,7 @@
 #include <modest-attachments-view.h>
 #include <modest-tny-mime-part.h>
 #include <modest-tny-msg.h>
+#include <modest-ui-constants.h>
 
 static GObjectClass *parent_class = NULL;
 
@@ -60,6 +61,7 @@ struct _ModestAttachmentsViewPrivate
        GList *selected;
        GtkWidget *rubber_start;
        GtkWidget *press_att_view;
+       GtkWidget *previous_selection;
        ModestAttachmentsViewStyle style;
 };
 
@@ -80,6 +82,8 @@ static void select_range (ModestAttachmentsView *atts_view, ModestAttachmentView
 static void clipboard_get (GtkClipboard *clipboard, GtkSelectionData *selection_data,
                           guint info, gpointer userdata);
 static void own_clipboard (ModestAttachmentsView *atts_view);
+static void on_notify_style (GObject *obj, GParamSpec *spec, gpointer userdata);
+static void update_style (ModestAttachmentsView *self);
 
 static guint signals[LAST_SIGNAL] = {0};
 
@@ -103,6 +107,27 @@ modest_attachments_view_new (TnyMsg *msg)
        return GTK_WIDGET (self);
 }
 
+static void
+add_digest_attachments (ModestAttachmentsView *attachments_view, TnyMimePart *part)
+{
+       TnyList *parts;
+       TnyIterator *iter;
+
+       parts = TNY_LIST (tny_simple_list_new());
+       tny_mime_part_get_parts (TNY_MIME_PART (part), parts);
+
+       for (iter  = tny_list_create_iterator(parts); 
+            !tny_iterator_is_done (iter);
+            tny_iterator_next (iter)) {
+               TnyMimePart *cur_part = TNY_MIME_PART (tny_iterator_get_current (iter));
+               modest_attachments_view_add_attachment (attachments_view, cur_part, TRUE, 0);
+               g_object_unref (cur_part);
+       }
+       g_object_unref (iter);
+       g_object_unref (parts);
+
+}
+
 
 void
 modest_attachments_view_set_message (ModestAttachmentsView *attachments_view, TnyMsg *msg)
@@ -112,6 +137,8 @@ modest_attachments_view_set_message (ModestAttachmentsView *attachments_view, Tn
        TnyIterator *iter;
        gchar *msg_content_type = NULL;
        TnyMimePart *part_to_check;
+       gboolean body_found;
+       gboolean is_alternate;
        
        if (msg == priv->msg) return;
 
@@ -126,14 +153,13 @@ modest_attachments_view_set_message (ModestAttachmentsView *attachments_view, Tn
        priv->selected = NULL;
 
        gtk_container_foreach (GTK_CONTAINER (priv->box), (GtkCallback) gtk_widget_destroy, NULL);
-       
-       if (priv->msg == NULL) {
+
+       if (priv->msg == NULL)
                return;
-       }
 
        part_to_check = modest_tny_msg_get_attachments_parent (TNY_MSG (msg));
-
        msg_content_type = modest_tny_mime_part_get_content_type (TNY_MIME_PART (part_to_check));
+       is_alternate = (msg_content_type != NULL) && !strcasecmp (msg_content_type, "multipart/alternative");
 
        /* If the top mime part is a multipart/related, we don't show the attachments, as they're
         * embedded images in body */
@@ -144,7 +170,7 @@ modest_attachments_view_set_message (ModestAttachmentsView *attachments_view, Tn
                g_free (msg_content_type);
 
                header_content_type = modest_tny_mime_part_get_headers_content_type (TNY_MIME_PART (part_to_check));
-               
+
                if ((header_content_type != NULL) && 
                    !strstr (header_content_type, "application/")) {
                        application_multipart = TRUE;
@@ -161,7 +187,8 @@ modest_attachments_view_set_message (ModestAttachmentsView *attachments_view, Tn
 
                direct_attach = (!g_str_has_prefix (msg_content_type, "message/rfc822") && 
                                 !g_str_has_prefix (msg_content_type, "multipart") && 
-                                !g_str_has_prefix (msg_content_type, "text/"));
+                                !g_str_has_prefix (msg_content_type, "text/plain") &&
+                                !g_str_has_prefix (msg_content_type, "text/html"));
 
                g_free (msg_content_type);
 
@@ -177,14 +204,34 @@ modest_attachments_view_set_message (ModestAttachmentsView *attachments_view, Tn
        tny_mime_part_get_parts (TNY_MIME_PART (part_to_check), parts);
        iter = tny_list_create_iterator (parts);
 
+       body_found = FALSE;
        while (!tny_iterator_is_done (iter)) {
                TnyMimePart *part;
+               gchar *content_type;
 
                part = TNY_MIME_PART (tny_iterator_get_current (iter));
 
-               if (part && (modest_tny_mime_part_is_attachment_for_modest (part))) 
+               if (part && (modest_tny_mime_part_is_attachment_for_modest (part))) {
                        modest_attachments_view_add_attachment (attachments_view, part, TRUE, 0);
 
+               } else if (part && !is_alternate) {
+                       content_type = g_ascii_strdown (tny_mime_part_get_content_type (part), -1);
+                       g_strstrip (content_type);
+
+                       if (g_str_has_prefix (content_type, "multipart/digest")) {
+                               add_digest_attachments (attachments_view, part);
+                       } else if (body_found && 
+                                  (g_str_has_prefix (content_type, "text/plain") ||
+                                   g_str_has_prefix (content_type, "text/html"))) {
+                                  modest_attachments_view_add_attachment (attachments_view, part, TRUE, 0);
+                       } else if (g_str_has_prefix (content_type, "multipart/") || 
+                                  g_str_has_prefix (content_type, "text/plain") ||
+                                  g_str_has_prefix (content_type, "text/html")) {
+                               body_found = TRUE;
+                       }
+               }
+
+
                if (part)
                        g_object_unref (part);
 
@@ -193,7 +240,6 @@ modest_attachments_view_set_message (ModestAttachmentsView *attachments_view, Tn
        g_object_unref (iter);
        g_object_unref (parts);
        g_object_unref (part_to_check);
-       
 
        gtk_widget_queue_draw (GTK_WIDGET (attachments_view));
 
@@ -327,6 +373,10 @@ modest_attachments_view_instance_init (GTypeInstance *instance, gpointer g_class
 
        GTK_WIDGET_SET_FLAGS (instance, GTK_CAN_FOCUS);
 
+       g_signal_connect (G_OBJECT (instance), "notify::style", G_CALLBACK (on_notify_style), (gpointer) instance);
+
+       update_style (MODEST_ATTACHMENTS_VIEW (instance));
+
        return;
 }
 
@@ -431,12 +481,16 @@ button_press_event (GtkWidget *widget,
                if (att_view != NULL) {
                        if (priv->style == MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS) {
                                unselect_all (MODEST_ATTACHMENTS_VIEW (widget));
-                       } else if ((priv->style == MODEST_ATTACHMENTS_VIEW_STYLE_LINKS) ||
-                           (GTK_WIDGET_STATE (att_view) == GTK_STATE_SELECTED && (g_list_length (priv->selected) < 2))) {
+                       } else if (priv->style == MODEST_ATTACHMENTS_VIEW_STYLE_LINKS) {
                                priv->press_att_view = att_view;
                                set_selected (MODEST_ATTACHMENTS_VIEW (widget), MODEST_ATTACHMENT_VIEW (att_view));
                                gtk_grab_add (widget);
                        } else {
+                               if (g_list_length (priv->selected) == 1) {
+                                       priv->previous_selection = GTK_WIDGET (priv->selected->data);
+                               } else {
+                                       priv->previous_selection = NULL;
+                               }
                                TnyMimePart *mime_part = tny_mime_part_view_get_part (TNY_MIME_PART_VIEW (att_view));
 
                                /* Do not select purged attachments */
@@ -476,7 +530,14 @@ button_release_event (GtkWidget *widget,
                        priv->press_att_view = NULL;
                } else {
 
-                       if (att_view != NULL) {
+                       if (priv->style != MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS &&
+                           priv->rubber_start == att_view  && 
+                           priv->previous_selection == att_view) {
+                               TnyMimePart *mime_part;
+                               mime_part = tny_mime_part_view_get_part (TNY_MIME_PART_VIEW (att_view));
+                               g_signal_emit (G_OBJECT (widget), signals[ACTIVATE_SIGNAL], 0, mime_part);
+                               g_object_unref (mime_part);
+                       } else if (att_view != NULL) {
                                unselect_all (MODEST_ATTACHMENTS_VIEW (widget));
                                select_range (MODEST_ATTACHMENTS_VIEW (widget), 
                                              MODEST_ATTACHMENT_VIEW (priv->rubber_start), 
@@ -502,9 +563,12 @@ motion_notify_event (GtkWidget *widget,
                                                   (gint) event->x_root, (gint) event->y_root);
                if (priv->style == MODEST_ATTACHMENTS_VIEW_STYLE_LINKS) {
                        if (att_view == priv->press_att_view) {
+                               if (priv->selected == NULL)
                                set_selected (MODEST_ATTACHMENTS_VIEW (widget), MODEST_ATTACHMENT_VIEW (att_view));
                        } else {
-                               unselect_all (MODEST_ATTACHMENTS_VIEW (widget));
+                               if (priv->selected) {
+                                       unselect_all (MODEST_ATTACHMENTS_VIEW (widget));
+                               }
                        }
                } else {
 
@@ -515,6 +579,7 @@ motion_notify_event (GtkWidget *widget,
                                              MODEST_ATTACHMENT_VIEW (att_view));
                        }
                }
+               gdk_event_request_motions (event);
        }
        return TRUE;
 }
@@ -700,10 +765,15 @@ get_att_view_at_coords (ModestAttachmentsView *atts_view,
                gint pos_x, pos_y, w, h, int_x, int_y;
                gint widget_x, widget_y;
 
+#if GTK_CHECK_VERSION (2,14,0)
+               gdk_window_get_origin (gtk_widget_get_window (att_view), &widget_x, &widget_y);
+#else
                gdk_window_get_origin (att_view->window, &widget_x, &widget_y);
+#endif
 
                pos_x = widget_x;
                pos_y = widget_y;
+
                w = att_view->allocation.width;
                h = att_view->allocation.height;
 
@@ -1048,3 +1118,33 @@ modest_attachments_view_get_num_attachments (ModestAttachmentsView *atts_view)
 
        return result;
 }
+
+static void 
+on_notify_style (GObject *obj, GParamSpec *spec, gpointer userdata)
+{
+       if (strcmp ("style", spec->name) == 0) {
+               update_style (MODEST_ATTACHMENTS_VIEW (obj));
+               gtk_widget_queue_draw (GTK_WIDGET (obj));
+       } 
+}
+
+/* This method updates the color (and other style settings) of widgets using secondary text color,
+ * tracking the gtk style */
+static void
+update_style (ModestAttachmentsView *self)
+{
+#ifdef MODEST_COMPACT_HEADER_BG
+       GdkColor bg_color;
+       GtkStyle *style;
+       GdkColor *current_bg;
+
+       g_return_if_fail (MODEST_IS_ATTACHMENTS_VIEW (self));
+
+       gdk_color_parse (MODEST_COMPACT_HEADER_BG, &bg_color);
+       style = gtk_widget_get_style (GTK_WIDGET (self));
+       current_bg = &(style->bg[GTK_STATE_NORMAL]);
+       if (current_bg->red != bg_color.red || current_bg->blue != bg_color.blue || current_bg->green != bg_color.green)
+               gtk_widget_modify_bg (GTK_WIDGET (self), GTK_STATE_NORMAL, &bg_color);
+#endif
+}
+