~ubuntu-branches/ubuntu/wily/evolution/wily

« back to all changes in this revision

Viewing changes to mail/e-mail-display.c

  • Committer: Package Import Robot
  • Author(s): Mathieu Trudel-Lapierre
  • Date: 2012-07-03 23:07:40 UTC
  • mfrom: (1.1.92)
  • Revision ID: package-import@ubuntu.com-20120703230740-0hjh6kfpxsyb88gx
Tags: 3.5.3.1-0ubuntu1
* New upstream release 3.5.3.1.
* debian/control:
  - Add libwebkitgtk-3.0-dev, libjavascriptcoregtk-3.0-dev >= 1.8.0 to build
    dependencies.
  - Adjust Build-Depends for the new minimum versions required for EDS 3.5.
  - Also update evolution's Depends to require evolution-data-server >= 3.5,
    and << 3.6.
* debian/rules:
  - Update ELIBDIR to point to /usr/lib/evolution/3.6 now, as per the base
    version defined in configure.
  - Build all plugins rather than enabling experimental specifically; we can
    sort them to other packages after.
  - Drop the binary-install/evolution-common target.
* debian/patches/01_ubuntu_signature.patch: dropped; upstream code has changed
  sufficiently that it would pretty much need a rewrite; and Evolution is no
  longer the default shipped mail client on Desktop.
* debian/patches/04_delay_alarm_notifier.patch: refreshed.
* debian/patches/89_remove_component_id_registration.patch: dropped: we don't
  have UNE anymore and component ID registration has been moved to GSettings.
* debian/patches/10_revert_libevolution_avoid-version.patch: refreshed.
* debian/patches/91_add_u1_email_translations.patch: refreshed.
* debian/evolution-common.install:
  - Drop debian/signature.py.
  - Don't install /usr/share/mime-info; it's not built anymore.
* debian/signature.py: dropped; since we dropped the Ubuntu signature patch.
* debian/evolution.install: don't try to install files in /etc/gconf; evo
  has migrated to GSettings so there are no such files anymore.
* debian/evolution.install,
  debian/evolution-plugins.install,
  debian/evolution-plugins-experimental.install: remove the plugins that were
  converted to modules. Modules are already installed by libevolution.

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
#include "e-mail-display.h"
27
27
 
28
28
#include <glib/gi18n.h>
29
 
 
 
29
#include <gdk/gdk.h>
 
30
 
 
31
#include <em-format/e-mail-part-utils.h>
 
32
#include <em-format/e-mail-formatter-extension.h>
 
33
#include <em-format/e-mail-extension-registry.h>
 
34
#include <em-format/e-mail-part-attachment.h>
 
35
#include <em-format/e-mail-formatter-print.h>
 
36
 
 
37
#include "e-util/e-marshal.h"
30
38
#include "e-util/e-util.h"
31
39
#include "e-util/e-plugin-ui.h"
 
40
#include "e-util/e-file-request.h"
 
41
#include "e-util/e-stock-request.h"
32
42
#include "mail/em-composer-utils.h"
33
43
#include "mail/em-utils.h"
 
44
#include "mail/e-mail-request.h"
 
45
#include "mail/e-http-request.h"
 
46
#include "widgets/misc/e-attachment-bar.h"
 
47
#include "widgets/misc/e-attachment-button.h"
 
48
 
 
49
#include <camel/camel.h>
 
50
 
 
51
#include <JavaScriptCore/JavaScript.h>
 
52
 
 
53
#define d(x)
 
54
 
 
55
G_DEFINE_TYPE (EMailDisplay, e_mail_display, E_TYPE_WEB_VIEW)
34
56
 
35
57
#define E_MAIL_DISPLAY_GET_PRIVATE(obj) \
36
58
        (G_TYPE_INSTANCE_GET_PRIVATE \
37
59
        ((obj), E_TYPE_MAIL_DISPLAY, EMailDisplayPrivate))
38
60
 
39
61
struct _EMailDisplayPrivate {
40
 
        EMFormatHTML *formatter;
 
62
        EMailPartList *part_list;
 
63
        EMailFormatterMode mode;
 
64
        EMailFormatter *formatter;
 
65
 
 
66
        gboolean headers_collapsable;
 
67
        gboolean headers_collapsed;
 
68
 
 
69
        gint force_image_load: 1;
 
70
 
 
71
        GSettings *settings;
 
72
 
 
73
        GHashTable *widgets;
 
74
 
 
75
        guint reload_scheduled: 1;
41
76
};
42
77
 
43
78
enum {
44
79
        PROP_0,
45
 
        PROP_FORMATTER
 
80
        PROP_MODE,
 
81
        PROP_PART_LIST,
 
82
        PROP_HEADERS_COLLAPSABLE,
 
83
        PROP_HEADERS_COLLAPSED,
46
84
};
47
85
 
 
86
static CamelDataCache *emd_global_http_cache = 0;
 
87
 
48
88
static const gchar *ui =
49
89
"<ui>"
50
90
"  <popup name='context'>"
61
101
"  </popup>"
62
102
"</ui>";
63
103
 
 
104
static const gchar *image_ui =
 
105
"<ui>"
 
106
"  <popup name='context'>"
 
107
"    <placeholder name='custom-actions-2'>"
 
108
"      <menuitem action='image-save'/>"
 
109
"    </placeholder>"
 
110
"  </popup>"
 
111
"</ui>";
 
112
 
64
113
static GtkActionEntry mailto_entries[] = {
65
114
 
66
115
        { "add-to-address-book",
88
137
          NULL,
89
138
          N_("Send _Reply To..."),
90
139
          NULL,
91
 
          N_("Send a reply message to this address"),  
 
140
          N_("Send a reply message to this address"),
92
141
          NULL   /* Handled by EMailReader */ },
93
142
 
94
143
        /*** Menus ***/
101
150
          NULL }
102
151
};
103
152
 
104
 
G_DEFINE_TYPE (EMailDisplay, e_mail_display, E_TYPE_WEB_VIEW)
 
153
static GtkActionEntry image_entries[] = {
 
154
 
 
155
        { "image-save",
 
156
        GTK_STOCK_SAVE,
 
157
        N_("Save _Image..."),
 
158
        NULL,
 
159
        N_("Save the image to a file"),
 
160
        NULL    /* Handled by EMailReader */ },
 
161
 
 
162
};
 
163
 
 
164
static void
 
165
mail_display_update_actions (EWebView *web_view,
 
166
                             GdkEventButton *event)
 
167
{
 
168
        WebKitHitTestResult *hit_test;
 
169
        WebKitHitTestResultContext context;
 
170
        gchar *image_src;
 
171
        gboolean visible;
 
172
        GtkAction *action;
 
173
 
 
174
        /* Chain up first! */
 
175
        E_WEB_VIEW_CLASS (e_mail_display_parent_class)->
 
176
                update_actions (web_view, event);
 
177
 
 
178
        hit_test = webkit_web_view_get_hit_test_result (
 
179
                        WEBKIT_WEB_VIEW (web_view), event);
 
180
        g_object_get (
 
181
                G_OBJECT (hit_test),
 
182
                "context", &context,
 
183
                "image-uri", &image_src,
 
184
                NULL);
 
185
 
 
186
        if (!(context & WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE))
 
187
                return;
 
188
 
 
189
        visible = image_src && g_str_has_prefix (image_src, "cid:");
 
190
        if (!visible && image_src) {
 
191
                CamelStream *image_stream;
 
192
 
 
193
                image_stream = camel_data_cache_get (emd_global_http_cache, "http", image_src, NULL);
 
194
 
 
195
                visible = image_stream != NULL;
 
196
 
 
197
                if (image_stream)
 
198
                        g_object_unref (image_stream);
 
199
        }
 
200
 
 
201
        if (image_src)
 
202
                g_free (image_src);
 
203
 
 
204
        action = e_web_view_get_action (web_view, "image-save");
 
205
        if (action)
 
206
                gtk_action_set_visible (action, visible);
 
207
}
 
208
 
 
209
static void
 
210
formatter_image_loading_policy_changed_cb (GObject *object,
 
211
                                           GParamSpec *pspec,
 
212
                                           gpointer user_data)
 
213
{
 
214
        EMailDisplay *display = user_data;
 
215
 
 
216
        e_mail_display_load_images (display);
 
217
}
105
218
 
106
219
static void
107
220
mail_display_update_formatter_colors (EMailDisplay *display)
108
221
{
109
 
        EMFormatHTMLColorType type;
110
 
        EMFormatHTML *formatter;
111
 
        GdkColor *color;
 
222
        GtkStyle *style;
112
223
        GtkStateType state;
113
 
        GtkStyle *style;
114
 
 
 
224
 
 
225
        if (!display->priv->formatter)
 
226
                return;
 
227
 
 
228
        style = gtk_widget_get_style (GTK_WIDGET (display));
115
229
        state = gtk_widget_get_state (GTK_WIDGET (display));
116
 
        formatter = display->priv->formatter;
117
 
 
118
 
        style = gtk_widget_get_style (GTK_WIDGET (display));
119
 
        if (style == NULL)
120
 
                return;
121
 
 
122
 
        g_object_freeze_notify (G_OBJECT (formatter));
123
 
 
124
 
        color = &style->bg[state];
125
 
        type = EM_FORMAT_HTML_COLOR_BODY;
126
 
        em_format_html_set_color (formatter, type, color);
127
 
 
128
 
        color = &style->base[GTK_STATE_NORMAL];
129
 
        type = EM_FORMAT_HTML_COLOR_CONTENT;
130
 
        em_format_html_set_color (formatter, type, color);
131
 
 
132
 
        color = &style->dark[state];
133
 
        type = EM_FORMAT_HTML_COLOR_FRAME;
134
 
        em_format_html_set_color (formatter, type, color);
135
 
 
136
 
        color = &style->fg[state];
137
 
        type = EM_FORMAT_HTML_COLOR_HEADER;
138
 
        em_format_html_set_color (formatter, type, color);
139
 
 
140
 
        color = &style->text[state];
141
 
        type = EM_FORMAT_HTML_COLOR_TEXT;
142
 
        em_format_html_set_color (formatter, type, color);
143
 
 
144
 
        g_object_thaw_notify (G_OBJECT (formatter));
 
230
        e_mail_formatter_set_style (display->priv->formatter, style, state);
145
231
}
146
232
 
147
233
static void
151
237
                           GParamSpec *pspec)
152
238
{
153
239
        switch (property_id) {
154
 
                case PROP_FORMATTER:
155
 
                        e_mail_display_set_formatter (
156
 
                                E_MAIL_DISPLAY (object),
157
 
                                g_value_get_object (value));
 
240
                case PROP_PART_LIST:
 
241
                        e_mail_display_set_parts_list (
 
242
                                E_MAIL_DISPLAY (object),
 
243
                                g_value_get_pointer (value));
 
244
                        return;
 
245
                case PROP_MODE:
 
246
                        e_mail_display_set_mode (
 
247
                                E_MAIL_DISPLAY (object),
 
248
                                g_value_get_int (value));
 
249
                        return;
 
250
                case PROP_HEADERS_COLLAPSABLE:
 
251
                        e_mail_display_set_headers_collapsable (
 
252
                                E_MAIL_DISPLAY (object),
 
253
                                g_value_get_boolean (value));
 
254
                        return;
 
255
                case PROP_HEADERS_COLLAPSED:
 
256
                        e_mail_display_set_headers_collapsed (
 
257
                                E_MAIL_DISPLAY (object),
 
258
                                g_value_get_boolean (value));
158
259
                        return;
159
260
        }
160
261
 
168
269
                           GParamSpec *pspec)
