From 4a090c7aa0e2db13c93f4c04575dd18b0e5bcbfd Mon Sep 17 00:00:00 2001 From: Jose Dapena Paz Date: Wed, 10 Oct 2007 12:44:19 +0000 Subject: [PATCH] * src/modest-marshal.list: * Added two marshallers. * src/modest-tny-platform-factory.c: * Added a proper implementation of get_msg_view. * src/modest-msg-view.[ch]: * Removed all references to gtkhtml library, as now we use the new ModestGtkhtmlMimePartView. This hides all gtkhtml inners in modest/tny api. * Implemented ModestZoomable interface, and removed old api so now you have to use ModestZoomable api always. * Adapted the signal handlers to use the ModestMimePartView signals instead of gtkhtml signals. * Now ModestMsgView implement TnyMsg and TnyMimePart interfaces. Removed old methods to get/set messages, as now we use Tny api. * Reestructured a bit the code, to separate the interfaces implementations from the implementation itself. * Now we properly find the embedded attachments, if they're stored in a multipart/related. * Added src/modest-isearch-view.[ch]: * Incremental search view interface. This new interface exposes a view where incremental search is available (writing a string and beginning to search this string the times required to find it). * Added src/modest-mime-part-view.[ch]: * New interface, child of TnyMimePartView. This interface adds method is_empty and signals "activate_uri", "link_hover" and "fetch_url" to TnyMimePartView. This is for implementing the specific backend for gtkhtml (included in this commit) and a future one using GtkMozembed. * Added src/modest-zoomable.[ch]: * This new interface should be implemented by all widgets supporting any kind of zoom. In particular, this is implemented in the new ModestGtkhtmlMimePartView and in ModestMsgView. In the future ModestWindow children should implement this. * Added src/modest-gtkhtml-mime-part-view.[ch]: * This is an implementation of ModestMimePartView interface, ModestISearchView interface, and ModestZoomable interface. It uses gtkhtml as backend, and is, in fact, the place where all the gtkhtml code that was present in ModestMsgView has gone. * src/maemo/modest-msg-view-window.c: * Use TnyMsg and ModestZoomable api to access ModestMsgView. pmo-trunk-r3481 --- src/maemo/modest-msg-view-window.c | 18 +- src/modest-marshal.list | 2 + src/modest-tny-platform-factory.c | 5 +- src/widgets/Makefile.am | 10 +- src/widgets/modest-gtkhtml-mime-part-view.c | 662 +++++++++++++++++++++++++++ src/widgets/modest-gtkhtml-mime-part-view.h | 103 +++++ src/widgets/modest-isearch-view.c | 121 +++++ src/widgets/modest-isearch-view.h | 64 +++ src/widgets/modest-mime-part-view.c | 155 +++++++ src/widgets/modest-mime-part-view.h | 66 +++ src/widgets/modest-msg-view.c | 650 ++++++++++++++++---------- src/widgets/modest-msg-view.h | 42 +- src/widgets/modest-zoomable.c | 130 ++++++ src/widgets/modest-zoomable.h | 67 +++ 14 files changed, 1824 insertions(+), 271 deletions(-) create mode 100644 src/widgets/modest-gtkhtml-mime-part-view.c create mode 100644 src/widgets/modest-gtkhtml-mime-part-view.h create mode 100644 src/widgets/modest-isearch-view.c create mode 100644 src/widgets/modest-isearch-view.h create mode 100644 src/widgets/modest-mime-part-view.c create mode 100644 src/widgets/modest-mime-part-view.h create mode 100644 src/widgets/modest-zoomable.c create mode 100644 src/widgets/modest-zoomable.h diff --git a/src/maemo/modest-msg-view-window.c b/src/maemo/modest-msg-view-window.c index 904a218..5d14535 100644 --- a/src/maemo/modest-msg-view-window.c +++ b/src/maemo/modest-msg-view-window.c @@ -1196,7 +1196,7 @@ modest_msg_view_window_get_message (ModestMsgViewWindow *self) msg_view = MODEST_MSG_VIEW (priv->msg_view); - return modest_msg_view_get_message (msg_view); + return tny_msg_view_get_msg (TNY_MSG_VIEW (priv->msg_view)); } const gchar* @@ -1310,7 +1310,7 @@ modest_msg_view_window_set_zoom (ModestWindow *window, priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window); parent_priv = MODEST_WINDOW_GET_PRIVATE (window); - modest_msg_view_set_zoom (MODEST_MSG_VIEW (priv->msg_view), zoom); + modest_zoomable_set_zoom (MODEST_ZOOMABLE (priv->msg_view), zoom); action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"); @@ -1326,7 +1326,7 @@ modest_msg_view_window_get_zoom (ModestWindow *window) g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), 1.0); priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window); - return modest_msg_view_get_zoom (MODEST_MSG_VIEW (priv->msg_view)); + return modest_zoomable_get_zoom (MODEST_ZOOMABLE (priv->msg_view)); } static gboolean @@ -1788,7 +1788,7 @@ view_msg_cb (ModestMailOperation *mail_op, tny_header_set_flags (header, TNY_HEADER_FLAG_SEEN); /* Set new message */ - modest_msg_view_set_message (MODEST_MSG_VIEW (priv->msg_view), msg); + tny_msg_view_set_msg (TNY_MSG_VIEW (priv->msg_view), msg); modest_msg_view_window_update_priority (self); update_window_title (MODEST_MSG_VIEW_WINDOW (self)); modest_msg_view_grab_focus (MODEST_MSG_VIEW (priv->msg_view)); @@ -1818,7 +1818,7 @@ modest_msg_view_window_get_folder_type (ModestMsgViewWindow *window) folder_type = TNY_FOLDER_TYPE_UNKNOWN; - msg = modest_msg_view_get_message (MODEST_MSG_VIEW (priv->msg_view)); + msg = tny_msg_view_get_msg (TNY_MSG_VIEW (priv->msg_view)); if (msg) { TnyFolder *folder; @@ -2569,10 +2569,10 @@ modest_msg_view_window_remove_attachments (ModestMsgViewWindow *window, gboolean /* modest_msg_view_remove_attachment (MODEST_MSG_VIEW (priv->msg_view), node->data); */ } - msg = modest_msg_view_get_message (MODEST_MSG_VIEW (priv->msg_view)); - modest_msg_view_set_message (MODEST_MSG_VIEW (priv->msg_view), NULL); + msg = tny_msg_view_get_msg (TNY_MSG_VIEW (priv->msg_view)); + tny_msg_view_clear (TNY_MSG_VIEW (priv->msg_view)); tny_msg_rewrite_cache (msg); - modest_msg_view_set_message (MODEST_MSG_VIEW (priv->msg_view), msg); + tny_msg_view_set_msg (TNY_MSG_VIEW (priv->msg_view), msg); g_list_foreach (mime_parts, (GFunc) g_object_unref, NULL); g_list_free (mime_parts); @@ -2600,7 +2600,7 @@ update_window_title (ModestMsgViewWindow *window) TnyHeader *header = NULL; const gchar *subject = NULL; - msg = modest_msg_view_get_message (MODEST_MSG_VIEW (priv->msg_view)); + msg = tny_msg_view_get_msg (TNY_MSG_VIEW (priv->msg_view)); if (msg != NULL) { header = tny_msg_get_header (msg); subject = tny_header_get_subject (header); diff --git a/src/modest-marshal.list b/src/modest-marshal.list index 38e7b11..1d5587e 100644 --- a/src/modest-marshal.list +++ b/src/modest-marshal.list @@ -8,3 +8,5 @@ VOID:STRING,INT,INT VOID:STRING,BOOL VOID:STRING,POINTER,BOOL VOID:POINTER,INT +BOOL:STRING +BOOL:STRING,OBJECT diff --git a/src/modest-tny-platform-factory.c b/src/modest-tny-platform-factory.c index dad5e4b..e6a3870 100644 --- a/src/modest-tny-platform-factory.c +++ b/src/modest-tny-platform-factory.c @@ -39,6 +39,7 @@ #include "modest-tny-platform-factory.h" #include "modest-tny-account-store.h" +#include /* 'private'/'protected' functions */ static void modest_tny_platform_factory_class_init (ModestTnyPlatformFactoryClass *klass); @@ -188,8 +189,8 @@ modest_tny_platform_factory_new_device (TnyPlatformFactory *self) static TnyMsgView* modest_tny_platform_factory_new_msg_view (TnyPlatformFactory *self) { - /* TODO */ - return NULL; + /* Here we'll select one of the implementations available */ + return g_object_new (MODEST_TYPE_MSG_VIEW, NULL); } static TnyMsg* diff --git a/src/widgets/Makefile.am b/src/widgets/Makefile.am index 84ea7cd..351295f 100644 --- a/src/widgets/Makefile.am +++ b/src/widgets/Makefile.am @@ -31,6 +31,8 @@ libmodest_widgets_la_SOURCES= \ modest-folder-view.h \ modest-global-settings-dialog.c \ modest-global-settings-dialog.h \ + modest-gtkhtml-mime-part-view.c \ + modest-gtkhtml-mime-part-view.h \ modest-hbox-cell-renderer.c \ modest-hbox-cell-renderer.h \ modest-vbox-cell-renderer.c \ @@ -40,11 +42,15 @@ libmodest_widgets_la_SOURCES= \ modest-header-view-render.c \ modest-header-view.c \ modest-header-view.h \ + modest-isearch-view.c \ + modest-isearch-view.h \ modest-limit-retrieve-combo-box.h \ modest-limit-retrieve-combo-box.c \ modest-mail-header-view.c \ modest-mail-header-view.h \ modest-main-window.h \ + modest-mime-part-view.c \ + modest-mime-part-view.h \ modest-msg-edit-window-ui.h \ modest-msg-edit-window.h \ modest-msg-view-window.h \ @@ -69,7 +75,9 @@ libmodest_widgets_la_SOURCES= \ modest-window.c \ modest-window.h \ modest-window-mgr.h \ - modest-window-mgr.c + modest-window-mgr.c \ + modest-zoomable.h \ + modest-zoomable.c LDADD = \ $(MODEST_GSTUFF_LIBS) \ diff --git a/src/widgets/modest-gtkhtml-mime-part-view.c b/src/widgets/modest-gtkhtml-mime-part-view.c new file mode 100644 index 0000000..f167c9a --- /dev/null +++ b/src/widgets/modest-gtkhtml-mime-part-view.c @@ -0,0 +1,662 @@ +/* Copyright (c) 2006, 2007, Nokia Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Nokia Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* gobject structure methods */ +static void modest_gtkhtml_mime_part_view_class_init (ModestGtkhtmlMimePartViewClass *klass); +static void tny_mime_part_view_init (gpointer g, gpointer iface_data); +static void modest_mime_part_view_init (gpointer g, gpointer iface_data); +static void modest_zoomable_init (gpointer g, gpointer iface_data); +static void modest_isearch_view_init (gpointer g, gpointer iface_data); +static void modest_gtkhtml_mime_part_view_init (ModestGtkhtmlMimePartView *self); +static void modest_gtkhtml_mime_part_view_finalize (GObject *self); + +/* GtkHTML signal handlers */ +static gboolean on_link_clicked (GtkWidget *widget, const gchar *uri, ModestGtkhtmlMimePartView *self); +static gboolean on_url (GtkWidget *widget, const gchar *uri, ModestGtkhtmlMimePartView *self); +static gboolean on_url_requested (GtkWidget *widget, const gchar *uri, GtkHTMLStream *stream, + ModestGtkhtmlMimePartView *self); +/* TnyMimePartView implementation */ +static void modest_gtkhtml_mime_part_view_clear (TnyMimePartView *self); +static void modest_gtkhtml_mime_part_view_clear_default (TnyMimePartView *self); +static void modest_gtkhtml_mime_part_view_set_part (TnyMimePartView *self, TnyMimePart *part); +static void modest_gtkhtml_mime_part_view_set_part_default (TnyMimePartView *self, TnyMimePart *part); +static TnyMimePart* modest_gtkhtml_mime_part_view_get_part (TnyMimePartView *self); +static TnyMimePart* modest_gtkhtml_mime_part_view_get_part_default (TnyMimePartView *self); +/* ModestMimePartView implementation */ +static gboolean modest_gtkhtml_mime_part_view_is_empty (ModestMimePartView *self); +static gboolean modest_gtkhtml_mime_part_view_is_empty_default (ModestMimePartView *self); +/* ModestZoomable implementation */ +static gdouble modest_gtkhtml_mime_part_view_get_zoom (ModestZoomable *self); +static void modest_gtkhtml_mime_part_view_set_zoom (ModestZoomable *self, gdouble value); +static gboolean modest_gtkhtml_mime_part_view_zoom_minus (ModestZoomable *self); +static gboolean modest_gtkhtml_mime_part_view_zoom_plus (ModestZoomable *self); +static gdouble modest_gtkhtml_mime_part_view_get_zoom_default (ModestZoomable *self); +static void modest_gtkhtml_mime_part_view_set_zoom_default (ModestZoomable *self, gdouble value); +static gboolean modest_gtkhtml_mime_part_view_zoom_minus_default (ModestZoomable *self); +static gboolean modest_gtkhtml_mime_part_view_zoom_plus_default (ModestZoomable *self); +/* ModestISearchView implementation */ +static gboolean modest_gtkhtml_mime_part_view_search (ModestISearchView *self, const gchar *string); +static gboolean modest_gtkhtml_mime_part_view_search_next (ModestISearchView *self); +static gboolean modest_gtkhtml_mime_part_view_get_selection_area (ModestISearchView *self, gint *x, gint *y, + gint *width, gint *height); +static gboolean modest_gtkhtml_mime_part_view_search_default (ModestISearchView *self, const gchar *string); +static gboolean modest_gtkhtml_mime_part_view_search_next_default (ModestISearchView *self); +static gboolean modest_gtkhtml_mime_part_view_get_selection_area_default (ModestISearchView *self, gint *x, gint *y, + gint *width, gint *height); + + +/* internal api */ +static TnyMimePart *get_part (ModestGtkhtmlMimePartView *self); +static void set_html_part (ModestGtkhtmlMimePartView *self, TnyMimePart *part); +static void set_text_part (ModestGtkhtmlMimePartView *self, TnyMimePart *part); +static void set_empty_part (ModestGtkhtmlMimePartView *self); +static void set_part (ModestGtkhtmlMimePartView *self, TnyMimePart *part); +static gboolean is_empty (ModestGtkhtmlMimePartView *self); +static void set_zoom (ModestGtkhtmlMimePartView *self, gdouble zoom); +static gdouble get_zoom (ModestGtkhtmlMimePartView *self); +static gboolean has_contents_receiver (gpointer engine, const gchar *data, + size_t len, gboolean *has_contents); +static gboolean search (ModestGtkhtmlMimePartView *self, const gchar *string); +static gboolean search_next (ModestGtkhtmlMimePartView *self); +static gboolean get_selection_area (ModestGtkhtmlMimePartView *self, gint *x, gint *y, + gint *width, gint *height); + +typedef struct _ModestGtkhtmlMimePartViewPrivate ModestGtkhtmlMimePartViewPrivate; +struct _ModestGtkhtmlMimePartViewPrivate { + TnyMimePart *part; + gdouble current_zoom; +}; + +#define MODEST_GTKHTML_MIME_PART_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ + MODEST_TYPE_GTKHTML_MIME_PART_VIEW, \ + ModestGtkhtmlMimePartViewPrivate)) + +static GtkHTMLClass *parent_class = NULL; + +GtkWidget * +modest_gtkhtml_mime_part_view_new () +{ + return g_object_new (MODEST_TYPE_GTKHTML_MIME_PART_VIEW, NULL); +} + +/* GOBJECT IMPLEMENTATION */ +GType +modest_gtkhtml_mime_part_view_get_type (void) +{ + static GType my_type = 0; + if (!my_type) { + static const GTypeInfo my_info = { + sizeof(ModestGtkhtmlMimePartViewClass), + NULL, /* base init */ + NULL, /* base finalize */ + (GClassInitFunc) modest_gtkhtml_mime_part_view_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof(ModestGtkhtmlMimePartView), + 1, /* n_preallocs */ + (GInstanceInitFunc) modest_gtkhtml_mime_part_view_init, + NULL + }; + + static const GInterfaceInfo tny_mime_part_view_info = + { + (GInterfaceInitFunc) tny_mime_part_view_init, /* interface_init */ + NULL, /* interface_finalize */ + NULL /* interface_data */ + }; + + static const GInterfaceInfo modest_mime_part_view_info = + { + (GInterfaceInitFunc) modest_mime_part_view_init, /* interface_init */ + NULL, /* interface_finalize */ + NULL /* interface_data */ + }; + + static const GInterfaceInfo modest_zoomable_info = + { + (GInterfaceInitFunc) modest_zoomable_init, /* interface_init */ + NULL, /* interface_finalize */ + NULL /* interface_data */ + }; + + static const GInterfaceInfo modest_isearch_view_info = + { + (GInterfaceInitFunc) modest_isearch_view_init, /* interface_init */ + NULL, /* interface_finalize */ + NULL /* interface_data */ + }; + + my_type = g_type_register_static (GTK_TYPE_HTML, + "ModestGtkhtmlMimePartView", + &my_info, 0); + + g_type_add_interface_static (my_type, TNY_TYPE_MIME_PART_VIEW, + &tny_mime_part_view_info); + + g_type_add_interface_static (my_type, MODEST_TYPE_MIME_PART_VIEW, + &modest_mime_part_view_info); + + g_type_add_interface_static (my_type, MODEST_TYPE_ZOOMABLE, + &modest_zoomable_info); + g_type_add_interface_static (my_type, MODEST_TYPE_ISEARCH_VIEW, + &modest_isearch_view_info); + } + return my_type; +} + +static void +modest_gtkhtml_mime_part_view_class_init (ModestGtkhtmlMimePartViewClass *klass) +{ + GObjectClass *gobject_class; + gobject_class = (GObjectClass*) klass; + + parent_class = g_type_class_peek_parent (klass); + gobject_class->finalize = modest_gtkhtml_mime_part_view_finalize; + + klass->get_part_func = modest_gtkhtml_mime_part_view_get_part_default; + klass->set_part_func = modest_gtkhtml_mime_part_view_set_part_default; + klass->clear_func = modest_gtkhtml_mime_part_view_clear_default; + klass->is_empty_func = modest_gtkhtml_mime_part_view_is_empty_default; + klass->get_zoom_func = modest_gtkhtml_mime_part_view_get_zoom_default; + klass->set_zoom_func = modest_gtkhtml_mime_part_view_set_zoom_default; + klass->zoom_minus_func = modest_gtkhtml_mime_part_view_zoom_minus_default; + klass->zoom_plus_func = modest_gtkhtml_mime_part_view_zoom_plus_default; + klass->search_func = modest_gtkhtml_mime_part_view_search_default; + klass->search_next_func = modest_gtkhtml_mime_part_view_search_next_default; + klass->get_selection_area_func = modest_gtkhtml_mime_part_view_get_selection_area_default; + + g_type_class_add_private (gobject_class, sizeof(ModestGtkhtmlMimePartViewPrivate)); + +} + +static void +modest_gtkhtml_mime_part_view_init (ModestGtkhtmlMimePartView *self) +{ + ModestGtkhtmlMimePartViewPrivate *priv = MODEST_GTKHTML_MIME_PART_VIEW_GET_PRIVATE (self); + + gtk_html_set_editable (GTK_HTML(self), FALSE); + gtk_html_allow_selection (GTK_HTML(self), TRUE); + gtk_html_set_caret_mode (GTK_HTML(self), FALSE); + gtk_html_set_blocking (GTK_HTML(self), FALSE); + gtk_html_set_images_blocking (GTK_HTML(self), FALSE); + + g_signal_connect (G_OBJECT(self), "link_clicked", + G_CALLBACK(on_link_clicked), self); + g_signal_connect (G_OBJECT(self), "url_requested", + G_CALLBACK(on_url_requested), self); + g_signal_connect (G_OBJECT(self), "on_url", + G_CALLBACK(on_url), self); + + priv->part = NULL; + priv->current_zoom = 1.0; +} + +static void +modest_gtkhtml_mime_part_view_finalize (GObject *obj) +{ + G_OBJECT_CLASS (parent_class)->finalize (obj); +} + +/* GTKHTML SIGNALS HANDLERS */ + +static gboolean +on_link_clicked (GtkWidget *widget, const gchar *uri, ModestGtkhtmlMimePartView *self) +{ + gboolean result; + g_return_val_if_fail (MODEST_IS_GTKHTML_MIME_PART_VIEW (self), FALSE); + + g_signal_emit_by_name (G_OBJECT (self), "activate-link", uri, &result); + return result; +} + +static gboolean +on_url (GtkWidget *widget, const gchar *uri, ModestGtkhtmlMimePartView *self) +{ + gboolean result; + g_return_val_if_fail (MODEST_IS_GTKHTML_MIME_PART_VIEW (self), FALSE); + + g_signal_emit_by_name (G_OBJECT (self), "link-hover", uri, &result); + return result; +} + +static gboolean +on_url_requested (GtkWidget *widget, const gchar *uri, GtkHTMLStream *stream, + ModestGtkhtmlMimePartView *self) +{ + gboolean result; + TnyStream *tny_stream; + g_return_val_if_fail (MODEST_IS_GTKHTML_MIME_PART_VIEW (self), FALSE); + + tny_stream = TNY_STREAM (modest_tny_stream_gtkhtml_new (stream)); + g_signal_emit_by_name (MODEST_MIME_PART_VIEW (self), "fetch-url", uri, tny_stream, &result); + gtk_html_stream_close (stream, result?GTK_HTML_STREAM_OK:GTK_HTML_STREAM_ERROR); + g_object_unref (tny_stream); + return result; +} + +/* INTERNAL API */ + +static void +set_html_part (ModestGtkhtmlMimePartView *self, TnyMimePart *part) +{ + GtkHTMLStream *gtkhtml_stream; + TnyStream *tny_stream; + + g_return_if_fail (self); + g_return_if_fail (part); + + gtkhtml_stream = gtk_html_begin(GTK_HTML(self)); + + tny_stream = TNY_STREAM(modest_tny_stream_gtkhtml_new (gtkhtml_stream)); + tny_stream_reset (tny_stream); + + tny_mime_part_decode_to_stream ((TnyMimePart*)part, tny_stream); + g_object_unref (G_OBJECT(tny_stream)); + + gtk_html_stream_destroy (gtkhtml_stream); +} + +static void +set_text_part (ModestGtkhtmlMimePartView *self, TnyMimePart *part) +{ + GtkTextBuffer *buf; + GtkTextIter begin, end; + TnyStream* txt_stream, *tny_stream; + GtkHTMLStream *gtkhtml_stream; + gchar *txt; + + g_return_if_fail (self); + g_return_if_fail (part); + + buf = gtk_text_buffer_new (NULL); + txt_stream = TNY_STREAM(tny_gtk_text_buffer_stream_new (buf)); + + tny_stream_reset (txt_stream); + + gtkhtml_stream = gtk_html_begin(GTK_HTML(self)); + tny_stream = TNY_STREAM(modest_tny_stream_gtkhtml_new (gtkhtml_stream)); + + // FIXME: tinymail + tny_mime_part_decode_to_stream ((TnyMimePart*)part, txt_stream); + tny_stream_reset (txt_stream); + + gtk_text_buffer_get_bounds (buf, &begin, &end); + txt = gtk_text_buffer_get_text (buf, &begin, &end, FALSE); + if (txt) { + gchar *html = modest_text_utils_convert_to_html (txt); + tny_stream_write (tny_stream, html, strlen(html)); + tny_stream_reset (tny_stream); + g_free (txt); + g_free (html); + } + + g_object_unref (G_OBJECT(tny_stream)); + g_object_unref (G_OBJECT(txt_stream)); + g_object_unref (G_OBJECT(buf)); + + gtk_html_stream_destroy (gtkhtml_stream); +} + +static void +set_empty_part (ModestGtkhtmlMimePartView *self) +{ + g_return_if_fail (self); + + gtk_html_load_from_string (GTK_HTML(self), + "", 1); +} + +static void +set_part (ModestGtkhtmlMimePartView *self, TnyMimePart *part) +{ + ModestGtkhtmlMimePartViewPrivate *priv; + + g_return_if_fail (self); + + priv = MODEST_GTKHTML_MIME_PART_VIEW_GET_PRIVATE(self); + + if (part != priv->part) { + if (priv->part) + g_object_unref (G_OBJECT(priv->part)); + if (part) + g_object_ref (G_OBJECT(part)); + priv->part = part; + } + + if (!part) { + set_empty_part (self); + return; + } + + if (tny_mime_part_content_type_is (part, "text/html")) + set_html_part (self, part); + else + set_text_part (self, part); + +} + +static TnyMimePart* +get_part (ModestGtkhtmlMimePartView *self) +{ + TnyMimePart *part; + + g_return_val_if_fail (MODEST_IS_GTKHTML_MIME_PART_VIEW (self), NULL); + + part = MODEST_GTKHTML_MIME_PART_VIEW_GET_PRIVATE(self)->part; + + if (part) + g_object_ref (part); + + return part; +} + +static gboolean +has_contents_receiver (gpointer engine, const gchar *data, + size_t len, gboolean *has_contents) +{ + if (len > 1 || ((len == 1)&&(data[0]!='\n'))) { + *has_contents = TRUE; + return FALSE; + } + return TRUE; +} + +static gboolean +is_empty (ModestGtkhtmlMimePartView *self) +{ + /* TODO: Find some gtkhtml API to check whether there is any (visible, non markup) + * text in the message: + */ + gboolean has_contents = FALSE; + + gtk_html_export (GTK_HTML (self), "text/plain", + (GtkHTMLSaveReceiverFn) has_contents_receiver, &has_contents); + + return !has_contents; +} + +static void +set_zoom (ModestGtkhtmlMimePartView *self, gdouble zoom) +{ + ModestGtkhtmlMimePartViewPrivate *priv; + + g_return_if_fail (MODEST_IS_GTKHTML_MIME_PART_VIEW (self)); + + priv = MODEST_GTKHTML_MIME_PART_VIEW_GET_PRIVATE (self); + priv->current_zoom = zoom; + gtk_html_set_magnification (GTK_HTML(self), zoom); + + gtk_widget_queue_resize (GTK_WIDGET (self)); +} + +static gdouble +get_zoom (ModestGtkhtmlMimePartView *self) +{ + ModestGtkhtmlMimePartViewPrivate *priv; + + g_return_val_if_fail (MODEST_IS_GTKHTML_MIME_PART_VIEW (self), 1.0); + + priv = MODEST_GTKHTML_MIME_PART_VIEW_GET_PRIVATE (self); + + return priv->current_zoom; +} + +static gboolean +search (ModestGtkhtmlMimePartView *self, + const gchar *string) +{ + return gtk_html_engine_search (GTK_HTML (self), + string, + FALSE, /* case sensitive */ + TRUE, /* forward */ + FALSE); /* regexp */ +} + +static gboolean +search_next (ModestGtkhtmlMimePartView *self) +{ + return gtk_html_engine_search_next (GTK_HTML (self)); +} + +static gboolean +get_selection_area (ModestGtkhtmlMimePartView *self, + gint *x, gint *y, + gint *width, gint *height) +{ + gtk_html_get_selection_area (GTK_HTML (self), x, y, width, height); + return TRUE; +} + + +/* TNY MIME PART IMPLEMENTATION */ + +static void +tny_mime_part_view_init (gpointer g, gpointer iface_data) +{ + TnyMimePartViewIface *klass = (TnyMimePartViewIface *)g; + + klass->get_part_func = modest_gtkhtml_mime_part_view_get_part; + klass->set_part_func = modest_gtkhtml_mime_part_view_set_part; + klass->clear_func = modest_gtkhtml_mime_part_view_clear; + + return; +} + +static TnyMimePart* +modest_gtkhtml_mime_part_view_get_part (TnyMimePartView *self) +{ + return MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->get_part_func (self); +} + + +static TnyMimePart* +modest_gtkhtml_mime_part_view_get_part_default (TnyMimePartView *self) +{ + return TNY_MIME_PART (get_part (MODEST_GTKHTML_MIME_PART_VIEW (self))); +} + +static void +modest_gtkhtml_mime_part_view_set_part (TnyMimePartView *self, + TnyMimePart *part) +{ + MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->set_part_func (self, part); +} + +static void +modest_gtkhtml_mime_part_view_set_part_default (TnyMimePartView *self, + TnyMimePart *part) +{ + g_return_if_fail ((part == NULL) || TNY_IS_MIME_PART (part)); + + set_part (MODEST_GTKHTML_MIME_PART_VIEW (self), part); +} + +static void +modest_gtkhtml_mime_part_view_clear (TnyMimePartView *self) +{ + MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->clear_func (self); +} + +static void +modest_gtkhtml_mime_part_view_clear_default (TnyMimePartView *self) +{ + set_part (MODEST_GTKHTML_MIME_PART_VIEW (self), NULL); +} + +/* MODEST MIME PART VIEW IMPLEMENTATION */ + +static void +modest_mime_part_view_init (gpointer g, gpointer iface_data) +{ + ModestMimePartViewIface *klass = (ModestMimePartViewIface *)g; + + klass->is_empty_func = modest_gtkhtml_mime_part_view_is_empty; + + return; +} + +static gboolean +modest_gtkhtml_mime_part_view_is_empty (ModestMimePartView *self) +{ + return MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->is_empty_func (self); +} + +static gboolean +modest_gtkhtml_mime_part_view_is_empty_default (ModestMimePartView *self) +{ + return is_empty (MODEST_GTKHTML_MIME_PART_VIEW (self)); +} + + +/* MODEST ZOOMABLE IMPLEMENTATION */ +static void +modest_zoomable_init (gpointer g, gpointer iface_data) +{ + ModestZoomableIface *klass = (ModestZoomableIface *)g; + + klass->get_zoom_func = modest_gtkhtml_mime_part_view_get_zoom; + klass->set_zoom_func = modest_gtkhtml_mime_part_view_set_zoom; + klass->zoom_minus_func = modest_gtkhtml_mime_part_view_zoom_minus; + klass->zoom_plus_func = modest_gtkhtml_mime_part_view_zoom_plus; + + return; +} + +static gdouble +modest_gtkhtml_mime_part_view_get_zoom (ModestZoomable *self) +{ + return MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->get_zoom_func (self); +} + +static gdouble +modest_gtkhtml_mime_part_view_get_zoom_default (ModestZoomable *self) +{ + return get_zoom (MODEST_GTKHTML_MIME_PART_VIEW (self)); +} + +static void +modest_gtkhtml_mime_part_view_set_zoom (ModestZoomable *self, gdouble value) +{ + MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->set_zoom_func (self, value); +} + +static void +modest_gtkhtml_mime_part_view_set_zoom_default (ModestZoomable *self, gdouble value) +{ + set_zoom (MODEST_GTKHTML_MIME_PART_VIEW (self), value); +} + +static gboolean +modest_gtkhtml_mime_part_view_zoom_minus (ModestZoomable *self) +{ + return MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->zoom_minus_func (self); +} + +static gboolean +modest_gtkhtml_mime_part_view_zoom_minus_default (ModestZoomable *self) +{ + /* operation not supported in ModestGtkhtmlMimePartView */ + return FALSE; +} + +static gboolean +modest_gtkhtml_mime_part_view_zoom_plus (ModestZoomable *self) +{ + return MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->zoom_plus_func (self); +} + +static gboolean +modest_gtkhtml_mime_part_view_zoom_plus_default (ModestZoomable *self) +{ + /* operation not supported in ModestGtkhtmlMimePartView */ + return FALSE; +} + +/* ISEARCH VIEW IMPLEMENTATION */ +static void +modest_isearch_view_init (gpointer g, gpointer iface_data) +{ + ModestISearchViewIface *klass = (ModestISearchViewIface *)g; + + klass->search_func = modest_gtkhtml_mime_part_view_search; + klass->search_next_func = modest_gtkhtml_mime_part_view_search_next; + klass->get_selection_area_func = modest_gtkhtml_mime_part_view_get_selection_area; + + return; +} + +static gboolean +modest_gtkhtml_mime_part_view_search (ModestISearchView *self, const gchar *string) +{ + return MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->search_func (self, string); +} + +static gboolean +modest_gtkhtml_mime_part_view_search_default (ModestISearchView *self, const gchar *string) +{ + return search (MODEST_GTKHTML_MIME_PART_VIEW (self), string); +} + +static gboolean +modest_gtkhtml_mime_part_view_search_next(ModestISearchView *self) +{ + return MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->search_next_func (self); +} + +static gboolean +modest_gtkhtml_mime_part_view_search_next_default (ModestISearchView *self) +{ + return search_next (MODEST_GTKHTML_MIME_PART_VIEW (self)); +} + +static gboolean +modest_gtkhtml_mime_part_view_get_selection_area (ModestISearchView *self, gint *x, gint *y, + gint *width, gint *height) +{ + return MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->get_selection_area_func (self, x, y, width, height); +} + +static gboolean +modest_gtkhtml_mime_part_view_get_selection_area_default (ModestISearchView *self, gint *x, gint *y, + gint *width, gint *height) +{ + return get_selection_area (MODEST_GTKHTML_MIME_PART_VIEW (self), x, y, width, height); +} diff --git a/src/widgets/modest-gtkhtml-mime-part-view.h b/src/widgets/modest-gtkhtml-mime-part-view.h new file mode 100644 index 0000000..510f071 --- /dev/null +++ b/src/widgets/modest-gtkhtml-mime-part-view.h @@ -0,0 +1,103 @@ +/* Copyright (c) 2006, 2007, Nokia Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Nokia Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __MODEST_GTKHTML_MIME_PART_VIEW_H__ +#define __MODEST_GTKHTML_MIME_PART_VIEW_H__ + +#include +#include +#include +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +/* convenience macros */ +#define MODEST_TYPE_GTKHTML_MIME_PART_VIEW (modest_gtkhtml_mime_part_view_get_type()) +#define MODEST_GTKHTML_MIME_PART_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),MODEST_TYPE_GTKHTML_MIME_PART_VIEW,ModestGtkhtmlMimePartView)) +#define MODEST_GTKHTML_MIME_PART_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),MODEST_TYPE_GTKHTML_MIME_PART_VIEW,ModestGtkhtmlMimePartViewClass)) +#define MODEST_IS_GTKHTML_MIME_PART_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),MODEST_TYPE_GTKHTML_MIME_PART_VIEW)) +#define MODEST_IS_GTKHTML_MIME_PART_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),MODEST_TYPE_GTKHTML_MIME_PART_VIEW)) +#define MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),MODEST_TYPE_GTKHTML_MIME_PART_VIEW,ModestGtkhtmlMimePartViewClass)) + +typedef struct _ModestGtkhtmlMimePartView ModestGtkhtmlMimePartView; +typedef struct _ModestGtkhtmlMimePartViewClass ModestGtkhtmlMimePartViewClass; + +struct _ModestGtkhtmlMimePartView { + GtkHTML parent; +}; + +struct _ModestGtkhtmlMimePartViewClass { + GtkHTMLClass parent_class; + + /* TnyMimePartView interface methods */ + TnyMimePart* (*get_part_func) (TnyMimePartView *self); + void (*set_part_func) (TnyMimePartView *self, TnyMimePart *part); + void (*clear_func) (TnyMimePartView *self); + /* ModestMimePartView interface methods */ + gboolean (*is_empty_func) (ModestMimePartView *self); + /* ModestZoomable interface methods */ + gdouble (*get_zoom_func) (ModestZoomable *self); + void (*set_zoom_func) (ModestZoomable *self, gdouble value); + gboolean (*zoom_minus_func) (ModestZoomable *self); + gboolean (*zoom_plus_func) (ModestZoomable *self); + /* ModestISearchView interface methods */ + gboolean (*search_func) (ModestISearchView *self, const gchar *string); + gboolean (*search_next_func) (ModestISearchView *self); + gboolean (*get_selection_area_func) (ModestISearchView *self, gint *x, gint *y, gint *width, gint *height); +}; + + +/** + * + * modest_gtkhtml_mime_part_view_get_type + * + * get the GType for the this class + * + * Returns: the GType for this class + */ +GType modest_gtkhtml_mime_part_view_get_type (void) G_GNUC_CONST; + +/** + * modest_gtkhtml_mime_part_view_new: + * + * create a new #ModestGtkhtmlMimePartView instance, implementing + * interfaces #TnyMimePartView, #ModestMimePartView, #ModestZoomable + * and #ModestISearchView. + * + * Returns: a #ModestGtkhtmlMimePartView + */ +GtkWidget *modest_gtkhtml_mime_part_view_new (void); + +G_END_DECLS + +#endif /* __MODEST_GTK_HTML_MIME_PART_VIEW_H__ */ diff --git a/src/widgets/modest-isearch-view.c b/src/widgets/modest-isearch-view.c new file mode 100644 index 0000000..9e65c4b --- /dev/null +++ b/src/widgets/modest-isearch-view.c @@ -0,0 +1,121 @@ +/* Copyright (c) 2007, Nokia Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Nokia Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include + +/** + * modest_isearch_view_search: + * @self: a #ModestISearchView + * @string: a string + * + * Begins a new search in @self trying to match @string. + * + * Returns: %TRUE if @string was matches, %FALSE otherwise + */ +gboolean +modest_isearch_view_search (ModestISearchView *self, const gchar *string) +{ + return MODEST_ISEARCH_VIEW_GET_IFACE (self)->search_func (self, string); +} + +/** + * modest_isearch_view_search_next: + * @self: a #ModestISearchView + * + * Continues the last search. + * + * Returns: %TRUE if last search matches again, %FALSE otherwise + */ +gboolean +modest_isearch_view_search_next (ModestISearchView *self) +{ + return MODEST_ISEARCH_VIEW_GET_IFACE (self)->search_next_func (self); +} + +/** + * modest_isearch_view_get_selection_area: + * @self: a #ModestISearchView + * @x: a #gint pointer (out) + * @y: a #gint pointer (out) + * @width: a #gint pointer (out) + * @height: a #gint pointer (out) + * + * Obtains the area of the last search match. + * + * Returns: %TRUE if there's any search matched, %FALSE otherwise + */ +gboolean +modest_isearch_view_get_selection_area (ModestISearchView *self, + gint *x, gint *y, + gint *width, gint *height) +{ + return MODEST_ISEARCH_VIEW_GET_IFACE (self)->get_selection_area_func (self, x, y, width, height); +} + +static void +modest_isearch_view_base_init (gpointer g_class) +{ + static gboolean initialized = FALSE; + + if (!initialized) { + /* init signals here */ + initialized = TRUE; + } +} + +GType +modest_isearch_view_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY(type == 0)) + { + static const GTypeInfo info = + { + sizeof (ModestISearchViewIface), + modest_isearch_view_base_init, /* base_init */ + NULL, /* base_finalize */ + NULL, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + 0, + 0, /* n_preallocs */ + NULL, /* instance_init */ + NULL + }; + + type = g_type_register_static (G_TYPE_INTERFACE, + "ModestISearchView", &info, 0); + + } + + return type; +} diff --git a/src/widgets/modest-isearch-view.h b/src/widgets/modest-isearch-view.h new file mode 100644 index 0000000..e359627 --- /dev/null +++ b/src/widgets/modest-isearch-view.h @@ -0,0 +1,64 @@ +/* Copyright (c) 2007, Nokia Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Nokia Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MODEST_ISEARCH_VIEW_H +#define MODEST_ISEARCH_VIEW_H + +#include +#include + +G_BEGIN_DECLS + +#define MODEST_TYPE_ISEARCH_VIEW (modest_isearch_view_get_type ()) +#define MODEST_ISEARCH_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MODEST_TYPE_ISEARCH_VIEW, ModestISearchView)) +#define MODEST_IS_ISEARCH_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MODEST_TYPE_ISEARCH_VIEW)) +#define MODEST_ISEARCH_VIEW_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), MODEST_TYPE_ISEARCH_VIEW, ModestISearchViewIface)) + +typedef struct _ModestISearchView ModestISearchView; +typedef struct _ModestISearchViewIface ModestISearchViewIface; + +struct _ModestISearchViewIface +{ + GTypeInterface parent; + + /* virtuals */ + gboolean (*search_func) (ModestISearchView *self, const gchar *string); + gboolean (*search_next_func) (ModestISearchView *self); + gboolean (*get_selection_area_func) (ModestISearchView *self, gint *x, gint *y, gint *width, gint *height); +}; + +GType modest_isearch_view_get_type (void); + +gboolean modest_isearch_view_search (ModestISearchView *self, const gchar *string); +gboolean modest_isearch_view_search_next (ModestISearchView *self); +gboolean modest_isearch_view_get_selection_area (ModestISearchView *self, gint *x, gint *y, gint *width, gint *height); + +G_END_DECLS + +#endif diff --git a/src/widgets/modest-mime-part-view.c b/src/widgets/modest-mime-part-view.c new file mode 100644 index 0000000..a276c6a --- /dev/null +++ b/src/widgets/modest-mime-part-view.c @@ -0,0 +1,155 @@ +/* Copyright (c) 2007, Nokia Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Nokia Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include + +enum { + ACTIVATE_LINK, + LINK_HOVER, + FETCH_URL, + LAST_SIGNAL +}; + +static guint mime_part_view_signals[LAST_SIGNAL] = { 0 }; + +/** + * modest_mime_part_view_is_empty: + * @self: a #ModestMimePartView + * + * checks if the mail shown can be considered as empty or not. + * + * Returns: %TRUE if mail shown is empty, %FALSE otherwise. + */ +gboolean +modest_mime_part_view_is_empty (ModestMimePartView *self) +{ + return MODEST_MIME_PART_VIEW_GET_IFACE (self)->is_empty_func (self); +} + +static void +modest_mime_part_view_base_init (gpointer g_class) +{ + static gboolean initialized = FALSE; + + if (!initialized) { + + /** + * ModestMimePartView::activate-link: + * @self: a #ModestMimePartView instance the signal is emitted + * @string: a string containing the URI + * + * This signal is emitted when a URI is activated + * + * Returns: + */ + mime_part_view_signals[ACTIVATE_LINK] = + g_signal_new ("activate_link", + MODEST_TYPE_MIME_PART_VIEW, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ModestMimePartViewIface, activate_link), + NULL, NULL, + modest_marshal_BOOLEAN__STRING, + G_TYPE_BOOLEAN, 1, + G_TYPE_STRING); + /** + * ModestMimePartView::link-hover: + * @self: a #ModestMimePartView instance the signal is emitted + * @string: a string containing the URI + * + * This signal is emitted when user passes the mouse over a link + * + * Returns: + */ + mime_part_view_signals[LINK_HOVER] = + g_signal_new ("link_hover", + MODEST_TYPE_MIME_PART_VIEW, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ModestMimePartViewIface, link_hover), + NULL, NULL, + modest_marshal_BOOLEAN__STRING, + G_TYPE_BOOLEAN, 1, + G_TYPE_STRING); + + /** + * ModestMimePartView::fetch-url: + * @self: a #ModestMimePartView instance the signal is emitted + * @string: a string containing the URI + * @stream: a #TnyStream + * + * This signal is emitted when the page is rendered, and some + * url has to be resolved externally. You have to put the + * required information in the stream (images, etc). + * + * Returns: + */ + mime_part_view_signals[FETCH_URL] = + g_signal_new ("fetch_url", + MODEST_TYPE_MIME_PART_VIEW, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ModestMimePartViewIface, fetch_url), + NULL, NULL, + modest_marshal_BOOLEAN__STRING_OBJECT, + G_TYPE_BOOLEAN, 2, + G_TYPE_STRING, + G_TYPE_OBJECT); + initialized = TRUE; + } +} + +GType +modest_mime_part_view_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY(type == 0)) + { + static const GTypeInfo info = + { + sizeof (ModestMimePartViewIface), + modest_mime_part_view_base_init, /* base_init */ + NULL, /* base_finalize */ + NULL, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + 0, + 0, /* n_preallocs */ + NULL, /* instance_init */ + NULL + }; + + type = g_type_register_static (G_TYPE_INTERFACE, + "ModestMimePartView", &info, 0); + + } + + return type; +} diff --git a/src/widgets/modest-mime-part-view.h b/src/widgets/modest-mime-part-view.h new file mode 100644 index 0000000..b559861 --- /dev/null +++ b/src/widgets/modest-mime-part-view.h @@ -0,0 +1,66 @@ +/* Copyright (c) 2007, Nokia Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Nokia Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MODEST_MIME_PART_VIEW_H +#define MODEST_MIME_PART_VIEW_H + +#include +#include +#include + +G_BEGIN_DECLS + +#define MODEST_TYPE_MIME_PART_VIEW (modest_mime_part_view_get_type ()) +#define MODEST_MIME_PART_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MODEST_TYPE_MIME_PART_VIEW, ModestMimePartView)) +#define MODEST_IS_MIME_PART_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MODEST_TYPE_MIME_PART_VIEW)) +#define MODEST_MIME_PART_VIEW_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), MODEST_TYPE_MIME_PART_VIEW, ModestMimePartViewIface)) + +typedef struct _ModestMimePartView ModestMimePartView; +typedef struct _ModestMimePartViewIface ModestMimePartViewIface; + +struct _ModestMimePartViewIface +{ + GTypeInterface parent; + + /* signals */ + gboolean (*activate_link) (ModestMimePartView *self, const gchar *uri); + gboolean (*link_hover) (ModestMimePartView *self, const gchar *uri); + gboolean (*fetch_url) (ModestMimePartView *self, const gchar *uri, TnyStream *stream); + + /* virtuals */ + gboolean (*is_empty_func) (ModestMimePartView *self); +}; + +GType modest_mime_part_view_get_type (void); + +gboolean modest_mime_part_view_is_empty (ModestMimePartView *self); + +G_END_DECLS + +#endif diff --git a/src/widgets/modest-msg-view.c b/src/widgets/modest-msg-view.c index ee39e2e..aff2ca8 100644 --- a/src/widgets/modest-msg-view.c +++ b/src/widgets/modest-msg-view.c @@ -33,24 +33,24 @@ #include #include #include -#include -#include -#include -#include #include #include #include #include -#include "modest-msg-view.h" -#include "modest-tny-stream-gtkhtml.h" -#include -#include +#include +#include +#include #include +#include +#include /* 'private'/'protected' functions */ static void modest_msg_view_class_init (ModestMsgViewClass *klass); +static void tny_msg_view_init (gpointer g, gpointer iface_data); +static void tny_mime_part_view_init (gpointer g, gpointer iface_data); +static void modest_zoomable_init (gpointer g, gpointer iface_data); static void modest_msg_view_init (ModestMsgView *obj); static void modest_msg_view_finalize (GObject *obj); static void modest_msg_view_destroy (GtkObject *obj); @@ -61,10 +61,10 @@ static void get_property (GObject *object, guint prop_id, GValue *value, GPa static void on_recpt_activated (ModestMailHeaderView *header_view, const gchar *address, ModestMsgView *msg_view); static void on_attachment_activated (ModestAttachmentsView * att_view, TnyMimePart *mime_part, gpointer userdata); -/* GtkHtml signals */ -static gboolean on_link_clicked (GtkWidget *widget, const gchar *uri, ModestMsgView *msg_view); -static gboolean on_url_requested (GtkWidget *widget, const gchar *uri, GtkHTMLStream *stream, - ModestMsgView *msg_view); +/* body view signals */ +static gboolean on_activate_link (GtkWidget *widget, const gchar *uri, ModestMsgView *msg_view); +static gboolean on_fetch_url (GtkWidget *widget, const gchar *uri, TnyStream *stream, + ModestMsgView *msg_view); static gboolean on_link_hover (GtkWidget *widget, const gchar *uri, ModestMsgView *msg_view); #ifdef MAEMO_CHANGES @@ -93,6 +93,42 @@ static void forall (GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer userdata); static void container_remove (GtkContainer *container, GtkWidget *widget); +/* TnyMimePartView implementation */ +static void modest_msg_view_mp_clear (TnyMimePartView *self); +static void modest_msg_view_mp_set_part (TnyMimePartView *self, TnyMimePart *part); +static void modest_msg_view_mp_set_part_default (TnyMimePartView *self, TnyMimePart *part); +static TnyMimePart* modest_msg_view_mp_get_part (TnyMimePartView *self); +static TnyMimePart* modest_msg_view_mp_get_part_default (TnyMimePartView *self); +/* TnyMsgView implementation */ +static TnyMsg *modest_msg_view_get_msg (TnyMsgView *self); +static TnyMsg *modest_msg_view_get_msg_default (TnyMsgView *self); +static void modest_msg_view_set_msg (TnyMsgView *self, TnyMsg *msg); +static void modest_msg_view_set_msg_default (TnyMsgView *self, TnyMsg *msg); +static void modest_msg_view_clear (TnyMsgView *self); +static void modest_msg_view_clear_default (TnyMsgView *self); +static void modest_msg_view_set_unavailable (TnyMsgView *self); +static void modest_msg_view_set_unavailable_default (TnyMsgView *self); +static TnyMimePartView *modest_msg_view_create_mime_part_view_for (TnyMsgView *self, TnyMimePart *part); +static TnyMimePartView *modest_msg_view_create_mime_part_view_for_default (TnyMsgView *self, TnyMimePart *part); +static TnyMsgView *modest_msg_view_create_new_inline_viewer (TnyMsgView *self); +static TnyMsgView *modest_msg_view_create_new_inline_viewer_default (TnyMsgView *self); +/* ModestZoomable implementation */ +static gdouble modest_msg_view_get_zoom (ModestZoomable *self); +static void modest_msg_view_set_zoom (ModestZoomable *self, gdouble value); +static gboolean modest_msg_view_zoom_minus (ModestZoomable *self); +static gboolean modest_msg_view_zoom_plus (ModestZoomable *self); +static gdouble modest_msg_view_get_zoom_default (ModestZoomable *self); +static void modest_msg_view_set_zoom_default (ModestZoomable *self, gdouble value); +static gboolean modest_msg_view_zoom_minus_default (ModestZoomable *self); +static gboolean modest_msg_view_zoom_plus_default (ModestZoomable *self); + +/* internal api */ +static TnyMsg *get_message (ModestMsgView *self); +static void set_message (ModestMsgView *self, TnyMsg *tny_msg); +static void set_zoom (ModestMsgView *self, gdouble zoom); +static gdouble get_zoom (ModestMsgView *self); + + /* list my signals */ enum { LINK_CLICKED_SIGNAL, @@ -113,7 +149,7 @@ enum { typedef struct _ModestMsgViewPrivate ModestMsgViewPrivate; struct _ModestMsgViewPrivate { - GtkWidget *gtkhtml; + GtkWidget *body_view; GtkWidget *mail_header_view; GtkWidget *attachments_view; @@ -170,9 +206,39 @@ modest_msg_view_get_type (void) (GInstanceInitFunc) modest_msg_view_init, NULL }; + static const GInterfaceInfo tny_msg_view_info = + { + (GInterfaceInitFunc) tny_msg_view_init, /* interface_init */ + NULL, /* interface_finalize */ + NULL /* interface_data */ + }; + + static const GInterfaceInfo tny_mime_part_view_info = + { + (GInterfaceInitFunc) tny_mime_part_view_init, /* interface_init */ + NULL, /* interface_finalize */ + NULL /* interface_data */ + }; + + static const GInterfaceInfo modest_zoomable_info = + { + (GInterfaceInitFunc) modest_zoomable_init, /* interface_init */ + NULL, /* interface_finalize */ + NULL /* interface_data */ + }; + my_type = g_type_register_static (GTK_TYPE_CONTAINER, "ModestMsgView", &my_info, 0); + + g_type_add_interface_static (my_type, TNY_TYPE_MIME_PART_VIEW, + &tny_mime_part_view_info); + + g_type_add_interface_static (my_type, TNY_TYPE_MSG_VIEW, + &tny_msg_view_info); + + g_type_add_interface_static (my_type, MODEST_TYPE_ZOOMABLE, + &modest_zoomable_info); } return my_type; } @@ -205,6 +271,18 @@ modest_msg_view_class_init (ModestMsgViewClass *klass) container_class->remove = container_remove; klass->set_scroll_adjustments = set_scroll_adjustments; + klass->get_part_func = modest_msg_view_mp_get_part_default; + klass->set_part_func = modest_msg_view_mp_set_part_default; + klass->get_msg_func = modest_msg_view_get_msg_default; + klass->set_msg_func = modest_msg_view_set_msg_default; + klass->set_unavailable_func = modest_msg_view_set_unavailable_default; + klass->clear_func = modest_msg_view_clear_default; + klass->create_mime_part_view_for_func = modest_msg_view_create_mime_part_view_for_default; + klass->create_new_inline_viewer_func = modest_msg_view_create_new_inline_viewer_default; + klass->get_zoom_func = modest_msg_view_get_zoom_default; + klass->set_zoom_func = modest_msg_view_set_zoom_default; + klass->zoom_minus_func = modest_msg_view_zoom_minus_default; + klass->zoom_plus_func = modest_msg_view_zoom_plus_default; g_type_class_add_private (gobject_class, sizeof(ModestMsgViewPrivate)); @@ -468,7 +546,7 @@ set_scroll_adjustments (ModestMsgView *msg_view, modest_msg_view_set_hadjustment (msg_view, hadj); modest_msg_view_set_vadjustment (msg_view, vadj); - gtk_container_set_focus_vadjustment (GTK_CONTAINER (priv->gtkhtml), vadj); + gtk_container_set_focus_vadjustment (GTK_CONTAINER (priv->body_view), vadj); } static void @@ -492,7 +570,7 @@ realize (GtkWidget *widget) * widgets inside. * * headers_window: gdk window for headers_box. * * html_window: gdk window for html_scroll (the scrolled window containing the - * gtkhtml showing the contents of the mail). + * body view showing the contents of the mail). */ attributes.x = widget->allocation.x; @@ -856,6 +934,7 @@ modest_msg_view_init (ModestMsgView *obj) { ModestMsgViewPrivate *priv; GtkAdjustment *html_vadj; + GtkWidget *separator; GTK_WIDGET_UNSET_FLAGS (obj, GTK_NO_WINDOW); gtk_widget_set_redraw_on_allocate (GTK_WIDGET (obj), TRUE); @@ -882,23 +961,17 @@ modest_msg_view_init (ModestMsgView *obj) priv->msg = NULL; - priv->gtkhtml = gtk_html_new(); - gtk_html_set_editable (GTK_HTML(priv->gtkhtml), FALSE); - gtk_html_allow_selection (GTK_HTML(priv->gtkhtml), TRUE); - gtk_html_set_caret_mode (GTK_HTML(priv->gtkhtml), FALSE); - gtk_html_set_blocking (GTK_HTML(priv->gtkhtml), FALSE); - gtk_html_set_images_blocking (GTK_HTML(priv->gtkhtml), FALSE); - + priv->body_view = GTK_WIDGET (g_object_new (MODEST_TYPE_GTKHTML_MIME_PART_VIEW, NULL)); priv->mail_header_view = GTK_WIDGET(modest_mail_header_view_new (TRUE)); gtk_widget_set_no_show_all (priv->mail_header_view, TRUE); priv->attachments_view = GTK_WIDGET(modest_attachments_view_new (NULL)); - priv->sig1 = g_signal_connect (G_OBJECT(priv->gtkhtml), "link_clicked", - G_CALLBACK(on_link_clicked), obj); - priv->sig2 = g_signal_connect (G_OBJECT(priv->gtkhtml), "url_requested", - G_CALLBACK(on_url_requested), obj); - priv->sig3 = g_signal_connect (G_OBJECT(priv->gtkhtml), "on_url", + priv->sig1 = g_signal_connect (G_OBJECT(priv->body_view), "activate_link", + G_CALLBACK(on_activate_link), obj); + priv->sig2 = g_signal_connect (G_OBJECT(priv->body_view), "fetch_url", + G_CALLBACK(on_fetch_url), obj); + priv->sig3 = g_signal_connect (G_OBJECT(priv->body_view), "link_hover", G_CALLBACK(on_link_hover), obj); g_signal_connect (G_OBJECT (priv->mail_header_view), "recpt-activated", @@ -912,6 +985,40 @@ modest_msg_view_init (ModestMsgView *obj) g_signal_connect (G_OBJECT (html_vadj), "changed", G_CALLBACK (html_adjustment_changed), obj); + gtk_widget_push_composite_child (); + priv->headers_box = gtk_vbox_new (0, FALSE); + gtk_widget_set_composite_name (priv->headers_box, "headers"); + gtk_widget_pop_composite_child (); + + if (priv->mail_header_view) + gtk_box_pack_start (GTK_BOX(priv->headers_box), priv->mail_header_view, FALSE, FALSE, 0); + + if (priv->attachments_view) { + gchar *att_label = g_strconcat (_("mcen_me_viewer_attachments"), ":", NULL); + + priv->attachments_box = (GtkWidget *) + modest_mail_header_view_add_custom_header (MODEST_MAIL_HEADER_VIEW (priv->mail_header_view), + att_label, + priv->attachments_view, + FALSE, FALSE); + gtk_widget_hide_all (priv->attachments_box); + g_free (att_label); + } + + separator = gtk_hseparator_new (); + gtk_box_pack_start (GTK_BOX(priv->headers_box), separator, FALSE, FALSE, 0); + + gtk_widget_set_parent (priv->headers_box, GTK_WIDGET (obj)); + + if (priv->body_view) { + gtk_container_add (GTK_CONTAINER (priv->html_scroll), priv->body_view); + gtk_widget_set_parent (priv->html_scroll, GTK_WIDGET(obj)); +#ifdef MAEMO_CHANGES + gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->body_view), NULL, NULL, 0); + g_signal_connect (G_OBJECT (priv->body_view), "tap-and-hold", G_CALLBACK (on_tap_and_hold), obj); +#endif + } + } @@ -926,13 +1033,13 @@ modest_msg_view_finalize (GObject *obj) priv->msg = NULL; } - /* we cannot disconnect sigs, because priv->gtkhtml is + /* we cannot disconnect sigs, because priv->body_view is * already dead */ disconnect_vadjustment (MODEST_MSG_VIEW(obj)); disconnect_hadjustment (MODEST_MSG_VIEW(obj)); - priv->gtkhtml = NULL; + priv->body_view = NULL; priv->attachments_view = NULL; G_OBJECT_CLASS(parent_class)->finalize (obj); @@ -1079,49 +1186,10 @@ modest_msg_view_new (TnyMsg *msg) { GObject *obj; ModestMsgView* self; - ModestMsgViewPrivate *priv; - GtkWidget *separator; obj = G_OBJECT(g_object_new(MODEST_TYPE_MSG_VIEW, NULL)); self = MODEST_MSG_VIEW(obj); - priv = MODEST_MSG_VIEW_GET_PRIVATE (self); - - gtk_widget_push_composite_child (); - priv->headers_box = gtk_vbox_new (0, FALSE); - gtk_widget_set_composite_name (priv->headers_box, "headers"); - gtk_widget_pop_composite_child (); - - if (priv->mail_header_view) - gtk_box_pack_start (GTK_BOX(priv->headers_box), priv->mail_header_view, FALSE, FALSE, 0); - - if (priv->attachments_view) { - gchar *att_label = g_strconcat (_("mcen_me_viewer_attachments"), ":", NULL); - - priv->attachments_box = (GtkWidget *) - modest_mail_header_view_add_custom_header (MODEST_MAIL_HEADER_VIEW (priv->mail_header_view), - att_label, - priv->attachments_view, - FALSE, FALSE); - gtk_widget_hide_all (priv->attachments_box); - g_free (att_label); -/* gtk_widget_set_no_show_all (priv->attachments_box, TRUE); */ - } - - separator = gtk_hseparator_new (); - gtk_box_pack_start (GTK_BOX(priv->headers_box), separator, FALSE, FALSE, 0); - - gtk_widget_set_parent (priv->headers_box, GTK_WIDGET (self)); - - if (priv->gtkhtml) { - gtk_container_add (GTK_CONTAINER (priv->html_scroll), priv->gtkhtml); - gtk_widget_set_parent (priv->html_scroll, GTK_WIDGET(self)); -#ifdef MAEMO_CHANGES - gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->gtkhtml), NULL, NULL, 0); - g_signal_connect (G_OBJECT (priv->gtkhtml), "tap-and-hold", G_CALLBACK (on_tap_and_hold), obj); -#endif - } - - modest_msg_view_set_message (self, msg); + tny_msg_view_set_msg (TNY_MSG_VIEW (self), msg); return GTK_WIDGET(self); } @@ -1156,7 +1224,7 @@ on_attachment_activated (ModestAttachmentsView * att_view, TnyMimePart *mime_par } static gboolean -on_link_clicked (GtkWidget *widget, const gchar *uri, ModestMsgView *msg_view) +on_activate_link (GtkWidget *widget, const gchar *uri, ModestMsgView *msg_view) { g_return_val_if_fail (msg_view, FALSE); @@ -1200,14 +1268,42 @@ find_cid_image (TnyMsg *msg, const gchar *cid) while (!tny_iterator_is_done(iter)) { const gchar *part_cid; + part = TNY_MIME_PART(tny_iterator_get_current(iter)); part_cid = tny_mime_part_get_content_id (part); if (part_cid && strcmp (cid, part_cid) == 0) break; - if (part) - g_object_unref (G_OBJECT(part)); + if (tny_mime_part_content_type_is (part, "multipart/related")) { + TnyList *related_parts = TNY_LIST (tny_simple_list_new ()); + TnyIterator *related_iter = NULL; + TnyMimePart *related_part = NULL; + + tny_mime_part_get_parts (part, related_parts); + related_iter = tny_list_create_iterator (related_parts); + + while (!tny_iterator_is_done (related_iter)) { + related_part = TNY_MIME_PART (tny_iterator_get_current (related_iter)); + part_cid = tny_mime_part_get_content_id (related_part); + if (part_cid && strcmp (cid, part_cid) == 0) { + break; + } + g_object_unref (related_part); + related_part = NULL; + tny_iterator_next (related_iter); + } + + g_object_unref (related_iter); + g_object_unref (related_parts); + if (related_part != NULL) { + g_object_unref (part); + part = related_part; + break; + } + } + + g_object_unref (G_OBJECT(part)); part = NULL; tny_iterator_next (iter); @@ -1221,126 +1317,34 @@ find_cid_image (TnyMsg *msg, const gchar *cid) static gboolean -on_url_requested (GtkWidget *widget, const gchar *uri, - GtkHTMLStream *stream, ModestMsgView *msg_view) +on_fetch_url (GtkWidget *widget, const gchar *uri, + TnyStream *stream, ModestMsgView *msg_view) { ModestMsgViewPrivate *priv; priv = MODEST_MSG_VIEW_GET_PRIVATE (msg_view); + gboolean result = FALSE; if (g_str_has_prefix (uri, "cid:")) { /* +4 ==> skip "cid:" */ TnyMimePart *part = find_cid_image (priv->msg, uri + 4); if (!part) { g_printerr ("modest: '%s' not found\n", uri + 4); - gtk_html_stream_close (stream, GTK_HTML_STREAM_ERROR); + result = FALSE; } else { - TnyStream *tny_stream = - TNY_STREAM(modest_tny_stream_gtkhtml_new(stream)); tny_mime_part_decode_to_stream ((TnyMimePart*)part, - tny_stream); - gtk_html_stream_close (stream, GTK_HTML_STREAM_OK); - - g_object_unref (G_OBJECT(tny_stream)); + stream); g_object_unref (G_OBJECT(part)); + result = TRUE; } + } else { + return TRUE; } - return TRUE; -} - -static gboolean -set_html_message (ModestMsgView *self, TnyMimePart *tny_body, TnyMsg *msg) -{ - GtkHTMLStream *gtkhtml_stream; - TnyStream *tny_stream; - ModestMsgViewPrivate *priv; - - g_return_val_if_fail (self, FALSE); - g_return_val_if_fail (tny_body, FALSE); - - priv = MODEST_MSG_VIEW_GET_PRIVATE(self); - - gtkhtml_stream = gtk_html_begin(GTK_HTML(priv->gtkhtml)); - - tny_stream = TNY_STREAM(modest_tny_stream_gtkhtml_new (gtkhtml_stream)); - tny_stream_reset (tny_stream); - - tny_mime_part_decode_to_stream ((TnyMimePart*)tny_body, tny_stream); - g_object_unref (G_OBJECT(tny_stream)); - - gtk_html_stream_destroy (gtkhtml_stream); - - return TRUE; -} - - -/* FIXME: this is a hack --> we use the tny_text_buffer_stream to - * get the message text, then write to gtkhtml 'by hand' */ -static gboolean -set_text_message (ModestMsgView *self, TnyMimePart *tny_body, TnyMsg *msg) -{ - GtkTextBuffer *buf; - GtkTextIter begin, end; - TnyStream* txt_stream, *tny_stream; - GtkHTMLStream *gtkhtml_stream; - gchar *txt; - ModestMsgViewPrivate *priv; - - g_return_val_if_fail (self, FALSE); - g_return_val_if_fail (tny_body, FALSE); - - priv = MODEST_MSG_VIEW_GET_PRIVATE(self); - - buf = gtk_text_buffer_new (NULL); - txt_stream = TNY_STREAM(tny_gtk_text_buffer_stream_new (buf)); - - tny_stream_reset (txt_stream); - - gtkhtml_stream = gtk_html_begin(GTK_HTML(priv->gtkhtml)); - tny_stream = TNY_STREAM(modest_tny_stream_gtkhtml_new (gtkhtml_stream)); - - // FIXME: tinymail - tny_mime_part_decode_to_stream ((TnyMimePart*)tny_body, txt_stream); - tny_stream_reset (txt_stream); - - gtk_text_buffer_get_bounds (buf, &begin, &end); - txt = gtk_text_buffer_get_text (buf, &begin, &end, FALSE); - if (txt) { - gchar *html = modest_text_utils_convert_to_html (txt); - tny_stream_write (tny_stream, html, strlen(html)); - tny_stream_reset (tny_stream); - g_free (txt); - g_free (html); - } - - g_object_unref (G_OBJECT(tny_stream)); - g_object_unref (G_OBJECT(txt_stream)); - g_object_unref (G_OBJECT(buf)); - - gtk_html_stream_destroy (gtkhtml_stream); - - return TRUE; -} - - -static gboolean -set_empty_message (ModestMsgView *self) -{ - ModestMsgViewPrivate *priv; - - g_return_val_if_fail (self, FALSE); - priv = MODEST_MSG_VIEW_GET_PRIVATE(self); - - gtk_html_load_from_string (GTK_HTML(priv->gtkhtml), - "", 1); - - - return TRUE; + return result; } - -void -modest_msg_view_set_message (ModestMsgView *self, TnyMsg *msg) +static void +set_message (ModestMsgView *self, TnyMsg *msg) { TnyMimePart *body; ModestMsgViewPrivate *priv; @@ -1366,7 +1370,7 @@ modest_msg_view_set_message (ModestMsgView *self, TnyMsg *msg) gtk_widget_hide_all (priv->mail_header_view); gtk_widget_hide_all (priv->attachments_box); gtk_widget_set_no_show_all (priv->mail_header_view, TRUE); - set_empty_message (self); + tny_mime_part_view_clear (TNY_MIME_PART_VIEW (priv->body_view)); gtk_widget_queue_resize (GTK_WIDGET(self)); gtk_widget_queue_draw (GTK_WIDGET(self)); return; @@ -1381,10 +1385,7 @@ modest_msg_view_set_message (ModestMsgView *self, TnyMsg *msg) body = modest_tny_msg_find_body_part (msg, TRUE); if (body) { - if (tny_mime_part_content_type_is (body, "text/html")) - set_html_message (self, body, msg); - else - set_text_message (self, body, msg); + tny_mime_part_view_set_part (TNY_MIME_PART_VIEW (priv->body_view), body); if(modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view))) { gtk_widget_show_all (priv->attachments_box); @@ -1392,21 +1393,13 @@ modest_msg_view_set_message (ModestMsgView *self, TnyMsg *msg) gtk_widget_hide_all (priv->attachments_box); } -/* g_print ("---\nfilename %s\ncontent_location %s\ncontent_id%s\ncontent_type%s\n", */ -/* tny_mime_part_get_filename (body), */ -/* tny_mime_part_get_content_location (body), */ -/* tny_mime_part_get_content_id (body), */ -/* tny_mime_part_get_content_type (body)); */ - } else - set_empty_message (self); + tny_mime_part_view_clear (TNY_MIME_PART_VIEW (priv->body_view)); - gtk_widget_show (priv->gtkhtml); + gtk_widget_show (priv->body_view); gtk_widget_set_no_show_all (priv->attachments_box, TRUE); gtk_widget_show_all (priv->mail_header_view); gtk_widget_set_no_show_all (priv->attachments_box, FALSE); -/* gtk_widget_show_all (priv->attachments_box); */ -/* gtk_widget_show_all (priv->attachments_box); */ gtk_widget_set_no_show_all (priv->mail_header_view, TRUE); gtk_widget_queue_resize (GTK_WIDGET(self)); gtk_widget_queue_draw (GTK_WIDGET(self)); @@ -1428,8 +1421,8 @@ modest_msg_view_set_message (ModestMsgView *self, TnyMsg *msg) } -TnyMsg* -modest_msg_view_get_message (ModestMsgView *self) +static TnyMsg* +get_message (ModestMsgView *self) { TnyMsg *msg; @@ -1443,32 +1436,225 @@ modest_msg_view_get_message (ModestMsgView *self) return msg; } +gboolean +modest_msg_view_get_message_is_empty (ModestMsgView *self) +{ + ModestMsgViewPrivate *priv = MODEST_MSG_VIEW_GET_PRIVATE (self); + + return modest_mime_part_view_is_empty (MODEST_MIME_PART_VIEW (priv->body_view)); +} + +/* TNY MSG IMPLEMENTATION */ + +static void +tny_msg_view_init (gpointer g, gpointer iface_data) +{ + TnyMsgViewIface *klass = (TnyMsgViewIface *)g; + + klass->get_msg_func = modest_msg_view_get_msg; + klass->set_msg_func = modest_msg_view_set_msg; + klass->set_unavailable_func = modest_msg_view_set_unavailable; + klass->clear_func = modest_msg_view_clear; + klass->create_mime_part_view_for_func = modest_msg_view_create_mime_part_view_for; + klass->create_new_inline_viewer_func = modest_msg_view_create_new_inline_viewer; + + return; +} + +static TnyMsg * +modest_msg_view_get_msg (TnyMsgView *self) +{ + return MODEST_MSG_VIEW_GET_CLASS (self)->get_msg_func (self); +} + +static TnyMsg * +modest_msg_view_get_msg_default (TnyMsgView *self) +{ + return TNY_MSG (tny_mime_part_view_get_part (TNY_MIME_PART_VIEW (self))); +} + +static void +modest_msg_view_set_msg (TnyMsgView *self, TnyMsg *msg) +{ + MODEST_MSG_VIEW_GET_CLASS (self)->set_msg_func (self, msg); +} + +static void +modest_msg_view_set_msg_default (TnyMsgView *self, TnyMsg *msg) +{ + + tny_mime_part_view_set_part (TNY_MIME_PART_VIEW (self), TNY_MIME_PART (msg)); + + return; +} + +static void +modest_msg_view_set_unavailable (TnyMsgView *self) +{ + MODEST_MSG_VIEW_GET_CLASS (self)->set_unavailable_func (self); +} + +static void +modest_msg_view_set_unavailable_default (TnyMsgView *self) +{ + tny_msg_view_clear (self); + + return; +} + +static void +modest_msg_view_clear (TnyMsgView *self) +{ + MODEST_MSG_VIEW_GET_CLASS (self)->clear_func (self); +} + +static void +modest_msg_view_clear_default (TnyMsgView *self) +{ + set_message (MODEST_MSG_VIEW (self), NULL); +} + +static TnyMimePartView* +modest_msg_view_create_mime_part_view_for (TnyMsgView *self, TnyMimePart *part) +{ + return MODEST_MSG_VIEW_GET_CLASS (self)->create_mime_part_view_for_func (self, part); +} + +static TnyMimePartView* +modest_msg_view_create_mime_part_view_for_default (TnyMsgView *self, TnyMimePart *part) +{ + g_warning ("modest_msg_view_create_mime_part_view_for_default is not implemented"); + return NULL; +} + +static TnyMsgView* +modest_msg_view_create_new_inline_viewer (TnyMsgView *self) +{ + return MODEST_MSG_VIEW_GET_CLASS (self)->create_new_inline_viewer_func (self); +} + +static TnyMsgView* +modest_msg_view_create_new_inline_viewer_default (TnyMsgView *self) +{ + g_warning ("modest_msg_view_create_new_inline_viewer_default is not implemented"); + + return NULL; +} + +/* TNY MIME PART IMPLEMENTATION */ + +static void +tny_mime_part_view_init (gpointer g, gpointer iface_data) +{ + TnyMimePartViewIface *klass = (TnyMimePartViewIface *)g; + + klass->get_part_func = modest_msg_view_mp_get_part; + klass->set_part_func = modest_msg_view_mp_set_part; + klass->clear_func = modest_msg_view_mp_clear; + + return; +} + +static TnyMimePart* +modest_msg_view_mp_get_part (TnyMimePartView *self) +{ + return MODEST_MSG_VIEW_GET_CLASS (self)->get_part_func (self); +} + + +static TnyMimePart* +modest_msg_view_mp_get_part_default (TnyMimePartView *self) +{ + return TNY_MIME_PART (get_message (MODEST_MSG_VIEW (self))); +} + +static void +modest_msg_view_mp_set_part (TnyMimePartView *self, + TnyMimePart *part) +{ + MODEST_MSG_VIEW_GET_CLASS (self)->set_part_func (self, part); +} + +static void +modest_msg_view_mp_set_part_default (TnyMimePartView *self, + TnyMimePart *part) +{ + g_return_if_fail ((part == NULL) || TNY_IS_MSG (part)); + + set_message (MODEST_MSG_VIEW (self), TNY_MSG (part)); +} + +static void +modest_msg_view_mp_clear (TnyMimePartView *self) +{ + tny_msg_view_clear (TNY_MSG_VIEW (self)); +} + +/* MODEST ZOOMABLE IMPLEMENTATION */ +static void +modest_zoomable_init (gpointer g, gpointer iface_data) +{ + ModestZoomableIface *klass = (ModestZoomableIface *)g; + + klass->get_zoom_func = modest_msg_view_get_zoom; + klass->set_zoom_func = modest_msg_view_set_zoom; + klass->zoom_minus_func = modest_msg_view_zoom_minus; + klass->zoom_plus_func = modest_msg_view_zoom_plus; + + return; +} + +static gdouble +modest_msg_view_get_zoom (ModestZoomable *self) +{ + return MODEST_MSG_VIEW_GET_CLASS (self)->get_zoom_func (self); +} + +static gdouble +modest_msg_view_get_zoom_default (ModestZoomable *self) +{ + return get_zoom (MODEST_MSG_VIEW (self)); +} + +static void +modest_msg_view_set_zoom (ModestZoomable *self, gdouble value) +{ + MODEST_MSG_VIEW_GET_CLASS (self)->set_zoom_func (self, value); +} + +static void +modest_msg_view_set_zoom_default (ModestZoomable *self, gdouble value) +{ + set_zoom (MODEST_MSG_VIEW (self), value); +} + static gboolean -has_contents_receiver (gpointer engine, const gchar *data, - size_t len, gboolean *has_contents) +modest_msg_view_zoom_minus (ModestZoomable *self) { - if (len > 1 || ((len == 1)&&(data[0]!='\n'))) { - *has_contents = TRUE; - return FALSE; - } - return TRUE; + return MODEST_MSG_VIEW_GET_CLASS (self)->zoom_minus_func (self); } -gboolean -modest_msg_view_get_message_is_empty (ModestMsgView *self) +static gboolean +modest_msg_view_zoom_minus_default (ModestZoomable *self) { - /* TODO: Find some gtkhtml API to check whether there is any (visible, non markup) - * text in the message: - */ - ModestMsgViewPrivate *priv = MODEST_MSG_VIEW_GET_PRIVATE (self); - gboolean has_contents = FALSE; + /* operation not supported in ModestMsgView */ + return FALSE; +} - gtk_html_export (GTK_HTML (priv->gtkhtml), "text/plain", - (GtkHTMLSaveReceiverFn) has_contents_receiver, &has_contents); - - return !has_contents; +static gboolean +modest_msg_view_zoom_plus (ModestZoomable *self) +{ + return MODEST_MSG_VIEW_GET_CLASS (self)->zoom_plus_func (self); +} + +static gboolean +modest_msg_view_zoom_plus_default (ModestZoomable *self) +{ + /* operation not supported in ModestMsgView */ + return FALSE; } +/* INCREMENTAL SEARCH IMPLEMENTATION */ gboolean modest_msg_view_search (ModestMsgView *self, const gchar *search) @@ -1481,21 +1667,18 @@ modest_msg_view_search (ModestMsgView *self, const gchar *search) g_return_val_if_fail (MODEST_IS_MSG_VIEW (self), FALSE); priv = MODEST_MSG_VIEW_GET_PRIVATE (self); - vadj = gtk_layout_get_vadjustment (GTK_LAYOUT (priv->gtkhtml)); + vadj = gtk_layout_get_vadjustment (GTK_LAYOUT (priv->body_view)); g_object_ref (vadj); tmp_vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, vadj->lower, vadj->upper, vadj->step_increment, 32.0, 32.0)); - gtk_layout_set_vadjustment (GTK_LAYOUT (priv->gtkhtml), tmp_vadj); - result = gtk_html_engine_search (GTK_HTML (priv->gtkhtml), - search, - FALSE, /* case sensitive */ - TRUE, /* forward */ - FALSE); /* regexp */ + gtk_layout_set_vadjustment (GTK_LAYOUT (priv->body_view), tmp_vadj); + result = modest_isearch_view_search (MODEST_ISEARCH_VIEW (priv->body_view), + search); if (result) { gint x, y, w, h; gdouble offset_top, offset_bottom; GtkAdjustment *adj; - gtk_html_get_selection_area (GTK_HTML (priv->gtkhtml), &x, &y, &w, &h); + modest_isearch_view_get_selection_area (MODEST_ISEARCH_VIEW (priv->body_view), &x, &y, &w, &h); offset_top = (gdouble) (priv->headers_box->requisition.height + y); offset_bottom = (gdouble) (priv->headers_box->requisition.height + y + h); adj = GTK_ADJUSTMENT (priv->vadj); @@ -1506,7 +1689,7 @@ modest_msg_view_search (ModestMsgView *self, const gchar *search) } y_offset = tmp_vadj->value; - gtk_layout_set_vadjustment (GTK_LAYOUT (priv->gtkhtml), vadj); + gtk_layout_set_vadjustment (GTK_LAYOUT (priv->body_view), vadj); g_object_unref (vadj); return result; @@ -1521,14 +1704,13 @@ modest_msg_view_search_next (ModestMsgView *self) g_return_val_if_fail (MODEST_IS_MSG_VIEW (self), FALSE); priv = MODEST_MSG_VIEW_GET_PRIVATE (self); - result = gtk_html_engine_search_next (GTK_HTML (priv->gtkhtml)); + result = modest_isearch_view_search_next (MODEST_ISEARCH_VIEW (priv->body_view)); if (result) { gint x, y, w, h; gdouble offset_top, offset_bottom; GtkAdjustment *adj; - gtk_html_get_selection_area (GTK_HTML (priv->gtkhtml), &x, &y, &w, &h); - g_message ("SELECTION AREA x%d y%d w%d h%d", x, y, w, h); + modest_isearch_view_get_selection_area (MODEST_ISEARCH_VIEW (priv->body_view), &x, &y, &w, &h); offset_top = (gdouble) (priv->headers_box->requisition.height + y); offset_bottom = (gdouble) (priv->headers_box->requisition.height + y + h); adj = GTK_ADJUSTMENT (priv->vadj); @@ -1540,30 +1722,30 @@ modest_msg_view_search_next (ModestMsgView *self) return result; } -void -modest_msg_view_set_zoom (ModestMsgView *self, gdouble zoom) +/* ZOOM IMPLEMENTATION */ + +static void +set_zoom (ModestMsgView *self, gdouble zoom) { ModestMsgViewPrivate *priv; g_return_if_fail (MODEST_IS_MSG_VIEW (self)); - priv = MODEST_MSG_VIEW_GET_PRIVATE (self); - priv->current_zoom = zoom; - gtk_html_set_magnification (GTK_HTML(priv->gtkhtml), zoom); - gtk_widget_queue_resize (priv->gtkhtml); + modest_zoomable_set_zoom (MODEST_ZOOMABLE(priv->body_view), zoom); + + gtk_widget_queue_resize (priv->body_view); } -gdouble -modest_msg_view_get_zoom (ModestMsgView *self) +static gdouble +get_zoom (ModestMsgView *self) { ModestMsgViewPrivate *priv; g_return_val_if_fail (MODEST_IS_MSG_VIEW (self), 1.0); - priv = MODEST_MSG_VIEW_GET_PRIVATE (self); - return priv->current_zoom; + return modest_zoomable_get_zoom (MODEST_ZOOMABLE (priv->body_view)); } TnyHeaderFlags @@ -1624,20 +1806,18 @@ modest_msg_view_grab_focus (ModestMsgView *view) g_return_if_fail (MODEST_IS_MSG_VIEW (view)); priv = MODEST_MSG_VIEW_GET_PRIVATE (view); - gtk_widget_grab_focus (priv->gtkhtml); + gtk_widget_grab_focus (priv->body_view); } void modest_msg_view_remove_attachment (ModestMsgView *view, TnyMimePart *attachment) { - TnyMsg *msg; ModestMsgViewPrivate *priv; g_return_if_fail (MODEST_IS_MSG_VIEW (view)); g_return_if_fail (TNY_IS_MIME_PART (attachment)); priv = MODEST_MSG_VIEW_GET_PRIVATE (view); - msg = modest_msg_view_get_message (view); modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), attachment); diff --git a/src/widgets/modest-msg-view.h b/src/widgets/modest-msg-view.h index 067e236..80c0902 100644 --- a/src/widgets/modest-msg-view.h +++ b/src/widgets/modest-msg-view.h @@ -35,6 +35,7 @@ #include #include #include +#include G_BEGIN_DECLS @@ -56,6 +57,23 @@ struct _ModestMsgView { struct _ModestMsgViewClass { GtkContainerClass parent_class; + /* TnyMimePartView interface */ + TnyMimePart* (*get_part_func) (TnyMimePartView *self); + void (*set_part_func) (TnyMimePartView *self, TnyMimePart *part); + /* TnyMsgView interface */ + TnyMsg* (*get_msg_func) (TnyMsgView *self); + void (*set_msg_func) (TnyMsgView *self, TnyMsg *msg); + void (*set_unavailable_func) (TnyMsgView *self); + void (*clear_func) (TnyMsgView *self); + TnyMimePartView* (*create_mime_part_view_for_func) (TnyMsgView *self, TnyMimePart *part); + TnyMsgView* (*create_new_inline_viewer_func) (TnyMsgView *self); + /* ModestZoomable interface */ + gdouble (*get_zoom_func) (ModestZoomable *self); + void (*set_zoom_func) (ModestZoomable *self, gdouble value); + gboolean (*zoom_minus_func) (ModestZoomable *self); + gboolean (*zoom_plus_func) (ModestZoomable *self); + + /* signals */ void (*set_scroll_adjustments) (ModestMsgView *msg_view, GtkAdjustment *hadj, GtkAdjustment *vadj); @@ -97,28 +115,6 @@ GType modest_msg_view_get_type (void) G_GNUC_CONST; GtkWidget* modest_msg_view_new (TnyMsg *tny_msg); -/** - * modest_msg_view_set_message - * @self: a ModestMsgView instance - * @tny_msg: a TnyMsg instance, or NULL - * - * display the @tny_msg e-mail message. If @tny_msg is NULL, - * then a blank page will be displayed - * */ -void modest_msg_view_set_message (ModestMsgView *self, TnyMsg *tny_msg); - - - -/** - * modest_msg_view_set_message - * @self: a ModestMsgView instance - * - * gets a new reference the #TnyMsg of the message view. The caller - * must free the new reference - * - * Returns: the message or NULL - */ -TnyMsg* modest_msg_view_get_message (ModestMsgView *self); /** * modest_msg_view_get_message_is_empty @@ -140,8 +136,6 @@ GtkShadowType modest_msg_view_get_shadow_type (ModestMsgView *self); gboolean modest_msg_view_search (ModestMsgView *self, const gchar *search); gboolean modest_msg_view_search_next (ModestMsgView *self); -void modest_msg_view_set_zoom (ModestMsgView *self, gdouble zoom); -gdouble modest_msg_view_get_zoom (ModestMsgView *self); TnyHeaderFlags modest_msg_view_get_priority (ModestMsgView *self); void modest_msg_view_set_priority (ModestMsgView *self, TnyHeaderFlags flags); GList *modest_msg_view_get_selected_attachments (ModestMsgView *self); diff --git a/src/widgets/modest-zoomable.c b/src/widgets/modest-zoomable.c new file mode 100644 index 0000000..72e0eb8 --- /dev/null +++ b/src/widgets/modest-zoomable.c @@ -0,0 +1,130 @@ +/* Copyright (c) 2007, Nokia Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Nokia Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include + +/** + * modest_zoomable_set_zoom: + * @zoomable: a #ModestZoomable instance + * @value: a #gdouble (1.0 is no zoom). + * + * sets the current zoom leven of @zoomable to @value + */ +void +modest_zoomable_set_zoom (ModestZoomable *zoomable, + gdouble value) +{ + MODEST_ZOOMABLE_GET_IFACE (zoomable)->set_zoom_func (zoomable, value); +} + +/** + * modest_zoomable_get_zoom: + * @zoomable: a #ModestZoomable instance + * + * obtains the current zoom level of @zoomable. + * + * Returns: a #gdouble (1.0 is no zoom). + */ +gdouble +modest_zoomable_get_zoom (ModestZoomable *zoomable) +{ + return MODEST_ZOOMABLE_GET_IFACE (zoomable)->get_zoom_func (zoomable); +} + +/** + * modest_zoomable_zoom_plus: + * @zoomable: a #ModestZoomable instance + * + * increases the zoom level, if it can. If not + * it returns %FALSE + * + * Returns: %TRUE if zoom was increased, %FALSE otherwise + */ +gboolean +modest_zoomable_zoom_plus (ModestZoomable *zoomable) +{ + return MODEST_ZOOMABLE_GET_IFACE (zoomable)->zoom_plus_func (zoomable); +} + +/** + * modest_zoomable_zoom_minus: + * @zoomable: a #ModestZoomable instance + * + * decreases the zoom level, if it can. If not + * it returns %FALSE + * + * Returns: %TRUE if zoom was decreased, %FALSE otherwise + */ +gboolean +modest_zoomable_zoom_minus (ModestZoomable *zoomable) +{ + return MODEST_ZOOMABLE_GET_IFACE (zoomable)->zoom_minus_func (zoomable); +} + +static void +modest_zoomable_base_init (gpointer g_class) +{ + static gboolean initialized = FALSE; + + if (!initialized) { + /* create interface signals here. */ + initialized = TRUE; + } +} + +GType +modest_zoomable_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY(type == 0)) + { + static const GTypeInfo info = + { + sizeof (ModestZoomableIface), + modest_zoomable_base_init, /* base_init */ + NULL, /* base_finalize */ + NULL, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + 0, + 0, /* n_preallocs */ + NULL, /* instance_init */ + NULL + }; + + type = g_type_register_static (G_TYPE_INTERFACE, + "ModestZoomable", &info, 0); + + } + + return type; +} diff --git a/src/widgets/modest-zoomable.h b/src/widgets/modest-zoomable.h new file mode 100644 index 0000000..7953a08 --- /dev/null +++ b/src/widgets/modest-zoomable.h @@ -0,0 +1,67 @@ +/* Copyright (c) 2007, Nokia Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Nokia Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MODEST_ZOOMABLE_H +#define MODEST_ZOOMABLE_H + +#include +#include + +G_BEGIN_DECLS + +#define MODEST_TYPE_ZOOMABLE (modest_zoomable_get_type ()) +#define MODEST_ZOOMABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MODEST_TYPE_ZOOMABLE, ModestZoomable)) +#define MODEST_IS_ZOOMABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MODEST_TYPE_ZOOMABLE)) +#define MODEST_ZOOMABLE_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), MODEST_TYPE_ZOOMABLE, ModestZoomableIface)) + +typedef struct _ModestZoomable ModestZoomable; +typedef struct _ModestZoomableIface ModestZoomableIface; + +struct _ModestZoomableIface +{ + GTypeInterface parent; + + void (*set_zoom_func) (ModestZoomable *self, gdouble zoom); + gdouble (*get_zoom_func) (ModestZoomable *self); + gboolean (*zoom_plus_func) (ModestZoomable *self); + gboolean (*zoom_minus_func) (ModestZoomable *self); +}; + +GType modest_zoomable_get_type (void); + +void modest_zoomable_set_zoom (ModestZoomable *zoomable, + gdouble value); +gdouble modest_zoomable_get_zoom (ModestZoomable *zoomable); +gboolean modest_zoomable_zoom_plus (ModestZoomable *zoomable); +gboolean modest_zoomable_zoom_minus (ModestZoomable *zoomable); + + +G_END_DECLS + +#endif -- 1.7.9.5