From cd52c8748afe0d7ef9987994d2f2386c2f53fbee Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Fri, 21 Jul 2006 09:14:50 +0000 Subject: [PATCH] * ModestTnyFolderTreeView => ModestFolderView * ModestTnyHeaderTreeView => ModestHeaderView * ModestTnyMsgView => ModestMsgView * moved these widgets to src/widgets/ * update all dependencies * fixed compiler warnings all over the place pmo-trunk-r405 --- COPYING | 27 + Makefile.am | 2 +- configure.ac | 3 +- src/Makefile.am | 14 +- src/gtk/Makefile.am | 3 +- src/gtk/modest-ui-main-view.c | 72 ++- src/gtk/modest-ui-message-editor.c | 25 +- src/gtk/modest-ui-message-viewer.c | 10 +- src/gtk/modest-ui.c | 18 +- src/gtk2/Makefile.am | 2 +- src/gtk2/modest-account-view-window.c | 4 +- src/gtk2/modest-main-window.c | 47 +- src/gtk2/modest-msg-window.c | 4 +- src/hildon/Makefile.am | 3 +- src/hildon/modest-ui-main-view.c | 65 +-- src/hildon/modest-ui-message-editor.c | 17 +- src/hildon/modest-ui-message-viewer.c | 23 +- src/hildon/modest-ui.c | 20 +- src/hildon/modest-ui_1.c | 1034 --------------------------------- src/modest-account-mgr.c | 2 - src/modest-account-mgr.h | 2 +- src/modest-account-view.c | 313 ---------- src/modest-account-view.h | 72 --- src/modest-editor-window.c | 5 +- src/modest-main.c | 13 +- src/modest-text-utils.c | 13 +- src/modest-tny-account-store.c | 20 +- src/modest-tny-attachment.c | 12 +- src/modest-tny-folder-tree-view.c | 509 ---------------- src/modest-tny-folder-tree-view.h | 118 ---- src/modest-tny-header-tree-view.c | 936 ----------------------------- src/modest-tny-header-tree-view.h | 186 ------ src/modest-tny-msg-actions.c | 2 - src/modest-tny-msg-view.c | 702 ---------------------- src/modest-tny-msg-view.h | 115 ---- src/modest-tny-store-actions.c | 6 +- src/modest-ui.h | 2 +- src/modest-viewer-window.c | 14 +- src/modest-viewer-window.h | 2 +- src/modest-widget-factory.c | 49 +- src/modest-widget-factory.h | 28 +- src/widgets/modest-account-view.c | 307 ++++++++++ src/widgets/modest-account-view.h | 71 +++ src/widgets/modest-folder-view.c | 485 ++++++++++++++++ src/widgets/modest-folder-view.h | 118 ++++ src/widgets/modest-header-view.c | 949 ++++++++++++++++++++++++++++++ src/widgets/modest-header-view.h | 186 ++++++ src/widgets/modest-msg-view.c | 704 ++++++++++++++++++++++ src/widgets/modest-msg-view.h | 113 ++++ 49 files changed, 3214 insertions(+), 4233 deletions(-) delete mode 100644 src/hildon/modest-ui_1.c delete mode 100644 src/modest-account-view.c delete mode 100644 src/modest-account-view.h delete mode 100644 src/modest-tny-folder-tree-view.c delete mode 100644 src/modest-tny-folder-tree-view.h delete mode 100644 src/modest-tny-header-tree-view.c delete mode 100644 src/modest-tny-header-tree-view.h delete mode 100644 src/modest-tny-msg-view.c delete mode 100644 src/modest-tny-msg-view.h create mode 100644 src/widgets/modest-account-view.c create mode 100644 src/widgets/modest-account-view.h create mode 100644 src/widgets/modest-folder-view.c create mode 100644 src/widgets/modest-folder-view.h create mode 100644 src/widgets/modest-header-view.c create mode 100644 src/widgets/modest-header-view.h create mode 100644 src/widgets/modest-msg-view.c create mode 100644 src/widgets/modest-msg-view.h diff --git a/COPYING b/COPYING index 8b13789..042dc50 100644 --- a/COPYING +++ b/COPYING @@ -1 +1,28 @@ +Copyright (c) 2006, 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. diff --git a/Makefile.am b/Makefile.am index 79160e4..9b4d471 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,7 +8,7 @@ SUBDIRS=\ docs EXTRA_DIST=\ - autogen.sh + autogen.sh TODO COPYING CFLAGS=\ -Wall diff --git a/configure.ac b/configure.ac index 839115a..2514b8d 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ dnl configure.ac for modest -dnl Time-stamp: <2006-07-20 17:01:42 (djcb)> +dnl Time-stamp: <2006-07-21 09:30:11 (djcb)> dnl written by Dirk-Jan C. Binnema AC_INIT([modest],[0.0.1],[http://maemo.org]) @@ -63,6 +63,7 @@ src/gtk2/Makefile src/hildon/Makefile src/hildon/com.nokia.modest.service src/hildon/modest.desktop.in +src/widgets/Makefile docs/Makefile docs/reference/Makefile ]) diff --git a/src/Makefile.am b/src/Makefile.am index 9e55bac..2b05f64 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,6 @@ # # Makefile.am -# Time-stamp: <2006-07-19 18:21:49 (djcb)> +# Time-stamp: <2006-07-21 09:29:41 (djcb)> SUBDIRS=$(MODEST_PLATFORM_DIR) DIST_SUBDIRS = gtk gtk2 hildon @@ -38,20 +38,12 @@ modest_SOURCES=\ modest-account-keys.h\ modest-account-mgr.h\ modest-account-mgr.c\ - modest-account-view.h\ - modest-account-view.c\ modest-window-mgr.h\ modest-window-mgr.c\ modest-icon-factory.c\ modest-icon-factory.h\ modest-tny-account-store.h\ modest-tny-account-store.c\ - modest-tny-folder-tree-view.h\ - modest-tny-folder-tree-view.c\ - modest-tny-header-tree-view.h\ - modest-tny-header-tree-view.c\ - modest-tny-msg-view.h\ - modest-tny-msg-view.c\ modest-tny-msg-actions.h\ modest-tny-msg-actions.c\ modest-proto.h\ @@ -86,6 +78,8 @@ modest_LDADD = \ $(MODEST_GSTUFF_LIBS) \ $(MODEST_LIBTINYMAIL_GNOME_DESKTOP_LIBS) \ $(MODEST_LIBTINYMAIL_MAEMO_LIBS) \ - $(MODEST_PLATFORM_DIR)/libmodest-ui.la + $(MODEST_PLATFORM_DIR)/libmodest-ui.la \ + widgets/libmodest-widgets.la + EXTRA_DIST=modest-marshal.list diff --git a/src/gtk/Makefile.am b/src/gtk/Makefile.am index a53db65..69b4bd9 100644 --- a/src/gtk/Makefile.am +++ b/src/gtk/Makefile.am @@ -1,6 +1,6 @@ # # Makefile.am -# Time-stamp: <2006-06-06 14:27:48 (djcb)> +# Time-stamp: <2006-07-21 10:45:41 (djcb)> # # # use Automake 'trick' ==> convenience static libraries, which @@ -9,6 +9,7 @@ INCLUDES=\ $(MODEST_GSTUFF_CFLAGS) \ $(MODEST_LIBTINYMAIL_GNOME_DESKTOP_CFLAGS) \ + -I ${top_srcdir}/src \ -DPREFIX=\"@prefix@\" \ -Wall diff --git a/src/gtk/modest-ui-main-view.c b/src/gtk/modest-ui-main-view.c index b4a8a0a..b6c21c7 100644 --- a/src/gtk/modest-ui-main-view.c +++ b/src/gtk/modest-ui-main-view.c @@ -49,9 +49,9 @@ #include "../modest-identity-mgr.h" #include "../modest-tny-account-store.h" -#include "../modest-tny-folder-tree-view.h" -#include "../modest-tny-header-tree-view.h" -#include "../modest-tny-msg-view.h" +#include "../widgets/modest-folder-view.h" +#include "../widgets/modest-header-view.h" +#include "../widgets/modest-msg-view.h" #include "../modest-tny-transport-actions.h" #include "../modest-tny-store-actions.h" @@ -74,11 +74,11 @@ static GtkWidget* modest_main_window_folder_tree (ModestAccountMgr *modest_acc_m static GtkWidget* modest_main_window_header_tree (TnyMsgFolderIface *folder); -static void on_folder_clicked (ModestTnyFolderTreeView *folder_tree, +static void on_folder_clicked (ModestFolderView *folder_tree, TnyMsgFolderIface *folder, gpointer data); -static void on_message_clicked (ModestTnyFolderTreeView *folder_tree, +static void on_message_clicked (ModestFolderView *folder_tree, TnyMsgIface *message, gpointer data); @@ -94,8 +94,6 @@ static void on_forward_attached_activated (GtkWidget *widget, gpointer user_data static void on_headers_status_update (GtkWidget *header_view, const gchar *msg, gint status, gpointer user_data); -static void on_status_cleanup (gpointer user_data); - static void register_toolbar_callbacks (ModestUI *modest_ui); @@ -168,7 +166,7 @@ modest_ui_show_main_window (ModestUI *modest_ui) g_signal_connect (G_OBJECT(folder_view), "folder_selected", G_CALLBACK(on_folder_clicked), modest_ui); - message_view = GTK_WIDGET(modest_tny_msg_view_new (NULL)); + message_view = GTK_WIDGET(modest_msg_view_new (NULL)); priv->message_view = message_view; if (!message_view) { g_warning ("failed to create message view"); @@ -315,14 +313,14 @@ register_toolbar_callbacks (ModestUI *modest_ui) static void -on_folder_clicked (ModestTnyFolderTreeView *folder_tree, +on_folder_clicked (ModestFolderView *folder_tree, TnyMsgFolderIface *folder, gpointer data) { GtkWidget *win; GtkWidget *button; - ModestTnyHeaderTreeView *tree_view; - ModestTnyMsgView *msg_view; + ModestHeaderView *tree_view; + ModestMsgView *msg_view; ModestUIPrivate *priv; GtkWidget *scrollview; @@ -332,13 +330,13 @@ on_folder_clicked (ModestTnyFolderTreeView *folder_tree, priv = MODEST_UI_GET_PRIVATE(data); scrollview = glade_xml_get_widget (priv->glade_xml,"mail_list"); - tree_view = MODEST_TNY_HEADER_TREE_VIEW (priv->header_view); + tree_view = MODEST_HEADER_VIEW (priv->header_view); win = glade_xml_get_widget (priv->glade_xml, "main"); gtk_window_set_title (GTK_WINDOW(win), tny_msg_folder_iface_get_name(folder)); - modest_tny_header_tree_view_set_folder (tree_view, folder); + modest_header_view_set_folder (tree_view, folder); priv->current_folder = folder; button = glade_xml_get_widget (priv->glade_xml, "toolb_reply"); @@ -356,28 +354,28 @@ on_folder_clicked (ModestTnyFolderTreeView *folder_tree, gtk_widget_set_sensitive(button, FALSE); } - msg_view = MODEST_TNY_MSG_VIEW (priv->message_view); + msg_view = MODEST_MSG_VIEW (priv->message_view); g_return_if_fail (msg_view); - modest_tny_msg_view_set_message (msg_view, NULL); + modest_msg_view_set_message (msg_view, NULL); } static void -on_message_clicked (ModestTnyFolderTreeView *folder_tree, - TnyMsgIface *message, - gpointer data) +on_message_clicked (ModestFolderView *folder_tree, + TnyMsgIface *message, + gpointer data) { GtkWidget *button; - ModestTnyMsgView *msg_view; + ModestMsgView *msg_view; ModestUIPrivate *priv; g_return_if_fail (data); priv = MODEST_UI_GET_PRIVATE (data); - msg_view = MODEST_TNY_MSG_VIEW (priv->message_view); + msg_view = MODEST_MSG_VIEW (priv->message_view); - modest_tny_msg_view_set_message (msg_view, message); + modest_msg_view_set_message (msg_view, message); button = glade_xml_get_widget (priv->glade_xml, "toolb_reply"); if (button) { @@ -400,19 +398,19 @@ modest_main_window_header_tree (TnyMsgFolderIface *folder) int i; GSList *columns = NULL; GtkWidget *header_tree; - ModestTnyHeaderTreeViewColumn cols[] = { - MODEST_TNY_HEADER_TREE_VIEW_COLUMN_MSGTYPE, - MODEST_TNY_HEADER_TREE_VIEW_COLUMN_ATTACH, - MODEST_TNY_HEADER_TREE_VIEW_COLUMN_FROM, - MODEST_TNY_HEADER_TREE_VIEW_COLUMN_SUBJECT, - MODEST_TNY_HEADER_TREE_VIEW_COLUMN_RECEIVED_DATE + ModestHeaderViewColumn cols[] = { + MODEST_HEADER_VIEW_COLUMN_MSGTYPE, + MODEST_HEADER_VIEW_COLUMN_ATTACH, + MODEST_HEADER_VIEW_COLUMN_FROM, + MODEST_HEADER_VIEW_COLUMN_SUBJECT, + MODEST_HEADER_VIEW_COLUMN_RECEIVED_DATE }; - for (i = 0 ; i != sizeof(cols) / sizeof(ModestTnyHeaderTreeViewColumn); ++i) + for (i = 0 ; i != sizeof(cols) / sizeof(ModestHeaderViewColumn); ++i) columns = g_slist_append (columns, GINT_TO_POINTER(cols[i])); - header_tree = GTK_WIDGET(modest_tny_header_tree_view_new(folder, columns, - MODEST_TNY_HEADER_TREE_VIEW_STYLE_NORMAL)); + header_tree = GTK_WIDGET(modest_header_view_new(folder, columns, + MODEST_HEADER_VIEW_STYLE_NORMAL)); g_slist_free (columns); if (!header_tree) { @@ -430,7 +428,7 @@ modest_main_window_folder_tree (ModestAccountMgr *modest_acc_mgr, { GtkWidget *folder_tree; - folder_tree = GTK_WIDGET (modest_tny_folder_tree_view_new (account_store)); + folder_tree = GTK_WIDGET (modest_folder_view_new (account_store)); if (!folder_tree) { g_warning ("could not create folder list"); return NULL; @@ -467,18 +465,18 @@ on_delete_clicked (GtkWidget *widget, gpointer user_data) GtkTreeIter iter; GtkTreeModel *mymodel; - ModestTnyHeaderTreeView *header_view; - ModestTnyMsgView *msg_view; + ModestHeaderView *header_view; + ModestMsgView *msg_view; ModestUIPrivate *priv; g_return_if_fail (modest_ui); priv = MODEST_UI_GET_PRIVATE(modest_ui); - msg_view = MODEST_TNY_MSG_VIEW(priv->message_view); + msg_view = MODEST_MSG_VIEW(priv->message_view); g_return_if_fail (msg_view); - header_view = MODEST_TNY_HEADER_TREE_VIEW(priv->header_view); + header_view = MODEST_HEADER_VIEW(priv->header_view); g_return_if_fail (header_view); sel = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view)); @@ -550,8 +548,8 @@ on_sendreceive_button_clicked (GtkWidget *widget, gpointer user_data) if (priv->header_view && priv->current_folder) { - modest_tny_header_tree_view_set_folder (MODEST_TNY_HEADER_TREE_VIEW(priv->header_view), - priv->current_folder); + modest_header_view_set_folder (MODEST_HEADER_VIEW(priv->header_view), + priv->current_folder); gtk_widget_queue_draw (priv->header_view); } } diff --git a/src/gtk/modest-ui-message-editor.c b/src/gtk/modest-ui-message-editor.c index 015b2b1..96d3690 100644 --- a/src/gtk/modest-ui-message-editor.c +++ b/src/gtk/modest-ui-message-editor.c @@ -49,9 +49,9 @@ #include "../modest-identity-mgr.h" #include "../modest-tny-account-store.h" -#include "../modest-tny-folder-tree-view.h" -#include "../modest-tny-header-tree-view.h" -#include "../modest-tny-msg-view.h" +#include "../widgets/modest-folder-view.h" +#include "../widgets/modest-header-view.h" +#include "../widgets/modest-msg-view.h" #include "../modest-tny-transport-actions.h" #include "../modest-tny-store-actions.h" @@ -381,8 +381,8 @@ quoted_send_msg (ModestUI *modest_ui, quoted_send_type qstype) TnyMsgHeaderIface *header; - ModestTnyHeaderTreeView *header_view; - ModestTnyMsgView *msg_view; + ModestHeaderView *header_view; + ModestMsgView *msg_view; ModestUIPrivate *priv; const TnyMsgIface *msg; @@ -399,10 +399,10 @@ quoted_send_msg (ModestUI *modest_ui, quoted_send_type qstype) priv = MODEST_UI_GET_PRIVATE(modest_ui); - msg_view = MODEST_TNY_MSG_VIEW(priv->message_view); + msg_view = MODEST_MSG_VIEW(priv->message_view); g_return_if_fail (msg_view); - header_view = MODEST_TNY_HEADER_TREE_VIEW(priv->header_view); + header_view = MODEST_HEADER_VIEW(priv->header_view); g_return_if_fail (header_view); sel = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view)); @@ -440,23 +440,26 @@ quoted_send_msg (ModestUI *modest_ui, quoted_send_type qstype) from = tny_msg_header_iface_get_from(header); sent_date = tny_msg_header_iface_get_date_sent(header); - unquoted = modest_tny_msg_view_get_selected_text(msg_view); + unquoted = modest_msg_view_get_selected_text(msg_view); quoted = modest_tny_msg_actions_quote(msg, from, sent_date, line_limit, unquoted); switch (qstype) { case QUOTED_SEND_REPLY: g_string_prepend(re_sub, _("Re: ")); - new_editor_with_presets(modest_ui, from, /* cc */ "", /* bcc */ "", re_sub->str, quoted, attachments); + new_editor_with_presets(modest_ui, from, /* cc */ "", /* bcc */ "", + re_sub->str, quoted, attachments); break; case QUOTED_SEND_FORWARD: attachments = modest_tny_attachment_new_list_from_msg(msg, FALSE); g_string_prepend(re_sub, _("Fwd: ")); - new_editor_with_presets(modest_ui, /* from */ "", /* cc */ "", /* bcc */ "", re_sub->str, quoted, attachments); + new_editor_with_presets(modest_ui, /* from */ "", /* cc */ "", + /* bcc */ "", re_sub->str, quoted, attachments); break; case QUOTED_SEND_FORWARD_ATTACHED: attachments = modest_tny_attachment_new_list_from_msg(msg, TRUE); g_string_prepend(re_sub, _("Fwd: ")); - new_editor_with_presets(modest_ui, /* from */ "", /* cc */ "", /* bcc */ "", re_sub->str, "", attachments); + new_editor_with_presets(modest_ui, /* from */ "", /* cc */ "", + /* bcc */ "", re_sub->str, "", attachments); break; default: break; diff --git a/src/gtk/modest-ui-message-viewer.c b/src/gtk/modest-ui-message-viewer.c index d778daf..5406e7a 100644 --- a/src/gtk/modest-ui-message-viewer.c +++ b/src/gtk/modest-ui-message-viewer.c @@ -48,9 +48,9 @@ #include "../modest-identity-mgr.h" #include "../modest-tny-account-store.h" -#include "../modest-tny-folder-tree-view.h" -#include "../modest-tny-header-tree-view.h" -#include "../modest-tny-msg-view.h" +#include "../widgets/modest-folder-view.h" +#include "../widgets/modest-header-view.h" +#include "../widgets/modest-msg-view.h" #include "../modest-tny-transport-actions.h" #include "../modest-tny-store-actions.h" @@ -134,7 +134,7 @@ open_message_viewer_window(ModestUI *modest_ui) GtkTreeModel *model; GtkTreeIter iter; GtkScrolledWindow *scroll; - ModestTnyHeaderTreeView *header_view; + ModestHeaderView *header_view; TnyMsgHeaderIface *header; const TnyMsgFolderIface *folder; TnyMsgIface *msg; @@ -154,7 +154,7 @@ open_message_viewer_window(ModestUI *modest_ui) scroll = GTK_SCROLLED_WINDOW(gtk_paned_get_child1 (GTK_PANED(paned))); g_return_if_fail (scroll); - header_view = MODEST_TNY_HEADER_TREE_VIEW(gtk_bin_get_child (GTK_BIN(scroll))); + header_view = MODEST_HEADER_VIEW(gtk_bin_get_child (GTK_BIN(scroll))); g_return_if_fail (header_view); sel = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view)); diff --git a/src/gtk/modest-ui.c b/src/gtk/modest-ui.c index 5052e51..53c302f 100644 --- a/src/gtk/modest-ui.c +++ b/src/gtk/modest-ui.c @@ -47,9 +47,9 @@ #include "../modest-identity-mgr.h" #include "../modest-tny-account-store.h" -#include "../modest-tny-folder-tree-view.h" -#include "../modest-tny-header-tree-view.h" -#include "../modest-tny-msg-view.h" +#include "../widgets/modest-folder-view.h" +#include "../widgets/modest-header-view.h" +#include "../widgets/modest-msg-view.h" #include "../modest-tny-transport-actions.h" #include "../modest-tny-store-actions.h" @@ -65,8 +65,6 @@ static void modest_ui_class_init (ModestUIClass *klass); static void modest_ui_init (ModestUI *obj); static void modest_ui_finalize (GObject *obj); - -static void modest_ui_window_destroy (GtkWidget *win, GdkEvent *event, gpointer data); static void modest_ui_last_window_closed (GObject *obj, gpointer data); gchar *on_password_requested (TnyAccountIface *, const gchar *, gboolean *); @@ -165,14 +163,14 @@ on_accounts_reloaded (ModestTnyAccountStore *account_store, gpointer user_data) { ModestUIPrivate *priv = user_data; - g_return_if_fail (MODEST_IS_TNY_FOLDER_TREE_VIEW (priv->folder_view)); - g_return_if_fail (MODEST_IS_TNY_HEADER_TREE_VIEW (priv->header_view)); + g_return_if_fail (MODEST_IS_FOLDER_VIEW (priv->folder_view)); + g_return_if_fail (MODEST_IS_HEADER_VIEW (priv->header_view)); - modest_tny_header_tree_view_set_folder (MODEST_TNY_HEADER_TREE_VIEW(priv->header_view), + modest_header_view_set_folder (MODEST_HEADER_VIEW(priv->header_view), NULL); - modest_tny_folder_tree_view_update_model(MODEST_TNY_FOLDER_TREE_VIEW(priv->folder_view), - TNY_ACCOUNT_STORE_IFACE(account_store)); + modest_folder_view_update_model(MODEST_FOLDER_VIEW(priv->folder_view), + TNY_ACCOUNT_STORE_IFACE(account_store)); } diff --git a/src/gtk2/Makefile.am b/src/gtk2/Makefile.am index 00822ed..07b7508 100644 --- a/src/gtk2/Makefile.am +++ b/src/gtk2/Makefile.am @@ -9,7 +9,7 @@ INCLUDES=\ $(MODEST_GSTUFF_CFLAGS) \ $(MODEST_LIBTINYMAIL_GNOME_DESKTOP_CFLAGS) \ - -I ${top_srcdir}/src + -I ${top_srcdir}/src \ -DPREFIX=\"@prefix@\" \ -Wall diff --git a/src/gtk2/modest-account-view-window.c b/src/gtk2/modest-account-view-window.c index 37be559..030b463 100644 --- a/src/gtk2/modest-account-view-window.c +++ b/src/gtk2/modest-account-view-window.c @@ -180,7 +180,7 @@ button_box_new (ModestAccountViewWindow *self) { GtkWidget *button_box; - GtkWidget *add_button, *remove_button, *edit_button, *close_button; + GtkWidget *add_button, *remove_button, *edit_button; ModestAccountViewWindowPrivate *priv; priv = MODEST_ACCOUNT_VIEW_WINDOW_GET_PRIVATE(self); @@ -232,7 +232,7 @@ window_vbox_new (ModestAccountViewWindow *self) main_vbox = gtk_vbox_new (FALSE, 6); main_hbox = gtk_hbox_new (FALSE, 6); - account_view = modest_widget_factory_get_account_view_widget (priv->widget_factory); + account_view = modest_widget_factory_get_account_view (priv->widget_factory); sel = gtk_tree_view_get_selection (GTK_TREE_VIEW(account_view)); g_signal_connect (G_OBJECT(sel), "changed", G_CALLBACK(on_selection_changed), diff --git a/src/gtk2/modest-main-window.c b/src/gtk2/modest-main-window.c index 301453c..16bc5a7 100644 --- a/src/gtk2/modest-main-window.c +++ b/src/gtk2/modest-main-window.c @@ -55,9 +55,9 @@ struct _ModestMainWindowPrivate { ModestWidgetFactory *widget_factory; ModestConf *conf; - ModestTnyHeaderTreeView *header_view; - ModestTnyFolderTreeView *folder_view; - ModestTnyMsgView *msg_preview; + ModestHeaderView *header_view; + ModestFolderView *folder_view; + ModestMsgView *msg_preview; }; @@ -166,7 +166,6 @@ on_menu_accounts (ModestMainWindow *self, guint action, GtkWidget *widget) { GtkWidget *account_win; ModestMainWindowPrivate *priv; - ModestAccountMgr *account_mgr; g_return_if_fail (widget); g_return_if_fail (self); @@ -259,28 +258,28 @@ menubar_new (ModestMainWindow *self) -static ModestTnyHeaderTreeView* +static ModestHeaderView* header_view_new (ModestMainWindow *self) { int i; GSList *columns = NULL; - ModestTnyHeaderTreeView *header_view; + ModestHeaderView *header_view; ModestMainWindowPrivate *priv; - ModestTnyHeaderTreeViewColumn cols[] = { - MODEST_TNY_HEADER_TREE_VIEW_COLUMN_MSGTYPE, - MODEST_TNY_HEADER_TREE_VIEW_COLUMN_ATTACH, - MODEST_TNY_HEADER_TREE_VIEW_COLUMN_FROM, - MODEST_TNY_HEADER_TREE_VIEW_COLUMN_SUBJECT, - MODEST_TNY_HEADER_TREE_VIEW_COLUMN_RECEIVED_DATE + ModestHeaderViewColumn cols[] = { + MODEST_HEADER_VIEW_COLUMN_MSGTYPE, + MODEST_HEADER_VIEW_COLUMN_ATTACH, + MODEST_HEADER_VIEW_COLUMN_FROM, + MODEST_HEADER_VIEW_COLUMN_SUBJECT, + MODEST_HEADER_VIEW_COLUMN_RECEIVED_DATE }; priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self); - for (i = 0 ; i != sizeof(cols) / sizeof(ModestTnyHeaderTreeViewColumn); ++i) + for (i = 0 ; i != sizeof(cols) / sizeof(ModestHeaderViewColumn); ++i) columns = g_slist_append (columns, GINT_TO_POINTER(cols[i])); - header_view = modest_widget_factory_get_header_tree_widget (priv->widget_factory); - modest_tny_header_tree_view_set_columns (header_view, columns); + header_view = modest_widget_factory_get_header_view (priv->widget_factory); + modest_header_view_set_columns (header_view, columns); g_slist_free (columns); return header_view; @@ -345,20 +344,6 @@ set_sizes (ModestMainWindow *self) -static void -save_sizes (ModestMainWindow *self, ModestConf *conf) -{ - ModestMainWindowPrivate *priv; - - int x,y; - - priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self); - - -} - - - static GtkWidget* wrapped_in_scrolled_window (GtkWidget *widget, gboolean needs_viewport) { @@ -403,9 +388,9 @@ modest_main_window_new (ModestWidgetFactory *factory, ModestConf *conf) priv->conf = conf; /* widgets from factory */ - priv->folder_view = modest_widget_factory_get_folder_tree_widget (factory); + priv->folder_view = modest_widget_factory_get_folder_view (factory); priv->header_view = header_view_new (MODEST_MAIN_WINDOW(obj)); - priv->msg_preview = modest_widget_factory_get_msg_preview_widget (factory); + priv->msg_preview = modest_widget_factory_get_msg_preview (factory); folder_win = wrapped_in_scrolled_window (GTK_WIDGET(priv->folder_view), FALSE); diff --git a/src/gtk2/modest-msg-window.c b/src/gtk2/modest-msg-window.c index 072c704..7b8c008 100644 --- a/src/gtk2/modest-msg-window.c +++ b/src/gtk2/modest-msg-window.c @@ -27,7 +27,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include #include "modest-msg-window.h" /* 'private'/'protected' functions */ @@ -131,7 +131,7 @@ modest_msg_window_init (ModestMsgWindow *obj) gtk_table_attach_defaults (GTK_TABLE(header_table), bcc_field, 1,2,2,3); gtk_table_attach_defaults (GTK_TABLE(header_table), subject_field, 1,2,3,4); - msg_field = modest_tny_msg_view_new (NULL); + msg_field = modest_msg_view_new (NULL); main_vbox = gtk_vbox_new (FALSE, 6); diff --git a/src/hildon/Makefile.am b/src/hildon/Makefile.am index aded4ef..c555e96 100644 --- a/src/hildon/Makefile.am +++ b/src/hildon/Makefile.am @@ -1,6 +1,6 @@ # # Makefile.am -# Time-stamp: <2006-06-06 14:27:48 (djcb)> +# Time-stamp: <2006-07-21 11:12:44 (djcb)> # # # use Automake 'trick' ==> convenience static libraries, which @@ -10,6 +10,7 @@ INCLUDES=\ $(MODEST_GSTUFF_CFLAGS) \ $(MODEST_LIBTINYMAIL_GNOME_DESKTOP_CFLAGS) \ $(MODEST_LIBTINYMAIL_MAEMO_CFLAGS) \ + -I ${top_srcdir}/src \ -DPREFIX=\"@prefix@\" \ -Wall diff --git a/src/hildon/modest-ui-main-view.c b/src/hildon/modest-ui-main-view.c index 9be32f3..06ce055 100644 --- a/src/hildon/modest-ui-main-view.c +++ b/src/hildon/modest-ui-main-view.c @@ -53,9 +53,9 @@ #include "../modest-identity-mgr.h" #include "../modest-tny-account-store.h" -#include "../modest-tny-folder-tree-view.h" -#include "../modest-tny-header-tree-view.h" -#include "../modest-tny-msg-view.h" +#include "../widgets/modest-folder-view.h" +#include "../widgets/modest-header-view.h" +#include "../widgets/modest-msg-view.h" #include "../modest-tny-transport-actions.h" #include "../modest-tny-store-actions.h" @@ -78,11 +78,11 @@ static GtkWidget* modest_main_window_folder_tree (ModestAccountMgr *modest_acc_m static GtkWidget* modest_main_window_header_tree (TnyMsgFolderIface *folder); -static void on_folder_clicked (ModestTnyFolderTreeView *folder_tree, +static void on_folder_clicked (ModestFolderView *folder_tree, TnyMsgFolderIface *folder, gpointer data); -static void on_message_clicked (ModestTnyFolderTreeView *folder_tree, +static void on_message_clicked (ModestFolderView *folder_tree, TnyMsgIface *message, gpointer data); @@ -100,7 +100,6 @@ static void on_forward_attached_activated (GtkWidget *widget, gpointer user_data static void on_headers_status_update (GtkWidget *header_view, const gchar *msg, gint status, gpointer user_data); -static void on_status_cleanup (gpointer user_data); static void register_toolbar_callbacks (ModestUI *modest_ui); @@ -185,7 +184,7 @@ modest_ui_show_main_window (ModestUI *modest_ui) show_attachments_inline = FALSE; - message_view = GTK_WIDGET(modest_tny_msg_view_new (NULL)); + message_view = GTK_WIDGET(modest_msg_view_new (NULL)); priv->message_view = message_view; if (!message_view) { g_warning ("failed to create message view"); @@ -366,14 +365,14 @@ register_toolbar_callbacks (ModestUI *modest_ui) static void -on_folder_clicked (ModestTnyFolderTreeView *folder_tree, +on_folder_clicked (ModestFolderView *folder_tree, TnyMsgFolderIface *folder, gpointer data) { GtkWidget *win; GtkWidget *button; - ModestTnyHeaderTreeView *tree_view; - ModestTnyMsgView *msg_view; + ModestHeaderView *tree_view; + ModestMsgView *msg_view; ModestUIPrivate *priv; GtkWidget *scrollview; @@ -383,13 +382,13 @@ on_folder_clicked (ModestTnyFolderTreeView *folder_tree, priv = MODEST_UI_GET_PRIVATE(data); scrollview = glade_xml_get_widget (priv->glade_xml,"mail_list"); - tree_view = MODEST_TNY_HEADER_TREE_VIEW (priv->header_view); + tree_view = MODEST_HEADER_VIEW (priv->header_view); win = glade_xml_get_widget (priv->glade_xml, "main"); gtk_window_set_title (GTK_WINDOW(win), tny_msg_folder_iface_get_name(folder)); - modest_tny_header_tree_view_set_folder (tree_view, folder); + modest_header_view_set_folder (tree_view, folder); priv->current_folder = folder; button = glade_xml_get_widget (priv->glade_xml, "toolb_reply"); @@ -407,28 +406,28 @@ on_folder_clicked (ModestTnyFolderTreeView *folder_tree, gtk_widget_set_sensitive(button, FALSE); } - msg_view = MODEST_TNY_MSG_VIEW (priv->message_view); + msg_view = MODEST_MSG_VIEW (priv->message_view); g_return_if_fail (msg_view); - modest_tny_msg_view_set_message (msg_view, NULL); + modest_msg_view_set_message (msg_view, NULL); } static void -on_message_clicked (ModestTnyFolderTreeView *folder_tree, +on_message_clicked (ModestFolderView *folder_tree, TnyMsgIface *message, gpointer data) { GtkWidget *button; - ModestTnyMsgView *msg_view; + ModestMsgView *msg_view; ModestUIPrivate *priv; g_return_if_fail (data); priv = MODEST_UI_GET_PRIVATE (data); - msg_view = MODEST_TNY_MSG_VIEW (priv->message_view); + msg_view = MODEST_MSG_VIEW (priv->message_view); - modest_tny_msg_view_set_message (msg_view, message); + modest_msg_view_set_message (msg_view, message); button = glade_xml_get_widget (priv->glade_xml, "toolb_reply"); if (button) { @@ -451,17 +450,17 @@ modest_main_window_header_tree (TnyMsgFolderIface *folder) int i; GSList *columns = NULL; GtkWidget *header_tree; - ModestTnyHeaderTreeViewColumn cols[] = { - MODEST_TNY_HEADER_TREE_VIEW_COLUMN_MSGTYPE, - MODEST_TNY_HEADER_TREE_VIEW_COLUMN_ATTACH, - MODEST_TNY_HEADER_TREE_VIEW_COLUMN_COMPACT_HEADER + ModestHeaderViewColumn cols[] = { + MODEST_HEADER_VIEW_COLUMN_MSGTYPE, + MODEST_HEADER_VIEW_COLUMN_ATTACH, + MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER }; - for (i = 0 ; i != sizeof(cols) / sizeof(ModestTnyHeaderTreeViewColumn); ++i) + for (i = 0 ; i != sizeof(cols) / sizeof(ModestHeaderViewColumn); ++i) columns = g_slist_append (columns, GINT_TO_POINTER(cols[i])); - header_tree = GTK_WIDGET(modest_tny_header_tree_view_new(folder, columns, - MODEST_TNY_HEADER_TREE_VIEW_STYLE_NORMAL)); + header_tree = GTK_WIDGET(modest_header_view_new(folder, columns, + MODEST_HEADER_VIEW_STYLE_NORMAL)); g_slist_free (columns); if (!header_tree) { @@ -479,7 +478,7 @@ modest_main_window_folder_tree (ModestAccountMgr *modest_acc_mgr, { GtkWidget *folder_tree; - folder_tree = GTK_WIDGET (modest_tny_folder_tree_view_new (account_store)); + folder_tree = GTK_WIDGET (modest_folder_view_new (account_store)); if (!folder_tree) { g_warning ("could not create folder list"); return NULL; @@ -512,7 +511,7 @@ on_view_attachments_toggled(GtkWidget *widget, gpointer user_data) { ModestUI *modest_ui = (ModestUI *)user_data; GtkWidget *view_attachments_item; - ModestTnyMsgView *msg_view; + ModestMsgView *msg_view; ModestUIPrivate *priv; gboolean view_attachments_inline; @@ -520,7 +519,7 @@ on_view_attachments_toggled(GtkWidget *widget, gpointer user_data) view_attachments_item = glade_xml_get_widget (priv->glade_xml, "menu_view_attachments"); g_return_if_fail(view_attachments_item); - msg_view = MODEST_TNY_MSG_VIEW(priv->message_view); + msg_view = MODEST_MSG_VIEW(priv->message_view); view_attachments_inline = gtk_check_menu_item_get_active( GTK_CHECK_MENU_ITEM(view_attachments_item)); @@ -536,18 +535,18 @@ on_delete_clicked (GtkWidget *widget, gpointer user_data) GtkTreeIter iter; GtkTreeModel *mymodel; - ModestTnyHeaderTreeView *header_view; - ModestTnyMsgView *msg_view; + ModestHeaderView *header_view; + ModestMsgView *msg_view; ModestUIPrivate *priv; g_return_if_fail (modest_ui); priv = MODEST_UI_GET_PRIVATE(modest_ui); - msg_view = MODEST_TNY_MSG_VIEW(priv->message_view); + msg_view = MODEST_MSG_VIEW(priv->message_view); g_return_if_fail (msg_view); - header_view = MODEST_TNY_HEADER_TREE_VIEW(priv->header_view); + header_view = MODEST_HEADER_VIEW(priv->header_view); g_return_if_fail (header_view); sel = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view)); @@ -611,7 +610,7 @@ on_sendreceive_button_clicked (GtkWidget *widget, gpointer user_data) if (priv->header_view && priv->current_folder) { - modest_tny_header_tree_view_set_folder (MODEST_TNY_HEADER_TREE_VIEW(priv->header_view), + modest_header_view_set_folder (MODEST_HEADER_VIEW(priv->header_view), priv->current_folder); gtk_widget_queue_draw (priv->header_view); } diff --git a/src/hildon/modest-ui-message-editor.c b/src/hildon/modest-ui-message-editor.c index d0d6170..a3c0172 100644 --- a/src/hildon/modest-ui-message-editor.c +++ b/src/hildon/modest-ui-message-editor.c @@ -43,6 +43,7 @@ /* TODO: put in auto* */ #include #include +#include #include "../modest-ui.h" #include "../modest-window-mgr.h" @@ -51,9 +52,9 @@ #include "../modest-identity-mgr.h" #include "../modest-tny-account-store.h" -#include "../modest-tny-folder-tree-view.h" -#include "../modest-tny-header-tree-view.h" -#include "../modest-tny-msg-view.h" +#include "../widgets/modest-folder-view.h" +#include "../widgets/modest-header-view.h" +#include "../widgets/modest-msg-view.h" #include "../modest-tny-transport-actions.h" #include "../modest-tny-store-actions.h" @@ -412,8 +413,8 @@ quoted_send_msg (ModestUI *modest_ui, quoted_send_type qstype) TnyMsgHeaderIface *header; - ModestTnyHeaderTreeView *header_view; - ModestTnyMsgView *msg_view; + ModestHeaderView *header_view; + ModestMsgView *msg_view; ModestUIPrivate *priv; const TnyMsgIface *msg; @@ -430,10 +431,10 @@ quoted_send_msg (ModestUI *modest_ui, quoted_send_type qstype) priv = MODEST_UI_GET_PRIVATE(modest_ui); - msg_view = MODEST_TNY_MSG_VIEW(priv->message_view); + msg_view = MODEST_MSG_VIEW(priv->message_view); g_return_if_fail (msg_view); - header_view = MODEST_TNY_HEADER_TREE_VIEW(priv->header_view); + header_view = MODEST_HEADER_VIEW(priv->header_view); g_return_if_fail (header_view); sel = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view)); @@ -471,7 +472,7 @@ quoted_send_msg (ModestUI *modest_ui, quoted_send_type qstype) from = tny_msg_header_iface_get_from(header); sent_date = tny_msg_header_iface_get_date_sent(header); - unquoted = modest_tny_msg_view_get_selected_text(msg_view); + unquoted = modest_msg_view_get_selected_text(msg_view); quoted = modest_tny_msg_actions_quote(msg, from, sent_date, line_limit, unquoted); switch (qstype) { diff --git a/src/hildon/modest-ui-message-viewer.c b/src/hildon/modest-ui-message-viewer.c index d778daf..3cdc161 100644 --- a/src/hildon/modest-ui-message-viewer.c +++ b/src/hildon/modest-ui-message-viewer.c @@ -48,9 +48,9 @@ #include "../modest-identity-mgr.h" #include "../modest-tny-account-store.h" -#include "../modest-tny-folder-tree-view.h" -#include "../modest-tny-header-tree-view.h" -#include "../modest-tny-msg-view.h" +#include "../widgets/modest-folder-view.h" +#include "../widgets/modest-header-view.h" +#include "../widgets/modest-msg-view.h" #include "../modest-tny-transport-actions.h" #include "../modest-tny-store-actions.h" @@ -121,6 +121,15 @@ close_viewer_window(GtkWidget *win, GdkEvent *event, gpointer data) gtk_widget_destroy(GTK_WIDGET(viewer_win)); } +/* just to prevent warnings: + * warning: `%x' yields only last 2 digits of year in some locales + */ +static size_t +my_strftime(char *s, size_t max, const char *fmt, const + struct tm *tm) { + return strftime(s, max, fmt, tm); +} + static void open_message_viewer_window(ModestUI *modest_ui) @@ -134,7 +143,7 @@ open_message_viewer_window(ModestUI *modest_ui) GtkTreeModel *model; GtkTreeIter iter; GtkScrolledWindow *scroll; - ModestTnyHeaderTreeView *header_view; + ModestHeaderView *header_view; TnyMsgHeaderIface *header; const TnyMsgFolderIface *folder; TnyMsgIface *msg; @@ -154,7 +163,7 @@ open_message_viewer_window(ModestUI *modest_ui) scroll = GTK_SCROLLED_WINDOW(gtk_paned_get_child1 (GTK_PANED(paned))); g_return_if_fail (scroll); - header_view = MODEST_TNY_HEADER_TREE_VIEW(gtk_bin_get_child (GTK_BIN(scroll))); + header_view = MODEST_HEADER_VIEW(gtk_bin_get_child (GTK_BIN(scroll))); g_return_if_fail (header_view); sel = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view)); @@ -193,8 +202,8 @@ open_message_viewer_window(ModestUI *modest_ui) from = tny_msg_header_iface_get_from(header); to = tny_msg_header_iface_get_to(header); sent_date = tny_msg_header_iface_get_date_sent(header); - strftime (date_str, 100, "%c", localtime (&sent_date)); - + my_strftime (date_str, 100, "%c", localtime (&sent_date)); + w = glade_xml_get_widget (windata->glade_xml, "from"); gtk_label_set_text(GTK_LABEL(w), from); w = glade_xml_get_widget (windata->glade_xml, "to"); diff --git a/src/hildon/modest-ui.c b/src/hildon/modest-ui.c index 47599d9..970c2fb 100644 --- a/src/hildon/modest-ui.c +++ b/src/hildon/modest-ui.c @@ -39,17 +39,17 @@ /* TODO: put in auto* */ #include #include +#include #include "../modest-ui.h" #include "../modest-window-mgr.h" #include "../modest-account-mgr.h" -#include "../modest-account-mgr.h" #include "../modest-identity-mgr.h" #include "../modest-tny-account-store.h" -#include "../modest-tny-folder-tree-view.h" -#include "../modest-tny-header-tree-view.h" -#include "../modest-tny-msg-view.h" +#include "../widgets/modest-folder-view.h" +#include "../widgets/modest-header-view.h" +#include "../widgets/modest-msg-view.h" #include "../modest-tny-transport-actions.h" #include "../modest-tny-store-actions.h" @@ -166,14 +166,14 @@ on_accounts_reloaded (ModestTnyAccountStore *account_store, gpointer user_data) { ModestUIPrivate *priv = user_data; - g_return_if_fail (MODEST_IS_TNY_FOLDER_TREE_VIEW (priv->folder_view)); - g_return_if_fail (MODEST_IS_TNY_HEADER_TREE_VIEW (priv->header_view)); - - modest_tny_header_tree_view_set_folder (MODEST_TNY_HEADER_TREE_VIEW(priv->header_view), + g_return_if_fail (MODEST_IS_FOLDER_VIEW (priv->folder_view)); + g_return_if_fail (MODEST_IS_HEADER_VIEW (priv->header_view)); + + modest_header_view_set_folder (MODEST_HEADER_VIEW(priv->header_view), NULL); - modest_tny_folder_tree_view_update_model(MODEST_TNY_FOLDER_TREE_VIEW(priv->folder_view), - TNY_ACCOUNT_STORE(account_store)); + modest_folder_view_update_model(MODEST_FOLDER_VIEW(priv->folder_view), + TNY_ACCOUNT_STORE_IFACE(account_store)); } diff --git a/src/hildon/modest-ui_1.c b/src/hildon/modest-ui_1.c deleted file mode 100644 index 375e9ce..0000000 --- a/src/hildon/modest-ui_1.c +++ /dev/null @@ -1,1034 +0,0 @@ -/* modest-ui.c */ - -/* insert (c)/licensing information) */ - -#include -#include -#include -#include - -/* TODO: put in auto* */ -#include - -#ifdef HAVE_CONFIG_H -#include -#endif /*HAVE_CONFIG_H*/ - -#include "../modest-ui.h" -#include "../modest-window-mgr.h" -#include "../modest-account-mgr.h" - -#include "../modest-tny-account-store.h" -#include "../modest-tny-folder-tree-view.h" -#include "../modest-tny-header-tree-view.h" -#include "../modest-tny-msg-view.h" -#include "../modest-tny-transport-actions.h" - - -#define MODEST_GLADE PREFIX "/share/modest/glade/modest.glade" -#define MODEST_GLADE_MAIN_WIN "main" -#define MODEST_GLADE_EDIT_WIN "new_mail" - - -/* 'private'/'protected' functions */ -static void modest_ui_class_init (ModestUIClass *klass); -static void modest_ui_init (ModestUI *obj); -static void modest_ui_finalize (GObject *obj); - -static void modest_ui_window_destroy (GtkWidget *win, gpointer data); -static void modest_ui_last_window_closed (GObject *obj, gpointer data); - -static GtkWidget* modest_main_window_toolbar (void); -static GtkWidget* modest_main_window_folder_tree (ModestAccountMgr *modest_acc_mgr, - TnyAccountStoreIface *account_store); -static GtkWidget* modest_main_window_header_tree (TnyMsgFolderIface *folder); - - -void on_account_settings1_activate (GtkMenuItem *, - gpointer); -static void on_password_requested (ModestTnyAccountStore *account_store, - const gchar *account_name, gpointer user_data); - -static void on_folder_clicked (ModestTnyFolderTreeView *folder_tree, - TnyMsgFolderIface *folder, - gpointer data); -static void on_message_clicked (ModestTnyFolderTreeView *folder_tree, - TnyMsgIface *message, - gpointer data); -static void on_new_mail_clicked (GtkWidget *widget, ModestUI *modest_ui); - -static void on_reply_clicked (GtkWidget *widget, ModestUI *modest_ui); - -static void on_send_button_clicked (GtkWidget *widget, ModestUI *modest_ui); - -static void register_toolbar_callbacks (ModestUI *modest_ui); - - -/* list my signals */ -enum { - /* MY_SIGNAL_1, */ - /* MY_SIGNAL_2, */ - LAST_SIGNAL -}; - - -typedef struct _ModestUIPrivate ModestUIPrivate; -struct _ModestUIPrivate { - - ModestConf *modest_conf; - ModestAccountMgr *modest_acc_mgr; - ModestWindowMgr *modest_window_mgr; - TnyAccountStoreIface *account_store; - - GtkWindow *main_window; - GladeXML *glade_xml; - - -}; -#define MODEST_UI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ - MODEST_TYPE_UI, \ - ModestUIPrivate)) -/* globals */ -static GObjectClass *parent_class = NULL; - -/* uncomment the following if you have defined any signals */ -/* static guint signals[LAST_SIGNAL] = {0}; */ - -GType -modest_ui_get_type (void) -{ - static GType my_type = 0; - if (!my_type) { - static const GTypeInfo my_info = { - sizeof(ModestUIClass), - NULL, /* base init */ - NULL, /* base finalize */ - (GClassInitFunc) modest_ui_class_init, - NULL, /* class finalize */ - NULL, /* class data */ - sizeof(ModestUI), - 1, /* n_preallocs */ - (GInstanceInitFunc) modest_ui_init, - }; - my_type = g_type_register_static (G_TYPE_OBJECT, - "ModestUI", - &my_info, 0); - } - return my_type; -} - -static void -modest_ui_class_init (ModestUIClass *klass) -{ - GObjectClass *gobject_class; - gobject_class = (GObjectClass*) klass; - - parent_class = g_type_class_peek_parent (klass); - gobject_class->finalize = modest_ui_finalize; - - g_type_class_add_private (gobject_class, sizeof(ModestUIPrivate)); - - /* signal definitions go here, e.g.: */ -/* signals[MY_SIGNAL_1] = */ -/* g_signal_new ("my_signal_1",....); */ -/* signals[MY_SIGNAL_2] = */ -/* g_signal_new ("my_signal_2",....); */ -/* etc. */ -} - -static void -modest_ui_init (ModestUI *obj) -{ - ModestUIPrivate *priv = MODEST_UI_GET_PRIVATE(obj); - - priv->modest_acc_mgr = NULL; - priv->modest_conf = NULL; - priv->modest_window_mgr = NULL; - priv->glade_xml = NULL; - -} - -static void -modest_ui_finalize (GObject *obj) -{ - ModestUIPrivate *priv = MODEST_UI_GET_PRIVATE(obj); - - if (priv->modest_acc_mgr) - g_object_unref (priv->modest_acc_mgr); - priv->modest_acc_mgr = NULL; - - if (priv->modest_conf) - g_object_unref (priv->modest_conf); - priv->modest_conf = NULL; - - if (priv->modest_window_mgr) - g_object_unref (priv->modest_window_mgr); - priv->modest_window_mgr = NULL; -} - -GObject* -modest_ui_new (ModestConf *modest_conf) -{ - GObject *obj; - ModestUIPrivate *priv; - ModestAccountMgr *modest_acc_mgr; - TnyAccountStoreIface *account_store_iface; - - g_return_val_if_fail (modest_conf, NULL); - - obj = g_object_new(MODEST_TYPE_UI, NULL); - priv = MODEST_UI_GET_PRIVATE(obj); - - modest_acc_mgr = - MODEST_ACCOUNT_MGR(modest_account_mgr_new (modest_conf)); - if (!modest_acc_mgr) { - g_warning ("could not create ModestAccountMgr instance"); - g_object_unref (obj); - return NULL; - } - - account_store_iface = - TNY_ACCOUNT_STORE_IFACE(modest_tny_account_store_new (modest_acc_mgr)); - if (!account_store_iface) { - g_warning ("could not initialze ModestTnyAccountStore"); - return NULL; - } - g_signal_connect (account_store_iface, "password_requested", - G_CALLBACK(on_password_requested), - NULL); - glade_init (); - priv->glade_xml = glade_xml_new (MODEST_GLADE, - NULL,NULL); - if (!priv->glade_xml) { - g_warning ("failed to do glade stuff"); - g_object_unref (obj); - return NULL; - } - - /* FIXME: could be used, but doesn't work atm. - * glade_xml_signal_autoconnect(priv->glade_xml); - */ - - priv->modest_acc_mgr = modest_acc_mgr; - g_object_ref (priv->modest_conf = modest_conf); - - priv->account_store = account_store_iface; - - priv->modest_window_mgr = MODEST_WINDOW_MGR(modest_window_mgr_new()); - g_signal_connect (priv->modest_window_mgr, "last_window_closed", - G_CALLBACK(modest_ui_last_window_closed), - NULL); - return obj; -} - - -gboolean -modest_ui_show_main_window (ModestUI *modest_ui) -{ - GtkWidget *win; - int height, width; - ModestUIPrivate *priv; - GtkWidget *folder_view, *header_view; - GtkWidget *message_view; - GtkWidget *account_settings_item; - - GtkWidget *folder_view_holder, - *header_view_holder, - *mail_paned; - - priv = MODEST_UI_GET_PRIVATE(modest_ui); - - height = modest_conf_get_int (priv->modest_conf, - MODEST_CONF_MAIN_WINDOW_HEIGHT,NULL); - width = modest_conf_get_int (priv->modest_conf, - MODEST_CONF_MAIN_WINDOW_WIDTH,NULL); - - win = glade_xml_get_widget (priv->glade_xml, "main"); - if (!win) { - g_warning ("could not create main window"); - return FALSE; - } - - folder_view = - GTK_WIDGET(modest_main_window_folder_tree(priv->modest_acc_mgr, - priv->account_store)); - folder_view_holder = glade_xml_get_widget (priv->glade_xml, "folders"); - if (!folder_view||!folder_view_holder) { - g_warning ("failed to create folder tree"); - return FALSE; - } - gtk_container_add (GTK_CONTAINER(folder_view_holder), folder_view); - - header_view = GTK_WIDGET(modest_main_window_header_tree (NULL)); - header_view_holder = glade_xml_get_widget (priv->glade_xml, "mail_list"); - if (!header_view) { - g_warning ("failed to create header tree"); - return FALSE; - } - gtk_container_add (GTK_CONTAINER(header_view_holder), header_view); - - g_signal_connect (G_OBJECT(folder_view), "folder_selected", - G_CALLBACK(on_folder_clicked), modest_ui); - - message_view = GTK_WIDGET(modest_tny_msg_view_new (NULL)); - if (!message_view) { - g_warning ("failed to create message view"); - return FALSE; - } - mail_paned = glade_xml_get_widget (priv->glade_xml, "mail_paned"); - gtk_paned_add2 (GTK_PANED(mail_paned), message_view); - - g_signal_connect (header_view, "message_selected", - G_CALLBACK(on_message_clicked), - modest_ui); - - account_settings_item = glade_xml_get_widget (priv->glade_xml, "account_settings1"); - if (!account_settings_item) - { - g_warning ("The account settings item isn't available!\n"); - return FALSE; - } - - g_signal_connect (account_settings_item, "activate", - G_CALLBACK(on_account_settings1_activate), - modest_ui); - - register_toolbar_callbacks (modest_ui); - - modest_window_mgr_register (priv->modest_window_mgr, - G_OBJECT(win), MODEST_MAIN_WINDOW, 0); - g_signal_connect (win, "destroy", G_CALLBACK(modest_ui_window_destroy), - modest_ui); - gtk_widget_set_usize (GTK_WIDGET(win), height, width); - gtk_window_set_title (GTK_WINDOW(win), PACKAGE_STRING); - - gtk_widget_show_all (win); - return TRUE; -} - - -static void -register_toolbar_callbacks (ModestUI *modest_ui) -{ - ModestUIPrivate *priv; - GtkWidget *button; - - g_return_if_fail (modest_ui); - - priv = MODEST_UI_GET_PRIVATE (modest_ui); - - button = glade_xml_get_widget (priv->glade_xml, "toolb_new_mail"); - if (button) - g_signal_connect (button, "clicked", - G_CALLBACK(on_new_mail_clicked), modest_ui); - - button = glade_xml_get_widget (priv->glade_xml, "toolb_reply"); - if (button) - g_signal_connect (button, "clicked", - G_CALLBACK(on_reply_clicked), modest_ui); -} - - - -static void -hide_edit_window (GtkWidget *win, gpointer data) -{ - gtk_widget_hide (win); -} - - - - -gboolean -modest_ui_show_edit_window (ModestUI *modest_ui, const gchar* to, - const gchar* cc, const gchar* bcc, - const gchar* subject, const gchar *body, - const GSList* att) -{ - GtkWidget *win, *to_entry, *subject_entry, *body_view; - - ModestUIPrivate *priv; - GtkWidget *btn; - GtkTextBuffer *buf; - - priv = MODEST_UI_GET_PRIVATE(modest_ui); - int height = modest_conf_get_int (priv->modest_conf, - MODEST_CONF_EDIT_WINDOW_HEIGHT,NULL); - int width = modest_conf_get_int (priv->modest_conf, - MODEST_CONF_EDIT_WINDOW_WIDTH,NULL); - - win = glade_xml_get_widget (priv->glade_xml, "new_mail"); - if (!win) { - g_warning ("could not create new mail window"); - return FALSE; - } - - modest_window_mgr_register (priv->modest_window_mgr, - G_OBJECT(win), MODEST_EDIT_WINDOW, 0); - to_entry = glade_xml_get_widget (priv->glade_xml, "to_entry"); - subject_entry = glade_xml_get_widget (priv->glade_xml, "subject_entry"); - body_view = glade_xml_get_widget (priv->glade_xml, "body_view"); - - gtk_entry_set_text(GTK_ENTRY(subject_entry), subject); - gtk_entry_set_text(GTK_ENTRY(to_entry), to); - - buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(body_view)); - gtk_text_buffer_set_text(buf, body, -1); - - g_signal_connect (win, "destroy", G_CALLBACK(hide_edit_window), - NULL); - - gtk_widget_set_usize (GTK_WIDGET(win), height, width); - gtk_window_set_title (GTK_WINDOW(win), - subject ? subject : "Untitled"); - - - btn = glade_xml_get_widget (priv->glade_xml, "toolb_send"); - g_signal_connect (btn, "clicked", G_CALLBACK(on_send_button_clicked), - modest_ui); - - gtk_widget_show_all (win); - - return TRUE; -} - - -static void -modest_ui_window_destroy (GtkWidget *win, gpointer data) -{ - ModestUIPrivate *priv; - - g_return_if_fail (data); - - priv = MODEST_UI_GET_PRIVATE((ModestUI*)data); - if (!modest_window_mgr_unregister (priv->modest_window_mgr, G_OBJECT(win))) - g_warning ("modest window mgr: failed to unregister %p", - G_OBJECT(win)); -} - - -static void -modest_ui_last_window_closed (GObject *obj, gpointer data) -{ - gtk_main_quit (); -} - -void -on_account_selector_selection_changed(GtkWidget *widget, - gpointer user_data) -{ - GtkTreeModel *model = gtk_combo_box_get_model(GTK_COMBO_BOX(widget)); - GtkTreeIter iter; - - gchar *account_name; - - if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(widget), &iter)) - { - gtk_tree_model_get(GTK_TREE_MODEL(model), - &iter, - 0, &account_name, - -1); - } - else - { - account_name="empty"; - } - - g_message("Value: '%s'\n", account_name); -} - -void -on_account_settings1_activate (GtkMenuItem *menuitem, - gpointer user_data) -{ - GladeXML *glade_xml; - GtkWidget *advanced_account_setup; - ModestUIPrivate *priv; - gint retval; - GSList *account_name_list; - GSList *account_name_list_iter; - GtkListStore *account_names; - GtkTreeIter account_names_iter; - GtkWidget *account_selector; - GtkCellRenderer *renderer; - - priv = MODEST_UI_GET_PRIVATE(MODEST_UI(user_data)); - - glade_xml = glade_xml_new(MODEST_GLADE, "mailbox_setup_advanced", NULL); - advanced_account_setup = glade_xml_get_widget(glade_xml, "mailbox_setup_advanced"); - - account_name_list=modest_account_mgr_account_names(priv->modest_acc_mgr, NULL); - account_names = gtk_list_store_new(1, G_TYPE_STRING); - - for (account_name_list_iter=account_name_list; - account_name_list_iter!=NULL; - account_name_list_iter=g_slist_next(account_name_list_iter)) - { - gtk_list_store_append(account_names, &account_names_iter); - gtk_list_store_set(account_names, &account_names_iter, - 0, account_name_list_iter->data, - -1); - } - - g_slist_free(account_name_list); - - account_selector = glade_xml_get_widget(glade_xml, "account_selector"); - gtk_combo_box_set_model(GTK_COMBO_BOX(account_selector), GTK_TREE_MODEL(account_names)); - - renderer = gtk_cell_renderer_text_new (); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (account_selector), renderer, TRUE); - gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (account_selector), renderer, - "text", 0, - NULL); - - g_signal_connect(GTK_WIDGET(account_selector), "changed", - G_CALLBACK(on_account_selector_selection_changed), - GTK_WIDGET(advanced_account_setup)); - - gtk_combo_box_set_active(GTK_COMBO_BOX(account_selector), 0); - - gtk_widget_show_all(GTK_WIDGET(advanced_account_setup)); - - retval=gtk_dialog_run(GTK_DIALOG(advanced_account_setup)); - - g_object_unref(account_names); - - gtk_widget_destroy(GTK_WIDGET(advanced_account_setup)); - - g_object_unref(glade_xml); -} - - -static void -on_folder_clicked (ModestTnyFolderTreeView *folder_tree, - TnyMsgFolderIface *folder, - gpointer data) -{ - GtkWidget *win; - ModestTnyHeaderTreeView *tree_view; - ModestUIPrivate *priv; - GtkWidget *scrollview; - - g_return_if_fail (folder); - g_return_if_fail (data); - - priv = MODEST_UI_GET_PRIVATE(data); - scrollview = glade_xml_get_widget (priv->glade_xml,"mail_list"); - - tree_view = MODEST_TNY_HEADER_TREE_VIEW( - gtk_bin_get_child(GTK_BIN(scrollview))); - win = glade_xml_get_widget (priv->glade_xml, "main"); - gtk_window_set_title (GTK_WINDOW(win), - tny_msg_folder_iface_get_name(folder)); - - modest_tny_header_tree_view_set_folder (tree_view, - folder); -} - - - -static void on_message_clicked (ModestTnyFolderTreeView *folder_tree, - TnyMsgIface *message, - gpointer data) -{ - GtkWidget *paned; - ModestTnyMsgView *msg_view; - ModestUIPrivate *priv; - - g_return_if_fail (message); - g_return_if_fail (data); - - priv = MODEST_UI_GET_PRIVATE(data); - paned = glade_xml_get_widget (priv->glade_xml,"mail_paned"); - msg_view = MODEST_TNY_MSG_VIEW(gtk_paned_get_child2 (GTK_PANED(paned))); - - modest_tny_msg_view_set_message (msg_view, - message); -} - -static void -on_password_requested (ModestTnyAccountStore *account_store, - const gchar *account_name, gpointer user_data) -{ - - GtkWidget *passdialog; - GtkWidget *vbox; - GtkWidget *infolabel; - GtkWidget *passentry; - gint retval; - const gchar *infostring=g_strconcat("Please enter the password for ", account_name, ".", NULL); - - passdialog = gtk_dialog_new_with_buttons("MyDialog", - NULL, - GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_STOCK_OK, - GTK_RESPONSE_ACCEPT, - GTK_STOCK_CANCEL, - GTK_RESPONSE_REJECT, - NULL); - - vbox=gtk_vbox_new(FALSE, 0); - - infolabel=gtk_label_new(infostring); - passentry=gtk_entry_new(); - - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(passdialog)->vbox), infolabel, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(passdialog)->vbox), passentry, FALSE, FALSE, 0); - gtk_widget_show_all(passdialog); - - retval = gtk_dialog_run (GTK_DIALOG(passdialog)); - - switch (retval) - { - case GTK_RESPONSE_ACCEPT: - modest_account_mgr_set_server_account_string(modest_tny_account_store_get_accout_mgr(account_store), - account_name, - "password", - gtk_entry_get_text(GTK_ENTRY(passentry)), - NULL); - break; - case GTK_RESPONSE_CANCEL: - /* FIXME: - * What happens, if canceled?" - */ - break; - } - - gtk_widget_destroy (passdialog); -} - - - - - - -static GtkWidget* -modest_main_window_header_tree (TnyMsgFolderIface *folder) -{ - GtkWidget *header_tree; - - header_tree = GTK_WIDGET(modest_tny_header_tree_view_new(folder)); - if (!header_tree) { - g_warning ("could not create header tree"); - return NULL; - } - - return GTK_WIDGET(header_tree); -} - - - -static GtkWidget* -modest_main_window_folder_tree (ModestAccountMgr *modest_acc_mgr, - TnyAccountStoreIface *account_store) -{ - GtkTreeViewColumn *column; - GtkCellRenderer *renderer = gtk_cell_renderer_text_new (); - GtkWidget *folder_tree; - - folder_tree = GTK_WIDGET(modest_tny_folder_tree_view_new (account_store)); - if (!folder_tree) { - g_warning ("could not create folder list"); - return NULL; - } - - column = gtk_tree_view_column_new_with_attributes(_("All Mail Folders"), - renderer,"text", - TNY_ACCOUNT_TREE_MODEL_NAME_COLUMN, - NULL); - gtk_tree_view_column_set_resizable (column, TRUE); - gtk_tree_view_append_column (GTK_TREE_VIEW(folder_tree), column); - - column = gtk_tree_view_column_new_with_attributes(_("Unread"), - renderer, "text", - TNY_ACCOUNT_TREE_MODEL_UNREAD_COLUMN, - NULL); - gtk_tree_view_column_set_resizable (column, TRUE); - gtk_tree_view_append_column (GTK_TREE_VIEW(folder_tree), column); - - - gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(folder_tree), TRUE); - gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW(folder_tree), TRUE); - - return folder_tree; -} - - -static void -on_new_mail_clicked (GtkWidget *widget, ModestUI *modest_ui) -{ - g_return_if_fail (modest_ui); - modest_ui_show_edit_window (modest_ui, "", "", "", "", "", NULL); -} - -static gchar* -modest_ui_quote_msg(const TnyMsgIface *src, const gchar *from, time_t sent_date) -{ - GList *parts; - TnyMsgMimePartIface *part; - TnyStreamIface* stream; - TnyTextBufferStream *dest; - TnyMsgMimePartIface *body = NULL; - GtkTextBuffer *buf; - GtkTextIter begin, end, iter1, iter2, iter3; - gchar *txt, *line; - gint tmp; - gint indent; - gboolean break_line; -<<<<<<< .mine - gchar sent_str[101]; - gchar from_cut[82]; - gchar reply_head[202]; - -======= - ->>>>>>> .r91 - buf = gtk_text_buffer_new(NULL); - dest = tny_text_buffer_stream_new(buf); - parts = (GList*) tny_msg_iface_get_parts (src); - - while (parts) { - /* TODO: maybe we'd like to quote more than one part? - * cleanup, fix leaks - */ - TnyMsgMimePartIface *part = - TNY_MSG_MIME_PART_IFACE(parts->data); - if (tny_msg_mime_part_iface_content_type_is (part, "text/plain")) { - body = part; - break; - } - parts = parts->next; - } - if (!body) { - return ""; - } - buf = gtk_text_buffer_new (NULL); - stream = TNY_STREAM_IFACE(tny_text_buffer_stream_new (buf)); - - tny_stream_iface_reset (stream); - tny_msg_mime_part_iface_decode_to_stream (body, stream); - tny_stream_iface_reset (stream); - - /* format sent_date */ - strftime(sent_str, 100, "%c", localtime(&sent_date)); - strncpy(from_cut, from, 80); - sprintf(reply_head, "On %s, %s wrote:\n", sent_str, from_cut); - - gtk_text_buffer_get_iter_at_line(buf, &iter1, 0); - gtk_text_buffer_insert(buf, &iter1, reply_head, -1); - gtk_text_buffer_get_iter_at_line(buf, &iter1, 1); - while (TRUE) { - /* at each beginning of this while, iter1 must be at the beginning of - the (next) line to quote */ - - iter2 = iter1; -<<<<<<< .mine - if (gtk_text_iter_get_chars_in_line(&iter1) > 1) { - /* check whether line is already quoted */ - iter2 = iter1; - gtk_text_iter_forward_char (&iter2); - txt = gtk_text_buffer_get_text (buf, &iter1, &iter2, FALSE); - } else { - txt = ""; - } -======= - gtk_text_iter_forward_to_line_end(&iter2); - txt = gtk_text_buffer_get_text (buf, &iter1, &iter2, FALSE); - printf("%s\n", txt); - /* check whether line is already quoted */ - iter2 = iter1; - - gtk_text_iter_forward_word_end(&iter2); - txt = gtk_text_buffer_get_text (buf, &iter1, &iter2, FALSE); - ->>>>>>> .r91 - /* insert quotation mark */ - tmp = gtk_text_iter_get_offset(&iter1); - gtk_text_buffer_insert(buf, &iter1, "> ", -1); - - /* still at the beginning of the line */ - gtk_text_buffer_get_iter_at_offset(buf, &iter1, tmp); - iter2 = iter1; - - if (strcmp(txt, ">") != 0) { - - /* line was not already quoted */ - - /* now check whether the line must be broken: */ - if (gtk_text_iter_get_chars_in_line(&iter2) >= 79) { - - gtk_text_iter_set_line_offset(&iter2, 79); - - /* move iter1 behind quote mark at the beginnig of the line */ - gtk_text_iter_forward_word_end(&iter1); - - /* save iter2 position */ - iter3 = iter2; - - /* move iter2 back one word (from breakpoint in line) */ - gtk_text_iter_backward_word_start(&iter2); - - /* check for one-word line (up to iter2) */ - if (!gtk_text_iter_compare(&iter1, &iter2) < 0) { - gtk_text_iter_forward_word_end(&iter2); /* BUG? */ - } - - /* insert linebreak */ - tmp = gtk_text_iter_get_offset(&iter2); -<<<<<<< .mine - gtk_text_buffer_insert(buf, &iter2, "\n", -1); -======= - gtk_text_buffer_insert(buf, &iter2, "\n#", -1); - ->>>>>>> .r91 - gtk_text_buffer_get_iter_at_offset(buf, &iter1, tmp); - - /* move to the beginning of the "new" line */ - gtk_text_iter_forward_line(&iter1); - - /* try to kill 1 space */ - iter2 = iter1; - gtk_text_iter_forward_char(&iter2); - txt = gtk_text_buffer_get_text(buf, &iter1, &iter2, FALSE); - if (strcmp(txt, " ") == 0) { - tmp = gtk_text_iter_get_offset(&iter1); - gtk_text_buffer_delete(buf, &iter1, &iter2); - gtk_text_buffer_get_iter_at_offset(buf, &iter1, tmp); - } - - /* check whether there is a next line to merge */ - iter3 = iter1; - if (!gtk_text_iter_forward_line(&iter3)) { - continue; - } -<<<<<<< .mine - /* iter3 is now at the beginning of the next line.*/ - -======= - ->>>>>>> .r91 - /* check for empty line */ - if (gtk_text_iter_get_chars_in_line(&iter3) < 2) { - continue; - } - - /* check for quote */ - iter2 = iter3; - gtk_text_iter_forward_char (&iter2); - txt = gtk_text_buffer_get_text(buf, &iter3, &iter2, FALSE); - if (strcmp(txt, ">") == 0) { - /* iter1 is still at the beginning of the newly broken - * so we don't have to cleanup */ - continue; - } -<<<<<<< .mine - -======= - - /* now merge in the next line */ ->>>>>>> .r91 - if (!gtk_text_iter_forward_to_line_end(&iter1)) { - /* no further lines to merge */ - continue; - } - - /* "mark" newline */ - iter2 = iter1; - gtk_text_iter_forward_char(&iter2); -<<<<<<< .mine - - /* do the merge */ -======= - ->>>>>>> .r91 - tmp = gtk_text_iter_get_offset(&iter1); -<<<<<<< .mine -======= - - /* do the merge */ ->>>>>>> .r91 - gtk_text_buffer_delete (buf, &iter1, &iter2); - gtk_text_buffer_get_iter_at_offset (buf, &iter1, tmp); - - /* insert space */ - gtk_text_buffer_insert(buf, &iter1, " ", -1); - gtk_text_buffer_get_iter_at_offset (buf, &iter1, tmp); - - /* move to beginning of line and continue */ - gtk_text_iter_set_line_offset(&iter1, 0); -<<<<<<< .mine - continue; - -======= - ->>>>>>> .r91 - } else { - /* line doesn't have to be broken, we're done. */ - if (!gtk_text_iter_forward_line(&iter1)) { - break; - } - continue; - } - } else { - /* line was already quoted */ - if (!gtk_text_iter_forward_line(&iter1)) { - break; - } - continue; - } - } - - gtk_text_buffer_get_bounds (buf, &begin, &end); - txt = gtk_text_buffer_get_text (buf, &begin, &end, FALSE); - - return txt; -} - -static void -modest_ui_reply_to_msg (ModestUI *modest_ui, TnyMsgHeaderIface *header, - ModestTnyMsgView *msg_view) { - const gchar *subject, *from, *quoted; - time_t sent_date; - const TnyMsgIface *msg; - const TnyMsgFolderIface *folder; - gchar *re_sub; - - quoted = ""; - if (header) { - folder = tny_msg_header_iface_get_folder (TNY_MSG_HEADER_IFACE(header)); - if (!folder) { - g_warning ("cannot find folder"); - return; - } - - msg = tny_msg_folder_iface_get_message (TNY_MSG_FOLDER_IFACE(folder), header); - if (!msg) { - g_warning ("cannot find msg"); - return; - } - subject = tny_msg_header_iface_get_subject(header); - /* TODO: checks, free */ - re_sub = malloc(strlen(subject) + 5); - strcpy (re_sub, "Re: "); - strcat (re_sub, subject); - /* FIXME: honor replyto, cc */ - from = tny_msg_header_iface_get_from(header); - sent_date = tny_msg_header_iface_get_date_sent(header); - quoted = modest_ui_quote_msg(msg, from, sent_date); - - } else { - printf("no header\n"); - return; - } - - modest_ui_show_edit_window (modest_ui, from, "FIXME:cc", /* bcc */ "", re_sub, quoted, NULL); -} - - -/* WIP, testing az */ -static void -on_reply_clicked (GtkWidget *widget, ModestUI *modest_ui) -{ - GtkTreeSelection *sel; - GtkWidget *paned; - GtkTreeModel *model; - GtkTreeIter iter; - GtkScrolledWindow *scroll; - - TnyMsgHeaderIface *header; - - ModestTnyHeaderTreeView *header_view; - ModestTnyMsgView *msg_view; - ModestUIPrivate *priv; - - g_return_if_fail (modest_ui); - - priv = MODEST_UI_GET_PRIVATE(modest_ui); - - paned = glade_xml_get_widget (priv->glade_xml,"mail_paned"); - g_return_if_fail (paned); - - scroll = GTK_SCROLLED_WINDOW(gtk_paned_get_child1 (GTK_PANED(paned))); - g_return_if_fail (scroll); - - msg_view = MODEST_TNY_MSG_VIEW(gtk_paned_get_child2 (GTK_PANED(paned))); - g_return_if_fail (msg_view); - - header_view = MODEST_TNY_HEADER_TREE_VIEW(gtk_bin_get_child (GTK_BIN(scroll))); - g_return_if_fail (header_view); - - sel = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view)); - g_return_if_fail (sel); - - if (!gtk_tree_selection_get_selected (sel, &model, &iter)) - /* no message was selected. TODO: disable reply button in this case */ - return; - - gtk_tree_model_get (model, &iter, - TNY_MSG_HEADER_LIST_MODEL_INSTANCE_COLUMN, - &header, -1); - - modest_ui_reply_to_msg (modest_ui, header, msg_view); -} - - - -/* FIXME: truly evil --> we cannot really assume that - * there is only one edit window open... - */ -static void -on_send_button_clicked (GtkWidget *widget, ModestUI *modest_ui) -{ - ModestTnyTransportActions *actions; - ModestUIPrivate *priv; - GtkWidget *to_entry, *subject_entry, *body_view; - const gchar *to, *subject; - gchar *body; - GtkTextIter start, end; - GtkTextBuffer *buf; - TnyAccountStoreIface *account_store; - const GList *transport_accounts; - TnyTransportAccountIface *transport_account; - - g_return_if_fail (modest_ui); - - actions = MODEST_TNY_TRANSPORT_ACTIONS - (modest_tny_transport_actions_new ()); - priv = MODEST_UI_GET_PRIVATE(modest_ui); - - account_store = priv->account_store; - transport_accounts = - tny_account_store_iface_get_transport_accounts (account_store); - if (!transport_accounts) { - g_message ("cannot send message: no transport account defined"); - return; - } else /* take the first one! */ - transport_account = - TNY_TRANSPORT_ACCOUNT_IFACE(transport_accounts->data); - - to_entry = glade_xml_get_widget (priv->glade_xml, "to_entry"); - subject_entry = glade_xml_get_widget (priv->glade_xml, "subject_entry"); - body_view = glade_xml_get_widget (priv->glade_xml, "body_view"); - - to = gtk_entry_get_text (GTK_ENTRY(to_entry)); - subject = gtk_entry_get_text (GTK_ENTRY(subject_entry)); - - buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(body_view)); - gtk_text_buffer_get_bounds (buf, &start, &end); - body = gtk_text_buffer_get_text (buf, &start, &end, FALSE); - - g_message ("sending %s ==> %s", subject, to); - modest_tny_transport_actions_send_message (actions, - transport_account, - "dirk-jan.binnema@nokia.com", - to, "", "", subject, - body); - g_free (body); - g_object_unref (G_OBJECT(actions)); - - gtk_entry_set_text (GTK_ENTRY(to_entry), ""); - gtk_entry_set_text (GTK_ENTRY(subject_entry), ""); - gtk_text_buffer_set_text (buf, "", 0); - - gtk_widget_hide (glade_xml_get_widget (priv->glade_xml, "new_mail")); -} diff --git a/src/modest-account-mgr.c b/src/modest-account-mgr.c index c63ff48..ce093f3 100644 --- a/src/modest-account-mgr.c +++ b/src/modest-account-mgr.c @@ -172,8 +172,6 @@ static void modest_account_mgr_class_init (ModestAccountMgrClass * klass) { GObjectClass *gobject_class; - GType paramtypes[3] = {G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER}; - gobject_class = (GObjectClass *) klass; parent_class = g_type_class_peek_parent (klass); diff --git a/src/modest-account-mgr.h b/src/modest-account-mgr.h index 5c36a63..c524f6f 100644 --- a/src/modest-account-mgr.h +++ b/src/modest-account-mgr.h @@ -203,7 +203,7 @@ gboolean modest_account_mgr_account_exists (ModestAccountMgr *self, * * Returns: TRUE if it worked, FALSE otherwise */ -gboolean modest_account_mgr_set_account_enabled (ModestAccountMgr *self, const gchar* name, +gboolean modest_account_mgr_account_set_enabled (ModestAccountMgr *self, const gchar* name, gboolean is_server_account, gboolean enabled); diff --git a/src/modest-account-view.c b/src/modest-account-view.c deleted file mode 100644 index e06f9b8..0000000 --- a/src/modest-account-view.c +++ /dev/null @@ -1,313 +0,0 @@ -/* Copyright (c) 2006, 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 "modest-account-view.h" -/* include other impl specific header files */ - -/* 'private'/'protected' functions */ -static void modest_account_view_class_init (ModestAccountViewClass *klass); -static void modest_account_view_init (ModestAccountView *obj); -static void modest_account_view_finalize (GObject *obj); - - -enum _AccountViewColumns { - ENABLED_COLUMN, - NAME_COLUMN, - PROTO_COLUMN, - N_COLUMNS -}; -typedef enum _AccountViewColumns AccountViewColumns; - - -/* list my signals */ -enum { - /* MY_SIGNAL_1, */ - /* MY_SIGNAL_2, */ - LAST_SIGNAL -}; - -typedef struct _ModestAccountViewPrivate ModestAccountViewPrivate; -struct _ModestAccountViewPrivate { - ModestAccountMgr *account_mgr; -}; -#define MODEST_ACCOUNT_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ - MODEST_TYPE_ACCOUNT_VIEW, \ - ModestAccountViewPrivate)) -/* globals */ -static GtkTreeViewClass *parent_class = NULL; - -/* uncomment the following if you have defined any signals */ -/* static guint signals[LAST_SIGNAL] = {0}; */ - -GType -modest_account_view_get_type (void) -{ - static GType my_type = 0; - if (!my_type) { - static const GTypeInfo my_info = { - sizeof(ModestAccountViewClass), - NULL, /* base init */ - NULL, /* base finalize */ - (GClassInitFunc) modest_account_view_class_init, - NULL, /* class finalize */ - NULL, /* class data */ - sizeof(ModestAccountView), - 1, /* n_preallocs */ - (GInstanceInitFunc) modest_account_view_init, - }; - my_type = g_type_register_static (GTK_TYPE_TREE_VIEW, - "ModestAccountView", - &my_info, 0); - } - return my_type; -} - -static void -modest_account_view_class_init (ModestAccountViewClass *klass) -{ - GObjectClass *gobject_class; - gobject_class = (GObjectClass*) klass; - - parent_class = g_type_class_peek_parent (klass); - gobject_class->finalize = modest_account_view_finalize; - - g_type_class_add_private (gobject_class, sizeof(ModestAccountViewPrivate)); - - /* signal definitions go here, e.g.: */ -/* signals[MY_SIGNAL_1] = */ -/* g_signal_new ("my_signal_1",....); */ -/* signals[MY_SIGNAL_2] = */ -/* g_signal_new ("my_signal_2",....); */ -/* etc. */ -} - -static void -modest_account_view_init (ModestAccountView *obj) -{ - ModestAccountViewPrivate *priv; - - priv = MODEST_ACCOUNT_VIEW_GET_PRIVATE(obj); - - priv->account_mgr = NULL; -} - -static void -modest_account_view_finalize (GObject *obj) -{ - ModestAccountViewPrivate *priv; - - priv = MODEST_ACCOUNT_VIEW_GET_PRIVATE(obj); - - if (priv->account_mgr) { - g_object_unref (G_OBJECT(priv->account_mgr)); - priv->account_mgr = NULL; - } -} - - - -static void -update_account_view (ModestAccountMgr *account_mgr, ModestAccountView *view) -{ - GSList *account_names, *cursor; - GtkListStore *model; - GtkTreeIter iter; - - model = GTK_LIST_STORE(gtk_tree_view_get_model (GTK_TREE_VIEW(view))); - gtk_list_store_clear (model); - - cursor = account_names = - modest_account_mgr_account_names (account_mgr, NULL); - - while (cursor) { - gchar *proto, *store, *account_name; - gboolean enabled; - - account_name = (gchar*)cursor->data; - - store = modest_account_mgr_get_string (account_mgr, - account_name, - MODEST_ACCOUNT_STORE_ACCOUNT, - FALSE, NULL); - if (store) { - proto = modest_account_mgr_get_string (account_mgr, - store, - MODEST_ACCOUNT_PROTO, - TRUE, NULL); - g_free(store); - } - - enabled = modest_account_mgr_account_get_enabled (account_mgr, - account_name, - FALSE); - gtk_list_store_insert_with_values ( - model, NULL, 0, - ENABLED_COLUMN, enabled, - NAME_COLUMN, account_name, - PROTO_COLUMN, proto, - -1); - - g_free (account_name); - g_free (proto); - - cursor = cursor->next; - } - g_slist_free (account_names); -} - - -static void -on_account_changed (ModestAccountMgr *account_mgr, - const gchar* account, const gchar* key, - gboolean server_account, ModestAccountView *self) -{ - ModestAccountViewPrivate *priv; - priv = MODEST_ACCOUNT_VIEW_GET_PRIVATE(self); - - update_account_view (account_mgr, self); -} - - -static void -on_account_removed (ModestAccountMgr *account_mgr, - const gchar* account, gboolean server_account, - gpointer user_data) -{ - on_account_changed (account_mgr, account, NULL, server_account, user_data); -} - - - - -static void -on_account_enable_toggled (GtkCellRendererToggle *cell_renderer, gchar *path, - ModestAccountView *self) -{ - GtkTreeIter iter; - ModestAccountViewPrivate *priv; - GtkTreeModel *model; - gchar *account_name; - gboolean enabled; - - priv = MODEST_ACCOUNT_VIEW_GET_PRIVATE(self); - model = gtk_tree_view_get_model (GTK_TREE_VIEW(self)); - - if (!gtk_tree_model_get_iter_from_string (model, &iter, path)) { - g_printerr ("modest: cannot find iterator\n"); - return; - } - - gtk_tree_model_get (model, &iter, - ENABLED_COLUMN, &enabled, - NAME_COLUMN, &account_name, - -1); - - /* toggle enabled / disabled */ - modest_account_mgr_account_set_enabled (priv->account_mgr, account_name, - FALSE, !enabled); - g_free (account_name); -} - - - - - - -static -init_view (ModestAccountView *self) -{ - ModestAccountViewPrivate *priv; - GtkTreeSelection *sel; - GtkWidget *account_view; - GtkCellRenderer *renderer; - GtkListStore *model; - GtkTreeIter iter; - - priv = MODEST_ACCOUNT_VIEW_GET_PRIVATE(self); - - model = gtk_list_store_new (3, - G_TYPE_BOOLEAN, /* checkbox */ - G_TYPE_STRING, /* account name */ - G_TYPE_STRING); /* account type (pop, imap,...) */ - - gtk_tree_view_set_model (GTK_TREE_VIEW(self), GTK_TREE_MODEL(model)); - - renderer = gtk_cell_renderer_toggle_new (); - g_object_set (G_OBJECT(renderer), "activatable", TRUE,"radio", FALSE, NULL); - - g_signal_connect (G_OBJECT(renderer), "toggled", - G_CALLBACK(on_account_enable_toggled), - self); - - gtk_tree_view_append_column (GTK_TREE_VIEW(self), - gtk_tree_view_column_new_with_attributes ( - _("Enabled"), renderer, - "active", ENABLED_COLUMN, NULL)); - gtk_tree_view_append_column (GTK_TREE_VIEW(self), - gtk_tree_view_column_new_with_attributes ( - _("Account"), - gtk_cell_renderer_text_new (), - "text", NAME_COLUMN, NULL)); - gtk_tree_view_append_column (GTK_TREE_VIEW(self), - gtk_tree_view_column_new_with_attributes ( - _("Type"), - gtk_cell_renderer_text_new (), - "text", PROTO_COLUMN, NULL)); - - sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(self)); - - g_signal_connect (G_OBJECT(priv->account_mgr), - "account_removed", - G_CALLBACK(on_account_removed), self); - g_signal_connect (G_OBJECT(priv->account_mgr), - "account_changed", - G_CALLBACK(on_account_changed), self); -} - - - -GtkWidget* -modest_account_view_new (ModestAccountMgr *account_mgr) -{ - GObject *obj; - ModestAccountViewPrivate *priv; - - g_return_val_if_fail (account_mgr, NULL); - - obj = g_object_new(MODEST_TYPE_ACCOUNT_VIEW, NULL); - priv = MODEST_ACCOUNT_VIEW_GET_PRIVATE(obj); - - g_object_ref (G_OBJECT(account_mgr)); - priv->account_mgr = account_mgr; - - init_view (MODEST_ACCOUNT_VIEW (obj)); - - return GTK_WIDGET(obj); -} - diff --git a/src/modest-account-view.h b/src/modest-account-view.h deleted file mode 100644 index 2b78bbf..0000000 --- a/src/modest-account-view.h +++ /dev/null @@ -1,72 +0,0 @@ -/* Copyright (c) 2006, 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_ACCOUNT_VIEW_H__ -#define __MODEST_ACCOUNT_VIEW_H__ - -#include -#include - -#include "modest-account-mgr.h" - -G_BEGIN_DECLS - -/* convenience macros */ -#define MODEST_TYPE_ACCOUNT_VIEW (modest_account_view_get_type()) -#define MODEST_ACCOUNT_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),MODEST_TYPE_ACCOUNT_VIEW,ModestAccountView)) -#define MODEST_ACCOUNT_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),MODEST_TYPE_ACCOUNT_VIEW,GtkTreeView)) -#define MODEST_IS_ACCOUNT_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),MODEST_TYPE_ACCOUNT_VIEW)) -#define MODEST_IS_ACCOUNT_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),MODEST_TYPE_ACCOUNT_VIEW)) -#define MODEST_ACCOUNT_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),MODEST_TYPE_ACCOUNT_VIEW,ModestAccountViewClass)) - -typedef struct _ModestAccountView ModestAccountView; -typedef struct _ModestAccountViewClass ModestAccountViewClass; - -struct _ModestAccountView { - GtkTreeView parent; - /* insert public members, if any */ -}; - -struct _ModestAccountViewClass { - GtkTreeViewClass parent_class; - /* insert signal callback declarations, eg. */ - /* void (* my_event) (ModestAccountView* obj); */ -}; - -/* member functions */ -GType modest_account_view_get_type (void) G_GNUC_CONST; - - - -GtkWidget* modest_account_view_new (ModestAccountMgr *account_mgr); - -G_END_DECLS - -#endif /* __MODEST_ACCOUNT_VIEW_H__ */ - diff --git a/src/modest-editor-window.c b/src/modest-editor-window.c index 4dd7595..c270db6 100644 --- a/src/modest-editor-window.c +++ b/src/modest-editor-window.c @@ -44,7 +44,6 @@ enum { typedef struct _ModestEditorWindowPrivate ModestEditorWindowPrivate; struct _ModestEditorWindowPrivate { - GtkWidget *window; gpointer user_data; gboolean modified; GList *attachments; @@ -142,14 +141,14 @@ modest_editor_window_new (ModestUI *ui) /* for now create a local test-window */ data = NULL; - edit_win = modest_ui_new_editor_window(ui, &data); + edit_win = G_OBJECT(modest_ui_new_editor_window(ui, &data)); if (!edit_win) return NULL; if (!data) g_message("editor window user data is emtpy"); - MODEST_EDITOR_WINDOW(self)->window = edit_win; + MODEST_EDITOR_WINDOW(self)->window = GTK_WINDOW(edit_win); priv->user_data = data; return self; diff --git a/src/modest-main.c b/src/modest-main.c index 6b35614..4167296 100644 --- a/src/modest-main.c +++ b/src/modest-main.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -42,9 +43,6 @@ #include "modest-tny-transport-actions.h" #include "modest-tny-account-store.h" -#ifdef HAVE_CONFIG_H -#include -#endif /*HAVE_CONFIG_H*/ #ifdef MODEST_ENABLE_HILDON /* Hildon includes */ #include @@ -72,7 +70,6 @@ main (int argc, char *argv[]) { GOptionContext *context = NULL; ModestConf *modest_conf = NULL; - ModestUI *modest_ui = NULL; GError *err = NULL; int retval = MODEST_ERR_NONE; @@ -142,9 +139,8 @@ start_ui (ModestConf *conf, const gchar* mailto, const gchar *cc, const gchar *b const gchar* subject, const gchar *body) { - GtkWidget *win; ModestUI *modest_ui; - gint ok, retval = 0; + gint retval = 0; modest_ui = MODEST_UI(modest_ui_new (conf)); if (!modest_ui) { @@ -219,11 +215,8 @@ send_mail (ModestConf *conf, const gchar* mailto, const gchar *cc, const gchar * TnyListIface *accounts = NULL; TnyIteratorIface *iter = NULL; - - TnyTransportAccountIface *account = NULL; - + TnyTransportAccountIface *account = NULL; int retval; - int i = 0; acc_mgr = modest_account_mgr_new (conf); acc_store = modest_tny_account_store_new (acc_mgr); diff --git a/src/modest-text-utils.c b/src/modest-text-utils.c index 5742fbb..27a829c 100644 --- a/src/modest-text-utils.c +++ b/src/modest-text-utils.c @@ -198,6 +198,17 @@ get_breakpoint (const gchar * s, const gint indent, const gint limit) } + +/* just to prevent warnings: + * warning: `%x' yields only last 2 digits of year in some locales + */ +static size_t +my_strftime(char *s, size_t max, const char *fmt, const + struct tm *tm) { + return strftime(s, max, fmt, tm); +} + + gchar * modest_text_utils_quote (const gchar * to_quote, const gchar * from, const time_t sent_date, const int limit) @@ -209,7 +220,7 @@ modest_text_utils_quote (const gchar * to_quote, const gchar * from, gsize len; /* format sent_date */ - strftime (sent_str, 100, "%c", localtime (&sent_date)); + my_strftime (sent_str, 100, "%c", localtime (&sent_date)); q = g_string_new (""); g_string_printf (q, "On %s, %s wrote:\n", sent_str, from); diff --git a/src/modest-tny-account-store.c b/src/modest-tny-account-store.c index ef13dd7..56ebc4d 100644 --- a/src/modest-tny-account-store.c +++ b/src/modest-tny-account-store.c @@ -56,7 +56,6 @@ static void modest_tny_account_store_add_transport_account (TnyAccountStore TnyTransportAccountIface *account); static void modest_tny_account_store_get_accounts (TnyAccountStoreIface *iface, TnyListIface *list, TnyGetAccountsRequestType type); - /* list my signals */ enum { PASSWORD_REQUESTED_SIGNAL, @@ -334,8 +333,10 @@ modest_tny_account_store_finalize (GObject *obj) priv->modest_acc_mgr = NULL; } + if (priv->tny_session_camel) { - g_object_unref (G_OBJECT(priv->tny_session_camel)); +// FIXME: how to kill a camel + //g_object_unref (G_OBJECT(priv->tny_session_camel)); priv->tny_session_camel = NULL; } @@ -344,7 +345,8 @@ modest_tny_account_store_finalize (GObject *obj) priv->device = NULL; } - g_mutex_free (priv->store_lock); + if (priv->store_lock) + g_mutex_free (priv->store_lock); g_free (priv->cache_dir); priv->cache_dir = NULL; @@ -525,6 +527,14 @@ modest_tny_account_store_get_device (TnyAccountStoreIface *self) } +static gboolean +modest_tny_account_store_alert (TnyAccountStoreIface *self, TnyAlertType type, + const gchar *prompt) +{ + return TRUE; /* FIXME: implement this */ +} + + static void modest_tny_account_store_iface_init (gpointer g_iface, gpointer iface_data) { @@ -538,10 +548,14 @@ modest_tny_account_store_iface_init (gpointer g_iface, gpointer iface_data) modest_tny_account_store_get_accounts; klass->add_transport_account_func = modest_tny_account_store_add_transport_account; + klass->add_store_account_func = + modest_tny_account_store_add_store_account; klass->get_cache_dir_func = modest_tny_account_store_get_cache_dir; klass->get_device_func = modest_tny_account_store_get_device; + klass->alert_func = + modest_tny_account_store_alert; } void diff --git a/src/modest-tny-attachment.c b/src/modest-tny-attachment.c index e35fdee..ed73136 100644 --- a/src/modest-tny-attachment.c +++ b/src/modest-tny-attachment.c @@ -330,12 +330,16 @@ modest_tny_attachment_new_from_message(const TnyMsgIface *msg) GList * modest_tny_attachment_new_list_from_msg(const TnyMsgIface *msg, gboolean with_body) { - GList *list = NULL; + // FIXME: does not work anymore. needs the new TnyList stuff... + return NULL; +#if 0 + + TnyList *att_list const GList *attachments = NULL; TnyMsgMimePartIface *part; ModestTnyAttachment *att; -#if 0 + if (with_body) { /* TODO: make plain over html configurable */ part = modest_tny_msg_actions_find_body_part ((TnyMsgIface *)msg, "text/plain"); @@ -348,7 +352,7 @@ modest_tny_attachment_new_list_from_msg(const TnyMsgIface *msg, gboolean with_bo list = g_list_append(list, att); } } -#endif + if (with_body) { list = g_list_append(list, modest_tny_attachment_new_from_message(msg)); } else { @@ -363,4 +367,6 @@ modest_tny_attachment_new_list_from_msg(const TnyMsgIface *msg, gboolean with_bo attachments = attachments->next; } return list; + +#endif } diff --git a/src/modest-tny-folder-tree-view.c b/src/modest-tny-folder-tree-view.c deleted file mode 100644 index a3d37f9..0000000 --- a/src/modest-tny-folder-tree-view.c +++ /dev/null @@ -1,509 +0,0 @@ -/* Copyright (c) 2006, 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 "modest-tny-folder-tree-view.h" - -#include -#include "modest-icon-factory.h" - - -/* 'private'/'protected' functions */ -static void modest_tny_folder_tree_view_class_init (ModestTnyFolderTreeViewClass *klass); -static void modest_tny_folder_tree_view_init (ModestTnyFolderTreeView *obj); -static void modest_tny_folder_tree_view_finalize (GObject *obj); - -//static void modest_tny_folder_tree_view_iface_init (gpointer iface, gpointer data); -static void modest_tny_folder_tree_view_set_account_store (TnySummaryWindowIface *self, - TnyAccountStoreIface *account_store); -static gboolean update_model (ModestTnyFolderTreeView *self,TnyAccountStoreIface *iface); -static gboolean update_model_empty (ModestTnyFolderTreeView *self); - -static void selection_changed (GtkTreeSelection *sel, gpointer data); - -enum { - FOLDER_SELECTED_SIGNAL, - LAST_SIGNAL -}; - -typedef struct _ModestTnyFolderTreeViewPrivate ModestTnyFolderTreeViewPrivate; -struct _ModestTnyFolderTreeViewPrivate { - - TnyAccountStoreIface *tny_account_store; - TnyMsgFolderIface *cur_folder; - gboolean view_is_empty; - - GMutex *lock; -}; -#define MODEST_TNY_FOLDER_TREE_VIEW_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), \ - MODEST_TYPE_TNY_FOLDER_TREE_VIEW, \ - ModestTnyFolderTreeViewPrivate)) -/* globals */ -static GObjectClass *parent_class = NULL; - -static guint signals[LAST_SIGNAL] = {0}; - -GType -modest_tny_folder_tree_view_get_type (void) -{ - static GType my_type = 0; - if (!my_type) { - static const GTypeInfo my_info = { - sizeof(ModestTnyFolderTreeViewClass), - NULL, /* base init */ - NULL, /* base finalize */ - (GClassInitFunc) modest_tny_folder_tree_view_class_init, - NULL, /* class finalize */ - NULL, /* class data */ - sizeof(ModestTnyFolderTreeView), - 1, /* n_preallocs */ - (GInstanceInitFunc) modest_tny_folder_tree_view_init, - }; - - my_type = g_type_register_static (GTK_TYPE_TREE_VIEW, - "ModestTnyFolderTreeView", - &my_info, 0); - } - return my_type; -} - -static void -modest_tny_folder_tree_view_class_init (ModestTnyFolderTreeViewClass *klass) -{ - GObjectClass *gobject_class; - gobject_class = (GObjectClass*) klass; - - parent_class = g_type_class_peek_parent (klass); - gobject_class->finalize = modest_tny_folder_tree_view_finalize; - - klass->update_model = modest_tny_folder_tree_view_update_model; - - g_type_class_add_private (gobject_class, - sizeof(ModestTnyFolderTreeViewPrivate)); - - signals[FOLDER_SELECTED_SIGNAL] = - g_signal_new ("folder_selected", - G_TYPE_FROM_CLASS (gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (ModestTnyFolderTreeViewClass, - folder_selected), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); -} - - - -static void -text_cell_data (GtkTreeViewColumn *column, GtkCellRenderer *renderer, - GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data) -{ - GObject *rendobj; - gchar *fname; - gint unread; - TnyMsgFolderType type; - - gtk_tree_model_get (tree_model, iter, - TNY_ACCOUNT_TREE_MODEL_NAME_COLUMN, &fname, - TNY_ACCOUNT_TREE_MODEL_TYPE_COLUMN, &type, - TNY_ACCOUNT_TREE_MODEL_UNREAD_COLUMN, &unread, -1); - rendobj = G_OBJECT(renderer); - - if (unread > 0) { - gchar *folder_title = g_strdup_printf ("%s (%d)", fname, unread); - g_object_set (rendobj,"text", folder_title, "weight", 800, NULL); - g_free (folder_title); - } else - g_object_set (rendobj,"text", fname, "weight", 400, NULL); - - g_free (fname); -} - -/* FIXME: move these to TnyMail */ -enum { - - TNY_MSG_FOLDER_TYPE_NOTES = TNY_MSG_FOLDER_TYPE_SENT + 1, /* urgh */ - TNY_MSG_FOLDER_TYPE_DRAFTS, - TNY_MSG_FOLDER_TYPE_CONTACTS, - TNY_MSG_FOLDER_TYPE_CALENDAR -}; - -static TnyMsgFolderType -guess_folder_type (const gchar* name) -{ - TnyMsgFolderType type; - gchar *folder; - - g_return_val_if_fail (name, TNY_MSG_FOLDER_TYPE_NORMAL); - - type = TNY_MSG_FOLDER_TYPE_NORMAL; - folder = g_utf8_strdown (name, strlen(name)); - - if (strcmp (folder, "inbox") == 0 || - strcmp (folder, _("inbox")) == 0) - type = TNY_MSG_FOLDER_TYPE_INBOX; - else if (strcmp (folder, "outbox") == 0 || - strcmp (folder, _("outbox")) == 0) - type = TNY_MSG_FOLDER_TYPE_OUTBOX; - else if (g_str_has_prefix(folder, "junk") || - g_str_has_prefix(folder, _("junk"))) - type = TNY_MSG_FOLDER_TYPE_JUNK; - else if (g_str_has_prefix(folder, "trash") || - g_str_has_prefix(folder, _("trash"))) - type = TNY_MSG_FOLDER_TYPE_JUNK; - else if (g_str_has_prefix(folder, "sent") || - g_str_has_prefix(folder, _("sent"))) - type = TNY_MSG_FOLDER_TYPE_SENT; - - /* these are not *really* TNY_ types */ - else if (g_str_has_prefix(folder, "draft") || - g_str_has_prefix(folder, _("draft"))) - type = TNY_MSG_FOLDER_TYPE_DRAFTS; - else if (g_str_has_prefix(folder, "notes") || - g_str_has_prefix(folder, _("notes"))) - type = TNY_MSG_FOLDER_TYPE_NOTES; - else if (g_str_has_prefix(folder, "contacts") || - g_str_has_prefix(folder, _("contacts"))) - type = TNY_MSG_FOLDER_TYPE_CONTACTS; - else if (g_str_has_prefix(folder, "calendar") || - g_str_has_prefix(folder, _("calendar"))) - type = TNY_MSG_FOLDER_TYPE_CALENDAR; - - g_free (folder); - return type; -} - - -static void -icon_cell_data (GtkTreeViewColumn *column, GtkCellRenderer *renderer, - GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data) -{ - GObject *rendobj; - GdkPixbuf *pixbuf; - TnyMsgFolderType type; - gchar *fname = NULL; - gint unread; - - rendobj = G_OBJECT(renderer); - gtk_tree_model_get (tree_model, iter, - TNY_ACCOUNT_TREE_MODEL_TYPE_COLUMN, &type, - TNY_ACCOUNT_TREE_MODEL_NAME_COLUMN, &fname, - TNY_ACCOUNT_TREE_MODEL_UNREAD_COLUMN, &unread, -1); - rendobj = G_OBJECT(renderer); - - if (type == TNY_MSG_FOLDER_TYPE_NORMAL) - type = guess_folder_type (fname); - - if (fname); - g_free (fname); - - switch (type) { - case TNY_MSG_FOLDER_TYPE_INBOX: - pixbuf = modest_icon_factory_get_icon (MODEST_FOLDER_ICON_INBOX); - break; - case TNY_MSG_FOLDER_TYPE_OUTBOX: - pixbuf = modest_icon_factory_get_icon (MODEST_FOLDER_ICON_OUTBOX); - break; - case TNY_MSG_FOLDER_TYPE_JUNK: - pixbuf = modest_icon_factory_get_icon (MODEST_FOLDER_ICON_JUNK); - break; - case TNY_MSG_FOLDER_TYPE_SENT: - pixbuf = modest_icon_factory_get_icon (MODEST_FOLDER_ICON_SENT); - break; - case TNY_MSG_FOLDER_TYPE_DRAFTS: - pixbuf = modest_icon_factory_get_icon (MODEST_FOLDER_ICON_DRAFTS); - break; - case TNY_MSG_FOLDER_TYPE_NOTES: - pixbuf = modest_icon_factory_get_icon (MODEST_FOLDER_ICON_NOTES); - break; - case TNY_MSG_FOLDER_TYPE_CALENDAR: - pixbuf = modest_icon_factory_get_icon (MODEST_FOLDER_ICON_CALENDAR); - break; - case TNY_MSG_FOLDER_TYPE_CONTACTS: - pixbuf = modest_icon_factory_get_icon (MODEST_FOLDER_ICON_CONTACTS); - break; - case TNY_MSG_FOLDER_TYPE_NORMAL: - default: - pixbuf = modest_icon_factory_get_icon (MODEST_FOLDER_ICON_NORMAL); - break; - } - - g_object_set (rendobj, - "pixbuf-expander-open", - modest_icon_factory_get_icon (MODEST_FOLDER_ICON_OPEN), - "pixbuf-expander-closed", - modest_icon_factory_get_icon (MODEST_FOLDER_ICON_CLOSED), - "pixbuf", pixbuf, - NULL); -} - -static void -modest_tny_folder_tree_view_init (ModestTnyFolderTreeView *obj) -{ - ModestTnyFolderTreeViewPrivate *priv; - GtkTreeViewColumn *column; - GtkCellRenderer *renderer; - GtkTreeSelection *sel; - - priv = MODEST_TNY_FOLDER_TREE_VIEW_GET_PRIVATE(obj); - - priv->view_is_empty = TRUE; - priv->tny_account_store = NULL; - priv->cur_folder = NULL; - - priv->lock = g_mutex_new (); - - column = gtk_tree_view_column_new (); - gtk_tree_view_column_set_title (column, - _("All Mail Folders")); - - gtk_tree_view_append_column (GTK_TREE_VIEW(obj), - column); - - renderer = gtk_cell_renderer_pixbuf_new(); - gtk_tree_view_column_pack_start (column, renderer, FALSE); - gtk_tree_view_column_set_cell_data_func(column, renderer, - icon_cell_data, NULL, NULL); - - renderer = gtk_cell_renderer_text_new(); - gtk_tree_view_column_pack_start (column, renderer, FALSE); - gtk_tree_view_column_set_cell_data_func(column, renderer, - text_cell_data, NULL, NULL); - - sel = gtk_tree_view_get_selection (GTK_TREE_VIEW(obj)); - gtk_tree_selection_set_mode (sel, GTK_SELECTION_SINGLE); - - gtk_tree_view_column_set_spacing (column, 2); - gtk_tree_view_column_set_resizable (column, TRUE); - gtk_tree_view_column_set_fixed_width (column, TRUE); - gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(obj), TRUE); - gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW(obj), FALSE); - -} - - -static void -modest_tny_folder_tree_view_finalize (GObject *obj) -{ - ModestTnyFolderTreeViewPrivate *priv; - - g_return_if_fail (obj); - - priv = MODEST_TNY_FOLDER_TREE_VIEW_GET_PRIVATE(obj); - if (priv->tny_account_store) { - g_object_unref (G_OBJECT(priv->tny_account_store)); - priv->tny_account_store = NULL; - } - - - if (priv->lock) { - g_mutex_free (priv->lock); - priv->lock = NULL; - } - - G_OBJECT_CLASS(parent_class)->finalize (obj); -} - - -static void -modest_tny_folder_tree_view_set_account_store (TnySummaryWindowIface *self, - TnyAccountStoreIface *account_store) -{ - ModestTnyFolderTreeViewPrivate *priv; - - g_return_if_fail (self); - g_return_if_fail (account_store); - - priv = MODEST_TNY_FOLDER_TREE_VIEW_GET_PRIVATE(self); - if (priv->tny_account_store) { - g_object_unref (priv->tny_account_store); - priv->tny_account_store = NULL; - } - - g_object_ref (G_OBJECT(priv->tny_account_store = account_store)); -} - - - -static void -on_accounts_update (TnyAccountStoreIface *account_store, const gchar *account, - gpointer user_data) -{ - update_model_empty (MODEST_TNY_FOLDER_TREE_VIEW(user_data)); - - if (!update_model (MODEST_TNY_FOLDER_TREE_VIEW(user_data), account_store)) - g_printerr ("modest: failed to update model for changes in '%s'", - account); -} - - -GtkWidget* -modest_tny_folder_tree_view_new (TnyAccountStoreIface *account_store) -{ - GObject *self; - ModestTnyFolderTreeViewPrivate *priv; - GtkTreeSelection *sel; - - self = G_OBJECT(g_object_new(MODEST_TYPE_TNY_FOLDER_TREE_VIEW, NULL)); - priv = MODEST_TNY_FOLDER_TREE_VIEW_GET_PRIVATE(self); - - g_return_val_if_fail (account_store, NULL); - - if (!update_model (MODEST_TNY_FOLDER_TREE_VIEW(self), account_store)) - g_printerr ("modest: failed to update model"); - - g_signal_connect (G_OBJECT(account_store), "update_accounts", - G_CALLBACK (on_accounts_update), self); - - sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(self)); - g_signal_connect (sel, "changed", - G_CALLBACK(selection_changed), self); - - return self; -} - - - - -static gboolean -update_model_empty (ModestTnyFolderTreeView *self) -{ - GtkTreeIter iter; - GtkTreeStore *store; - ModestTnyFolderTreeViewPrivate *priv; - - g_return_val_if_fail (self, FALSE); - - store = gtk_tree_store_new (1, G_TYPE_STRING); - gtk_tree_store_append (store, &iter, NULL); - - gtk_tree_store_set (store, &iter, 0, - _("(empty)"), -1); - - gtk_tree_view_set_model (GTK_TREE_VIEW(self), - GTK_TREE_MODEL(store)); - g_object_unref (store); - - priv = MODEST_TNY_FOLDER_TREE_VIEW_GET_PRIVATE(self); - priv->view_is_empty = TRUE; - - return TRUE; -} - - -static gboolean -update_model (ModestTnyFolderTreeView *self, TnyAccountStoreIface *account_store) -{ - ModestTnyFolderTreeViewPrivate *priv; - TnyListIface *account_list; - GtkTreeModel *model, *sortable; - - g_return_val_if_fail (account_store, FALSE); - - priv = MODEST_TNY_FOLDER_TREE_VIEW_GET_PRIVATE(self); - - model = GTK_TREE_MODEL(tny_account_tree_model_new ()); - account_list = TNY_LIST_IFACE(model); - - update_model_empty (self); /* cleanup */ - priv->view_is_empty = TRUE; - - tny_account_store_iface_get_accounts (account_store, account_list, - TNY_ACCOUNT_STORE_IFACE_STORE_ACCOUNTS); - if (!account_list) /* no store accounts found */ - return TRUE; - - sortable = gtk_tree_model_sort_new_with_model (model); - gtk_tree_view_set_model (GTK_TREE_VIEW(self), sortable); - - priv->view_is_empty = FALSE; - g_object_unref (model); - - return TRUE; -} - - -void -selection_changed (GtkTreeSelection *sel, gpointer user_data) -{ - GtkTreeModel *model; - TnyMsgFolderIface *folder = NULL; - GtkTreeIter iter; - ModestTnyFolderTreeView *tree_view; - ModestTnyFolderTreeViewPrivate *priv; - - g_return_if_fail (sel); - g_return_if_fail (user_data); - - priv = MODEST_TNY_FOLDER_TREE_VIEW_GET_PRIVATE(user_data); - - /* is_empty means that there is only the 'empty' item */ - if (priv->view_is_empty) - return; - - /* folder was _un_selected if true */ - if (!gtk_tree_selection_get_selected (sel, &model, &iter)) { - priv->cur_folder = NULL; - return; - } - - tree_view = MODEST_TNY_FOLDER_TREE_VIEW (user_data); - - gtk_tree_model_get (model, &iter, - TNY_ACCOUNT_TREE_MODEL_INSTANCE_COLUMN, - &folder, -1); - - if (priv->cur_folder) - tny_msg_folder_iface_expunge (priv->cur_folder); - priv->cur_folder = folder; - - /* folder will not be defined if you click eg. on the root node */ - if (folder) - g_signal_emit (G_OBJECT(tree_view), signals[FOLDER_SELECTED_SIGNAL], 0, - folder); -} - - -gboolean -modest_tny_folder_tree_view_update_model(ModestTnyFolderTreeView *self, - TnyAccountStoreIface *iface) -{ - g_return_val_if_fail (MODEST_IS_TNY_FOLDER_TREE_VIEW (self), FALSE); - - return update_model (self, iface); -} diff --git a/src/modest-tny-folder-tree-view.h b/src/modest-tny-folder-tree-view.h deleted file mode 100644 index dc9f170..0000000 --- a/src/modest-tny-folder-tree-view.h +++ /dev/null @@ -1,118 +0,0 @@ -/* Copyright (c) 2006, 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_TNY_FOLDER_TREE_VIEW_H__ -#define __MODEST_TNY_FOLDER_TREE_VIEW_H__ - -#include -#include -#include - -G_BEGIN_DECLS - -/* convenience macros */ -#define MODEST_TYPE_TNY_FOLDER_TREE_VIEW (modest_tny_folder_tree_view_get_type()) -#define MODEST_TNY_FOLDER_TREE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),MODEST_TYPE_TNY_FOLDER_TREE_VIEW,ModestTnyFolderTreeView)) -#define MODEST_TNY_FOLDER_TREE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),MODEST_TYPE_TNY_FOLDER_TREE_VIEW,ModestTnyFolderTreeViewClass)) -#define MODEST_IS_TNY_FOLDER_TREE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),MODEST_TYPE_TNY_FOLDER_TREE_VIEW)) -#define MODEST_IS_TNY_FOLDER_TREE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),MODEST_TYPE_TNY_FOLDER_TREE_VIEW)) -#define MODEST_TNY_FOLDER_TREE_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),MODEST_TYPE_TNY_FOLDER_TREE_VIEW,ModestTnyFolderTreeViewClass)) - -typedef struct _ModestTnyFolderTreeView ModestTnyFolderTreeView; -typedef struct _ModestTnyFolderTreeViewClass ModestTnyFolderTreeViewClass; - -struct _ModestTnyFolderTreeView { - GtkTreeView parent; - /* insert public members, if any */ -}; - -struct _ModestTnyFolderTreeViewClass { - GtkTreeViewClass parent_class; - - /* emitted when a folder is clicked */ - void (*folder_selected) (ModestTnyFolderTreeView* self, - TnyMsgFolderIface *folder, - gpointer user_data); - - gboolean (*update_model) (ModestTnyFolderTreeView *self, - TnyAccountStoreIface *iface); - -}; - - -/** - * modest_tny_folder_tree_view_get_type: - * - * get the GType for ModestTnyFolderTreeView - * - * Returns: the GType - */ -GType modest_tny_folder_tree_view_get_type (void) G_GNUC_CONST; - - -/** - * modest_tny_folder_tree_view_new: - * @iface: a TnyAccountStoreIface object - * - * create a new ModestTnyFolderTreeView instance, based on an account store - * - * Returns: a new GtkWidget (a GtkTreeView-subclass) - */ -GtkWidget* modest_tny_folder_tree_view_new (TnyAccountStoreIface *iface); - - -/** - * modest_tny_folder_tree_view_is_empty: - * @self: a ModestTnyFolderTreeView instance - * - * check to see of the view is empty. Note that when it is empty, - * there will still be one item, telling "(empty)" or similar - * - * Returns: TRUE if the tree view is empty, FALSE otherwise - */ -gboolean modest_tny_folder_tree_view_is_empty (ModestTnyFolderTreeView *self); - - -/** - * modest_tny_folder_tree_view_update_model: - * @self: a #ModestTnyFolderTreeView instance - * @iface: a #TnyAccountStoreIface instance - * - * Update the thee model from a given account store. - * - * Returns: TRUE on success, FALSE otherwise - */ -gboolean modest_tny_folder_tree_view_update_model(ModestTnyFolderTreeView *self, - TnyAccountStoreIface *iface); - - -G_END_DECLS - -#endif /* __MODEST_TNY_FOLDER_TREE_VIEW_H__ */ - diff --git a/src/modest-tny-header-tree-view.c b/src/modest-tny-header-tree-view.c deleted file mode 100644 index 7e88c5e..0000000 --- a/src/modest-tny-header-tree-view.c +++ /dev/null @@ -1,936 +0,0 @@ -/* Copyright (c) 2006, 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. - */ - - -/* modest-tny-header-tree-view.c */ - -#include -#include "modest-tny-header-tree-view.h" -#include -#include -#include "modest-marshal.h" - -#include -#include "modest-icon-factory.h" - -static void modest_tny_header_tree_view_class_init (ModestTnyHeaderTreeViewClass *klass); -static void modest_tny_header_tree_view_init (ModestTnyHeaderTreeView *obj); -static void modest_tny_header_tree_view_finalize (GObject *obj); - -static void on_selection_changed (GtkTreeSelection *sel, gpointer user_data); -static void on_column_clicked (GtkTreeViewColumn *treeviewcolumn, gpointer user_data); -static gboolean refresh_folder_finish_status_update (gpointer user_data); - -enum { - MESSAGE_SELECTED_SIGNAL, - STATUS_UPDATE_SIGNAL, - LAST_SIGNAL -}; - -typedef struct _ModestTnyHeaderTreeViewPrivate ModestTnyHeaderTreeViewPrivate; -struct _ModestTnyHeaderTreeViewPrivate { - - TnyMsgFolderIface *tny_msg_folder; - TnyListIface *headers; - - gint status_id; - GSList *columns; - - GMutex *lock; - - ModestTnyHeaderTreeViewStyle style; -}; -#define MODEST_TNY_HEADER_TREE_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ - MODEST_TYPE_TNY_HEADER_TREE_VIEW, \ - ModestTnyHeaderTreeViewPrivate)) -/* globals */ -static GObjectClass *parent_class = NULL; - -/* uncomment the following if you have defined any signals */ -static guint signals[LAST_SIGNAL] = {0}; - -GType -modest_tny_header_tree_view_get_type (void) -{ - static GType my_type = 0; - if (!my_type) { - static const GTypeInfo my_info = { - sizeof(ModestTnyHeaderTreeViewClass), - NULL, /* base init */ - NULL, /* base finalize */ - (GClassInitFunc) modest_tny_header_tree_view_class_init, - NULL, /* class finalize */ - NULL, /* class data */ - sizeof(ModestTnyHeaderTreeView), - 1, /* n_preallocs */ - (GInstanceInitFunc) modest_tny_header_tree_view_init, - }; - my_type = g_type_register_static (GTK_TYPE_TREE_VIEW, - "ModestTnyHeaderTreeView", - &my_info, 0); - } - return my_type; -} - -static void -modest_tny_header_tree_view_class_init (ModestTnyHeaderTreeViewClass *klass) -{ - GObjectClass *gobject_class; - gobject_class = (GObjectClass*) klass; - - parent_class = g_type_class_peek_parent (klass); - gobject_class->finalize = modest_tny_header_tree_view_finalize; - - g_type_class_add_private (gobject_class, sizeof(ModestTnyHeaderTreeViewPrivate)); - - signals[MESSAGE_SELECTED_SIGNAL] = - g_signal_new ("message_selected", - G_TYPE_FROM_CLASS (gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (ModestTnyHeaderTreeViewClass,message_selected), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); - - signals[STATUS_UPDATE_SIGNAL] = - g_signal_new ("status_update", - G_TYPE_FROM_CLASS (gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (ModestTnyHeaderTreeViewClass,message_selected), - NULL, NULL, - modest_marshal_VOID__STRING_INT, - G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT); -} - - - - - -static void -msgtype_cell_data (GtkTreeViewColumn *column, GtkCellRenderer *renderer, - GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer user_data) -{ - TnyMsgHeaderFlags flags; - GdkPixbuf *pixbuf = NULL; - - gtk_tree_model_get (tree_model, iter, TNY_MSG_HEADER_LIST_MODEL_FLAGS_COLUMN, - &flags, -1); - - if (flags & TNY_MSG_HEADER_FLAG_DELETED) - pixbuf = modest_icon_factory_get_icon (MODEST_HEADER_ICON_DELETED); - else if (flags & TNY_MSG_HEADER_FLAG_SEEN) - pixbuf = modest_icon_factory_get_icon (MODEST_HEADER_ICON_READ); - else - pixbuf = modest_icon_factory_get_icon (MODEST_HEADER_ICON_UNREAD); - - g_object_set (G_OBJECT (renderer), "pixbuf", pixbuf, NULL); -} - -static void -attach_cell_data (GtkTreeViewColumn *column, GtkCellRenderer *renderer, - GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer user_data) -{ - TnyMsgHeaderFlags flags; - GdkPixbuf *pixbuf = NULL; - - gtk_tree_model_get (tree_model, iter, TNY_MSG_HEADER_LIST_MODEL_FLAGS_COLUMN, - &flags, -1); - - if (flags & TNY_MSG_HEADER_FLAG_ATTACHMENTS) - pixbuf = modest_icon_factory_get_icon (MODEST_HEADER_ICON_ATTACH); - - g_object_set (G_OBJECT (renderer), "pixbuf", pixbuf, NULL); -} - - -static void -header_cell_data (GtkTreeViewColumn *column, GtkCellRenderer *renderer, - GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer user_data) -{ - TnyMsgHeaderFlags flags; - - gtk_tree_model_get (tree_model, iter, TNY_MSG_HEADER_LIST_MODEL_FLAGS_COLUMN, - &flags, -1); - - g_object_set (G_OBJECT(renderer), - "weight", (flags & TNY_MSG_HEADER_FLAG_SEEN) ? 400: 800, - "style", (flags & TNY_MSG_HEADER_FLAG_DELETED) ? - PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL, - NULL); -} - - - -/* try to make a shorter display address; changes it arg in-place */ -static gchar* -display_address (gchar *address) -{ - gchar *cursor; - - if (!address) - return; - - /* simplistic --> remove from display name */ - cursor = g_strstr_len (address, strlen(address), "<"); - if (cursor) - cursor[0]='\0'; - - /* simplistic --> remove (bla bla) from display name */ - cursor = g_strstr_len (address, strlen(address), "("); - if (cursor) - cursor[0]='\0'; - - return address; -} - - - -static void -sender_receiver_cell_data (GtkTreeViewColumn *column, GtkCellRenderer *renderer, - GtkTreeModel *tree_model, GtkTreeIter *iter, gboolean is_sender) -{ - TnyMsgHeaderFlags flags; - gchar *address; - gint sender_receiver_col; - - if (is_sender) - sender_receiver_col = TNY_MSG_HEADER_LIST_MODEL_FROM_COLUMN; - else - sender_receiver_col = TNY_MSG_HEADER_LIST_MODEL_TO_COLUMN; - - gtk_tree_model_get (tree_model, iter, - sender_receiver_col, &address, - TNY_MSG_HEADER_LIST_MODEL_FLAGS_COLUMN, &flags, - -1); - - g_object_set (G_OBJECT(renderer), - "text", - display_address (address), - "weight", - (flags & TNY_MSG_HEADER_FLAG_SEEN) ? 400 : 800, - "style", - (flags & TNY_MSG_HEADER_FLAG_DELETED)?PANGO_STYLE_ITALIC:PANGO_STYLE_NORMAL, - NULL); - - g_free (address); -} - - -/* not reentrant/thread-safe */ -const gchar* -display_date (time_t date) -{ - struct tm date_tm, now_tm; - time_t now; - - const gint buf_size = 64; - static gchar date_buf[64]; /* buf_size is not ... */ - static gchar now_buf[64]; /* ...const enough... */ - - now = time (NULL); - - localtime_r(&now, &now_tm); - localtime_r(&date, &date_tm); - - /* get today's date */ - strftime (date_buf, buf_size, "%x", &date_tm); - strftime (now_buf, buf_size, "%x", &now_tm); /* today */ - - /* if this is today, get the time instead of the date */ - if (strcmp (date_buf, now_buf) == 0) - strftime (date_buf, buf_size, _("%X"), &date_tm); - - return date_buf; -} - - -static void -compact_header_cell_data (GtkTreeViewColumn *column, GtkCellRenderer *renderer, - GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer user_data) -{ - GObject *rendobj; - TnyMsgHeaderFlags flags; - gchar *from, *subject; - gchar *header; - time_t date; - - gtk_tree_model_get (tree_model, iter, - TNY_MSG_HEADER_LIST_MODEL_FLAGS_COLUMN, &flags, - TNY_MSG_HEADER_LIST_MODEL_FROM_COLUMN, &from, - TNY_MSG_HEADER_LIST_MODEL_SUBJECT_COLUMN, &subject, - TNY_MSG_HEADER_LIST_MODEL_DATE_RECEIVED_TIME_T_COLUMN, &date, - -1); - rendobj = G_OBJECT(renderer); - - header = g_strdup_printf ("%s %s\n%s", - display_address (from), - display_date(date), - subject); - - g_object_set (G_OBJECT(renderer), - "text", header, - "weight", (flags & TNY_MSG_HEADER_FLAG_SEEN) ? 400: 800, - "style", (flags & TNY_MSG_HEADER_FLAG_DELETED) ? - PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL, - NULL); - g_free (header); - g_free (from); - g_free (subject); -} - - -static GtkTreeViewColumn* -get_new_column (const gchar *name, GtkCellRenderer *renderer, - gboolean resizable, gint sort_col_id, gboolean show_as_text, - GtkTreeCellDataFunc cell_data_func, gpointer user_data) -{ - GtkTreeViewColumn *column; - - column = gtk_tree_view_column_new_with_attributes(name, renderer, NULL); - gtk_tree_view_column_set_resizable (column, resizable); - - if (show_as_text) - gtk_tree_view_column_add_attribute (column, renderer, "text", - sort_col_id); - if (sort_col_id >= 0) - gtk_tree_view_column_set_sort_column_id (column, sort_col_id); - - gtk_tree_view_column_set_sort_indicator (column, FALSE); - gtk_tree_view_column_set_reorderable (column, TRUE); - - if (cell_data_func) - gtk_tree_view_column_set_cell_data_func(column, renderer, cell_data_func, - user_data, NULL); - -/* g_signal_connect (G_OBJECT (column), "clicked", */ -/* G_CALLBACK (column_clicked), obj); */ - - return column; -} - - - - -static void -remove_all_columns (ModestTnyHeaderTreeView *obj) -{ - GList *columns, *cursor; - - columns = gtk_tree_view_get_columns (GTK_TREE_VIEW(obj)); - - for (cursor = columns; cursor; cursor = cursor->next) - gtk_tree_view_remove_column (GTK_TREE_VIEW(obj), - GTK_TREE_VIEW_COLUMN(cursor->data)); - g_list_free (columns); -} - - - - -static void -init_columns (ModestTnyHeaderTreeView *obj) -{ - GtkTreeViewColumn *column=NULL; - GtkCellRenderer *renderer_msgtype, - *renderer_header, - *renderer_attach; - - ModestTnyHeaderTreeViewPrivate *priv; - GSList *cursor; - - priv = MODEST_TNY_HEADER_TREE_VIEW_GET_PRIVATE(obj); - - renderer_msgtype = gtk_cell_renderer_pixbuf_new (); - renderer_attach = gtk_cell_renderer_pixbuf_new (); - renderer_header = gtk_cell_renderer_text_new (); - - remove_all_columns (obj); - - for (cursor = priv->columns; cursor; cursor = cursor->next) { - ModestTnyHeaderTreeViewColumn col = - (ModestTnyHeaderTreeViewColumn) GPOINTER_TO_INT(cursor->data); - - switch (col) { - - case MODEST_TNY_HEADER_TREE_VIEW_COLUMN_MSGTYPE: - - column = get_new_column (_("M"), renderer_msgtype, FALSE, - TNY_MSG_HEADER_LIST_MODEL_FLAGS_COLUMN, - FALSE, (GtkTreeCellDataFunc)msgtype_cell_data, - NULL); - break; - - case MODEST_TNY_HEADER_TREE_VIEW_COLUMN_ATTACH: - - column = get_new_column (_("A"), renderer_attach, FALSE, - TNY_MSG_HEADER_LIST_MODEL_FLAGS_COLUMN, - FALSE, (GtkTreeCellDataFunc)attach_cell_data, - NULL); - break; - - case MODEST_TNY_HEADER_TREE_VIEW_COLUMN_RECEIVED_DATE: - column = get_new_column (_("Received"), renderer_header, TRUE, - TNY_MSG_HEADER_LIST_MODEL_DATE_RECEIVED_COLUMN, - TRUE, (GtkTreeCellDataFunc)header_cell_data, - NULL); - break; - - case MODEST_TNY_HEADER_TREE_VIEW_COLUMN_FROM: - column = get_new_column (_("From"), renderer_header, TRUE, - TNY_MSG_HEADER_LIST_MODEL_FROM_COLUMN, - TRUE, (GtkTreeCellDataFunc)sender_receiver_cell_data, - GINT_TO_POINTER(TRUE)); - break; - - case MODEST_TNY_HEADER_TREE_VIEW_COLUMN_TO: - column = get_new_column (_("To"), renderer_header, TRUE, - TNY_MSG_HEADER_LIST_MODEL_TO_COLUMN, - TRUE, (GtkTreeCellDataFunc)sender_receiver_cell_data, - GINT_TO_POINTER(FALSE)); - break; - - case MODEST_TNY_HEADER_TREE_VIEW_COLUMN_COMPACT_HEADER: - column = get_new_column (_("Header"), renderer_header, TRUE, - TNY_MSG_HEADER_LIST_MODEL_FROM_COLUMN, - TRUE, (GtkTreeCellDataFunc)compact_header_cell_data, - NULL); - break; - - case MODEST_TNY_HEADER_TREE_VIEW_COLUMN_SUBJECT: - column = get_new_column (_("Subject"), renderer_header, TRUE, - TNY_MSG_HEADER_LIST_MODEL_SUBJECT_COLUMN, - TRUE, (GtkTreeCellDataFunc)header_cell_data, - NULL); - break; - - - case MODEST_TNY_HEADER_TREE_VIEW_COLUMN_SENT_DATE: - column = get_new_column (_("Sent"), renderer_header, TRUE, - TNY_MSG_HEADER_LIST_MODEL_DATE_SENT_COLUMN, - TRUE, (GtkTreeCellDataFunc)header_cell_data, - NULL); - break; - } - gtk_tree_view_append_column (GTK_TREE_VIEW(obj), column); - } -} - - - - - -static void -modest_tny_header_tree_view_init (ModestTnyHeaderTreeView *obj) -{ - ModestTnyHeaderTreeViewPrivate *priv; - priv = MODEST_TNY_HEADER_TREE_VIEW_GET_PRIVATE(obj); - - priv->status_id = 0; - priv->lock = g_mutex_new (); -} - -static void -modest_tny_header_tree_view_finalize (GObject *obj) -{ - ModestTnyHeaderTreeView *self; - ModestTnyHeaderTreeViewPrivate *priv; - - self = MODEST_TNY_HEADER_TREE_VIEW(obj); - priv = MODEST_TNY_HEADER_TREE_VIEW_GET_PRIVATE(self); - - if (priv->headers) - g_object_unref (G_OBJECT(priv->headers)); - - - if (priv->lock) { - g_mutex_free (priv->lock); - priv->lock = NULL; - } - - priv->headers = NULL; - priv->tny_msg_folder = NULL; - - G_OBJECT_CLASS(parent_class)->finalize (obj); -} - -GtkWidget* -modest_tny_header_tree_view_new (TnyMsgFolderIface *folder, - GSList *columns, - ModestTnyHeaderTreeViewStyle style) -{ - GObject *obj; - GtkTreeSelection *sel; - ModestTnyHeaderTreeView *self; - - obj = G_OBJECT(g_object_new(MODEST_TYPE_TNY_HEADER_TREE_VIEW, NULL)); - self = MODEST_TNY_HEADER_TREE_VIEW(obj); - - if (!modest_tny_header_tree_view_set_folder (self, NULL)) { - g_warning ("could not set the folder"); - g_object_unref (obj); - return NULL; - } - - modest_tny_header_tree_view_set_style (self, style); - modest_tny_header_tree_view_set_columns (self, columns); - - /* all cols */ - gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(obj), TRUE); - gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW(obj), TRUE); - - gtk_tree_view_set_rules_hint (GTK_TREE_VIEW(obj), - TRUE); /* alternating row colors */ - - sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(self)); - g_signal_connect (sel, "changed", - G_CALLBACK(on_selection_changed), self); - - return GTK_WIDGET(self); -} - -gboolean -modest_tny_header_tree_view_set_columns (ModestTnyHeaderTreeView *self, GSList *columns) -{ - ModestTnyHeaderTreeViewPrivate *priv; - GSList *cursor; - - g_return_val_if_fail (self, FALSE); - - priv = MODEST_TNY_HEADER_TREE_VIEW_GET_PRIVATE(self); - - g_slist_free (priv->columns); - - for (cursor = columns; cursor; cursor = cursor->next) { - ModestTnyHeaderTreeViewColumn col = - (ModestTnyHeaderTreeViewColumn) GPOINTER_TO_INT(cursor->data); - if (0 > col || col >= MODEST_TNY_HEADER_TREE_VIEW_COLUMN_NUM) - g_warning ("invalid column in column list"); - else - priv->columns = g_slist_append (priv->columns, cursor->data); - } - - init_columns (self); /* redraw them */ - return TRUE; -} - - - -const GSList* -modest_tny_header_tree_view_get_columns (ModestTnyHeaderTreeView *self) -{ - ModestTnyHeaderTreeViewPrivate *priv; - - g_return_val_if_fail (self, FALSE); - - priv = MODEST_TNY_HEADER_TREE_VIEW_GET_PRIVATE(self); - return priv->columns; -} - - - - -gboolean -modest_tny_header_tree_view_set_style (ModestTnyHeaderTreeView *self, - ModestTnyHeaderTreeViewStyle style) -{ - g_return_val_if_fail (self, FALSE); - g_return_val_if_fail (style >= 0 && style < MODEST_TNY_HEADER_TREE_VIEW_STYLE_NUM, - FALSE); - - MODEST_TNY_HEADER_TREE_VIEW_GET_PRIVATE(self)->style = style; - - return TRUE; -} - -ModestTnyHeaderTreeViewStyle -modest_tny_header_tree_view_get_style (ModestTnyHeaderTreeView *self) -{ - g_return_val_if_fail (self, FALSE); - - return MODEST_TNY_HEADER_TREE_VIEW_GET_PRIVATE(self)->style; -} - - - -/* get the length of any prefix that should be ignored for sorting */ -static inline int -get_prefix_len (const gchar *sub) -{ - gint i = 0; - const static gchar* prefix[] = {"Re:", "RE:", "Fwd:", "FWD:", "FW:", "AW:", NULL}; - - if (sub[0] != 'R' && sub[0] != 'F') /* optimization */ - return 0; - - while (prefix[i]) { - if (g_str_has_prefix(sub, prefix[i])) { - int prefix_len = strlen(prefix[i]); - if (sub[prefix_len] == ' ') - ++prefix_len; /* ignore space after prefix as well */ - return prefix_len; - } - ++i; - } - return 0; -} - - -static inline gint -cmp_normalized_subject (const gchar* s1, const gchar *s2) -{ - gint result = 0; - register gchar *n1, *n2; - - n1 = g_utf8_collate_key (s1 + get_prefix_len(s1), -1); - n2 = g_utf8_collate_key (s2 + get_prefix_len(s2), -1); - - result = strcmp (n1, n2); - g_free (n1); - g_free (n2); - - return result; -} - - -static gint -cmp_rows (GtkTreeModel *tree_model, GtkTreeIter *iter1, GtkTreeIter *iter2, - gpointer user_data) -{ - gint col_id = GPOINTER_TO_INT (user_data); - gint t1, t2; - gint val1, val2; - gchar *s1, *s2; - gint cmp; - - g_return_val_if_fail (GTK_IS_TREE_MODEL(tree_model), -1); - - switch (col_id) { - - /* first one, we decide based on the time */ - case MODEST_TNY_HEADER_TREE_VIEW_COLUMN_COMPACT_HEADER: - case MODEST_TNY_HEADER_TREE_VIEW_COLUMN_RECEIVED_DATE: - gtk_tree_model_get (tree_model, iter1, - TNY_MSG_HEADER_LIST_MODEL_DATE_RECEIVED_TIME_T_COLUMN, - &t1,-1); - gtk_tree_model_get (tree_model, iter2, - TNY_MSG_HEADER_LIST_MODEL_DATE_RECEIVED_TIME_T_COLUMN, - &t2,-1); - return t1 - t2; - - case MODEST_TNY_HEADER_TREE_VIEW_COLUMN_SENT_DATE: - gtk_tree_model_get (tree_model, iter1, - TNY_MSG_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, - &t1,-1); - gtk_tree_model_get (tree_model, iter2, - TNY_MSG_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, - &t2,-1); - return t1 - t2; - - - /* next ones, we try the search criteria first, if they're the same, then we use 'sent date' */ - case MODEST_TNY_HEADER_TREE_VIEW_COLUMN_SUBJECT: { - - gtk_tree_model_get (tree_model, iter1, - TNY_MSG_HEADER_LIST_MODEL_SUBJECT_COLUMN, &s1, - TNY_MSG_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t1, - -1); - gtk_tree_model_get (tree_model, iter2, - TNY_MSG_HEADER_LIST_MODEL_SUBJECT_COLUMN, &s2, - TNY_MSG_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t2, - -1); - - cmp = cmp_normalized_subject(s1, s2); - - g_free (s1); - g_free (s2); - - return cmp ? cmp : t1 - t2; - } - - case MODEST_TNY_HEADER_TREE_VIEW_COLUMN_FROM: - - gtk_tree_model_get (tree_model, iter1, - TNY_MSG_HEADER_LIST_MODEL_FROM_COLUMN, &s1, - TNY_MSG_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t1, - -1); - gtk_tree_model_get (tree_model, iter2, - TNY_MSG_HEADER_LIST_MODEL_FROM_COLUMN, &s2, - TNY_MSG_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t2, - -1); - cmp = strcmp (s1, s2); - g_free (s1); - g_free (s2); - - return cmp ? cmp : t1 - t2; - - case MODEST_TNY_HEADER_TREE_VIEW_COLUMN_TO: - - gtk_tree_model_get (tree_model, iter1, - TNY_MSG_HEADER_LIST_MODEL_TO_COLUMN, &s1, - TNY_MSG_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t1, - -1); - gtk_tree_model_get (tree_model, iter2, - TNY_MSG_HEADER_LIST_MODEL_TO_COLUMN, &s2, - TNY_MSG_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t2, - -1); - cmp = strcmp (s1, s2); - g_free (s1); - g_free (s2); - - return cmp ? cmp : t1 - t2; - - case MODEST_TNY_HEADER_TREE_VIEW_COLUMN_ATTACH: - - gtk_tree_model_get (tree_model, iter1, TNY_MSG_HEADER_LIST_MODEL_FLAGS_COLUMN, &val1, - TNY_MSG_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t1, -1); - gtk_tree_model_get (tree_model, iter2, TNY_MSG_HEADER_LIST_MODEL_FLAGS_COLUMN, &val2, - TNY_MSG_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t2, -1); - - cmp = (val1 & TNY_MSG_HEADER_FLAG_ATTACHMENTS) - - (val2 & TNY_MSG_HEADER_FLAG_ATTACHMENTS); - - return cmp ? cmp : t1 - t2; - - case MODEST_TNY_HEADER_TREE_VIEW_COLUMN_MSGTYPE: - gtk_tree_model_get (tree_model, iter1, TNY_MSG_HEADER_LIST_MODEL_FLAGS_COLUMN, &val1, - TNY_MSG_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t1,-1); - gtk_tree_model_get (tree_model, iter2, TNY_MSG_HEADER_LIST_MODEL_FLAGS_COLUMN, &val2, - TNY_MSG_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t2,-1); - cmp = (val1 & TNY_MSG_HEADER_FLAG_SEEN) - (val2 & TNY_MSG_HEADER_FLAG_SEEN); - - return cmp ? cmp : t1 - t2; - - default: - return &iter1 - &iter2; /* oughhhh */ - } -} - - -static void -refresh_folder (TnyMsgFolderIface *folder, gboolean cancelled, - gpointer user_data) -{ - GtkTreeModel *oldsortable, *sortable; - ModestTnyHeaderTreeView *self = - MODEST_TNY_HEADER_TREE_VIEW(user_data); - ModestTnyHeaderTreeViewPrivate *priv; - - g_return_if_fail (self); - - if (cancelled) - return; - - priv = MODEST_TNY_HEADER_TREE_VIEW_GET_PRIVATE(self); - - if (!folder) /* when there is no folder */ - gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(self), FALSE); - - else { /* it's a new one or a refresh */ - GSList *col; - - priv->headers = TNY_LIST_IFACE(tny_msg_header_list_model_new ()); - - tny_msg_folder_iface_get_headers (folder, priv->headers, FALSE); - tny_msg_header_list_model_set_folder (TNY_MSG_HEADER_LIST_MODEL(priv->headers), - folder, TRUE); /* async */ - - oldsortable = gtk_tree_view_get_model(GTK_TREE_VIEW (self)); - if (oldsortable && GTK_IS_TREE_MODEL_SORT(oldsortable)) { - GtkTreeModel *oldmodel = gtk_tree_model_sort_get_model - (GTK_TREE_MODEL_SORT(oldsortable)); - if (oldmodel) - g_object_unref (G_OBJECT(oldmodel)); - g_object_unref (oldsortable); - } - - sortable = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL(priv->headers)); - - /* install our special sorting functions */ - col = priv->columns; - while (col) { - gint col_id = GPOINTER_TO_INT (col->data); - gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE(sortable), col_id, - (GtkTreeIterCompareFunc)cmp_rows, - GINT_TO_POINTER(col_id), NULL); - col = col->next; - } - - gtk_tree_view_set_model (GTK_TREE_VIEW (self), sortable); - gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW(self), TRUE); - /* no need to unref sortable */ - } - -} - - -static void -refresh_folder_status_update (TnyMsgFolderIface *folder, const gchar *msg, - gint status_id, gpointer user_data) -{ - ModestTnyHeaderTreeView *self; - ModestTnyHeaderTreeViewPrivate *priv; - - self = MODEST_TNY_HEADER_TREE_VIEW (user_data); - priv = MODEST_TNY_HEADER_TREE_VIEW_GET_PRIVATE(self); - - g_signal_emit (G_OBJECT(self), - signals[STATUS_UPDATE_SIGNAL], 0, - msg, status_id); - if (msg) - g_timeout_add (750, - (GSourceFunc)refresh_folder_finish_status_update, - self); - - priv->status_id = status_id; -} - - -static gboolean -refresh_folder_finish_status_update (gpointer user_data) -{ - ModestTnyHeaderTreeView *self; - ModestTnyHeaderTreeViewPrivate *priv; - - self = MODEST_TNY_HEADER_TREE_VIEW (user_data); - priv = MODEST_TNY_HEADER_TREE_VIEW_GET_PRIVATE(self); - - if (priv->status_id == 0) - return FALSE; - - refresh_folder_status_update (NULL, NULL, priv->status_id, - user_data); - priv->status_id = 0; - - return FALSE; -} - - -gboolean -modest_tny_header_tree_view_set_folder (ModestTnyHeaderTreeView *self, - TnyMsgFolderIface *folder) -{ - ModestTnyHeaderTreeViewPrivate *priv; - - g_return_val_if_fail (MODEST_IS_TNY_HEADER_TREE_VIEW (self), FALSE); - - priv = MODEST_TNY_HEADER_TREE_VIEW_GET_PRIVATE(self); - - g_mutex_lock (priv->lock); - - if (!folder) {/* when there is no folder */ - GtkTreeModel *model; - model = gtk_tree_view_get_model (GTK_TREE_VIEW(self)); - gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(self), FALSE); - gtk_tree_view_set_model (GTK_TREE_VIEW (self), NULL); - if (model) - g_object_unref (model); - } - else { /* it's a new one or a refresh */ - tny_msg_folder_iface_refresh_async (folder, - refresh_folder, - refresh_folder_status_update, - self); - } - - /* no message selected */ - g_signal_emit (G_OBJECT(self), signals[MESSAGE_SELECTED_SIGNAL], 0, - NULL); - - g_mutex_unlock (priv->lock); - - return TRUE; -} - - - -static void -on_selection_changed (GtkTreeSelection *sel, gpointer user_data) -{ - GtkTreeModel *model; - TnyMsgHeaderIface *header; - GtkTreeIter iter; - ModestTnyHeaderTreeView *self; - ModestTnyHeaderTreeViewPrivate *priv; - - g_return_if_fail (sel); - g_return_if_fail (user_data); - - self = MODEST_TNY_HEADER_TREE_VIEW (user_data); - priv = MODEST_TNY_HEADER_TREE_VIEW_GET_PRIVATE(self); - - - if (!gtk_tree_selection_get_selected (sel, &model, &iter)) - return; /* msg was _un_selected */ - - //g_mutex_lock (priv->lock); - - gtk_tree_model_get (model, &iter, - TNY_MSG_HEADER_LIST_MODEL_INSTANCE_COLUMN, - &header, -1); - - if (header) { - const TnyMsgIface *msg = NULL; - const TnyMsgFolderIface *folder; - - folder = tny_msg_header_iface_get_folder (TNY_MSG_HEADER_IFACE(header)); - if (!folder) - g_printerr ("modest: cannot find folder\n"); - else { - msg = tny_msg_folder_iface_get_message (TNY_MSG_FOLDER_IFACE(folder), - header); - if (!msg) { - g_printerr ("modest: cannot find msg\n"); - gtk_tree_store_remove (GTK_TREE_STORE(model), - &iter); - } - } - - g_signal_emit (G_OBJECT(self), signals[MESSAGE_SELECTED_SIGNAL], 0, - msg); - - /* mark message as seen; _set_flags crashes, bug in tinymail? */ - //flags = tny_msg_header_iface_get_flags (TNY_MSG_HEADER_IFACE(header)); - //tny_msg_header_iface_set_flags (header, TNY_MSG_HEADER_FLAG_SEEN); - } - - // g_mutex_unlock (priv->lock); - -} - -static void -on_column_clicked (GtkTreeViewColumn *col, gpointer user_data) -{ - GtkTreeView *treeview; - gint id; - - treeview = GTK_TREE_VIEW (user_data); - id = gtk_tree_view_column_get_sort_column_id (col); - - gtk_tree_view_set_search_column (treeview, id); -} diff --git a/src/modest-tny-header-tree-view.h b/src/modest-tny-header-tree-view.h deleted file mode 100644 index 33f27be..0000000 --- a/src/modest-tny-header-tree-view.h +++ /dev/null @@ -1,186 +0,0 @@ -/* Copyright (c) 2006, 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_TNY_HEADER_TREE_VIEW_H__ -#define __MODEST_TNY_HEADER_TREE_VIEW_H__ - -#include -#include -#include -#include -#include -#include - -G_BEGIN_DECLS - -/* convenience macros */ -#define MODEST_TYPE_TNY_HEADER_TREE_VIEW (modest_tny_header_tree_view_get_type()) -#define MODEST_TNY_HEADER_TREE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),MODEST_TYPE_TNY_HEADER_TREE_VIEW,ModestTnyHeaderTreeView)) -#define MODEST_TNY_HEADER_TREE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),MODEST_TYPE_TNY_HEADER_TREE_VIEW,ModestTnyHeaderTreeViewClass)) -#define MODEST_IS_TNY_HEADER_TREE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),MODEST_TYPE_TNY_HEADER_TREE_VIEW)) -#define MODEST_IS_TNY_HEADER_TREE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),MODEST_TYPE_TNY_HEADER_TREE_VIEW)) -#define MODEST_TNY_HEADER_TREE_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),MODEST_TYPE_TNY_HEADER_TREE_VIEW,ModestTnyHeaderTreeViewClass)) - -typedef struct _ModestTnyHeaderTreeView ModestTnyHeaderTreeView; -typedef struct _ModestTnyHeaderTreeViewClass ModestTnyHeaderTreeViewClass; - -struct _ModestTnyHeaderTreeView { - GtkTreeView parent; - /* insert public members, if any */ -}; - -struct _ModestTnyHeaderTreeViewClass { - GtkTreeViewClass parent_class; - - void (*message_selected) (ModestTnyHeaderTreeView* self, - TnyMsgIface *msg, - gpointer user_data); - - /* msg == NULL implies that the operation is finished, ie. - * the progress indictation can be hidden */ - void (*status_update) (ModestTnyHeaderTreeView* self, - const gchar* msg, - gint status, - gpointer user_data); -}; - - -enum { - MODEST_TNY_HEADER_TREE_VIEW_COLUMN_FROM, - MODEST_TNY_HEADER_TREE_VIEW_COLUMN_TO, - MODEST_TNY_HEADER_TREE_VIEW_COLUMN_SUBJECT, - MODEST_TNY_HEADER_TREE_VIEW_COLUMN_SENT_DATE, - MODEST_TNY_HEADER_TREE_VIEW_COLUMN_RECEIVED_DATE, - MODEST_TNY_HEADER_TREE_VIEW_COLUMN_MSGTYPE, - MODEST_TNY_HEADER_TREE_VIEW_COLUMN_ATTACH, - MODEST_TNY_HEADER_TREE_VIEW_COLUMN_COMPACT_HEADER, - - MODEST_TNY_HEADER_TREE_VIEW_COLUMN_NUM -}; -typedef guint ModestTnyHeaderTreeViewColumn; - -enum { - MODEST_TNY_HEADER_TREE_VIEW_STYLE_NORMAL, - MODEST_TNY_HEADER_TREE_VIEW_STYLE_COMPACT, - - MODEST_TNY_HEADER_TREE_VIEW_STYLE_NUM -}; -typedef guint ModestTnyHeaderTreeViewStyle; - - - -/** - * modest_tny_header_tree_view_get_type: - * - * get the GType for ModestTnyHeaderTreeView - * - * Returns: the GType - */ -GType modest_tny_header_tree_view_get_type (void) G_GNUC_CONST; - - -/** - * modest_tny_header_tree_view_new: - * @folder: a TnyMsgFolderIface object - * @columns: a list of ModestTnyHeaderTreeViewColumn - * @style: a ModestTnyHeaderTreeViewColumn with the style of this listview - * ( MODEST_TNY_HEADER_TREE_VIEW_STYLE_NORMAL or MODEST_TNY_HEADER_TREE_VIEW_STYLE_COMPACT) - * - * create a new ModestTnyHeaderTreeView instance, based on a folder iface - * - * Returns: a new GtkWidget (a GtkTreeView-subclass) - */ -GtkWidget* modest_tny_header_tree_view_new (TnyMsgFolderIface *folder, - GSList *columns, - ModestTnyHeaderTreeViewStyle style); - -/** - * modest_tny_header_tree_view_set_folder: - * @self: a ModestTnyHeaderTreeView instance - * @folder: a TnyMsgFolderIface object - * - * set the folder for this ModestTnyHeaderTreeView - * - * Returns: TRUE if it succeeded, FALSE otherwise - */ -gboolean modest_tny_header_tree_view_set_folder (ModestTnyHeaderTreeView *self, - TnyMsgFolderIface *folder); - - -/** - * modest_tny_header_tree_view_set_columns: - * @self: a ModestTnyHeaderTreeView instance - * @columns: a list of ModestTnyHeaderTreeViewColumn - * - * set the columns for this ModestTnyHeaderTreeView - * - * Returns: TRUE if it succeeded, FALSE otherwise - */ -gboolean modest_tny_header_tree_view_set_columns (ModestTnyHeaderTreeView *self, - GSList *columns); -/** - * modest_tny_header_tree_view_get_columns: - * @self: a ModestTnyHeaderTreeView instance - * @folder: a TnyMsgFolderIface object - * - * get the columns for this ModestTnyHeaderTreeView - * - * Returns: list of columms, or NULL in case of no columns or error - */ -const GSList* modest_tny_header_tree_view_get_columns (ModestTnyHeaderTreeView *self); - - -/** - * modest_tny_header_tree_view_set_style: - * @self: a ModestTnyHeaderTreeView instance - * @style: the style for this tree view - * - * set the folder for this ModestTnyHeaderTreeView - * - * Returns: TRUE if it succeeded, FALSE otherwise - */ -gboolean modest_tny_header_tree_view_set_style (ModestTnyHeaderTreeView *self, - ModestTnyHeaderTreeViewStyle style); - -/** - * modest_tny_header_tree_view_set_folder: - * @self: a ModestTnyHeaderTreeView instance - * @folder: a TnyMsgFolderIface object - * - * set the folder for this ModestTnyHeaderTreeView - * - * Returns: TRUE if it succeeded, FALSE otherwise - */ -ModestTnyHeaderTreeViewStyle modest_tny_header_tree_view_get_style (ModestTnyHeaderTreeView *self); - -G_END_DECLS - - -#endif /* __MODEST_TNY_HEADER_TREE_VIEW_H__ */ - diff --git a/src/modest-tny-msg-actions.c b/src/modest-tny-msg-actions.c index d084b7c..2d60cd8 100644 --- a/src/modest-tny-msg-actions.c +++ b/src/modest-tny-msg-actions.c @@ -85,8 +85,6 @@ modest_tny_msg_actions_quote (const TnyMsgIface * self, const gchar * from, time_t sent_date, gint limit, const gchar * to_quote) { - gchar *quoted; - /* 2 cases: */ /* a) quote text from selection */ diff --git a/src/modest-tny-msg-view.c b/src/modest-tny-msg-view.c deleted file mode 100644 index cd5811b..0000000 --- a/src/modest-tny-msg-view.c +++ /dev/null @@ -1,702 +0,0 @@ -/* Copyright (c) 2006, 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 "modest-tny-msg-view.h" -#include "modest-tny-stream-gtkhtml.h" -#include "modest-tny-msg-actions.h" - - -/* 'private'/'protected' functions */ -static void modest_tny_msg_view_class_init (ModestTnyMsgViewClass *klass); -static void modest_tny_msg_view_init (ModestTnyMsgView *obj); -static void modest_tny_msg_view_finalize (GObject *obj); - - -static GSList* get_url_matches (GString *txt); -static gboolean on_link_clicked (GtkWidget *widget, const gchar *uri, - ModestTnyMsgView *msg_view); -static gboolean on_url_requested (GtkWidget *widget, const gchar *uri, - GtkHTMLStream *stream, - ModestTnyMsgView *msg_view); - -/* - * we need these regexps to find URLs in plain text e-mails - */ -typedef struct _UrlMatchPattern UrlMatchPattern; -struct _UrlMatchPattern { - gchar *regex; - regex_t *preg; - gchar *prefix; - -}; - -#define ATT_PREFIX "att:" - -#define MAIL_VIEWER_URL_MATCH_PATTERNS { \ - { "(file|http|ftp|https)://[-A-Za-z0-9_$.+!*(),;:@%&=?/~#]+[-A-Za-z0-9_$%&=?/~#]",\ - NULL, NULL },\ - { "www\\.[-a-z0-9.]+[-a-z0-9](:[0-9]*)?(/[-A-Za-z0-9_$.+!*(),;:@%&=?/~#]*[^]}\\),?!;:\"]?)?",\ - NULL, "http://" },\ - { "ftp\\.[-a-z0-9.]+[-a-z0-9](:[0-9]*)?(/[-A-Za-z0-9_$.+!*(),;:@%&=?/~#]*[^]}\\),?!;:\"]?)?",\ - NULL, "ftp://" },\ - { "(voipto|callto|chatto|jabberto|xmpp):[-_a-z@0-9.\\+]+", \ - NULL, NULL}, \ - { "mailto:[-_a-z0-9.\\+]+@[-_a-z0-9.]+", \ - NULL, NULL},\ - { "[-_a-z0-9.\\+]+@[-_a-z0-9.]+",\ - NULL, "mailto:"}\ - } - - -/* list my signals */ -enum { - LINK_CLICKED_SIGNAL, - ATTACHMENT_CLICKED_SIGNAL, - LAST_SIGNAL -}; - -typedef struct _ModestTnyMsgViewPrivate ModestTnyMsgViewPrivate; -struct _ModestTnyMsgViewPrivate { - GtkWidget *gtkhtml; - const TnyMsgIface *msg; -}; -#define MODEST_TNY_MSG_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ - MODEST_TYPE_TNY_MSG_VIEW, \ - ModestTnyMsgViewPrivate)) -/* globals */ -static GtkContainerClass *parent_class = NULL; - -/* uncomment the following if you have defined any signals */ -static guint signals[LAST_SIGNAL] = {0}; - -GType -modest_tny_msg_view_get_type (void) -{ - static GType my_type = 0; - if (!my_type) { - static const GTypeInfo my_info = { - sizeof(ModestTnyMsgViewClass), - NULL, /* base init */ - NULL, /* base finalize */ - (GClassInitFunc) modest_tny_msg_view_class_init, - NULL, /* class finalize */ - NULL, /* class data */ - sizeof(ModestTnyMsgView), - 1, /* n_preallocs */ - (GInstanceInitFunc) modest_tny_msg_view_init, - }; - my_type = g_type_register_static (GTK_TYPE_SCROLLED_WINDOW, - "ModestTnyMsgView", - &my_info, 0); - } - return my_type; -} - -static void -modest_tny_msg_view_class_init (ModestTnyMsgViewClass *klass) -{ - GObjectClass *gobject_class; - gobject_class = (GObjectClass*) klass; - - parent_class = g_type_class_peek_parent (klass); - gobject_class->finalize = modest_tny_msg_view_finalize; - - g_type_class_add_private (gobject_class, sizeof(ModestTnyMsgViewPrivate)); - - - signals[LINK_CLICKED_SIGNAL] = - g_signal_new ("link_clicked", - G_TYPE_FROM_CLASS (gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(ModestTnyMsgViewClass, link_clicked), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); - - signals[ATTACHMENT_CLICKED_SIGNAL] = - g_signal_new ("attachment_clicked", - G_TYPE_FROM_CLASS (gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(ModestTnyMsgViewClass, attachment_clicked), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_INT); - -} - -static void -modest_tny_msg_view_init (ModestTnyMsgView *obj) -{ - ModestTnyMsgViewPrivate *priv; - - priv = MODEST_TNY_MSG_VIEW_GET_PRIVATE(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); - - g_signal_connect (G_OBJECT(priv->gtkhtml), "link_clicked", - G_CALLBACK(on_link_clicked), obj); - - g_signal_connect (G_OBJECT(priv->gtkhtml), "url_requested", - G_CALLBACK(on_url_requested), obj); -} - - -static void -modest_tny_msg_view_finalize (GObject *obj) -{ - G_OBJECT_CLASS(parent_class)->finalize (obj); -} - - -GtkWidget* -modest_tny_msg_view_new (const TnyMsgIface *msg) -{ - GObject *obj; - ModestTnyMsgView* self; - ModestTnyMsgViewPrivate *priv; - - obj = G_OBJECT(g_object_new(MODEST_TYPE_TNY_MSG_VIEW, NULL)); - self = MODEST_TNY_MSG_VIEW(obj); - priv = MODEST_TNY_MSG_VIEW_GET_PRIVATE (self); - - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(self), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - - if (priv->gtkhtml) - gtk_container_add (GTK_CONTAINER(obj), priv->gtkhtml); - - if (msg) - modest_tny_msg_view_set_message (self, msg); - - return GTK_WIDGET(self); -} - - -static gboolean -on_link_clicked (GtkWidget *widget, const gchar *uri, ModestTnyMsgView *msg_view) -{ - - int index; - - g_return_val_if_fail (msg_view, FALSE); - - /* is it an attachment? */ - if (g_str_has_prefix(uri, ATT_PREFIX)) { - - index = atoi (uri + strlen(ATT_PREFIX)); - - if (index == 0) { - /* index is 1-based, so 0 indicates an error */ - g_printerr ("modest: invalid attachment id: %s\n", uri); - return FALSE; - } - - g_signal_emit (G_OBJECT(msg_view), signals[ATTACHMENT_CLICKED_SIGNAL], - 0, index); - return FALSE; - } - - g_signal_emit (G_OBJECT(msg_view), signals[LINK_CLICKED_SIGNAL], 0, uri); - - return FALSE; -} - - -static TnyMsgMimePartIface * -find_cid_image (const TnyMsgIface *msg, const gchar *cid) -{ - TnyMsgMimePartIface *part = NULL; - const TnyListIface *parts; - TnyIteratorIface *iter; - - g_return_val_if_fail (msg, NULL); - g_return_val_if_fail (cid, NULL); - - parts = tny_msg_iface_get_parts ((TnyMsgIface*)msg); // FIXME: tinymail - iter = tny_list_iface_create_iterator ((TnyListIface*)parts); - - while (!tny_iterator_iface_is_done(iter)) { - const gchar *part_cid; - part = TNY_MSG_MIME_PART_IFACE(tny_iterator_iface_current(iter)); - part_cid = tny_msg_mime_part_iface_get_content_id (part); - - if (part_cid && strcmp (cid, part_cid) == 0) - break; - - part = NULL; - tny_iterator_iface_next (iter); - } - - g_object_unref (G_OBJECT(iter)); - return part; -} - - -static gboolean -on_url_requested (GtkWidget *widget, const gchar *uri, - GtkHTMLStream *stream, - ModestTnyMsgView *msg_view) -{ - ModestTnyMsgViewPrivate *priv; - priv = MODEST_TNY_MSG_VIEW_GET_PRIVATE (msg_view); - - if (g_str_has_prefix (uri, "cid:")) { - /* +4 ==> skip "cid:" */ - const TnyMsgMimePartIface *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); - } else { - TnyStreamIface *tny_stream = - TNY_STREAM_IFACE(modest_tny_stream_gtkhtml_new(stream)); - // FIXME: tinymail - tny_msg_mime_part_iface_decode_to_stream ((TnyMsgMimePartIface*)part, - tny_stream); - gtk_html_stream_close (stream, GTK_HTML_STREAM_OK); - } - } - - return TRUE; -} - - -typedef struct { - guint offset; - guint len; - const gchar* prefix; -} url_match_t; - - - -/* render the attachments as hyperlinks in html */ -static gchar* -attachments_as_html (ModestTnyMsgView *self, const TnyMsgIface *msg) -{ - ModestTnyMsgViewPrivate *priv; - GString *appendix; - const TnyListIface *parts; - TnyIteratorIface *iter; - gchar *html; - int index = 0; - - if (!msg) - return NULL; - - priv = MODEST_TNY_MSG_VIEW_GET_PRIVATE (self); - parts = tny_msg_iface_get_parts ((TnyMsgIface*)msg); - // FIXME: tinymail - iter = tny_list_iface_create_iterator ((TnyListIface*)parts); - - appendix= g_string_new (""); - - while (!tny_iterator_iface_is_done(iter)) { - TnyMsgMimePartIface *part; - - ++index; /* attachment numbers are 1-based */ - - part = TNY_MSG_MIME_PART_IFACE(tny_iterator_iface_current (iter)); - - if (tny_msg_mime_part_iface_is_attachment (part)) { - - const gchar *filename = tny_msg_mime_part_iface_get_filename(part); - if (!filename) - filename = _("attachment"); - - g_string_append_printf (appendix, "%s \n", - ATT_PREFIX, index, filename); - } - tny_iterator_iface_next (iter); - } - g_object_unref (G_OBJECT(iter)); - - if (appendix->len == 0) - return g_string_free (appendix, TRUE); - - html = g_strdup_printf ("%s: %s\n
", - _("Attachments"), appendix->str); - g_string_free (appendix, TRUE); - - return html; -} - - - -static void -hyperlinkify_plain_text (GString *txt) -{ - GSList *cursor; - GSList *match_list = get_url_matches (txt); - - /* we will work backwards, so the offsets stay valid */ - for (cursor = match_list; cursor; cursor = cursor->next) { - - url_match_t *match = (url_match_t*) cursor->data; - gchar *url = g_strndup (txt->str + match->offset, match->len); - gchar *repl = NULL; /* replacement */ - - /* the prefix is NULL: use the one that is already there */ - repl = g_strdup_printf ("%s", - match->prefix ? match->prefix : "", url, url); - - /* replace the old thing with our hyperlink - * replacement thing */ - g_string_erase (txt, match->offset, match->len); - g_string_insert (txt, match->offset, repl); - - g_free (url); - g_free (repl); - - g_free (cursor->data); - } - - g_slist_free (match_list); -} - - - -static gchar * -convert_to_html (const gchar *data) -{ - int i; - gboolean first_space = TRUE; - GString *html; - gsize len; - - if (!data) - return NULL; - - len = strlen (data); - html = g_string_sized_new (len + 100); /* just a guess... */ - - g_string_append_printf (html, - "" - "" - "" - "" - ""); - - /* replace with special html chars where needed*/ - for (i = 0; i != len; ++i) { - char kar = data[i]; - switch (kar) { - - case 0: break; /* ignore embedded \0s */ - case '<' : g_string_append (html, "<"); break; - case '>' : g_string_append (html, ">"); break; - case '&' : g_string_append (html, """); break; - case '\n': g_string_append (html, "
\n"); break; - default: - if (kar == ' ') { - g_string_append (html, first_space ? " " : " "); - first_space = FALSE; - } else if (kar == '\t') - g_string_append (html, "    "); - else { - int charnum = 0; - first_space = TRUE; - /* optimization trick: accumulate 'normal' chars, then copy */ - do { - kar = data [++charnum + i]; - - } while ((i + charnum < len) && - (kar > '>' || (kar != '<' && kar != '>' - && kar != '&' && kar != ' ' - && kar != '\n' && kar != '\t'))); - g_string_append_len (html, &data[i], charnum); - i += (charnum - 1); - } - } - } - - g_string_append (html, "
"); - hyperlinkify_plain_text (html); - - return g_string_free (html, FALSE); -} - - - - -static gint -cmp_offsets_reverse (const url_match_t *match1, const url_match_t *match2) -{ - return match2->offset - match1->offset; -} - - - -/* - * check if the match is inside an existing match... */ -static void -chk_partial_match (const url_match_t *match, int* offset) -{ - if (*offset >= match->offset && *offset < match->offset + match->len) - *offset = -1; -} - -static GSList* -get_url_matches (GString *txt) -{ - regmatch_t rm; - int rv, i, offset = 0; - GSList *match_list = NULL; - - static UrlMatchPattern patterns[] = MAIL_VIEWER_URL_MATCH_PATTERNS; - const size_t pattern_num = sizeof(patterns)/sizeof(UrlMatchPattern); - - /* initalize the regexps */ - for (i = 0; i != pattern_num; ++i) { - patterns[i].preg = g_new0 (regex_t,1); - g_assert(regcomp (patterns[i].preg, patterns[i].regex, - REG_ICASE|REG_EXTENDED|REG_NEWLINE) == 0); - } - /* find all the matches */ - for (i = 0; i != pattern_num; ++i) { - offset = 0; - while (1) { - int test_offset; - if ((rv = regexec (patterns[i].preg, txt->str + offset, 1, &rm, 0)) != 0) { - g_assert (rv == REG_NOMATCH); /* this should not happen */ - break; /* try next regexp */ - } - if (rm.rm_so == -1) - break; - - /* FIXME: optimize this */ - /* to avoid partial matches on something that was already found... */ - /* check_partial_match will put -1 in the data ptr if that is the case */ - test_offset = offset + rm.rm_so; - g_slist_foreach (match_list, (GFunc)chk_partial_match, &test_offset); - - /* make a list of our matches ( tupels)*/ - if (test_offset != -1) { - url_match_t *match = g_new (url_match_t,1); - match->offset = offset + rm.rm_so; - match->len = rm.rm_eo - rm.rm_so; - match->prefix = patterns[i].prefix; - match_list = g_slist_prepend (match_list, match); - } - offset += rm.rm_eo; - } - } - - for (i = 0; i != pattern_num; ++i) { - regfree (patterns[i].preg); - g_free (patterns[i].preg); - } /* don't free patterns itself -- it's static */ - - /* now sort the list, so the matches are in reverse order of occurence. - * that way, we can do the replacements starting from the end, so we don't need - * to recalculate the offsets - */ - match_list = g_slist_sort (match_list, - (GCompareFunc)cmp_offsets_reverse); - return match_list; -} - - - -static gboolean -set_html_message (ModestTnyMsgView *self, const TnyMsgMimePartIface *tny_body, - const TnyMsgIface *msg) -{ - gchar *html_attachments; - TnyStreamIface *gtkhtml_stream; - ModestTnyMsgViewPrivate *priv; - - g_return_val_if_fail (self, FALSE); - g_return_val_if_fail (tny_body, FALSE); - - priv = MODEST_TNY_MSG_VIEW_GET_PRIVATE(self); - - gtkhtml_stream = - TNY_STREAM_IFACE(modest_tny_stream_gtkhtml_new - (gtk_html_begin(GTK_HTML(priv->gtkhtml)))); - - tny_stream_iface_reset (gtkhtml_stream); - - html_attachments = attachments_as_html(self, msg); - if (html_attachments) { - tny_stream_iface_write (gtkhtml_stream, html_attachments, - strlen(html_attachments)); - tny_stream_iface_reset (gtkhtml_stream); - g_free (html_attachments); - } - - // FIXME: tinymail - tny_msg_mime_part_iface_decode_to_stream ((TnyMsgMimePartIface*)tny_body, - gtkhtml_stream); - - g_object_unref (G_OBJECT(gtkhtml_stream)); - - return TRUE; -} - - -/* 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 (ModestTnyMsgView *self, const TnyMsgMimePartIface *tny_body, - const TnyMsgIface *msg) -{ - GtkTextBuffer *buf; - GtkTextIter begin, end; - TnyStreamIface* txt_stream, *gtkhtml_stream; - gchar *txt, *html_attachments; - ModestTnyMsgViewPrivate *priv; - - g_return_val_if_fail (self, FALSE); - g_return_val_if_fail (tny_body, FALSE); - - priv = MODEST_TNY_MSG_VIEW_GET_PRIVATE(self); - - buf = gtk_text_buffer_new (NULL); - txt_stream = TNY_STREAM_IFACE(tny_text_buffer_stream_new (buf)); - - tny_stream_iface_reset (txt_stream); - - gtkhtml_stream = - TNY_STREAM_IFACE(modest_tny_stream_gtkhtml_new - (gtk_html_begin(GTK_HTML(priv->gtkhtml)))); - - html_attachments = attachments_as_html(self, msg); - if (html_attachments) { - tny_stream_iface_write (gtkhtml_stream, html_attachments, - strlen(html_attachments)); - tny_stream_iface_reset (gtkhtml_stream); - g_free (html_attachments); - } - - // FIXME: tinymail - tny_msg_mime_part_iface_decode_to_stream ((TnyMsgMimePartIface*)tny_body, - txt_stream); - tny_stream_iface_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 = convert_to_html (txt); - tny_stream_iface_write (gtkhtml_stream, html, strlen(html)); - tny_stream_iface_reset (gtkhtml_stream); - g_free (txt); - g_free (html); - } - - g_object_unref (G_OBJECT(gtkhtml_stream)); - g_object_unref (G_OBJECT(txt_stream)); - g_object_unref (G_OBJECT(buf)); - - return TRUE; -} - - -static gboolean -set_empty_message (ModestTnyMsgView *self) -{ - ModestTnyMsgViewPrivate *priv; - - g_return_val_if_fail (self, FALSE); - priv = MODEST_TNY_MSG_VIEW_GET_PRIVATE(self); - - gtk_html_load_from_string (priv->gtkhtml, "", 1); - - return TRUE; -} - - -gchar * -modest_tny_msg_view_get_selected_text (ModestTnyMsgView *self) -{ - ModestTnyMsgViewPrivate *priv; - gchar *sel; - GtkWidget *html; - int len; - GtkClipboard *clip; - - g_return_val_if_fail (self, NULL); - priv = MODEST_TNY_MSG_VIEW_GET_PRIVATE(self); - html = priv->gtkhtml; - - /* I'm sure there is a better way to check for selected text */ - sel = gtk_html_get_selection_html(GTK_HTML(html), &len); - if (!sel) - return NULL; - - g_free(sel); - - clip = gtk_widget_get_clipboard(html, GDK_SELECTION_PRIMARY); - return gtk_clipboard_wait_for_text(clip); -} - - -void -modest_tny_msg_view_set_message (ModestTnyMsgView *self, const TnyMsgIface *msg) -{ - TnyMsgMimePartIface *body; - ModestTnyMsgViewPrivate *priv; - - g_return_if_fail (self); - - priv = MODEST_TNY_MSG_VIEW_GET_PRIVATE(self); - - priv->msg = msg; - - if (!msg) { - set_empty_message (self); - return; - } - - body = modest_tny_msg_actions_find_body_part (msg, TRUE); - if (body) { - if (tny_msg_mime_part_iface_content_type_is (body, "text/html")) - set_html_message (self, body, msg); - else - set_text_message (self, body, msg); - return; - } else - set_empty_message (self); -} diff --git a/src/modest-tny-msg-view.h b/src/modest-tny-msg-view.h deleted file mode 100644 index c071168..0000000 --- a/src/modest-tny-msg-view.h +++ /dev/null @@ -1,115 +0,0 @@ -/* Copyright (c) 2006, 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. - */ - - -/* modest-tny-msg-view.h */ - -#ifndef __MODEST_TNY_MSG_VIEW_H__ -#define __MODEST_TNY_MSG_VIEW_H__ - - -#include -#include -#include -#include - -#include "modest-conf.h" - -G_BEGIN_DECLS - -/* convenience macros */ -#define MODEST_TYPE_TNY_MSG_VIEW (modest_tny_msg_view_get_type()) -#define MODEST_TNY_MSG_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),MODEST_TYPE_TNY_MSG_VIEW,ModestTnyMsgView)) -#define MODEST_TNY_MSG_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),MODEST_TYPE_TNY_MSG_VIEW,ModestTnyMsgViewClass)) -#define MODEST_IS_TNY_MSG_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),MODEST_TYPE_TNY_MSG_VIEW)) -#define MODEST_IS_TNY_MSG_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),MODEST_TYPE_TNY_MSG_VIEW)) -#define MODEST_TNY_MSG_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),MODEST_TYPE_TNY_MSG_VIEW,ModestTnyMsgViewClass)) - -typedef struct _ModestTnyMsgView ModestTnyMsgView; -typedef struct _ModestTnyMsgViewClass ModestTnyMsgViewClass; - -struct _ModestTnyMsgView { - GtkScrolledWindow parent; -}; - -struct _ModestTnyMsgViewClass { - GtkScrolledWindowClass parent_class; - - void (*link_clicked) (GtkWidget *widget, const gchar* link, gpointer user_data); - void (*attachment_clicked) (GtkWidget *widget, int index, gpointer user_data); -}; - - -/** - * modest_tny_msg_view_get_type - * - * get the GType for the this class - * - * Returns: the GType for this class - */ -GType modest_tny_msg_view_get_type (void) G_GNUC_CONST; - - -/** - * modest_tny_msg_view_new - * @tny_msg: a TnyMsgIface instance, or NULL - * - * create a new ModestTnyMsgView widget (a GtkScrolledWindow subclass), - * and display the @tny_msg e-mail message in it. If @tny_msg is NULL, - * then a blank page will be displayed - * - * Returns: a new ModestTnyMsgView widget, or NULL if there's an error - */ -GtkWidget* modest_tny_msg_view_new (const TnyMsgIface *tny_msg); - - -/** - * modest_tny_msg_view_set_message - * @self: a ModestTnyMsgView instance - * @tny_msg: a TnyMsgIface instance, or NULL - * - * display the @tny_msg e-mail message. If @tny_msg is NULL, - * then a blank page will be displayed - * */ -void modest_tny_msg_view_set_message (ModestTnyMsgView *self, - const TnyMsgIface *tny_msg); - -/** - * modest_tny_msg_view_get_selected_text: - * @self: a ModestTnyMsgView instance - * - * get the user selected part of the message - * - * Returns: a newly allocated string of the user's selection or NULL if nothing is selected - */ -gchar * modest_tny_msg_view_get_selected_text (ModestTnyMsgView *self); - -G_END_DECLS - -#endif /* __MODEST_TNY_MSG_VIEW_H__ */ diff --git a/src/modest-tny-store-actions.c b/src/modest-tny-store-actions.c index 58c4001..208e7ff 100644 --- a/src/modest-tny-store-actions.c +++ b/src/modest-tny-store-actions.c @@ -50,11 +50,13 @@ void modest_tny_store_actions_update_folders (TnyStoreAccountIface *storage_account) { +// FIXME TODO: This results in failure on folder change. + /* const TnyListIface* folders; TnyIteratorIface* ifolders; const TnyMsgFolderIface *cur_folder; -#warning TODO: This results in failure on folder change. -/* folders = tny_store_account_iface_get_folders (storage_account, + + folders = tny_store_account_iface_get_folders (storage_account, TNY_STORE_ACCOUNT_FOLDER_TYPE_SUBSCRIBED); ifolders = tny_list_iface_create_iterator (folders); diff --git a/src/modest-ui.h b/src/modest-ui.h index 0e3ffa5..186142d 100644 --- a/src/modest-ui.h +++ b/src/modest-ui.h @@ -33,7 +33,7 @@ #include #include #include "modest-conf.h" -#include "modest-tny-msg-view.h" +#include "widgets/modest-msg-view.h" G_BEGIN_DECLS diff --git a/src/modest-viewer-window.c b/src/modest-viewer-window.c index b6fa336..dc9036c 100644 --- a/src/modest-viewer-window.c +++ b/src/modest-viewer-window.c @@ -29,7 +29,7 @@ #include "modest-ui.h" -#include "modest-tny-msg-view.h" +#include "widgets/modest-msg-view.h" #include "modest-viewer-window.h" @@ -45,8 +45,8 @@ enum { typedef struct _ModestViewerWindowPrivate ModestViewerWindowPrivate; struct _ModestViewerWindowPrivate { - ModestTnyMsgView *msg_view; - gpointer user_data; + ModestMsgView *msg_view; + gpointer user_data; }; #define MODEST_VIEWER_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ MODEST_TYPE_VIEWER_WINDOW, \ @@ -134,7 +134,7 @@ modest_viewer_window_new (ModestUI *ui, TnyMsgIface *msg) self = G_OBJECT(g_object_new(MODEST_TYPE_VIEWER_WINDOW, NULL)); priv = MODEST_VIEWER_WINDOW_GET_PRIVATE(self); - msg_view = modest_tny_msg_view_new(msg); + msg_view = modest_msg_view_new(msg); data = NULL; w = GTK_WIDGET(modest_ui_new_viewer_window(ui, msg_view, msg, &data)); @@ -145,7 +145,7 @@ modest_viewer_window_new (ModestUI *ui, TnyMsgIface *msg) gtk_container_add(GTK_CONTAINER(self), w); priv->user_data = data; - priv->msg_view = MODEST_TNY_MSG_VIEW(msg_view); + priv->msg_view = MODEST_MSG_VIEW(msg_view); return GTK_WIDGET(self); } @@ -168,13 +168,13 @@ modest_viewer_window_get_data(ModestViewerWindow *viewer_win) } -ModestTnyMsgView* +ModestMsgView* modest_viewer_window_get_tiny_msg_view(ModestViewerWindow *viewer_win) { ModestViewerWindowPrivate *priv; g_return_val_if_fail (viewer_win, NULL); - + priv = MODEST_VIEWER_WINDOW_GET_PRIVATE(viewer_win); return priv->msg_view; diff --git a/src/modest-viewer-window.h b/src/modest-viewer-window.h index 00385a4..6dcf8b2 100644 --- a/src/modest-viewer-window.h +++ b/src/modest-viewer-window.h @@ -74,7 +74,7 @@ gpointer modest_viewer_window_get_data(ModestViewerWindow *viewer_win); * * Returns: the ModestTnyMsgView widget from the viewer instance */ -ModestTnyMsgView *modest_viewer_window_get_tiny_msg_view(ModestViewerWindow *viewer_win); +ModestMsgView *modest_viewer_window_get_tiny_msg_view(ModestViewerWindow *viewer_win); G_END_DECLS diff --git a/src/modest-widget-factory.c b/src/modest-widget-factory.c index 5708a7a..e15b913 100644 --- a/src/modest-widget-factory.c +++ b/src/modest-widget-factory.c @@ -35,9 +35,9 @@ static void modest_widget_factory_class_init (ModestWidgetFactoryClass *klass static void modest_widget_factory_init (ModestWidgetFactory *obj); static void modest_widget_factory_finalize (GObject *obj); -static void on_folder_clicked (ModestTnyFolderTreeView *folder_view, TnyMsgFolderIface *folder, - ModestWidgetFactory *self); -static void on_message_selected (ModestTnyFolderTreeView *folder_view, TnyMsgIface *msg, +static void on_folder_clicked (ModestFolderView *folder_view, TnyMsgFolderIface *folder, + ModestWidgetFactory *self); +static void on_message_selected (ModestFolderView *folder_view, TnyMsgIface *msg, ModestWidgetFactory *self); /* list my signals */ @@ -54,9 +54,9 @@ struct _ModestWidgetFactoryPrivate { ModestAccountMgr *account_mgr; ModestConf *conf; - ModestTnyHeaderTreeView *header_view; - ModestTnyFolderTreeView *folder_view; - ModestTnyMsgView *msg_preview; + ModestHeaderView *header_view; + ModestFolderView *folder_view; + ModestMsgView *msg_preview; ModestAccountView *account_view; gboolean auto_connect; @@ -178,8 +178,8 @@ modest_widget_factory_new (ModestConf *conf, -ModestTnyFolderTreeView* -modest_widget_factory_get_folder_tree_widget (ModestWidgetFactory *self) +ModestFolderView* +modest_widget_factory_get_folder_view (ModestWidgetFactory *self) { ModestWidgetFactoryPrivate *priv; @@ -189,8 +189,8 @@ modest_widget_factory_get_folder_tree_widget (ModestWidgetFactory *self) if (!priv->folder_view) { priv->folder_view = - MODEST_TNY_FOLDER_TREE_VIEW(modest_tny_folder_tree_view_new - (TNY_ACCOUNT_STORE_IFACE(priv->account_store))); + MODEST_FOLDER_VIEW(modest_folder_view_new + (TNY_ACCOUNT_STORE_IFACE(priv->account_store))); if (priv->folder_view && priv->auto_connect) g_signal_connect (G_OBJECT(priv->folder_view), "folder_selected", G_CALLBACK(on_folder_clicked), self); @@ -203,8 +203,8 @@ modest_widget_factory_get_folder_tree_widget (ModestWidgetFactory *self) } -ModestTnyHeaderTreeView* -modest_widget_factory_get_header_tree_widget (ModestWidgetFactory *self) +ModestHeaderView* +modest_widget_factory_get_header_view (ModestWidgetFactory *self) { ModestWidgetFactoryPrivate *priv; @@ -214,9 +214,9 @@ modest_widget_factory_get_header_tree_widget (ModestWidgetFactory *self) if (!priv->header_view) { priv->header_view = - MODEST_TNY_HEADER_TREE_VIEW(modest_tny_header_tree_view_new - (NULL, NULL, - MODEST_TNY_HEADER_TREE_VIEW_STYLE_NORMAL)); + MODEST_HEADER_VIEW(modest_header_view_new + (NULL, NULL, + MODEST_HEADER_VIEW_STYLE_NORMAL)); if (priv->header_view && priv->auto_connect) g_signal_connect (G_OBJECT(priv->header_view), "message_selected", G_CALLBACK(on_message_selected), self); @@ -229,8 +229,8 @@ modest_widget_factory_get_header_tree_widget (ModestWidgetFactory *self) } -ModestTnyMsgView* -modest_widget_factory_get_msg_preview_widget (ModestWidgetFactory *self) +ModestMsgView* +modest_widget_factory_get_msg_preview (ModestWidgetFactory *self) { ModestWidgetFactoryPrivate *priv; @@ -239,8 +239,7 @@ modest_widget_factory_get_msg_preview_widget (ModestWidgetFactory *self) priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(self); if (!priv->msg_preview) - priv->msg_preview = - MODEST_TNY_MSG_VIEW(modest_tny_msg_view_new (NULL)); + priv->msg_preview = MODEST_MSG_VIEW(modest_msg_view_new (NULL)); if (!priv->msg_preview) g_printerr ("modest: cannot instantiate header view\n"); @@ -250,29 +249,29 @@ modest_widget_factory_get_msg_preview_widget (ModestWidgetFactory *self) static void -on_folder_clicked (ModestTnyFolderTreeView *folder_view, TnyMsgFolderIface *folder, +on_folder_clicked (ModestFolderView *folder_view, TnyMsgFolderIface *folder, ModestWidgetFactory *self) { ModestWidgetFactoryPrivate *priv; priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(self); - modest_tny_header_tree_view_set_folder (priv->header_view, folder); + modest_header_view_set_folder (priv->header_view, folder); } static void -on_message_selected (ModestTnyFolderTreeView *folder_view, TnyMsgIface *msg, +on_message_selected (ModestFolderView *folder_view, TnyMsgIface *msg, ModestWidgetFactory *self) { ModestWidgetFactoryPrivate *priv; priv = MODEST_WIDGET_FACTORY_GET_PRIVATE(self); - modest_tny_msg_view_set_message (priv->msg_preview, msg); + modest_msg_view_set_message (priv->msg_preview, msg); } ModestAccountView* -modest_widget_factory_get_account_view_widget (ModestWidgetFactory *self) +modest_widget_factory_get_account_view (ModestWidgetFactory *self) { ModestWidgetFactoryPrivate *priv; @@ -286,6 +285,6 @@ modest_widget_factory_get_account_view_widget (ModestWidgetFactory *self) if (!priv->account_view) g_printerr ("modest: cannot create account view widget\n"); - + return priv->account_view; } diff --git a/src/modest-widget-factory.h b/src/modest-widget-factory.h index 53cf3b0..a8a72b3 100644 --- a/src/modest-widget-factory.h +++ b/src/modest-widget-factory.h @@ -33,11 +33,11 @@ #include #include "modest-account-mgr.h" #include "modest-tny-account-store.h" -#include "modest-tny-header-tree-view.h" -#include "modest-tny-folder-tree-view.h" -#include "modest-tny-msg-view.h" -#include "modest-account-view.h" +#include "widgets/modest-header-view.h" +#include "widgets/modest-folder-view.h" +#include "widgets/modest-msg-view.h" +#include "widgets/modest-account-view.h" G_BEGIN_DECLS @@ -90,7 +90,7 @@ ModestWidgetFactory* modest_widget_factory_new (ModestConf *conf, ModestAccountMgr *account_mgr, gboolean auto_connect); /** - * modest_widget_factory_get_folder_tree_widget + * modest_widget_factory_get_folder_view * @self: a ModestWidgetFactory instance * * return the folder tree widget (ie. the widget with the list of folders); @@ -100,11 +100,11 @@ ModestWidgetFactory* modest_widget_factory_new (ModestConf *conf, * * Returns: a folder tree view, or NULL in case of error */ -ModestTnyFolderTreeView* modest_widget_factory_get_folder_tree_widget (ModestWidgetFactory *self); +ModestFolderView* modest_widget_factory_get_folder_view (ModestWidgetFactory *self); /** - * modest_widget_factory_get_header_tree_widget + * modest_widget_factory_get_header_view * @self: a ModestWidgetFactory instance * * return the header tree widget (ie. the widget with the list of headers); @@ -114,11 +114,11 @@ ModestTnyFolderTreeView* modest_widget_factory_get_folder_tree_widget (Modest * * Returns: a header tree view, or NULL in case of error */ -ModestTnyHeaderTreeView* modest_widget_factory_get_header_tree_widget (ModestWidgetFactory *self); +ModestHeaderView* modest_widget_factory_get_header_view (ModestWidgetFactory *self); /** - * modest_widget_factory_get_header_tree_widget + * modest_widget_factory_get_msg_preview * @self: a ModestWidgetFactory instance * * return the message preview widget (ie. the widget with shows the currently selected message); @@ -128,12 +128,11 @@ ModestTnyHeaderTreeView* modest_widget_factory_get_header_tree_widget (Modest * * Returns: a header tree view, or NULL in case of error */ -ModestTnyMsgView* modest_widget_factory_get_msg_preview_widget (ModestWidgetFactory *self); - +ModestMsgView* modest_widget_factory_get_msg_preview (ModestWidgetFactory *self); /** - * modest_widget_factory_get_account_view_widget + * modest_widget_factory_get_account_view * @self: a ModestWidgetFactory instance * * return an account view widget (ie. the widget that shows a list of accounts) @@ -143,10 +142,7 @@ ModestTnyMsgView* modest_widget_factory_get_msg_preview_widget (Modest * * Returns: the account view, or NULL in case of error */ -ModestAccountView* modest_widget_factory_get_account_view_widget (ModestWidgetFactory *self); - - - +ModestAccountView* modest_widget_factory_get_account_view (ModestWidgetFactory *self); G_END_DECLS diff --git a/src/widgets/modest-account-view.c b/src/widgets/modest-account-view.c new file mode 100644 index 0000000..356168d --- /dev/null +++ b/src/widgets/modest-account-view.c @@ -0,0 +1,307 @@ +/* Copyright (c) 2006, 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 "modest-account-view.h" +/* include other impl specific header files */ + +/* 'private'/'protected' functions */ +static void modest_account_view_class_init (ModestAccountViewClass *klass); +static void modest_account_view_init (ModestAccountView *obj); +static void modest_account_view_finalize (GObject *obj); + + +enum _AccountViewColumns { + ENABLED_COLUMN, + NAME_COLUMN, + PROTO_COLUMN, + N_COLUMNS +}; +typedef enum _AccountViewColumns AccountViewColumns; + + +/* list my signals */ +enum { + /* MY_SIGNAL_1, */ + /* MY_SIGNAL_2, */ + LAST_SIGNAL +}; + +typedef struct _ModestAccountViewPrivate ModestAccountViewPrivate; +struct _ModestAccountViewPrivate { + ModestAccountMgr *account_mgr; +}; +#define MODEST_ACCOUNT_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ + MODEST_TYPE_ACCOUNT_VIEW, \ + ModestAccountViewPrivate)) +/* globals */ +static GtkTreeViewClass *parent_class = NULL; + +/* uncomment the following if you have defined any signals */ +/* static guint signals[LAST_SIGNAL] = {0}; */ + +GType +modest_account_view_get_type (void) +{ + static GType my_type = 0; + if (!my_type) { + static const GTypeInfo my_info = { + sizeof(ModestAccountViewClass), + NULL, /* base init */ + NULL, /* base finalize */ + (GClassInitFunc) modest_account_view_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof(ModestAccountView), + 1, /* n_preallocs */ + (GInstanceInitFunc) modest_account_view_init, + }; + my_type = g_type_register_static (GTK_TYPE_TREE_VIEW, + "ModestAccountView", + &my_info, 0); + } + return my_type; +} + +static void +modest_account_view_class_init (ModestAccountViewClass *klass) +{ + GObjectClass *gobject_class; + gobject_class = (GObjectClass*) klass; + + parent_class = g_type_class_peek_parent (klass); + gobject_class->finalize = modest_account_view_finalize; + + g_type_class_add_private (gobject_class, sizeof(ModestAccountViewPrivate)); + + /* signal definitions go here, e.g.: */ +/* signals[MY_SIGNAL_1] = */ +/* g_signal_new ("my_signal_1",....); */ +/* signals[MY_SIGNAL_2] = */ +/* g_signal_new ("my_signal_2",....); */ +/* etc. */ +} + +static void +modest_account_view_init (ModestAccountView *obj) +{ + ModestAccountViewPrivate *priv; + + priv = MODEST_ACCOUNT_VIEW_GET_PRIVATE(obj); + + priv->account_mgr = NULL; +} + +static void +modest_account_view_finalize (GObject *obj) +{ + ModestAccountViewPrivate *priv; + + priv = MODEST_ACCOUNT_VIEW_GET_PRIVATE(obj); + + if (priv->account_mgr) { + g_object_unref (G_OBJECT(priv->account_mgr)); + priv->account_mgr = NULL; + } +} + + + +static void +update_account_view (ModestAccountMgr *account_mgr, ModestAccountView *view) +{ + GSList *account_names, *cursor; + GtkListStore *model; + + model = GTK_LIST_STORE(gtk_tree_view_get_model (GTK_TREE_VIEW(view))); + gtk_list_store_clear (model); + + cursor = account_names = + modest_account_mgr_account_names (account_mgr, NULL); + + while (cursor) { + gchar *proto = NULL; + gchar *store, *account_name; + gboolean enabled; + + account_name = (gchar*)cursor->data; + + store = modest_account_mgr_get_string (account_mgr, + account_name, + MODEST_ACCOUNT_STORE_ACCOUNT, + FALSE, NULL); + if (store) { + proto = modest_account_mgr_get_string (account_mgr, + store, + MODEST_ACCOUNT_PROTO, + TRUE, NULL); + g_free(store); + } + + enabled = modest_account_mgr_account_get_enabled (account_mgr, + account_name, + FALSE); + gtk_list_store_insert_with_values ( + model, NULL, 0, + ENABLED_COLUMN, enabled, + NAME_COLUMN, account_name, + PROTO_COLUMN, proto, + -1); + + g_free (account_name); + g_free (proto); + + cursor = cursor->next; + } + g_slist_free (account_names); +} + + +static void +on_account_changed (ModestAccountMgr *account_mgr, + const gchar* account, const gchar* key, + gboolean server_account, ModestAccountView *self) +{ + ModestAccountViewPrivate *priv; + priv = MODEST_ACCOUNT_VIEW_GET_PRIVATE(self); + + update_account_view (account_mgr, self); +} + + +static void +on_account_removed (ModestAccountMgr *account_mgr, + const gchar* account, gboolean server_account, + gpointer user_data) +{ + on_account_changed (account_mgr, account, NULL, server_account, user_data); +} + + + + +static void +on_account_enable_toggled (GtkCellRendererToggle *cell_renderer, gchar *path, + ModestAccountView *self) +{ + GtkTreeIter iter; + ModestAccountViewPrivate *priv; + GtkTreeModel *model; + gchar *account_name; + gboolean enabled; + + priv = MODEST_ACCOUNT_VIEW_GET_PRIVATE(self); + model = gtk_tree_view_get_model (GTK_TREE_VIEW(self)); + + if (!gtk_tree_model_get_iter_from_string (model, &iter, path)) { + g_printerr ("modest: cannot find iterator\n"); + return; + } + + gtk_tree_model_get (model, &iter, + ENABLED_COLUMN, &enabled, + NAME_COLUMN, &account_name, + -1); + + /* toggle enabled / disabled */ + modest_account_mgr_account_set_enabled (priv->account_mgr, account_name, + FALSE, !enabled); + g_free (account_name); +} + + +static void +init_view (ModestAccountView *self) +{ + ModestAccountViewPrivate *priv; + GtkTreeSelection *sel; + GtkCellRenderer *renderer; + GtkListStore *model; + + priv = MODEST_ACCOUNT_VIEW_GET_PRIVATE(self); + + model = gtk_list_store_new (3, + G_TYPE_BOOLEAN, /* checkbox */ + G_TYPE_STRING, /* account name */ + G_TYPE_STRING); /* account type (pop, imap,...) */ + + gtk_tree_view_set_model (GTK_TREE_VIEW(self), GTK_TREE_MODEL(model)); + + renderer = gtk_cell_renderer_toggle_new (); + g_object_set (G_OBJECT(renderer), "activatable", TRUE,"radio", FALSE, NULL); + + g_signal_connect (G_OBJECT(renderer), "toggled", + G_CALLBACK(on_account_enable_toggled), + self); + + gtk_tree_view_append_column (GTK_TREE_VIEW(self), + gtk_tree_view_column_new_with_attributes ( + _("Enabled"), renderer, + "active", ENABLED_COLUMN, NULL)); + gtk_tree_view_append_column (GTK_TREE_VIEW(self), + gtk_tree_view_column_new_with_attributes ( + _("Account"), + gtk_cell_renderer_text_new (), + "text", NAME_COLUMN, NULL)); + gtk_tree_view_append_column (GTK_TREE_VIEW(self), + gtk_tree_view_column_new_with_attributes ( + _("Type"), + gtk_cell_renderer_text_new (), + "text", PROTO_COLUMN, NULL)); + + sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(self)); + + g_signal_connect (G_OBJECT(priv->account_mgr), + "account_removed", + G_CALLBACK(on_account_removed), self); + g_signal_connect (G_OBJECT(priv->account_mgr), + "account_changed", + G_CALLBACK(on_account_changed), self); +} + + + +GtkWidget* +modest_account_view_new (ModestAccountMgr *account_mgr) +{ + GObject *obj; + ModestAccountViewPrivate *priv; + + g_return_val_if_fail (account_mgr, NULL); + + obj = g_object_new(MODEST_TYPE_ACCOUNT_VIEW, NULL); + priv = MODEST_ACCOUNT_VIEW_GET_PRIVATE(obj); + + g_object_ref (G_OBJECT(account_mgr)); + priv->account_mgr = account_mgr; + + init_view (MODEST_ACCOUNT_VIEW (obj)); + + return GTK_WIDGET(obj); +} + diff --git a/src/widgets/modest-account-view.h b/src/widgets/modest-account-view.h new file mode 100644 index 0000000..bb0263d --- /dev/null +++ b/src/widgets/modest-account-view.h @@ -0,0 +1,71 @@ +/* Copyright (c) 2006, 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_ACCOUNT_VIEW_H__ +#define __MODEST_ACCOUNT_VIEW_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +/* convenience macros */ +#define MODEST_TYPE_ACCOUNT_VIEW (modest_account_view_get_type()) +#define MODEST_ACCOUNT_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),MODEST_TYPE_ACCOUNT_VIEW,ModestAccountView)) +#define MODEST_ACCOUNT_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),MODEST_TYPE_ACCOUNT_VIEW,GtkTreeView)) +#define MODEST_IS_ACCOUNT_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),MODEST_TYPE_ACCOUNT_VIEW)) +#define MODEST_IS_ACCOUNT_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),MODEST_TYPE_ACCOUNT_VIEW)) +#define MODEST_ACCOUNT_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),MODEST_TYPE_ACCOUNT_VIEW,ModestAccountViewClass)) + +typedef struct _ModestAccountView ModestAccountView; +typedef struct _ModestAccountViewClass ModestAccountViewClass; + +struct _ModestAccountView { + GtkTreeView parent; + /* insert public members, if any */ +}; + +struct _ModestAccountViewClass { + GtkTreeViewClass parent_class; + /* insert signal callback declarations, eg. */ + /* void (* my_event) (ModestAccountView* obj); */ +}; + +/* member functions */ +GType modest_account_view_get_type (void) G_GNUC_CONST; + + + +GtkWidget* modest_account_view_new (ModestAccountMgr *account_mgr); + +G_END_DECLS + +#endif /* __MODEST_ACCOUNT_VIEW_H__ */ + diff --git a/src/widgets/modest-folder-view.c b/src/widgets/modest-folder-view.c new file mode 100644 index 0000000..b560094 --- /dev/null +++ b/src/widgets/modest-folder-view.c @@ -0,0 +1,485 @@ +/* Copyright (c) 2006, 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 "modest-icon-factory.h" + +#include "modest-folder-view.h" + + +/* 'private'/'protected' functions */ +static void modest_folder_view_class_init (ModestFolderViewClass *klass); +static void modest_folder_view_init (ModestFolderView *obj); +static void modest_folder_view_finalize (GObject *obj); + +static gboolean update_model (ModestFolderView *self,TnyAccountStoreIface *iface); +static gboolean update_model_empty (ModestFolderView *self); + +static void selection_changed (GtkTreeSelection *sel, gpointer data); + +enum { + FOLDER_SELECTED_SIGNAL, + LAST_SIGNAL +}; + +typedef struct _ModestFolderViewPrivate ModestFolderViewPrivate; +struct _ModestFolderViewPrivate { + + TnyAccountStoreIface *tny_account_store; + TnyMsgFolderIface *cur_folder; + gboolean view_is_empty; + + GMutex *lock; +}; +#define MODEST_FOLDER_VIEW_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), \ + MODEST_TYPE_FOLDER_VIEW, \ + ModestFolderViewPrivate)) +/* globals */ +static GObjectClass *parent_class = NULL; + +static guint signals[LAST_SIGNAL] = {0}; + +GType +modest_folder_view_get_type (void) +{ + static GType my_type = 0; + if (!my_type) { + static const GTypeInfo my_info = { + sizeof(ModestFolderViewClass), + NULL, /* base init */ + NULL, /* base finalize */ + (GClassInitFunc) modest_folder_view_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof(ModestFolderView), + 1, /* n_preallocs */ + (GInstanceInitFunc) modest_folder_view_init, + }; + + my_type = g_type_register_static (GTK_TYPE_TREE_VIEW, + "ModestFolderView", + &my_info, 0); + } + return my_type; +} + +static void +modest_folder_view_class_init (ModestFolderViewClass *klass) +{ + GObjectClass *gobject_class; + gobject_class = (GObjectClass*) klass; + + parent_class = g_type_class_peek_parent (klass); + gobject_class->finalize = modest_folder_view_finalize; + + klass->update_model = modest_folder_view_update_model; + + g_type_class_add_private (gobject_class, + sizeof(ModestFolderViewPrivate)); + + signals[FOLDER_SELECTED_SIGNAL] = + g_signal_new ("folder_selected", + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (ModestFolderViewClass, + folder_selected), + NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER); +} + + + +static void +text_cell_data (GtkTreeViewColumn *column, GtkCellRenderer *renderer, + GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data) +{ + GObject *rendobj; + gchar *fname; + gint unread; + TnyMsgFolderType type; + + gtk_tree_model_get (tree_model, iter, + TNY_ACCOUNT_TREE_MODEL_NAME_COLUMN, &fname, + TNY_ACCOUNT_TREE_MODEL_TYPE_COLUMN, &type, + TNY_ACCOUNT_TREE_MODEL_UNREAD_COLUMN, &unread, -1); + rendobj = G_OBJECT(renderer); + + if (unread > 0) { + gchar *folder_title = g_strdup_printf ("%s (%d)", fname, unread); + g_object_set (rendobj,"text", folder_title, "weight", 800, NULL); + g_free (folder_title); + } else + g_object_set (rendobj,"text", fname, "weight", 400, NULL); + + g_free (fname); +} + +/* FIXME: move these to TnyMail */ +enum { + + TNY_MSG_FOLDER_TYPE_NOTES = TNY_MSG_FOLDER_TYPE_SENT + 1, /* urgh */ + TNY_MSG_FOLDER_TYPE_DRAFTS, + TNY_MSG_FOLDER_TYPE_CONTACTS, + TNY_MSG_FOLDER_TYPE_CALENDAR +}; + +static TnyMsgFolderType +guess_folder_type (const gchar* name) +{ + TnyMsgFolderType type; + gchar *folder; + + g_return_val_if_fail (name, TNY_MSG_FOLDER_TYPE_NORMAL); + + type = TNY_MSG_FOLDER_TYPE_NORMAL; + folder = g_utf8_strdown (name, strlen(name)); + + if (strcmp (folder, "inbox") == 0 || + strcmp (folder, _("inbox")) == 0) + type = TNY_MSG_FOLDER_TYPE_INBOX; + else if (strcmp (folder, "outbox") == 0 || + strcmp (folder, _("outbox")) == 0) + type = TNY_MSG_FOLDER_TYPE_OUTBOX; + else if (g_str_has_prefix(folder, "junk") || + g_str_has_prefix(folder, _("junk"))) + type = TNY_MSG_FOLDER_TYPE_JUNK; + else if (g_str_has_prefix(folder, "trash") || + g_str_has_prefix(folder, _("trash"))) + type = TNY_MSG_FOLDER_TYPE_JUNK; + else if (g_str_has_prefix(folder, "sent") || + g_str_has_prefix(folder, _("sent"))) + type = TNY_MSG_FOLDER_TYPE_SENT; + + /* these are not *really* TNY_ types */ + else if (g_str_has_prefix(folder, "draft") || + g_str_has_prefix(folder, _("draft"))) + type = TNY_MSG_FOLDER_TYPE_DRAFTS; + else if (g_str_has_prefix(folder, "notes") || + g_str_has_prefix(folder, _("notes"))) + type = TNY_MSG_FOLDER_TYPE_NOTES; + else if (g_str_has_prefix(folder, "contacts") || + g_str_has_prefix(folder, _("contacts"))) + type = TNY_MSG_FOLDER_TYPE_CONTACTS; + else if (g_str_has_prefix(folder, "calendar") || + g_str_has_prefix(folder, _("calendar"))) + type = TNY_MSG_FOLDER_TYPE_CALENDAR; + + g_free (folder); + return type; +} + + +static void +icon_cell_data (GtkTreeViewColumn *column, GtkCellRenderer *renderer, + GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data) +{ + GObject *rendobj; + GdkPixbuf *pixbuf; + TnyMsgFolderType type; + gchar *fname = NULL; + gint unread; + + rendobj = G_OBJECT(renderer); + gtk_tree_model_get (tree_model, iter, + TNY_ACCOUNT_TREE_MODEL_TYPE_COLUMN, &type, + TNY_ACCOUNT_TREE_MODEL_NAME_COLUMN, &fname, + TNY_ACCOUNT_TREE_MODEL_UNREAD_COLUMN, &unread, -1); + rendobj = G_OBJECT(renderer); + + if (type == TNY_MSG_FOLDER_TYPE_NORMAL) + type = guess_folder_type (fname); + + if (fname); + g_free (fname); + + switch (type) { + case TNY_MSG_FOLDER_TYPE_INBOX: + pixbuf = modest_icon_factory_get_icon (MODEST_FOLDER_ICON_INBOX); + break; + case TNY_MSG_FOLDER_TYPE_OUTBOX: + pixbuf = modest_icon_factory_get_icon (MODEST_FOLDER_ICON_OUTBOX); + break; + case TNY_MSG_FOLDER_TYPE_JUNK: + pixbuf = modest_icon_factory_get_icon (MODEST_FOLDER_ICON_JUNK); + break; + case TNY_MSG_FOLDER_TYPE_SENT: + pixbuf = modest_icon_factory_get_icon (MODEST_FOLDER_ICON_SENT); + break; + case TNY_MSG_FOLDER_TYPE_DRAFTS: + pixbuf = modest_icon_factory_get_icon (MODEST_FOLDER_ICON_DRAFTS); + break; + case TNY_MSG_FOLDER_TYPE_NOTES: + pixbuf = modest_icon_factory_get_icon (MODEST_FOLDER_ICON_NOTES); + break; + case TNY_MSG_FOLDER_TYPE_CALENDAR: + pixbuf = modest_icon_factory_get_icon (MODEST_FOLDER_ICON_CALENDAR); + break; + case TNY_MSG_FOLDER_TYPE_CONTACTS: + pixbuf = modest_icon_factory_get_icon (MODEST_FOLDER_ICON_CONTACTS); + break; + case TNY_MSG_FOLDER_TYPE_NORMAL: + default: + pixbuf = modest_icon_factory_get_icon (MODEST_FOLDER_ICON_NORMAL); + break; + } + + g_object_set (rendobj, + "pixbuf-expander-open", + modest_icon_factory_get_icon (MODEST_FOLDER_ICON_OPEN), + "pixbuf-expander-closed", + modest_icon_factory_get_icon (MODEST_FOLDER_ICON_CLOSED), + "pixbuf", pixbuf, + NULL); +} + +static void +modest_folder_view_init (ModestFolderView *obj) +{ + ModestFolderViewPrivate *priv; + GtkTreeViewColumn *column; + GtkCellRenderer *renderer; + GtkTreeSelection *sel; + + priv = MODEST_FOLDER_VIEW_GET_PRIVATE(obj); + + priv->view_is_empty = TRUE; + priv->tny_account_store = NULL; + priv->cur_folder = NULL; + + priv->lock = g_mutex_new (); + + column = gtk_tree_view_column_new (); + gtk_tree_view_column_set_title (column, + _("All Mail Folders")); + + gtk_tree_view_append_column (GTK_TREE_VIEW(obj), + column); + + renderer = gtk_cell_renderer_pixbuf_new(); + gtk_tree_view_column_pack_start (column, renderer, FALSE); + gtk_tree_view_column_set_cell_data_func(column, renderer, + icon_cell_data, NULL, NULL); + + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_column_pack_start (column, renderer, FALSE); + gtk_tree_view_column_set_cell_data_func(column, renderer, + text_cell_data, NULL, NULL); + + sel = gtk_tree_view_get_selection (GTK_TREE_VIEW(obj)); + gtk_tree_selection_set_mode (sel, GTK_SELECTION_SINGLE); + + gtk_tree_view_column_set_spacing (column, 2); + gtk_tree_view_column_set_resizable (column, TRUE); + gtk_tree_view_column_set_fixed_width (column, TRUE); + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(obj), TRUE); + gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW(obj), FALSE); + +} + + +static void +modest_folder_view_finalize (GObject *obj) +{ + ModestFolderViewPrivate *priv; + + g_return_if_fail (obj); + + priv = MODEST_FOLDER_VIEW_GET_PRIVATE(obj); + if (priv->tny_account_store) { + g_object_unref (G_OBJECT(priv->tny_account_store)); + priv->tny_account_store = NULL; + } + + + if (priv->lock) { + g_mutex_free (priv->lock); + priv->lock = NULL; + } + + G_OBJECT_CLASS(parent_class)->finalize (obj); +} + + +static void +on_accounts_update (TnyAccountStoreIface *account_store, const gchar *account, + gpointer user_data) +{ + update_model_empty (MODEST_FOLDER_VIEW(user_data)); + + if (!update_model (MODEST_FOLDER_VIEW(user_data), account_store)) + g_printerr ("modest: failed to update model for changes in '%s'", + account); +} + + +GtkWidget* +modest_folder_view_new (TnyAccountStoreIface *account_store) +{ + GObject *self; + ModestFolderViewPrivate *priv; + GtkTreeSelection *sel; + + self = G_OBJECT(g_object_new(MODEST_TYPE_FOLDER_VIEW, NULL)); + priv = MODEST_FOLDER_VIEW_GET_PRIVATE(self); + + g_return_val_if_fail (account_store, NULL); + + if (!update_model (MODEST_FOLDER_VIEW(self), account_store)) + g_printerr ("modest: failed to update model"); + + g_signal_connect (G_OBJECT(account_store), "update_accounts", + G_CALLBACK (on_accounts_update), self); + + sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(self)); + g_signal_connect (sel, "changed", + G_CALLBACK(selection_changed), self); + + return GTK_WIDGET(self); +} + + + + +static gboolean +update_model_empty (ModestFolderView *self) +{ + GtkTreeIter iter; + GtkTreeStore *store; + ModestFolderViewPrivate *priv; + + g_return_val_if_fail (self, FALSE); + + store = gtk_tree_store_new (1, G_TYPE_STRING); + gtk_tree_store_append (store, &iter, NULL); + + gtk_tree_store_set (store, &iter, 0, + _("(empty)"), -1); + + gtk_tree_view_set_model (GTK_TREE_VIEW(self), + GTK_TREE_MODEL(store)); + g_object_unref (store); + + priv = MODEST_FOLDER_VIEW_GET_PRIVATE(self); + priv->view_is_empty = TRUE; + + return TRUE; +} + + +static gboolean +update_model (ModestFolderView *self, TnyAccountStoreIface *account_store) +{ + ModestFolderViewPrivate *priv; + TnyListIface *account_list; + GtkTreeModel *model, *sortable; + + g_return_val_if_fail (account_store, FALSE); + + priv = MODEST_FOLDER_VIEW_GET_PRIVATE(self); + + model = GTK_TREE_MODEL(tny_account_tree_model_new ()); + account_list = TNY_LIST_IFACE(model); + + update_model_empty (self); /* cleanup */ + priv->view_is_empty = TRUE; + + tny_account_store_iface_get_accounts (account_store, account_list, + TNY_ACCOUNT_STORE_IFACE_STORE_ACCOUNTS); + if (!account_list) /* no store accounts found */ + return TRUE; + + sortable = gtk_tree_model_sort_new_with_model (model); + gtk_tree_view_set_model (GTK_TREE_VIEW(self), sortable); + + priv->view_is_empty = FALSE; + g_object_unref (model); + + return TRUE; +} + + +void +selection_changed (GtkTreeSelection *sel, gpointer user_data) +{ + GtkTreeModel *model; + TnyMsgFolderIface *folder = NULL; + GtkTreeIter iter; + ModestFolderView *tree_view; + ModestFolderViewPrivate *priv; + + g_return_if_fail (sel); + g_return_if_fail (user_data); + + priv = MODEST_FOLDER_VIEW_GET_PRIVATE(user_data); + + /* is_empty means that there is only the 'empty' item */ + if (priv->view_is_empty) + return; + + /* folder was _un_selected if true */ + if (!gtk_tree_selection_get_selected (sel, &model, &iter)) { + priv->cur_folder = NULL; + return; + } + + tree_view = MODEST_FOLDER_VIEW (user_data); + + gtk_tree_model_get (model, &iter, + TNY_ACCOUNT_TREE_MODEL_INSTANCE_COLUMN, + &folder, -1); + + if (priv->cur_folder) + tny_msg_folder_iface_expunge (priv->cur_folder); + priv->cur_folder = folder; + + /* folder will not be defined if you click eg. on the root node */ + if (folder) + g_signal_emit (G_OBJECT(tree_view), signals[FOLDER_SELECTED_SIGNAL], 0, + folder); +} + + +gboolean +modest_folder_view_update_model(ModestFolderView *self, + TnyAccountStoreIface *iface) +{ + g_return_val_if_fail (MODEST_IS_FOLDER_VIEW (self), FALSE); + + return update_model (self, iface); +} diff --git a/src/widgets/modest-folder-view.h b/src/widgets/modest-folder-view.h new file mode 100644 index 0000000..1da8f63 --- /dev/null +++ b/src/widgets/modest-folder-view.h @@ -0,0 +1,118 @@ +/* Copyright (c) 2006, 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_FOLDER_VIEW_H__ +#define __MODEST_FOLDER_VIEW_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +/* convenience macros */ +#define MODEST_TYPE_FOLDER_VIEW (modest_folder_view_get_type()) +#define MODEST_FOLDER_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),MODEST_TYPE_FOLDER_VIEW,ModestFolderView)) +#define MODEST_FOLDER_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),MODEST_TYPE_FOLDER_VIEW,ModestFolderViewClass)) +#define MODEST_IS_FOLDER_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),MODEST_TYPE_FOLDER_VIEW)) +#define MODEST_IS_FOLDER_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),MODEST_TYPE_FOLDER_VIEW)) +#define MODEST_FOLDER_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),MODEST_TYPE_FOLDER_VIEW,ModestFolderViewClass)) + +typedef struct _ModestFolderView ModestFolderView; +typedef struct _ModestFolderViewClass ModestFolderViewClass; + +struct _ModestFolderView { + GtkTreeView parent; + /* insert public members, if any */ +}; + +struct _ModestFolderViewClass { + GtkTreeViewClass parent_class; + + /* emitted when a folder is clicked */ + void (*folder_selected) (ModestFolderView* self, + TnyMsgFolderIface *folder, + gpointer user_data); + + gboolean (*update_model) (ModestFolderView *self, + TnyAccountStoreIface *iface); + +}; + + +/** + * modest_folder_view_get_type: + * + * get the GType for ModestFolderView + * + * Returns: the GType + */ +GType modest_folder_view_get_type (void) G_GNUC_CONST; + + +/** + * modest_folder_view_new: + * @iface: a TnyAccountStoreIface object + * + * create a new ModestFolderView instance, based on an account store + * + * Returns: a new GtkWidget (a GtkTreeView-subclass) + */ +GtkWidget* modest_folder_view_new (TnyAccountStoreIface *iface); + + +/** + * modest_folder_view_is_empty: + * @self: a ModestFolderView instance + * + * check to see of the view is empty. Note that when it is empty, + * there will still be one item, telling "(empty)" or similar + * + * Returns: TRUE if the tree view is empty, FALSE otherwise + */ +gboolean modest_folder_view_is_empty (ModestFolderView *self); + + +/** + * modest_folder_view_update_model: + * @self: a #ModestFolderView instance + * @iface: a #TnyAccountStoreIface instance + * + * Update the thee model from a given account store. + * + * Returns: TRUE on success, FALSE otherwise + */ +gboolean modest_folder_view_update_model(ModestFolderView *self, + TnyAccountStoreIface *iface); + + +G_END_DECLS + +#endif /* __MODEST_FOLDER_VIEW_H__ */ + diff --git a/src/widgets/modest-header-view.c b/src/widgets/modest-header-view.c new file mode 100644 index 0000000..bfe2b7b --- /dev/null +++ b/src/widgets/modest-header-view.c @@ -0,0 +1,949 @@ +/* Copyright (c) 2006, 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. + */ + + +/* modest-tny-header-tree-view.c */ + +#include +#include "modest-header-view.h" +#include +#include +#include + +#include +#include "modest-icon-factory.h" + +static void modest_header_view_class_init (ModestHeaderViewClass *klass); +static void modest_header_view_init (ModestHeaderView *obj); +static void modest_header_view_finalize (GObject *obj); + +static void on_selection_changed (GtkTreeSelection *sel, gpointer user_data); +//static void on_column_clicked (GtkTreeViewColumn *treeviewcolumn, gpointer user_data); +static gboolean refresh_folder_finish_status_update (gpointer user_data); + +enum { + MESSAGE_SELECTED_SIGNAL, + STATUS_UPDATE_SIGNAL, + LAST_SIGNAL +}; + +typedef struct _ModestHeaderViewPrivate ModestHeaderViewPrivate; +struct _ModestHeaderViewPrivate { + + TnyMsgFolderIface *tny_msg_folder; + TnyListIface *headers; + + gint status_id; + GSList *columns; + + GMutex *lock; + + ModestHeaderViewStyle style; +}; +#define MODEST_HEADER_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ + MODEST_TYPE_HEADER_VIEW, \ + ModestHeaderViewPrivate)) +/* globals */ +static GObjectClass *parent_class = NULL; + +/* uncomment the following if you have defined any signals */ +static guint signals[LAST_SIGNAL] = {0}; + +GType +modest_header_view_get_type (void) +{ + static GType my_type = 0; + if (!my_type) { + static const GTypeInfo my_info = { + sizeof(ModestHeaderViewClass), + NULL, /* base init */ + NULL, /* base finalize */ + (GClassInitFunc) modest_header_view_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof(ModestHeaderView), + 1, /* n_preallocs */ + (GInstanceInitFunc) modest_header_view_init, + }; + my_type = g_type_register_static (GTK_TYPE_TREE_VIEW, + "ModestHeaderView", + &my_info, 0); + } + return my_type; +} + +static void +modest_header_view_class_init (ModestHeaderViewClass *klass) +{ + GObjectClass *gobject_class; + gobject_class = (GObjectClass*) klass; + + parent_class = g_type_class_peek_parent (klass); + gobject_class->finalize = modest_header_view_finalize; + + g_type_class_add_private (gobject_class, sizeof(ModestHeaderViewPrivate)); + + signals[MESSAGE_SELECTED_SIGNAL] = + g_signal_new ("message_selected", + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (ModestHeaderViewClass,message_selected), + NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER); + + signals[STATUS_UPDATE_SIGNAL] = + g_signal_new ("status_update", + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (ModestHeaderViewClass,message_selected), + NULL, NULL, + modest_marshal_VOID__STRING_INT, + G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT); +} + + + + + +static void +msgtype_cell_data (GtkTreeViewColumn *column, GtkCellRenderer *renderer, + GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer user_data) +{ + TnyMsgHeaderFlags flags; + GdkPixbuf *pixbuf = NULL; + + gtk_tree_model_get (tree_model, iter, TNY_MSG_HEADER_LIST_MODEL_FLAGS_COLUMN, + &flags, -1); + + if (flags & TNY_MSG_HEADER_FLAG_DELETED) + pixbuf = modest_icon_factory_get_icon (MODEST_HEADER_ICON_DELETED); + else if (flags & TNY_MSG_HEADER_FLAG_SEEN) + pixbuf = modest_icon_factory_get_icon (MODEST_HEADER_ICON_READ); + else + pixbuf = modest_icon_factory_get_icon (MODEST_HEADER_ICON_UNREAD); + + g_object_set (G_OBJECT (renderer), "pixbuf", pixbuf, NULL); +} + +static void +attach_cell_data (GtkTreeViewColumn *column, GtkCellRenderer *renderer, + GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer user_data) +{ + TnyMsgHeaderFlags flags; + GdkPixbuf *pixbuf = NULL; + + gtk_tree_model_get (tree_model, iter, TNY_MSG_HEADER_LIST_MODEL_FLAGS_COLUMN, + &flags, -1); + + if (flags & TNY_MSG_HEADER_FLAG_ATTACHMENTS) + pixbuf = modest_icon_factory_get_icon (MODEST_HEADER_ICON_ATTACH); + + g_object_set (G_OBJECT (renderer), "pixbuf", pixbuf, NULL); +} + + +static void +header_cell_data (GtkTreeViewColumn *column, GtkCellRenderer *renderer, + GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer user_data) +{ + TnyMsgHeaderFlags flags; + + gtk_tree_model_get (tree_model, iter, TNY_MSG_HEADER_LIST_MODEL_FLAGS_COLUMN, + &flags, -1); + + g_object_set (G_OBJECT(renderer), + "weight", (flags & TNY_MSG_HEADER_FLAG_SEEN) ? 400: 800, + "style", (flags & TNY_MSG_HEADER_FLAG_DELETED) ? + PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL, + NULL); +} + + + +/* try to make a shorter display address; changes it arg in-place */ +static gchar* +display_address (gchar *address) +{ + gchar *cursor; + + if (!address) + return NULL; + + /* simplistic --> remove from display name */ + cursor = g_strstr_len (address, strlen(address), "<"); + if (cursor) + cursor[0]='\0'; + + /* simplistic --> remove (bla bla) from display name */ + cursor = g_strstr_len (address, strlen(address), "("); + if (cursor) + cursor[0]='\0'; + + return address; +} + + + +static void +sender_receiver_cell_data (GtkTreeViewColumn *column, GtkCellRenderer *renderer, + GtkTreeModel *tree_model, GtkTreeIter *iter, gboolean is_sender) +{ + TnyMsgHeaderFlags flags; + gchar *address; + gint sender_receiver_col; + + if (is_sender) + sender_receiver_col = TNY_MSG_HEADER_LIST_MODEL_FROM_COLUMN; + else + sender_receiver_col = TNY_MSG_HEADER_LIST_MODEL_TO_COLUMN; + + gtk_tree_model_get (tree_model, iter, + sender_receiver_col, &address, + TNY_MSG_HEADER_LIST_MODEL_FLAGS_COLUMN, &flags, + -1); + + g_object_set (G_OBJECT(renderer), + "text", + display_address (address), + "weight", + (flags & TNY_MSG_HEADER_FLAG_SEEN) ? 400 : 800, + "style", + (flags & TNY_MSG_HEADER_FLAG_DELETED)?PANGO_STYLE_ITALIC:PANGO_STYLE_NORMAL, + NULL); + + g_free (address); +} + + + +/* just to prevent warnings: + * warning: `%x' yields only last 2 digits of year in some locales + */ +static size_t +my_strftime(char *s, size_t max, const char *fmt, const + struct tm *tm) { + return strftime(s, max, fmt, tm); +} + + + +/* not reentrant/thread-safe */ +const gchar* +display_date (time_t date) +{ + struct tm date_tm, now_tm; + time_t now; + + const gint buf_size = 64; + static gchar date_buf[64]; /* buf_size is not ... */ + static gchar now_buf[64]; /* ...const enough... */ + + now = time (NULL); + + localtime_r(&now, &now_tm); + localtime_r(&date, &date_tm); + + /* get today's date */ + my_strftime (date_buf, buf_size, "%x", &date_tm); + my_strftime (now_buf, buf_size, "%x", &now_tm); /* today */ + + /* if this is today, get the time instead of the date */ + if (strcmp (date_buf, now_buf) == 0) + strftime (date_buf, buf_size, _("%X"), &date_tm); + + return date_buf; +} + + +static void +compact_header_cell_data (GtkTreeViewColumn *column, GtkCellRenderer *renderer, + GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer user_data) +{ + GObject *rendobj; + TnyMsgHeaderFlags flags; + gchar *from, *subject; + gchar *header; + time_t date; + + gtk_tree_model_get (tree_model, iter, + TNY_MSG_HEADER_LIST_MODEL_FLAGS_COLUMN, &flags, + TNY_MSG_HEADER_LIST_MODEL_FROM_COLUMN, &from, + TNY_MSG_HEADER_LIST_MODEL_SUBJECT_COLUMN, &subject, + TNY_MSG_HEADER_LIST_MODEL_DATE_RECEIVED_TIME_T_COLUMN, &date, + -1); + rendobj = G_OBJECT(renderer); + + header = g_strdup_printf ("%s %s\n%s", + display_address (from), + display_date(date), + subject); + + g_object_set (G_OBJECT(renderer), + "text", header, + "weight", (flags & TNY_MSG_HEADER_FLAG_SEEN) ? 400: 800, + "style", (flags & TNY_MSG_HEADER_FLAG_DELETED) ? + PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL, + NULL); + g_free (header); + g_free (from); + g_free (subject); +} + + +static GtkTreeViewColumn* +get_new_column (const gchar *name, GtkCellRenderer *renderer, + gboolean resizable, gint sort_col_id, gboolean show_as_text, + GtkTreeCellDataFunc cell_data_func, gpointer user_data) +{ + GtkTreeViewColumn *column; + + column = gtk_tree_view_column_new_with_attributes(name, renderer, NULL); + gtk_tree_view_column_set_resizable (column, resizable); + + if (show_as_text) + gtk_tree_view_column_add_attribute (column, renderer, "text", + sort_col_id); + if (sort_col_id >= 0) + gtk_tree_view_column_set_sort_column_id (column, sort_col_id); + + gtk_tree_view_column_set_sort_indicator (column, FALSE); + gtk_tree_view_column_set_reorderable (column, TRUE); + + if (cell_data_func) + gtk_tree_view_column_set_cell_data_func(column, renderer, cell_data_func, + user_data, NULL); + +/* g_signal_connect (G_OBJECT (column), "clicked", */ +/* G_CALLBACK (column_clicked), obj); */ + + return column; +} + + + + +static void +remove_all_columns (ModestHeaderView *obj) +{ + GList *columns, *cursor; + + columns = gtk_tree_view_get_columns (GTK_TREE_VIEW(obj)); + + for (cursor = columns; cursor; cursor = cursor->next) + gtk_tree_view_remove_column (GTK_TREE_VIEW(obj), + GTK_TREE_VIEW_COLUMN(cursor->data)); + g_list_free (columns); +} + + + + +static void +init_columns (ModestHeaderView *obj) +{ + GtkTreeViewColumn *column=NULL; + GtkCellRenderer *renderer_msgtype, + *renderer_header, + *renderer_attach; + + ModestHeaderViewPrivate *priv; + GSList *cursor; + + priv = MODEST_HEADER_VIEW_GET_PRIVATE(obj); + + renderer_msgtype = gtk_cell_renderer_pixbuf_new (); + renderer_attach = gtk_cell_renderer_pixbuf_new (); + renderer_header = gtk_cell_renderer_text_new (); + + remove_all_columns (obj); + + for (cursor = priv->columns; cursor; cursor = cursor->next) { + ModestHeaderViewColumn col = + (ModestHeaderViewColumn) GPOINTER_TO_INT(cursor->data); + + switch (col) { + + case MODEST_HEADER_VIEW_COLUMN_MSGTYPE: + + column = get_new_column (_("M"), renderer_msgtype, FALSE, + TNY_MSG_HEADER_LIST_MODEL_FLAGS_COLUMN, + FALSE, (GtkTreeCellDataFunc)msgtype_cell_data, + NULL); + break; + + case MODEST_HEADER_VIEW_COLUMN_ATTACH: + + column = get_new_column (_("A"), renderer_attach, FALSE, + TNY_MSG_HEADER_LIST_MODEL_FLAGS_COLUMN, + FALSE, (GtkTreeCellDataFunc)attach_cell_data, + NULL); + break; + + case MODEST_HEADER_VIEW_COLUMN_RECEIVED_DATE: + column = get_new_column (_("Received"), renderer_header, TRUE, + TNY_MSG_HEADER_LIST_MODEL_DATE_RECEIVED_COLUMN, + TRUE, (GtkTreeCellDataFunc)header_cell_data, + NULL); + break; + + case MODEST_HEADER_VIEW_COLUMN_FROM: + column = get_new_column (_("From"), renderer_header, TRUE, + TNY_MSG_HEADER_LIST_MODEL_FROM_COLUMN, + TRUE, (GtkTreeCellDataFunc)sender_receiver_cell_data, + GINT_TO_POINTER(TRUE)); + break; + + case MODEST_HEADER_VIEW_COLUMN_TO: + column = get_new_column (_("To"), renderer_header, TRUE, + TNY_MSG_HEADER_LIST_MODEL_TO_COLUMN, + TRUE, (GtkTreeCellDataFunc)sender_receiver_cell_data, + GINT_TO_POINTER(FALSE)); + break; + + case MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER: + column = get_new_column (_("Header"), renderer_header, TRUE, + TNY_MSG_HEADER_LIST_MODEL_FROM_COLUMN, + TRUE, (GtkTreeCellDataFunc)compact_header_cell_data, + NULL); + break; + + case MODEST_HEADER_VIEW_COLUMN_SUBJECT: + column = get_new_column (_("Subject"), renderer_header, TRUE, + TNY_MSG_HEADER_LIST_MODEL_SUBJECT_COLUMN, + TRUE, (GtkTreeCellDataFunc)header_cell_data, + NULL); + break; + + + case MODEST_HEADER_VIEW_COLUMN_SENT_DATE: + column = get_new_column (_("Sent"), renderer_header, TRUE, + TNY_MSG_HEADER_LIST_MODEL_DATE_SENT_COLUMN, + TRUE, (GtkTreeCellDataFunc)header_cell_data, + NULL); + break; + } + gtk_tree_view_append_column (GTK_TREE_VIEW(obj), column); + } +} + + + + + +static void +modest_header_view_init (ModestHeaderView *obj) +{ + ModestHeaderViewPrivate *priv; + priv = MODEST_HEADER_VIEW_GET_PRIVATE(obj); + + priv->status_id = 0; + priv->lock = g_mutex_new (); +} + +static void +modest_header_view_finalize (GObject *obj) +{ + ModestHeaderView *self; + ModestHeaderViewPrivate *priv; + + self = MODEST_HEADER_VIEW(obj); + priv = MODEST_HEADER_VIEW_GET_PRIVATE(self); + + if (priv->headers) + g_object_unref (G_OBJECT(priv->headers)); + + + if (priv->lock) { + g_mutex_free (priv->lock); + priv->lock = NULL; + } + + priv->headers = NULL; + priv->tny_msg_folder = NULL; + + G_OBJECT_CLASS(parent_class)->finalize (obj); +} + +GtkWidget* +modest_header_view_new (TnyMsgFolderIface *folder, + GSList *columns, + ModestHeaderViewStyle style) +{ + GObject *obj; + GtkTreeSelection *sel; + ModestHeaderView *self; + + obj = G_OBJECT(g_object_new(MODEST_TYPE_HEADER_VIEW, NULL)); + self = MODEST_HEADER_VIEW(obj); + + if (!modest_header_view_set_folder (self, NULL)) { + g_warning ("could not set the folder"); + g_object_unref (obj); + return NULL; + } + + modest_header_view_set_style (self, style); + modest_header_view_set_columns (self, columns); + + /* all cols */ + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(obj), TRUE); + gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW(obj), TRUE); + + gtk_tree_view_set_rules_hint (GTK_TREE_VIEW(obj), + TRUE); /* alternating row colors */ + + sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(self)); + g_signal_connect (sel, "changed", + G_CALLBACK(on_selection_changed), self); + + return GTK_WIDGET(self); +} + +gboolean +modest_header_view_set_columns (ModestHeaderView *self, GSList *columns) +{ + ModestHeaderViewPrivate *priv; + GSList *cursor; + + g_return_val_if_fail (self, FALSE); + + priv = MODEST_HEADER_VIEW_GET_PRIVATE(self); + + g_slist_free (priv->columns); + + for (cursor = columns; cursor; cursor = cursor->next) { + ModestHeaderViewColumn col = + (ModestHeaderViewColumn) GPOINTER_TO_INT(cursor->data); + if (0 > col || col >= MODEST_HEADER_VIEW_COLUMN_NUM) + g_warning ("invalid column in column list"); + else + priv->columns = g_slist_append (priv->columns, cursor->data); + } + + init_columns (self); /* redraw them */ + return TRUE; +} + + + +const GSList* +modest_header_view_get_columns (ModestHeaderView *self) +{ + ModestHeaderViewPrivate *priv; + + g_return_val_if_fail (self, FALSE); + + priv = MODEST_HEADER_VIEW_GET_PRIVATE(self); + return priv->columns; +} + + + + +gboolean +modest_header_view_set_style (ModestHeaderView *self, + ModestHeaderViewStyle style) +{ + g_return_val_if_fail (self, FALSE); + g_return_val_if_fail (style >= 0 && style < MODEST_HEADER_VIEW_STYLE_NUM, + FALSE); + + MODEST_HEADER_VIEW_GET_PRIVATE(self)->style = style; + + return TRUE; +} + +ModestHeaderViewStyle +modest_header_view_get_style (ModestHeaderView *self) +{ + g_return_val_if_fail (self, FALSE); + + return MODEST_HEADER_VIEW_GET_PRIVATE(self)->style; +} + + + +/* get the length of any prefix that should be ignored for sorting */ +static inline int +get_prefix_len (const gchar *sub) +{ + gint i = 0; + const static gchar* prefix[] = {"Re:", "RE:", "Fwd:", "FWD:", "FW:", "AW:", NULL}; + + if (sub[0] != 'R' && sub[0] != 'F') /* optimization */ + return 0; + + while (prefix[i]) { + if (g_str_has_prefix(sub, prefix[i])) { + int prefix_len = strlen(prefix[i]); + if (sub[prefix_len] == ' ') + ++prefix_len; /* ignore space after prefix as well */ + return prefix_len; + } + ++i; + } + return 0; +} + + +static inline gint +cmp_normalized_subject (const gchar* s1, const gchar *s2) +{ + gint result = 0; + register gchar *n1, *n2; + + n1 = g_utf8_collate_key (s1 + get_prefix_len(s1), -1); + n2 = g_utf8_collate_key (s2 + get_prefix_len(s2), -1); + + result = strcmp (n1, n2); + g_free (n1); + g_free (n2); + + return result; +} + + +static gint +cmp_rows (GtkTreeModel *tree_model, GtkTreeIter *iter1, GtkTreeIter *iter2, + gpointer user_data) +{ + gint col_id = GPOINTER_TO_INT (user_data); + gint t1, t2; + gint val1, val2; + gchar *s1, *s2; + gint cmp; + + g_return_val_if_fail (GTK_IS_TREE_MODEL(tree_model), -1); + + switch (col_id) { + + /* first one, we decide based on the time */ + case MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER: + case MODEST_HEADER_VIEW_COLUMN_RECEIVED_DATE: + gtk_tree_model_get (tree_model, iter1, + TNY_MSG_HEADER_LIST_MODEL_DATE_RECEIVED_TIME_T_COLUMN, + &t1,-1); + gtk_tree_model_get (tree_model, iter2, + TNY_MSG_HEADER_LIST_MODEL_DATE_RECEIVED_TIME_T_COLUMN, + &t2,-1); + return t1 - t2; + + case MODEST_HEADER_VIEW_COLUMN_SENT_DATE: + gtk_tree_model_get (tree_model, iter1, + TNY_MSG_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, + &t1,-1); + gtk_tree_model_get (tree_model, iter2, + TNY_MSG_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, + &t2,-1); + return t1 - t2; + + + /* next ones, we try the search criteria first, if they're the same, then we use 'sent date' */ + case MODEST_HEADER_VIEW_COLUMN_SUBJECT: { + + gtk_tree_model_get (tree_model, iter1, + TNY_MSG_HEADER_LIST_MODEL_SUBJECT_COLUMN, &s1, + TNY_MSG_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t1, + -1); + gtk_tree_model_get (tree_model, iter2, + TNY_MSG_HEADER_LIST_MODEL_SUBJECT_COLUMN, &s2, + TNY_MSG_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t2, + -1); + + cmp = cmp_normalized_subject(s1, s2); + + g_free (s1); + g_free (s2); + + return cmp ? cmp : t1 - t2; + } + + case MODEST_HEADER_VIEW_COLUMN_FROM: + + gtk_tree_model_get (tree_model, iter1, + TNY_MSG_HEADER_LIST_MODEL_FROM_COLUMN, &s1, + TNY_MSG_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t1, + -1); + gtk_tree_model_get (tree_model, iter2, + TNY_MSG_HEADER_LIST_MODEL_FROM_COLUMN, &s2, + TNY_MSG_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t2, + -1); + cmp = strcmp (s1, s2); + g_free (s1); + g_free (s2); + + return cmp ? cmp : t1 - t2; + + case MODEST_HEADER_VIEW_COLUMN_TO: + + gtk_tree_model_get (tree_model, iter1, + TNY_MSG_HEADER_LIST_MODEL_TO_COLUMN, &s1, + TNY_MSG_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t1, + -1); + gtk_tree_model_get (tree_model, iter2, + TNY_MSG_HEADER_LIST_MODEL_TO_COLUMN, &s2, + TNY_MSG_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t2, + -1); + cmp = strcmp (s1, s2); + g_free (s1); + g_free (s2); + + return cmp ? cmp : t1 - t2; + + case MODEST_HEADER_VIEW_COLUMN_ATTACH: + + gtk_tree_model_get (tree_model, iter1, TNY_MSG_HEADER_LIST_MODEL_FLAGS_COLUMN, &val1, + TNY_MSG_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t1, -1); + gtk_tree_model_get (tree_model, iter2, TNY_MSG_HEADER_LIST_MODEL_FLAGS_COLUMN, &val2, + TNY_MSG_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t2, -1); + + cmp = (val1 & TNY_MSG_HEADER_FLAG_ATTACHMENTS) - + (val2 & TNY_MSG_HEADER_FLAG_ATTACHMENTS); + + return cmp ? cmp : t1 - t2; + + case MODEST_HEADER_VIEW_COLUMN_MSGTYPE: + gtk_tree_model_get (tree_model, iter1, TNY_MSG_HEADER_LIST_MODEL_FLAGS_COLUMN, &val1, + TNY_MSG_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t1,-1); + gtk_tree_model_get (tree_model, iter2, TNY_MSG_HEADER_LIST_MODEL_FLAGS_COLUMN, &val2, + TNY_MSG_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t2,-1); + cmp = (val1 & TNY_MSG_HEADER_FLAG_SEEN) - (val2 & TNY_MSG_HEADER_FLAG_SEEN); + + return cmp ? cmp : t1 - t2; + + default: + return &iter1 - &iter2; /* oughhhh */ + } +} + + +static void +refresh_folder (TnyMsgFolderIface *folder, gboolean cancelled, + gpointer user_data) +{ + GtkTreeModel *oldsortable, *sortable; + ModestHeaderView *self = + MODEST_HEADER_VIEW(user_data); + ModestHeaderViewPrivate *priv; + + g_return_if_fail (self); + + if (cancelled) + return; + + priv = MODEST_HEADER_VIEW_GET_PRIVATE(self); + + if (!folder) /* when there is no folder */ + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(self), FALSE); + + else { /* it's a new one or a refresh */ + GSList *col; + + priv->headers = TNY_LIST_IFACE(tny_msg_header_list_model_new ()); + + tny_msg_folder_iface_get_headers (folder, priv->headers, FALSE); + tny_msg_header_list_model_set_folder (TNY_MSG_HEADER_LIST_MODEL(priv->headers), + folder, TRUE); /* async */ + + oldsortable = gtk_tree_view_get_model(GTK_TREE_VIEW (self)); + if (oldsortable && GTK_IS_TREE_MODEL_SORT(oldsortable)) { + GtkTreeModel *oldmodel = gtk_tree_model_sort_get_model + (GTK_TREE_MODEL_SORT(oldsortable)); + if (oldmodel) + g_object_unref (G_OBJECT(oldmodel)); + g_object_unref (oldsortable); + } + + sortable = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL(priv->headers)); + + /* install our special sorting functions */ + col = priv->columns; + while (col) { + gint col_id = GPOINTER_TO_INT (col->data); + gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE(sortable), col_id, + (GtkTreeIterCompareFunc)cmp_rows, + GINT_TO_POINTER(col_id), NULL); + col = col->next; + } + + gtk_tree_view_set_model (GTK_TREE_VIEW (self), sortable); + gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW(self), TRUE); + /* no need to unref sortable */ + } + +} + + +static void +refresh_folder_status_update (TnyMsgFolderIface *folder, const gchar *msg, + gint status_id, gpointer user_data) +{ + ModestHeaderView *self; + ModestHeaderViewPrivate *priv; + + self = MODEST_HEADER_VIEW (user_data); + priv = MODEST_HEADER_VIEW_GET_PRIVATE(self); + + g_signal_emit (G_OBJECT(self), + signals[STATUS_UPDATE_SIGNAL], 0, + msg, status_id); + if (msg) + g_timeout_add (750, + (GSourceFunc)refresh_folder_finish_status_update, + self); + + priv->status_id = status_id; +} + + +static gboolean +refresh_folder_finish_status_update (gpointer user_data) +{ + ModestHeaderView *self; + ModestHeaderViewPrivate *priv; + + self = MODEST_HEADER_VIEW (user_data); + priv = MODEST_HEADER_VIEW_GET_PRIVATE(self); + + if (priv->status_id == 0) + return FALSE; + + refresh_folder_status_update (NULL, NULL, priv->status_id, + user_data); + priv->status_id = 0; + + return FALSE; +} + + +gboolean +modest_header_view_set_folder (ModestHeaderView *self, + TnyMsgFolderIface *folder) +{ + ModestHeaderViewPrivate *priv; + + g_return_val_if_fail (MODEST_IS_HEADER_VIEW (self), FALSE); + + priv = MODEST_HEADER_VIEW_GET_PRIVATE(self); + + g_mutex_lock (priv->lock); + + if (!folder) {/* when there is no folder */ + GtkTreeModel *model; + model = gtk_tree_view_get_model (GTK_TREE_VIEW(self)); + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(self), FALSE); + gtk_tree_view_set_model (GTK_TREE_VIEW (self), NULL); + if (model) + g_object_unref (model); + } + else { /* it's a new one or a refresh */ + tny_msg_folder_iface_refresh_async (folder, + refresh_folder, + refresh_folder_status_update, + self); + } + + /* no message selected */ + g_signal_emit (G_OBJECT(self), signals[MESSAGE_SELECTED_SIGNAL], 0, + NULL); + + g_mutex_unlock (priv->lock); + + return TRUE; +} + + + +static void +on_selection_changed (GtkTreeSelection *sel, gpointer user_data) +{ + GtkTreeModel *model; + TnyMsgHeaderIface *header; + GtkTreeIter iter; + ModestHeaderView *self; + ModestHeaderViewPrivate *priv; + + g_return_if_fail (sel); + g_return_if_fail (user_data); + + self = MODEST_HEADER_VIEW (user_data); + priv = MODEST_HEADER_VIEW_GET_PRIVATE(self); + + + if (!gtk_tree_selection_get_selected (sel, &model, &iter)) + return; /* msg was _un_selected */ + + //g_mutex_lock (priv->lock); + + gtk_tree_model_get (model, &iter, + TNY_MSG_HEADER_LIST_MODEL_INSTANCE_COLUMN, + &header, -1); + + if (header) { + const TnyMsgIface *msg = NULL; + const TnyMsgFolderIface *folder; + + folder = tny_msg_header_iface_get_folder (TNY_MSG_HEADER_IFACE(header)); + if (!folder) + g_printerr ("modest: cannot find folder\n"); + else { + msg = tny_msg_folder_iface_get_message (TNY_MSG_FOLDER_IFACE(folder), + header); + if (!msg) { + g_printerr ("modest: cannot find msg\n"); + gtk_tree_store_remove (GTK_TREE_STORE(model), + &iter); + } + } + + g_signal_emit (G_OBJECT(self), signals[MESSAGE_SELECTED_SIGNAL], 0, + msg); + + /* mark message as seen; _set_flags crashes, bug in tinymail? */ + //flags = tny_msg_header_iface_get_flags (TNY_MSG_HEADER_IFACE(header)); + //tny_msg_header_iface_set_flags (header, TNY_MSG_HEADER_FLAG_SEEN); + } + + // g_mutex_unlock (priv->lock); + +} + + +/* static void */ +/* on_column_clicked (GtkTreeViewColumn *col, gpointer user_data) */ +/* { */ +/* GtkTreeView *treeview; */ +/* gint id; */ + +/* treeview = GTK_TREE_VIEW (user_data); */ +/* id = gtk_tree_view_column_get_sort_column_id (col); */ + +/* gtk_tree_view_set_search_column (treeview, id); */ +/* } */ diff --git a/src/widgets/modest-header-view.h b/src/widgets/modest-header-view.h new file mode 100644 index 0000000..1ed2676 --- /dev/null +++ b/src/widgets/modest-header-view.h @@ -0,0 +1,186 @@ +/* Copyright (c) 2006, 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_HEADER_VIEW_H__ +#define __MODEST_HEADER_VIEW_H__ + +#include +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +/* convenience macros */ +#define MODEST_TYPE_HEADER_VIEW (modest_header_view_get_type()) +#define MODEST_HEADER_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),MODEST_TYPE_HEADER_VIEW,ModestHeaderView)) +#define MODEST_HEADER_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),MODEST_TYPE_HEADER_VIEW,ModestHeaderViewClass)) +#define MODEST_IS_HEADER_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),MODEST_TYPE_HEADER_VIEW)) +#define MODEST_IS_HEADER_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),MODEST_TYPE_HEADER_VIEW)) +#define MODEST_HEADER_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),MODEST_TYPE_HEADER_VIEW,ModestHeaderViewClass)) + +typedef struct _ModestHeaderView ModestHeaderView; +typedef struct _ModestHeaderViewClass ModestHeaderViewClass; + +struct _ModestHeaderView { + GtkTreeView parent; + /* insert public members, if any */ +}; + +struct _ModestHeaderViewClass { + GtkTreeViewClass parent_class; + + void (*message_selected) (ModestHeaderView* self, + TnyMsgIface *msg, + gpointer user_data); + + /* msg == NULL implies that the operation is finished, ie. + * the progress indictation can be hidden */ + void (*status_update) (ModestHeaderView* self, + const gchar* msg, + gint status, + gpointer user_data); +}; + + +enum { + MODEST_HEADER_VIEW_COLUMN_FROM, + MODEST_HEADER_VIEW_COLUMN_TO, + MODEST_HEADER_VIEW_COLUMN_SUBJECT, + MODEST_HEADER_VIEW_COLUMN_SENT_DATE, + MODEST_HEADER_VIEW_COLUMN_RECEIVED_DATE, + MODEST_HEADER_VIEW_COLUMN_MSGTYPE, + MODEST_HEADER_VIEW_COLUMN_ATTACH, + MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER, + + MODEST_HEADER_VIEW_COLUMN_NUM +}; +typedef guint ModestHeaderViewColumn; + +enum { + MODEST_HEADER_VIEW_STYLE_NORMAL, + MODEST_HEADER_VIEW_STYLE_COMPACT, + + MODEST_HEADER_VIEW_STYLE_NUM +}; +typedef guint ModestHeaderViewStyle; + + + +/** + * modest_header_view_get_type: + * + * get the GType for ModestHeaderView + * + * Returns: the GType + */ +GType modest_header_view_get_type (void) G_GNUC_CONST; + + +/** + * modest_header_view_new: + * @folder: a TnyMsgFolderIface object + * @columns: a list of ModestHeaderViewColumn + * @style: a ModestHeaderViewColumn with the style of this listview + * ( MODEST_HEADER_VIEW_STYLE_NORMAL or MODEST_HEADER_VIEW_STYLE_COMPACT) + * + * create a new ModestHeaderView instance, based on a folder iface + * + * Returns: a new GtkWidget (a GtkTreeView-subclass) + */ +GtkWidget* modest_header_view_new (TnyMsgFolderIface *folder, + GSList *columns, + ModestHeaderViewStyle style); + +/** + * modest_header_view_set_folder: + * @self: a ModestHeaderView instance + * @folder: a TnyMsgFolderIface object + * + * set the folder for this ModestHeaderView + * + * Returns: TRUE if it succeeded, FALSE otherwise + */ +gboolean modest_header_view_set_folder (ModestHeaderView *self, + TnyMsgFolderIface *folder); + + +/** + * modest_header_view_set_columns: + * @self: a ModestHeaderView instance + * @columns: a list of ModestHeaderViewColumn + * + * set the columns for this ModestHeaderView + * + * Returns: TRUE if it succeeded, FALSE otherwise + */ +gboolean modest_header_view_set_columns (ModestHeaderView *self, + GSList *columns); +/** + * modest_header_view_get_columns: + * @self: a ModestHeaderView instance + * @folder: a TnyMsgFolderIface object + * + * get the columns for this ModestHeaderView + * + * Returns: list of columms, or NULL in case of no columns or error + */ +const GSList* modest_header_view_get_columns (ModestHeaderView *self); + + +/** + * modest_header_view_set_style: + * @self: a ModestHeaderView instance + * @style: the style for this tree view + * + * set the folder for this ModestHeaderView + * + * Returns: TRUE if it succeeded, FALSE otherwise + */ +gboolean modest_header_view_set_style (ModestHeaderView *self, + ModestHeaderViewStyle style); + +/** + * modest_header_view_set_folder: + * @self: a ModestHeaderView instance + * @folder: a TnyMsgFolderIface object + * + * set the folder for this ModestHeaderView + * + * Returns: TRUE if it succeeded, FALSE otherwise + */ +ModestHeaderViewStyle modest_header_view_get_style (ModestHeaderView *self); + +G_END_DECLS + + +#endif /* __MODEST_HEADER_VIEW_H__ */ + diff --git a/src/widgets/modest-msg-view.c b/src/widgets/modest-msg-view.c new file mode 100644 index 0000000..5a16918 --- /dev/null +++ b/src/widgets/modest-msg-view.c @@ -0,0 +1,704 @@ +/* Copyright (c) 2006, 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 "modest-msg-view.h" +#include "modest-tny-stream-gtkhtml.h" + + +/* 'private'/'protected' functions */ +static void modest_msg_view_class_init (ModestMsgViewClass *klass); +static void modest_msg_view_init (ModestMsgView *obj); +static void modest_msg_view_finalize (GObject *obj); + + +static GSList* get_url_matches (GString *txt); +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); + +/* + * we need these regexps to find URLs in plain text e-mails + */ +typedef struct _UrlMatchPattern UrlMatchPattern; +struct _UrlMatchPattern { + gchar *regex; + regex_t *preg; + gchar *prefix; + +}; + +#define ATT_PREFIX "att:" + +#define MAIL_VIEWER_URL_MATCH_PATTERNS { \ + { "(file|http|ftp|https)://[-A-Za-z0-9_$.+!*(),;:@%&=?/~#]+[-A-Za-z0-9_$%&=?/~#]",\ + NULL, NULL },\ + { "www\\.[-a-z0-9.]+[-a-z0-9](:[0-9]*)?(/[-A-Za-z0-9_$.+!*(),;:@%&=?/~#]*[^]}\\),?!;:\"]?)?",\ + NULL, "http://" },\ + { "ftp\\.[-a-z0-9.]+[-a-z0-9](:[0-9]*)?(/[-A-Za-z0-9_$.+!*(),;:@%&=?/~#]*[^]}\\),?!;:\"]?)?",\ + NULL, "ftp://" },\ + { "(voipto|callto|chatto|jabberto|xmpp):[-_a-z@0-9.\\+]+", \ + NULL, NULL}, \ + { "mailto:[-_a-z0-9.\\+]+@[-_a-z0-9.]+", \ + NULL, NULL},\ + { "[-_a-z0-9.\\+]+@[-_a-z0-9.]+",\ + NULL, "mailto:"}\ + } + + +/* list my signals */ +enum { + LINK_CLICKED_SIGNAL, + ATTACHMENT_CLICKED_SIGNAL, + LAST_SIGNAL +}; + +typedef struct _ModestMsgViewPrivate ModestMsgViewPrivate; +struct _ModestMsgViewPrivate { + GtkWidget *gtkhtml; + const TnyMsgIface *msg; +}; +#define MODEST_MSG_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ + MODEST_TYPE_MSG_VIEW, \ + ModestMsgViewPrivate)) +/* globals */ +static GtkContainerClass *parent_class = NULL; + +/* uncomment the following if you have defined any signals */ +static guint signals[LAST_SIGNAL] = {0}; + +GType +modest_msg_view_get_type (void) +{ + static GType my_type = 0; + if (!my_type) { + static const GTypeInfo my_info = { + sizeof(ModestMsgViewClass), + NULL, /* base init */ + NULL, /* base finalize */ + (GClassInitFunc) modest_msg_view_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof(ModestMsgView), + 1, /* n_preallocs */ + (GInstanceInitFunc) modest_msg_view_init, + }; + my_type = g_type_register_static (GTK_TYPE_SCROLLED_WINDOW, + "ModestMsgView", + &my_info, 0); + } + return my_type; +} + +static void +modest_msg_view_class_init (ModestMsgViewClass *klass) +{ + GObjectClass *gobject_class; + gobject_class = (GObjectClass*) klass; + + parent_class = g_type_class_peek_parent (klass); + gobject_class->finalize = modest_msg_view_finalize; + + g_type_class_add_private (gobject_class, sizeof(ModestMsgViewPrivate)); + + + signals[LINK_CLICKED_SIGNAL] = + g_signal_new ("link_clicked", + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(ModestMsgViewClass, link_clicked), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, G_TYPE_STRING); + + signals[ATTACHMENT_CLICKED_SIGNAL] = + g_signal_new ("attachment_clicked", + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(ModestMsgViewClass, attachment_clicked), + NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_INT); + +} + +static void +modest_msg_view_init (ModestMsgView *obj) +{ + ModestMsgViewPrivate *priv; + + priv = MODEST_MSG_VIEW_GET_PRIVATE(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); + + g_signal_connect (G_OBJECT(priv->gtkhtml), "link_clicked", + G_CALLBACK(on_link_clicked), obj); + + g_signal_connect (G_OBJECT(priv->gtkhtml), "url_requested", + G_CALLBACK(on_url_requested), obj); +} + + +static void +modest_msg_view_finalize (GObject *obj) +{ + G_OBJECT_CLASS(parent_class)->finalize (obj); +} + + +GtkWidget* +modest_msg_view_new (const TnyMsgIface *msg) +{ + GObject *obj; + ModestMsgView* self; + ModestMsgViewPrivate *priv; + + obj = G_OBJECT(g_object_new(MODEST_TYPE_MSG_VIEW, NULL)); + self = MODEST_MSG_VIEW(obj); + priv = MODEST_MSG_VIEW_GET_PRIVATE (self); + + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(self), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + + if (priv->gtkhtml) + gtk_container_add (GTK_CONTAINER(obj), priv->gtkhtml); + + if (msg) + modest_msg_view_set_message (self, msg); + + return GTK_WIDGET(self); +} + + +static gboolean +on_link_clicked (GtkWidget *widget, const gchar *uri, ModestMsgView *msg_view) +{ + + int index; + + g_return_val_if_fail (msg_view, FALSE); + + /* is it an attachment? */ + if (g_str_has_prefix(uri, ATT_PREFIX)) { + + index = atoi (uri + strlen(ATT_PREFIX)); + + if (index == 0) { + /* index is 1-based, so 0 indicates an error */ + g_printerr ("modest: invalid attachment id: %s\n", uri); + return FALSE; + } + + g_signal_emit (G_OBJECT(msg_view), signals[ATTACHMENT_CLICKED_SIGNAL], + 0, index); + return FALSE; + } + + g_signal_emit (G_OBJECT(msg_view), signals[LINK_CLICKED_SIGNAL], 0, uri); + + return FALSE; +} + + +static TnyMsgMimePartIface * +find_cid_image (const TnyMsgIface *msg, const gchar *cid) +{ + TnyMsgMimePartIface *part = NULL; + const TnyListIface *parts; + TnyIteratorIface *iter; + + g_return_val_if_fail (msg, NULL); + g_return_val_if_fail (cid, NULL); + + parts = tny_msg_iface_get_parts ((TnyMsgIface*)msg); // FIXME: tinymail + iter = tny_list_iface_create_iterator ((TnyListIface*)parts); + + while (!tny_iterator_iface_is_done(iter)) { + const gchar *part_cid; + part = TNY_MSG_MIME_PART_IFACE(tny_iterator_iface_current(iter)); + part_cid = tny_msg_mime_part_iface_get_content_id (part); + + if (part_cid && strcmp (cid, part_cid) == 0) + break; + + part = NULL; + tny_iterator_iface_next (iter); + } + + g_object_unref (G_OBJECT(iter)); + return part; +} + + +static gboolean +on_url_requested (GtkWidget *widget, const gchar *uri, + GtkHTMLStream *stream, + ModestMsgView *msg_view) +{ + ModestMsgViewPrivate *priv; + priv = MODEST_MSG_VIEW_GET_PRIVATE (msg_view); + + if (g_str_has_prefix (uri, "cid:")) { + /* +4 ==> skip "cid:" */ + const TnyMsgMimePartIface *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); + } else { + TnyStreamIface *tny_stream = + TNY_STREAM_IFACE(modest_tny_stream_gtkhtml_new(stream)); + // FIXME: tinymail + tny_msg_mime_part_iface_decode_to_stream ((TnyMsgMimePartIface*)part, + tny_stream); + gtk_html_stream_close (stream, GTK_HTML_STREAM_OK); + } + } + + return TRUE; +} + + +typedef struct { + guint offset; + guint len; + const gchar* prefix; +} url_match_t; + + + +/* render the attachments as hyperlinks in html */ +static gchar* +attachments_as_html (ModestMsgView *self, const TnyMsgIface *msg) +{ + ModestMsgViewPrivate *priv; + GString *appendix; + const TnyListIface *parts; + TnyIteratorIface *iter; + gchar *html; + int index = 0; + + if (!msg) + return NULL; + + priv = MODEST_MSG_VIEW_GET_PRIVATE (self); + parts = tny_msg_iface_get_parts ((TnyMsgIface*)msg); + // FIXME: tinymail + iter = tny_list_iface_create_iterator ((TnyListIface*)parts); + + appendix= g_string_new (""); + + while (!tny_iterator_iface_is_done(iter)) { + TnyMsgMimePartIface *part; + + ++index; /* attachment numbers are 1-based */ + + part = TNY_MSG_MIME_PART_IFACE(tny_iterator_iface_current (iter)); + + if (tny_msg_mime_part_iface_is_attachment (part)) { + + const gchar *filename = tny_msg_mime_part_iface_get_filename(part); + if (!filename) + filename = _("attachment"); + + g_string_append_printf (appendix, "%s \n", + ATT_PREFIX, index, filename); + } + tny_iterator_iface_next (iter); + } + g_object_unref (G_OBJECT(iter)); + + if (appendix->len == 0) + return g_string_free (appendix, TRUE); + + html = g_strdup_printf ("%s: %s\n
", + _("Attachments"), appendix->str); + g_string_free (appendix, TRUE); + + return html; +} + + + +static void +hyperlinkify_plain_text (GString *txt) +{ + GSList *cursor; + GSList *match_list = get_url_matches (txt); + + /* we will work backwards, so the offsets stay valid */ + for (cursor = match_list; cursor; cursor = cursor->next) { + + url_match_t *match = (url_match_t*) cursor->data; + gchar *url = g_strndup (txt->str + match->offset, match->len); + gchar *repl = NULL; /* replacement */ + + /* the prefix is NULL: use the one that is already there */ + repl = g_strdup_printf ("%s", + match->prefix ? match->prefix : "", url, url); + + /* replace the old thing with our hyperlink + * replacement thing */ + g_string_erase (txt, match->offset, match->len); + g_string_insert (txt, match->offset, repl); + + g_free (url); + g_free (repl); + + g_free (cursor->data); + } + + g_slist_free (match_list); +} + + + +static gchar * +convert_to_html (const gchar *data) +{ + int i; + gboolean first_space = TRUE; + GString *html; + gsize len; + + if (!data) + return NULL; + + len = strlen (data); + html = g_string_sized_new (len + 100); /* just a guess... */ + + g_string_append_printf (html, + "" + "" + "" + "" + ""); + + /* replace with special html chars where needed*/ + for (i = 0; i != len; ++i) { + char kar = data[i]; + switch (kar) { + + case 0: break; /* ignore embedded \0s */ + case '<' : g_string_append (html, "<"); break; + case '>' : g_string_append (html, ">"); break; + case '&' : g_string_append (html, """); break; + case '\n': g_string_append (html, "
\n"); break; + default: + if (kar == ' ') { + g_string_append (html, first_space ? " " : " "); + first_space = FALSE; + } else if (kar == '\t') + g_string_append (html, "    "); + else { + int charnum = 0; + first_space = TRUE; + /* optimization trick: accumulate 'normal' chars, then copy */ + do { + kar = data [++charnum + i]; + + } while ((i + charnum < len) && + (kar > '>' || (kar != '<' && kar != '>' + && kar != '&' && kar != ' ' + && kar != '\n' && kar != '\t'))); + g_string_append_len (html, &data[i], charnum); + i += (charnum - 1); + } + } + } + + g_string_append (html, "
"); + hyperlinkify_plain_text (html); + + return g_string_free (html, FALSE); +} + + + + +static gint +cmp_offsets_reverse (const url_match_t *match1, const url_match_t *match2) +{ + return match2->offset - match1->offset; +} + + + +/* + * check if the match is inside an existing match... */ +static void +chk_partial_match (const url_match_t *match, int* offset) +{ + if (*offset >= match->offset && *offset < match->offset + match->len) + *offset = -1; +} + +static GSList* +get_url_matches (GString *txt) +{ + regmatch_t rm; + int rv, i, offset = 0; + GSList *match_list = NULL; + + static UrlMatchPattern patterns[] = MAIL_VIEWER_URL_MATCH_PATTERNS; + const size_t pattern_num = sizeof(patterns)/sizeof(UrlMatchPattern); + + /* initalize the regexps */ + for (i = 0; i != pattern_num; ++i) { + patterns[i].preg = g_new0 (regex_t,1); + g_assert(regcomp (patterns[i].preg, patterns[i].regex, + REG_ICASE|REG_EXTENDED|REG_NEWLINE) == 0); + } + /* find all the matches */ + for (i = 0; i != pattern_num; ++i) { + offset = 0; + while (1) { + int test_offset; + if ((rv = regexec (patterns[i].preg, txt->str + offset, 1, &rm, 0)) != 0) { + g_assert (rv == REG_NOMATCH); /* this should not happen */ + break; /* try next regexp */ + } + if (rm.rm_so == -1) + break; + + /* FIXME: optimize this */ + /* to avoid partial matches on something that was already found... */ + /* check_partial_match will put -1 in the data ptr if that is the case */ + test_offset = offset + rm.rm_so; + g_slist_foreach (match_list, (GFunc)chk_partial_match, &test_offset); + + /* make a list of our matches ( tupels)*/ + if (test_offset != -1) { + url_match_t *match = g_new (url_match_t,1); + match->offset = offset + rm.rm_so; + match->len = rm.rm_eo - rm.rm_so; + match->prefix = patterns[i].prefix; + match_list = g_slist_prepend (match_list, match); + } + offset += rm.rm_eo; + } + } + + for (i = 0; i != pattern_num; ++i) { + regfree (patterns[i].preg); + g_free (patterns[i].preg); + } /* don't free patterns itself -- it's static */ + + /* now sort the list, so the matches are in reverse order of occurence. + * that way, we can do the replacements starting from the end, so we don't need + * to recalculate the offsets + */ + match_list = g_slist_sort (match_list, + (GCompareFunc)cmp_offsets_reverse); + return match_list; +} + + + +static gboolean +set_html_message (ModestMsgView *self, const TnyMsgMimePartIface *tny_body, + const TnyMsgIface *msg) +{ + gchar *html_attachments; + TnyStreamIface *gtkhtml_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 = + TNY_STREAM_IFACE(modest_tny_stream_gtkhtml_new + (gtk_html_begin(GTK_HTML(priv->gtkhtml)))); + + tny_stream_iface_reset (gtkhtml_stream); + + html_attachments = attachments_as_html(self, msg); + if (html_attachments) { + tny_stream_iface_write (gtkhtml_stream, html_attachments, + strlen(html_attachments)); + tny_stream_iface_reset (gtkhtml_stream); + g_free (html_attachments); + } + + // FIXME: tinymail + tny_msg_mime_part_iface_decode_to_stream ((TnyMsgMimePartIface*)tny_body, + gtkhtml_stream); + + g_object_unref (G_OBJECT(gtkhtml_stream)); + + return TRUE; +} + + +/* 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, const TnyMsgMimePartIface *tny_body, + const TnyMsgIface *msg) +{ + GtkTextBuffer *buf; + GtkTextIter begin, end; + TnyStreamIface* txt_stream, *gtkhtml_stream; + gchar *txt, *html_attachments; + 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_IFACE(tny_text_buffer_stream_new (buf)); + + tny_stream_iface_reset (txt_stream); + + gtkhtml_stream = + TNY_STREAM_IFACE(modest_tny_stream_gtkhtml_new + (gtk_html_begin(GTK_HTML(priv->gtkhtml)))); + + html_attachments = attachments_as_html(self, msg); + if (html_attachments) { + tny_stream_iface_write (gtkhtml_stream, html_attachments, + strlen(html_attachments)); + tny_stream_iface_reset (gtkhtml_stream); + g_free (html_attachments); + } + + // FIXME: tinymail + tny_msg_mime_part_iface_decode_to_stream ((TnyMsgMimePartIface*)tny_body, + txt_stream); + tny_stream_iface_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 = convert_to_html (txt); + tny_stream_iface_write (gtkhtml_stream, html, strlen(html)); + tny_stream_iface_reset (gtkhtml_stream); + g_free (txt); + g_free (html); + } + + g_object_unref (G_OBJECT(gtkhtml_stream)); + g_object_unref (G_OBJECT(txt_stream)); + g_object_unref (G_OBJECT(buf)); + + 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; +} + + +gchar * +modest_msg_view_get_selected_text (ModestMsgView *self) +{ + ModestMsgViewPrivate *priv; + gchar *sel; + GtkWidget *html; + int len; + GtkClipboard *clip; + + g_return_val_if_fail (self, NULL); + priv = MODEST_MSG_VIEW_GET_PRIVATE(self); + html = priv->gtkhtml; + + /* I'm sure there is a better way to check for selected text */ + sel = gtk_html_get_selection_html(GTK_HTML(html), &len); + if (!sel) + return NULL; + + g_free(sel); + + clip = gtk_widget_get_clipboard(html, GDK_SELECTION_PRIMARY); + return gtk_clipboard_wait_for_text(clip); +} + + +void +modest_msg_view_set_message (ModestMsgView *self, const TnyMsgIface *msg) +{ + TnyMsgMimePartIface *body; + ModestMsgViewPrivate *priv; + + g_return_if_fail (self); + + priv = MODEST_MSG_VIEW_GET_PRIVATE(self); + + priv->msg = msg; + + if (!msg) { + set_empty_message (self); + return; + } + + body = modest_tny_msg_actions_find_body_part (msg, TRUE); + if (body) { + if (tny_msg_mime_part_iface_content_type_is (body, "text/html")) + set_html_message (self, body, msg); + else + set_text_message (self, body, msg); + return; + } else + set_empty_message (self); +} diff --git a/src/widgets/modest-msg-view.h b/src/widgets/modest-msg-view.h new file mode 100644 index 0000000..fe92c7a --- /dev/null +++ b/src/widgets/modest-msg-view.h @@ -0,0 +1,113 @@ +/* Copyright (c) 2006, 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. + */ + + +/* modest-tny-msg-view.h */ + +#ifndef __MODEST_MSG_VIEW_H__ +#define __MODEST_MSG_VIEW_H__ + +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +/* convenience macros */ +#define MODEST_TYPE_MSG_VIEW (modest_msg_view_get_type()) +#define MODEST_MSG_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),MODEST_TYPE_MSG_VIEW,ModestMsgView)) +#define MODEST_MSG_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),MODEST_TYPE_MSG_VIEW,ModestMsgViewClass)) +#define MODEST_IS_MSG_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),MODEST_TYPE_MSG_VIEW)) +#define MODEST_IS_MSG_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),MODEST_TYPE_MSG_VIEW)) +#define MODEST_MSG_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),MODEST_TYPE_MSG_VIEW,ModestMsgViewClass)) + +typedef struct _ModestMsgView ModestMsgView; +typedef struct _ModestMsgViewClass ModestMsgViewClass; + +struct _ModestMsgView { + GtkScrolledWindow parent; +}; + +struct _ModestMsgViewClass { + GtkScrolledWindowClass parent_class; + + void (*link_clicked) (GtkWidget *widget, const gchar* link, gpointer user_data); + void (*attachment_clicked) (GtkWidget *widget, int index, gpointer user_data); +}; + + +/** + * modest_msg_view_get_type + * + * get the GType for the this class + * + * Returns: the GType for this class + */ +GType modest_msg_view_get_type (void) G_GNUC_CONST; + + +/** + * modest_msg_view_new + * @tny_msg: a TnyMsgIface instance, or NULL + * + * create a new ModestMsgView widget (a GtkScrolledWindow subclass), + * and display the @tny_msg e-mail message in it. If @tny_msg is NULL, + * then a blank page will be displayed + * + * Returns: a new ModestMsgView widget, or NULL if there's an error + */ +GtkWidget* modest_msg_view_new (const TnyMsgIface *tny_msg); + + +/** + * modest_msg_view_set_message + * @self: a ModestMsgView instance + * @tny_msg: a TnyMsgIface 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, + const TnyMsgIface *tny_msg); + +/** + * modest_msg_view_get_selected_text: + * @self: a ModestMsgView instance + * + * get the user selected part of the message + * + * Returns: a newly allocated string of the user's selection or NULL if nothing is selected + */ +gchar * modest_msg_view_get_selected_text (ModestMsgView *self); + +G_END_DECLS + +#endif /* __MODEST_MSG_VIEW_H__ */ -- 1.7.9.5