[geary] Display participants in subtitle of conversation header



commit ef87b0dbc3d09855ea54f1923d3d95014ebc1aaa
Author: Robert Schroll <rschroll gmail com>
Date:   Wed Mar 4 01:21:09 2015 -0500

    Display participants in subtitle of conversation header

 src/client/components/main-toolbar.vala            |   33 ++++++-
 .../formatted-conversation-data.vala               |  102 +------------------
 src/client/util/util-email.vala                    |  109 ++++++++++++++++++++
 3 files changed, 143 insertions(+), 101 deletions(-)
---
diff --git a/src/client/components/main-toolbar.vala b/src/client/components/main-toolbar.vala
index bf6a980..99524fe 100644
--- a/src/client/components/main-toolbar.vala
+++ b/src/client/components/main-toolbar.vala
@@ -11,6 +11,7 @@ public class MainToolbar : Gtk.Box {
     public string account { get; set; }
     public string folder { get; set; }
     public string conversation_title { get; private set; }
+    public string conversation_participants { get; private set; }
     public bool show_close_button { get; set; default = false; }
     public bool show_close_button_left { get; private set; }
     public bool show_close_button_right { get; private set; }
@@ -40,6 +41,8 @@ public class MainToolbar : Gtk.Box {
             BindingFlags.SYNC_CREATE);
         this.bind_property("conversation-title", conversation_header, "title",
             BindingFlags.SYNC_CREATE);
+        this.bind_property("conversation-participants", conversation_header, "subtitle",
+            BindingFlags.SYNC_CREATE);
         this.bind_property("show-close-button-right", conversation_header, "show-close-button",
             BindingFlags.SYNC_CREATE);
         
@@ -136,6 +139,27 @@ public class MainToolbar : Gtk.Box {
         conversation_header.add_end(archive_trash_delete);
 #endif
         
+        Gtk.Label title_label = new Gtk.Label(null);
+        conversation_header.bind_property("title", title_label, "label", BindingFlags.SYNC_CREATE);
+        conversation_header.bind_property("title", title_label, "tooltip-text",
+            BindingFlags.SYNC_CREATE);
+        title_label.get_style_context().add_class("title");
+        title_label.ellipsize = Pango.EllipsizeMode.END;
+        Gtk.Label subtitle_label = new Gtk.Label(null);
+        conversation_header.bind_property("subtitle", subtitle_label, "label",
+            BindingFlags.SYNC_CREATE);
+        conversation_header.bind_property("subtitle", subtitle_label, "tooltip-text",
+            BindingFlags.SYNC_CREATE);
+        subtitle_label.get_style_context().add_class("subtitle");
+        subtitle_label.get_style_context().add_class("dim-label");
+        subtitle_label.ellipsize = Pango.EllipsizeMode.END;
+        Gtk.Box title_box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
+        title_box.pack_start(title_label);
+        title_box.pack_start(subtitle_label);
+        title_box.set_margin_left(6);
+        title_box.set_margin_right(6);
+        conversation_header.set_custom_title(title_box);
+        
         pack_start(folder_header, false, false);
         pack_start(new Gtk.Separator(Gtk.Orientation.VERTICAL), false, false);
         pack_start(conversation_header, true, true);
@@ -192,16 +216,23 @@ public class MainToolbar : Gtk.Box {
         int selected_count = conversations.size;
         if (selected_count == 0) {
             conversation_title = _("No conversations selected");
+            conversation_participants = "";
         } else if (selected_count == 1) {
-            Geary.Email? last_email = conversations.to_array()[0].get_latest_recv_email(
+            Geary.App.Conversation conversation = conversations.to_array()[0];
+            Geary.Email? last_email = conversation.get_latest_recv_email(
                 Geary.App.Conversation.Location.ANYWHERE);
             if (last_email != null)
                 conversation_title = EmailUtil.strip_subject_prefixes(last_email);
             else
                 conversation_title = "";
+            
+            conversation_participants = EmailUtil.get_participants(conversation,
+                current_folder.account.information.get_all_mailboxes(),
+                current_folder.special_folder_type.is_outgoing(), false);
         } else {
             conversation_title = ngettext("%u conversation selected", "%u conversations selected",
                 selected_count).printf(selected_count);
+            conversation_participants = "";
         }
     }
 }
diff --git a/src/client/conversation-list/formatted-conversation-data.vala 
b/src/client/conversation-list/formatted-conversation-data.vala
index 4cd56d2..84ca6a4 100644
--- a/src/client/conversation-list/formatted-conversation-data.vala
+++ b/src/client/conversation-list/formatted-conversation-data.vala
@@ -8,7 +8,6 @@
 public class FormattedConversationData : Geary.BaseObject {
     public const int LINE_SPACING = 6;
     
-    private const string ME = _("Me");
     private const string STYLE_EXAMPLE = "Gg"; // Use both upper and lower case to get max height.
     private const int TEXT_LEFT = LINE_SPACING * 2 + IconFactory.UNREAD_ICON_SIZE;
     private const double DIM_TEXT_AMOUNT = 0.05;
@@ -19,59 +18,6 @@ public class FormattedConversationData : Geary.BaseObject {
     private const int FONT_SIZE_FROM = 11;
     private const int FONT_SIZE_PREVIEW = 8;
     
-    private class ParticipantDisplay : Geary.BaseObject, Gee.Hashable<ParticipantDisplay> {
-        public Geary.RFC822.MailboxAddress address;
-        public bool is_unread;
-        
-        public ParticipantDisplay(Geary.RFC822.MailboxAddress address, bool is_unread) {
-            this.address = address;
-            this.is_unread = is_unread;
-        }
-        
-        public string get_full_markup(Gee.List<Geary.RFC822.MailboxAddress> account_mailboxes) {
-            return get_as_markup((address in account_mailboxes) ? ME : address.get_short_address());
-        }
-        
-        public string get_short_markup(Gee.List<Geary.RFC822.MailboxAddress> account_mailboxes) {
-            if (address in account_mailboxes)
-                return get_as_markup(ME);
-            
-            string short_address = address.get_short_address().strip();
-            
-            if (", " in short_address) {
-                // assume address is in Last, First format
-                string[] tokens = short_address.split(", ", 2);
-                short_address = tokens[1].strip();
-                if (Geary.String.is_empty(short_address))
-                    return get_full_markup(account_mailboxes);
-            }
-            
-            // use first name as delimited by a space
-            string[] tokens = short_address.split(" ", 2);
-            if (tokens.length < 1)
-                return get_full_markup(account_mailboxes);
-            
-            string first_name = tokens[0].strip();
-            if (Geary.String.is_empty_or_whitespace(first_name))
-                return get_full_markup(account_mailboxes);
-            
-            return get_as_markup(first_name);
-        }
-        
-        private string get_as_markup(string participant) {
-            return "%s%s%s".printf(
-                is_unread ? "<b>" : "", Geary.HTML.escape_markup(participant), is_unread ? "</b>" : "");
-        }
-        
-        public bool equal_to(ParticipantDisplay other) {
-            return address.equal_to(other.address);
-        }
-        
-        public uint hash() {
-            return address.hash();
-        }
-    }
-    
     private static int cell_height = -1;
     private static int preview_height = -1;
     
@@ -171,52 +117,8 @@ public class FormattedConversationData : Geary.BaseObject {
         if (conversation == null || account_owner_emails == null || account_owner_emails.size == 0)
             return "";
         
-        // Build chronological list of AuthorDisplay records, setting to unread if any message by
-        // that author is unread
-        Gee.ArrayList<ParticipantDisplay> list = new Gee.ArrayList<ParticipantDisplay>();
-        foreach (Geary.Email message in 
conversation.get_emails(Geary.App.Conversation.Ordering.RECV_DATE_ASCENDING)) {
-            // only display if something to display
-            Geary.RFC822.MailboxAddresses? addresses = use_to ? message.to : message.from;
-            if (addresses == null || addresses.size < 1)
-                continue;
-            
-            foreach (Geary.RFC822.MailboxAddress address in addresses) {
-                ParticipantDisplay participant_display = new ParticipantDisplay(address,
-                    message.email_flags.is_unread());
-
-                // if not present, add in chronological order
-                int existing_index = list.index_of(participant_display);
-                if (existing_index < 0) {
-                    list.add(participant_display);
-
-                    continue;
-                }
-                
-                // if present and this message is unread but the prior were read,
-                // this author is now unread
-                if (message.email_flags.is_unread() && !list[existing_index].is_unread)
-                    list[existing_index].is_unread = true;
-            }
-        }
-        
-        StringBuilder builder = new StringBuilder("<span foreground='%s'>".printf(
-            rgba_to_markup(get_foreground_rgba(widget, selected))));
-        if (list.size == 1) {
-            // if only one participant, use full name
-            builder.append(list[0].get_full_markup(account_owner_emails));
-        } else {
-            bool first = true;
-            foreach (ParticipantDisplay participant in list) {
-                if (!first)
-                    builder.append(", ");
-                
-                builder.append(participant.get_short_markup(account_owner_emails));
-                first = false;
-            }
-        }
-        builder.append("</span>");
-        
-        return builder.str;
+        return EmailUtil.get_participants(conversation, account_owner_emails, use_to, true,
+            rgba_to_markup(get_foreground_rgba(widget, selected)));
     }
     
     public void render(Cairo.Context ctx, Gtk.Widget widget, Gdk.Rectangle background_area, 
diff --git a/src/client/util/util-email.vala b/src/client/util/util-email.vala
index 3f23759..a06e8a4 100644
--- a/src/client/util/util-email.vala
+++ b/src/client/util/util-email.vala
@@ -30,5 +30,114 @@ public string strip_subject_prefixes(Geary.Email email) {
     return !Geary.String.is_empty(cleaned) ? cleaned : _("(no subject)");
 }
 
+public string get_participants(Geary.App.Conversation conversation,
+    Gee.List<Geary.RFC822.MailboxAddress> account_owner_emails, bool use_to, bool markup,
+    string? foreground = null) {
+    
+    // Build chronological list of AuthorDisplay records, setting to unread if any message by
+    // that author is unread
+    Gee.ArrayList<ParticipantDisplay> list = new Gee.ArrayList<ParticipantDisplay>();
+    foreach (Geary.Email message in conversation.get_emails(
+        Geary.App.Conversation.Ordering.RECV_DATE_ASCENDING)) {
+        // only display if something to display
+        Geary.RFC822.MailboxAddresses? addresses = use_to ? message.to : message.from;
+        if (addresses == null || addresses.size < 1)
+            continue;
+        
+        foreach (Geary.RFC822.MailboxAddress address in addresses) {
+            ParticipantDisplay participant_display = new ParticipantDisplay(address,
+                markup && message.email_flags.is_unread());
+
+            // if not present, add in chronological order
+            int existing_index = list.index_of(participant_display);
+            if (existing_index < 0) {
+                list.add(participant_display);
+
+                continue;
+            }
+            
+            // if present and this message is unread but the prior were read,
+            // this author is now unread
+            if (message.email_flags.is_unread() && !list[existing_index].is_unread)
+                list[existing_index].is_unread = true;
+        }
+    }
+    
+    StringBuilder builder = new StringBuilder(markup ? @"<span foreground='$foreground'>" : "");
+    if (list.size == 1) {
+        // if only one participant, use full name
+        builder.append(list[0].get_full(account_owner_emails, markup));
+    } else {
+        bool first = true;
+        foreach (ParticipantDisplay participant in list) {
+            if (!first)
+                builder.append(", ");
+            
+            builder.append(participant.get_short(account_owner_emails, markup));
+            first = false;
+        }
+    }
+    if (markup)
+        builder.append("</span>");
+    
+    return builder.str;
+}
+
+private class ParticipantDisplay : Geary.BaseObject, Gee.Hashable<ParticipantDisplay> {
+    private const string ME = _("Me");
+    
+    public Geary.RFC822.MailboxAddress address;
+    public bool is_unread;
+    
+    public ParticipantDisplay(Geary.RFC822.MailboxAddress address, bool is_unread) {
+        this.address = address;
+        this.is_unread = is_unread;
+    }
+    
+    public string get_full(Gee.List<Geary.RFC822.MailboxAddress> account_mailboxes, bool markup) {
+        string name = (address in account_mailboxes) ? ME : address.get_short_address();
+        return markup ? get_as_markup(name) : name;
+    }
+    
+    public string get_short(Gee.List<Geary.RFC822.MailboxAddress> account_mailboxes, bool markup) {
+        if (address in account_mailboxes)
+            return markup ? get_as_markup(ME) : ME;
+        
+        string short_address = address.get_short_address().strip();
+        
+        if (", " in short_address) {
+            // assume address is in Last, First format
+            string[] tokens = short_address.split(", ", 2);
+            short_address = tokens[1].strip();
+            if (Geary.String.is_empty(short_address))
+                return get_full(account_mailboxes, markup);
+        }
+        
+        // use first name as delimited by a space
+        string[] tokens = short_address.split(" ", 2);
+        if (tokens.length < 1)
+            return get_full(account_mailboxes, markup);
+        
+        string first_name = tokens[0].strip();
+        if (Geary.String.is_empty_or_whitespace(first_name))
+            return get_full(account_mailboxes, markup);
+        
+        return markup ? get_as_markup(first_name) : first_name;
+    }
+    
+    private string get_as_markup(string participant) {
+        return "%s%s%s".printf(
+            is_unread ? "<b>" : "", Geary.HTML.escape_markup(participant), is_unread ? "</b>" : "");
+    }
+    
+    public bool equal_to(ParticipantDisplay other) {
+        return address.equal_to(other.address);
+    }
+    
+    public uint hash() {
+        return address.hash();
+    }
+}
+
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]