From 32ba35b63ed6986eab57acf8bfd76dba10ee129e Mon Sep 17 00:00:00 2001 From: Jose Dapena Paz Date: Mon, 5 Mar 2007 18:22:46 +0000 Subject: [PATCH] * src/widgets/modest-recpt.view.[ch]: * Changed a lot the structure. Now it inherits from GtkScrolledWindow, and contains a GtkTextView (instead of a GtkLabel). * This scrolled window is limited to two lines. Then this widget includes internal methods for this, and to manage specific scrollbuttons. * Removed the calculation of address bounds in a string (it's now in text utils). * Added a method modest_recpt_view_set_recipients (), as now we don't have the GtkLabel API set_text function. * Migrated the button press/release events handling to use GtkTextView API. * Scrollbar button clicks move buffer line by line. * Now the activate handler passes a string with the recipient list. * src/widgets/modest-mail-header-view.[ch]: * Modified recpt view activate handler (now it passes a string with the activated address, not the recpt view object). * Updates to fit the new ModestRecptView api (now it's not a GtkLabel child, but a GtkScrolledWindow's). * Force allocation update of expander (to prevent a nasty effect on expanding more than one time the from/to recpt view. Now the full expander is sent to the resize and draw queues. * Added alignment hint for from/to label. * Set spacing among other headers vbox to 0. * Set the mail header "reallocate_redraws" to TRUE * src/modest-msg-view.c: * Use the new recpt view activate API. * src/modest-ui-actions.[ch]: * Added implementation of action "add to contacts". It gets the primary selection and calls the addressbook add to contacts implementation. * Updated API of msg_recpt_view_activated (now handler gets a string with the activated address). * src/modest-text-utils.[ch]: * Added modest_text_utils_address_range_at_position, used to find addresses in a string (used for automatic selection). * Added src/modest-address-book.h: * Interface to addressbook functions. Implementations fall in specific gnome/maemo modules. * src/Makefile.am: * Add modest address book interface. * src/maemo/modest-main-window-ui.h: * Added action for adding primary selection to contacts. * Added src/maemo/modest-address-book.c: * Implementation for maemo of address book interface. * Currently it only contains stub implementations, and a draft implementation of add to contacts method. * Added src/gnome/modest-address-book.c: * Implementation for gnome of address book interface. * Currently it only contains stub implementations. * src/maemo/Makefile.am * Added compilation of address book implementation * src/gnome/Makefile.am * Added compilation of address book implementation * src/maemo/ui/modest-msg-view-window-ui.xml: * Added add to contacts menu option. * src/maemo/ui/modest-main-window-ui.xml: * Added add to contacts menu option. * src/gnome/ui/modest-main-window-ui.xml: * Added add to contacts menu option. * configure.ac: * Added dependency on osso-address-book in MAEMO platform. pmo-trunk-r886 --- configure.ac | 2 +- src/Makefile.am | 1 + src/gnome/Makefile.am | 1 + src/gnome/modest-address-book.c | 45 ++++++ src/gnome/modest-main-window-ui.h | 1 + src/gnome/ui/modest-main-window-ui.xml | 4 +- src/maemo/Makefile.am | 1 + src/maemo/modest-address-book.c | 119 +++++++++++++++ src/maemo/modest-main-window-ui.h | 1 + src/maemo/ui/modest-main-window-ui.xml | 1 + src/maemo/ui/modest-msg-view-window-ui.xml | 4 + src/modest-address-book.h | 58 +++++++ src/modest-text-utils.c | 37 +++++ src/modest-text-utils.h | 18 +++ src/modest-ui-actions.c | 31 ++-- src/modest-ui-actions.h | 4 +- src/widgets/modest-mail-header-view.c | 33 ++-- src/widgets/modest-mail-header-view.h | 2 +- src/widgets/modest-msg-view.c | 10 +- src/widgets/modest-msg-view.h | 2 +- src/widgets/modest-recpt-view.c | 229 ++++++++++++++++++---------- src/widgets/modest-recpt-view.h | 8 +- 22 files changed, 491 insertions(+), 121 deletions(-) create mode 100644 src/gnome/modest-address-book.c create mode 100644 src/maemo/modest-address-book.c create mode 100644 src/modest-address-book.h diff --git a/configure.ac b/configure.ac index e7754a3..c85b54a 100644 --- a/configure.ac +++ b/configure.ac @@ -87,7 +87,7 @@ esac], [MODEST_PLATFORM=gnome AC_SUBST(MODEST_PLATFORM) if test "x$with_platform" = "xmaemo"; then - PKG_CHECK_MODULES(MODEST_LIBTINYMAIL_MAEMO,libtinymail-maemo-1.0 hildon-libs libosso libossomime) + PKG_CHECK_MODULES(MODEST_LIBTINYMAIL_MAEMO,libtinymail-maemo-1.0 hildon-libs libosso libossomime osso-addressbook-1.0) AC_SUBST(MODEST_LIBTINYMAIL_MAEMO_CFLAGS) AC_SUBST(MODEST_LIBTINYMAIL_MAEMO_LIBS) diff --git a/src/Makefile.am b/src/Makefile.am index 55a3012..1c341b9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -35,6 +35,7 @@ modest_SOURCES=\ modest-account-mgr-priv.h\ modest-account-mgr.c\ modest-account-mgr.h\ + modest-address-book.h\ modest-cache-mgr.c\ modest-cache-mgr.h\ modest-conf.c\ diff --git a/src/gnome/Makefile.am b/src/gnome/Makefile.am index 6358395..a951862 100644 --- a/src/gnome/Makefile.am +++ b/src/gnome/Makefile.am @@ -27,6 +27,7 @@ libmodest_ui_la_SOURCES= \ modest-account-assistant.c \ modest-account-assistant.h \ modest-account-view-window.c \ + modest-address-book.c \ modest-msg-edit-window.c \ modest-icon-names.h \ modest-main-window.c \ diff --git a/src/gnome/modest-address-book.c b/src/gnome/modest-address-book.c new file mode 100644 index 0000000..4dbca7d --- /dev/null +++ b/src/gnome/modest-address-book.c @@ -0,0 +1,45 @@ +/* Copyright (c) 2007, Nokia Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Nokia Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* modest-address-book.c */ + +#include + +void +modest_address_book_add_address (const gchar *address) +{ + g_message (__FUNCTION__); +} + +gchar * +modest_address_book_select_addresses (void) +{ + g_message (__FUNCTION__); + return NULL; +} diff --git a/src/gnome/modest-main-window-ui.h b/src/gnome/modest-main-window-ui.h index b62b390..ce2f341 100644 --- a/src/gnome/modest-main-window-ui.h +++ b/src/gnome/modest-main-window-ui.h @@ -85,6 +85,7 @@ static const GtkActionEntry modest_action_entries [] = { { "GotoNext", GTK_STOCK_GO_FORWARD, N_("Next"), NULL, N_("Go to next message"), G_CALLBACK (modest_ui_actions_on_next) }, /* OPTIONS */ + { "OptionsAddToContacts", NULL, N_("A_dd to accounts"), NULL, N_("Add selection to accounts"), G_CALLBACK (modest_ui_actions_on_add_to_contacts) }, { "OptionsAccounts", NULL, N_("_Accounts"), NULL, N_("Manage accounts"), G_CALLBACK (modest_ui_actions_on_accounts) }, { "OptionsContacts", NULL, N_("_Contacts"), NULL, N_("Manage contacts"), NULL }, diff --git a/src/gnome/ui/modest-main-window-ui.xml b/src/gnome/ui/modest-main-window-ui.xml index 007e1c5..2e8f21d 100644 --- a/src/gnome/ui/modest-main-window-ui.xml +++ b/src/gnome/ui/modest-main-window-ui.xml @@ -67,7 +67,9 @@ + + @@ -105,4 +107,4 @@ - \ No newline at end of file + diff --git a/src/maemo/Makefile.am b/src/maemo/Makefile.am index 8c726af..96e1231 100644 --- a/src/maemo/Makefile.am +++ b/src/maemo/Makefile.am @@ -43,6 +43,7 @@ noinst_LTLIBRARIES=\ libmodest_ui_la_SOURCES= \ modest-account-view-window.c \ + modest-address-book.c \ modest-icon-names.h \ modest-main-window.c \ modest-main-window-ui.h \ diff --git a/src/maemo/modest-address-book.c b/src/maemo/modest-address-book.c new file mode 100644 index 0000000..8babb30 --- /dev/null +++ b/src/maemo/modest-address-book.c @@ -0,0 +1,119 @@ +/* Copyright (c) 2007, Nokia Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Nokia Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* modest-address-book.c */ + +#include +#include +#include +#include + +static OssoABookContactModel *contact_model = NULL; +static EBook *book = NULL; +static EBookView * book_view = NULL; + + +static void +get_book_view_cb (EBook *book, EBookStatus status, EBookView *bookview, gpointer data) +{ + if (status != E_BOOK_ERROR_OK) { + g_object_unref (book); + book = NULL; + return; + } + book_view = bookview; + + if (contact_model) + osso_abook_tree_model_set_book_view (OSSO_ABOOK_TREE_MODEL (contact_model), + book_view); + + e_book_view_start (book_view); +} + +static void +book_open_cb (EBook *view, EBookStatus status, gpointer data) +{ + EBookQuery *query = NULL; + + if (status != E_BOOK_ERROR_OK) { + g_object_unref (book); + book = NULL; + return; + } + query = e_book_query_any_field_contains (""); + e_book_async_get_book_view (book, query, NULL, -1, get_book_view_cb, NULL); + e_book_query_unref (query); +} + +static gboolean +open_addressbook () +{ + book = e_book_new_system_addressbook (NULL); + if (!book) + return FALSE; + + e_book_async_open (book, FALSE, book_open_cb, NULL); + +} + +void +modest_address_book_add_address (const gchar *address) +{ + OssoABookAccount *account = NULL; + GtkWidget *dialog = NULL; + + contact_model = osso_abook_contact_model_new (); + if (!open_addressbook ()) { + if (contact_model) { + g_object_unref (contact_model); + contact_model = NULL; + } + return; + } + + account = osso_abook_account_get (EVC_EMAIL, NULL, address); + dialog = osso_abook_add_to_contacts_dialog_new (contact_model, account); + g_object_unref (account); + gtk_dialog_run (GTK_DIALOG (dialog)); + + if (contact_model) { + g_object_unref (contact_model); + contact_model = NULL; + } + + gtk_widget_destroy (dialog); + +} + +gchar * +modest_address_book_select_addresses (void) +{ + g_message (__FUNCTION__); +} + diff --git a/src/maemo/modest-main-window-ui.h b/src/maemo/modest-main-window-ui.h index a0d7797..e299c4f 100644 --- a/src/maemo/modest-main-window-ui.h +++ b/src/maemo/modest-main-window-ui.h @@ -95,6 +95,7 @@ static const GtkActionEntry modest_action_entries [] = { /* Tools */ { "ToolsSettings", NULL, N_("Settings..."), NULL, NULL, NULL }, + { "ToolsAddToContacts", NULL, N_("Add to contact..."), NULL, NULL, G_CALLBACK (modest_ui_actions_on_add_to_contacts) }, { "ToolsContacts", NULL, N_("Contact..."), NULL, NULL, NULL }, { "ToolsFontSettings", NULL, N_("Font settings..."), NULL, NULL, NULL }, { "ToolsSearchMessages", NULL, N_("Search messages..."), NULL, NULL, NULL }, diff --git a/src/maemo/ui/modest-main-window-ui.xml b/src/maemo/ui/modest-main-window-ui.xml index 9cb7b34..55800e6 100644 --- a/src/maemo/ui/modest-main-window-ui.xml +++ b/src/maemo/ui/modest-main-window-ui.xml @@ -87,6 +87,7 @@ + diff --git a/src/maemo/ui/modest-msg-view-window-ui.xml b/src/maemo/ui/modest-msg-view-window-ui.xml index 2495c5e..5d17534 100644 --- a/src/maemo/ui/modest-msg-view-window-ui.xml +++ b/src/maemo/ui/modest-msg-view-window-ui.xml @@ -43,6 +43,10 @@ + + + + diff --git a/src/modest-address-book.h b/src/modest-address-book.h new file mode 100644 index 0000000..75a1a9a --- /dev/null +++ b/src/modest-address-book.h @@ -0,0 +1,58 @@ +/* Copyright (c) 2007, Nokia Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Nokia Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* modest-address-book.h */ + +#ifndef __MODEST_ADDRESS_BOOK_H__ +#define __MODEST_ADDRESS_BOOK_H__ + +#include + +/** + * modest_address_book_add_address: + * @address: a string + * + * launches the UI for adding @address to the addressbook + */ +void +modest_address_book_add_address (const gchar *address); + +/** + * modest_address_book_select_addresses: + * + * Shows a dialog to select some addresses from the + * address book. + * + * Returns: a string with the addresses + */ +gchar * +modest_address_book_select_addresses (void); + + +#endif /* __MODEST_ADDRESS_BOOK_H__ */ diff --git a/src/modest-text-utils.c b/src/modest-text-utils.c index 038ac26..cfa6414 100644 --- a/src/modest-text-utils.c +++ b/src/modest-text-utils.c @@ -376,6 +376,43 @@ modest_text_utils_split_addresses_list (const gchar *addresses) } +void +modest_text_utils_address_range_at_position (const gchar *recipients_list, + gint position, + gint *start, + gint *end) +{ + gchar *current = NULL; + gint range_start = 0; + gint range_end = 0; + gint index; + gboolean is_quoted = FALSE; + + index = 0; + for (current = (gchar *) recipients_list; *current != '\0'; current = g_utf8_find_next_char (current, NULL)) { + gunichar c = g_utf8_get_char (current); + + if ((c == ',') && (!is_quoted)) { + if (index < position) { + range_start = index + 1; + } else { + break; + } + } else if (c == '\"') { + is_quoted = !is_quoted; + } else if ((c == ' ') &&(range_start == index)) { + range_start ++; + } + index ++; + range_end = index; + } + + if (start) + *start = range_start; + if (end) + *end = range_end; +} + /* ******************************************************************* */ /* ************************* UTILIY FUNCTIONS ************************ */ diff --git a/src/modest-text-utils.h b/src/modest-text-utils.h index e636ce0..18dea34 100644 --- a/src/modest-text-utils.h +++ b/src/modest-text-utils.h @@ -120,6 +120,24 @@ gchar* modest_text_utils_remove_address (const gchar *address_list, const gchar *address); /** + * modest_text_utils_address_range_at_position: + * @address_list: utf8 string containing a list of addresses + * @position: a gint + * @start: a gint pointer + * @end: a gint pointer + * + * Finds the start and end positions of the address at @position, + * in @recipients_list, a list of addresses in the format of a + * recipient list in email. It stores the results in @start and + * @end + */ +void modest_text_utils_address_range_at_position (const gchar *recipients_list, + gint position, + gint *start, + gint *end); + + +/** * modest_text_utils_convert_to_html: * @txt: a string which contains the message to quote * diff --git a/src/modest-ui-actions.c b/src/modest-ui-actions.c index 1f23d3f..83f60ff 100644 --- a/src/modest-ui-actions.c +++ b/src/modest-ui-actions.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "modest-ui-actions.h" @@ -190,6 +191,19 @@ modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win) } void +modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win) +{ + GtkClipboard *clipboard = NULL; + gchar *selection = NULL; + + clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY); + selection = gtk_clipboard_wait_for_text (clipboard); + + modest_address_book_add_address (selection); + g_free (selection); +} + +void modest_ui_actions_on_accounts (GtkAction *action, ModestWindow *win) { /* GtkDialog *account_win; */ @@ -955,23 +969,10 @@ modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, int index, void modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview, - ModestRecptView *recpt_view, + const gchar *address, ModestWindow *win) { - gint start, end; - gchar *utf_start, *utf_end; - gchar *full_string = NULL; - gchar *substring; - - gtk_label_get_selection_bounds (GTK_LABEL (recpt_view), &start, &end); - full_string = (gchar *) gtk_label_get_text (GTK_LABEL (recpt_view)); - utf_start = g_utf8_offset_to_pointer (full_string, start); - utf_end = g_utf8_offset_to_pointer (full_string, end); - substring = g_strndup (utf_start, utf_end - utf_start); - g_message ("%s %s", __FUNCTION__, substring); - - g_free (substring); - + g_message ("%s %s", __FUNCTION__, address); } void diff --git a/src/modest-ui-actions.h b/src/modest-ui-actions.h index 323d7c8..542b062 100644 --- a/src/modest-ui-actions.h +++ b/src/modest-ui-actions.h @@ -45,6 +45,8 @@ void modest_ui_actions_on_quit (GtkAction *action, ModestWindow *wi void modest_ui_actions_on_accounts (GtkAction *action, ModestWindow *win); +void modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win); + void modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win); void modest_ui_actions_on_open (GtkAction *action, ModestWindow *win); @@ -96,7 +98,7 @@ void modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, void modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, int index, ModestWindow *win); -void modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview, ModestRecptView *recpt_view, +void modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview, const gchar *address, ModestWindow *win); void modest_ui_actions_on_send (GtkWidget *widget, diff --git a/src/widgets/modest-mail-header-view.c b/src/widgets/modest-mail-header-view.c index 4e5ac27..77a3ce3 100644 --- a/src/widgets/modest-mail-header-view.c +++ b/src/widgets/modest-mail-header-view.c @@ -64,11 +64,11 @@ struct _ModestMailHeaderViewPriv static guint signals[LAST_SIGNAL] = {0}; static void -activate_recpt (GtkWidget *recpt_view, gpointer user_data) +activate_recpt (GtkWidget *recpt_view, const gchar *address, gpointer user_data) { ModestMailHeaderView * view = MODEST_MAIL_HEADER_VIEW (user_data); - g_signal_emit (G_OBJECT (view), signals[RECPT_ACTIVATED_SIGNAL], 0, recpt_view); + g_signal_emit (G_OBJECT (view), signals[RECPT_ACTIVATED_SIGNAL], 0, address); } static void @@ -108,9 +108,7 @@ add_recpt_header (ModestMailHeaderView *widget, const gchar *field, const gchar gtk_label_set_markup (GTK_LABEL (label_field), field); gtk_misc_set_alignment (GTK_MISC (label_field), 0.0, 0.0); label_value = modest_recpt_view_new (); - gtk_label_set_text (GTK_LABEL (label_value), value); - gtk_label_set_selectable (GTK_LABEL (label_value), TRUE); - gtk_misc_set_alignment (GTK_MISC (label_value), 0.0, 0.0); + modest_recpt_view_set_recipients (MODEST_RECPT_VIEW(label_value), value); g_signal_connect (G_OBJECT (label_value), "activate", G_CALLBACK (activate_recpt), widget); gtk_box_pack_start (GTK_BOX (hbox), label_field, FALSE, FALSE, 0); @@ -173,14 +171,14 @@ modest_mail_header_view_set_header_default (TnyHeaderView *self, TnyHeader *head gchar *sent = modest_text_utils_get_display_date (tny_header_get_date_sent (header)); gtk_label_set_markup (GTK_LABEL (priv->fromto_label), _("To:")); if (to) - gtk_label_set_text (GTK_LABEL (priv->fromto_contents), to); + modest_recpt_view_set_recipients (MODEST_RECPT_VIEW (priv->fromto_contents), to); add_header (MODEST_MAIL_HEADER_VIEW (self), _("Sent:"), sent); g_free (sent); } else { gchar *received = modest_text_utils_get_display_date (tny_header_get_date_received (header)); gtk_label_set_markup (GTK_LABEL (priv->fromto_label), _("From:")); if (from) - gtk_label_set_text (GTK_LABEL (priv->fromto_contents), from); + modest_recpt_view_set_recipients (MODEST_RECPT_VIEW (priv->fromto_contents), from); add_header (MODEST_MAIL_HEADER_VIEW (self), _("Received:"), received); g_free (received); } @@ -214,7 +212,7 @@ modest_mail_header_view_clear_default (TnyHeaderView *self) clean_headers (priv->headers_vbox); gtk_label_set_text (GTK_LABEL (priv->fromto_label), ""); - gtk_label_set_text (GTK_LABEL (priv->fromto_contents), ""); + modest_recpt_view_set_recipients (MODEST_RECPT_VIEW (priv->fromto_contents), ""); gtk_widget_hide (GTK_WIDGET(self)); @@ -226,6 +224,9 @@ expander_activate (GtkWidget *expander, ModestMailHeaderView *header_view) { ModestMailHeaderViewPriv *priv = MODEST_MAIL_HEADER_VIEW_GET_PRIVATE (header_view); + gtk_widget_queue_resize (GTK_WIDGET (header_view)); + gtk_widget_queue_draw (GTK_WIDGET (header_view)); + if (gtk_expander_get_expanded (GTK_EXPANDER (expander))) { if (gtk_widget_get_parent (priv->headers_vbox) == NULL) { gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->headers_vbox, TRUE, TRUE, 0); @@ -236,8 +237,8 @@ expander_activate (GtkWidget *expander, ModestMailHeaderView *header_view) gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->headers_vbox); } } - gtk_widget_queue_resize (GTK_WIDGET (header_view)); - gtk_widget_queue_draw (GTK_WIDGET (header_view)); + gtk_widget_queue_resize (GTK_WIDGET (priv->expander)); + gtk_widget_queue_draw (GTK_WIDGET (priv->expander)); } /** @@ -271,10 +272,8 @@ modest_mail_header_view_instance_init (GTypeInstance *instance, gpointer g_class fromto_hbox = gtk_hbox_new (FALSE, 12); priv->fromto_label = gtk_label_new (NULL); - priv->fromto_contents = modest_recpt_view_new (); - gtk_label_set_selectable (GTK_LABEL (priv->fromto_contents), TRUE); gtk_misc_set_alignment (GTK_MISC (priv->fromto_label), 0.0, 0.0); - gtk_misc_set_alignment (GTK_MISC (priv->fromto_contents), 0.0, 0.0); + priv->fromto_contents = modest_recpt_view_new (); g_signal_connect (G_OBJECT (priv->fromto_contents), "activate", G_CALLBACK (activate_recpt), instance); gtk_box_pack_start (GTK_BOX (fromto_hbox), priv->fromto_label, FALSE, FALSE, 0); @@ -284,7 +283,7 @@ modest_mail_header_view_instance_init (GTypeInstance *instance, gpointer g_class priv->labels_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); gtk_size_group_add_widget (priv->labels_size_group, priv->fromto_label); - priv->headers_vbox = gtk_vbox_new (FALSE, 1); + priv->headers_vbox = gtk_vbox_new (FALSE, 0); g_object_ref (priv->headers_vbox); expander_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); @@ -292,6 +291,8 @@ modest_mail_header_view_instance_init (GTypeInstance *instance, gpointer g_class gtk_size_group_add_widget (expander_group, fromto_hbox); g_object_unref (expander_group); + gtk_container_set_reallocate_redraws (GTK_CONTAINER (instance), TRUE); + priv->is_sent = FALSE; return; @@ -353,9 +354,9 @@ modest_mail_header_view_class_init (ModestMailHeaderViewClass *klass) G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, G_STRUCT_OFFSET(ModestMailHeaderViewClass, recpt_activated), NULL, NULL, - g_cclosure_marshal_VOID__POINTER, + g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, - MODEST_TYPE_RECPT_VIEW); + G_TYPE_STRING); return; diff --git a/src/widgets/modest-mail-header-view.h b/src/widgets/modest-mail-header-view.h index d949bdc..bf76528 100644 --- a/src/widgets/modest-mail-header-view.h +++ b/src/widgets/modest-mail-header-view.h @@ -63,7 +63,7 @@ struct _ModestMailHeaderViewClass void (*clear_func) (TnyHeaderView *self); /* signals */ - void (*recpt_activated) (ModestRecptView *recpt_view); + void (*recpt_activated) (const gchar *address); }; GType modest_mail_header_view_get_type (void); diff --git a/src/widgets/modest-msg-view.c b/src/widgets/modest-msg-view.c index b6e25e8..7d1653d 100644 --- a/src/widgets/modest-msg-view.c +++ b/src/widgets/modest-msg-view.c @@ -50,7 +50,7 @@ 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 void on_recpt_activated (ModestMailHeaderView *header_view, ModestRecptView *recpt_view, ModestMsgView *msg_view); +static void on_recpt_activated (ModestMailHeaderView *header_view, const gchar *address, ModestMsgView *msg_view); 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); @@ -153,8 +153,8 @@ modest_msg_view_class_init (ModestMsgViewClass *klass) G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(ModestMsgViewClass, recpt_activated), NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, MODEST_TYPE_RECPT_VIEW); + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, G_TYPE_STRING); } static void @@ -243,10 +243,10 @@ modest_msg_view_new (TnyMsg *msg) static void on_recpt_activated (ModestMailHeaderView *header_view, - ModestRecptView *recpt_view, + const gchar *address, ModestMsgView * view) { - g_signal_emit (G_OBJECT (view), signals[RECPT_ACTIVATED_SIGNAL], 0, recpt_view); + g_signal_emit (G_OBJECT (view), signals[RECPT_ACTIVATED_SIGNAL], 0, address); } static gboolean diff --git a/src/widgets/modest-msg-view.h b/src/widgets/modest-msg-view.h index 99c16b0..e348762 100644 --- a/src/widgets/modest-msg-view.h +++ b/src/widgets/modest-msg-view.h @@ -62,7 +62,7 @@ struct _ModestMsgViewClass { gpointer user_data); void (*attachment_clicked) (ModestMsgView *msgview, int index, gpointer user_data); - void (*recpt_activated) (ModestMsgView *msgview, ModestRecptView *recpt_view, + void (*recpt_activated) (ModestMsgView *msgview, const gchar *address, gpointer user_data); }; diff --git a/src/widgets/modest-recpt-view.c b/src/widgets/modest-recpt-view.c index 9c45732..f724876 100644 --- a/src/widgets/modest-recpt-view.c +++ b/src/widgets/modest-recpt-view.c @@ -34,7 +34,8 @@ #include #include -#include "modest-recpt-view.h" +#include +#include static GObjectClass *parent_class = NULL; @@ -48,8 +49,10 @@ typedef struct _ModestRecptViewPriv ModestRecptViewPriv; struct _ModestRecptViewPriv { + GtkWidget *text_view; gboolean button_pressed; gdouble pressed_x, pressed_y; + gint line_height; }; #define MODEST_RECPT_VIEW_GET_PRIVATE(o) \ @@ -57,6 +60,7 @@ struct _ModestRecptViewPriv static guint signals[LAST_SIGNAL] = {0}; + /** * modest_recpt_view_new: * @@ -70,107 +74,103 @@ modest_recpt_view_new (void) return GTK_WIDGET (self); } -static void -address_bounds_at_position (const gchar *recipients_list, gint position, gint *start, gint *end) +void +modest_recpt_view_set_recipients (ModestRecptView *recpt_view, const gchar *recipients) { - gchar *current = NULL; - gint range_start = 0; - gint range_end = 0; - gint index; - gboolean is_quoted = FALSE; - - index = 0; - for (current = (gchar *) recipients_list; *current != '\0'; current = g_utf8_find_next_char (current, NULL)) { - gunichar c = g_utf8_get_char (current); - - if ((c == ',') && (!is_quoted)) { - if (index < position) { - range_start = index + 1; - } else { - break; - } - } else if (c == '\"') { - is_quoted = !is_quoted; - } else if ((c == ' ') &&(range_start == index)) { - range_start ++; - } - index ++; - range_end = index; - } + GtkTextBuffer *buffer = NULL; + ModestRecptViewPriv *priv = MODEST_RECPT_VIEW_GET_PRIVATE (recpt_view); + + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->text_view)); + gtk_text_buffer_set_text (buffer, recipients, -1); + gtk_widget_queue_resize (GTK_WIDGET (recpt_view)); - if (start) - *start = range_start; - if (end) - *end = range_end; } -static gboolean +static gint button_press_event (GtkWidget *widget, GdkEventButton *event, gpointer user_data) { - ModestRecptViewPriv *priv = MODEST_RECPT_VIEW_GET_PRIVATE (MODEST_RECPT_VIEW (widget)); - - if (!gtk_label_get_selectable (GTK_LABEL (widget))) - return FALSE; + ModestRecptViewPriv *priv = MODEST_RECPT_VIEW_GET_PRIVATE (MODEST_RECPT_VIEW (user_data)); - if (event->type == GDK_BUTTON_PRESS) { + if (event->type == GDK_BUTTON_PRESS && event->button == 1) { priv->button_pressed = TRUE; priv->pressed_x = event->x; priv->pressed_y = event->y; } - return FALSE; + return TRUE; } -static gboolean +static gint button_release_event (GtkWidget *widget, - GdkEventButton *event, - gpointer user_data) + GdkEventButton *event, + gpointer user_data) { - ModestRecptViewPriv *priv = MODEST_RECPT_VIEW_GET_PRIVATE (MODEST_RECPT_VIEW (widget)); - - if (!gtk_label_get_selectable (GTK_LABEL (widget))) - return TRUE; + ModestRecptViewPriv *priv = MODEST_RECPT_VIEW_GET_PRIVATE (MODEST_RECPT_VIEW (user_data)); if (event->type != GDK_BUTTON_RELEASE) return TRUE; if ((priv->button_pressed) && - (event->type == GDK_BUTTON_RELEASE) && + (event->type == GDK_BUTTON_RELEASE) && (priv->pressed_x == event->x) && (priv->pressed_y == event->y)) { priv->button_pressed = FALSE; if (event->button == 1) { - PangoLayout *layout = NULL; + gint buffer_x, buffer_y; int index; - layout = gtk_label_get_layout (GTK_LABEL (widget)); - if (pango_layout_xy_to_index (layout, event->x*PANGO_SCALE, event->y*PANGO_SCALE, &index, NULL)) { + GtkTextIter iter; + gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (priv->text_view), GTK_TEXT_WINDOW_WIDGET, + event->x, event->y, &buffer_x, &buffer_y); + gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (priv->text_view), &iter, buffer_x, buffer_y); + index = gtk_text_iter_get_offset (&iter); + + if (!gtk_text_iter_is_end (&iter)) { int selection_start, selection_end; gboolean selected = FALSE; - if (gtk_label_get_selection_bounds (GTK_LABEL (widget), - &selection_start, - &selection_end) && - (index >= selection_start)&&(index < selection_end)) { + GtkTextIter start_iter, end_iter; + GtkTextBuffer *buffer; + + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->text_view)); + if (gtk_text_buffer_get_selection_bounds (buffer, &start_iter, &end_iter) && + gtk_text_iter_in_range (&iter, &start_iter, &end_iter)) { selected = TRUE; + } else { + gchar *text = NULL; + GtkTextIter start_iter, end_iter; + + gtk_text_buffer_get_start_iter (buffer, &start_iter); + gtk_text_buffer_get_end_iter (buffer, &end_iter); + text = gtk_text_buffer_get_text (buffer, &start_iter, &end_iter, FALSE); + + modest_text_utils_address_range_at_position (text, + index, + &selection_start, &selection_end); + /* TODO: now gtk label tries to select more than the label as usual, + * and we force it to recover the selected region for the defined area. + * It should be fixed (maybe preventing gtklabel to manage selections + * in parallel with us + */ + gtk_text_buffer_get_iter_at_offset (buffer, &start_iter, selection_start); + gtk_text_buffer_get_iter_at_offset (buffer, &end_iter, selection_end); + gtk_text_buffer_select_range (buffer, &start_iter, &end_iter); + + if (text) + g_free (text); + + } + + if (selected) { + gchar *selection; + + gtk_text_buffer_get_selection_bounds (buffer, &start_iter, &end_iter); + selection = gtk_text_buffer_get_text (buffer, &start_iter, &end_iter, FALSE); + g_signal_emit (G_OBJECT (user_data), signals[ACTIVATE_SIGNAL], 0, selection); + g_free (selection); } - address_bounds_at_position (gtk_label_get_text (GTK_LABEL (widget)), - index, - &selection_start, &selection_end); - /* TODO: now gtk label tries to select more than the label as usual, - * and we force it to recover the selected region for the defined area. - * It should be fixed (maybe preventing gtklabel to manage selections - * in parallel with us - */ - gtk_label_select_region (GTK_LABEL (widget), - selection_start, - selection_end); - - if (selected) - g_signal_emit (G_OBJECT (widget), signals[ACTIVATE_SIGNAL], 0); - - return TRUE; } + return TRUE; } } priv->button_pressed = FALSE; @@ -178,15 +178,88 @@ button_release_event (GtkWidget *widget, } static void +text_view_size_request (GtkWidget *widget, + GtkRequisition *requisition, + gpointer user_data) +{ + GtkTextBuffer *buffer = NULL; + GtkTextIter iter; + int line; + GdkRectangle iter_rectangle; + GtkWidget *text_view = GTK_WIDGET (user_data); + GtkAdjustment *adj = NULL; + ModestRecptViewPriv *priv = MODEST_RECPT_VIEW_GET_PRIVATE (widget); + + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view)); + + gtk_text_buffer_get_start_iter (buffer, &iter); + gtk_text_view_get_iter_location (GTK_TEXT_VIEW (text_view), &iter, &iter_rectangle); + + for (line = 0; line < 2; line++) { + if (!gtk_text_view_forward_display_line (GTK_TEXT_VIEW (text_view), &iter)) + break; + } + + gtk_text_buffer_get_start_iter (buffer, &iter); + + gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (text_view), &iter, 0.0, TRUE, 0.0, 0.0); + + adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (widget)); + if (adj != NULL) { + g_object_set (G_OBJECT (adj), "page-increment", (gdouble) iter_rectangle.height, "step-increment", (gdouble) iter_rectangle.height, NULL); + gtk_adjustment_changed (adj); + } + + if (line > 0) { + requisition->height = iter_rectangle.height * 2; + } else { + requisition->height = iter_rectangle.height; + } + + priv->line_height = iter_rectangle.height; + +} + +static void +view_size_allocate (GtkWidget *widget, + GtkAllocation *allocation, + gpointer user_data) +{ + GtkAdjustment *adj = NULL; + ModestRecptViewPriv *priv = MODEST_RECPT_VIEW_GET_PRIVATE (widget); + + adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (widget)); + if (adj != NULL) { + g_object_set (G_OBJECT (adj), "page-increment", (gdouble) priv->line_height, "step-increment", (gdouble) priv->line_height, NULL); + } + gtk_adjustment_changed (adj); +} + +static void modest_recpt_view_instance_init (GTypeInstance *instance, gpointer g_class) { + ModestRecptViewPriv *priv = MODEST_RECPT_VIEW_GET_PRIVATE (instance); + + priv->text_view = gtk_text_view_new (); + + gtk_text_view_set_editable (GTK_TEXT_VIEW (priv->text_view), FALSE); + gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->text_view), GTK_WRAP_WORD_CHAR); + gtk_text_view_set_pixels_above_lines (GTK_TEXT_VIEW (priv->text_view), 0); + gtk_text_view_set_pixels_below_lines (GTK_TEXT_VIEW (priv->text_view), 0); + gtk_text_view_set_justification (GTK_TEXT_VIEW (priv->text_view), GTK_JUSTIFY_LEFT); + gtk_text_view_set_left_margin (GTK_TEXT_VIEW (priv->text_view), 0); + gtk_text_view_set_right_margin (GTK_TEXT_VIEW (priv->text_view), 0); + gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (priv->text_view), FALSE); + gtk_drag_dest_unset (priv->text_view); + + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (instance), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); - gtk_label_set_justify (GTK_LABEL (instance), GTK_JUSTIFY_LEFT); - gtk_label_set_line_wrap (GTK_LABEL (instance), TRUE); - gtk_label_set_selectable (GTK_LABEL (instance), TRUE); + gtk_container_add (GTK_CONTAINER (instance), priv->text_view); - g_signal_connect (G_OBJECT (instance), "button-press-event", G_CALLBACK(button_press_event), NULL); - g_signal_connect (G_OBJECT (instance), "button-release-event", G_CALLBACK(button_release_event), NULL); + g_signal_connect (G_OBJECT (instance), "size-request", G_CALLBACK (text_view_size_request), priv->text_view); + g_signal_connect (G_OBJECT (instance), "size-allocate", G_CALLBACK (view_size_allocate), NULL); + g_signal_connect (G_OBJECT (priv->text_view), "button-press-event", G_CALLBACK (button_press_event), instance); + g_signal_connect (G_OBJECT (priv->text_view), "button-release-event", G_CALLBACK (button_release_event), instance); return; } @@ -203,9 +276,11 @@ static void modest_recpt_view_class_init (ModestRecptViewClass *klass) { GObjectClass *object_class; + GtkWidgetClass *widget_class; parent_class = g_type_class_peek_parent (klass); object_class = (GObjectClass*) klass; + widget_class = GTK_WIDGET_CLASS (klass); object_class->finalize = modest_recpt_view_finalize; @@ -219,8 +294,8 @@ modest_recpt_view_class_init (ModestRecptViewClass *klass) G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, G_STRUCT_OFFSET(ModestRecptViewClass, activate), NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, G_TYPE_STRING); return; } @@ -245,7 +320,7 @@ modest_recpt_view_get_type (void) modest_recpt_view_instance_init /* instance_init */ }; - type = g_type_register_static (GTK_TYPE_LABEL, + type = g_type_register_static (GTK_TYPE_SCROLLED_WINDOW, "ModestRecptView", &info, 0); diff --git a/src/widgets/modest-recpt-view.h b/src/widgets/modest-recpt-view.h index 021d24b..3810f7a 100644 --- a/src/widgets/modest-recpt-view.h +++ b/src/widgets/modest-recpt-view.h @@ -46,21 +46,23 @@ typedef struct _ModestRecptViewClass ModestRecptViewClass; struct _ModestRecptView { - GtkLabel parent; + GtkScrolledWindow parent; }; struct _ModestRecptViewClass { - GtkLabelClass parent_class; + GtkScrolledWindowClass parent_class; - void (*activate) (ModestRecptView *recpt_view); + void (*activate) (ModestRecptView *recpt_view, const gchar *address); }; GType modest_recpt_view_get_type (void); GtkWidget* modest_recpt_view_new (void); +void modest_recpt_view_set_recipients (ModestRecptView *recpt_view, const gchar *recipients); + G_END_DECLS #endif -- 1.7.9.5