[geary] Allow user to specify signature for new messages: Bug #712895



commit c5228fd777e8d4c88dc014d85610e5dabf17f2f3
Author: Gustavo Rubio <gus ahivamos net>
Date:   Thu May 29 15:49:04 2014 -0700

    Allow user to specify signature for new messages: Bug #712895
    
    User may now add a brief signature in the Accounts manager for
    each account.  When starting a new message or replying, the signature
    is prepended to the edit text.

 THANKS                                        |    1 +
 src/client/accounts/add-edit-page.vala        |   46 ++++++++-
 src/client/composer/composer-widget.vala      |   36 +++++++
 src/engine/api/geary-account-information.vala |   20 ++++
 ui/login.glade                                |  132 +++++++++++++++++++------
 5 files changed, 202 insertions(+), 33 deletions(-)
---
diff --git a/THANKS b/THANKS
index e47e3cf..1028885 100644
--- a/THANKS
+++ b/THANKS
@@ -36,6 +36,7 @@ Mario Sanchez Prada <msanchez igalia com>
 Tiago Quelhas <tiagoq gmail com>
 Didier Roche <didrocks ubuntu com>
 Janosch Rolles <janosch rolles org>
+Gustavo Rubio <gus ahivamos net>
 Michel Alexandre Salim <salimma fedoraproject org>
 Anirudh Sanjeev <skyronic gmail com>
 Jakub Steiner <jimmac gmail com>
diff --git a/src/client/accounts/add-edit-page.vala b/src/client/accounts/add-edit-page.vala
index c59f274..40ac70e 100644
--- a/src/client/accounts/add-edit-page.vala
+++ b/src/client/accounts/add-edit-page.vala
@@ -49,7 +49,21 @@ public class AddEditPage : Gtk.Box {
         get { return check_remember_password.active; }
         set { check_remember_password.active = value; }
     }
+
+    public bool use_email_signature {
+        get { return check_use_email_signature.active; }
+        set { check_use_email_signature.active = value;}
+    }
     