169
270
{
170
271
        switch (property_id) {
171
 
                case PROP_FORMATTER:
172
 
                        g_value_set_object (
173
 
                                value, e_mail_display_get_formatter (
 
272
                case PROP_PART_LIST:
 
273
                        g_value_set_pointer (
 
274
                                value, e_mail_display_get_parts_list (
 
275
                                E_MAIL_DISPLAY (object)));
 
276
                        return;
 
277
                case PROP_MODE:
 
278
                        g_value_set_int (
 
279
                                value, e_mail_display_get_mode (
 
280
                                E_MAIL_DISPLAY (object)));
 
281
                        return;
 
282
                case PROP_HEADERS_COLLAPSABLE:
 
283
                        g_value_set_boolean (
 
284
                                value, e_mail_display_get_headers_collapsable (
 
285
                                E_MAIL_DISPLAY (object)));
 
286
                        return;
 
287
                case PROP_HEADERS_COLLAPSED:
 
288
                        g_value_set_boolean (
 
289
                                value, e_mail_display_get_headers_collapsed (
174
290
                                E_MAIL_DISPLAY (object)));
175
291
                        return;
176
292
        }
185
301
 
186
302
        priv = E_MAIL_DISPLAY_GET_PRIVATE (object);
187
303
 
188
 
        if (priv->formatter) {
189
 
                g_object_unref (priv->formatter);
190
 
                priv->formatter = NULL;
 
304
        if (priv->part_list) {
 
305
                g_object_unref (priv->part_list);
 
306
                priv->part_list = NULL;
 
307
        }
 
308
 
 
309
        if (priv->settings) {
 
310
                g_object_unref (priv->settings);
 
311
                priv->settings = NULL;
 
312
        }
 
313
 
 
314
        if (priv->widgets) {
 
315
                g_hash_table_destroy (priv->widgets);
 
316
                priv->widgets = NULL;
191
317
        }
192
318
 
193
319
        /* Chain up to parent's dispose() method. */
207
333
mail_display_style_set (GtkWidget *widget,
208
334
                        GtkStyle *previous_style)
209
335
{
210
 
        EMailDisplayPrivate *priv;
 
336
        EMailDisplay *display = E_MAIL_DISPLAY (widget);
211
337
 
212
 
        priv = E_MAIL_DISPLAY_GET_PRIVATE (widget);
 
338
        mail_display_update_formatter_colors (display);
213
339
 
214
340
        /* Chain up to parent's style_set() method. */
215
341
        GTK_WIDGET_CLASS (e_mail_display_parent_class)->
216
342
                style_set (widget, previous_style);
217
 
 
218
 
        mail_display_update_formatter_colors (E_MAIL_DISPLAY (widget));
219
 
        em_format_queue_redraw (EM_FORMAT (priv->formatter));
220
 
}
221
 
 
222
 
static void
223
 
mail_display_load_string (EWebView *web_view,
224
 
                          const gchar *string)
225
 
{
226
 
        EMailDisplayPrivate *priv;
227
 
 
228
 
        priv = E_MAIL_DISPLAY_GET_PRIVATE (web_view);
229
 
        g_return_if_fail (priv->formatter != NULL);
230
 
 
231
 
        if (em_format_busy (EM_FORMAT (priv->formatter)))
232
 
                return;
233
 
 
234
 
        /* Chain up to parent's load_string() method. */
235
 
        E_WEB_VIEW_CLASS (e_mail_display_parent_class)->
236
 
                load_string (web_view, string);
237
 
}
238
 
 
239
 
static void
240
 
mail_display_url_requested (GtkHTML *html,
241
 
                            const gchar *uri,
242
 
                            GtkHTMLStream *stream)
243
 
{
244
 
        /* XXX Sadly, we must block the default method
245
 
         *     until EMFormatHTML is made asynchronous. */
246
343
}
247
344
 
248
345
static gboolean
249
346
mail_display_process_mailto (EWebView *web_view,
250
 
                             const gchar *mailto_uri)
 
347
                             const gchar *mailto_uri,
 
348
                             gpointer user_data)
251
349
{
252
 
        g_return_val_if_fail (web_view != NULL, FALSE);
 
350
        g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
253
351
        g_return_val_if_fail (mailto_uri != NULL, FALSE);
254
 
        g_return_val_if_fail (E_IS_MAIL_DISPLAY (web_view), FALSE);
255
352
 
256
353
        if (g_ascii_strncasecmp (mailto_uri, "mailto:", 7) == 0) {
257
 
                EMailDisplayPrivate *priv;
258
 
                EMFormat *format;
259
 
                CamelFolder *folder = NULL;
260
354
                EShell *shell;
261
 
 
262
 
                priv = E_MAIL_DISPLAY_GET_PRIVATE (web_view);
263
 
                g_return_val_if_fail (priv->formatter != NULL, FALSE);
264
 
 
265
 
                format = EM_FORMAT (priv->formatter);
266
 
 
267
 
                if (format != NULL && format->folder != NULL)
268
 
                        folder = format->folder;
 
355
                EMailPartList *part_list;
 
356
 
 
357
                part_list = E_MAIL_DISPLAY (web_view)->priv->part_list;
269
358
 
270
359
                shell = e_shell_get_default ();
271
360
                em_utils_compose_new_message_with_mailto (
272
 
                        shell, mailto_uri, folder);
 
361
                        shell, mailto_uri, part_list->folder);
273
362
 
274
363
                return TRUE;
275
364
        }
277
366
        return FALSE;
278
367
}
279
368
 
280
 
static void
281
 
mail_display_link_clicked (GtkHTML *html,
282
 
                           const gchar *uri)
 
369
static gboolean
 
370
mail_display_link_clicked (WebKitWebView *web_view,
 
371
                           WebKitWebFrame *frame,
 
372
                           WebKitNetworkRequest *request,
 
373
                           WebKitWebNavigationAction *navigation_action,
 
374
                           WebKitWebPolicyDecision *policy_decision,
 
375
                           gpointer user_data)
283
376
{
284
 
        EMailDisplayPrivate *priv;
285
 
 
286
 
        priv = E_MAIL_DISPLAY_GET_PRIVATE (html);
287
 
        g_return_if_fail (priv->formatter != NULL);
288
 
 
289
 
        if (g_str_has_prefix (uri, "##")) {
290
 
                guint32 flags;
291
 
 
292
 
                flags = priv->formatter->header_wrap_flags;
293
 
 
294
 
                if (strcmp (uri, "##TO##") == 0) {
295
 
                        if (!(flags & EM_FORMAT_HTML_HEADER_TO))
296
 
                                flags |= EM_FORMAT_HTML_HEADER_TO;
297
 
                        else
298
 
                                flags &= ~EM_FORMAT_HTML_HEADER_TO;
299
 
                } else if (strcmp (uri, "##CC##") == 0) {
300
 
                        if (!(flags & EM_FORMAT_HTML_HEADER_CC))
301
 
                                flags |= EM_FORMAT_HTML_HEADER_CC;
302
 
                        else
303
 
                                flags &= ~EM_FORMAT_HTML_HEADER_CC;
304
 
                } else if (strcmp (uri, "##BCC##") == 0) {
305
 
                        if (!(flags & EM_FORMAT_HTML_HEADER_BCC))
306
 
                                flags |= EM_FORMAT_HTML_HEADER_BCC;
307
 
                        else
308
 
                                flags &= ~EM_FORMAT_HTML_HEADER_BCC;
309
 
                } else if (strcmp (uri, "##HEADERS##") == 0) {
310
 
                        EMFormatHTMLHeadersState state;
311
 
 
312
 
                        state = em_format_html_get_headers_state (
313
 
                                priv->formatter);
314
 
 
315
 
                        if (state == EM_FORMAT_HTML_HEADERS_STATE_COLLAPSED)
316
 
                                state = EM_FORMAT_HTML_HEADERS_STATE_EXPANDED;
317
 
                        else
318
 
                                state = EM_FORMAT_HTML_HEADERS_STATE_COLLAPSED;
319
 
 
320
 
                        em_format_html_set_headers_state (
321
 
                                priv->formatter, state);
 
377
        const gchar *uri = webkit_network_request_get_uri (request);
 
378
 
 
379
        if (g_str_has_prefix (uri, "file://")) {
 
380
                gchar *filename;
 
381
                filename = g_filename_from_uri (uri, NULL, NULL);
 
382
 
 
383
                if (g_file_test (filename, G_FILE_TEST_IS_DIR)) {
 
384
                        webkit_web_policy_decision_ignore (policy_decision);
 
385
                        webkit_network_request_set_uri (request, "about:blank");
 
386
                        g_free (filename);
 
387
                        return TRUE;
322
388
                }
323
389
 
324
 
                priv->formatter->header_wrap_flags = flags;
325
 
                em_format_queue_redraw (EM_FORMAT (priv->formatter));
 
390
                g_free (filename);
 
391
        }
326
392
 
327
 
        } else if (mail_display_process_mailto (E_WEB_VIEW (html), uri)) {
 
393
        if (mail_display_process_mailto (E_WEB_VIEW (web_view), uri, NULL)) {
328
394
                /* do nothing, function handled the "mailto:" uri already */
329
 
        } else if (*uri == '#')
330
 
                gtk_html_jump_to_anchor (html, uri + 1);
331
 
 
332
 
        else if (g_ascii_strncasecmp (uri, "thismessage:", 12) == 0)
333
 
                /* ignore */ ;
334
 
 
335
 
        else if (g_ascii_strncasecmp (uri, "cid:", 4) == 0)
336
 
                /* ignore */ ;
337
 
 
338
 
        else {
339
 
                /* Chain up to parent's link_clicked() method. */
340
 
                GTK_HTML_CLASS (e_mail_display_parent_class)->
341
 
                        link_clicked (html, uri);
342
 
        }
 
395
                webkit_web_policy_decision_ignore (policy_decision);
 
396
                return TRUE;
 
397
 
 
398
        } else if (g_ascii_strncasecmp (uri, "thismessage:", 12) == 0) {
 
399
                /* ignore */ ;
 
400
                webkit_web_policy_decision_ignore (policy_decision);
 
401
                return TRUE;
 
402
 
 
403
        } else if (g_ascii_strncasecmp (uri, "cid:", 4) == 0) {
 
404
                /* ignore */ ;
 
405
                webkit_web_policy_decision_ignore (policy_decision);
 
406
                return TRUE;
 
407
 
 
408
        }
 
409
 
 
410
        /* Let webkit handle it */
 
411
        return FALSE;
 
412
}
 
413
 
 
414
static void
 
415
webkit_request_load_from_file (WebKitNetworkRequest *request,
 
416
                               const gchar *path)
 
417
{
 
418
        gchar *data = NULL;
 
419
        gsize length = 0;
 
420
        gboolean status;
 
421
        gchar *b64, *new_uri;
 
422
        gchar *ct;
 
423
 
 
424
        status = g_file_get_contents (path, &data, &length, NULL);
 
425
        if (!status)
 
426
                return;
 
427
 
 
428
        b64 = g_base64_encode ((guchar *) data, length);
 
429
        ct = g_content_type_guess (path, NULL, 0, NULL);
 
430
 
 
431
        new_uri =  g_strdup_printf ("data:%s;base64,%s", ct, b64);
 
432
        webkit_network_request_set_uri (request, new_uri);
 
433
 
 
434
        g_free (b64);
 
435
        g_free (new_uri);
 
436
        g_free (ct);
 
437
        g_free (data);
 
438
}
 
439
 
 
440
static void
 
441
mail_display_resource_requested (WebKitWebView *web_view,
 
442
                                 WebKitWebFrame *frame,
 
443
                                 WebKitWebResource *resource,
 
444
                                 WebKitNetworkRequest *request,
 
445
                                 WebKitNetworkResponse *response,
 
446
                                 gpointer user_data)
 
447
{
 
448
        EMailDisplay *display = E_MAIL_DISPLAY (web_view);
 
449
        EMailPartList *part_list;
 
450
        const gchar *uri = webkit_network_request_get_uri (request);
 
451
 
 
452
        part_list = display->priv->part_list;
 
453
        if (!part_list) {
 
454
                return;
 
455
        }
 
456
 
 
457
        /* Redirect cid:part_id to mail://mail_id/cid:part_id */
 
458
        if (g_str_has_prefix (uri, "cid:")) {
 
459
 
 
460
                /* Always write raw content of CID object */
 
461
                gchar *new_uri = e_mail_part_build_uri (
 
462
                        part_list->folder, part_list->message_uid,
 
463
                        "part_id", G_TYPE_STRING, uri,
 
464
                        "mode", G_TYPE_INT, E_MAIL_FORMATTER_MODE_RAW, NULL);
 
465
 
 
466
                webkit_network_request_set_uri (request, new_uri);
 
467
 
 
468
                g_free (new_uri);
 
469
 
 
470
        /* WebKit won't allow to load a local file when displaing "remote" mail://,
 
471
           protocol, so we need to handle this manually */
 
472
        } else if (g_str_has_prefix (uri, "file:")) {
 
473
                gchar *path;
 
474
 
 
475
                path = g_filename_from_uri (uri, NULL, NULL);
 
476
                if (!path)
 
477
                        return;
 
478
 
 
479
                webkit_request_load_from_file (request, path);
 
480
 
 
481
                g_free (path);
 
482
 
 
483
        /* Redirect http(s) request to evo-http(s) protocol. See EMailRequest for
 
484
         * further details about this. */
 
485
        } else if (g_str_has_prefix (uri, "http:") || g_str_has_prefix (uri, "https")) {
 
486
 
 
487
                gchar *new_uri, *mail_uri, *enc;
 
488
                SoupURI *soup_uri;
 
489
                GHashTable *query;
 
490
                gchar *uri_md5;
 
491
                CamelStream *stream;
 
492
                EMailImageLoadingPolicy image_policy;
 
493
 
 
494
                /* Open Evolution's cache */
 
495
                uri_md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, uri, -1);
 
496
                stream = camel_data_cache_get (
 
497
                                emd_global_http_cache, "http", uri_md5, NULL);
 
498
                g_free (uri_md5);
 
499
 
 
500
                /* If the URI is not cached and we are not allowed to load it
 
501
                 * then redirect to invalid URI, so that webkit would display
 
502
                 * a native placeholder for it. */
 
503
                image_policy = e_mail_formatter_get_image_loading_policy (
 
504
                                        display->priv->formatter);
 
505
                if (!stream && !display->priv->force_image_load &&
 
506
                    (image_policy == E_MAIL_IMAGE_LOADING_POLICY_NEVER)) {
 
507
                        webkit_network_request_set_uri (request, "about:blank");
 
508
                        return;
 
509
                }
 
510
 
 
511
                new_uri = g_strconcat ("evo-", uri, NULL);
 
512
                mail_uri = e_mail_part_build_uri (part_list->folder,
 
513
                                part_list->message_uid, NULL, NULL);
 
514
 
 
515
                soup_uri = soup_uri_new (new_uri);
 
516
                if (soup_uri->query) {
 
517
                        query = soup_form_decode (soup_uri->query);
 
518
                } else {
 
519
                        query = g_hash_table_new_full (g_str_hash, g_str_equal,
 
520
                                                       g_free, g_free);
 
521
                }
 
522
                enc = soup_uri_encode (mail_uri, NULL);
 
523
                g_hash_table_insert (query, g_strdup ("__evo-mail"), enc);
 
524
 
 
525
                if (display->priv->force_image_load) {
 
526
                        g_hash_table_insert (query,
 
527
                                g_strdup ("__evo-load-images"),
 
528
                                             g_strdup ("true"));
 
529
                }
 
530
 
 
531
                g_free (mail_uri);
 
532
 
 
533
                soup_uri_set_query_from_form (soup_uri, query);
 
534
                g_free (new_uri);
 
535
 
 
536
                new_uri = soup_uri_to_string (soup_uri, FALSE);
 
537
                webkit_network_request_set_uri (request, new_uri);
 
538
 
 
539
                g_free (new_uri);
 
540
                soup_uri_free (soup_uri);
 
541
                g_hash_table_unref (query);
 
542
        }
 
543
}
 
544
 
 
545
static WebKitDOMElement *
 
546
find_element_by_id (WebKitDOMDocument *document,
 
547
                    const gchar *id)
 
548
{
 
549
        WebKitDOMNodeList *frames;
 
550
        WebKitDOMElement *element;
 
551
        gulong i, length;
 
552
 
 
553
        if (!WEBKIT_DOM_IS_DOCUMENT (document))
 
554
                return NULL;
 
555
 
 
556
        /* Try to look up the element in this DOM document */
 
557
        element = webkit_dom_document_get_element_by_id (document, id);
 
558
        if (element)
 
559
                return element;
 
560
 
 
561
        /* If the element is not here then recursively scan all frames */
 
562
        frames = webkit_dom_document_get_elements_by_tag_name(document, "iframe");
 
563
        length = webkit_dom_node_list_get_length (frames);
 
564
        for (i = 0; i < length; i++) {
 
565
 
 
566
                WebKitDOMHTMLIFrameElement *iframe =
 
567
                        WEBKIT_DOM_HTML_IFRAME_ELEMENT (
 
568
                                webkit_dom_node_list_item (frames, i));
 
569
 
 
570
                WebKitDOMDocument *frame_doc =
 
571
                        webkit_dom_html_iframe_element_get_content_document (iframe);
 
572
 
 
573
                WebKitDOMElement *el =
 
574
                        find_element_by_id (frame_doc, id);
 
575
 
 
576
                if (el)
 
577
                        return el;
 
578
        }
 
579
 
 
580
        return NULL;
 
581
}
 
582
 
 
583
static void
 
584
mail_display_plugin_widget_resize (GObject *object,
 
585
                                   gpointer dummy,
 
586
                                   EMailDisplay *display)
 
587
{
 
588
        GtkWidget *widget;
 
589
        WebKitDOMElement *parent_element;
 
590
        gchar *dim;
 
591
        gint height;
 
592
 
 
593
        widget = GTK_WIDGET (object);
 
594
        parent_element = g_object_get_data (object, "parent_element");
 
595
 
 
596
        if (!parent_element || !WEBKIT_DOM_IS_ELEMENT (parent_element)) {
 
597
                d(printf("%s: %s does not have (valid) parent element!\n",
 
598
                        G_STRFUNC, (gchar *) g_object_get_data (object, "uri")));
 
599
                return;
 
600
        }
 
601
 
 
602
        /* For attachment bar, we need to ask for height it's parent,
 
603
         * GtkBox, because EAttachmentBar itself lies about it's real height. */
 
604
        if (E_IS_ATTACHMENT_BAR (widget)) {
 
605
                widget = gtk_widget_get_parent (widget);
 
606
        }
 
607
 
 
608
        gtk_widget_get_preferred_height (widget, &height, NULL);
 
609
 
 
610
        /* Int -> Str */
 
611
        dim = g_strdup_printf ("%d", height);
 
612
 
 
613
        /* Set height of the containment <object> to match height of the
 
614
         * GtkWidget it contains */
 
615
        webkit_dom_html_object_element_set_height (
 
616
                WEBKIT_DOM_HTML_OBJECT_ELEMENT (parent_element), dim);
 
617
        g_free (dim);
 
618
}
 
619
 
 
620
static void
 
621
mail_display_plugin_widget_realize_cb (GtkWidget *widget,
 
622
                                       gpointer user_data)
 
623
{
 
624
        WebKitDOMHTMLElement *el;
 
625
 
 
626
        if (GTK_IS_BOX (widget)) {
 
627
                GList *children;
 
628
 
 
629
                children = gtk_container_get_children (GTK_CONTAINER (widget));
 
630
                if (children && children->data &&
 
631
                    E_IS_ATTACHMENT_BAR (children->data)) {
 
632
                        widget = children->data;
 
633
                }
 
634
 
 
635
                g_list_free (children);
 
636
        }
 
637
 
 
638
        /* First check if we are actually supposed to be visible */
 
639
        el = g_object_get_data (G_OBJECT (widget), "parent_element");
 
640
        if (!el || !WEBKIT_DOM_IS_HTML_ELEMENT (el)) {
 
641
                g_warning ("UAAAAA");
 
642
        } else {
 
643
                if (webkit_dom_html_element_get_hidden (el)) {
 
644
                        gtk_widget_hide (widget);
 
645
                        return;
 
646
                }
 
647
        }
 
648
 
 
649
        /* Initial resize of the <object> element when the widget
 
650
         * is displayed for the first time. */
 
651
        mail_display_plugin_widget_resize (G_OBJECT (widget), NULL, user_data);
 
652
}
 
653
 
 
654
static void
 
655
plugin_widget_set_parent_element (GtkWidget *widget,
 
656
                                  EMailDisplay *display)
 
657
{
 
658
        const gchar *uri;
 
659
        WebKitDOMDocument *document;
 
660
        WebKitDOMElement *element;
 
661
 
 
662
        uri = g_object_get_data (G_OBJECT (widget), "uri");
 
663
        if (!uri || !*uri)
 
664
                return;
 
665
 
 
666
        document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (display));
 
667
        element = find_element_by_id (document, uri);
 
668
 
 
669
        if (!element || !WEBKIT_DOM_IS_ELEMENT (element)) {
 
670
                g_warning ("Failed to find parent <object> for '%s' - no ID set?", uri);
 
671
                return;
 
672
        }
 
673
 
 
674
        /* Assign the WebKitDOMElement to "parent_element" data of the GtkWidget
 
675
         * and the GtkWidget to "widget" data of the DOM Element */
 
676
        g_object_set_data (G_OBJECT (widget), "parent_element", element);
 
677
        g_object_set_data (G_OBJECT (element), "widget", widget);
 
678
 
 
679
        g_object_bind_property (
 
680
                element, "hidden",
 
681
                widget, "visible",
 
682
                G_BINDING_SYNC_CREATE |
 
683
                G_BINDING_INVERT_BOOLEAN);
 
684
}
 
685
 
 
686
static void
 
687
toggle_widget_visibility (EAttachmentButton *button,
 
688
                          EMailDisplay *display,
 
689
                          WebKitDOMElement *element)
 
690
{
 
691
        gchar *id;
 
692
        GtkWidget *widget;
 
693
 
 
694
        id = webkit_dom_html_element_get_id (WEBKIT_DOM_HTML_ELEMENT (element));
 
695
        if (!id || !*id) {
 
696
                return;
 
697
        }
 
698
 
 
699
        if (!display->priv->widgets) {
 
700
                g_free (id);
 
701
                return;
 
702
        }
 
703
 
 
704
        widget = g_hash_table_lookup (display->priv->widgets, id);
 
705
        g_free (id);
 
706
        if (!widget) {
 
707
                return;
 
708
        }
 
709
 
 
710
        /* If the widget encapsulates EAttachmentBar then check, whether
 
711
         * the attachment bar is not empty. We want to display it only
 
712
         * when there's at least one attachment */
 
713
        if (GTK_IS_BOX (widget)) {
 
714
                GList *children;
 
715
 
 
716
                children = gtk_container_get_children (GTK_CONTAINER (widget));
 
717
                if (children && children->data && E_IS_ATTACHMENT_BAR (children->data)) {
 
718
                        EAttachmentStore *store;
 
719
 
 
720
                        store = e_attachment_bar_get_store (
 
721
                                        E_ATTACHMENT_BAR (children->data));
 
722
 
 
723
                        g_list_free (children);
 
724
 
 
725
                        /* Don't allow to display such attachment bar,
 
726
                         * but always allow to hide it */
 
727
                        if (e_attachment_button_get_expanded (button) &&
 
728
                            (e_attachment_store_get_num_attachments (store) == 0)) {
 
729
                                return;
 
730
                        }
 
731
                }
 
732
        }
 
733
 
 
734
        webkit_dom_html_element_set_hidden (
 
735
                WEBKIT_DOM_HTML_ELEMENT (element),
 
736
                !e_attachment_button_get_expanded (button));
 
737
 
 
738
        if (e_attachment_button_get_expanded (button)) {
 
739
                gtk_widget_show (widget);
 
740
        } else {
 
741
                gtk_widget_hide (widget);
 
742
        }
 
743
}
 
744
 
 
745
/**
 
746
 * @button: An #EAttachmentButton
 
747
 * @iframe: An iframe element containing document with an attachment
 
748
 *          represented by the @button
 
749
 */
 
750
static void
 
751
bind_iframe_content_visibility (WebKitDOMElement *iframe,
 
752
                                EMailDisplay *display,
 
753
                                EAttachmentButton *button)
 
754
{
 
755
        WebKitDOMDocument *document;
 
756
        WebKitDOMNodeList *nodes;
 
757
        gulong i, length;
 
758
 
 
759
        if (!iframe || !WEBKIT_DOM_IS_HTML_IFRAME_ELEMENT (iframe))
 
760
                return;
 
761
 
 
762
        document = webkit_dom_html_iframe_element_get_content_document (
 
763
                        WEBKIT_DOM_HTML_IFRAME_ELEMENT (iframe));
 
764
        if (!WEBKIT_DOM_IS_DOCUMENT (document))
 
765
                return;
 
766
 
 
767
        nodes = webkit_dom_document_get_elements_by_tag_name (document, "object");
 
768
        length = webkit_dom_node_list_get_length (nodes);
 
769
 
 
770
        d ({
 
771
                gchar *name = webkit_dom_html_iframe_element_get_name (
 
772
                                WEBKIT_DOM_HTML_IFRAME_ELEMENT (iframe));
 
773
                printf("Found %ld objects within iframe %s\n", length, name);
 
774
                g_free (name);
 
775
        });
 
776
 
 
777
        /* Iterate through all <object>s and bind visibility of their widget
 
778
         * with expanded-state of related attachment button */
 
779
        for (i = 0; i < length; i++) {
 
780
 
 
781
                WebKitDOMNode *node = webkit_dom_node_list_item (nodes, i);
 
782
 
 
783
                /* Initial sync */
 
784
                toggle_widget_visibility (button, display, WEBKIT_DOM_ELEMENT (node));
 
785
        }
 
786
}
 
787
 
 
788
static void
 
789
attachment_button_expanded (GObject *object,
 
790
                            GParamSpec *pspec,
 
791
                            gpointer user_data)
 
792
{
 
793
        EAttachmentButton *button = E_ATTACHMENT_BUTTON (object);
 
794
        EMailDisplay *display = user_data;
 
795
        WebKitDOMDocument *document;
 
796
        WebKitDOMElement *element;
 
797
        WebKitDOMCSSStyleDeclaration *css;
 
798
        gboolean expanded;
 
799
        gchar *id;
 
800
 
 
801
        d(printf("Attachment button %s has been %s!\n",
 
802
                (gchar *) g_object_get_data (object, "uri"),
 
803
                (e_attachment_button_get_expanded (button) ? "expanded" : "collapsed")));
 
804
 
 
805
        expanded = e_attachment_button_get_expanded (button) &&
 
806
                        gtk_widget_get_visible (GTK_WIDGET (button));
 
807
 
 
808
        document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (display));
 
809
        element = find_element_by_id (document, g_object_get_data (object, "attachment_id"));
 
810
 
 
811
        if (!WEBKIT_DOM_IS_ELEMENT (element)) {
 
812
                d(printf("%s: Content <div> of attachment %s does not exist!!\n",
 
813
                        G_STRFUNC, (gchar *) g_object_get_data (object, "uri")));
 
814
                return;
 
815
        }
 
816
 
 
817
        /* Show or hide the DIV which contains the attachment (iframe, image...) */
 
818
        css = webkit_dom_element_get_style (element);
 
819
        webkit_dom_css_style_declaration_set_property (
 
820
                css, "display", expanded ? "block" : "none", "", NULL);
 
821
 
 
822
        id = g_strconcat (g_object_get_data (object, "attachment_id"), ".iframe", NULL);
 
823
        element = find_element_by_id (document, id);
 
824
        g_free (id);
 
825
 
 
826
        if (!WEBKIT_DOM_IS_HTML_IFRAME_ELEMENT (element)) {
 
827
                d(printf("%s: No <iframe> found\n",
 
828
                         (gchar *) g_object_get_data (object, "attachment_id")));
 
829
                return;
 
830
        }
 
831
        bind_iframe_content_visibility (element, display, button);
 
832
}
 
