* some compile (-Wall -Werror) fixes
[modest] / src / widgets / modest-attachments-view.c
1 /* Copyright (c) 2007, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
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.
16  *
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.
28  */
29
30 #include <config.h>
31
32 //#include <glib/gi18n-lib.h>
33
34 #include <string.h>
35 #include <gtk/gtk.h>
36
37 #include <tny-list.h>
38 #include <tny-simple-list.h>
39
40 #include <modest-platform.h>
41 #include <modest-runtime.h>
42 #include <modest-attachments-view.h>
43
44 static GObjectClass *parent_class = NULL;
45
46 /* signals */
47 enum {
48         ACTIVATE_SIGNAL,
49         LAST_SIGNAL
50 };
51
52 typedef struct _ModestAttachmentsViewPriv ModestAttachmentsViewPriv;
53
54 struct _ModestAttachmentsViewPriv
55 {
56         TnyMsg *msg;
57 };
58
59 #define MODEST_ATTACHMENTS_VIEW_GET_PRIVATE(o)  \
60         (G_TYPE_INSTANCE_GET_PRIVATE ((o), MODEST_TYPE_ATTACHMENTS_VIEW, ModestAttachmentsViewPriv))
61
62 static guint signals[LAST_SIGNAL] = {0};
63
64
65 /**
66  * modest_attachments_view_new:
67  * @msg: a #TnyMsg
68  *
69  * Constructor for attachments view widget.
70  *
71  * Return value: a new #ModestAttachmentsView instance implemented for Gtk+
72  **/
73 GtkWidget*
74 modest_attachments_view_new (TnyMsg *msg)
75 {
76         ModestAttachmentsView *self = g_object_new (MODEST_TYPE_ATTACHMENTS_VIEW, NULL);
77
78         modest_attachments_view_set_message (self, msg);
79
80         return GTK_WIDGET (self);
81 }
82
83 void
84 modest_attachments_view_set_message (ModestAttachmentsView *attachments_view, TnyMsg *msg)
85 {
86         ModestAttachmentsViewPriv *priv = MODEST_ATTACHMENTS_VIEW_GET_PRIVATE (attachments_view);
87         TnyList *parts;
88         TnyIterator *iter;
89         gint index = 0;
90         GtkTextBuffer *buffer = NULL;
91         gboolean has_first = FALSE;
92         GtkTextIter text_iter;
93         gint icon_height;
94
95         if (priv->msg) 
96                 g_object_unref (priv->msg);
97         if (msg)
98                 g_object_ref (G_OBJECT(msg));
99         
100         priv->msg = msg;
101         
102         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (attachments_view));
103         gtk_text_buffer_set_text (buffer, "", -1);
104         gtk_text_buffer_get_end_iter (buffer, &text_iter);
105
106         if (priv->msg == NULL) {
107                 gtk_widget_hide (GTK_WIDGET (attachments_view));
108                 return;
109         }
110
111         parts = TNY_LIST (tny_simple_list_new ());
112         tny_mime_part_get_parts (TNY_MIME_PART (priv->msg), parts);
113         iter = tny_list_create_iterator (parts);
114
115         gtk_icon_size_lookup (GTK_ICON_SIZE_BUTTON, NULL, &icon_height);
116
117         while (!tny_iterator_is_done (iter)) {
118                 TnyMimePart *part;
119
120                 ++index;
121                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
122                 if (tny_mime_part_is_attachment (part)) {
123                         const gchar *filename = tny_mime_part_get_filename (part);
124                         gchar *file_icon_name = 
125                                 modest_platform_get_file_icon_name (filename, tny_mime_part_get_content_type(part) , NULL);
126                         GdkPixbuf *pixbuf = NULL;
127                         GtkTextTag *tag = NULL;
128
129                         if (has_first) {
130                                 gtk_text_buffer_insert (buffer, &text_iter, ", ", -1);
131                                 gtk_text_buffer_get_end_iter (buffer, &text_iter);
132                         }
133                         
134                         tag = gtk_text_buffer_create_tag (buffer, NULL,
135                                                           "underline", PANGO_UNDERLINE_SINGLE,
136                                                           "foreground", "blue",
137                                                           NULL);
138                         
139                         g_object_set_data (G_OBJECT (tag), "attachment-index", GINT_TO_POINTER (index));
140                         g_object_set_data (G_OBJECT (tag), "attachment-set", GINT_TO_POINTER (TRUE));
141                         
142                         if (file_icon_name) {
143                                 pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), file_icon_name, 
144                                                                    icon_height, GTK_ICON_LOOKUP_USE_BUILTIN, NULL);
145                                 if (pixbuf) {
146                                         gtk_text_buffer_insert_pixbuf (buffer, &text_iter, pixbuf);
147                                 }
148                         }
149                         gtk_text_buffer_insert_with_tags (buffer, &text_iter, filename, -1, tag, NULL);
150                         gtk_text_buffer_get_end_iter (buffer, &text_iter);
151                         if (file_icon_name)
152                                 g_free (file_icon_name);
153                         has_first = TRUE;
154                 }
155                 g_object_unref (part);
156                 tny_iterator_next (iter);
157         }
158
159         if (has_first)
160                 gtk_widget_show (GTK_WIDGET (attachments_view));
161         else
162                 gtk_widget_hide (GTK_WIDGET (attachments_view));
163
164 }
165
166 static gboolean
167 button_release_event (GtkWidget *widget,
168                       GdkEventButton *event,
169                       gpointer user_data)
170 {
171         gint buffer_x, buffer_y;
172         GtkTextIter iter;
173         GSList *tags = NULL;
174         GSList *node = NULL;
175         
176         if ((event->type != GDK_BUTTON_RELEASE) 
177             || (event->button != 1))
178                 return FALSE;
179         
180         gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (widget), GTK_TEXT_WINDOW_WIDGET,
181                                                event->x, event->y, &buffer_x, &buffer_y);
182         gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (widget), &iter, buffer_x, buffer_y);
183
184         tags = gtk_text_iter_get_tags (&iter);
185
186         for (node = tags; node != NULL; node = g_slist_next (node)) {
187                 GtkTextTag *tag = node->data;
188                 gboolean is_attachment = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (tag), "attachment-set"));
189
190                 if (is_attachment) {
191                         gint attachment_index = 0;
192
193                         attachment_index = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (tag), "attachment-index"));
194                         g_signal_emit (G_OBJECT (widget), signals[ACTIVATE_SIGNAL], 0,
195                                        attachment_index);
196                         break;
197                 }
198                 
199         }
200         return FALSE;
201 }
202
203 static void
204 modest_attachments_view_instance_init (GTypeInstance *instance, gpointer g_class)
205 {
206         ModestAttachmentsViewPriv *priv = MODEST_ATTACHMENTS_VIEW_GET_PRIVATE (instance);
207         GtkTextBuffer *buffer = NULL;
208
209         gtk_text_view_set_editable (GTK_TEXT_VIEW (instance), FALSE);
210         gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (instance), GTK_WRAP_WORD_CHAR);
211         gtk_text_view_set_pixels_above_lines (GTK_TEXT_VIEW (instance), 0);
212         gtk_text_view_set_pixels_below_lines (GTK_TEXT_VIEW (instance), 0);
213         gtk_text_view_set_justification (GTK_TEXT_VIEW (instance), GTK_JUSTIFY_LEFT);
214         gtk_text_view_set_left_margin (GTK_TEXT_VIEW (instance), 0);
215         gtk_text_view_set_right_margin (GTK_TEXT_VIEW (instance), 0);
216         gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (instance), FALSE);
217
218         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (instance));
219
220         g_signal_connect (G_OBJECT (instance), "button-release-event", G_CALLBACK (button_release_event), NULL);
221
222         priv->msg = NULL;
223
224         return;
225 }
226
227 static void
228 modest_attachments_view_finalize (GObject *object)
229 {
230         ModestAttachmentsViewPriv *priv = MODEST_ATTACHMENTS_VIEW_GET_PRIVATE (object);
231
232         if (priv->msg) {
233                 g_object_unref (priv->msg);
234                 priv->msg = NULL;
235         }
236
237         (*parent_class->finalize) (object);
238
239         return;
240 }
241
242 static void 
243 modest_attachments_view_class_init (ModestAttachmentsViewClass *klass)
244 {
245         GObjectClass *object_class;
246         GtkWidgetClass *widget_class;
247
248         parent_class = g_type_class_peek_parent (klass);
249         object_class = (GObjectClass*) klass;
250         widget_class = GTK_WIDGET_CLASS (klass);
251
252         object_class->finalize = modest_attachments_view_finalize;
253
254         klass->activate = NULL;
255
256         g_type_class_add_private (object_class, sizeof (ModestAttachmentsViewPriv));
257
258         signals[ACTIVATE_SIGNAL] =
259                 g_signal_new ("activate",
260                               G_TYPE_FROM_CLASS (object_class),
261                               G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
262                               G_STRUCT_OFFSET(ModestAttachmentsViewClass, activate),
263                               NULL, NULL,
264                               g_cclosure_marshal_VOID__INT,
265                               G_TYPE_NONE, 1, G_TYPE_INT);
266         
267         return;
268 }
269
270 GType 
271 modest_attachments_view_get_type (void)
272 {
273         static GType type = 0;
274
275         if (G_UNLIKELY(type == 0))
276         {
277                 static const GTypeInfo info = 
278                 {
279                   sizeof (ModestAttachmentsViewClass),
280                   NULL,   /* base_init */
281                   NULL,   /* base_finalize */
282                   (GClassInitFunc) modest_attachments_view_class_init,   /* class_init */
283                   NULL,   /* class_finalize */
284                   NULL,   /* class_data */
285                   sizeof (ModestAttachmentsView),
286                   0,      /* n_preallocs */
287                   modest_attachments_view_instance_init    /* instance_init */
288                 };
289
290                 type = g_type_register_static (GTK_TYPE_TEXT_VIEW,
291                         "ModestAttachmentsView",
292                         &info, 0);
293
294         }
295
296         return type;
297 }