+    public string email_signature {
+        owned get {
+            return textview_email_signature.buffer.text;
+        }
+        set {
+            textview_email_signature.buffer.text = value ?? "";
+        }
+    }
+
     public bool save_sent_mail {
         get { return check_save_sent_mail.active; }
         set { check_save_sent_mail.active = value; }
@@ -155,6 +169,11 @@ public class AddEditPage : Gtk.Box {
     private Gtk.ComboBoxText combo_service;
     private Gtk.CheckButton check_remember_password;
     private Gtk.CheckButton check_save_sent_mail;
+
+    // Signature
+    private Gtk.Box composer_container;
+    private Gtk.CheckButton check_use_email_signature;
+    private Gtk.TextView textview_email_signature;
     
     private Gtk.Alignment other_info;
     
@@ -218,9 +237,7 @@ public class AddEditPage : Gtk.Box {
         entry_password = (Gtk.Entry) builder.get_object("entry: password");
         check_remember_password = (Gtk.CheckButton) builder.get_object("check: remember_password");
         check_save_sent_mail = (Gtk.CheckButton) builder.get_object("check: save_sent_mail");
-        
         label_error = (Gtk.Label) builder.get_object("label: error");
-        
         other_info = (Gtk.Alignment) builder.get_object("container: other_info");
         
         // Storage options.
@@ -236,6 +253,11 @@ public class AddEditPage : Gtk.Box {
         combo_storage_length.append("1461", _("4 years back"));
         combo_storage_length.append(".", "."); // Separator
         combo_storage_length.append("-1", _("Everything"));
+
+        // composer options
+        composer_container = (Gtk.Box) builder.get_object("composer container");
+        check_use_email_signature = (Gtk.CheckButton) builder.get_object("check: use_email_signature");
+        textview_email_signature = (Gtk.TextView) builder.get_object("textview: email_signature");        
         
         // IMAP info widgets.
         entry_imap_host = (Gtk.Entry) builder.get_object("entry: imap host");
@@ -293,6 +315,8 @@ public class AddEditPage : Gtk.Box {
         entry_smtp_port.insert_text.connect(on_port_insert_text);
         
         entry_nickname.insert_text.connect(on_nickname_insert_text);
+
+        check_use_email_signature.toggled.connect(() => on_use_signature_changed());
         
         // Reset the "first update" flag when the window is mapped.
         map.connect(() => { first_ui_update = true; });
@@ -323,6 +347,8 @@ public class AddEditPage : Gtk.Box {
             info.default_smtp_server_noauth,
             info.prefetch_period_days,
             info.save_drafts,
+            info.use_email_signature,
+            info.email_signature,
             result);
     }
     
@@ -351,6 +377,8 @@ public class AddEditPage : Gtk.Box {
         bool initial_default_smtp_noauth = false,
         int prefetch_period_days = Geary.AccountInformation.DEFAULT_PREFETCH_PERIOD_DAYS,
         bool initial_save_drafts = true,
+        bool initial_use_email_signature = false,
+        string? initial_email_signature = null,
         Geary.Engine.ValidationResult result = Geary.Engine.ValidationResult.OK) {
         
         // Set defaults
@@ -364,6 +392,8 @@ public class AddEditPage : Gtk.Box {
         set_service_provider((Geary.ServiceProvider) initial_service_provider);
         combo_imap_encryption.active = Encryption.NONE; // Must be default; set to real value below.
         combo_smtp_encryption.active = Encryption.NONE;
+        use_email_signature = initial_use_email_signature;
+        email_signature = initial_email_signature;
         
         // Set defaults for IMAP info
         imap_host = initial_default_imap_host ?? "";
@@ -520,6 +550,15 @@ public class AddEditPage : Gtk.Box {
         }
     }
     
+    private void on_use_signature_changed() {
+        if(check_use_email_signature.active == true) {
+            textview_email_signature.sensitive = true;
+        } else {
+            textview_email_signature.buffer.text = "";
+            textview_email_signature.sensitive = false;
+        }
+    }
+
     private uint16 get_default_smtp_port() {
         switch (combo_smtp_encryption.active) {
             case Encryption.SSL:
@@ -608,6 +647,8 @@ public class AddEditPage : Gtk.Box {
         account_information.default_smtp_server_noauth = smtp_noauth;
         account_information.prefetch_period_days = get_storage_length();
         account_information.save_drafts = save_drafts;
+        account_information.use_email_signature = use_email_signature;
+        account_information.email_signature = email_signature;
         
         if (smtp_noauth)
             account_information.smtp_credentials = null;
@@ -635,6 +676,7 @@ public class AddEditPage : Gtk.Box {
         storage_container.visible = mode == PageMode.EDIT;
         check_save_sent_mail.visible = mode == PageMode.EDIT;
         check_save_drafts.visible = mode == PageMode.EDIT;
+        composer_container.visible = mode == PageMode.EDIT;
         
         if (get_service_provider() == Geary.ServiceProvider.OTHER) {
             // Display all options for custom providers.
diff --git a/src/client/composer/composer-widget.vala b/src/client/composer/composer-widget.vala
index 593335e..c1b07fc 100644
--- a/src/client/composer/composer-widget.vala
+++ b/src/client/composer/composer-widget.vala
@@ -457,6 +457,10 @@ public class ComposerWidget : Gtk.EventBox {
             }
         }
         
+        // only add signature if the option is actually set
+        if (account.information.use_email_signature)
+            add_signature();
+        
         editor = new WebKit.WebView();
         edit_fixer = new WebViewEditFixer(editor);
 
@@ -793,6 +797,38 @@ public class ComposerWidget : Gtk.EventBox {
         set_focus();
     }
     
+    private void add_signature() {
+        string? signature = null;
+        
+        // If use signature is enabled but no contents are on settings then we'll use ~/.signature, if any
+        // otherwise use whatever the user has input in settings dialog
+        if (account.information.use_email_signature && 
Geary.String.is_empty_or_whitespace(account.information.email_signature)) {
+            File signature_file = File.new_for_path(Environment.get_home_dir()).get_child(".signature");
+            if (!signature_file.query_exists())
+                return;
+            
+            try {
+                FileUtils.get_contents(signature_file.get_path(), out signature);
+                if (Geary.String.is_empty_or_whitespace(signature))
+                    return;
+            } catch (Error error) {
+                debug("Error reading signature file %s: %s", signature_file.get_path(), error.message);
+                return;
+            }
+        } else {
+            signature = account.information.email_signature;
+            if(Geary.String.is_empty_or_whitespace(signature))
+                return;
+        }
+        
+        signature = Geary.HTML.escape_markup(signature);
+        
+        if (body_html == null)
+            body_html = Geary.HTML.preserve_whitespace("\n\n" + signature);
+        else
+            body_html = Geary.HTML.preserve_whitespace("\n\n" + signature) + body_html;
+    }
+    
     private bool can_save() {
         return (drafts_folder != null && drafts_folder.get_open_state() == Geary.Folder.OpenState.BOTH
             && !drafts_folder.properties.create_never_returns_id && editor.can_undo()
diff --git a/src/engine/api/geary-account-information.vala b/src/engine/api/geary-account-information.vala
index 9c3155d..793df1b 100644
--- a/src/engine/api/geary-account-information.vala
+++ b/src/engine/api/geary-account-information.vala
@@ -33,6 +33,8 @@ public class Geary.AccountInformation : BaseObject {
     private const string SPAM_FOLDER_KEY = "spam_folder";
     private const string TRASH_FOLDER_KEY = "trash_folder";
     private const string SAVE_DRAFTS_KEY = "save_drafts";
+    private const string USE_EMAIL_SIGNATURE_KEY = "use_email_signature";
+    private const string EMAIL_SIGNATURE_KEY = "email_signature";
     
     //
     // "Retired" keys
@@ -87,6 +89,8 @@ public class Geary.AccountInformation : BaseObject {
     public bool default_smtp_server_starttls { get; set; }
     public bool default_smtp_use_imap_credentials { get; set; }
     public bool default_smtp_server_noauth { get; set; }
+    public bool use_email_signature { get; set; }
+    public string email_signature {get; set; } 
     
     public Geary.FolderPath? drafts_folder_path { get; set; default = null; }
     public Geary.FolderPath? sent_mail_folder_path { get; set; default = null; }
@@ -133,6 +137,8 @@ public class Geary.AccountInformation : BaseObject {
                 DEFAULT_PREFETCH_PERIOD_DAYS);
             save_sent_mail = get_bool_value(key_file, GROUP, SAVE_SENT_MAIL_KEY, true);
             ordinal = get_int_value(key_file, GROUP, ORDINAL_KEY, default_ordinal++);
+            use_email_signature = get_bool_value(key_file, GROUP, USE_EMAIL_SIGNATURE_KEY);
+            email_signature = get_escaped_string(key_file, GROUP, EMAIL_SIGNATURE_KEY);
             
             if (ordinal >= default_ordinal)
                 default_ordinal = ordinal + 1;
@@ -201,6 +207,8 @@ public class Geary.AccountInformation : BaseObject {
         spam_folder_path = from.spam_folder_path;
         trash_folder_path = from.trash_folder_path;
         save_drafts = from.save_drafts;
+        use_email_signature = from.use_email_signature;
+        email_signature = from.email_signature;
     }
     
     /**
@@ -514,6 +522,16 @@ public class Geary.AccountInformation : BaseObject {
         
         return def;
     }
+
+    private string get_escaped_string(KeyFile key_file, string group, string key, string def = "") {
+        try {
+            return key_file.get_string(group, key);
+        } catch (KeyFileError err) {
+            // ignore
+        }
+
+        return def;
+    }
     
     private Gee.List<string> get_string_list_value(KeyFile key_file, string group, string key) {
         try {
@@ -587,6 +605,8 @@ public class Geary.AccountInformation : BaseObject {
         key_file.set_boolean(GROUP, SMTP_REMEMBER_PASSWORD_KEY, smtp_remember_password);
         key_file.set_integer(GROUP, PREFETCH_PERIOD_DAYS_KEY, prefetch_period_days);
         key_file.set_boolean(GROUP, SAVE_SENT_MAIL_KEY, save_sent_mail);
+        key_file.set_boolean(GROUP, USE_EMAIL_SIGNATURE_KEY, use_email_signature);
+        key_file.set_string(GROUP, EMAIL_SIGNATURE_KEY, email_signature);
         
         if (service_provider == ServiceProvider.OTHER) {
             key_file.set_value(GROUP, IMAP_HOST, default_imap_server_host);
diff --git a/ui/login.glade b/ui/login.glade
index a971933..8bc8205 100644
--- a/ui/login.glade
+++ b/ui/login.glade
@@ -1,7 +1,13 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!-- Generated with glade 3.16.1 -->
 <interface>
-  <requires lib="gtk+" version="3.0"/>
+  <requires lib="gtk+" version="3.10"/>
+  <object class="GtkAdjustment" id="adjustment1">
+    <property name="upper">100</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+  <object class="GtkTextBuffer" id="buffer: email_signature"/>
   <object class="GtkBox" id="container">
     <property name="visible">True</property>
     <property name="can_focus">False</property>
@@ -76,7 +82,6 @@
             <property name="invisible_char">•</property>
             <property name="activates_default">True</property>
             <property name="width_chars">0</property>
-            <property name="invisible_char_set">True</property>
             <property name="primary_icon_activatable">False</property>
             <property name="secondary_icon_activatable">False</property>
             <property name="placeholder_text">email example com</property>
@@ -96,7 +101,6 @@
             <property name="visibility">False</property>
             <property name="invisible_char">•</property>
             <property name="activates_default">True</property>
-            <property name="invisible_char_set">True</property>
             <property name="primary_icon_activatable">False</property>
             <property name="secondary_icon_activatable">False</property>
             <property name="placeholder_text" translatable="yes">Password</property>
@@ -205,7 +209,6 @@
             <property name="hexpand">True</property>
             <property name="invisible_char">•</property>
             <property name="activates_default">True</property>
-            <property name="invisible_char_set">True</property>
             <property name="primary_icon_activatable">False</property>
             <property name="secondary_icon_activatable">False</property>
           </object>
@@ -262,7 +265,6 @@
             <property name="max_length">255</property>
             <property name="invisible_char">•</property>
             <property name="activates_default">True</property>
-            <property name="invisible_char_set">True</property>
             <property name="primary_icon_activatable">False</property>
             <property name="secondary_icon_activatable">False</property>
             <property name="placeholder_text" translatable="yes">Work, Home, etc.</property>
@@ -293,21 +295,7 @@
           </packing>
         </child>
         <child>
-          <object class="GtkCheckButton" id="check: save_drafts">
-            <property name="label" translatable="yes">Save dra_fts on server</property>
-            <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="receives_default">False</property>
-            <property name="use_underline">True</property>
-            <property name="xalign">0</property>
-            <property name="draw_indicator">True</property>
-          </object>
-          <packing>
-            <property name="left_attach">1</property>
-            <property name="top_attach">7</property>
-            <property name="width">1</property>
-            <property name="height">1</property>
-          </packing>
+          <placeholder/>
         </child>
         <child>
           <placeholder/>
@@ -433,7 +421,6 @@
                 <property name="can_focus">True</property>
                 <property name="invisible_char">•</property>
                 <property name="activates_default">True</property>
-                <property name="invisible_char_set">True</property>
                 <property name="placeholder_text">smtp.example.com</property>
               </object>
               <packing>
@@ -451,7 +438,6 @@
                 <property name="activates_default">True</property>
                 <property name="width_chars">5</property>
                 <property name="text">587</property>
-                <property name="invisible_char_set">True</property>
               </object>
               <packing>
                 <property name="left_attach">3</property>
@@ -710,8 +696,6 @@
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
                 <property name="active">1</property>
-                <property name="entry_text_column">0</property>
-                <property name="id_column">1</property>
                 <items>
                   <item translatable="yes">None</item>
                   <item translatable="yes">SSL/TLS</item>
@@ -730,8 +714,6 @@
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
                 <property name="active">2</property>
-                <property name="entry_text_column">0</property>
-                <property name="id_column">1</property>
                 <items>
                   <item translatable="yes">None</item>
                   <item translatable="yes">SSL/TLS</item>
@@ -893,9 +875,9 @@
                 <property name="xpad">12</property>
                 <property name="label" translatable="yes">_Download mail</property>
                 <property name="use_underline">True</property>
-            <style>
-              <class name="dim-label"/>
-            </style>
+                <style>
+                  <class name="dim-label"/>
+                </style>
               </object>
               <packing>
                 <property name="left_attach">0</property>
@@ -909,8 +891,6 @@
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
                 <property name="active">0</property>
-                <property name="entry_text_column">0</property>
-                <property name="id_column">1</property>
               </object>
               <packing>
                 <property name="left_attach">1</property>
@@ -933,5 +913,95 @@
         <property name="position">4</property>
       </packing>
     </child>
+    <child>
+      <object class="GtkBox" id="composer container">
+        <property name="can_focus">False</property>
+        <property name="margin_bottom">10</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <object class="GtkLabel" id="label: composer">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="margin_top">8</property>
+            <property name="xalign">0</property>
+            <property name="xpad">4</property>
+            <property name="ypad">6</property>
+            <property name="label" translatable="yes">Composer</property>
+            <attributes>
+              <attribute name="weight" value="bold"/>
+            </attributes>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkCheckButton" id="check: save_drafts">
+            <property name="label" translatable="yes">Save dra_fts on server</property>
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="receives_default">False</property>
+            <property name="margin_left">12</property>
+            <property name="use_underline">True</property>
+            <property name="xalign">0</property>
+            <property name="draw_indicator">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkCheckButton" id="check: use_email_signature">
+            <property name="label" translatable="yes">Si_gn emails:</property>
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="receives_default">False</property>
+            <property name="margin_left">12</property>
+            <property name="use_underline">True</property>
+            <property name="xalign">0</property>
+            <property name="draw_indicator">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkScrolledWindow" id="scrolledwindow2">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="margin_left">12</property>
+            <property name="shadow_type">in</property>
+            <child>
+              <object class="GtkTextView" id="textview: email_signature">
+                <property name="visible">True</property>
+                <property name="sensitive">False</property>
+                <property name="can_focus">True</property>
+                <property name="wrap_mode">word</property>
+                <property name="buffer">buffer: email_signature</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">3</property>
+          </packing>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">4</property>
+      </packing>
+    </child>
   </object>
 </interface>


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