833
 
 
834
static void
 
835
mail_display_attachment_count_changed (EAttachmentStore *store,
 
836
                                       GParamSpec *pspec,
 
837
                                       GtkWidget *box)
 
838
{
 
839
        WebKitDOMHTMLElement *element;
 
840
        GList *children;
 
841
 
 
842
        children = gtk_container_get_children (GTK_CONTAINER (box));
 
843
        g_return_if_fail (children  && children->data);
 
844
 
 
845
        element = g_object_get_data (children->data, "parent_element");
 
846
        g_list_free (children);
 
847
 
 
848
        g_return_if_fail (WEBKIT_DOM_IS_HTML_ELEMENT (element));
 
849
 
 
850
        if (e_attachment_store_get_num_attachments (store) == 0) {
 
851
                gtk_widget_hide (box);
 
852
                webkit_dom_html_element_set_hidden (element, TRUE);
 
853
        } else {
 
854
                gtk_widget_show (box);
 
855
                webkit_dom_html_element_set_hidden (element, FALSE);
 
856
        }
 
857
}
 
858
 
 
859
static GtkWidget *
 
860
mail_display_plugin_widget_requested (WebKitWebView *web_view,
 
861
                                      gchar *mime_type,
 
862
                                      gchar *uri,
 
863
                                      GHashTable *param,
 
864
                                      gpointer user_data)
 
