From 42b465f66ba9d4d5080103fd3b185b7b5b306cfa Mon Sep 17 00:00:00 2001 From: Robert Schroll Date: Fri, 22 Jun 2012 15:44:54 -0700 Subject: [PATCH] Let user customize conversation viewer via CSS: Closes #5435 Courtesy Robert Schroll. --- THANKS | 1 + src/client/geary-application.vala | 6 +++- src/client/ui/message-viewer.vala | 56 ++++++++++++++++++++++++++++++- 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/THANKS b/THANKS index b889b977..bfc6afef 100644 --- a/THANKS +++ b/THANKS @@ -5,4 +5,5 @@ Christian Dywan Timo Kluck Charles Lindsay Matthew Pirocchi +Robert Schroll diff --git a/src/client/geary-application.vala b/src/client/geary-application.vala index e9d6996a..e651ff96 100644 --- a/src/client/geary-application.vala +++ b/src/client/geary-application.vala @@ -392,7 +392,11 @@ along with Geary; if not, write to the Free Software Foundation, Inc., } public File get_user_data_directory() { - return File.new_for_path(Environment.get_user_data_dir()).get_child(Environment.get_prgname()); + return File.new_for_path(Environment.get_user_data_dir()).get_child("geary"); + } + + public File get_user_config_directory() { + return File.new_for_path(Environment.get_user_config_dir()).get_child("geary"); } /** diff --git a/src/client/ui/message-viewer.vala b/src/client/ui/message-viewer.vala index 1f783f50..311d3bc3 100644 --- a/src/client/ui/message-viewer.vala +++ b/src/client/ui/message-viewer.vala @@ -14,7 +14,9 @@ public class MessageViewer : WebKit.WebView { | Geary.Email.Field.DATE | Geary.Email.Field.FLAGS | Geary.Email.Field.PREVIEW; - + + public const string USER_CSS = "user-message.css"; + private const int ATTACHMENT_PREVIEW_SIZE = 50; private const string MESSAGE_CONTAINER_ID = "message_container"; private const string SELECTION_COUNTER_ID = "multiple_messages"; @@ -63,6 +65,7 @@ public class MessageViewer : WebKit.WebView { private string? hover_url = null; private Gtk.Menu? context_menu = null; private Gtk.Menu? message_menu = null; + private FileMonitor? user_style_monitor = null; public MessageViewer() { valign = Gtk.Align.START; @@ -104,6 +107,8 @@ public class MessageViewer : WebKit.WebView { debug("Unable to load message-viewer document from files: %s", error.message); } + load_user_style(); + // Grab the HTML container. WebKit.DOM.Element? _container = get_dom_document().get_element_by_id("message_container"); assert(_container != null); @@ -127,6 +132,55 @@ public class MessageViewer : WebKit.WebView { } } + private void load_user_style() { + try { + WebKit.DOM.Document document = get_dom_document(); + WebKit.DOM.Element style_element = document.create_element(STYLE_NAME); + style_element.set_attribute("id", "user_style"); + WebKit.DOM.HTMLHeadElement head_element = document.get_head(); + head_element.append_child(style_element); + + File user_style = GearyApplication.instance.get_user_config_directory().get_child(USER_CSS); + user_style_monitor = user_style.monitor_file(FileMonitorFlags.NONE, null); + user_style_monitor.changed.connect(on_user_style_changed); + + // And call it once to load the initial user style + on_user_style_changed(user_style, null, FileMonitorEvent.CREATED); + } catch (Error error) { + debug("Error setting up user style: %s", error.message); + } + } + + private void on_user_style_changed(File user_style, File? other_file, FileMonitorEvent event_type) { + // Changing a file produces 1 created signal, 3 changes done hints, and 0 changed + if (event_type != FileMonitorEvent.CHANGED && event_type != FileMonitorEvent.CREATED + && event_type != FileMonitorEvent.DELETED) { + return; + } + + debug("Loading new message viewer style from %s...", user_style.get_path()); + + WebKit.DOM.Document document = get_dom_document(); + WebKit.DOM.Element style_element = document.get_element_by_id("user_style"); + ulong n = style_element.child_nodes.length; + try { + for (int i = 0; i < n; i++) + style_element.remove_child(style_element.first_child); + } catch (Error error) { + debug("Error removing old user style: %s", error.message); + } + + try { + DataInputStream data_input_stream = new DataInputStream(user_style.read()); + size_t length; + string user_css = data_input_stream.read_upto("\0", 1, out length); + WebKit.DOM.Text text_node = document.create_text_node(user_css); + style_element.append_child(text_node); + } catch (Error error) { + // Expected if file was deleted. + } + } + private void set_icon_src(string selector, string icon_name) { try { // Load the icon.