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
-
-
-
-
-
-
-
-
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();
});