diff --git a/CMakeLists.txt b/CMakeLists.txt index 2fae06704..207bf7843 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -100,6 +100,7 @@ set(UI_PACKAGES vala_precompile(FEEDREADER ${FEEDREADER_NAME} src/FavIcon.vala src/FeedReader.vala + src/ArticleTheme.vala src/Widgets/AddPopover.vala src/Widgets/ArticleRow.vala src/Widgets/ArticleView.vala @@ -190,7 +191,7 @@ OPTIONS --header=FeedReader.h --vapi=FeedReader.vapi --enable-experimental - + GENERATE_VAPI FeedReader @@ -234,3 +235,4 @@ install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/org.gnome.FeedReader.appdata.xml install (DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data/application-icons/hicolor DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons) install (CODE "execute_process (COMMAND gtk-update-icon-cache -t ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor)") install (DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data/GrabberConfig DESTINATION ${PKGDATADIR}) +install (DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data/ArticleView DESTINATION ${PKGDATADIR}) diff --git a/data/ArticleView/article.html b/data/ArticleView/article.html deleted file mode 100644 index d8af75dea..000000000 --- a/data/ArticleView/article.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - FeedReader Article - - - - -
-
- $FEED -

$TITLE

- $AUTHOR -
- -
- $HTML -
-
- - - diff --git a/data/ArticleView/default/article.html b/data/ArticleView/default/article.html new file mode 100644 index 000000000..279452910 --- /dev/null +++ b/data/ArticleView/default/article.html @@ -0,0 +1,33 @@ + + + + FeedReader Article View + + + + + + + +
+
+
+
$FEED
+ +
+ $AUTHOR +
+
+ +
+ $HTML +
+ +
+
+ + + + diff --git a/data/ArticleView/default/style.css b/data/ArticleView/default/style.css new file mode 100644 index 000000000..7eb84a5eb --- /dev/null +++ b/data/ArticleView/default/style.css @@ -0,0 +1,67 @@ +html, body { + margin: 0; + padding: 0; + width: auto; +} +a { + text-decoration: none; + color: #000; +} + + +.unselectable { + -webkit-user-select: none; + -webkit-touch-callout: none; + -webkit-user-drag: none; + user-select: none; +} + + +a:hover { + opacity:0.7; +} + +body{ + font-family: Arial, Helvetica, sans-serif; +} +img { + max-width: 100%; + height: auto; + width: auto; +} + +p { + text-align: justify; +} + +#feedreader-container { + background-color: #FFFFFF; + margin: 10px; + padding: 20px; +} +#feedreader-container article header { + font-family: LyonText,Georgia,serif; + margin-bottom: 50px; +} + +#feedreader-container article header #title { + font-size: 3em; + font-weight: 400; + line-height: 1.3em; + margin-bottom: 5px; + margin-top: 0; +} + +#feedreader-container article header #author { + font-size: 1.1em; + font-weight: 400; + line-height: 0.8em; + margin-bottom: 5px; + margin-top: 0; + color: #AFAFAF; +} + + +#feedreader-container article #content { + margin: 5px; +} diff --git a/data/ArticleView/default/theme.json b/data/ArticleView/default/theme.json new file mode 100644 index 000000000..3170578e7 --- /dev/null +++ b/data/ArticleView/default/theme.json @@ -0,0 +1,4 @@ +{ + "name": "Default", + "author": "Bilal Elmoussaoui" +} diff --git a/data/ArticleView/midnight/article.html b/data/ArticleView/midnight/article.html new file mode 100644 index 000000000..279452910 --- /dev/null +++ b/data/ArticleView/midnight/article.html @@ -0,0 +1,33 @@ + + + + FeedReader Article View + + + + + + + +
+
+
+
$FEED
+ +
+ $AUTHOR +
+
+ +
+ $HTML +
+ +
+
+ + + + diff --git a/data/ArticleView/midnight/style.css b/data/ArticleView/midnight/style.css new file mode 100644 index 000000000..a0f0d0af7 --- /dev/null +++ b/data/ArticleView/midnight/style.css @@ -0,0 +1,87 @@ +html, +body { + margin: 0; + padding: 0; + width: auto; +} + +a, +body { + color: #ECECEC; +} + +img { + max-width: 100%; + height: auto; + width: auto; +} + +pre, +code { + background-color: #D7DDE8; + padding: 3px; + color: #2E3440; + font-family: monospace; + display: inline-block; + margin: 3px; +} + +pre { + width: 100%; +} + +.unselectable { + -webkit-user-select: none; + -webkit-touch-callout: none; + -webkit-user-drag: none; + user-select: none; +} + +a { + text-decoration: none; +} + +a:hover { + opacity: 0.7; +} + +body { + font-family: Arial, Helvetica, sans-serif; + background-color: #2E3440; +} + +p { + text-align: justify; +} + +#feedreader-container { + margin: 10px; + padding: 20px; +} + +#feedreader-container article header { + font-family: LyonText, Georgia, serif; + margin-bottom: 50px; +} + +#feedreader-container article header #title { + font-size: 3em; + font-weight: 400; + line-height: 1.3em; + margin-bottom: 5px; + margin-top: 0; +} + +#feedreader-container article header #author { + font-size: 1.1em; + font-weight: 400; + line-height: 0.8em; + margin-bottom: 5px; + margin-top: 0; + color: #AFAFAF; +} + +#feedreader-container article #content { + margin: 5px; +} + diff --git a/data/ArticleView/midnight/theme.json b/data/ArticleView/midnight/theme.json new file mode 100644 index 000000000..bc4e339ad --- /dev/null +++ b/data/ArticleView/midnight/theme.json @@ -0,0 +1,4 @@ +{ + "name": "Midnight", + "author": "Bilal Elmoussaoui" +} diff --git a/data/ArticleView/style.css b/data/ArticleView/style.css deleted file mode 100644 index fcb0199b0..000000000 --- a/data/ArticleView/style.css +++ /dev/null @@ -1,544 +0,0 @@ -/* CSS RESET --------------------------------------------------------------------------------------------------------------------------------------------*/ - -* { - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; -} - - -/* Sensible box-sizing */ - -body, -html, -div, -blockquote, -img, -label, -p, -h1, -h2, -h3, -h4, -h5, -h6, -pre, -ul, -ol, -li, -dl, -dt, -dd, -form, -a, -fieldset, -input, -th, -td, -figure { - margin: 0; - padding: 0; - border: 0; -} - -.unselectable { - -webkit-user-select: none; - -webkit-touch-callout: none; - -webkit-user-drag: none; - user-select: none; -} - -img { - border: 0; - box-sizing: content-box; - height: auto; -} - -ol, -ul { - list-style: disc outside none; - margin-left: 30px; -} - - -/* Style stripping */ - -blockquote:before, -blockquote:after, -q:before, -q:after { - content: ""; -} - -blockquote, -q { - quotes: "" ""; -} - - -/* Blockquotes */ - -.both { - clear: both; -} - -br.both { - clear: both; - display: block; - width: 0px; - height: 0px; - overflow: hidden; -} - - -/* Basic clear styles */ - -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -menu, -nav, -section { - display: block; -} - - -/* HTML5 reset */ - -.cf:after, -.pw:after { - content: ""; - display: table; - clear: both; -} - - -/* Clearfix */ - -div.pw { - width: 90%; - margin: 0 auto; - padding: 5% 0; -} - -body { - cursor: default; - font-weight: normal; - max-width: 50em; - margin: auto; - text-rendering: optimizeLegibility; - margin-top: 1rem; -} - -.tlblue { - background-color: #2295AB; - color: white; -} - -.tlgrey { - background-color: #eee; -} - -h1, -h2, -h3, -h4, -h5, -h6 { - font-weight: 500; - text-align: left; - line-height: 120%; -} - -h1 a, -h2 a, -h3 a, -h4 a, -h5 a, -h6 a { - color: #1d1f1c; -} - -h1 { - margin-top: 2rem; - margin-bottom: 1rem; - font-size: 2rem; - font-weight: normal; -} - -h2 { - margin-top: 2rem; - margin-bottom: 1rem; - font-size: 1.5rem; - font-weight: normal; -} - -h3 { - font-size: 1.25rem; - margin-bottom: 0.5rem; -} - -h4 { - font-size: 1.25rem; - margin-bottom: 0.5rem; - text-transform: uppercase; - font-weight: normal; -} - -h5 { - font-size: 1.2rem; - margin-bottom: 0.25rem; -} - -h6 { - font-size: 1rem; - margin-bottom: 0.25rem; - text-transform: uppercase; -} - -em, -i { - font-style: italic; -} - -strong, -b { - font-weight: 500; -} - -body, -p { - margin-bottom: 1rem; - color: #1d1f1c; - line-height: 1.8em; - text-align: left; -} - -pre, -code { - background-color: #eee; - margin: 0 0 1em; - white-space: pre-wrap; - font-family: monospace, Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, serif; - overflow: auto; - width: auto; -} - -pre { - padding: .5em 1em; -} - -code { - padding: .3em .3em; -} - -p:last-of-type { - margin-bottom: 0; -} - -not(h1) a { - white-space: nowrap; -} - -a :not(img){ - outline:none; - overflow: hidden; -} - -a { - text-overflow: ellipsis; -} - -ins, -a:hover { - text-decoration: none; -} - -strong { - font-weight: 600; -} - -footer, -iframe, -img { - padding: 0.2rem; - border: 1px solid rgba(0, 0, 0, 0.05); - max-width: 100%; - max-height: auto; -} - -.clickable-img-hover { - outline: 2px solid black; - cursor: pointer; -} - -figure { - display: inline-block; - margin: 2rem auto; - margin: 1rem; - border: 1px solid rgba(0, 0, 0, 0.05); -} - -figure p, -figure caption { - font-size: 0.875rem; - color: rgba(0, 0, 0, 0.6); -} - -figure img { - margin: 0 auto; - padding: 0; - border: 0; - max-width: 100%; - max-height: auto; - height: auto; -} - -figure:first-child { - margin-top: 0rem; -} - -header.post { - padding: 1rem 2rem; -} - -div.introtext { - font-weight: 600; -} - -header.post h1 { - font-weight: 600; - margin-top: 0.5rem; - margin-bottom: 0.5rem; -} - -header.post a:link { - outline: none; - text-decoration: none; -} - -header.post span.source { - color: rgba(0, 0, 0, 0.75); - font-size: 0.75rem; -} - -header.post span.author { - color: rgba(0, 0, 0, 0.8); - font-weight: 500; - font-size: 0.75rem; -} - -div.frcontent { - padding: 1rem 2rem; - text-align: justify; - font-size: inherit; -} - -dt { - float: left; - font-weight: bold; - margin-right: 0.5em; -} - -dt:after { - content: ": "; -} - -dd:after { - clear: left; - content: " "; - display: block; -} - -blockquote { - margin-top: 10px; - margin-bottom: 10px; - padding-left: 15px; - margin-left: 15px; - border-left: 3px solid #ccc; -} - -b { - font-weight: bold; -} - -.videoWrapper { - position: relative; - padding-bottom: 56.25%; /* 16:9 */ - padding-top: 25px; - height: 0; -} - -.videoWrapper iframe { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; -} - -/* Themes with no background boxes need less padding */ -body.theme.default header.post, body.theme.parchment header.post, -body.theme.default div.frcontent, body.theme.parchment div.frcontent -{ - padding-top: 0; - padding-bottom: 0; - margin-bottom: 1rem; - margin-top: 1rem; -} - -/* DEFAULT THEME*/ - -body.theme.default { - background: white; -} - -footer, -iframe, -img, -figure { - border: none; -} - -/* MIDNIGHT THEME -- also default dark */ - -body.theme.midnight { - color: rgba(255, 255, 255, 0.6); - background: #233540; -} - -body.theme.midnight pre, -body.theme.midnight pre code, -body.theme.midnight code { - background-color: rgba(255, 255, 255, 0.6); - color: #233540; -} - -body.theme.midnight table, -body.theme.midnight th, -body.theme.midnight td { - border: 1px solid rgba(255, 255, 255, 0.6); -} - -body.theme.midnight div.frcontent th, -body.theme.midnight header.post { - background: rgba(0, 0, 0, 0.1); -} - -body.theme.midnight header.post h1 { - color: #fff; -} - -body.theme.midnight header.post h1 a { - color: #9BA6AC; -} - -body.theme.midnight header.post span.source { - color: #2978a6; -} - -body.theme.midnight header.post span.author { - color: rgba(255, 255, 255, 0.6); -} - -body.theme.midnight div.frcontent { - border: 1px solid rgba(0, 0, 0, 0.1); -} - -body.theme.midnight div.frcontent a { - color: #2978a6; -} - -body.theme.midnight div.frcontent h1, -body.theme.midnight div.frcontent h2, -body.theme.midnight div.frcontent h3, -body.theme.midnight div.frcontent h4 { - color: #2978a6; -} - -body.theme.midnight div.frcontent h2 { - border-color: #2978a6; -} - -body.theme.midnight div.frcontent body, -body.theme.midnight div.frcontent ul, -body.theme.midnight div.frcontent figcaption, -body.theme.midnight div.frcontent h5, -body.theme.midnight div.frcontent h6, -body.theme.midnight div.frcontent p { - color: rgba(255, 255, 255, 0.6); - text-align: justify; -} - -body.theme.spring { - background: #f8fff2; -} - -body.theme.spring header.post { - background: #ccffa6; -} - -body.theme.spring header.post h1 { - color: #405e80; -} - -body.theme.spring header.post span.source { - color: #405e80; -} - -body.theme.spring div.frcontent { - border: 1px solid #ccffa6; -} - -body.theme.spring div.frcontent a { - color: #405e80; -} - -body.theme.spring div.frcontent h1, -body.theme.spring div.frcontent h2, -body.theme.spring div.frcontent h3, -body.theme.spring div.frcontent h4 { - color: #405e80; -} - -body.theme.spring div.frcontent h2 { - border-color: #405e80; -} - -body.theme.parchment { - background: #faf2e1; -} - -body.theme.parchment header.post h1 { - color: #99400f; -} - -body.theme.parchment div.frcontent a { - color: #99400f; -} - -body.theme.parchment div.frcontent h1, -body.theme.parchment div.frcontent h2, -body.theme.parchment div.frcontent h3, -body.theme.parchment div.frcontent h4 { - color: #99400f; -} - -body.theme.parchment div.frcontent h2 { - border-color: #99400f; -} - -body.theme.parchment div.frcontent body, -body.theme.parchment div.frcontent ul, -body.theme.parchment div.frcontent figcaption, -body.theme.parchment div.frcontent h5, -body.theme.parchment div.frcontent h6, -body.theme.parchment div.frcontent p { - color: rgba(0, 0, 0, 0.8); -} diff --git a/data/GrabberConfig b/data/GrabberConfig index 563925676..d7da5aedc 160000 --- a/data/GrabberConfig +++ b/data/GrabberConfig @@ -1 +1 @@ -Subproject commit 563925676d110a51197025aad8ddcac14d18e36a +Subproject commit d7da5aedc2f7d414713d9c975db51ba8b3d2d6b7 diff --git a/data/org.gnome.FeedReader.gresource.xml b/data/org.gnome.FeedReader.gresource.xml index a04066d65..7bbe4a850 100644 --- a/data/org.gnome.FeedReader.gresource.xml +++ b/data/org.gnome.FeedReader.gresource.xml @@ -6,8 +6,8 @@ gtk-css/gtk.css gtk-css/elementary.css - ArticleView/style.css - ArticleView/article.html + ArticleView/default/article.html + ArticleView/default/style.css icons/16x16/actions/feed-add-symbolic.svg icons/16x16/actions/feed-arrow-up-symbolic.svg diff --git a/schemas/org.gnome.feedreader.gschema.xml b/schemas/org.gnome.feedreader.gschema.xml index af069b515..70aa56389 100644 --- a/schemas/org.gnome.feedreader.gschema.xml +++ b/schemas/org.gnome.feedreader.gschema.xml @@ -1,12 +1,4 @@ - - - - - - - - @@ -60,8 +52,8 @@ 'none' - - 'DEFAULT' + + 'default' diff --git a/src/ArticleTheme.vala b/src/ArticleTheme.vala new file mode 100644 index 000000000..80234719a --- /dev/null +++ b/src/ArticleTheme.vala @@ -0,0 +1,103 @@ +// This file is part of FeedReader. +// +// FeedReader is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// FeedReader is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with FeedReader. If not, see . +using Gee; + +public struct ThemeInfo { + string name; + string author; + string path; +} + +public class FeedReader.ArticleTheme { + private static HashMap ? themes = null; + + public static HashMap getThemes(){ + if(themes == null){ + // Local themes + themes = new HashMap (); + string local_dir = GLib.Environment.get_user_data_dir() + "/feedreader/themes/"; + grabThemes(local_dir); + // Global themes + string global_dir = Constants.INSTALL_PREFIX + "/share/FeedReader/ArticleView/"; + grabThemes(global_dir); + } + return themes; + } + + private static ThemeInfo? getTheme (string theme_path) { + var themeInfo = ThemeInfo (); + bool corrupted_theme = false; + try { + string path = Path.build_filename(theme_path, "theme.json"); + Json.Parser parser = new Json.Parser(); + parser.load_from_file(path); + Json.Object obj = parser.get_root().get_object(); + + Value val; + foreach (unowned string node_name in obj.get_members()){ + val = obj.get_member(node_name).get_value(); + switch(node_name) { + case "author": + themeInfo.author = (string) val; + break; + case "name": + themeInfo.name = (string) val; + break; + } + } + themeInfo.path = theme_path; + + } catch(GLib.FileError err){ + Logger.error("[ArticleTheme] A theme must be corrupted: " + theme_path); + corrupted_theme = true; + } catch (GLib.Error err) { + Logger.error("[ArticleTheme] Couldn't parse theme.json: " + theme_path); + corrupted_theme = true; + } + + if (corrupted_theme) + return null; + + return themeInfo; + } + + public static void grabThemes(string location) { + try{ + Dir dir = Dir.open(location, 0); + string ? name = null; + while ((name = dir.read_name()) != null){ + string path = Path.build_filename(location, name); + if(FileUtils.test(path, FileTest.IS_DIR)){ + var themeInfo = getTheme(path); + if(themeInfo != null) + themes.set(name, themeInfo); + } + } + } catch (GLib.FileError err){ + Logger.debug("Couldn't reach the location of themes : " + location); + } + } + + public static bool exists(string theme_location){ + // Check wether a theme exists or not + bool exists = true; + try { + Dir.open(theme_location, 0); + } catch(GLib.FileError err) { + exists = false; + } + return exists; + } +} diff --git a/src/Enums.vala b/src/Enums.vala index d7ca2e945..ef298d4d1 100644 --- a/src/Enums.vala +++ b/src/Enums.vala @@ -146,13 +146,6 @@ namespace FeedReader { DELETE } - public enum ArticleTheme { - DEFAULT, - SPRING, - MIDNIGHT, - PARCHMENT - } - public enum FeedListTheme { GTK, DARK, diff --git a/src/Utils.vala b/src/Utils.vala index 7660bda39..4ca1b994c 100644 --- a/src/Utils.vala +++ b/src/Utils.vala @@ -595,89 +595,32 @@ public class FeedReader.Utils : GLib.Object { public static string buildArticle(string html, string title, string url, string? author, string date, string feedID) { - var article = new GLib.StringBuilder(); - string author_date = ""; - if(author != null) - author_date += _("posted by: %s, ").printf(author); - - author_date += date; + string theme = Settings.general().get_string("article-theme"); + string template = ""; + string css = ""; try { - uint8[] contents; - var file = File.new_for_uri("resource:///org/gnome/FeedReader/ArticleView/article.html"); - file.load_contents(null, out contents, null); - article.assign((string)contents); + if (!ArticleTheme.exists(theme)) { + uint8[] templateContents; + var htmlFile = File.new_for_uri("resource:///org/gnome/FeedReader/ArticleView/default/article.html"); + htmlFile.load_contents(null, out templateContents, null); + template = (string)templateContents; + uint8[] cssContents; + var cssFile = File.new_for_uri("resource:///org/gnome/FeedReader/ArticleView/default/style.css"); + cssFile.load_contents(null, out cssContents, null); + css = (string)cssContents; + } else { + GLib.FileUtils.get_contents(theme + "/article.html", out template); + GLib.FileUtils.get_contents(theme + "/style.css", out css); + } } catch(GLib.Error e) { Logger.error("Utils.buildArticle: %s".printf(e.message)); } - string html_id = "$HTML"; - int html_pos = article.str.index_of(html_id); - article.erase(html_pos, html_id.length); - article.insert(html_pos, html); - - string author_id = "$AUTHOR"; - int author_pos = article.str.index_of(author_id); - article.erase(author_pos, author_id.length); - article.insert(author_pos, author_date); - - string title_id = "$TITLE"; - int title_pos = article.str.index_of(title_id); - article.erase(title_pos, title_id.length); - article.insert(title_pos, title); - - string url_id = "$URL"; - int url_pos = article.str.index_of(url_id); - article.erase(url_pos, url_id.length); - article.insert(url_pos, url); - - string feed_id = "$FEED"; - int feed_pos = article.str.index_of(feed_id); - article.erase(feed_pos, feed_id.length); - article.insert(feed_pos, DataBase.readOnly().read_feed(feedID).getTitle()); - - - string theme = "theme "; - switch(Settings.general().get_enum("article-theme")) - { - case ArticleTheme.DEFAULT: - theme += "default"; - break; - - case ArticleTheme.SPRING: - theme += "spring"; - break; - - case ArticleTheme.MIDNIGHT: - theme += "midnight"; - break; - - case ArticleTheme.PARCHMENT: - theme += "parchment"; - break; - } - - string theme_id = "$THEME"; - int theme_pos = article.str.index_of(theme_id); - article.erase(theme_pos, theme_id.length); - article.insert(theme_pos, theme); - - string select_id = "$UNSELECTABLE"; - int select_pos = article.str.index_of(select_id); - - if(Settings.tweaks().get_boolean("article-select-text")) - { - article.erase(select_pos-1, select_id.length+1); - } - else - { - article.erase(select_pos, select_id.length); - article.insert(select_pos, "unselectable"); - } - + // Calculate the Large and Small font sizes string font = Settings.general().get_string("font"); var desc = Pango.FontDescription.from_string(font); string fontfamilly = desc.get_family(); @@ -686,45 +629,31 @@ public class FeedReader.Utils : GLib.Object { string large_size = (fontsize * 2).to_string(); string normal_size = fontsize.to_string(); - string fontfamily_id = "$FONTFAMILY"; - int fontfamilly_pos = article.str.index_of(fontfamily_id); - article.erase(fontfamilly_pos, fontfamily_id.length); - article.insert(fontfamilly_pos, fontfamilly); - - string fontsize_id = "$FONTSIZE"; - string sourcefontsize_id = "$SMALLSIZE"; - int fontsize_pos = article.str.index_of(fontsize_id); - article.erase(fontsize_pos, fontsize_id.length); - article.insert(fontsize_pos, normal_size); + if (author != null) { + template = template.replace("$AUTHOR", author); + } else { + template = template.replace("$AUTHOR", _("Unknown")); + } + template = template.replace("$HTML", html); + template = template.replace("$DATE", date); + template = template.replace("$TITLE", title); + template = template.replace("$URL", url); + template = template.replace("$FEED", DataBase.readOnly().read_feed(feedID).getTitle()); + template = template.replace("$FONTFAMILY", fontfamilly); + template = template.replace("$SMALLSIZE", normal_size); + template = template.replace("$LARGESIZE", large_size); + template = template.replace("$FONTSIZE", small_size); + template = template.replace("$CSS", css); - string largesize_id = "$LARGESIZE"; - int largesize_pos = article.str.index_of(largesize_id); - article.erase(largesize_pos, largesize_id.length); - article.insert(largesize_pos, large_size); - - for(int i = article.str.index_of(sourcefontsize_id, 0); i != -1; i = article.str.index_of(sourcefontsize_id, i)) - { - article.erase(i, sourcefontsize_id.length); - article.insert(i, small_size); - } - - - try + if(Settings.tweaks().get_boolean("article-select-text")) { - uint8[] contents; - var file = File.new_for_uri("resource:///org/gnome/FeedReader/ArticleView/style.css"); - file.load_contents(null, out contents, null); - string css_id = "$CSS"; - int css_pos = article.str.index_of(css_id); - article.erase(css_pos, css_id.length); - article.insert(css_pos, (string)contents); + template = template.replace("$UNSELECTABLE", ""); } - catch(GLib.Error e) + else { - Logger.error("Utils.buildArticle: load CSS: " + e.message); + template = template.replace("$UNSELECTABLE", "unselectable"); } - - return article.str; + return template; } public static bool canManipulateContent(bool? online = null) @@ -939,4 +868,5 @@ public class FeedReader.Utils : GLib.Object { Logger.debug(@"getRelevantArticles: $count"); return count; } + } diff --git a/src/Widgets/Setting.vala b/src/Widgets/Setting.vala index fd0291759..9b87f61da 100644 --- a/src/Widgets/Setting.vala +++ b/src/Widgets/Setting.vala @@ -12,6 +12,7 @@ // // You should have received a copy of the GNU General Public License // along with FeedReader. If not, see . +using Gee; public class FeedReader.Setting : Gtk.Box { @@ -53,6 +54,55 @@ public class FeedReader.SettingFont : FeedReader.Setting { } +public class FeedReader.ArticleThemeSetting : FeedReader.Setting { + + public ArticleThemeSetting (string name, GLib.Settings settings, string key, HashMap ? themes = null, string ? tooltip = null){ + base (name, tooltip); + if (themes != null) { + var liststore = new Gtk.ListStore(2, typeof(string), typeof(string)); + int active = 0; + bool was_found = false; + string current_theme = settings.get_string(key); + + foreach(ThemeInfo theme in themes.values) { + Gtk.TreeIter iter; + + if (current_theme == theme.path){ + was_found = true; + } + liststore.append(out iter); + liststore.set(iter, 0, theme.name); + liststore.set(iter, 1, theme.path); + if(!was_found){ + active += 1; + } + } + + var dropbox = new Gtk.ComboBox.with_model(liststore); + var renderer = new Gtk.CellRendererText(); + dropbox.pack_start(renderer, false); + dropbox.add_attribute(renderer, "text", 0); + dropbox.set_active(active); + dropbox.changed.connect(() => { + Value selected_theme; + Gtk.TreeIter iter; + dropbox.get_active_iter(out iter); + liststore.get_value(iter, 1, out selected_theme); + settings.set_string(key, (string)selected_theme); + changed(); + }); + + this.pack_end(dropbox, false, false, 0); + } else { + var theme_label = new Gtk.Label(_("Default")); + + this.pack_end(theme_label, false, false, 0); + } + } + +} + + public class FeedReader.SettingDropbox : FeedReader.Setting { public SettingDropbox(string name, GLib.Settings settings, string key, string[] values, string? tooltip = null) diff --git a/src/Widgets/SettingsDialog.vala b/src/Widgets/SettingsDialog.vala index c2a044c9f..c043446b9 100644 --- a/src/Widgets/SettingsDialog.vala +++ b/src/Widgets/SettingsDialog.vala @@ -108,7 +108,7 @@ public class FeedReader.SettingsDialog : Gtk.Dialog { var articleview_settings = headline(_("Article View:")); - var article_theme = new SettingDropbox(_("Theme"), Settings.general(), "article-theme", {_("Default"), _("Spring"), _("Midnight"), _("Parchment")}); + var article_theme = new ArticleThemeSetting(_("Theme"), Settings.general(), "article-theme", ArticleTheme.getThemes()); article_theme.changed.connect(() => { ColumnView.get_default().reloadArticleView(); });