865
{
 
866
        EMailDisplay *display;
 
867
        EMailExtensionRegistry *reg;
 
868
        EMailFormatterExtension *extension;
 
869
        GQueue *extensions;
 
870
        GList *iter;
 
871
        EMailPart *part;
 
872
        GtkWidget *widget;
 
873
        gchar *part_id, *type, *object_uri;
 
874
 
 
875
        part_id = g_hash_table_lookup (param, "data");
 
876
        if (!part_id || !g_str_has_prefix (uri, "mail://"))
 
877
                return NULL;
 
878
 
 
879
        type = g_hash_table_lookup (param, "type");
 
880
        if (!type)
 
881
                return NULL;
 
882
 
 
883
        display = E_MAIL_DISPLAY (web_view);
 
884
 
 
885
        if ((widget = g_hash_table_lookup (display->priv->widgets, part_id)) != NULL) {
 
886
                d(printf("Handeled %s widget request from cache\n", part_id));
 
887
                return widget;
 
888
        }
 
889
 
 
890
        /* Findt EMailPart representing requested widget */
 
891
        part = e_mail_part_list_find_part (display->priv->part_list, part_id);
 
892
        if (!part) {
 
893
                return NULL;
 
894
        }
 
895
 
 
896
        reg = e_mail_formatter_get_extension_registry (display->priv->formatter);
 
897
        extensions = e_mail_extension_registry_get_for_mime_type (reg, type);
 
898
        if (!extensions)
 
899
                return NULL;
 
900
 
 
901
        extension = NULL;
 
902
        for (iter = g_queue_peek_head_link (extensions); iter; iter = iter->next) {
 
903
 
 
904
                extension = iter->data;
 
905
                if (!extension)
 
906
                        continue;
 
907
 
 
908
                if (e_mail_formatter_extension_has_widget (extension))
 
909
                        break;
 
910
        }
 
911
 
 
912
        if (!extension)
 
913
                return NULL;
 
914
 
 
915
        /* Get the widget from formatter */
 
916
        widget = e_mail_formatter_extension_get_widget (
 
917
                        extension, display->priv->part_list, part, param);
 
918
        d(printf("Created widget %s (%p) for part %s\n",
 
919
                        G_OBJECT_TYPE_NAME (widget), widget, part_id));
 
920
 
 
921
        /* Should not happen! WebKit will display an ugly 'Plug-in not available'
 
922
         * placeholder instead of hiding the <object> element */
 
923
        if (!widget)
 
924
                return NULL;
 
925
 
 
926
        /* Attachment button has URI different then the actual PURI because
 
927
         * that URI identifies the attachment itself */
 
928
        if (E_IS_ATTACHMENT_BUTTON (widget)) {
 
929
                EMailPartAttachment *empa = (EMailPartAttachment *) part;
 
930
                gchar *attachment_part_id;
 
931
 
 
932
                if (empa->attachment_view_part_id)
 
933
                        attachment_part_id = empa->attachment_view_part_id;
 
934
                else
 
935
                        attachment_part_id = part_id;
 
936
 
 
937
                object_uri = g_strconcat (attachment_part_id, ".attachment_button", NULL);
 
938
                g_object_set_data_full (G_OBJECT (widget), "attachment_id",
 
939
                        g_strdup (attachment_part_id), (GDestroyNotify) g_free);
 
940
        } else {
 
941
                object_uri = g_strdup (part_id);
 
942
        }
 
943
 
 
944
        /* Store the uri as data of the widget */
 
945
        g_object_set_data_full (G_OBJECT (widget), "uri",
 
946
                object_uri, (GDestroyNotify) g_free);
 
947
 
 
948
        /* Set pointer to the <object> element as GObject data "parent_element"
 
949
         * and set pointer to the widget as GObject data "widget" to the <object>
 
950
         * element */
 
951
        plugin_widget_set_parent_element (widget, display);
 
952
 
 
953
        /* Resizing a GtkWidget requires changing size of parent
 
954
         * <object> HTML element in DOM. */
 
955
        g_signal_connect (widget, "realize",
 
956
                          G_CALLBACK (mail_display_plugin_widget_realize_cb), display);
 
957
        g_signal_connect (widget, "size-allocate",
 
958
                          G_CALLBACK (mail_display_plugin_widget_resize), display);
 
959
 
 
960
        if (E_IS_ATTACHMENT_BAR (widget)) {
 
961
                GtkWidget *box = NULL;
 
962
                EAttachmentStore *store;
 
963
 
 
964
                /* Only when packed in box (grid does not work),
 
965
                 * EAttachmentBar reports correct height */
 
966
                box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
 
967
                gtk_box_pack_start (GTK_BOX (box), widget, TRUE, TRUE, 0);
 
968
 
 
969
                /* When EAttachmentBar is expanded/collapsed it does not
 
970
                 * emit size-allocate signal despite it changes it's height. */
 
971
                g_signal_connect (widget, "notify::expanded",
 
972
                        G_CALLBACK (mail_display_plugin_widget_resize), display);
 
973
                g_signal_connect (widget, "notify::active-view",
 
974
                        G_CALLBACK (mail_display_plugin_widget_resize), display);
 
975
 
 
976
                /* Always hide an attachment bar without attachments */
 
977
                store = e_attachment_bar_get_store (E_ATTACHMENT_BAR (widget));
 
978
                g_signal_connect (store, "notify::num-attachments",
 
979
                        G_CALLBACK (mail_display_attachment_count_changed), box);
 
980
 
 
981
                gtk_widget_show (widget);
 
982
                gtk_widget_show (box);
 
983
 
 
984
                /* Initial sync */
 
985
                mail_display_attachment_count_changed (store, NULL, box);
 
986
 
 
987
                widget = box;
 
988
 
 
989
        } else if (E_IS_ATTACHMENT_BUTTON (widget)) {
 
990
 
 
991
                /* Bind visibility of DOM element containing related
 
992
                 * attachment with 'expanded' property of this
 
993
                 * attachment button. */
 
994
                WebKitDOMElement *attachment;
 
995
                WebKitDOMDocument *document;
 
996
                EMailPartAttachment *empa = (EMailPartAttachment *) part;
 
997
                gchar *attachment_part_id;
 
998
 
 
999
                if (empa->attachment_view_part_id)
 
1000
                        attachment_part_id = empa->attachment_view_part_id;
 
1001
                else
 
1002
                        attachment_part_id = part_id;
 
1003
 
 
1004
                /* Find attachment-wrapper div which contains the content of the
 
1005
                 * attachment (iframe) */
 
1006
                document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (display));
 
1007
                attachment = find_element_by_id (document, attachment_part_id);
 
1008
 
 
1009
                /* None found? Attachment cannot be expanded */
 
1010
                if (!attachment) {
 
1011
                        e_attachment_button_set_expandable (
 
1012
                                E_ATTACHMENT_BUTTON (widget), FALSE);
 
1013
                } else {
 
1014
                        const CamelContentDisposition *disposition;
 
1015
 
 
1016
                        e_attachment_button_set_expandable (
 
1017
                                E_ATTACHMENT_BUTTON (widget), TRUE);
 
1018
 
 
1019
                        /* Show/hide the attachment when the EAttachmentButton
 
1020
 *                       * is expanded/collapsed or shown/hidden */
 
1021
                        g_signal_connect (widget, "notify::expanded",
 
1022
                                G_CALLBACK (attachment_button_expanded), display);
 
1023
                        g_signal_connect (widget, "notify::visible",
 
1024
                                G_CALLBACK (attachment_button_expanded), display);
 
1025
 
 
1026
                        /* Automatically expand attachments that have inline
 
1027
                         * disposition or the EMailParts have specific force_inline
 
1028
                         * flag set */
 
1029
                        disposition =
 
1030
                                camel_mime_part_get_content_disposition (part->part);
 
1031
                        if (!part->force_collapse &&
 
1032
                            (part->force_inline ||
 
1033
                            (g_strcmp0 (empa->snoop_mime_type, "message/rfc822") == 0) ||
 
1034
                             (disposition && disposition->disposition &&
 
1035
                                g_ascii_strncasecmp (
 
1036
                                     disposition->disposition, "inline", 6) == 0))) {
 
1037
 
 
1038
                                e_attachment_button_set_expanded (
 
1039
                                        E_ATTACHMENT_BUTTON (widget), TRUE);
 
1040
                        } else {
 
1041
                                e_attachment_button_set_expanded (
 
1042
                                        E_ATTACHMENT_BUTTON (widget), FALSE);
 
1043
                                attachment_button_expanded (
 
1044
                                        G_OBJECT (widget), NULL, display);
 
1045
                        }
 
1046
                }
 
1047
        }
 
1048
 
 
1049
        g_hash_table_insert (
 
1050
                display->priv->widgets,
 
1051
                g_strdup (object_uri), g_object_ref (widget));
 
1052
 
 
1053
        return widget;
 
1054
}
 
1055
 
 
1056
static void
 
1057
toggle_headers_visibility (WebKitDOMElement *button,
 
1058
                           WebKitDOMEvent *event,
 
1059
                           WebKitWebView *web_view)
 
1060
{
 
1061
        WebKitDOMDocument *document;
 
1062
        WebKitDOMElement *short_headers, *full_headers;
 
1063
        WebKitDOMCSSStyleDeclaration *css_short, *css_full;
 
1064
        gboolean expanded;
 
1065
        const gchar *path;
 
1066
        gchar *css_value;
 
1067
 
 
1068
        document = webkit_web_view_get_dom_document (web_view);
 
1069
 
 
1070
        short_headers = webkit_dom_document_get_element_by_id (
 
1071
                document, "__evo-short-headers");
 
1072
        if (!short_headers)
 
1073
                return;
 
1074
 
 
1075
        css_short = webkit_dom_element_get_style (short_headers);
 
1076
 
 
1077
        full_headers = webkit_dom_document_get_element_by_id (
 
1078
                document, "__evo-full-headers");
 
1079
        if (!full_headers)
 
1080
                return;
 
1081
 
 
1082
        css_full = webkit_dom_element_get_style (full_headers);
 
1083
        css_value = webkit_dom_css_style_declaration_get_property_value (
 
1084
                        css_full, "display");
 
1085
        expanded = (g_strcmp0 (css_value, "block") == 0);
 
1086
        g_free (css_value);
 
1087
 
 
1088
        webkit_dom_css_style_declaration_set_property (css_full, "display",
 
1089
                expanded ? "none" : "block", "", NULL);
 
1090
        webkit_dom_css_style_declaration_set_property (css_short, "display",
 
1091
                expanded ? "block" : "none", "", NULL);
 
1092
 
 
1093
        if (expanded)
 
1094
                path = "evo-file://" EVOLUTION_IMAGESDIR "/plus.png";
 
1095
        else
 
1096
                path = "evo-file://" EVOLUTION_IMAGESDIR "/minus.png";
 
1097
 
 
1098
        webkit_dom_html_image_element_set_src (
 
1099
                WEBKIT_DOM_HTML_IMAGE_ELEMENT (button), path);
 
1100
 
 
1101
        e_mail_display_set_headers_collapsed (E_MAIL_DISPLAY (web_view), expanded);
 
1102
 
 
1103
        d(printf("Headers %s!\n", expanded ? "collapsed" : "expanded"));
 
1104
}
 
1105
 
 
1106
static const gchar* addresses[] = { "to", "cc", "bcc" };
 
1107
 
 
1108
static void
 
1109
toggle_address_visibility (WebKitDOMElement *button,
 
1110
                           WebKitDOMEvent *event,
 
1111
                           const gchar *address)
 
1112
{
 
1113
        WebKitDOMElement *full_addr, *ellipsis;
 
1114
        WebKitDOMCSSStyleDeclaration *css_full, *css_ellipsis;
 
1115
        WebKitDOMDocument *document;
 
1116
        gchar *id;
 
1117
        const gchar *path;
 
1118
        gboolean expanded;
 
1119
 
 
1120
        document = webkit_dom_node_get_owner_document (WEBKIT_DOM_NODE (button));
 
1121
 
 
1122
        id = g_strconcat ("__evo-moreaddr-", address, NULL);
 
1123
        full_addr = webkit_dom_document_get_element_by_id (document, id);
 
1124
        g_free (id);
 
1125
 
 
1126
        if (!full_addr)
 
1127
                return;
 
1128
 
 
1129
        css_full = webkit_dom_element_get_style (full_addr);
 
1130
 
 
1131
        id = g_strconcat ("__evo-moreaddr-ellipsis-", address, NULL);
 
1132
        ellipsis = webkit_dom_document_get_element_by_id (document, id);
 
1133
        g_free (id);
 
1134
 
 
1135
        if (!ellipsis)
 
1136
                return;
 
1137
 
 
1138
        css_ellipsis = webkit_dom_element_get_style (ellipsis);
 
1139
 
 
1140
        expanded = (g_strcmp0 (
 
1141
                webkit_dom_css_style_declaration_get_property_value (
 
1142
                css_full, "display"), "inline") == 0);
 
1143
 
 
1144
        webkit_dom_css_style_declaration_set_property (
 
1145
                css_full, "display", (expanded ? "none" : "inline"), "", NULL);
 
1146
        webkit_dom_css_style_declaration_set_property (
 
1147
                css_ellipsis, "display", (expanded ? "inline" : "none"), "", NULL);
 
1148
 
 
1149
        if (expanded) {
 
1150
                path = "evo-file://" EVOLUTION_IMAGESDIR "/plus.png";
 
1151
        } else {
 
1152
                path = "evo-file://" EVOLUTION_IMAGESDIR "/minus.png";
 
1153
        }
 
1154
 
 
1155
        if (!WEBKIT_DOM_IS_HTML_IMAGE_ELEMENT (button)) {
 
1156
                id = g_strconcat ("__evo-moreaddr-img-", address, NULL);
 
1157
                button = webkit_dom_document_get_element_by_id (document, id);
 
1158
                g_free (id);
 
1159
 
 
1160
                if (!button)
 
1161
                        return;
 
1162
        }
 
1163
 
 
1164
        webkit_dom_html_image_element_set_src (
 
1165
                WEBKIT_DOM_HTML_IMAGE_ELEMENT (button), path);
 
1166
 
 
1167
}
 
1168
 
 
1169
static void
 
1170
setup_DOM_bindings (GObject *object,
 
1171
                    GParamSpec *pspec,
 
1172
                    gpointer user_data)
 
1173
{
 
1174
        WebKitWebView *web_view;
 
1175
        WebKitWebFrame *frame;
 
1176
        WebKitLoadStatus load_status;
 
1177
        WebKitDOMDocument *document;
 
1178
        WebKitDOMElement *button;
 
1179
        gint i = 0;
 
1180
 
 
1181
        frame = WEBKIT_WEB_FRAME (object);
 
1182
        load_status = webkit_web_frame_get_load_status (frame);
 
1183
        if (load_status != WEBKIT_LOAD_FINISHED)
 
1184
                return;
 
1185
 
 
1186
        web_view = webkit_web_frame_get_web_view (frame);
 
1187
        document = webkit_web_view_get_dom_document (web_view);
 
1188
 
 
1189
        button = webkit_dom_document_get_element_by_id (
 
1190
                        document, "__evo-collapse-headers-img");
 
1191
        if (!button)
 
1192
                return;
 
1193
 
 
1194
        d(printf("Conntecting to __evo-collapsable-headers-img::click event\n"));
 
1195
 
 
1196
        webkit_dom_event_target_add_event_listener (
 
1197
                WEBKIT_DOM_EVENT_TARGET (button), "click",
 
1198
                G_CALLBACK (toggle_headers_visibility), FALSE, web_view);
 
1199
 
 
1200
        for (i = 0; i < 3; i++) {
 
1201
                gchar *id;
 
1202
                id = g_strconcat ("__evo-moreaddr-img-", addresses[i], NULL);
 
1203
                button = webkit_dom_document_get_element_by_id (document, id);
 
1204
                g_free (id);
 
1205
 
 
1206
                if (!button)
 
1207
                        continue;
 
1208
 
 
1209
                webkit_dom_event_target_add_event_listener (
 
1210
                        WEBKIT_DOM_EVENT_TARGET (button), "click",
 
1211
                        G_CALLBACK (toggle_address_visibility), FALSE,
 
1212
                        (gpointer) addresses[i]);
 
1213
 
 
1214
                id = g_strconcat ("__evo-moreaddr-ellipsis-", addresses[i], NULL);
 
1215
                button = webkit_dom_document_get_element_by_id (document, id);
 
1216
                g_free (id);
 
1217
 
 
1218
                if (!button)
 
1219
                        continue;
 
1220
 
 
1221
                webkit_dom_event_target_add_event_listener (
 
1222
                        WEBKIT_DOM_EVENT_TARGET (button), "click",
 
1223
                        G_CALLBACK (toggle_address_visibility), FALSE,
 
1224
                        (gpointer) addresses[i]);
 
1225
        }
 
1226
}
 
1227
 
 
1228
static void
 
1229
mail_parts_bind_dom (GObject *object,
 
1230
                     GParamSpec *pspec,
 
1231
                     gpointer user_data)
 
1232
{
 
1233
        WebKitWebFrame *frame;
 
1234
        WebKitLoadStatus load_status;
 
1235
        WebKitWebView *web_view;
 
1236
        WebKitDOMDocument *document;
 
1237
        EMailDisplay *display;
 
1238
        GSList *iter;
 
1239
        const gchar *frame_name;
 
1240
 
 
1241
        frame = WEBKIT_WEB_FRAME (object);
 
1242
        load_status = webkit_web_frame_get_load_status (frame);
 
1243
 
 
1244
        if (load_status != WEBKIT_LOAD_FINISHED)
 
1245
                return;
 
1246
 
 
1247
        web_view = webkit_web_frame_get_web_view (frame);
 
1248
        display = E_MAIL_DISPLAY (web_view);
 
1249
        if (display->priv->part_list == NULL)
 
1250
                return;
 
1251
 
 
1252
        frame_name = webkit_web_frame_get_name (frame);
 
1253
        if (!frame_name || !*frame_name)
 
1254
                frame_name = ".message.headers";
 
1255
 
 
1256
        for (iter = display->priv->part_list->list; iter; iter = iter->next) {
 
1257
 
 
1258
                EMailPart *part = iter->data;
 
1259
                if (!part)
 
1260
                        continue;
 
1261
 
 
1262
                if (g_strcmp0 (part->id, frame_name) == 0)
 
1263
                        break;
 
1264
        }
 
1265
 
 
1266
        document = webkit_web_view_get_dom_document (web_view);
 
1267
        while (iter) {
 
1268
 
 
1269
                EMailPart *part = iter->data;
 
1270
                if (!part) {
 
1271
                        iter = iter->next;
 
1272
                        continue;
 
1273
                }
 
1274
 
 
1275
                /* Iterate only the parts rendered in the frame and all it's subparts */
 
1276
                if (!g_str_has_prefix (part->id, frame_name))
 
1277
                        break;
 
1278
 
 
1279
                if (part->bind_func) {
 
1280
                        WebKitDOMElement *el = find_element_by_id (document, part->id);
 
1281
                        if (el) {
 
1282
                                d(printf("/*bind_func*/ for %s\n", part->id));
 
1283
                                part->bind_func (part, el);
 
1284
                        }
 
1285
                }
 
1286
 
 
1287
                iter = iter->next;
 
1288
        }
 
1289
}
 
1290
 
 
1291
static void
 
1292
mail_display_frame_created (WebKitWebView *web_view,
 
1293
                            WebKitWebFrame *frame,
 
1294
                            gpointer user_data)
 
1295
{
 
1296
        d(printf("Frame %s created!\n", webkit_web_frame_get_name (frame)));
 
1297
 
 
1298
        /* Call bind_func of all parts written in this frame */
 
1299
        g_signal_connect (frame, "notify::load-status",
 
1300
                G_CALLBACK (mail_parts_bind_dom), NULL);
 
1301
}
 
1302
 
 
1303
static void
 
1304
mail_display_uri_changed (EMailDisplay *display,
 
1305
                          GParamSpec *pspec,
 
1306
                          gpointer dummy)
 
1307
{
 
1308
        d(printf("EMailDisplay URI changed, recreating widgets hashtable\n"));
 
1309
 
 
1310
        if (display->priv->widgets)
 
1311
                g_hash_table_destroy (display->priv->widgets);
 
1312
 
 
1313
        display->priv->widgets = g_hash_table_new_full (
 
1314
                                        g_str_hash, g_str_equal,
 
1315
                                        (GDestroyNotify) g_free,
 
1316
                                        (GDestroyNotify) g_object_unref);
 
1317
}
 
1318
 
 
1319
static void
 
1320
mail_display_set_fonts (EWebView *web_view,
 
1321
                        PangoFontDescription **monospace,
 
1322
                        PangoFontDescription **variable)
 
1323
{
 
1324
        EMailDisplay *display = E_MAIL_DISPLAY (web_view);
 
1325
        gboolean use_custom_font;
 
1326
        gchar *monospace_font, *variable_font;
 
1327
 
 
1328
        use_custom_font = g_settings_get_boolean (display->priv->settings, "use-custom-font");
 
1329
        if (!use_custom_font) {
 
1330
                *monospace = NULL;
 
1331
                *variable = NULL;
 
1332
                return;
 
1333
        }
 
1334
 
 
1335
        monospace_font = g_settings_get_string (
 
1336
                                display->priv->settings,
 
1337
                                "monospace-font");
 
1338
        variable_font = g_settings_get_string (
 
1339
                                display->priv->settings,
 
1340
                                "variable-width-font");
 
1341
 
 
1342
        *monospace = monospace_font ? pango_font_description_from_string (monospace_font) : NULL;
 
1343
        *variable = variable_font ? pango_font_description_from_string (variable_font) : NULL;
 
1344
 
 
1345
        if (monospace_font)
 
1346
                g_free (monospace_font);
 
1347
        if (variable_font)
 
1348
                g_free (variable_font);
343
1349
}
344
1350
 
345
1351
static void
346
1352
e_mail_display_class_init (EMailDisplayClass *class)
347
1353
{
348
1354
        GObjectClass *object_class;
 
1355
        EWebViewClass *web_view_class;
349
1356
        GtkWidgetClass *widget_class;
350
 
        EWebViewClass *web_view_class;
351
 
        GtkHTMLClass *html_class;
352
1357
 
353
1358
        g_type_class_add_private (class, sizeof (EMailDisplayPrivate));
354
1359
 
357
1362
        object_class->get_property = mail_display_get_property;
358
1363
        object_class->dispose = mail_display_dispose;
359
1364
 
 
1365
        web_view_class = E_WEB_VIEW_CLASS (class);
 
1366
        web_view_class->set_fonts = mail_display_set_fonts;
 
1367
        web_view_class->update_actions = mail_display_update_actions;
 
1368
 
360
1369
        widget_class = GTK_WIDGET_CLASS (class);
361
1370
        widget_class->realize = mail_display_realize;
362
1371
        widget_class->style_set = mail_display_style_set;
363
1372
 
364
 
        web_view_class = E_WEB_VIEW_CLASS (class);
365
 
        web_view_class->load_string = mail_display_load_string;
366
 
        web_view_class->process_mailto = mail_display_process_mailto;
367
 
 
368
 
        html_class = GTK_HTML_CLASS (class);
369
 
        html_class->url_requested = mail_display_url_requested;
370
 
        html_class->link_clicked = mail_display_link_clicked;
371
 
 
372
 
        g_object_class_install_property (
373
 
                object_class,
374
 
                PROP_FORMATTER,
375
 
                g_param_spec_object (
376
 
                        "formatter",
377
 
                        "HTML Formatter",
378
 
                        NULL,
379
 
                        EM_TYPE_FORMAT_HTML,
 
1373
        g_object_class_install_property (
 
1374
                object_class,
 
1375
                PROP_PART_LIST,
 
1376
                g_param_spec_pointer (
 
1377
                        "part-list",
 
1378
                        "Part List",
 
1379
                        NULL,
 
1380
                        G_PARAM_READWRITE));
 
1381
 
 
1382
        g_object_class_install_property (
 
1383
                object_class,
 
1384
                PROP_MODE,
 
1385
                g_param_spec_int (
 
1386
                        "mode",
 
1387
                        "Display Mode",
 
1388
                        NULL,
 
1389
                        E_MAIL_FORMATTER_MODE_INVALID,
 
1390
                        G_MAXINT,
 
1391
                        E_MAIL_FORMATTER_MODE_NORMAL,
 
1392
                        G_PARAM_READWRITE));
 
1393
 
 
1394
        g_object_class_install_property (
 
1395
                object_class,
 
1396
                PROP_HEADERS_COLLAPSABLE,
 
1397
                g_param_spec_boolean (
 
1398
                        "headers-collapsable",
 
1399
                        "Headers Collapsable",
 
1400
                        NULL,
 
1401
                        FALSE,
 
1402
                        G_PARAM_READWRITE));
 
1403
 
 
1404
        g_object_class_install_property (
 
1405
                object_class,
 
1406
                PROP_HEADERS_COLLAPSED,
 
1407
                g_param_spec_boolean (
 
1408
                        "headers-collapsed",
 
1409
                        "Headers Collapsed",
 
1410
                        NULL,
 
1411
                        FALSE,
380
1412
                        G_PARAM_READWRITE));
381
1413
}
382
1414
 
383
1415
static void
384
1416
e_mail_display_init (EMailDisplay *display)
385
1417
{
386
 
        EWebView *web_view;
387
1418
        GtkUIManager *ui_manager;
388
 
        GtkActionGroup *action_group;
389
 
        GError *error = NULL;
390
 
 
391
 
        web_view = E_WEB_VIEW (display);
 
1419
        const gchar *user_cache_dir;
 
1420
        WebKitWebSettings *settings;
 
1421
        WebKitWebFrame *main_frame;
 
1422
        GtkActionGroup *actions;
392
1423
 
393
1424
        display->priv = E_MAIL_DISPLAY_GET_PRIVATE (display);
394
1425
 
395
 
        /* EWebView's action groups are added during its instance
396
 
         * initialization function (like what we're in now), so it
397
 
         * is safe to fetch them this early in construction. */
398
 
        action_group = e_web_view_get_action_group (web_view, "mailto");
399
 
 
400
 
        /* We don't actually handle the actions we're adding.
401
 
         * EMailReader handles them.  How devious is that? */
402
 
        gtk_action_group_add_actions (
403
 
                action_group, mailto_entries,
404
 
                G_N_ELEMENTS (mailto_entries), display);
405
 
 
406
 
        /* Because we are loading from a hard-coded string, there is
407
 
         * no chance of I/O errors.  Failure here implies a malformed
408
 
         * UI definition.  Full stop. */
409
 
        ui_manager = e_web_view_get_ui_manager (web_view);
410
 
        gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error);
411
 
        if (error != NULL)
412
 
                g_error ("%s", error->message);
413
 
}
414
 
 
415
 
EMFormatHTML *
416
 
e_mail_display_get_formatter (EMailDisplay *display)
417
 
{
418
 
        g_return_val_if_fail (E_IS_MAIL_DISPLAY (display), NULL);
419
 
 
420
 
        return display->priv->formatter;
421
 
}
422
 
 
423
 
void
424
 
e_mail_display_set_formatter (EMailDisplay *display,
425
 
                              EMFormatHTML *formatter)
426
 
{
427
 
        g_return_if_fail (E_IS_MAIL_DISPLAY (display));
428
 
        g_return_if_fail (EM_IS_FORMAT_HTML (formatter));
429
 
 
430
 
        if (display->priv->formatter != NULL)
431
 
                g_object_unref (display->priv->formatter);
432
 
 
433
 
        display->priv->formatter = g_object_ref (formatter);
434
 
 
435
 
        g_object_notify (G_OBJECT (display), "formatter");
 
1426
        /* Set invalid mode so that MODE property initialization is run
 
1427
         * completely (see e_mail_display_set_mode) */
 
1428
        display->priv->mode = E_MAIL_FORMATTER_MODE_INVALID;
 
1429
        e_mail_display_set_mode (display, E_MAIL_FORMATTER_MODE_NORMAL);
 
1430
        display->priv->force_image_load = FALSE;
 
1431
 
 
1432
        webkit_web_view_set_full_content_zoom (WEBKIT_WEB_VIEW (display), TRUE);
 
1433
 
 
1434
        settings = webkit_web_view_get_settings (WEBKIT_WEB_VIEW (display));
 
1435
        g_object_set (settings, "enable-frame-flattening", TRUE, NULL);
 
1436
 
 
1437
        g_signal_connect (display, "navigation-policy-decision-requested",
 
1438
                          G_CALLBACK (mail_display_link_clicked), NULL);
 
1439
        g_signal_connect (display, "resource-request-starting",
 
1440
                          G_CALLBACK (mail_display_resource_requested), NULL);
 
1441
        g_signal_connect (display, "process-mailto",
 
1442
                          G_CALLBACK (mail_display_process_mailto), NULL);
 
1443
        g_signal_connect (display, "create-plugin-widget",
 
1444
                          G_CALLBACK (mail_display_plugin_widget_requested), NULL);
 
1445
        g_signal_connect (display, "frame-created",
 
1446
                          G_CALLBACK (mail_display_frame_created), NULL);
 
1447
        g_signal_connect (display, "notify::uri",
 
1448
                          G_CALLBACK (mail_display_uri_changed), NULL);
 
1449
 
 
1450
        display->priv->settings = g_settings_new ("org.gnome.evolution.mail");
 
1451
        g_signal_connect_swapped (
 
1452
                display->priv->settings , "changed::monospace-font",
 
1453
                G_CALLBACK (e_web_view_update_fonts), display);
 
1454
        g_signal_connect_swapped (
 
1455
                display->priv->settings , "changed::variable-width-font",
 
1456
                G_CALLBACK (e_web_view_update_fonts), display);
 
1457
        g_signal_connect_swapped (
 
1458
                display->priv->settings , "changed::use-custom-font",
 
1459
                G_CALLBACK (e_web_view_update_fonts), display);
 
1460
 
 
1461
        e_web_view_update_fonts (E_WEB_VIEW (display));
 
1462
 
 
1463
        main_frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (display));
 
1464
        g_signal_connect (main_frame, "notify::load-status",
 
1465
                G_CALLBACK (setup_DOM_bindings), NULL);
 
1466
        main_frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (display));
 
1467
        g_signal_connect (main_frame, "notify::load-status",
 
1468
                          G_CALLBACK (mail_parts_bind_dom), NULL);
 
1469
 
 
1470
        actions = e_web_view_get_action_group (E_WEB_VIEW (display), "mailto");
 
1471
        gtk_action_group_add_actions (
 
1472
                actions, mailto_entries, G_N_ELEMENTS (mailto_entries), display);
 
1473
        ui_manager = e_web_view_get_ui_manager (E_WEB_VIEW (display));
 
1474
        gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, NULL);
 
1475
 
 
1476
        actions = e_web_view_get_action_group (E_WEB_VIEW (display), "image");
 
1477
        gtk_action_group_add_actions (
 
1478
                actions, image_entries, G_N_ELEMENTS (image_entries), display);
 
1479
        gtk_ui_manager_add_ui_from_string (ui_manager, image_ui, -1, NULL);
 
1480
 
 
1481
        e_web_view_install_request_handler (E_WEB_VIEW (display), E_TYPE_MAIL_REQUEST);
 
1482
        e_web_view_install_request_handler (E_WEB_VIEW (display), E_TYPE_HTTP_REQUEST);
 
1483
        e_web_view_install_request_handler (E_WEB_VIEW (display), E_TYPE_FILE_REQUEST);
 
1484
        e_web_view_install_request_handler (E_WEB_VIEW (display), E_TYPE_STOCK_REQUEST);
 
1485
 
 
1486
        /* cache expiry - 2 hour access, 1 day max */
 
1487
        user_cache_dir = e_get_user_cache_dir ();
 
1488
        emd_global_http_cache = camel_data_cache_new (user_cache_dir, NULL);
 
1489
        if (emd_global_http_cache) {
 
1490
                camel_data_cache_set_expire_age (emd_global_http_cache, 24 * 60 * 60);
 
1491
                camel_data_cache_set_expire_access (emd_global_http_cache, 2 * 60 * 60);
 
1492
        }
 
1493
}
 
1494
 
 
1495
EMailFormatterMode
 
1496
e_mail_display_get_mode (EMailDisplay *display)
 
1497
{
 
1498
        g_return_val_if_fail (E_IS_MAIL_DISPLAY (display),
 
1499
                        E_MAIL_FORMATTER_MODE_NORMAL);
 
1500
 
 
1501
        return display->priv->mode;
 
1502
}
 
1503
 
 
1504
static gboolean
 
1505
reload_display (EMailDisplay *display)
 
1506
{
 
1507
        e_mail_display_reload (display);
 
1508
        return FALSE;
 
1509
}
 
1510
 
 
1511
static void
 
1512
schedule_display_reload (EMailDisplay *display)
 
1513
{
 
1514
        if (display->priv->reload_scheduled)
 
1515
                return;
 
1516
 
 
1517
        g_idle_add ((GSourceFunc) reload_display, display);
 
1518
        display->priv->reload_scheduled = TRUE;
 
1519
}
 
1520
 
 
1521
void
 
1522
e_mail_display_set_mode (EMailDisplay *display,
 
1523
                         EMailFormatterMode mode)
 
1524
{
 
1525
        EMailFormatter *formatter;
 
1526
        g_return_if_fail (E_IS_MAIL_DISPLAY (display));
 
1527
 
 
1528
        if (display->priv->mode == mode)
 
1529
                return;
 
1530
 
 
1531
        display->priv->mode = mode;
 
1532
 
 
1533
        if (display->priv->mode == E_MAIL_FORMATTER_MODE_PRINTING) {
 
1534
                formatter = e_mail_formatter_print_new ();
 
1535
        } else {
 
1536
                formatter = e_mail_formatter_new ();
 
1537
        }
 
1538
 
 
1539
        g_clear_object (&display->priv->formatter);
 
1540
        display->priv->formatter = formatter;
 
1541
        mail_display_update_formatter_colors (display);
 
1542
 
 
1543
        g_signal_connect (formatter, "notify::image-loading-policy",
 
1544
                G_CALLBACK (formatter_image_loading_policy_changed_cb), display);
 
1545
 
 
1546
        g_object_connect (formatter,
 
1547
                "swapped-signal::notify::charset",
 
1548
                        G_CALLBACK (schedule_display_reload), display,
 
1549
                "swapped-signal::notify::image-loading-policy",
 
1550
                        G_CALLBACK (schedule_display_reload), display,
 
1551
                "swapped-signal::notify::mark-citations",
 
1552
                        G_CALLBACK (schedule_display_reload), display,
 
1553
                "swapped-signal::notify::only-local-photos",
 
1554
                        G_CALLBACK (schedule_display_reload), display,
 
1555
                "swapped-signal::notify::show-sender-photo",
 
1556
                        G_CALLBACK (schedule_display_reload), display,
 
1557
                "swapped-signal::notify::show-real-date",
 
1558
                        G_CALLBACK (schedule_display_reload), display,
 
1559
                "swapped-signal::notify::animate-images",
 
1560
                        G_CALLBACK (schedule_display_reload), display,
 
1561
                "swapped-signal::notify::text-color",
 
1562
                        G_CALLBACK (schedule_display_reload), display,
 
1563
                "swapped-signal::notify::body-color",
 
1564
                        G_CALLBACK (schedule_display_reload), display,
 
1565
                "swapped-signal::notify::citation-color",
 
1566
                        G_CALLBACK (schedule_display_reload), display,
 
1567
                "swapped-signal::notify::content-color",
 
1568
                        G_CALLBACK (schedule_display_reload), display,
 
1569
                "swapped-signal::notify::frame-color",
 
1570
                        G_CALLBACK (schedule_display_reload), display,
 
1571
                "swapped-signal::notify::header-color",
 
1572
                        G_CALLBACK (schedule_display_reload), display,
 
1573
                "swapped-signal::need-redraw",
 
1574
                        G_CALLBACK (schedule_display_reload), display,
 
1575
                NULL);
 
1576
 
 
1577
        e_mail_display_reload (display);
 
1578
 
 
1579
        g_object_notify (G_OBJECT (display), "mode");
 
1580
}
 
1581
 
 
1582
EMailPartList *
 
1583
e_mail_display_get_parts_list (EMailDisplay *display)
 
1584
{
 
1585
        g_return_val_if_fail (E_IS_MAIL_DISPLAY (display), NULL);
 
1586
 
 
1587
        return display->priv->part_list;
 
1588
}
 
1589
 
 
1590
void
 
1591
e_mail_display_set_parts_list (EMailDisplay *display,
 
1592
                               EMailPartList *part_list)
 
1593
{
 
1594
        g_return_if_fail (E_IS_MAIL_DISPLAY (display));
 
1595
 
 
1596
        if (display->priv->part_list == part_list)
 
1597
                return;
 
1598
 
 
1599
        if (part_list) {
 
1600
                g_return_if_fail (E_IS_MAIL_PART_LIST (part_list));
 
1601
                g_object_ref (part_list);
 
1602
        }
 
1603
 
 
1604
        if (display->priv->part_list)
 
1605
                g_object_unref (display->priv->part_list);
 
1606
 
 
1607
        display->priv->part_list = part_list;
 
1608
 
 
1609
        g_object_notify (G_OBJECT (display), "part-list");
 
1610
}
 
1611
 
 
1612
gboolean
 
1613
e_mail_display_get_headers_collapsable (EMailDisplay *display)
 
1614
{
 
1615
        g_return_val_if_fail (E_IS_MAIL_DISPLAY (display), FALSE);
 
1616
 
 
1617
        return display->priv->headers_collapsable;
 
1618
}
 
1619
 
 
1620
void
 
1621
e_mail_display_set_headers_collapsable (EMailDisplay *display,
 
1622
                                        gboolean collapsable)
 
1623
{
 
1624
        g_return_if_fail (E_IS_MAIL_DISPLAY (display));
 
1625
 
 
1626
        if ((display->priv->headers_collapsable ? 1 : 0) == (collapsable ? 1 : 0))
 
1627
                return;
 
1628
 
 
1629
        display->priv->headers_collapsable = collapsable;
 
1630
        e_mail_display_reload (display);
 
1631
 
 
1632
        g_object_notify (G_OBJECT (display), "headers-collapsable");
 
1633
}
 
1634
 
 
1635
gboolean
 
1636
e_mail_display_get_headers_collapsed (EMailDisplay *display)
 
1637
{
 
1638
        g_return_val_if_fail (E_IS_MAIL_DISPLAY (display), FALSE);
 
1639
 
 
1640
        if (display->priv->headers_collapsable)
 
1641
                return display->priv->headers_collapsed;
 
1642
 
 
1643
        return FALSE;
 
1644
}
 
1645
 
 
1646
void
 
1647
e_mail_display_set_headers_collapsed (EMailDisplay *display,
 
1648
                                      gboolean collapsed)
 
1649
{
 
1650
        g_return_if_fail (E_IS_MAIL_DISPLAY (display));
 
1651
 
 
1652
        if ((display->priv->headers_collapsed ? 1 : 0) == (collapsed ? 1 : 0))
 
1653
                return;
 
1654
 
 
1655
        display->priv->headers_collapsed = collapsed;
 
1656
 
 
1657
        g_object_notify (G_OBJECT (display), "headers-collapsed");
 
1658
}
 
1659
 
 
1660
void
 
1661
e_mail_display_load (EMailDisplay *display,
 
1662
                     const gchar *msg_uri)
 
1663
{
 
1664
        gchar *uri;
 
1665
        EMailPartList *part_list;
 
1666
 
 
1667
        g_return_if_fail (E_IS_MAIL_DISPLAY (display));
 
1668
 
 
1669
        display->priv->force_image_load = FALSE;
 
1670
 
 
1671
        part_list = display->priv->part_list;
 
1672
        if (!part_list) {
 
1673
                e_web_view_clear (E_WEB_VIEW (display));
 
1674
                return;
 
1675
        }
 
1676
 
 
1677
        uri = e_mail_part_build_uri (
 
1678
                part_list->folder, part_list->message_uid,
 
1679
                "mode", G_TYPE_INT, display->priv->mode,
 
1680
                "headers_collapsable", G_TYPE_BOOLEAN, display->priv->headers_collapsable,
 
1681
                "headers_collapsed", G_TYPE_BOOLEAN, display->priv->headers_collapsed,
 
1682
                NULL);
 
1683
 
 
1684
        e_web_view_load_uri (E_WEB_VIEW (display), uri);
 
1685
 
 
1686
        g_free (uri);
 
1687
}
 
1688
 
 
1689
void
 
1690
e_mail_display_reload (EMailDisplay *display)
 
1691
{
 
1692
        EWebView *web_view;
 
1693
        const gchar *uri;
 
1694
        gchar *base;
 
1695
        GString *new_uri;
 
1696
        GHashTable *table;
 
1697
        GHashTableIter table_iter;
 
1698
        gpointer key, val;
 
1699
 
 
1700
        g_return_if_fail (E_IS_MAIL_DISPLAY (display));
 
1701
 
 
1702
        web_view = E_WEB_VIEW (display);
 
1703
        uri = e_web_view_get_uri (web_view);
 
1704
 
 
1705
        display->priv->reload_scheduled = FALSE;
 
1706
 
 
1707
        if (!uri || !*uri)
 
1708
                return;
 
1709
 
 
1710
        if (strstr(uri, "?") == NULL) {
 
1711
                e_web_view_reload (web_view);
 
1712
                return;
 
1713
        }
 
1714
 
 
1715
        base = g_strndup (uri, strstr (uri, "?") - uri + 1);
 
1716
        new_uri = g_string_new (base);
 
1717
        g_free (base);
 
1718
 
 
1719
        table = soup_form_decode (strstr (uri, "?") + 1);
 
1720
        g_hash_table_replace (table, g_strdup ("mode"), g_strdup_printf ("%d", display->priv->mode));
 
1721
        g_hash_table_replace (table, g_strdup ("headers_collapsable"), g_strdup_printf ("%d", display->priv->headers_collapsable));
 
1722
        g_hash_table_replace (table, g_strdup ("headers_collapsed"), g_strdup_printf ("%d", display->priv->headers_collapsed));
 
1723
 
 
1724
        g_hash_table_iter_init (&table_iter, table);
 
1725
        while (g_hash_table_iter_next (&table_iter, &key, &val)) {
 
1726
                g_string_append_printf (new_uri, "%s=%s&",
 
1727
                        (gchar *) key, (gchar *) val);
 
1728
 
 
1729
                /* Free the value as Soup constructs the GHashTable without
 
1730
                 * value_destroy_func */
 
1731
                g_free (val);
 
1732
        }
 
1733
 
 
1734
        e_web_view_load_uri (web_view, new_uri->str);
 
1735
 
 
1736
        g_string_free (new_uri, TRUE);
 
1737
        g_hash_table_destroy (table);
 
1738
 
 
1739
}
 
1740
 
 
1741
GtkAction *
 
1742
e_mail_display_get_action (EMailDisplay *display,
 
1743
                           const gchar *action_name)
 
1744
{
 
1745
        GtkAction *action;
 
1746
 
 
1747
        g_return_val_if_fail (E_IS_MAIL_DISPLAY (display), NULL);
 
1748
        g_return_val_if_fail (action_name != NULL, NULL);
 
1749
 
 
1750
        action = e_web_view_get_action (E_WEB_VIEW (display), action_name);
 
1751
 
 
1752
        return action;
 
1753
}
 
1754
 
 
1755
void
 
1756
e_mail_display_set_status (EMailDisplay *display,
 
1757
                           const gchar *status)
 
1758
{
 
1759
        gchar *str;
 
1760
 
 
1761
        g_return_if_fail (E_IS_MAIL_DISPLAY (display));
 
1762
 
 
1763
        str = g_strdup_printf (
 
1764
                "<!DOCTYPE>"
 
1765
                "<html>"
 
1766
                  "<head><title>Evolution Mail Display</title></head>"
 
1767
                  "<body>"
 
1768
                    "<table border=\"0\" width=\"100%%\" height=\"100%%\">"
 
1769
                      "<tr height=\"100%%\" valign=\"middle\">"
 
1770
                        "<td width=\"100%%\" align=\"center\">"
 
1771
                          "<strong>%s</strong>"
 
1772
                        "</td>"
 
1773
                      "</tr>"
 
1774
                    "</table>"
 
1775
                  "</body>"
 
1776
                "</html>", status);
 
1777
 
 
1778
        e_web_view_load_string (E_WEB_VIEW (display), str);
 
1779
        g_free (str);
 
1780
 
 
1781
        gtk_widget_show_all (GTK_WIDGET (display));
 
1782
}
 
1783
 
 
1784
gchar *
 
1785
e_mail_display_get_selection_plain_text (EMailDisplay *display,
 
1786
                                         gint *len)
 
1787
{
 
1788
        EWebView *web_view;
 
1789
        WebKitWebFrame *frame;
 
1790
        const gchar *frame_name;
 
1791
        GValue value = {0};
 
1792
        GType type;
 
1793
        const gchar *str;
 
1794
 
 
1795
        g_return_val_if_fail (E_IS_MAIL_DISPLAY (display), NULL);
 
1796
 
 
1797
        web_view = E_WEB_VIEW (display);
 
1798
        frame = webkit_web_view_get_focused_frame (WEBKIT_WEB_VIEW (web_view));
 
1799
        frame_name = webkit_web_frame_get_name (frame);
 
1800
 
 
1801
        type = e_web_view_frame_exec_script (web_view, frame_name, "window.getSelection().toString()", &value);
 
1802
        g_return_val_if_fail (type == G_TYPE_STRING, NULL);
 
1803
 
 
1804
        str = g_value_get_string (&value);
 
1805
 
 
1806
        if (len)
 
1807
                *len = strlen (str);
 
1808
 
 
1809
        return g_strdup (str);
 
1810
}
 
1811
 
 
1812
void
 
1813
e_mail_display_load_images (EMailDisplay *display)
 
1814
{
 
1815
        g_return_if_fail (E_IS_MAIL_DISPLAY (display));
 
1816
 
 
1817
        display->priv->force_image_load = TRUE;
 
1818
        e_web_view_reload (E_WEB_VIEW (display));
 
1819
}
 
1820
 
 
1821
void
 
1822
e_mail_display_set_force_load_images (EMailDisplay *display,
 
1823
                                      gboolean force_load_images)
 
1824
{
 
1825
        g_return_if_fail (E_IS_MAIL_DISPLAY (display));
 
1826
 
 
1827
        display->priv->force_image_load = force_load_images;
436
1828
}