Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/jangernert/FeedReader.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBrendan Long <self@brendanlong.com>2019-02-20 22:21:14 +0300
committerBrendan Long <self@brendanlong.com>2019-02-20 22:21:38 +0300
commit6905f466acb4b0fefd7f6269940202ff389a52dc (patch)
tree65e0fa120dca3e45a5ba897876589883315c3997 /src
parentc177d26d40562ea1a4659429180a8a262156bf64 (diff)
Remove indented empty lines
Diffstat (limited to 'src')
-rw-r--r--src/ActionCache.vala62
-rw-r--r--src/Backend/Backend.vala252
-rw-r--r--src/Backend/FeedServer.vala426
-rw-r--r--src/Backend/FeedServerInterface.vala118
-rw-r--r--src/Backend/OPMLparser.vala48
-rw-r--r--src/CachedActionManager.vala50
-rw-r--r--src/ContentGrabber/grabber.vala188
-rw-r--r--src/ContentGrabber/grabberConfig.vala74
-rw-r--r--src/ContentGrabber/grabberUtils.vala228
-rw-r--r--src/ContentGrabber/stringPair.vala6
-rw-r--r--src/DataBaseReadOnly.vala294
-rw-r--r--src/DataBaseWriteAccess.vala272
-rw-r--r--src/Enums.vala66
-rw-r--r--src/FavIcon.vala112
-rw-r--r--src/FeedReader.vala92
-rw-r--r--src/FeedReaderMain.vala30
-rw-r--r--src/Logger.vala14
-rw-r--r--src/Model/Article.vala88
-rw-r--r--src/Model/CachedAction.vala22
-rw-r--r--src/Model/Category.vala20
-rw-r--r--src/Model/Enclosure.vala8
-rw-r--r--src/Model/Feed.vala46
-rw-r--r--src/Model/InterfaceState.vala68
-rw-r--r--src/Model/ShareAccount.vala16
-rw-r--r--src/Model/Tag.vala14
-rw-r--r--src/Notification.vala12
-rw-r--r--src/Password.vala38
-rw-r--r--src/QueryBuilder.vala76
-rw-r--r--src/Rfc822.vala18
-rw-r--r--src/SQLite.vala24
-rw-r--r--src/Settings.vala26
-rw-r--r--src/Share/ServiceSetup.vala66
-rw-r--r--src/Share/ShareAccountInterface.vala32
-rw-r--r--src/Share/share.vala94
-rw-r--r--src/StringUtils.vala12
-rw-r--r--src/Structs.vala28
-rw-r--r--src/TestQueryBuilder.vala30
-rw-r--r--src/TestStringUtils.vala26
-rw-r--r--src/Utils.vala154
-rw-r--r--src/Widgets/AddPopover.vala48
-rw-r--r--src/Widgets/ArticleList/ArticleList.vala188
-rw-r--r--src/Widgets/ArticleList/ArticleListBox.vala202
-rw-r--r--src/Widgets/ArticleList/ArticleListEmptyLabel.vala8
-rw-r--r--src/Widgets/ArticleList/ArticleListScroll.vala88
-rw-r--r--src/Widgets/ArticleRow.vala202
-rw-r--r--src/Widgets/ArticleView.vala284
-rw-r--r--src/Widgets/ArticleViewHeader.vala50
-rw-r--r--src/Widgets/ArticleViewLoadProgress.vala18
-rw-r--r--src/Widgets/ArticleViewUrlOverlay.vala12
-rw-r--r--src/Widgets/BackendInfoPopover.vala62
-rw-r--r--src/Widgets/CategorieRow.vala224
-rw-r--r--src/Widgets/ColorCircle.vala38
-rw-r--r--src/Widgets/ColorPopover.vala8
-rw-r--r--src/Widgets/ColumnView.vala174
-rw-r--r--src/Widgets/ColumnViewHeader.vala72
-rw-r--r--src/Widgets/FeedList.vala202
-rw-r--r--src/Widgets/FeedListFooter.vala26
-rw-r--r--src/Widgets/FeedRow.vala136
-rw-r--r--src/Widgets/FullscreenButton.vala12
-rw-r--r--src/Widgets/FullscreenHeader.vala28
-rw-r--r--src/Widgets/HoverButton.vala40
-rw-r--r--src/Widgets/ImagePopup.vala96
-rw-r--r--src/Widgets/InAppNotification.vala18
-rw-r--r--src/Widgets/InfoBar.vala16
-rw-r--r--src/Widgets/LoginPage.vala58
-rw-r--r--src/Widgets/LoginRow.vala30
-rw-r--r--src/Widgets/MainWindow.vala184
-rw-r--r--src/Widgets/MediaButton.vala18
-rw-r--r--src/Widgets/MediaPlayer.vala120
-rw-r--r--src/Widgets/MediaRow.vala22
-rw-r--r--src/Widgets/ModeButton.vala84
-rw-r--r--src/Widgets/RemovePopover.vala34
-rw-r--r--src/Widgets/ResetPage.vala42
-rw-r--r--src/Widgets/ServiceInfo.vala20
-rw-r--r--src/Widgets/ServiceSettingsPopover.vala30
-rw-r--r--src/Widgets/Setting.vala46
-rw-r--r--src/Widgets/SettingsDialog.vala138
-rw-r--r--src/Widgets/SharePopover.vala44
-rw-r--r--src/Widgets/ShareRow.vala14
-rw-r--r--src/Widgets/ShortcutsWindow.vala32
-rw-r--r--src/Widgets/SimpleHeader.vala10
-rw-r--r--src/Widgets/SpringCleanPage.vala12
-rw-r--r--src/Widgets/TagPopover.vala68
-rw-r--r--src/Widgets/TagPopoverRow.vala22
-rw-r--r--src/Widgets/TagRow.vala90
-rw-r--r--src/Widgets/UpdateButton.vala32
-rw-r--r--src/Widgets/WebLoginPage.vala22
87 files changed, 3337 insertions, 3337 deletions
diff --git a/src/ActionCache.vala b/src/ActionCache.vala
index 4bcdd270..4ea0b43c 100644
--- a/src/ActionCache.vala
+++ b/src/ActionCache.vala
@@ -14,33 +14,33 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.ActionCache : GLib.Object {
-
+
// Similar to CachedActionManager this class collects all the actions done during a period of time
// to use that information at a later point of time
// however this class does not write the actions to the database
// this class is used cache the actions during a sync so the synced data can be updated accordingly afterwards
// this prevents articles that were marked as read after the sync began but before the data was written to the database
// to suddenly become unread again after the sync (and similar issues)
-
+
private Gee.List<CachedAction> m_list;
-
+
private static ActionCache? m_cache = null;
-
+
public static ActionCache get_default()
{
if(m_cache == null)
{
m_cache = new ActionCache();
}
-
+
return m_cache;
}
-
+
private ActionCache()
{
m_list = new Gee.ArrayList<CachedAction>();
}
-
+
public void markArticleRead(string id, ArticleStatus read)
{
var cachedAction = CachedActions.MARK_READ;
@@ -48,11 +48,11 @@ public class FeedReader.ActionCache : GLib.Object {
{
cachedAction = CachedActions.MARK_UNREAD;
}
-
+
var action = new CachedAction(cachedAction, id, "");
addAction(action);
}
-
+
public void markArticleStarred(string id, ArticleStatus marked)
{
var cachedAction = CachedActions.MARK_STARRED;
@@ -60,29 +60,29 @@ public class FeedReader.ActionCache : GLib.Object {
{
cachedAction = CachedActions.MARK_UNSTARRED;
}
-
+
var action = new CachedAction(cachedAction, id, "");
addAction(action);
}
-
+
public void markFeedRead(string id)
{
var action = new CachedAction(CachedActions.MARK_READ_FEED, id, "");
addAction(action);
}
-
+
public void markCategoryRead(string id)
{
var action = new CachedAction(CachedActions.MARK_READ_CATEGORY, id, "");
addAction(action);
}
-
+
public void markAllRead()
{
var action = new CachedAction(CachedActions.MARK_READ_ALL, "", "");
addAction(action);
}
-
+
private void addAction(CachedAction action)
{
switch(action.getType())
@@ -93,23 +93,23 @@ public class FeedReader.ActionCache : GLib.Object {
case CachedActions.MARK_UNSTARRED:
removeOpposite(action);
break;
-
+
case CachedActions.MARK_READ_FEED:
removeForFeed(action.getID());
break;
-
+
case CachedActions.MARK_READ_CATEGORY:
removeForCategory(action.getID());
break;
-
+
case CachedActions.MARK_READ_ALL:
removeForALL();
break;
}
-
+
m_list.add(action);
}
-
+
private void removeOpposite(CachedAction action)
{
foreach(CachedAction a in m_list)
@@ -122,7 +122,7 @@ public class FeedReader.ActionCache : GLib.Object {
}
}
}
-
+
private void removeForFeed(string feedID)
{
DataBaseReadOnly db = null;
@@ -142,7 +142,7 @@ public class FeedReader.ActionCache : GLib.Object {
}
}
}
-
+
private void removeForCategory(string catID)
{
var feedIDs = DataBase.readOnly().getFeedIDofCategorie(catID);
@@ -156,11 +156,11 @@ public class FeedReader.ActionCache : GLib.Object {
m_list.remove(a);
}
}
-
+
removeForFeed(feedID);
}
}
-
+
private void removeForALL()
{
foreach(CachedAction a in m_list)
@@ -177,7 +177,7 @@ public class FeedReader.ActionCache : GLib.Object {
}
}
}
-
+
public ArticleStatus checkStarred(string articleID, ArticleStatus marked)
{
var type = CachedActions.NONE;
@@ -189,7 +189,7 @@ public class FeedReader.ActionCache : GLib.Object {
{
type = CachedActions.MARK_UNSTARRED;
}
-
+
foreach(CachedAction a in m_list)
{
if(a.getType() == type
@@ -199,17 +199,17 @@ public class FeedReader.ActionCache : GLib.Object {
{
return ArticleStatus.MARKED;
}
-
+
if(type == CachedActions.MARK_UNSTARRED)
{
return ArticleStatus.UNMARKED;
}
}
}
-
+
return marked;
}
-
+
public ArticleStatus checkRead(Article a)
{
if(a.getUnread() == ArticleStatus.READ)
@@ -232,14 +232,14 @@ public class FeedReader.ActionCache : GLib.Object {
{
case CachedActions.MARK_READ_ALL:
return ArticleStatus.READ;
-
+
case CachedActions.MARK_READ_FEED:
if(action.getID() == a.getFeedID())
{
return ArticleStatus.READ;
}
break;
-
+
case CachedActions.MARK_READ_CATEGORY:
if (db == null)
{
@@ -257,7 +257,7 @@ public class FeedReader.ActionCache : GLib.Object {
}
}
}
-
+
return a.getUnread();
}
}
diff --git a/src/Backend/Backend.vala b/src/Backend/Backend.vala
index cb9c6b82..578aae0c 100644
--- a/src/Backend/Backend.vala
+++ b/src/Backend/Backend.vala
@@ -14,9 +14,9 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
namespace FeedReader {
-
+
public class FeedReaderBackend : GLib.Object {
-
+
#if LIBUNITY
private Unity.LauncherEntry m_launcher;
#endif
@@ -27,7 +27,7 @@ namespace FeedReader {
private uint m_timeout_source_id = 0;
private Mutex m_sync_lock;
private delegate void asyncPayload();
-
+
public signal void syncStarted();
public signal void syncFinished();
public signal void springCleanStarted();
@@ -42,24 +42,24 @@ namespace FeedReader {
public signal void opmlImported();
public signal void updateSyncProgress(string progress);
public signal void tryLogin();
-
+
private static FeedReaderBackend? m_backend;
-
+
public static FeedReaderBackend get_default()
{
if(m_backend == null)
{
m_backend = new FeedReaderBackend();
}
-
+
return m_backend;
}
-
+
private FeedReaderBackend()
{
Logger.debug("backend: constructor");
var plugID = Settings.general().get_string("plugin");
-
+
if(plugID == "none")
{
m_loggedin = LoginResponse.NO_BACKEND;
@@ -68,14 +68,14 @@ namespace FeedReader {
{
login(plugID);
}
-
+
#if LIBUNITY
m_launcher = Unity.LauncherEntry.get_for_desktop_id("org.gnome.FeedReader.desktop");
updateBadge();
#endif
m_cancellable = new GLib.Cancellable();
scheduleSync(Settings.general().get_int("sync"));
-
+
GLib.NetworkMonitor.get_default().network_changed.connect((available) => {
if(available)
{
@@ -86,7 +86,7 @@ namespace FeedReader {
setOffline();
}
});
-
+
this.setOffline.connect(() => {
m_offline = true;
});
@@ -95,7 +95,7 @@ namespace FeedReader {
CachedActionManager.get_default().executeActions();
});
}
-
+
public void startSync(bool initSync = false)
{
m_cancellable.reset();
@@ -104,70 +104,70 @@ namespace FeedReader {
callAsync.end(res);
});
}
-
+
public void cancelSync()
{
Logger.warning("backend: Cancel current sync");
m_cancellable.cancel();
}
-
+
public string getVersion()
{
return AboutInfo.version;
}
-
-
+
+
public bool supportTags()
{
return FeedServer.get_default().supportTags();
}
-
+
public bool supportCategories()
{
return FeedServer.get_default().supportCategories();
}
-
+
public bool supportFeedManipulation()
{
return FeedServer.get_default().supportFeedManipulation();
}
-
+
public bool supportMultiLevelCategories()
{
return FeedServer.get_default().supportMultiLevelCategories();
}
-
+
public string symbolicIcon()
{
Logger.debug("backend: symbolicIcon");
return FeedServer.get_default().symbolicIcon();
}
-
+
public string accountName()
{
return FeedServer.get_default().accountName();
}
-
+
public string getServerURL()
{
return FeedServer.get_default().getServerURL();
}
-
+
public string uncategorizedID()
{
return FeedServer.get_default().uncategorizedID();
}
-
+
public bool hideCategoryWhenEmpty(string catID)
{
return FeedServer.get_default().hideCategoryWhenEmpty(catID);
}
-
+
public bool useMaxArticles()
{
return FeedServer.get_default().useMaxArticles();
}
-
+
public void scheduleSync(int time)
{
if (m_timeout_source_id > 0)
@@ -175,12 +175,12 @@ namespace FeedReader {
GLib.Source.remove(m_timeout_source_id);
m_timeout_source_id = 0;
}
-
+
if(time == 0)
{
return;
}
-
+
m_timeout_source_id = GLib.Timeout.add_seconds_full(GLib.Priority.DEFAULT, time*60, () => {
if(!Settings.state().get_boolean("currently-updating")
&& FeedServer.get_default().pluginLoaded())
@@ -191,7 +191,7 @@ namespace FeedReader {
return true;
});
}
-
+
private void sync(bool initSync = false, GLib.Cancellable? cancellable = null)
{
// Prevent multiple concurrent syncs or spring cleanings
@@ -204,7 +204,7 @@ namespace FeedReader {
Logger.debug("Cant sync because login failed or sync/clean already ongoing");
return;
}
-
+
if(Utils.springCleaningNecessary())
{
Logger.info("backend: spring cleaning");
@@ -212,31 +212,31 @@ namespace FeedReader {
DataBase.writeAccess().springCleaning();
springCleanFinished();
}
-
+
if(cancellable != null && cancellable.is_cancelled())
{
return;
}
-
+
Logger.info("backend: sync started");
syncStarted();
Settings.state().set_boolean("currently-updating", true);
-
+
if(!checkOnline())
{
Logger.info("Cancelling sync because we're not online");
finishSync();
return;
}
-
+
if(cancellable != null && cancellable.is_cancelled())
{
finishSync();
return;
}
-
+
m_cacheSync = true;
-
+
if(initSync && FeedServer.get_default().doInitSync())
{
FeedServer.get_default().InitSyncContent(cancellable);
@@ -245,13 +245,13 @@ namespace FeedReader {
{
FeedServer.get_default().syncContent(cancellable);
}
-
+
if(cancellable != null && cancellable.is_cancelled())
{
finishSync();
return;
}
-
+
updateBadge();
m_cacheSync = false;
FeedServer.get_default().grabContent.begin(cancellable, (obj, res) => {
@@ -264,7 +264,7 @@ namespace FeedReader {
m_sync_lock.unlock();
}
}
-
+
private void finishSync()
{
Settings.state().set_boolean("currently-updating", false);
@@ -272,23 +272,23 @@ namespace FeedReader {
Logger.info("backend: sync finished/cancelled");
syncFinished();
}
-
+
public bool checkOnline()
{
Logger.debug("backend: checkOnline");
-
+
if(GLib.NetworkMonitor.get_default().get_connectivity() != GLib.NetworkConnectivity.FULL)
{
Logger.error("backend: no network available");
}
-
+
if(!FeedServer.get_default().serverAvailable())
{
m_loggedin = LoginResponse.UNKNOWN_ERROR;
setOffline();
return false;
}
-
+
if(m_loggedin != LoginResponse.SUCCESS)
{
FeedServer.get_default().logout();
@@ -299,19 +299,19 @@ namespace FeedReader {
return false;
}
}
-
+
setOnline();
return true;
}
-
-
+
+
public async bool checkOnlineAsync()
{
if(!FeedServer.get_default().pluginLoaded())
{
return false;
}
-
+
Logger.debug("backend: checkOnlineAsync");
bool online = false;
SourceFunc callback = checkOnlineAsync.callback;
@@ -320,27 +320,27 @@ namespace FeedReader {
online = checkOnline();
return null;
};
-
+
new Thread<void*>("checkOnlineAsync", run);
yield;
return online;
}
-
+
public LoginResponse login(string plugName)
{
Logger.debug("backend: new FeedServer and login");
-
+
FeedServer.get_default().setActivePlugin(plugName);
-
+
if(!FeedServer.get_default().pluginLoaded())
{
Logger.error(@"backend: no active plugin");
m_loggedin = LoginResponse.NO_BACKEND;
return m_loggedin;
}
-
+
m_loggedin = FeedServer.get_default().login();
-
+
if(m_loggedin == LoginResponse.SUCCESS)
{
Settings.general().set_string("plugin", plugName);
@@ -354,27 +354,27 @@ namespace FeedReader {
{
setOffline();
}
-
-
+
+
Logger.debug("backend: login status = " + m_loggedin.to_string());
return m_loggedin;
}
-
+
public LoginResponse isLoggedIn()
{
return m_loggedin;
}
-
+
public bool isOnline()
{
if(m_loggedin != LoginResponse.SUCCESS)
{
return false;
}
-
+
return true;
}
-
+
public void updateArticleRead(Article article)
{
if(m_offline)
@@ -387,11 +387,11 @@ namespace FeedReader {
{
ActionCache.get_default().markArticleRead(article.getArticleID(), article.getUnread());
}
-
+
asyncPayload pl = () => { FeedServer.get_default().setArticleIsRead(article.getArticleID(), article.getUnread()); };
callAsync.begin((owned)pl, (obj, res) => { callAsync.end(res); });
}
-
+
asyncPayload pl = () => { DataBase.writeAccess().update_article(article); };
callAsync.begin((owned)pl, (obj, res) => {
callAsync.end(res);
@@ -399,7 +399,7 @@ namespace FeedReader {
updateBadge();
});
}
-
+
public void updateArticleMarked(Article article)
{
if(m_offline)
@@ -415,65 +415,65 @@ namespace FeedReader {
asyncPayload pl = () => { FeedServer.get_default().setArticleIsMarked(article.getArticleID(), article.getMarked()); };
callAsync.begin((owned)pl, (obj, res) => { callAsync.end(res); });
}
-
-
+
+
asyncPayload pl = () => { DataBase.writeAccess().update_article(article); };
callAsync.begin((owned)pl, (obj, res) => {
callAsync.end(res);
refreshFeedListCounter();
});
}
-
-
+
+
public Tag? createTag(string caption)
{
if(m_offline)
{
return null;
}
-
+
string tagID = FeedServer.get_default().createTag(caption);
var tag = new Tag(tagID, caption, 0);
DataBase.writeAccess().write_tag(tag);
newFeedList();
-
+
return tag;
}
-
+
public void tagArticle(Article article, Tag tag, bool add)
{
if(m_offline)
{
return;
}
-
+
if(add)
{
asyncPayload pl = () => { FeedServer.get_default().tagArticle(article, tag); };
callAsync.begin((owned)pl, (obj, res) => { callAsync.end(res); });
-
+
article.addTag(tag.getTagID());
-
+
}
else
{
Logger.debug("backend: remove tag: " + tag.getTagID() + " from article: " + article.getArticleID());
-
+
asyncPayload pl = () => { FeedServer.get_default().removeArticleTag(article, tag); };
callAsync.begin((owned)pl, (obj, res) => { callAsync.end(res); });
-
+
article.removeTag(tag.getTagID());
}
-
+
var db = DataBase.writeAccess();
db.update_article(article);
-
+
if(!add && !db.tag_still_used(tag))
{
Logger.debug("backend: remove tag completely");
asyncPayload pl2 = () => { FeedServer.get_default().deleteTag(tag.getTagID()); };
callAsync.begin((owned)pl2, (obj, res) => { callAsync.end(res); });
-
+
asyncPayload pl3 = () => { db.dropTag(tag); };
callAsync.begin((owned)pl3, (obj, res) => {
callAsync.end(res);
@@ -481,62 +481,62 @@ namespace FeedReader {
});
}
}
-
+
public Tag renameTag(Tag tag, string newName)
{
if(m_offline)
{
return tag;
}
-
+
tag.setTitle(newName);
-
+
asyncPayload pl = () => { FeedServer.get_default().renameTag(tag.getTagID(), newName); };
callAsync.begin((owned)pl, (obj, res) => { callAsync.end(res); });
-
+
asyncPayload pl2 = () => { DataBase.writeAccess().update_tag(tag); };
callAsync.begin((owned)pl2, (obj, res) => {
callAsync.end(res);
newFeedList();
});
-
+
return tag;
}
-
+
public void deleteTag(Tag tag)
{
if(m_offline)
{
return;
}
-
+
asyncPayload pl = () => { FeedServer.get_default().deleteTag(tag.getTagID()); };
callAsync.begin((owned)pl, (obj, res) => { callAsync.end(res); });
-
+
asyncPayload pl2 = () => { DataBase.writeAccess().dropTag(tag); };
callAsync.begin((owned)pl2, (obj, res) => {
callAsync.end(res);
newFeedList();
});
}
-
+
public void updateTagColor(Tag tag)
{
DataBase.writeAccess().update_tag(tag);
}
-
+
public void resetDB()
{
var db = DataBase.writeAccess();
db.resetDB();
db.init();
}
-
+
public void resetAccount()
{
FeedServer.get_default().resetAccount();
}
-
+
public void markFeedAsRead(string feedID, bool isCat)
{
var useID = FeedServer.get_default().alwaysSetReadByID();
@@ -552,7 +552,7 @@ namespace FeedReader {
}
articleIDs = StringUtils.join(articleIDsList, ",");
}
-
+
if(isCat)
{
if(m_offline)
@@ -591,7 +591,7 @@ namespace FeedReader {
};
callAsync.begin((owned)pl, (obj, res) => { callAsync.end(res); });
}
-
+
asyncPayload pl = () => { DataBase.writeAccess().markCategorieRead(feedID); };
callAsync.begin((owned)pl, (obj, res) => {
callAsync.end(res);
@@ -638,7 +638,7 @@ namespace FeedReader {
};
callAsync.begin((owned)pl, (obj, res) => { callAsync.end(res); });
}
-
+
asyncPayload pl = () => { DataBase.writeAccess().markFeedRead(feedID); };
callAsync.begin((owned)pl, (obj, res) => {
callAsync.end(res);
@@ -648,7 +648,7 @@ namespace FeedReader {
});
}
}
-
+
public void markAllItemsRead()
{
var useID = FeedServer.get_default().alwaysSetReadByID();
@@ -663,7 +663,7 @@ namespace FeedReader {
}
articleIDs = StringUtils.join(articleIDsList, ",");
}
-
+
if(m_offline)
{
if(useID)
@@ -700,7 +700,7 @@ namespace FeedReader {
};
callAsync.begin((owned)pl, (obj, res) => { callAsync.end(res); });
}
-
+
asyncPayload pl = () => { DataBase.writeAccess().markAllRead(); };
callAsync.begin((owned)pl, (obj, res) => {
callAsync.end(res);
@@ -709,7 +709,7 @@ namespace FeedReader {
updateArticleList();
});
}
-
+
public void removeCategory(string catID)
{
var db = DataBase.writeAccess();
@@ -721,7 +721,7 @@ namespace FeedReader {
moveFeed(feed.getFeedID(), catID);
}
}
-
+
var cats = db.read_categories(feeds);
foreach(var cat in cats)
{
@@ -730,34 +730,34 @@ namespace FeedReader {
moveCategory(cat.getCatID(), uncategorizedID());
}
}
-
+
asyncPayload pl = () => { FeedServer.get_default().deleteCategory(catID); };
callAsync.begin((owned)pl, (obj, res) => { callAsync.end(res); });
-
+
asyncPayload pl2 = () => { db.delete_category(catID); };
callAsync.begin((owned)pl2, (obj, res) => {
callAsync.end(res);
newFeedList();
});
}
-
+
public void moveCategory(string catID, string newParentID)
{
asyncPayload pl = () => { FeedServer.get_default().moveCategory(catID, newParentID); };
callAsync.begin((owned)pl, (obj, res) => { callAsync.end(res); });
-
+
asyncPayload pl2 = () => { DataBase.writeAccess().move_category(catID, newParentID); };
callAsync.begin((owned)pl2, (obj, res) => {
callAsync.end(res);
newFeedList();
});
}
-
+
public string addCategory(string title, string? parentID = null, bool createLocally = false)
{
Logger.debug("backend: addCategory " + title);
string catID = FeedServer.get_default().createCategory(title, parentID);
-
+
if(createLocally)
{
string? parent = parentID;
@@ -772,22 +772,22 @@ namespace FeedReader {
var parentCat = db.read_category(parentID);
level = parentCat.getLevel()+1;
}
-
+
var cat = new Category(catID, title, 0, 99, parent, level);
var list = new Gee.LinkedList<Category>();
list.add(cat);
db.write_categories(list);
}
-
+
return catID;
}
-
+
public void removeCategoryWithChildren(string catID)
{
var db = DataBase.readOnly();
var feeds = db.read_feeds();
deleteFeedsInCategory(catID, feeds);
-
+
var cats = db.read_categories(feeds);
foreach(var cat in cats)
{
@@ -796,10 +796,10 @@ namespace FeedReader {
removeCategoryWithChildren(catID);
}
}
-
+
removeCategory(catID);
}
-
+
private void deleteFeedsInCategory(string catID, Gee.List<Feed> feeds)
{
foreach(Feed feed in feeds)
@@ -810,49 +810,49 @@ namespace FeedReader {
}
}
}
-
+
public void renameCategory(string catID, string newName)
{
asyncPayload pl = () => { FeedServer.get_default().renameCategory(catID, newName); };
callAsync.begin((owned)pl, (obj, res) => { callAsync.end(res); });
-
+
asyncPayload pl2 = () => { DataBase.writeAccess().rename_category(catID, newName); };
callAsync.begin((owned)pl2, (obj, res) => {
callAsync.end(res);
newFeedList();
});
}
-
+
public void renameFeed(string feedID, string newName)
{
asyncPayload pl = () => { FeedServer.get_default().renameFeed(feedID, newName); };
callAsync.begin((owned)pl, (obj, res) => { callAsync.end(res); });
-
+
asyncPayload pl2 = () => { DataBase.writeAccess().rename_feed(feedID, newName); };
callAsync.begin((owned)pl2, (obj, res) => {
callAsync.end(res);
newFeedList();
});
}
-
+
public void moveFeed(string feedID, string currentCatID, string? newCatID = null)
{
asyncPayload pl = () => { FeedServer.get_default().moveFeed(feedID, newCatID, currentCatID); };
callAsync.begin((owned)pl, (obj, res) => { callAsync.end(res); });
-
+
asyncPayload pl2 = () => { DataBase.writeAccess().move_feed(feedID, currentCatID, newCatID); };
callAsync.begin((owned)pl2, (obj, res) => {
callAsync.end(res);
newFeedList();
});
}
-
+
public void addFeed(string feedURL, string cat, bool isID)
{
string? catID = null;
string? newCatName = null;
string? feedID = null;
-
+
if(cat != "")
{
if(isID)
@@ -864,7 +864,7 @@ namespace FeedReader {
newCatName = cat;
}
}
-
+
string errmsg;
bool success = FeedServer.get_default().addFeed(feedURL, catID, newCatName, out feedID, out errmsg);
errmsg = success ? "" : errmsg;
@@ -874,12 +874,12 @@ namespace FeedReader {
startSync();
}
}
-
+
public void removeFeed(string feedID)
{
asyncPayload pl = () => { FeedServer.get_default().removeFeed(feedID); };
callAsync.begin((owned)pl, (obj, res) => { callAsync.end(res); });
-
+
asyncPayload pl2 = () => {
FeedReader.FavIcon.delete_feed(feedID);
DataBase.writeAccess().delete_feed(feedID);
@@ -890,19 +890,19 @@ namespace FeedReader {
updateArticleList();
});
}
-
+
public void removeFeedOnlyFromCat(string feedID, string catID)
{
asyncPayload pl = () => { FeedServer.get_default().removeCatFromFeed(feedID, catID); };
callAsync.begin((owned)pl, (obj, res) => { callAsync.end(res); });
-
+
asyncPayload pl2 = () => { DataBase.writeAccess().removeCatFromFeed(feedID, catID); };
callAsync.begin((owned)pl2, (obj, res) => {
callAsync.end(res);
newFeedList();
});
}
-
+
public void importOPML(string opml)
{
asyncPayload pl = () => { FeedServer.get_default().importOPML(opml); };
@@ -911,7 +911,7 @@ namespace FeedReader {
opmlImported();
});
}
-
+
public void updateBadge()
{
#if LIBUNITY
@@ -931,7 +931,7 @@ namespace FeedReader {
}
#endif
}
-
+
private async void callAsync(owned asyncPayload func)
{
SourceFunc callback = callAsync.callback;
@@ -942,6 +942,6 @@ namespace FeedReader {
});
yield;
}
-
+
}
}
diff --git a/src/Backend/FeedServer.vala b/src/Backend/FeedServer.vala
index 622ff868..2e57f12e 100644
--- a/src/Backend/FeedServer.vala
+++ b/src/Backend/FeedServer.vala
@@ -14,39 +14,39 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.FeedServer : GLib.Object {
-
+
private bool m_pluginLoaded = false;
private Peas.ExtensionSet m_extensions;
private string? m_activeExtension = null;
private FeedServerInterface? m_plugin;
private Peas.Engine m_engine;
-
+
public signal void PluginsChanedEvent();
-
+
private static FeedServer? m_server;
-
-
+
+
public static FeedServer get_default()
{
if(m_server == null)
{
m_server = new FeedServer();
}
-
+
return m_server;
}
-
+
private FeedServer()
{
string pluginPath = Constants.INSTALL_LIBDIR + "/plugins/";
Logger.debug(@"FeedServer: search path for plugins is $pluginPath");
-
+
m_engine = Peas.Engine.get_default();
m_engine.add_search_path(pluginPath, null);
m_engine.enable_loader("python3");
-
+
m_extensions = new Peas.ExtensionSet(m_engine, typeof(FeedServerInterface));
-
+
m_extensions.extension_added.connect((info, extension) => {
Logger.debug("feedserver: plugin loaded %s".printf(info.get_name()));
try
@@ -59,7 +59,7 @@ public class FeedReader.FeedServer : GLib.Object {
{
secrets = Secret.Collection.create_sync(secret_service, "Login", Secret.COLLECTION_DEFAULT, Secret.CollectionCreateFlags.COLLECTION_CREATE_NONE);
}
-
+
var settings_backend = null; // FIXME: Why does SettingsBackend.get_default() crash on Arch Linux?
(extension as FeedServerInterface).init(settings_backend, secrets);
PluginsChanedEvent();
@@ -70,20 +70,20 @@ public class FeedReader.FeedServer : GLib.Object {
Logger.error("FeedServer: " + e.message);
}
});
-
+
m_extensions.extension_removed.connect((info, extension) => {
Logger.debug("feedserver: plugin removed %s".printf(info.get_name()));
PluginsChanedEvent();
});
-
+
m_engine.load_plugin.connect((info) => {
Logger.debug("feedserver: engine load %s".printf(info.get_name()));
});
-
+
m_engine.unload_plugin.connect((info) => {
Logger.debug("feedserver: engine unload %s".printf(info.get_name()));
});
-
+
if(Settings.general().get_string("plugin") == "none")
{
LoadAllPlugins();
@@ -93,7 +93,7 @@ public class FeedReader.FeedServer : GLib.Object {
LoadPlugin(Settings.general().get_string("plugin"));
}
}
-
+
public void LoadAllPlugins()
{
Logger.debug("FeedServer: load all available plugins");
@@ -101,11 +101,11 @@ public class FeedReader.FeedServer : GLib.Object {
{
m_engine.try_load_plugin(plugin);
}
-
+
// have to readd this path, otherwise new icons won't show up
Gtk.IconTheme.get_default().add_resource_path("/org/gnome/FeedReader/icons");
}
-
+
private void LoadPlugin(string pluginID)
{
Logger.debug(@"FeedServer: load plugin $pluginID");
@@ -116,36 +116,36 @@ public class FeedReader.FeedServer : GLib.Object {
LoadAllPlugins();
}
}
-
+
public bool pluginLoaded()
{
return m_pluginLoaded;
}
-
+
public Peas.ExtensionSet getPlugins()
{
return m_extensions;
}
-
+
public bool setActivePlugin(string pluginID)
{
m_pluginLoaded = false;
m_plugin = null;
-
+
var plugin = m_engine.get_plugin_info(pluginID);
-
+
if(plugin == null)
{
Logger.error(@"feedserver: failed to load info for \"$pluginID\"");
return m_pluginLoaded;
}
-
+
Logger.info("Plugin Name: " + plugin.get_name());
Logger.info("Plugin Version: " + plugin.get_version());
Logger.info("Plugin Website: " + plugin.get_website());
Logger.info("Plugin Dir: " + plugin.get_module_dir());
-
-
+
+
m_activeExtension = pluginID;
m_extensions.foreach((extSet, info, ext) => {
var plug = ext as FeedServerInterface;
@@ -157,19 +157,19 @@ public class FeedReader.FeedServer : GLib.Object {
plug.updateArticleList.connect(() => { FeedReaderBackend.get_default().updateArticleList(); });
plug.showArticleListOverlay.connect(() => { FeedReaderBackend.get_default().showArticleListOverlay(); });
plug.writeArticles.connect((articles) => { writeArticles(articles); });
-
+
m_plugin = plug;
m_pluginLoaded = true;
}
});
return m_pluginLoaded;
}
-
+
public FeedServerInterface? getActivePlugin()
{
return m_plugin;
}
-
+
public void syncContent(GLib.Cancellable? cancellable = null)
{
if(!serverAvailable())
@@ -177,62 +177,62 @@ public class FeedReader.FeedServer : GLib.Object {
Logger.debug("FeedServer: can't sync - not logged in or unreachable");
return;
}
-
+
var db = DataBase.writeAccess();
if(syncFeedsAndCategories())
{
var categories = new Gee.LinkedList<Category>();
var feeds = new Gee.LinkedList<Feed>();
var tags = new Gee.LinkedList<Tag>();
-
+
if(cancellable != null && cancellable.is_cancelled())
{
return;
}
-
+
syncProgress(_("Getting feeds and categories"));
-
+
if(!getFeedsAndCats(feeds, categories, tags, cancellable))
{
Logger.error("FeedServer: something went wrong getting categories and feeds");
return;
}
-
+
if(cancellable != null && cancellable.is_cancelled())
{
return;
}
-
+
if(cancellable != null && cancellable.is_cancelled())
{
return;
}
-
+
// write categories
db.reset_exists_flag();
db.write_categories(categories);
db.delete_nonexisting_categories();
-
+
// write feeds
db.reset_subscribed_flag();
db.write_feeds(feeds);
db.delete_articles_without_feed();
db.delete_unsubscribed_feeds();
-
+
// write tags
db.reset_exists_tag();
db.write_tags(tags);
db.update_tags(tags);
db.delete_nonexisting_tags();
-
+
FeedReaderBackend.get_default().newFeedList();
}
-
+
if(cancellable != null && cancellable.is_cancelled())
{
return;
}
-
+
var drop_articles = (DropArticles)Settings.general().get_enum("drop-articles-after");
DateTime? since = drop_articles.to_start_date();
if(!db.isTableEmpty("articles"))
@@ -243,15 +243,15 @@ public class FeedReader.FeedServer : GLib.Object {
since = last_sync;
}
}
-
+
int unread = getUnreadCount();
int max = ArticleSyncCount();
-
-
+
+
syncProgress(_("Getting articles"));
string row_id = db.getMaxID("articles", "rowid");
int before = row_id != null ? int.parse(row_id) : 0;
-
+
if(unread > max && useMaxArticles())
{
getArticles(20, ArticleStatus.MARKED, since, null, false, cancellable);
@@ -261,15 +261,15 @@ public class FeedReader.FeedServer : GLib.Object {
{
getArticles(max, ArticleStatus.ALL, since, null, false, cancellable);
}
-
+
if(cancellable != null && cancellable.is_cancelled())
{
return;
}
-
+
//update fulltext table
db.updateFTS();
-
+
int new_and_unread = db.get_new_unread_count(row_id != null ? int.parse(row_id) : 0);
row_id = db.getMaxID("articles", "rowid");
int after = row_id != null ? int.parse(row_id) : 0;
@@ -278,75 +278,75 @@ public class FeedReader.FeedServer : GLib.Object {
{
Notification.send(newArticles, new_and_unread);
}
-
+
var drop_weeks = drop_articles.to_weeks();
if(drop_weeks != null)
{
db.dropOldArticles(-(int)drop_weeks);
}
-
+
var now = new DateTime.now_local();
Settings.state().set_int("last-sync", (int)now.to_unix());
-
+
db.checkpoint();
FeedReaderBackend.get_default().newFeedList();
return;
}
-
+
public void InitSyncContent(GLib.Cancellable? cancellable = null)
{
Logger.debug("FeedServer: initial sync");
-
+
var db = DataBase.writeAccess();
if(syncFeedsAndCategories())
{
var categories = new Gee.LinkedList<Category>();
var feeds = new Gee.LinkedList<Feed>();
var tags = new Gee.LinkedList<Tag>();
-
+
syncProgress(_("Getting feeds and categories"));
-
+
getFeedsAndCats(feeds, categories, tags, cancellable);
-
+
if(cancellable != null && cancellable.is_cancelled())
{
return;
}
-
+
if(cancellable != null && cancellable.is_cancelled())
{
return;
}
-
+
// write categories
db.write_categories(categories);
-
+
// write feeds
db.write_feeds(feeds);
-
+
// write tags
db.write_tags(tags);
-
+
FeedReaderBackend.get_default().newFeedList();
}
-
+
if(cancellable != null && cancellable.is_cancelled())
{
return;
}
-
+
var drop_articles = (DropArticles)Settings.general().get_enum("drop-articles-after");
DateTime? since = drop_articles.to_start_date();
-
+
// get marked articles
syncProgress(_("Getting starred articles"));
getArticles(Settings.general().get_int("max-articles"), ArticleStatus.MARKED, since, null, false, cancellable);
-
+
if(cancellable != null && cancellable.is_cancelled())
{
return;
}
-
+
// get articles for each tag
syncProgress(_("Getting tagged articles"));
foreach(var tag_item in db.read_tags())
@@ -357,58 +357,58 @@ public class FeedReader.FeedServer : GLib.Object {
return;
}
}
-
+
if(useMaxArticles())
{
//get max-articls amunt like normal sync
getArticles(Settings.general().get_int("max-articles"), ArticleStatus.ALL, since, null, false, cancellable);
}
-
+
if(cancellable != null && cancellable.is_cancelled())
{
return;
}
-
+
// get unread articles
syncProgress(_("Getting unread articles"));
getArticles(getUnreadCount(), ArticleStatus.UNREAD, since, null, false, cancellable);
-
+
if(cancellable != null && cancellable.is_cancelled())
{
return;
}
-
+
//update fulltext table
db.updateFTS();
-
+
Settings.general().reset("content-grabber");
-
+
var now = new DateTime.now_local();
Settings.state().set_int("last-sync", (int)now.to_unix());
-
+
return;
}
-
+
private void writeArticles(Gee.List<Article> articles)
{
if(articles.size > 0)
{
var db = DataBase.writeAccess();
db.update_articles(articles);
-
+
// Reverse the list
var new_articles = new Gee.ArrayList<Article>();
foreach(var article in articles)
{
new_articles.insert(0, article);
}
-
+
db.write_articles(new_articles);
FeedReaderBackend.get_default().refreshFeedListCounter();
FeedReaderBackend.get_default().updateArticleList();
}
}
-
+
public async void grabContent(GLib.Cancellable? cancellable = null)
{
if(!Settings.general().get_boolean("download-images")
@@ -416,7 +416,7 @@ public class FeedReader.FeedServer : GLib.Object {
{
return;
}
-
+
Logger.debug("FeedServer: grabContent");
var db = DataBase.writeAccess();
var articles = db.readUnfetchedArticles();
@@ -424,14 +424,14 @@ public class FeedReader.FeedServer : GLib.Object {
int i = 0;
var new_article_content = new Gee.ArrayList<Article>();
GLib.Mutex mutex = GLib.Mutex();
-
+
if(size > 0)
{
var session = new Soup.Session();
session.user_agent = Constants.USER_AGENT;
session.timeout = 5;
session.ssl_strict = false;
-
+
try
{
var threads = new ThreadPool<Article>.with_owned_data((article) => {
@@ -439,7 +439,7 @@ public class FeedReader.FeedServer : GLib.Object {
{
return;
}
-
+
if(Settings.general().get_boolean("content-grabber"))
{
var grabber = new Grabber(session, article);
@@ -456,13 +456,13 @@ public class FeedReader.FeedServer : GLib.Object {
}
string html = grabber.getArticle();
string xml = "<?xml";
-
+
while(html.has_prefix(xml))
{
int end = html.index_of_char('>');
html = html.slice(end+1, html.length).chug();
}
-
+
article.setHTML(html);
}
else
@@ -474,23 +474,23 @@ public class FeedReader.FeedServer : GLib.Object {
{
downloadImages(session, article, cancellable);
}
-
+
if(cancellable == null || !cancellable.is_cancelled())
{
mutex.lock();
new_article_content.add(article);
mutex.unlock();
}
-
+
++i;
syncProgress(_(@"Grabbing full content: $i / $size"));
}, (int)GLib.get_num_processors(), true);
-
+
foreach(var Article in articles)
{
threads.add(Article);
}
-
+
bool immediate = false; // allow to queue up additional tasks
bool wait = true; // function will block until all tasks are done
ThreadPool.free((owned)threads, immediate, wait);
@@ -499,7 +499,7 @@ public class FeedReader.FeedServer : GLib.Object {
{
Logger.error("FeedServer.grabContent: " + e.message);
}
-
+
foreach(var content in new_article_content)
{
if (cancellable != null && cancellable.is_cancelled())
@@ -508,24 +508,24 @@ public class FeedReader.FeedServer : GLib.Object {
}
db.writeContent(content);
}
-
+
if (cancellable != null && cancellable.is_cancelled())
{
return;
}
-
+
//update fulltext table
db.updateFTS();
}
}
-
+
private void downloadImages(Soup.Session session, Article article, GLib.Cancellable? cancellable = null)
{
if(!Settings.general().get_boolean("download-images"))
{
return;
}
-
+
var html_cntx = new Html.ParserCtxt();
html_cntx.use_options(Html.ParserOption.NOERROR + Html.ParserOption.NOWARNING);
Html.Doc* doc = html_cntx.read_doc(article.getHTML(), "");
@@ -543,32 +543,32 @@ public class FeedReader.FeedServer : GLib.Object {
grabberUtils.removeAttributes(doc, "img", "srcset");
grabberUtils.removeAttributes(doc, "img", "sizes");
grabberUtils.addAttributes(doc, "a", "target", "_blank");
-
+
if(cancellable != null && cancellable.is_cancelled())
{
delete doc;
return;
}
-
+
grabberUtils.saveImages(session, doc, article, cancellable);
-
+
string html = "";
doc->dump_memory_enc(out html);
html = grabberUtils.postProcessing(ref html);
article.setHTML(html);
delete doc;
}
-
+
private int ArticleSyncCount()
{
if(!useMaxArticles())
{
return -1;
}
-
+
return Settings.general().get_int("max-articles");
}
-
+
// Only used with command-line
public static void grabArticle(string url)
{
@@ -576,7 +576,7 @@ public class FeedReader.FeedServer : GLib.Object {
session.user_agent = Constants.USER_AGENT;
session.timeout = 5;
session.ssl_strict = false;
-
+
var a = new Article ("",
"",
url,
@@ -587,29 +587,29 @@ public class FeedReader.FeedServer : GLib.Object {
"",
null,
new GLib.DateTime.now_local());
-
+
var grabber = new Grabber(session, a);
if(grabber.process())
{
grabber.print();
-
+
string html = Utils.UTF8fix(grabber.getArticle(), false);
string title = Utils.UTF8fix(grabber.getTitle(), true);
string xml = "<?xml";
-
+
while(html.has_prefix(xml))
{
int end = html.index_of_char('>');
html = html.slice(end+1, html.length).chug();
}
-
+
string path = GLib.Environment.get_user_data_dir() + "/feedreader/debug-article/%s.html".printf(title);
-
+
if(FileUtils.test(path, GLib.FileTest.EXISTS))
{
GLib.FileUtils.remove(path);
}
-
+
try
{
var file = GLib.File.new_for_path(path);
@@ -618,33 +618,33 @@ public class FeedReader.FeedServer : GLib.Object {
{
parent.make_directory_with_parents();
}
-
+
var stream = file.create(FileCreateFlags.REPLACE_DESTINATION);
-
+
stream.write(html.data);
Logger.debug("Grabber: article html written to " + path);
-
+
string output = Utils.UTF8fix(html, true);
-
+
if(output == "" || output == null)
{
Logger.error("could not generate preview text");
return;
}
-
+
output = output.replace("\n"," ");
output = output.replace("_"," ");
-
+
path = GLib.Environment.get_user_data_dir() + "/feedreader/debug-article/%s.txt".printf(title);
-
+
if(FileUtils.test(path, GLib.FileTest.EXISTS))
{
GLib.FileUtils.remove(path);
}
-
+
file = GLib.File.new_for_path(path);
stream = file.create(FileCreateFlags.REPLACE_DESTINATION);
-
+
stream.write(output.data);
Logger.debug("Grabber: preview written to " + path);
}
@@ -658,7 +658,7 @@ public class FeedReader.FeedServer : GLib.Object {
Logger.error("FeedServer.grabArticle: article could not be processed " + url);
}
}
-
+
// Only used with command-line
public static void grabImages(string htmlFile, string url)
{
@@ -666,7 +666,7 @@ public class FeedReader.FeedServer : GLib.Object {
session.user_agent = Constants.USER_AGENT;
session.timeout = 5;
session.ssl_strict = false;
-
+
var html_cntx = new Html.ParserCtxt();
html_cntx.use_options(Html.ParserOption.NOERROR + Html.ParserOption.NOWARNING);
Html.Doc* doc = html_cntx.read_file(htmlFile);
@@ -675,7 +675,7 @@ public class FeedReader.FeedServer : GLib.Object {
Logger.debug("Grabber: parsing failed");
return;
}
-
+
var a = new Article ("",
"",
url,
@@ -686,15 +686,15 @@ public class FeedReader.FeedServer : GLib.Object {
"",
null,
new GLib.DateTime.now_local());
-
-
+
+
grabberUtils.repairURL("//img", "src", doc, url);
grabberUtils.saveImages(session, doc, a);
-
+
string html = "";
doc->dump_memory_enc(out html);
html = html.replace("<h3/>", "<h3></h3>");
-
+
int pos1 = html.index_of("<iframe", 0);
int pos2 = -1;
while(pos1 != -1)
@@ -713,7 +713,7 @@ public class FeedReader.FeedServer : GLib.Object {
pos1 = pos3;
}
}
-
+
try
{
var file = GLib.File.new_for_path(GLib.Environment.get_user_data_dir() + "/debug-article/ArticleLocalImages.html");
@@ -724,132 +724,132 @@ public class FeedReader.FeedServer : GLib.Object {
{
Logger.error("FeedServer.grabImages: %s".printf(e.message));
}
-
+
delete doc;
}
-
+
public bool supportTags()
{
if(!m_pluginLoaded)
{
return false;
}
-
+
return m_plugin.supportTags();
}
-
+
public bool doInitSync()
{
if(!m_pluginLoaded)
{
return false;
}
-
+
return m_plugin.doInitSync();
}
-
+
public string symbolicIcon()
{
Logger.debug("feedserver: symbolicIcon");
-
+
if(!m_pluginLoaded)
{
return "none";
}
-
+
return m_plugin.symbolicIcon();
}
-
+
public string accountName()
{
if(!m_pluginLoaded)
{
return "none";
}
-
+
return m_plugin.accountName();
}
-
+
public string getServerURL()
{
if(!m_pluginLoaded)
{
return "none";
}
-
+
return m_plugin.getServerURL();
}
-
+
public string uncategorizedID()
{
if(!m_pluginLoaded)
{
return "";
}
-
+
return m_plugin.uncategorizedID();
}
-
+
public bool hideCategoryWhenEmpty(string catID)
{
if(!m_pluginLoaded)
{
return false;
}
-
+
return m_plugin.hideCategoryWhenEmpty(catID);
}
-
+
public bool supportCategories()
{
if(!m_pluginLoaded)
{
return false;
}
-
+
return m_plugin.supportCategories();
}
-
+
public bool supportFeedManipulation()
{
if(!m_pluginLoaded)
{
return false;
}
-
+
return m_plugin.supportFeedManipulation();
}
-
+
public bool supportMultiLevelCategories()
{
if(!m_pluginLoaded)
{
return false;
}
-
+
return m_plugin.supportMultiLevelCategories();
}
-
+
public bool supportMultiCategoriesPerFeed()
{
if(!m_pluginLoaded)
{
return false;
}
-
+
return m_plugin.supportMultiCategoriesPerFeed();
}
-
+
public bool syncFeedsAndCategories()
{
if(!m_pluginLoaded)
{
return false;
}
-
+
return m_plugin.syncFeedsAndCategories();
}
-
+
// some backends (inoreader, feedly) have the tag-name as part of the ID
// but for some of them the tagID changes when the name was changed (inoreader)
public bool tagIDaffectedByNameChange()
@@ -858,20 +858,20 @@ public class FeedReader.FeedServer : GLib.Object {
{
return false;
}
-
+
return m_plugin.tagIDaffectedByNameChange();
}
-
+
public void resetAccount()
{
if(!m_pluginLoaded)
{
return;
}
-
+
m_plugin.resetAccount();
}
-
+
// whether or not to use the "max-articles"-setting
public bool useMaxArticles()
{
@@ -879,145 +879,145 @@ public class FeedReader.FeedServer : GLib.Object {
{
return true;
}
-
+
return m_plugin.useMaxArticles();
}
-
+
public LoginResponse login()
{
return m_plugin.login();
}
-
+
public bool logout()
{
if(!m_pluginLoaded)
{
return false;
}
-
+
return m_plugin.logout();
}
-
+
public void setArticleIsRead(string articleIDs, ArticleStatus read)
{
if(!m_pluginLoaded)
{
return;
}
-
+
m_plugin.setArticleIsRead(articleIDs, read);
}
-
+
public void setArticleIsMarked(string articleID, ArticleStatus marked)
{
if(!m_pluginLoaded)
{
return;
}
-
+
m_plugin.setArticleIsMarked(articleID, marked);
}
-
+
public bool alwaysSetReadByID()
{
if(!m_pluginLoaded)
{
return false;
}
-
+
return m_plugin.alwaysSetReadByID();
}
-
+
public void setFeedRead(string feedID)
{
if(!m_pluginLoaded)
{
return;
}
-
+
m_plugin.setFeedRead(feedID);
}
-
+
public void setCategoryRead(string catID)
{
if(!m_pluginLoaded)
{
return;
}
-
+
m_plugin.setCategoryRead(catID);
}
-
+
public void markAllItemsRead()
{
if(!m_pluginLoaded)
{
return;
}
-
+
m_plugin.markAllItemsRead();
}
-
+
public void tagArticle(Article article, Tag tag)
{
if(!m_pluginLoaded)
{
return;
}
-
+
m_plugin.tagArticle(article.getArticleID(), tag.getTagID());
}
-
+
public void removeArticleTag(Article article, Tag tag)
{
if(!m_pluginLoaded)
{
return;
}
-
+
m_plugin.removeArticleTag(article.getArticleID(), tag.getTagID());
}
-
+
public string createTag(string caption)
{
if(!m_pluginLoaded)
{
return "";
}
-
+
return m_plugin.createTag(caption);
}
-
+
public void deleteTag(string tagID)
{
if(!m_pluginLoaded)
{
return;
}
-
+
m_plugin.deleteTag(tagID);
}
-
+
public void renameTag(string tagID, string title)
{
if(!m_pluginLoaded)
{
return;
}
-
+
m_plugin.renameTag(tagID, title);
}
-
+
public bool serverAvailable()
{
if(!m_pluginLoaded)
{
return false;
}
-
+
return m_plugin.serverAvailable();
}
-
+
public bool addFeed(string feedURL, string? catID, string? newCatName, out string? feedID, out string errmsg)
{
if(!m_pluginLoaded)
@@ -1026,12 +1026,12 @@ public class FeedReader.FeedServer : GLib.Object {
errmsg = "Plugin not loaded";
return false;
}
-
+
if(!m_plugin.addFeed(feedURL, catID, newCatName, out feedID, out errmsg))
{
return false;
}
-
+
int maxArticles = ArticleSyncCount();
DateTime? since = ((DropArticles)Settings.general().get_enum("drop-articles-after")).to_start_date();
var sinceStr = since == null ? "(null)" : since.to_string();
@@ -1039,127 +1039,127 @@ public class FeedReader.FeedServer : GLib.Object {
getArticles(maxArticles, ArticleStatus.ALL, since, feedID);
return true;
}
-
+
public void addFeeds(Gee.List<Feed> feeds)
{
if(!m_pluginLoaded)
{
return;
}
-
+
m_plugin.addFeeds(feeds);
}
-
+
public void removeFeed(string feedID)
{
if(!m_pluginLoaded)
{
return;
}
-
+
m_plugin.removeFeed(feedID);
}
-
+
public void renameFeed(string feedID, string title)
{
if(!m_pluginLoaded)
{
return;
}
-
+
m_plugin.renameFeed(feedID, title);
}
-
+
public void moveFeed(string feedID, string newCatID, string? currentCatID = null)
{
if(!m_pluginLoaded)
{
return;
}
-
+
m_plugin.moveFeed(feedID, newCatID, currentCatID);
}
-
+
public string createCategory(string title, string? parentID = null)
{
if(!m_pluginLoaded)
{
return "";
}
-
+
return m_plugin.createCategory(title, parentID);
}
-
+
public void renameCategory(string catID, string title)
{
if(!m_pluginLoaded)
{
return;
}
-
+
m_plugin.renameCategory(catID, title);
}
-
+
public void moveCategory(string catID, string newParentID)
{
if(!m_pluginLoaded)
{
return;
}
-
+
m_plugin.moveCategory(catID, newParentID);
}
-
+
public void deleteCategory(string catID)
{
if(!m_pluginLoaded)
{
return;
}
-
+
m_plugin.deleteCategory(catID);
}
-
+
public void removeCatFromFeed(string feedID, string catID)
{
if(!m_pluginLoaded)
{
return;
}
-
+
m_plugin.removeCatFromFeed(feedID, catID);
}
-
+
public void importOPML(string opml)
{
if(!m_pluginLoaded)
{
return;
}
-
+
m_plugin.importOPML(opml);
}
-
+
public bool getFeedsAndCats(Gee.List<Feed> feeds, Gee.List<Category> categories, Gee.List<Tag> tags, GLib.Cancellable? cancellable = null)
{
if(!m_pluginLoaded)
{
return false;
}
-
+
return m_plugin.getFeedsAndCats(feeds, categories, tags);
}
-
+
public int getUnreadCount()
{
if(!m_pluginLoaded)
{
return 0;
}
-
+
return m_plugin.getUnreadCount();
}
-
+
public void getArticles(int count, ArticleStatus whatToGet = ArticleStatus.ALL, DateTime? since = null, string? feedID = null, bool isTagID = false, GLib.Cancellable? cancellable = null)
{
if(!m_pluginLoaded)
@@ -1167,14 +1167,14 @@ public class FeedReader.FeedServer : GLib.Object {
Logger.error("getArticles() called with no plugin loaded");
return;
}
-
+
m_plugin.getArticles(count, whatToGet, since, feedID, isTagID);
}
-
+
private void syncProgress(string text)
{
FeedReaderBackend.get_default().updateSyncProgress(text);
Settings.state().set_string("sync-status", text);
}
-
+
}
diff --git a/src/Backend/FeedServerInterface.vala b/src/Backend/FeedServerInterface.vala
index 5682bf7e..e17e89ef 100644
--- a/src/Backend/FeedServerInterface.vala
+++ b/src/Backend/FeedServerInterface.vala
@@ -14,81 +14,81 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public abstract class FeedReader.FeedServerInterface : Peas.ExtensionBase {
-
+
public signal void newFeedList();
public signal void refreshFeedListCounter();
public signal void updateArticleList();
public signal void showArticleListOverlay();
public signal void writeArticles(Gee.List<Article> articles);
-
+
public abstract void init(GLib.SettingsBackend? settings_backend, Secret.Collection secrets);
-
+
public abstract bool supportTags();
-
+
public abstract bool doInitSync();
-
+
public abstract string symbolicIcon();
-
+
public abstract string accountName();
-
+
public abstract string getServerURL();
-
+
public abstract string uncategorizedID();
-
+
public abstract bool hideCategoryWhenEmpty(string catID);
-
+
public abstract bool supportCategories();
-
+
public abstract bool supportFeedManipulation();
-
+
public abstract bool supportMultiLevelCategories();
-
+
public abstract bool supportMultiCategoriesPerFeed();
-
+
public abstract bool syncFeedsAndCategories();
-
+
// some backends (inoreader, feedly) have the tag-name as part of the ID
// but for some of them the tagID changes when the name was changed (inoreader)
public abstract bool tagIDaffectedByNameChange();
-
+
public abstract void resetAccount();
-
+
// whether or not to use the "max-articles"-setting
public abstract bool useMaxArticles();
-
+
public abstract LoginResponse login();
-
+
public virtual bool logout()
{
return true;
}
-
+
public abstract bool alwaysSetReadByID();
-
+
public abstract void setArticleIsRead(string articleIDs, ArticleStatus read);
-
+
public abstract void setArticleIsMarked(string articleID, ArticleStatus marked);
-
+
public abstract void setFeedRead(string feedID);
-
+
public abstract void setCategoryRead(string catID);
-
+
public abstract void markAllItemsRead();
-
+
public abstract void tagArticle(string articleID, string tagID);
-
+
public abstract void removeArticleTag(string articleID, string tagID);
-
+
public abstract string createTag(string caption);
-
+
public abstract void deleteTag(string tagID);
-
+
public abstract void renameTag(string tagID, string title);
-
+
public abstract bool serverAvailable();
-
+
public abstract bool addFeed(string feedURL, string? catID, string? newCatName, out string feedID, out string errmsg);
-
+
public virtual void addFeeds(Gee.List<Feed> feeds)
{
string feedID, errmsg;
@@ -98,76 +98,76 @@ public abstract class FeedReader.FeedServerInterface : Peas.ExtensionBase {
addFeed(feed.getXmlUrl(), catString != "" ? catString : null, null, out feedID, out errmsg);
}
}
-
+
public abstract void removeFeed(string feedID);
-
+
public abstract void renameFeed(string feedID, string title);
-
+
public abstract void moveFeed(string feedID, string newCatID, string? currentCatID = null);
-
+
public abstract string createCategory(string title, string? parentID = null);
-
+
public abstract void renameCategory(string catID, string title);
-
+
public abstract void moveCategory(string catID, string newParentID);
-
+
public abstract void deleteCategory(string catID);
-
+
public abstract void removeCatFromFeed(string feedID, string catID);
-
+
public virtual void importOPML(string opml)
{
var parser = new OPMLparser(opml);
var feeds = parser.parse();
addFeeds(feeds);
}
-
+
public abstract bool getFeedsAndCats(Gee.List<Feed> feeds, Gee.List<Category> categories, Gee.List<Tag> tags, GLib.Cancellable? cancellable = null);
-
+
public abstract int getUnreadCount();
-
+
public abstract void getArticles(int count, ArticleStatus whatToGet = ArticleStatus.ALL, DateTime? since = null, string? feedID = null, bool isTagID = false, GLib.Cancellable? cancellable = null);
-
+
// UI stuff
public signal void tryLogin();
-
+
public abstract string getWebsite();
-
+
public abstract BackendFlags getFlags();
-
+
public abstract string getID();
-
+
public virtual Gtk.Box? getWidget()
{
return null;
}
-
+
public abstract string iconName();
-
+
public abstract string serviceName();
-
+
public abstract bool needWebLogin();
-
+
public virtual void showHtAccess()
{
}
-
+
public virtual void writeData()
{
}
-
+
public virtual async void postLoginAction()
{
}
-
+
public virtual bool extractCode(string redirectURL)
{
return false;
}
-
+
public virtual string buildLoginURL()
{
return "";
}
-
+
}
diff --git a/src/Backend/OPMLparser.vala b/src/Backend/OPMLparser.vala
index 734d852d..2f4884dd 100644
--- a/src/Backend/OPMLparser.vala
+++ b/src/Backend/OPMLparser.vala
@@ -14,16 +14,16 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.OPMLparser : GLib.Object {
-
+
private string m_opmlString;
private uint m_level = 0;
private Gee.List<Feed> m_feeds = new Gee.ArrayList<Feed>();
-
+
public OPMLparser(string opml)
{
m_opmlString = opml;
}
-
+
public Gee.List<Feed> parse()
{
if(!m_feeds.is_empty)
@@ -31,22 +31,22 @@ public class FeedReader.OPMLparser : GLib.Object {
Logger.error("OPMLParser is not meant to be re-used!");
m_feeds = new Gee.ArrayList<Feed>();
}
-
+
Xml.Doc* doc = Xml.Parser.read_doc(m_opmlString, null, null, 0);
if(doc == null)
{
Logger.error("OPML: parsing xml failed");
return m_feeds;
}
-
+
Xml.Node* root = doc->get_root_element();
if(root->name != "opml")
{
return m_feeds;
}
-
+
Logger.debug("OPML version: " + root->get_prop("version"));
-
+
for(var node = root->children; node != null; node = node->next)
{
if(node->type == Xml.ElementType.ELEMENT_NODE)
@@ -56,17 +56,17 @@ public class FeedReader.OPMLparser : GLib.Object {
case "head":
parseHead(node);
break;
-
+
case "body":
parseTree(node);
break;
}
}
}
-
+
return m_feeds;
}
-
+
private void parseHead(Xml.Node* root)
{
Logger.debug("Parse OPML head");
@@ -79,11 +79,11 @@ public class FeedReader.OPMLparser : GLib.Object {
case "title":
Logger.debug("Title: " + node->get_content());
break;
-
+
case "dateCreated":
Logger.debug("dateCreated: " + node->get_content());
break;
-
+
case "dateModified":
Logger.debug("dateModified: " + node->get_content());
break;
@@ -91,7 +91,7 @@ public class FeedReader.OPMLparser : GLib.Object {
}
}
}
-
+
private void parseTree(Xml.Node* root, string? catID = null)
{
m_level++;
@@ -115,7 +115,7 @@ public class FeedReader.OPMLparser : GLib.Object {
}
m_level--;
}
-
+
private void parseCat(Xml.Node* node, string? parentCatID = null)
{
string title = "No Title";
@@ -127,12 +127,12 @@ public class FeedReader.OPMLparser : GLib.Object {
{
title = node->get_prop("title");
}
-
+
Logger.debug(space() + "Category: " + title);
string catID = FeedReaderBackend.get_default().addCategory(title, parentCatID, true);
parseTree(node, catID);
}
-
+
private void parseFeed(Xml.Node* node, string? catID = null)
{
if(node->get_prop("type") == "rss" || node->get_prop("type") == "atom")
@@ -147,9 +147,9 @@ public class FeedReader.OPMLparser : GLib.Object {
title = node->get_prop("title");
}
string feedURL = node->get_prop("xmlUrl");
-
+
string website = "";
-
+
if(hasProp(node, "htmlUrl"))
{
website = node->get_prop("htmlUrl");
@@ -159,7 +159,7 @@ public class FeedReader.OPMLparser : GLib.Object {
{
Logger.debug(space() + "Feed: " + title + " feedURL: " + feedURL);
}
-
+
var categories = new Gee.ArrayList<string>();
if(catID == null)
{
@@ -169,21 +169,21 @@ public class FeedReader.OPMLparser : GLib.Object {
{
categories.add(catID);
}
-
+
m_feeds.add(new Feed("", title, website, 0, categories, null, feedURL));
}
}
-
+
private bool hasProp(Xml.Node* node, string prop)
{
if(node->get_prop(prop) != null)
{
return true;
}
-
+
return false;
}
-
+
private string space()
{
string tmp = "";
@@ -191,7 +191,7 @@ public class FeedReader.OPMLparser : GLib.Object {
{
tmp += " ";
}
-
+
return tmp;
}
}
diff --git a/src/CachedActionManager.vala b/src/CachedActionManager.vala
index 128d0f1d..b6ee6743 100644
--- a/src/CachedActionManager.vala
+++ b/src/CachedActionManager.vala
@@ -14,28 +14,28 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.CachedActionManager : GLib.Object {
-
+
private CachedActions m_lastAction = CachedActions.NONE;
private string m_ids = "";
-
+
private static CachedActionManager? m_manager = null;
-
+
public static CachedActionManager get_default()
{
if(m_manager == null)
{
m_manager = new CachedActionManager();
}
-
+
return m_manager;
}
-
+
private CachedActionManager()
{
-
+
}
-
-
+
+
public void markArticleRead(string id, ArticleStatus read)
{
var cachedAction = CachedActions.MARK_READ;
@@ -43,11 +43,11 @@ public class FeedReader.CachedActionManager : GLib.Object {
{
cachedAction = CachedActions.MARK_UNREAD;
}
-
+
var action = new CachedAction(cachedAction, id, "");
addAction(action);
}
-
+
public void markArticleStarred(string id, ArticleStatus marked)
{
var cachedAction = CachedActions.MARK_STARRED;
@@ -55,29 +55,29 @@ public class FeedReader.CachedActionManager : GLib.Object {
{
cachedAction = CachedActions.MARK_UNSTARRED;
}
-
+
var action = new CachedAction(cachedAction, id, "");
addAction(action);
}
-
+
public void markFeedRead(string id)
{
var action = new CachedAction(CachedActions.MARK_READ_FEED, id, "");
addAction(action);
}
-
+
public void markCategoryRead(string id)
{
var action = new CachedAction(CachedActions.MARK_READ_CATEGORY, id, "");
addAction(action);
}
-
+
public void markAllRead()
{
var action = new CachedAction(CachedActions.MARK_READ_ALL, "", "");
addAction(action);
}
-
+
private void addAction(CachedAction action)
{
var db = DataBase.writeAccess();
@@ -90,7 +90,7 @@ public class FeedReader.CachedActionManager : GLib.Object {
db.deleteOppositeCachedAction(action);
}
}
-
+
public void executeActions()
{
var db = DataBase.writeAccess();
@@ -99,12 +99,12 @@ public class FeedReader.CachedActionManager : GLib.Object {
Logger.debug("CachedActionManager - executeActions: no actions to perform");
return;
}
-
-
+
+
Logger.debug("CachedActionManager: executeActions");
-
+
var actions = db.readCachedActions();
-
+
foreach(CachedAction action in actions)
{
Logger.debug("CachedActionManager: executeActions %s %s".printf(action.getID(), action.getType().to_string()));
@@ -140,18 +140,18 @@ public class FeedReader.CachedActionManager : GLib.Object {
FeedServer.get_default().markAllItemsRead();
break;
}
-
+
m_lastAction = action.getType();
}
-
+
if(m_ids != "")
{
execute(m_ids.substring(1), m_lastAction);
}
-
+
db.resetCachedActions();
}
-
+
private void execute(string ids, CachedActions action)
{
Logger.debug("CachedActionManager: execute %s %s".printf(ids, action.to_string()));
@@ -165,5 +165,5 @@ public class FeedReader.CachedActionManager : GLib.Object {
break;
}
}
-
+
}
diff --git a/src/ContentGrabber/grabber.vala b/src/ContentGrabber/grabber.vala
index 8ea5615f..70d7bbfd 100644
--- a/src/ContentGrabber/grabber.vala
+++ b/src/ContentGrabber/grabber.vala
@@ -26,13 +26,13 @@ public class FeedReader.Grabber : GLib.Object {
private Xml.Ns* m_ns;
private bool m_foundSomething;
private bool m_singlePage;
-
-
+
+
public string m_author;
public string m_title;
public string m_date;
public string m_html;
-
+
public Grabber(Soup.Session session, Article article)
{
m_article = article;
@@ -40,24 +40,24 @@ public class FeedReader.Grabber : GLib.Object {
{
m_article.setURL("http:" + m_article.getURL());
}
-
+
m_articleURL = m_article.getURL();
m_firstPage = true;
m_foundSomething = false;
m_singlePage = false;
m_session = session;
}
-
+
~Grabber()
{
delete m_doc;
delete m_ns;
}
-
+
private bool checkConfigFile()
{
string filepath = Constants.INSTALL_PREFIX + "/share/feedreader/GrabberConfig/";
-
+
string hostName = grabberUtils.buildHostName(m_articleURL, false);
string filename = filepath + hostName + ".txt";
if(FileUtils.test(filename, GLib.FileTest.EXISTS))
@@ -66,9 +66,9 @@ public class FeedReader.Grabber : GLib.Object {
Logger.debug("Grabber: using config %s.txt".printf(hostName));
return true;
}
-
+
Logger.debug("Grabber: no config (%s.txt) found for article: %s".printf(hostName, m_articleURL));
-
+
string newHostName = grabberUtils.buildHostName(m_articleURL, true);
if(hostName != newHostName)
{
@@ -80,35 +80,35 @@ public class FeedReader.Grabber : GLib.Object {
return true;
}
}
-
-
+
+
Logger.debug("Grabber: no config (%s.txt) - cutSubdomain - found for article: %s".printf(newHostName, m_articleURL));
return false;
}
-
+
public bool process(GLib.Cancellable? cancellable = null)
{
Logger.debug("Grabber: process article: " + m_articleURL);
-
+
var uri = new Soup.URI(m_articleURL);
if(uri == null)
{
Logger.error("No valid article-url?!?");
return false;
}
-
+
if(!checkContentType())
{
return false;
}
-
+
if(cancellable != null && cancellable.is_cancelled())
{
return false;
}
-
+
bool downloaded = false;
-
+
if(!checkConfigFile())
{
// special treatment for sites like youtube
@@ -120,16 +120,16 @@ public class FeedReader.Grabber : GLib.Object {
int start = m_articleURL.index_of(youtube) + youtube.length;
int end = m_articleURL.index_of("?", start);
string id = m_articleURL.substring(start, (end == -1) ? -1 : end-start);
-
+
m_html = ytHTML.printf(id);
return true;
}
-
+
string oldURL = m_articleURL;
-
+
// download to check if website redirects
downloaded = download();
-
+
// if URL is different now after redirect
if(m_articleURL != oldURL)
{
@@ -145,50 +145,50 @@ public class FeedReader.Grabber : GLib.Object {
return false;
}
}
-
+
if(cancellable != null && cancellable.is_cancelled())
{
return false;
}
-
+
Logger.debug("Grabber: config found");
-
+
if(!downloaded && !download())
{
return false;
}
-
-
+
+
Logger.debug("Grabber: download success");
-
+
prepArticle();
-
+
Logger.debug("Grabber: empty article preped");
-
+
if(!parse(cancellable))
{
return false;
}
-
+
if(!m_foundSomething)
{
Logger.error("Grabber: no body found");
return false;
}
-
+
return true;
}
-
+
private bool checkContentType()
{
Logger.debug("Grabber: check contentType");
var message = new Soup.Message("HEAD", m_articleURL.escape(""));
-
+
if(message == null)
{
return false;
}
-
+
m_session.send_message(message);
var params = new GLib.HashTable<string, string>(null, null);
string? contentType = message.response_headers.get_content_type(out params);
@@ -199,13 +199,13 @@ public class FeedReader.Grabber : GLib.Object {
return true;
}
}
-
+
Logger.debug(@"Grabber: type $contentType");
Logger.debug(@"Grabber: type != text/html so not going to proceed further");
-
+
return false;
}
-
+
private bool download()
{
var msg = new Soup.Message("GET", m_articleURL.escape(""));
@@ -219,39 +219,39 @@ public class FeedReader.Grabber : GLib.Object {
Logger.debug("Grabber: new url is: " + m_articleURL);
}
});
-
+
if(msg == null)
{
return false;
}
-
+
if(Settings.tweaks().get_boolean("do-not-track"))
{
msg.request_headers.append("DNT", "1");
}
-
+
m_session.send_message(msg);
msg.disconnect(handlerID);
-
+
if(msg.response_body == null)
{
Logger.debug("Grabber: download failed - no response");
return false;
}
-
+
if((string)msg.response_body.flatten().data == "")
{
Logger.debug("Grabber: download failed - empty response");
return false;
}
-
+
m_rawHtml = (string)msg.response_body.flatten().data;
if(!m_rawHtml.validate())
{
string needle = "content=\"text/html; charset=";
int start = m_rawHtml.index_of(needle) + needle.length;
string locale = "";
-
+
if(start != -1)
{
int end = m_rawHtml.index_of("\"", start);
@@ -271,7 +271,7 @@ public class FeedReader.Grabber : GLib.Object {
return false;
}
}
-
+
Logger.info(locale);
try
{
@@ -282,15 +282,15 @@ public class FeedReader.Grabber : GLib.Object {
Logger.error("grabber: failed to convert locale - " + e.message);
}
}
-
+
return true;
}
-
+
private bool parse(GLib.Cancellable? cancellable = null)
{
m_nexPageURL = null;
Logger.debug("Grabber: start parsing");
-
+
// replace strings before parsing html
unowned Gee.List<StringPair> replace = m_config.getReplace();
if(replace.size != 0)
@@ -300,9 +300,9 @@ public class FeedReader.Grabber : GLib.Object {
m_rawHtml = m_rawHtml.replace(pair.getString1(), pair.getString2());
}
}
-
+
Logger.debug("Grabber: parse html");
-
+
// parse html
var html_cntx = new Html.ParserCtxt();
html_cntx.use_options(Html.ParserOption.NOERROR + Html.ParserOption.NOWARNING);
@@ -312,17 +312,17 @@ public class FeedReader.Grabber : GLib.Object {
Logger.debug("Grabber: parsing failed");
return false;
}
-
+
Logger.debug("Grabber: html parsed");
-
-
+
+
// get link to next page of article if there are more than one pages
if(m_config.getXPathNextPageURL() != null)
{
Logger.debug("Grabber: grab next page url");
m_nexPageURL = grabberUtils.getURL(doc, m_config.getXPathNextPageURL());
}
-
+
// get link to single-page view if it exists and download that page
if(m_config.getXPathSinglePageURL() != null && m_nexPageURL == null)
{
@@ -341,7 +341,7 @@ public class FeedReader.Grabber : GLib.Object {
doc = html_cntx.read_doc(m_rawHtml, "");
}
}
-
+
// get the title from the html (useful if feed doesn't provide one)
unowned Gee.List<string> title = m_config.getXPathTitle();
if(title.size != 0 && m_firstPage)
@@ -356,13 +356,13 @@ public class FeedReader.Grabber : GLib.Object {
}
}
}
-
+
if(cancellable != null && cancellable.is_cancelled())
{
delete doc;
return false;
}
-
+
// get the author from the html (useful if feed doesn't provide one)
unowned Gee.List<string> author = m_config.getXPathAuthor();
if(author.size != 0)
@@ -377,13 +377,13 @@ public class FeedReader.Grabber : GLib.Object {
}
}
}
-
+
if(cancellable != null && cancellable.is_cancelled())
{
delete doc;
return false;
}
-
+
// get the date from the html (useful if feed doesn't provide one)
unowned Gee.List<string> date = m_config.getXPathDate();
if(date.size != 0)
@@ -398,13 +398,13 @@ public class FeedReader.Grabber : GLib.Object {
}
}
}
-
+
if(cancellable != null && cancellable.is_cancelled())
{
delete doc;
return false;
}
-
+
// strip junk
unowned Gee.List<string> strip = m_config.getXPathStrip();
if(strip.size != 0)
@@ -416,13 +416,13 @@ public class FeedReader.Grabber : GLib.Object {
grabberUtils.stripNode(doc, xpath);
}
}
-
+
if(cancellable != null && cancellable.is_cancelled())
{
delete doc;
return false;
}
-
+
// strip any element whose @id or @class contains this substring
unowned Gee.List<string> _stripIDorClass = m_config.getXPathStripIDorClass();
if(_stripIDorClass.size != 0)
@@ -433,13 +433,13 @@ public class FeedReader.Grabber : GLib.Object {
grabberUtils.stripIDorClass(doc, IDorClass);
}
}
-
+
if(cancellable != null && cancellable.is_cancelled())
{
delete doc;
return false;
}
-
+
//strip any <img> element where @src attribute contains this substring
unowned Gee.List<string> stripImgSrc = m_config.getXPathStripImgSrc();
if(stripImgSrc.size != 0)
@@ -450,13 +450,13 @@ public class FeedReader.Grabber : GLib.Object {
grabberUtils.stripNode(doc, "//img[contains(@src,'%s')]".printf(ImgSrc));
}
}
-
+
if(cancellable != null && cancellable.is_cancelled())
{
delete doc;
return false;
}
-
+
grabberUtils.fixLazyImg(doc, "lazyload", "data-src");
grabberUtils.fixIframeSize(doc, "youtube.com");
grabberUtils.removeAttributes(doc, null, "style");
@@ -464,13 +464,13 @@ public class FeedReader.Grabber : GLib.Object {
grabberUtils.removeAttributes(doc, "img", "srcset");
grabberUtils.removeAttributes(doc, "img", "sizes");
grabberUtils.addAttributes(doc, "a", "target", "_blank");
-
+
if(cancellable != null && cancellable.is_cancelled())
{
delete doc;
return false;
}
-
+
// complete relative source urls of images
Logger.debug("Grabber: complete urls");
grabberUtils.repairURL("//img", "src", doc, m_articleURL);
@@ -478,7 +478,7 @@ public class FeedReader.Grabber : GLib.Object {
grabberUtils.repairURL("//a", "href", doc, m_articleURL);
grabberUtils.repairURL("//object", "data", doc, m_articleURL);
grabberUtils.repairURL("//iframe", "src", doc, m_articleURL);
-
+
// strip elements using Readability.com and Instapaper.com ignore class names
// .entry-unrelated and .instapaper_ignore
// See https://www.readability.com/publishers/guidelines/#view-plainGuidelines
@@ -486,43 +486,43 @@ public class FeedReader.Grabber : GLib.Object {
Logger.debug("Grabber: strip instapaper and readability");
grabberUtils.stripNode(doc,
"//*[contains(concat(' ',normalize-space(@class),' '),' entry-unrelated ') or contains(concat(' ',normalize-space(@class),' '),' instapaper_ignore ')]");
-
+
if(cancellable != null && cancellable.is_cancelled())
{
delete doc;
return false;
}
-
+
// strip elements that contain style="display: none;"
Logger.debug("Grabber: strip invisible elements");
grabberUtils.stripNode(doc, "//*[contains(@style,'display:none')]");
-
+
// strip all scripts
Logger.debug("Grabber: strip all scripts");
grabberUtils.stripNode(doc, "//script");
-
+
// strip <noscript>
Logger.debug("Grabber: strip all <noscript>");
grabberUtils.onlyRemoveNode(doc, "//noscript");
-
+
// strip all comments
Logger.debug("Grabber: strip all comments");
grabberUtils.stripNode(doc, "//comment()");
-
+
// strip all empty url-tags <a/>
Logger.debug("Grabber: strip all empty url-tags");
grabberUtils.stripNode(doc, "//a[not(node())]");
-
+
// strip all external css and fonts
Logger.debug("Grabber: strip all external css and fonts");
grabberUtils.stripNode(doc, "//*[@type='text/css']");
-
+
if(cancellable != null && cancellable.is_cancelled())
{
delete doc;
return false;
}
-
+
// get the content of the article
unowned Gee.List<string> bodyList = m_config.getXPathBody();
if(bodyList.size != 0)
@@ -539,7 +539,7 @@ public class FeedReader.Grabber : GLib.Object {
Logger.info("Failed to find: " + bodyXPath);
}
}
-
+
if(m_foundSomething)
{
Logger.debug("Grabber: body found");
@@ -554,16 +554,16 @@ public class FeedReader.Grabber : GLib.Object {
{
Logger.error("Grabber: config file has no rule for 'body'");
}
-
+
delete doc;
-
+
if(cancellable != null && cancellable.is_cancelled())
{
return false;
}
-
+
m_firstPage = false;
-
+
if(m_nexPageURL != null && !m_singlePage)
{
Logger.debug("Grabber: load next page");
@@ -580,22 +580,22 @@ public class FeedReader.Grabber : GLib.Object {
return true;
}
}
-
+
if(Settings.general().get_boolean("download-images"))
{
grabberUtils.saveImages(m_session, m_doc, m_article, cancellable);
}
-
+
if(cancellable != null && cancellable.is_cancelled())
{
return false;
}
-
+
m_doc->dump_memory_enc(out m_html);
m_html = grabberUtils.postProcessing(ref m_html);
return true;
}
-
+
private void prepArticle()
{
m_doc = new Html.Doc("1.0");
@@ -604,35 +604,35 @@ public class FeedReader.Grabber : GLib.Object {
m_root = new Xml.Node(m_ns, "body");
m_doc->set_root_element(m_root);
}
-
+
public string getArticle()
{
return m_html;
}
-
+
public void print()
{
if(m_title != null)
{
Logger.debug("Grabber: title: %s".printf(m_title));
}
-
+
if(m_author != null)
{
Logger.debug("Grabber: author: %s".printf(m_author));
}
-
+
if(m_date != null)
{
Logger.debug("Grabber: date: %s".printf(m_date));
}
}
-
+
public string? getAuthor()
{
return m_author;
}
-
+
public string? getTitle()
{
return m_title;
diff --git a/src/ContentGrabber/grabberConfig.vala b/src/ContentGrabber/grabberConfig.vala
index b2982cba..3afdb498 100644
--- a/src/ContentGrabber/grabberConfig.vala
+++ b/src/ContentGrabber/grabberConfig.vala
@@ -14,7 +14,7 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.GrabberConfig : GLib.Object {
-
+
private Gee.List<string> m_xpath_title;
private Gee.List<string> m_xpath_author;
private Gee.List<string> m_xpath_date;
@@ -29,7 +29,7 @@ public class FeedReader.GrabberConfig : GLib.Object {
private string m_nextPageLink;
private Gee.List<StringPair> m_replace;
private string m_testURL;
-
+
public GrabberConfig(string filename)
{
m_xpath_title = new Gee.ArrayList<string>();
@@ -40,25 +40,25 @@ public class FeedReader.GrabberConfig : GLib.Object {
m_xpath_stripIDorClass = new Gee.ArrayList<string>();
m_xpath_stripImgSrc = new Gee.ArrayList<string>();
m_replace = new Gee.ArrayList<StringPair>();
-
+
// init defaults:
m_tidy = true;
m_prune = true;
m_autodetectOnFailure = true;
-
+
var file = File.new_for_path(filename);
-
+
if(!file.query_exists())
{
Logger.error("File '%s' doesn't exist.".printf(file.get_path()));
return;
}
-
+
try
{
var dis = new DataInputStream(file.read ());
string line;
-
+
while((line = dis.read_line()) != null)
{
line = line.chug();
@@ -146,20 +146,20 @@ public class FeedReader.GrabberConfig : GLib.Object {
error("%s", e.message);
}
}
-
+
private string extractValue(string identifier, string line)
{
string res = line.splice(0, identifier.length);
-
+
int index = res.index_of("#");
if(index != -1)
{
res = res.splice(index, res.length);
}
-
+
return res.chug().chomp();
}
-
+
private void splitValues(ref Gee.List<string> list, string line)
{
var array = line.split(" | ");
@@ -168,11 +168,11 @@ public class FeedReader.GrabberConfig : GLib.Object {
list.add(tmp);
}
}
-
+
public void print()
{
const string TAB = " ";
-
+
if(m_xpath_title.size != 0)
{
Logger.debug("title:");
@@ -181,7 +181,7 @@ public class FeedReader.GrabberConfig : GLib.Object {
Logger.debug(TAB + title);
}
}
-
+
if(m_xpath_author.size != 0)
{
Logger.debug("author:");
@@ -190,7 +190,7 @@ public class FeedReader.GrabberConfig : GLib.Object {
Logger.debug(TAB + author);
}
}
-
+
if(m_xpath_date.size != 0)
{
Logger.debug("date:");
@@ -199,7 +199,7 @@ public class FeedReader.GrabberConfig : GLib.Object {
Logger.debug(TAB + date);
}
}
-
+
if(m_xpath_body.size != 0)
{
Logger.debug("body:");
@@ -208,7 +208,7 @@ public class FeedReader.GrabberConfig : GLib.Object {
Logger.debug(TAB + body);
}
}
-
+
if(m_xpath_strip.size != 0)
{
Logger.debug("strip:");
@@ -217,7 +217,7 @@ public class FeedReader.GrabberConfig : GLib.Object {
Logger.debug(TAB + strip);
}
}
-
+
if(m_xpath_stripIDorClass.size != 0)
{
Logger.debug("stripIDorClass:");
@@ -226,7 +226,7 @@ public class FeedReader.GrabberConfig : GLib.Object {
Logger.debug(TAB + stripIDorClass);
}
}
-
+
if(m_xpath_stripImgSrc.size != 0)
{
Logger.debug("stripImgSrc:");
@@ -235,7 +235,7 @@ public class FeedReader.GrabberConfig : GLib.Object {
Logger.debug(TAB + stripImgSrc);
}
}
-
+
if(m_tidy)
{
Logger.debug("tidy: yes");
@@ -244,7 +244,7 @@ public class FeedReader.GrabberConfig : GLib.Object {
{
Logger.debug("tidy: no");
}
-
+
if(m_prune)
{
Logger.debug("prune: yes");
@@ -253,7 +253,7 @@ public class FeedReader.GrabberConfig : GLib.Object {
{
Logger.debug("prune: no");
}
-
+
if(m_autodetectOnFailure)
{
Logger.debug("autodetectOnFailure: yes");
@@ -262,17 +262,17 @@ public class FeedReader.GrabberConfig : GLib.Object {
{
Logger.debug("autodetectOnFailure: no");
}
-
+
if(m_singlePageLink != null)
{
Logger.debug("singlePageLink: " + m_singlePageLink);
}
-
+
if(m_nextPageLink != null)
{
Logger.debug("nextPageLink: " + m_nextPageLink);
}
-
+
if(m_replace.size != 0)
{
Logger.debug("replace:");
@@ -281,59 +281,59 @@ public class FeedReader.GrabberConfig : GLib.Object {
Logger.debug("replace %s with %s".printf(tmp.getString1(), tmp.getString2()));
}
}
-
+
if(m_testURL != null)
{
Logger.debug("testURL: " + m_testURL);
}
}
-
-
+
+
public string getXPathNextPageURL()
{
return m_nextPageLink;
}
-
+
public string getXPathSinglePageURL()
{
return m_singlePageLink;
}
-
+
public unowned Gee.List<string> getXPathTitle()
{
return m_xpath_title;
}
-
+
public unowned Gee.List<string> getXPathAuthor()
{
return m_xpath_author;
}
-
+
public unowned Gee.List<string> getXPathDate()
{
return m_xpath_date;
}
-
+
public unowned Gee.List<string> getXPathStrip()
{
return m_xpath_strip;
}
-
+
public unowned Gee.List<string> getXPathStripIDorClass()
{
return m_xpath_stripIDorClass;
}
-
+
public unowned Gee.List<string> getXPathStripImgSrc()
{
return m_xpath_stripImgSrc;
}
-
+
public unowned Gee.List<string> getXPathBody()
{
return m_xpath_body;
}
-
+
public unowned Gee.List<StringPair> getReplace()
{
return m_replace;
diff --git a/src/ContentGrabber/grabberUtils.vala b/src/ContentGrabber/grabberUtils.vala
index 072216ba..3d7a7eaf 100644
--- a/src/ContentGrabber/grabberUtils.vala
+++ b/src/ContentGrabber/grabberUtils.vala
@@ -14,18 +14,18 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.grabberUtils : GLib.Object {
-
+
public grabberUtils()
{
-
+
}
-
+
public static bool extractBody(Html.Doc* doc, string xpath, Xml.Node* destination)
{
bool foundSomething = false;
var cntx = new Xml.XPath.Context(doc);
var res = cntx.eval_expression(xpath);
-
+
if(res == null)
{
return false;
@@ -35,32 +35,32 @@ public class FeedReader.grabberUtils : GLib.Object {
delete res;
return false;
}
-
+
for(int i = 0; i < res->nodesetval->length(); i++)
{
Xml.Node* node = res->nodesetval->item(i);
-
+
// remove property "style" of all tags
node->has_prop("style")->remove();
-
+
node->unlink();
destination->add_child(node);
-
+
if(!foundSomething)
{
foundSomething = true;
}
}
-
+
delete res;
return foundSomething;
}
-
+
public static string? getURL(Html.Doc* doc, string xpath)
{
var cntx = new Xml.XPath.Context(doc);
var res = cntx.eval_expression(xpath);
-
+
if(res == null)
{
return null;
@@ -70,21 +70,21 @@ public class FeedReader.grabberUtils : GLib.Object {
delete res;
return null;
}
-
+
Xml.Node* node = res->nodesetval->item(0);
string URL = node->get_prop("href");
-
+
node->unlink();
node->free_list();
delete res;
return URL;
}
-
+
public static string? getValue(Html.Doc* doc, string xpath, bool remove = false)
{
Xml.XPath.Context cntx = new Xml.XPath.Context(doc);
Xml.XPath.Object* res = cntx.eval_expression(xpath);
-
+
if(res == null)
{
return null;
@@ -94,26 +94,26 @@ public class FeedReader.grabberUtils : GLib.Object {
delete res;
return null;
}
-
+
Xml.Node* node = res->nodesetval->item(0);
string result = cleanString(node->get_content());
-
+
if(remove)
{
node->unlink();
node->free_list();
}
-
+
delete res;
return result;
}
-
+
public static bool repairURL(string xpath, string attr, Html.Doc* doc, string articleURL)
{
Logger.debug("GrabberUtils: repairURL xpath:\"%s\" attr:\"%s\"".printf(xpath, attr));
Xml.XPath.Context cntx = new Xml.XPath.Context(doc);
Xml.XPath.Object* res = cntx.eval_expression(xpath);
-
+
if(res == null)
{
return false;
@@ -123,7 +123,7 @@ public class FeedReader.grabberUtils : GLib.Object {
delete res;
return false;
}
-
+
for(int i = 0; i < res->nodesetval->length(); i++)
{
Xml.Node* node = res->nodesetval->item(i);
@@ -132,17 +132,17 @@ public class FeedReader.grabberUtils : GLib.Object {
node->set_prop(attr, completeURL(node->get_prop(attr), articleURL));
}
}
-
+
delete res;
return true;
}
-
+
public static bool fixLazyImg(Html.Doc* doc, string className, string correctURL)
{
Logger.debug("grabberUtils: fixLazyImg");
Xml.XPath.Context cntx = new Xml.XPath.Context(doc);
Xml.XPath.Object* res = cntx.eval_expression("//img[contains(@class, '%s')]".printf(className));
-
+
if(res == null)
{
return false;
@@ -152,23 +152,23 @@ public class FeedReader.grabberUtils : GLib.Object {
delete res;
return false;
}
-
+
for(int i = 0; i < res->nodesetval->length(); i++)
{
Xml.Node* node = res->nodesetval->item(i);
node->set_prop("src", node->get_prop(correctURL));
}
-
+
delete res;
return true;
}
-
+
public static bool fixIframeSize(Html.Doc* doc, string siteName)
{
Logger.debug("grabberUtils: fixIframeSize");
Xml.XPath.Context cntx = new Xml.XPath.Context(doc);
Xml.XPath.Object* res = cntx.eval_expression(@"//iframe[contains(@src, '$siteName')]");
-
+
if(res == null)
{
return false;
@@ -178,26 +178,26 @@ public class FeedReader.grabberUtils : GLib.Object {
delete res;
return false;
}
-
+
for(int i = 0; i < res->nodesetval->length(); i++)
{
Xml.Node* node = res->nodesetval->item(i);
Xml.Node* videoWrapper = new Xml.Node(null, "div");
Xml.Node* parent = node->parent;
-
+
videoWrapper->set_prop("class", "videoWrapper");
node->set_prop("width", "100%");
node->unset_prop("height");
-
+
node->unlink();
videoWrapper->add_child(node);
parent->add_child(videoWrapper);
}
-
+
delete res;
return true;
}
-
+
public static void stripNode(Html.Doc* doc, string xpath)
{
string ancestor = xpath;
@@ -206,10 +206,10 @@ public class FeedReader.grabberUtils : GLib.Object {
ancestor = ancestor.substring(2);
}
string query = "%s[not(ancestor::%s)]".printf(xpath, ancestor);
-
+
Xml.XPath.Context cntx = new Xml.XPath.Context(doc);
Xml.XPath.Object* res = cntx.eval_expression(query);
-
+
if(res != null
&& res->type == Xml.XPath.ObjectType.NODESET
&& res->nodesetval != null)
@@ -221,15 +221,15 @@ public class FeedReader.grabberUtils : GLib.Object {
{
continue;
}
-
+
node->unlink();
node->free_list();
}
}
-
+
delete res;
}
-
+
public static void onlyRemoveNode(Html.Doc* doc, string xpath)
{
Xml.XPath.Context cntx = new Xml.XPath.Context(doc);
@@ -238,7 +238,7 @@ public class FeedReader.grabberUtils : GLib.Object {
{
changed = false;
Xml.XPath.Object* res = cntx.eval_expression(xpath);
-
+
if(res != null
&& res->type == Xml.XPath.ObjectType.NODESET
&& res->nodesetval != null)
@@ -250,29 +250,29 @@ public class FeedReader.grabberUtils : GLib.Object {
{
continue;
}
-
+
Xml.Node* parent = node->parent;
Xml.Node* children = node->children;
-
+
children->unlink();
parent->add_child(children);
-
+
node->unlink();
node->free_list();
changed = true;
break;
}
}
-
+
delete res;
} while(changed);
}
-
+
public static bool setAttributes(Html.Doc* doc, string attribute, string newValue)
{
Xml.XPath.Context cntx = new Xml.XPath.Context(doc);
Xml.XPath.Object* res = cntx.eval_expression("//*[@%s]".printf(attribute));
-
+
if(res == null)
{
return false;
@@ -282,17 +282,17 @@ public class FeedReader.grabberUtils : GLib.Object {
delete res;
return false;
}
-
+
for(int i = 0; i < res->nodesetval->length(); i++)
{
Xml.Node* node = res->nodesetval->item(i);
node->set_prop(attribute, newValue);
}
-
+
delete res;
return true;
}
-
+
public static bool removeAttributes(Html.Doc* doc, string? tag, string attribute)
{
Xml.XPath.Context cntx = new Xml.XPath.Context(doc);
@@ -305,7 +305,7 @@ public class FeedReader.grabberUtils : GLib.Object {
{
res = cntx.eval_expression("//%s[@%s]".printf(tag, attribute));
}
-
+
if(res == null)
{
return false;
@@ -315,17 +315,17 @@ public class FeedReader.grabberUtils : GLib.Object {
delete res;
return false;
}
-
+
for(int i = 0; i < res->nodesetval->length(); i++)
{
Xml.Node* node = res->nodesetval->item(i);
node->unset_prop(attribute);
}
-
+
delete res;
return true;
}
-
+
public static bool addAttributes(Html.Doc* doc, string? tag, string attribute, string val)
{
Xml.XPath.Context cntx = new Xml.XPath.Context(doc);
@@ -340,7 +340,7 @@ public class FeedReader.grabberUtils : GLib.Object {
Logger.debug(@"addAttributes: //$tag $attribute $val");
res = cntx.eval_expression(@"//$tag");
}
-
+
if(res == null)
{
return false;
@@ -350,23 +350,23 @@ public class FeedReader.grabberUtils : GLib.Object {
delete res;
return false;
}
-
+
for(int i = 0; i < res->nodesetval->length(); i++)
{
Xml.Node* node = res->nodesetval->item(i);
node->set_prop(attribute, val);
}
-
+
delete res;
return true;
}
-
+
public static void stripIDorClass(Html.Doc* doc, string IDorClass)
{
Xml.XPath.Context cntx = new Xml.XPath.Context(doc);
string xpath = "//*[contains(@class, '%s') or contains(@id, '%s')]".printf(IDorClass, IDorClass);
Xml.XPath.Object* res = cntx.eval_expression(xpath);
-
+
if(res != null
&& res->type == Xml.XPath.ObjectType.NODESET
&& res->nodesetval != null)
@@ -383,21 +383,21 @@ public class FeedReader.grabberUtils : GLib.Object {
}
}
}
-
+
delete res;
}
-
+
public static string cleanString(string? text)
{
if(text == null)
{
return "";
}
-
+
var tmpText = text.replace("\n", "");
var array = tmpText.split(" ");
tmpText = "";
-
+
foreach(string word in array)
{
if(word.chug() != "")
@@ -405,10 +405,10 @@ public class FeedReader.grabberUtils : GLib.Object {
tmpText += word + " ";
}
}
-
+
return tmpText.chomp();
}
-
+
public static string completeURL(string incompleteURL, string articleURL)
{
int index = 0;
@@ -420,9 +420,9 @@ public class FeedReader.grabberUtils : GLib.Object {
{
index = articleURL.index_of_char('.', 0);
}
-
+
string baseURL = "";
-
+
if(incompleteURL.has_prefix("/") && !incompleteURL.has_prefix("//"))
{
index = articleURL.index_of_char('/', index);
@@ -455,10 +455,10 @@ public class FeedReader.grabberUtils : GLib.Object {
{
return "http:" + incompleteURL;
}
-
+
return incompleteURL;
}
-
+
public static string buildHostName(string URL, bool cutSubdomain = true)
{
string hostname = URL;
@@ -470,15 +470,15 @@ public class FeedReader.grabberUtils : GLib.Object {
{
hostname = hostname.substring(8);
}
-
+
if(hostname.has_prefix("www."))
{
hostname = hostname.substring(4);
}
-
+
int index = hostname.index_of_char('/');
hostname = hostname.substring(0, index);
-
+
if(cutSubdomain)
{
index = hostname.index_of_char('.');
@@ -487,17 +487,17 @@ public class FeedReader.grabberUtils : GLib.Object {
hostname = hostname.substring(index);
}
}
-
+
return hostname;
}
-
-
+
+
public static bool saveImages(Soup.Session session, Html.Doc* doc, Article article, GLib.Cancellable? cancellable = null)
{
Logger.debug("GrabberUtils: save Images: %s, %s".printf(article.getArticleID(), article.getFeedID()));
Xml.XPath.Context cntx = new Xml.XPath.Context(doc);
Xml.XPath.Object* res = cntx.eval_expression("//img");
-
+
if(res == null)
{
return false;
@@ -507,14 +507,14 @@ public class FeedReader.grabberUtils : GLib.Object {
delete res;
return false;
}
-
+
for(int i = 0; i < res->nodesetval->length(); i++)
{
if(cancellable != null && cancellable.is_cancelled())
{
break;
}
-
+
Xml.Node* node = res->nodesetval->item(i);
if(node->get_prop("src") != null)
{
@@ -527,17 +527,17 @@ public class FeedReader.grabberUtils : GLib.Object {
)
{
string? original = downloadImage(session, node->get_prop("src"), article, i+1);
-
+
if(original == null)
{
continue;
}
-
+
string? parentURL = checkParent(session, node);
if(parentURL != null)
{
string parent = downloadImage(session, parentURL, article, i+1, true);
-
+
if(compareImageSize(parent, original) > 0)
{
// parent is bigger than orignal image
@@ -568,27 +568,27 @@ public class FeedReader.grabberUtils : GLib.Object {
}
}
}
-
+
delete res;
return true;
}
-
-
+
+
public static string? downloadImage(Soup.Session session, string? url, Article article, int nr, bool parent = false)
{
if(url == null || url.down().has_prefix("data:image"))
{
return null;
}
-
+
string fixedURL = url;
string imgPath = GLib.Environment.get_user_data_dir();
-
+
if(fixedURL.has_prefix("//"))
{
fixedURL = "http:" + fixedURL;
}
-
+
if(article.getArticleID() == "" && article.getFeedID() == "")
{
imgPath += "/debug-article/ArticleImages/";
@@ -597,7 +597,7 @@ public class FeedReader.grabberUtils : GLib.Object {
{
imgPath += "/feedreader/data/images/%s/%s/".printf(article.getFeedFileName(), article.getArticleFileName());
}
-
+
var path = GLib.File.new_for_path(imgPath);
try
{
@@ -607,29 +607,29 @@ public class FeedReader.grabberUtils : GLib.Object {
{
//Logger.debug(e.message);
}
-
+
string localFilename = imgPath + nr.to_string();
-
+
if(parent)
{
localFilename += "_parent";
}
-
+
if(!FileUtils.test(localFilename, GLib.FileTest.EXISTS))
{
var message_dlImg = new Soup.Message("GET", fixedURL);
-
+
if(message_dlImg == null)
{
Logger.warning(@"grabberUtils.downloadImage: could not create soup message $fixedURL");
return url;
}
-
+
if(Settings.tweaks().get_boolean("do-not-track"))
{
message_dlImg.request_headers.append("DNT", "1");
}
-
+
var status = session.send_message(message_dlImg);
if(status == 200)
{
@@ -643,7 +643,7 @@ public class FeedReader.grabberUtils : GLib.Object {
localFilename += ".svg";
}
}
-
+
try{
FileUtils.set_contents( localFilename,
(string)message_dlImg.response_body.flatten().data,
@@ -661,11 +661,11 @@ public class FeedReader.grabberUtils : GLib.Object {
return url;
}
}
-
+
return localFilename.replace("?", "%3F");
}
-
-
+
+
// if image is >2000px then resize it to 1000px and add FR_huge attribute
// with url to original image
private static string? resizeImg(string path)
@@ -675,12 +675,12 @@ public class FeedReader.grabberUtils : GLib.Object {
int? height = 0;
int? width = 0;
Gdk.PixbufFormat? format = Gdk.Pixbuf.get_file_info(path, out width, out height);
-
+
if(format == null || height == null || width == null)
{
return null;
}
-
+
if(width > 2000 || height > 2000)
{
int nHeight = 1000;
@@ -693,7 +693,7 @@ public class FeedReader.grabberUtils : GLib.Object {
{
nWidth = -1;
}
-
+
var img = new Gdk.Pixbuf.from_file_at_scale(path, nWidth, nHeight, true);
img.save(path + "_resized", "png");
return path + "_resized";
@@ -706,7 +706,7 @@ public class FeedReader.grabberUtils : GLib.Object {
}
return null;
}
-
+
// receives 2 paths to images stored on the hdd and compares the size
// 1: file1 > file2
// 0: file1 = file2
@@ -716,11 +716,11 @@ public class FeedReader.grabberUtils : GLib.Object {
int? height1 = 0;
int? width1 = 0;
Gdk.Pixbuf.get_file_info(file1, out width1, out height1);
-
+
int? height2 = 0;
int? width2 = 0;
Gdk.Pixbuf.get_file_info(file2, out width2, out height2);
-
+
if(height1 == null
|| width1 == null
|| height2 == null
@@ -729,7 +729,7 @@ public class FeedReader.grabberUtils : GLib.Object {
Logger.warning("Utils.compareImageSize: couldn't read image sizes");
return 0;
}
-
+
if(height1 == height2
&& width1 == width2)
{
@@ -744,7 +744,7 @@ public class FeedReader.grabberUtils : GLib.Object {
return -1;
}
}
-
+
// check if the parent node is a link that points to a picture
// (most likely a bigger version of said picture)
private static string? checkParent(Soup.Session session, Xml.Node* node)
@@ -759,14 +759,14 @@ public class FeedReader.grabberUtils : GLib.Object {
if(name == "a")
{
string url = parent->get_prop("href");
-
+
if(url != "" && url != null)
{
if(url.has_prefix("//"))
{
url = "http:" + url;
}
-
+
var message = new Soup.Message("HEAD", url);
if(message == null)
{
@@ -807,15 +807,15 @@ public class FeedReader.grabberUtils : GLib.Object {
}
}
}
-
+
return null;
}
-
+
public static string postProcessing(ref string html)
{
Logger.debug("GrabberUtils: postProcessing");
html = html.replace("<h3/>", "<h3></h3>");
-
+
int pos1 = html.index_of("<iframe", 0);
int pos2 = -1;
int pos3 = -1;
@@ -823,23 +823,23 @@ public class FeedReader.grabberUtils : GLib.Object {
{
pos2 = html.index_of("/>", pos1);
pos3 = html.index_of("</iframe>", pos1);
-
+
if(pos3 == -1 && pos2 == -1)
{
Logger.error("GrabberUtils.postProcessing: could not find closing for iframe tag");
pos1 = html.index_of("<iframe", pos1+7);
continue;
}
-
+
if((pos2 != -1 && pos3 != -1 && pos3 < pos2) || pos2 == -1)
{
Logger.debug("GrabberUtils.postProcessing: iframe not broken");
pos1 = html.index_of("<iframe", pos1+7);
continue;
}
-
-
-
+
+
+
string broken_iframe = html.substring(pos1, pos2+2-pos1);
Logger.debug("GrabberUtils: broken = %s".printf(broken_iframe));
string fixed_iframe = broken_iframe.substring(0, broken_iframe.length-2) + "></iframe>";
diff --git a/src/ContentGrabber/stringPair.vala b/src/ContentGrabber/stringPair.vala
index 6b8b16ef..b4eb99cd 100644
--- a/src/ContentGrabber/stringPair.vala
+++ b/src/ContentGrabber/stringPair.vala
@@ -16,18 +16,18 @@
public class FeedReader.StringPair : GLib.Object {
private string m_string1;
private string m_string2;
-
+
public StringPair(string string1, string string2)
{
m_string1 = string1;
m_string2 = string2;
}
-
+
public string getString1()
{
return m_string1;
}
-
+
public string getString2()
{
return m_string2;
diff --git a/src/DataBaseReadOnly.vala b/src/DataBaseReadOnly.vala
index cce90f3c..7e8b494a 100644
--- a/src/DataBaseReadOnly.vala
+++ b/src/DataBaseReadOnly.vala
@@ -14,33 +14,33 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.DataBaseReadOnly : GLib.Object {
-
+
protected SQLite m_db;
-
+
static construct {
Sqlite.config(Sqlite.Config.LOG, errorLogCallback);
}
-
+
public DataBaseReadOnly(string db_file = "feedreader-%01i.db".printf(Constants.DB_SCHEMA_VERSION))
{
string db_path = GLib.Environment.get_user_data_dir() + "/feedreader/data/" + db_file;
-
+
Logger.debug(@"Opening Database: $db_path");
m_db = new SQLite(db_path);
}
-
+
private void errorLogCallback(int code, string msg)
{
Logger.error(@"dbErrorLog: $code: $msg");
}
-
+
public void init()
{
Logger.debug("init database");
m_db.simple_query("PRAGMA journal_mode = WAL");
m_db.simple_query("PRAGMA page_size = 4096");
m_db.simple_query("PRAGMA foreign_keys = ON");
-
+
m_db.simple_query("""
CREATE TABLE IF NOT EXISTS "main"."feeds"
(
@@ -53,7 +53,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
"iconURL" TEXT
)
""");
-
+
m_db.simple_query("""
CREATE TABLE IF NOT EXISTS "main"."categories"
(
@@ -65,7 +65,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
"Level" INTEGER
)
""");
-
+
m_db.simple_query("""
CREATE TABLE IF NOT EXISTS "main"."articles"
(
@@ -84,7 +84,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
"contentFetched" INTEGER NOT NULL
)
""");
-
+
m_db.simple_query("""
CREATE TABLE IF NOT EXISTS "main"."tags"
(
@@ -94,7 +94,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
"color" INTEGER
)
""");
-
+
m_db.simple_query("""
CREATE TABLE IF NOT EXISTS "main"."CachedActions"
(
@@ -103,7 +103,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
"argument" INTEGER
)
""");
-
+
m_db.simple_query("""
CREATE TABLE IF NOT EXISTS "main"."Enclosures"
(
@@ -113,7 +113,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
FOREIGN KEY(articleID) REFERENCES articles(articleID)
)
""");
-
+
m_db.simple_query("""
CREATE TABLE IF NOT EXISTS "main"."taggings"
(
@@ -123,18 +123,18 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
FOREIGN KEY(tagID) REFERENCES tags(tagID)
)
""");
-
+
m_db.simple_query("""
CREATE INDEX IF NOT EXISTS "index_articles"
ON "articles" ("feedID" DESC, "unread" ASC, "marked" ASC)
""");
-
+
m_db.simple_query("""
CREATE VIRTUAL TABLE IF NOT EXISTS fts_table
USING fts4 (content='articles', articleID, preview, title, author)
""");
}
-
+
public bool uninitialized()
{
string query = "SELECT count(*) FROM sqlite_master WHERE type='table' AND name='articles'";
@@ -142,7 +142,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
assert(rows.size == 1 && rows[0].size == 1);
return rows[0][0].to_int() == 0;
}
-
+
public bool isEmpty()
{
return isTableEmpty("articles")
@@ -150,7 +150,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
&& isTableEmpty("feeds")
&& isTableEmpty("tags");
}
-
+
public bool isTableEmpty(string table)
requires (table != "")
{
@@ -159,7 +159,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
assert(rows.size == 1 && rows[0].size == 1);
return rows[0][0].to_int() == 0;
}
-
+
private uint count_article_status(ArticleStatus status)
{
var query = "SELECT COUNT(*) FROM articles";
@@ -172,17 +172,17 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
assert(rows.size == 1 && rows[0].size == 1);
return rows[0][0].to_int();
}
-
+
public uint get_unread_total()
{
return count_article_status(ArticleStatus.UNREAD);
}
-
+
public uint get_marked_total()
{
return count_article_status(ArticleStatus.MARKED);
}
-
+
private uint count_status_uncategorized(ArticleStatus status)
{
var query = new QueryBuilder(QueryType.SELECT, "articles");
@@ -192,15 +192,15 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
{
query.where_equal_int(status_column, status.to_int());
}
-
-
+
+
var subquery = new QueryBuilder(QueryType.SELECT, "feeds");
subquery.select_field("feed_id");
subquery.where(getUncategorizedQuery());
query.where("feedID IN (%s)".printf(subquery.to_string()));
-
+
Sqlite.Statement stmt = m_db.prepare(query.to_string());
-
+
int unread = 0;
while (stmt.step() == Sqlite.ROW) {
unread = stmt.column_int(0);
@@ -208,30 +208,30 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
stmt.reset();
return unread;
}
-
+
public uint get_unread_uncategorized()
{
return count_status_uncategorized(ArticleStatus.UNREAD);
}
-
+
public uint get_marked_uncategorized()
{
return count_status_uncategorized(ArticleStatus.MARKED);
}
-
+
public int get_new_unread_count(int row_id)
{
if(row_id == 0)
{
return 0;
}
-
+
string query = "SELECT count(*) FROM articles WHERE unread = ? AND rowid > ?";
var rows = m_db.execute(query, { ArticleStatus.UNREAD, row_id });
assert(rows.size == 1 && rows[0].size == 1);
return rows[0][0].to_int();
}
-
+
public int getTagColor()
{
var rows = m_db.execute("SELECT COUNT(*) FROM tags WHERE instr(tagID, 'global.') = 0");
@@ -239,14 +239,14 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
int tagCount = rows[0][0].to_int();
return tagCount % Constants.COLORS.length;
}
-
+
public bool tag_still_used(Tag tag)
{
var query = "SELECT 1 FROM main.taggings WHERE tagID = ? LIMIT 1";
var rows = m_db.execute(query, { tag.getTagID() });
return rows.size > 0;
}
-
+
public string? getTagName(string tag_id)
{
var query = "SELECT title FROM tags WHERE tagID = ?";
@@ -258,7 +258,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
}
return _("Unknown tag");
}
-
+
public int getLastModified()
{
var query = "SELECT MAX(lastModified) FROM articles";
@@ -273,31 +273,31 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
return 0;
}
}
-
+
public string getCategoryName(string catID)
{
if(catID == CategoryID.TAGS.to_string())
{
return "Tags";
}
-
+
var query = "SELECT title FROM categories WHERE categorieID = ?";
var rows = m_db.execute(query, { catID });
-
+
string result = "";
if(rows.size != 0)
{
result = rows[0][0].to_string();
}
-
+
if(result == "")
{
result = _("Uncategorized");
}
-
+
return result;
}
-
+
public string? getCategoryID(string catname)
{
var query = "SELECT categorieID FROM categories WHERE title = ?";
@@ -311,7 +311,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
return rows[0][0].to_string();
}
}
-
+
public bool preview_empty(string articleID)
{
var query = "SELECT COUNT(*) FROM articles WHERE articleID = ? AND preview != ''";
@@ -319,7 +319,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
assert(rows.size == 1 && rows[0].size == 1);
return rows[0][0].to_int() != 0;
}
-
+
public Gee.List<Article> read_article_between(
string feedID,
FeedListType selectedType,
@@ -332,7 +332,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
{
var query = articleQuery(feedID, selectedType, state, searchTerm);
var sorting = (ArticleListSort)Settings.general().get_enum("articlelist-sort-by");
-
+
if(sorting == ArticleListSort.RECEIVED)
{
query.where(
@@ -348,9 +348,9 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
var smallerDate = (bigger) ? date2.to_unix() : date1.to_unix();
query.where(@"date BETWEEN $smallerDate AND $biggerDate");
}
-
+
Sqlite.Statement stmt = m_db.prepare(query.to_string());
-
+
var articles = new Gee.ArrayList<Article>();
while (stmt.step () == Sqlite.ROW)
{
@@ -359,7 +359,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
{
continue;
}
-
+
articles.add(new Article(
stmt.column_text(2), // articleID
stmt.column_text(3), // title
@@ -380,32 +380,32 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
stmt.reset();
return articles;
}
-
+
private Gee.List<Enclosure> read_enclosures(string article_id)
{
var list = new Gee.ArrayList<Enclosure>();
-
+
var query = "SELECT url, type FROM Enclosures WHERE articleID = ?";
var rows = m_db.execute(query, { article_id });
-
+
foreach(var row in rows)
{
list.add(new Enclosure(article_id, row[0].to_string(), (EnclosureType)row[1].to_int()));
}
-
+
return list;
}
-
+
public Gee.HashMap<string, Article> read_article_stats(Gee.List<string> ids)
{
var query = new QueryBuilder(QueryType.SELECT, "articles");
query.select_field("articleID, unread, marked");
query.where_in_strings("articleID", ids);
-
+
Sqlite.Statement stmt = m_db.prepare(query.to_string());
-
+
var articles = new Gee.HashMap<string, Article>();
-
+
while(stmt.step() == Sqlite.ROW)
{
articles.set(stmt.column_text(0),
@@ -415,7 +415,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
stmt.reset();
return articles;
}
-
+
public Article? read_article(string articleID)
{
Logger.debug(@"DataBaseReadOnly.read_article(): $articleID");
@@ -430,7 +430,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
{
author = null;
}
-
+
return new Article(
articleID,
row[3].to_string(),
@@ -448,7 +448,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
row[11].to_string() // guid
);
}
-
+
public int getMaxCatLevel()
{
var rows = m_db.execute("SELECT MAX(Level) FROM categories");
@@ -460,18 +460,18 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
}
return maxCatLevel;
}
-
+
public bool haveFeedsWithoutCat()
{
var query = new QueryBuilder(QueryType.SELECT, "feeds");
query.select_field("count(*)");
query.where(getUncategorizedQuery());
-
+
Sqlite.Statement stmt = m_db.prepare(query.to_string());
-
+
while (stmt.step () == Sqlite.ROW) {
int count = stmt.column_int(0);
-
+
if(count > 0)
{
return true;
@@ -479,34 +479,34 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
}
return false;
}
-
+
public bool haveCategories()
{
var rows = m_db.execute("SELECT COUNT(*) FROM categories");
assert(rows.size == 1 && rows[0].size == 1);
return rows[0][0].to_int() > 0;
}
-
+
public bool article_exists(string articleID)
{
var rows = m_db.execute("SELECT 1 FROM articles WHERE articleID = ? LIMIT 1", { articleID });
return rows.size != 0;
}
-
+
public int getArticleCountNewerThanID(string articleID, string feedID, FeedListType selectedType, ArticleListState state, string searchTerm)
ensures (result >= 0)
{
string order_by = ((ArticleListSort)Settings.general().get_enum("articlelist-sort-by") == ArticleListSort.RECEIVED) ? "rowid" : "date";
-
+
var query = new QueryBuilder(QueryType.SELECT, "articles");
query.where_equal_string("articleID", articleID);
-
+
var query2 = new QueryBuilder(QueryType.SELECT, "articles");
query2.select_field("count(*)");
-
-
+
+
query.select_field(order_by);
-
+
if(Settings.general().get_boolean("articlelist-oldest-first") && state == ArticleListState.UNREAD)
{
query2.where(@"$order_by < (%s)".printf(query.to_string()));
@@ -515,8 +515,8 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
{
query2.where(@"$order_by > (%s)".printf(query.to_string()));
}
-
-
+
+
if(selectedType == FeedListType.FEED && feedID != FeedID.ALL.to_string())
{
query2.where_equal_string("feedID", feedID);
@@ -533,7 +533,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
{
query2.where_in_strings("articleID", read_taggings_by_tag_id(feedID));
}
-
+
if(state == ArticleListState.UNREAD)
{
query2.where_equal_int("unread", ArticleStatus.UNREAD.to_int());
@@ -542,7 +542,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
{
query2.where_equal_int("marked", ArticleStatus.MARKED.to_int());
}
-
+
if(searchTerm != "")
{
string search_column;
@@ -568,37 +568,37 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
search_column,
SQLite.quote_string(Utils.prepareSearchQuery(searchTerm))));
}
-
+
bool desc = true;
if(Settings.general().get_boolean("articlelist-oldest-first") && state == ArticleListState.UNREAD)
{
desc = false;
}
-
+
query2.order_by(order_by, desc);
-
+
Sqlite.Statement stmt = m_db.prepare(query2.to_string());
-
+
int res = 0;
while (stmt.step () == Sqlite.ROW) {
res = stmt.column_int(0);
}
return res;
}
-
+
public Gee.List<string> getFeedIDofCategorie(string categorieID)
{
var feedIDs = new Gee.ArrayList<string>();
-
+
var query = new QueryBuilder(QueryType.SELECT, "feeds");
query.select_field("feed_id, category_id");
-
+
Sqlite.Statement stmt = m_db.prepare(query.to_string());
-
+
while (stmt.step() == Sqlite.ROW) {
string catString = stmt.column_text(1);
string[] categories = catString.split(",");
-
+
if(categorieID == "")
{
if((categories.length == 0)
@@ -620,13 +620,13 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
}
return feedIDs;
}
-
+
protected string getUncategorizedQuery()
{
string catID = FeedServer.get_default().uncategorizedID();
return "category_id = %s".printf(SQLite.quote_string(catID));
}
-
+
protected bool showCategory(string catID, Gee.List<Feed> feeds)
{
if(FeedServer.get_default().hideCategoryWhenEmpty(catID)
@@ -636,7 +636,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
}
return true;
}
-
+
public string getFeedIDofArticle(string articleID)
{
var rows = m_db.execute("SELECT feedID FROM articles WHERE articleID = ?", { articleID });
@@ -651,7 +651,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
}
return id;
}
-
+
public string getNewestArticle()
{
var rows = m_db.execute("SELECT articleID FROM articles WHERE rowid = ?", { getMaxID("articles", "rowid") });
@@ -661,7 +661,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
}
return rows[0][0].to_string();
}
-
+
public string getMaxID(string table, string field)
{
var rows = m_db.execute(@"SELECT MAX($field) FROM $table");
@@ -676,7 +676,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
}
return id;
}
-
+
public bool feed_exists(string feed_url)
{
var rows = m_db.execute("SELECT COUNT(*) FROM main.feeds WHERE url = ? LIMIT 1", { feed_url });
@@ -684,7 +684,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
// FIXME: Why > 1 and not > 0?
return rows[0][0].to_int() > 1;
}
-
+
public Feed? read_feed(string feedID)
{
var rows = m_db.execute("SELECT * FROM feeds WHERE feed_id = ?", { feedID });
@@ -692,7 +692,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
{
return null;
}
-
+
var row = rows[0];
return new Feed(
feedID,
@@ -703,20 +703,20 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
row[6].to_string(),
row[5].to_string());
}
-
+
public Gee.List<Feed> read_feeds(bool starredCount = false)
{
Gee.List<Feed> feeds = new Gee.ArrayList<Feed>();
-
+
var query = new QueryBuilder(QueryType.SELECT, "feeds");
query.select_field("*");
if(Settings.general().get_enum("feedlist-sort-by") == FeedListSort.ALPHABETICAL)
{
query.order_by("name", true);
}
-
+
Sqlite.Statement stmt = m_db.prepare(query.to_string());
-
+
while (stmt.step () == Sqlite.ROW) {
string feedID = stmt.column_text(0);
string catString = stmt.column_text(3);
@@ -725,7 +725,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
string url = stmt.column_text(2);
string name = stmt.column_text(1);
var categories = StringUtils.split(catString, ",", true);
-
+
uint count = 0;
if(starredCount)
{
@@ -735,14 +735,14 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
{
count = getFeedUnread(feedID);
}
-
+
var feed = new Feed(feedID, name, url, count, categories, iconURL, xmlURL);
feeds.add(feed);
}
-
+
return feeds;
}
-
+
public uint getFeedUnread(string feedID)
{
var query = "SELECT COUNT(*) FROM articles WHERE unread = ? AND feedID = ?";
@@ -750,7 +750,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
assert(rows.size == 1 && rows[0].size == 1);
return rows[0][0].to_int();
}
-
+
public uint getFeedStarred(string feedID)
{
var query = "SELECT COUNT(*) FROM articles WHERE marked = ? AND feedID = ?";
@@ -758,11 +758,11 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
assert(rows.size == 1 && rows[0].size == 1);
return rows[0][0].to_int();
}
-
+
public Gee.List<Feed> read_feeds_without_cat()
{
var feeds = new Gee.ArrayList<Feed>();
-
+
var query = new QueryBuilder(QueryType.SELECT, "feeds");
query.select_field("*");
query.where(getUncategorizedQuery());
@@ -770,9 +770,9 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
{
query.order_by("name", true);
}
-
+
Sqlite.Statement stmt = m_db.prepare(query.to_string());
-
+
while (stmt.step () == Sqlite.ROW) {
string feedID = stmt.column_text(0);
string catString = stmt.column_text(3);
@@ -784,10 +784,10 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
var feed = new Feed(feedID, name, url, getFeedUnread(feedID), categories, iconURL, xmlURL);
feeds.add(feed);
}
-
+
return feeds;
}
-
+
public Category? read_category(string catID)
{
var query = "SELECT * FROM categories WHERE categorieID = ?";
@@ -796,7 +796,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
{
return null;
}
-
+
var row = rows[0];
return new Category(
catID,
@@ -807,11 +807,11 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
row[5].to_int()
);
}
-
+
public Gee.List<Tag> read_tags()
{
var rows = m_db.execute("SELECT * FROM tags WHERE instr(tagID, 'global.') = 0");
-
+
var tags = new Gee.ArrayList<Tag>();
foreach(var row in rows)
{
@@ -821,38 +821,38 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
row[3].to_int());
tags.add(tag);
}
-
+
return tags;
}
-
+
private Gee.List<string> read_taggings_by_article_id(string articleID)
{
var list = new Gee.LinkedList<string>();
-
+
var rows = m_db.execute("SELECT tagID FROM taggings WHERE articleID = ?", { articleID });
-
+
foreach(var row in rows)
{
list.add(row[0].to_string());
}
-
+
return list;
}
-
+
private Gee.List<string> read_taggings_by_tag_id(string tagID)
{
var list = new Gee.LinkedList<string>();
-
+
var rows = m_db.execute("SELECT articleID FROM taggings WHERE tagID = ?", { tagID });
-
+
foreach(var row in rows)
{
list.add(row[0].to_string());
}
-
+
return list;
}
-
+
public Tag? read_tag(string tagID)
{
var query = "SELECT * FROM tags WHERE tagID = ?";
@@ -861,24 +861,24 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
{
return null;
}
-
+
var row = rows[0];
return new Tag(
row[0].to_string(),
row[1].to_string(),
row[3].to_int());
}
-
+
protected string getAllTagsCondition()
{
return "articleID IN (SELECT articleID FROM taggings WHERE instr(tagID, 'global.') = 0)";
}
-
+
public Gee.List<Category> read_categories_level(int level, Gee.List<Feed>? feeds = null)
{
var categories = read_categories(feeds);
var results = new Gee.ArrayList<Category>();
-
+
foreach(Category cat in categories)
{
if(cat.getLevel() == level)
@@ -886,15 +886,15 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
results.add(cat);
}
}
-
+
return results;
}
-
+
public Gee.List<Category> read_categories(Gee.List<Feed>? feeds = null)
{
var query = new QueryBuilder(QueryType.SELECT, "categories");
query.select_field("*");
-
+
if(Settings.general().get_enum("feedlist-sort-by") == FeedListSort.ALPHABETICAL)
{
query.order_by("title", true);
@@ -903,14 +903,14 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
{
query.order_by("orderID", true);
}
-
+
Sqlite.Statement stmt = m_db.prepare(query.to_string());
-
+
var results = new Gee.ArrayList<Category>();
while(stmt.step () == Sqlite.ROW)
{
string catID = stmt.column_text(0);
-
+
if(feeds == null || showCategory(catID, feeds))
{
var category = new Category(
@@ -921,18 +921,18 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
stmt.column_text(4),
stmt.column_int(5)
);
-
+
results.add(category);
}
}
-
+
return results;
}
-
+
public Gee.List<Article> readUnfetchedArticles()
{
var rows = m_db.execute("SELECT articleID, url, preview, html, feedID FROM articles WHERE contentFetched = 0");
-
+
var articles = new Gee.LinkedList<Article>();
foreach(var row in rows)
{
@@ -951,11 +951,11 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
}
return articles;
}
-
+
public QueryBuilder articleQuery(string id, FeedListType selectedType, ArticleListState state, string searchTerm)
{
string order_by = ((ArticleListSort)Settings.general().get_enum("articlelist-sort-by") == ArticleListSort.RECEIVED) ? "rowid" : "date";
-
+
var query = new QueryBuilder(QueryType.SELECT, "articles");
query.select_field("ROWID");
query.select_field("feedID");
@@ -968,7 +968,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
query.select_field("marked");
query.select_field("date");
query.select_field("guidHash");
-
+
if(selectedType == FeedListType.FEED && id != FeedID.ALL.to_string())
{
query.where_equal_string("feedID", id);
@@ -985,7 +985,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
{
query.where_in_strings("articleID", read_taggings_by_tag_id(id));
}
-
+
if(state == ArticleListState.UNREAD)
{
query.where_equal_int("unread", ArticleStatus.UNREAD.to_int());
@@ -994,7 +994,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
{
query.where_equal_int("marked", ArticleStatus.MARKED.to_int());
}
-
+
if(searchTerm != "")
{
if(searchTerm.has_prefix("title: "))
@@ -1014,40 +1014,40 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
query.where("articleID IN (SELECT articleID FROM fts_table WHERE fts_table MATCH '%s')".printf(Utils.prepareSearchQuery(searchTerm)));
}
}
-
+
bool desc = true;
if(Settings.general().get_boolean("articlelist-oldest-first") && state == ArticleListState.UNREAD)
{
desc = false;
}
-
+
query.order_by(order_by, desc);
-
+
return query;
}
-
+
public Gee.List<Article> read_articles(string id, FeedListType selectedType, ArticleListState state, string searchTerm, uint limit = 20, uint offset = 0, int searchRows = 0)
requires (limit > 0)
{
var query = articleQuery(id, selectedType, state, searchTerm);
-
+
string desc = "DESC";
if(Settings.general().get_boolean("articlelist-oldest-first") && state == ArticleListState.UNREAD)
{
desc = "ASC";
}
-
+
if(searchRows != 0)
{
string order_by = ((ArticleListSort)Settings.general().get_enum("articlelist-sort-by") == ArticleListSort.RECEIVED) ? "rowid" : "date";
query.where(@"articleID in (SELECT articleID FROM articles ORDER BY $order_by $desc LIMIT $searchRows)");
}
-
+
query.limit(limit);
query.offset(offset);
-
+
Sqlite.Statement stmt = m_db.prepare(query.to_string());
-
+
var results = new Gee.LinkedList<Article>();
while (stmt.step () == Sqlite.ROW)
{
@@ -1068,7 +1068,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object {
stmt.column_text(10) // guid
));
}
-
+
return results;
}
}
diff --git a/src/DataBaseWriteAccess.vala b/src/DataBaseWriteAccess.vala
index d0357776..26274b7f 100644
--- a/src/DataBaseWriteAccess.vala
+++ b/src/DataBaseWriteAccess.vala
@@ -14,7 +14,7 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.DataBase : DataBaseReadOnly {
-
+
public static new DataBase writeAccess()
{
var database = new DataBase();
@@ -22,25 +22,25 @@ public class FeedReader.DataBase : DataBaseReadOnly {
{
database.init();
}
-
+
return database;
}
-
+
public static new DataBaseReadOnly readOnly()
{
return writeAccess() as DataBaseReadOnly;
}
-
+
public DataBase(string dbFile = "feedreader-%01i.db".printf(Constants.DB_SCHEMA_VERSION))
{
base(dbFile);
}
-
+
public void checkpoint()
{
m_db.checkpoint();
}
-
+
public bool resetDB()
{
Logger.warning("resetDB");
@@ -53,10 +53,10 @@ public class FeedReader.DataBase : DataBaseReadOnly {
m_db.simple_query("DROP TABLE main.categories");
m_db.simple_query("DROP TABLE main.feeds");
m_db.simple_query("VACUUM");
-
+
string query = "PRAGMA INTEGRITY_CHECK";
Sqlite.Statement stmt = m_db.prepare(query);
-
+
int cols = stmt.column_count ();
while (stmt.step () == Sqlite.ROW) {
for (int i = 0; i < cols; i++) {
@@ -70,19 +70,19 @@ public class FeedReader.DataBase : DataBaseReadOnly {
stmt.reset();
return true;
}
-
+
public void updateFTS()
{
m_db.simple_query("INSERT INTO fts_table(fts_table) VALUES('rebuild')");
}
-
+
public void springCleaning()
{
m_db.simple_query("VACUUM");
var now = new DateTime.now_local();
Settings.state().set_int("last-spring-cleaning", (int)now.to_unix());
}
-
+
public void dropOldArticles(int weeks)
{
var query = new QueryBuilder(QueryType.SELECT, "main.articles");
@@ -95,13 +95,13 @@ public class FeedReader.DataBase : DataBaseReadOnly {
int syncCount = Settings.general().get_int("max-articles");
query.where(@"rowid BETWEEN 1 AND (SELECT rowid FROM articles ORDER BY rowid DESC LIMIT 1 OFFSET $syncCount)");
}
-
+
Sqlite.Statement stmt = m_db.prepare(query.to_string());
while (stmt.step () == Sqlite.ROW) {
delete_article(stmt.column_text(0), stmt.column_text(1));
}
}
-
+
private void delete_article(string articleID, string feedID)
{
Logger.info(@"Deleting article \"$articleID\"");
@@ -110,17 +110,17 @@ public class FeedReader.DataBase : DataBaseReadOnly {
string folder_path = GLib.Environment.get_user_data_dir() + @"/feedreader/data/images/$feedID/$articleID/";
Utils.remove_directory(folder_path);
}
-
+
public void dropTag(Tag tag)
{
m_db.execute("DELETE FROM main.tags WHERE tagID = ?", { tag.getTagID() });
m_db.execute("DELETE FROM main.taggings WHERE tagID = ?", { tag.getTagID() });
}
-
+
public void write_feeds(Gee.Collection<Feed> feeds)
{
m_db.simple_query("BEGIN TRANSACTION");
-
+
var query = new QueryBuilder(QueryType.INSERT_OR_REPLACE, "main.feeds");
query.insert_param("feed_id", "$FEEDID");
query.insert_param("name", "$FEEDNAME");
@@ -129,9 +129,9 @@ public class FeedReader.DataBase : DataBaseReadOnly {
query.insert_int("subscribed", 1);
query.insert_param("xmlURL", "$XMLURL");
query.insert_param("iconURL", "$ICONURL");
-
+
Sqlite.Statement stmt = m_db.prepare(query.to_string());
-
+
int feedID_pos = stmt.bind_parameter_index("$FEEDID");
int feedName_pos = stmt.bind_parameter_index("$FEEDNAME");
int feedURL_pos = stmt.bind_parameter_index("$FEEDURL");
@@ -144,7 +144,7 @@ public class FeedReader.DataBase : DataBaseReadOnly {
assert (catID_pos > 0);
assert (xmlURL_pos > 0);
assert (iconURL_pos > 0);
-
+
foreach(var feed_item in feeds)
{
stmt.bind_text(feedID_pos, feed_item.getFeedID());
@@ -153,80 +153,80 @@ public class FeedReader.DataBase : DataBaseReadOnly {
stmt.bind_text(catID_pos, StringUtils.join(feed_item.getCatIDs(), ","));
stmt.bind_text(xmlURL_pos, feed_item.getXmlUrl());
stmt.bind_text(iconURL_pos, feed_item.getIconURL());
-
+
while(stmt.step() == Sqlite.ROW) {}
stmt.reset();
}
-
+
m_db.simple_query("COMMIT TRANSACTION");
}
-
+
public void write_tag(Tag tag)
{
var list = new Gee.ArrayList<Tag>();
list.add(tag);
write_tags(list);
}
-
+
public void write_tags(Gee.Collection<Tag> tags)
{
m_db.simple_query("BEGIN TRANSACTION");
-
+
var query = new QueryBuilder(QueryType.INSERT_OR_IGNORE, "main.tags");
query.insert_param("tagID", "$TAGID");
query.insert_param("title", "$LABEL");
query.insert_int("\"exists\"", 1);
query.insert_param("color", "$COLOR");
-
+
Sqlite.Statement stmt = m_db.prepare(query.to_string());
-
+
int tagID_position = stmt.bind_parameter_index("$TAGID");
int label_position = stmt.bind_parameter_index("$LABEL");
int color_position = stmt.bind_parameter_index("$COLOR");
assert (tagID_position > 0);
assert (label_position > 0);
assert (color_position > 0);
-
+
foreach(var tag_item in tags)
{
stmt.bind_text(tagID_position, tag_item.getTagID());
stmt.bind_text(label_position, tag_item.getTitle());
stmt.bind_int (color_position, tag_item.getColor());
-
+
while(stmt.step() == Sqlite.ROW) {}
stmt.reset ();
}
-
+
m_db.simple_query("COMMIT TRANSACTION");
}
-
+
public void update_tag(Tag tag)
{
update_tags(ListUtils.single(tag));
-
+
if(FeedServer.get_default().tagIDaffectedByNameChange())
{
string newID = tag.getTagID().replace(tag.getTitle(), tag.getTitle());
m_db.execute("UPDATE tags SET tagID = ? WHERE tagID = ?", { newID, tag.getTagID() });
}
}
-
+
public void update_tags(Gee.List<Tag> tags)
{
m_db.simple_query("BEGIN TRANSACTION");
-
+
var query = new QueryBuilder(QueryType.UPDATE, "main.tags");
query.update_param("title", "$TITLE");
query.update_int("\"exists\"", 1);
query.where_equal_param("tagID", "$TAGID");
-
+
Sqlite.Statement stmt = m_db.prepare(query.to_string());
-
+
int title_position = stmt.bind_parameter_index("$TITLE");
int tagID_position = stmt.bind_parameter_index("$TAGID");
assert (title_position > 0);
assert (tagID_position > 0);
-
+
foreach(var tag_item in tags)
{
stmt.bind_text(title_position, tag_item.getTitle());
@@ -234,15 +234,15 @@ public class FeedReader.DataBase : DataBaseReadOnly {
while (stmt.step () == Sqlite.ROW) {}
stmt.reset ();
}
-
+
m_db.simple_query("COMMIT TRANSACTION");
}
-
-
+
+
public void write_categories(Gee.List<Category> categories)
{
m_db.simple_query("BEGIN TRANSACTION");
-
+
var query = new QueryBuilder(QueryType.INSERT_OR_REPLACE, "main.categories");
query.insert_param("categorieID", "$CATID");
query.insert_param("title", "$FEEDNAME");
@@ -250,9 +250,9 @@ public class FeedReader.DataBase : DataBaseReadOnly {
query.insert_int("\"exists\"", 1);
query.insert_param("Parent", "$PARENT");
query.insert_param("Level", "$LEVEL");
-
+
Sqlite.Statement stmt = m_db.prepare(query.to_string());
-
+
int catID_position = stmt.bind_parameter_index("$CATID");
int feedName_position = stmt.bind_parameter_index("$FEEDNAME");
int orderID_position = stmt.bind_parameter_index("$ORDERID");
@@ -263,7 +263,7 @@ public class FeedReader.DataBase : DataBaseReadOnly {
assert (orderID_position > 0);
assert (parent_position > 0);
assert (level_position > 0);
-
+
foreach(var cat_item in categories)
{
stmt.bind_text(catID_position, cat_item.getCatID());
@@ -271,14 +271,14 @@ public class FeedReader.DataBase : DataBaseReadOnly {
stmt.bind_int (orderID_position, cat_item.getOrderID());
stmt.bind_text(parent_position, cat_item.getParent());
stmt.bind_int (level_position, cat_item.getLevel());
-
+
while (stmt.step () == Sqlite.ROW) {}
stmt.reset ();
}
-
+
m_db.simple_query("COMMIT TRANSACTION");
}
-
+
public void updateArticlesByID(Gee.List<string> ids, string field)
{
// first reset all articles
@@ -292,13 +292,13 @@ public class FeedReader.DataBase : DataBaseReadOnly {
reset_query.update_int(field, ArticleStatus.UNMARKED.to_int());
}
m_db.simple_query(reset_query.to_string());
-
-
+
+
m_db.simple_query("BEGIN TRANSACTION");
-
+
// then reapply states of the synced articles
var update_query = new QueryBuilder(QueryType.UPDATE, "main.articles");
-
+
if(field == "unread")
{
update_query.update_int(field, ArticleStatus.UNREAD.to_int());
@@ -307,25 +307,25 @@ public class FeedReader.DataBase : DataBaseReadOnly {
{
update_query.update_int(field, ArticleStatus.MARKED.to_int());
}
-
+
update_query.where_equal_param("articleID", "$ARTICLEID");
-
+
Sqlite.Statement stmt = m_db.prepare(update_query.to_string());
-
+
int articleID_position = stmt.bind_parameter_index("$ARTICLEID");
assert (articleID_position > 0);
-
-
+
+
foreach(string id in ids)
{
stmt.bind_text(articleID_position, id);
while(stmt.step() != Sqlite.DONE) {}
stmt.reset();
}
-
+
m_db.simple_query("COMMIT TRANSACTION");
}
-
+
public void writeContent(Article article)
{
var update_query = new QueryBuilder(QueryType.UPDATE, "main.articles");
@@ -333,39 +333,39 @@ public class FeedReader.DataBase : DataBaseReadOnly {
update_query.update_param("preview", "$PREVIEW");
update_query.update_int("contentFetched", 1);
update_query.where_equal_string("articleID", article.getArticleID());
-
+
Sqlite.Statement stmt = m_db.prepare(update_query.to_string());
-
+
int html_position = stmt.bind_parameter_index("$HTML");
int preview_position = stmt.bind_parameter_index("$PREVIEW");
assert (html_position > 0);
assert (preview_position > 0);
-
-
+
+
stmt.bind_text(html_position, article.getHTML());
stmt.bind_text(preview_position, article.getPreview());
-
+
while(stmt.step() != Sqlite.DONE) {}
stmt.reset();
}
-
+
public void update_article(Article article)
{
update_articles(ListUtils.single(article));
}
-
+
public void update_articles(Gee.List<Article> articles)
{
m_db.simple_query("BEGIN TRANSACTION");
-
+
var update_query = new QueryBuilder(QueryType.UPDATE, "main.articles");
update_query.update_param("unread", "$UNREAD");
update_query.update_param("marked", "$MARKED");
update_query.update_param("lastModified", "$LASTMODIFIED");
update_query.where_equal_param("articleID", "$ARTICLEID");
-
+
Sqlite.Statement stmt = m_db.prepare(update_query.to_string());
-
+
int unread_position = stmt.bind_parameter_index("$UNREAD");
int marked_position = stmt.bind_parameter_index("$MARKED");
int modified_position = stmt.bind_parameter_index("$LASTMODIFIED");
@@ -374,45 +374,45 @@ public class FeedReader.DataBase : DataBaseReadOnly {
assert (marked_position > 0);
assert (modified_position > 0);
assert (articleID_position > 0);
-
-
+
+
foreach(Article a in articles)
{
var unread = ActionCache.get_default().checkRead(a);
var marked = ActionCache.get_default().checkStarred(a.getArticleID(), a.getMarked());
-
+
if(unread != ArticleStatus.READ && unread != ArticleStatus.UNREAD)
{
Logger.warning(@"DataBase.update_articles: writing invalid unread status $unread for article " + a.getArticleID());
}
-
+
if(marked != ArticleStatus.MARKED && marked != ArticleStatus.UNMARKED)
{
Logger.warning(@"DataBase.update_articles: writing invalid marked status $marked for article " + a.getArticleID());
}
-
+
stmt.bind_int (unread_position, unread);
stmt.bind_int (marked_position, marked);
stmt.bind_int (modified_position, a.getLastModified());
stmt.bind_text(articleID_position, a.getArticleID());
-
+
while(stmt.step() != Sqlite.DONE) {}
stmt.reset();
-
+
write_taggings(a);
}
-
+
m_db.simple_query("COMMIT TRANSACTION");
}
-
-
+
+
public void write_articles(Gee.List<Article> articles)
{
Utils.generatePreviews(articles);
Utils.checkHTML(articles);
-
+
m_db.simple_query("BEGIN TRANSACTION");
-
+
var query = new QueryBuilder(QueryType.INSERT_OR_IGNORE, "main.articles");
query.insert_param("articleID", "$ARTICLEID");
query.insert_param("feedID", "$FEEDID");
@@ -427,9 +427,9 @@ public class FeedReader.DataBase : DataBaseReadOnly {
query.insert_param("guidHash", "$GUIDHASH");
query.insert_param("lastModified", "$LASTMODIFIED");
query.insert_int("contentFetched", 0);
-
+
Sqlite.Statement stmt = m_db.prepare(query.to_string());
-
+
int articleID_position = stmt.bind_parameter_index("$ARTICLEID");
int feedID_position = stmt.bind_parameter_index("$FEEDID");
int url_position = stmt.bind_parameter_index("$URL");
@@ -442,7 +442,7 @@ public class FeedReader.DataBase : DataBaseReadOnly {
int date_position = stmt.bind_parameter_index("$DATE");
int guidHash_position = stmt.bind_parameter_index("$GUIDHASH");
int modified_position = stmt.bind_parameter_index("$LASTMODIFIED");
-
+
assert (articleID_position > 0);
assert (feedID_position > 0);
assert (url_position > 0);
@@ -455,7 +455,7 @@ public class FeedReader.DataBase : DataBaseReadOnly {
assert (date_position > 0);
assert (guidHash_position > 0);
assert (modified_position > 0);
-
+
foreach(var article in articles)
{
// if article time is in the future
@@ -464,14 +464,14 @@ public class FeedReader.DataBase : DataBaseReadOnly {
{
article.SetDate(now);
}
-
+
int? weeks = ((DropArticles)Settings.general().get_enum("drop-articles-after")).to_weeks();
if(weeks != null && article.getDate().compare(now.add_weeks(-(int)weeks)) == -1)
{
Logger.info("Ignoring old article: %s".printf(article.getTitle()));
continue;
}
-
+
stmt.bind_text(articleID_position, article.getArticleID());
stmt.bind_text(feedID_position, article.getFeedID());
stmt.bind_text(url_position, article.getURL());
@@ -484,69 +484,69 @@ public class FeedReader.DataBase : DataBaseReadOnly {
stmt.bind_int64(date_position, article.getDate().to_unix());
stmt.bind_text(guidHash_position, article.getHash());
stmt.bind_int (modified_position, article.getLastModified());
-
+
while(stmt.step() != Sqlite.DONE) {}
stmt.reset();
-
+
write_enclosures(article);
write_taggings(article);
}
-
+
m_db.simple_query("COMMIT TRANSACTION");
}
-
+
private void write_taggings(Article article)
{
var query = new QueryBuilder(QueryType.INSERT_OR_REPLACE, "main.taggings");
query.insert_param("articleID", "$ARTICLEID");
query.insert_param("tagID", "$TAGID");
-
+
Sqlite.Statement stmt = m_db.prepare(query.to_string());
-
+
int articleID_position = stmt.bind_parameter_index("$ARTICLEID");
int tagID_position = stmt.bind_parameter_index("$TAGID");
-
+
assert (articleID_position > 0);
assert (tagID_position > 0);
-
+
foreach(string tagID in article.getTagIDs())
{
stmt.bind_text(articleID_position, article.getArticleID());
stmt.bind_text(tagID_position, tagID);
-
+
while(stmt.step() != Sqlite.DONE) {}
stmt.reset();
}
}
-
+
private void write_enclosures(Article article)
{
var query = new QueryBuilder(QueryType.INSERT_OR_REPLACE, "main.Enclosures");
query.insert_param("articleID", "$ARTICLEID");
query.insert_param("url", "$URL");
query.insert_param("type", "$TYPE");
-
+
Sqlite.Statement stmt = m_db.prepare(query.to_string());
-
+
int articleID_position = stmt.bind_parameter_index("$ARTICLEID");
int url_position = stmt.bind_parameter_index("$URL");
int type_position = stmt.bind_parameter_index("$TYPE");
-
+
assert (articleID_position > 0);
assert (url_position > 0);
assert (type_position > 0);
-
+
foreach(Enclosure enc in article.getEnclosures())
{
stmt.bind_text(articleID_position, article.getArticleID());
stmt.bind_text(url_position, enc.get_url());
stmt.bind_int (type_position, enc.get_enclosure_type());
-
+
while(stmt.step() != Sqlite.DONE) {}
stmt.reset();
}
}
-
+
public void markCategorieRead(string catID)
{
var query = new QueryBuilder(QueryType.UPDATE, "main.articles");
@@ -554,64 +554,64 @@ public class FeedReader.DataBase : DataBaseReadOnly {
query.where_in_strings("feedID", getFeedIDofCategorie(catID));
m_db.simple_query(query.to_string());
}
-
+
public void markFeedRead(string feedID)
{
m_db.execute("UPDATE main.articles SET unread = ? WHERE feedID = ?", { ArticleStatus.READ, feedID });
}
-
+
public void markAllRead()
{
m_db.execute("UPDATE main.articles SET unread = ?", { ArticleStatus.READ });
}
-
+
public void reset_subscribed_flag()
{
m_db.simple_query("UPDATE main.feeds SET \"subscribed\" = 0");
}
-
+
public void reset_exists_tag()
{
m_db.simple_query("UPDATE main.tags SET \"exists\" = 0");
}
-
+
public void reset_exists_flag()
{
m_db.simple_query("UPDATE main.categories SET \"exists\" = 0");
}
-
+
public void delete_unsubscribed_feeds()
{
Logger.warning("DataBase: Deleting unsubscribed feeds");
m_db.simple_query("DELETE FROM main.feeds WHERE \"subscribed\" = 0");
}
-
+
public void delete_nonexisting_categories()
{
Logger.warning("DataBase: Deleting nonexisting categories");
m_db.simple_query("DELETE FROM main.categories WHERE \"exists\" = 0");
}
-
+
public void delete_nonexisting_tags()
{
Logger.warning("DataBase: Deleting nonexisting tags");
m_db.simple_query("DELETE FROM main.tags WHERE \"exists\" = 0");
}
-
+
public void delete_articles_without_feed()
{
Logger.warning("DataBase: Deleting articles without feed");
var query = new QueryBuilder(QueryType.SELECT, "main.feeds");
query.select_field("feed_id");
query.where_equal_int("subscribed", 0);
-
+
Sqlite.Statement stmt = m_db.prepare(query.to_string());
while(stmt.step () == Sqlite.ROW)
{
delete_articles(stmt.column_text(0));
}
}
-
+
public void delete_articles(string feedID)
{
Logger.warning(@"DataBase: Deleting all articles of feed \"$feedID\"");
@@ -620,12 +620,12 @@ public class FeedReader.DataBase : DataBaseReadOnly {
string folder_path = GLib.Environment.get_user_data_dir() + @"/feedreader/data/images/$feedID/";
Utils.remove_directory(folder_path);
}
-
+
public void delete_category(string catID)
{
m_db.execute("DELETE FROM main.categories WHERE categorieID = ?", { catID });
}
-
+
public void rename_category(string catID, string newName)
{
if(FeedServer.get_default().tagIDaffectedByNameChange())
@@ -634,7 +634,7 @@ public class FeedReader.DataBase : DataBaseReadOnly {
string newID = catID.replace(cat.getTitle(), newName);
var query = "UPDATE categories SET categorieID = ?, title = ? WHERE categorieID = ?";
m_db.execute(query, {newID, newName, catID });
-
+
query = "UPDATE feeds SET category_id = replace(category_id, ?, ?) WHERE instr(category_id, ?)";
m_db.execute(query, { catID, newID, catID });
}
@@ -644,79 +644,79 @@ public class FeedReader.DataBase : DataBaseReadOnly {
m_db.execute(query, { newName, catID });
}
}
-
+
public void move_category(string catID, string newParentID)
{
var parent = read_category(newParentID);
var query = "UPDATE categories SET Parent = ?, Level = ? WHERE categorieID = ?";
m_db.execute(query, { newParentID, parent.getLevel() + 1, catID });
}
-
+
public void rename_feed(string feedID, string newName)
{
var query = "UPDATE feeds SET name = ? WHERE feed_id = ?";
m_db.execute(query, { newName, feedID });
}
-
+
public void move_feed(string feedID, string currentCatID, string? newCatID = null)
{
var Feed = read_feed(feedID);
var categories = Feed.getCatIDs();
categories.remove(currentCatID);
-
+
if(newCatID != null)
{
categories.add(newCatID);
}
-
+
string catString = StringUtils.join(categories, ",");
-
+
var query = "UPDATE feeds SET category_id = ? WHERE feed_id = ?";
m_db.execute(query, { catString, feedID });
}
-
+
public void removeCatFromFeed(string feedID, string catID)
{
var feed = read_feed(feedID);
m_db.execute("UPDATE feeds SET category_id = ? WHERE feed_id = ?",
{ feed.getCatString().replace(catID + ",", ""), feedID });
}
-
+
public void delete_feed(string feedID)
{
m_db.execute("DELETE FROM feeds WHERE feed_id = ?", { feedID });
delete_articles(feedID);
}
-
+
public void addCachedAction(CachedActions action, string id, string? argument = "")
{
m_db.simple_query("BEGIN TRANSACTION");
-
+
var query = new QueryBuilder(QueryType.INSERT_OR_IGNORE, "main.CachedActions");
query.insert_param("action", "$ACTION");
query.insert_param("id", "$ID");
query.insert_param("argument", "$ARGUMENT");
-
+
Sqlite.Statement stmt = m_db.prepare(query.to_string());
-
+
int action_position = stmt.bind_parameter_index("$ACTION");
int id_position = stmt.bind_parameter_index("$ID");
int argument_position = stmt.bind_parameter_index("$ARGUMENT");
assert (action_position > 0);
assert (id_position > 0);
assert (argument_position > 0);
-
+
stmt.bind_int (action_position, action);
stmt.bind_text(id_position, id);
stmt.bind_text(argument_position, argument);
-
+
while (stmt.step () == Sqlite.ROW) {}
stmt.reset ();
-
+
m_db.simple_query("COMMIT TRANSACTION");
}
-
-
+
+
public Gee.List<CachedAction> readCachedActions()
{
var query = "SELECT * FROM CachedActions";
@@ -733,13 +733,13 @@ public class FeedReader.DataBase : DataBaseReadOnly {
}
return actions;
}
-
+
public void resetCachedActions()
{
Logger.warning("resetCachedActions");
m_db.simple_query("DELETE FROM CachedActions");
}
-
+
public bool cachedActionNecessary(CachedAction action)
{
var query = "SELECT COUNT(*) FROM CachedActions WHERE argument = ? AND id = ? AND action = ?";
@@ -747,11 +747,11 @@ public class FeedReader.DataBase : DataBaseReadOnly {
assert(rows.size == 1 && rows[0].size == 1);
return rows[0][0].to_int() == 0;
}
-
+
public void deleteOppositeCachedAction(CachedAction action)
{
var query = "DELETE FROM CachedActions WHERE argument = ? AND id = ? AND action = ?";
m_db.execute(query, { action.getArgument(), action.getID(), action.opposite() });
}
-
+
}
diff --git a/src/Enums.vala b/src/Enums.vala
index d86b5721..1fe545f9 100644
--- a/src/Enums.vala
+++ b/src/Enums.vala
@@ -14,30 +14,30 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
namespace FeedReader {
-
+
public enum FeedID {
SEPARATOR = -77,
ALL,
CATEGORIES;
-
+
public string to_string()
{
return ((int)this).to_string();
}
}
-
+
public enum ArticleListState {
ALL,
UNREAD,
MARKED
}
-
+
public enum DragTarget {
TAG,
FEED,
CAT
}
-
+
public enum ConsoleColor {
BLACK,
RED,
@@ -48,14 +48,14 @@ namespace FeedReader {
CYAN,
WHITE,
}
-
+
public enum LogMessage {
ERROR,
WARNING,
INFO,
DEBUG
}
-
+
public enum ConnectionError {
SUCCESS,
NO_RESPONSE,
@@ -66,24 +66,24 @@ namespace FeedReader {
UNAUTHORIZED,
UNKNOWN
}
-
+
public enum ArticleStatus {
READ = 8,
UNREAD,
UNMARKED,
MARKED,
ALL;
-
+
public string to_string()
{
return ((int)this).to_string();
}
-
+
public int to_int()
{
return (int)this;
}
-
+
public string? column()
{
switch(this) {
@@ -98,7 +98,7 @@ namespace FeedReader {
}
}
}
-
+
public enum LoginResponse {
SUCCESS,
MISSING_USER,
@@ -117,12 +117,12 @@ namespace FeedReader {
CA_ERROR,
PLUGIN_NEEDED
}
-
+
public enum ArticleListSort {
RECEIVED,
DATE
}
-
+
public enum CachedActions {
NONE,
MARK_READ,
@@ -133,50 +133,50 @@ namespace FeedReader {
MARK_READ_CATEGORY,
MARK_READ_ALL
}
-
+
public enum MediaType {
VIDEO,
AUDIO
}
-
+
public enum DisplayPosition {
ALL,
POS,
LEFT
}
-
+
public enum MouseButton {
LEFT = 1,
MIDDLE,
RIGHT,
}
-
+
public enum ArticleTheme {
DEFAULT,
SPRING,
MIDNIGHT,
PARCHMENT
}
-
+
public enum FeedListTheme {
GTK,
DARK,
ELEMENTARY
}
-
+
public enum FontSize {
SMALL,
NORMAL,
LARGE,
HUGE
}
-
+
public enum DropArticles {
NEVER,
ONE_WEEK,
ONE_MONTH,
SIX_MONTHS;
-
+
public int? to_weeks()
{
switch(this)
@@ -193,7 +193,7 @@ namespace FeedReader {
assert_not_reached();
}
}
-
+
public DateTime? to_start_date()
{
int? weeks = to_weeks();
@@ -201,52 +201,52 @@ namespace FeedReader {
{
return null;
}
-
+
return new DateTime.now_utc().add_weeks(-(int)weeks);
}
}
-
+
public enum FeedListType {
ALL_FEEDS,
CATEGORY,
FEED,
TAG
}
-
+
public enum FeedListSort {
RECEIVED,
ALPHABETICAL
}
-
+
public enum CategoryID {
NONE = -99,
MASTER = -2,
TAGS = -3,
NEW = -4;
-
+
public string to_string()
{
return ((int)this).to_string();
}
}
-
+
public enum ArticleListBalance {
NONE,
TOP,
BOTTOM
}
-
+
public enum ScrollDirection {
UP,
DOWN
}
-
+
public enum EnclosureType {
IMAGE,
VIDEO,
AUDIO,
FILE;
-
+
public static EnclosureType from_string(string? str)
{
if (str != null)
@@ -267,7 +267,7 @@ namespace FeedReader {
return FILE;
}
}
-
+
[Flags] public enum BackendFlags {
LOCAL,
HOSTED,
diff --git a/src/FavIcon.vala b/src/FavIcon.vala
index fe177802..1afa0c41 100644
--- a/src/FavIcon.vala
+++ b/src/FavIcon.vala
@@ -16,14 +16,14 @@ public class FeedReader.FavIcon : GLib.Object
{
private static string m_icon_path = GLib.Environment.get_user_data_dir() + "/feedreader/data/feed_icons/";
private static Gee.Map<string?, FavIcon?> m_map = null;
-
+
public static FavIcon for_feed(Feed? feed)
{
if(m_map == null)
{
m_map = new Gee.HashMap<string?, FavIcon?>();
}
-
+
var feed_id = feed != null ? feed.getFeedID() : null;
var icon = m_map.get(feed_id);
if(icon == null)
@@ -31,10 +31,10 @@ public class FeedReader.FavIcon : GLib.Object
icon = new FavIcon(feed);
m_map.set(feed_id, icon);
}
-
+
return icon;
}
-
+
public static void delete_feed(string feed_id)
ensures (m_map == null || !m_map.has_key(feed_id))
{
@@ -42,36 +42,36 @@ public class FeedReader.FavIcon : GLib.Object
{
return;
}
-
+
FavIcon icon;
m_map.unset(feed_id, out icon);
if(icon == null)
{
return;
}
-
+
icon.delete.begin((obj,res) => {
icon.delete.end(res);
});
}
-
+
private Feed? m_feed;
private Gee.Promise<Gdk.Pixbuf?> m_pixbuf = null;
private ResourceMetadata m_metadata;
-
+
public signal void surface_changed(Feed feed, Cairo.Surface surface);
-
+
private FavIcon(Feed? feed)
{
m_feed = feed;
}
-
+
private int get_scale_factor()
ensures (result > 0)
{
return MainWindow.get_default().get_style_context().get_scale();
}
-
+
private Cairo.Surface create_surface_from_pixbuf(Gdk.Pixbuf pixbuf)
requires (pixbuf.width > 0)
requires (pixbuf.height > 0)
@@ -79,7 +79,7 @@ public class FeedReader.FavIcon : GLib.Object
{
return Gdk.cairo_surface_create_from_pixbuf(pixbuf, get_scale_factor(), null);
}
-
+
public async Cairo.Surface? get_surface()
{
// This can happen if an API gives us weird data by returning an article
@@ -88,7 +88,7 @@ public class FeedReader.FavIcon : GLib.Object
{
return null;
}
-
+
// wait for ready + expired so we don't make a bunch of requests at once
if(m_pixbuf == null || (m_pixbuf.future.ready && m_metadata.is_expired()))
{
@@ -102,7 +102,7 @@ public class FeedReader.FavIcon : GLib.Object
{
return null;
}
-
+
return create_surface_from_pixbuf(pixbuf);
}
catch(Error e)
@@ -111,7 +111,7 @@ public class FeedReader.FavIcon : GLib.Object
return null;
}
}
-
+
private async void load()
{
try
@@ -121,10 +121,10 @@ public class FeedReader.FavIcon : GLib.Object
{
return;
}
-
+
var pixbuf = yield new Gdk.Pixbuf.from_stream_async(stream);
stream.close();
-
+
if(pixbuf.get_height() <= 1 && pixbuf.get_width() <= 1)
{
Logger.warning("FavIcon: Icon for feed %s is too small".printf(m_feed.getTitle()));
@@ -132,7 +132,7 @@ public class FeedReader.FavIcon : GLib.Object
}
int scale = get_scale_factor();
pixbuf = pixbuf.scale_simple(24 * scale, 24 * scale, Gdk.InterpType.BILINEAR);
-
+
m_pixbuf.set_value(pixbuf);
if(pixbuf != null)
{
@@ -151,14 +151,14 @@ public class FeedReader.FavIcon : GLib.Object
}
}
}
-
+
private InputStream? try_load_data_uri(string? icon_url)
{
if(icon_url == null || !icon_url.has_prefix("data"))
{
return null;
}
-
+
// LibSoup doesn't seem to handle data URI's properly, so handle them
// ourselves..
int comma = icon_url.index_of_char(',');
@@ -180,32 +180,32 @@ public class FeedReader.FavIcon : GLib.Object
}
return new MemoryInputStream.from_data(data);
}
-
+
private string fileNamePrefix()
requires(m_feed != null)
{
return m_icon_path + m_feed.getFeedFileName();
}
-
+
private string iconFileName()
{
string filename_prefix = fileNamePrefix();
return @"$filename_prefix.ico";
}
-
+
private string metadataFileName()
{
string filename_prefix = fileNamePrefix();
return @"$filename_prefix.txt";
}
-
+
private async void delete()
{
if (m_feed == null)
{
return;
}
-
+
try
{
var icon_file = File.new_for_path(iconFileName());
@@ -216,7 +216,7 @@ public class FeedReader.FavIcon : GLib.Object
var feed_id = m_feed.getFeedID();
Logger.warning(@"Error deleting icon for feed $feed_id: " + e.message);
}
-
+
try
{
var metadata_file = File.new_for_path(metadataFileName());
@@ -228,7 +228,7 @@ public class FeedReader.FavIcon : GLib.Object
Logger.warning(@"Error deleting icon metadata for feed $feed_id: " + e.message);
}
}
-
+
private async InputStream? downloadFavIcon(GLib.Cancellable? cancellable = null) throws GLib.Error
requires(m_feed != null)
{
@@ -237,23 +237,23 @@ public class FeedReader.FavIcon : GLib.Object
{
return datastream;
}
-
+
string icon_filename = iconFileName();
string metadata_filename = metadataFileName();
-
+
if(!yield Utils.ensure_path(m_icon_path))
{
return null;
}
-
+
m_metadata = yield ResourceMetadata.from_file_async(metadata_filename);
DateTime? expires = m_metadata.expires;
-
+
if(cancellable != null && cancellable.is_cancelled())
{
return null;
}
-
+
bool use_cached = false;
if(!m_metadata.is_expired())
{
@@ -277,16 +277,16 @@ public class FeedReader.FavIcon : GLib.Object
return null;
}
}
-
+
try
{
var obvious_icons = new Gee.ArrayList<string>();
-
+
if(m_feed.getIconURL() != null)
{
obvious_icons.add(m_feed.getIconURL());
}
-
+
// try domainname/favicon.ico
var uri = new Soup.URI(m_feed.getURL());
string? siteURL = null;
@@ -294,7 +294,7 @@ public class FeedReader.FavIcon : GLib.Object
{
string hostname = uri.get_host();
siteURL = uri.get_scheme() + "://" + hostname;
-
+
var icon_url = siteURL;
if(!icon_url.has_suffix("/"))
{
@@ -303,7 +303,7 @@ public class FeedReader.FavIcon : GLib.Object
icon_url += "favicon.ico";
obvious_icons.add(icon_url);
}
-
+
// Try to find one of those icons
foreach(var url in obvious_icons)
{
@@ -312,25 +312,25 @@ public class FeedReader.FavIcon : GLib.Object
{
return stream;
}
-
+
if(cancellable != null && cancellable.is_cancelled())
{
return null;
}
}
-
+
// If all else fails, download html and parse to find location of favicon
if(siteURL == null)
{
return null;
}
-
+
var message_html = new Soup.Message("GET", siteURL);
if(Settings.tweaks().get_boolean("do-not-track"))
{
message_html.request_headers.append("DNT", "1");
}
-
+
string html;
try
{
@@ -352,24 +352,24 @@ public class FeedReader.FavIcon : GLib.Object
Logger.debug(@"Utils.downloadFavIcon: parsing html on $siteURL failed");
return null;
}
-
+
try
{
// check for <link rel="icon">
var xpath = grabberUtils.getURL(doc, "//link[@rel='icon']");
-
+
if(xpath == null)
{
// check for <link rel="shortcut icon">
xpath = grabberUtils.getURL(doc, "//link[@rel='shortcut icon']");
}
-
+
if(xpath == null)
{
// check for <link rel="apple-touch-icon">
xpath = grabberUtils.getURL(doc, "//link[@rel='apple-touch-icon']");
}
-
+
if(xpath != null)
{
xpath = grabberUtils.completeURL(xpath, siteURL);
@@ -381,7 +381,7 @@ public class FeedReader.FavIcon : GLib.Object
delete doc;
}
}
-
+
return null;
}
finally
@@ -394,7 +394,7 @@ public class FeedReader.FavIcon : GLib.Object
yield m_metadata.save_to_file_async(metadata_filename);
}
}
-
+
private async InputStream? downloadIcon(string? icon_url, Cancellable? cancellable) throws GLib.Error
{
if(icon_url == "" || icon_url == null || GLib.Uri.parse_scheme(icon_url) == null)
@@ -402,12 +402,12 @@ public class FeedReader.FavIcon : GLib.Object
Logger.warning(@"Utils.downloadIcon: icon_url not valid $icon_url");
return null;
}
-
+
string icon_filename = iconFileName();
-
+
string etag = m_metadata.etag;
string last_modified = m_metadata.last_modified;
-
+
Logger.debug(@"Utils.downloadIcon: url = $icon_url");
var message = new Soup.Message("GET", icon_url);
if(message == null)
@@ -419,7 +419,7 @@ public class FeedReader.FavIcon : GLib.Object
{
message.request_headers.append("DNT", "1");
}
-
+
if(etag != null)
{
message.request_headers.append("If-None-Match", etag);
@@ -428,7 +428,7 @@ public class FeedReader.FavIcon : GLib.Object
{
message.request_headers.append("If-Modified-Since", last_modified);
}
-
+
uint8[]? data;
try
{
@@ -462,10 +462,10 @@ public class FeedReader.FavIcon : GLib.Object
Logger.error("Error writing icon: %s".printf(e.message));
return null;
}
-
+
m_metadata.etag = message.response_headers.get_one("ETag");
m_metadata.last_modified = message.response_headers.get_one("Last-Modified");
-
+
var cache_control = message.response_headers.get_list("Cache-Control");
if(cache_control != null)
{
@@ -482,11 +482,11 @@ public class FeedReader.FavIcon : GLib.Object
m_metadata.expires = expires;
}
}
-
+
m_metadata.last_modified = message.response_headers.get_one("Last-Modified");
return new MemoryInputStream.from_data(data);
}
-
+
Logger.warning(@"Could not download icon for feed: %s $icon_url, got response code $status".printf(m_feed.getFeedID()));
return null;
}
diff --git a/src/FeedReader.vala b/src/FeedReader.vala
index f8bfbe92..4c4df4bc 100644
--- a/src/FeedReader.vala
+++ b/src/FeedReader.vala
@@ -17,48 +17,48 @@ using GLib;
using Gtk;
namespace FeedReader {
-
+
public const string QUICKLIST_ABOUT_STOCK = N_("About FeedReader");
-
+
public class FeedReaderApp : Gtk.Application {
-
+
private MainWindow m_window;
private bool m_online = true;
private static FeedReaderApp? m_app = null;
public static bool m_verbose = false;
public signal void callback (string content);
-
-
+
+
public new static FeedReaderApp get_default()
{
if(m_app == null)
{
m_app = new FeedReaderApp();
}
-
+
return m_app;
}
-
+
public bool isOnline()
{
return m_online;
}
-
+
public void setOnline(bool online)
{
m_online = online;
}
-
+
protected override void startup()
{
Logger.init(m_verbose);
Logger.info("FeedReader " + AboutInfo.version);
-
+
Settings.state().set_boolean("currently-updating", false);
-
+
base.startup();
}
-
+
public override void activate()
{
base.activate();
@@ -67,14 +67,14 @@ namespace FeedReader {
Intl.bindtextdomain (Constants.GETTEXT_PACKAGE, Constants.LOCALE_DIR);
Intl.bind_textdomain_codeset (Constants.GETTEXT_PACKAGE, "UTF-8");
Intl.textdomain (Constants.GETTEXT_PACKAGE);
-
+
if(m_window == null)
{
SetupActions();
m_window = MainWindow.get_default();
m_window.set_icon_name("org.gnome.FeedReader");
Gtk.IconTheme.get_default().add_resource_path("/org/gnome/FeedReader/icons");
-
+
FeedReaderBackend.get_default().newFeedList.connect(() => {
GLib.Idle.add(() => {
Logger.debug("FeedReader: newFeedList");
@@ -82,7 +82,7 @@ namespace FeedReader {
return GLib.Source.REMOVE;
});
});
-
+
FeedReaderBackend.get_default().refreshFeedListCounter.connect(() => {
GLib.Idle.add(() => {
Logger.debug("FeedReader: refreshFeedListCounter");
@@ -90,7 +90,7 @@ namespace FeedReader {
return GLib.Source.REMOVE;
});
});
-
+
FeedReaderBackend.get_default().updateArticleList.connect(() => {
GLib.Idle.add(() => {
Logger.debug("FeedReader: updateArticleList");
@@ -98,7 +98,7 @@ namespace FeedReader {
return GLib.Source.REMOVE;
});
});
-
+
FeedReaderBackend.get_default().syncStarted.connect(() => {
GLib.Idle.add(() => {
Logger.debug("FeedReader: syncStarted");
@@ -107,7 +107,7 @@ namespace FeedReader {
return GLib.Source.REMOVE;
});
});
-
+
FeedReaderBackend.get_default().syncFinished.connect(() => {
GLib.Idle.add(() => {
Logger.debug("FeedReader: syncFinished");
@@ -117,7 +117,7 @@ namespace FeedReader {
return GLib.Source.REMOVE;
});
});
-
+
FeedReaderBackend.get_default().springCleanStarted.connect(() => {
GLib.Idle.add(() => {
Logger.debug("FeedReader: springCleanStarted");
@@ -125,7 +125,7 @@ namespace FeedReader {
return GLib.Source.REMOVE;
});
});
-
+
FeedReaderBackend.get_default().springCleanFinished.connect(() => {
GLib.Idle.add(() => {
Logger.debug("FeedReader: springCleanFinished");
@@ -133,7 +133,7 @@ namespace FeedReader {
return GLib.Source.REMOVE;
});
});
-
+
FeedReaderBackend.get_default().showArticleListOverlay.connect(() => {
GLib.Idle.add(() => {
Logger.debug("FeedReader: showArticleListOverlay");
@@ -141,7 +141,7 @@ namespace FeedReader {
return GLib.Source.REMOVE;
});
});
-
+
FeedReaderBackend.get_default().setOffline.connect(() => {
GLib.Idle.add(() => {
Logger.debug("FeedReader: setOffline");
@@ -153,7 +153,7 @@ namespace FeedReader {
return GLib.Source.REMOVE;
});
});
-
+
FeedReaderBackend.get_default().setOnline.connect(() => {
GLib.Idle.add(() => {
Logger.debug("FeedReader: setOnline");
@@ -165,7 +165,7 @@ namespace FeedReader {
return GLib.Source.REMOVE;
});
});
-
+
FeedReaderBackend.get_default().feedAdded.connect((error, errmsg) => {
GLib.Idle.add(() => {
Logger.debug("FeedReader: feedAdded");
@@ -177,7 +177,7 @@ namespace FeedReader {
return GLib.Source.REMOVE;
});
});
-
+
FeedReaderBackend.get_default().opmlImported.connect(() => {
GLib.Idle.add(() => {
Logger.debug("FeedReader: opmlImported");
@@ -186,7 +186,7 @@ namespace FeedReader {
return GLib.Source.REMOVE;
});
});
-
+
FeedReaderBackend.get_default().updateSyncProgress.connect((progress) => {
GLib.Idle.add(() => {
Logger.debug("FeedReader: updateSyncProgress");
@@ -194,15 +194,15 @@ namespace FeedReader {
return GLib.Source.REMOVE;
});
});
-
+
FeedReaderBackend.get_default().updateBadge();
FeedReaderBackend.get_default().checkOnlineAsync.begin();
}
-
+
m_window.show_all();
m_window.present();
}
-
+
public override int command_line(ApplicationCommandLine command_line)
{
var args = command_line.get_arguments();
@@ -211,42 +211,42 @@ namespace FeedReader {
Logger.debug("FeedReader: callback %s".printf(args[1]));
callback (args[1]);
}
-
+
activate();
-
+
return 0;
}
-
+
protected override void shutdown()
{
Logger.debug("Shutdown!");
Gst.deinit();
base.shutdown();
}
-
+
public void sync()
{
FeedReaderBackend.get_default().startSync();
}
-
+
public void cancelSync()
{
FeedReaderBackend.get_default().cancelSync();
}
-
+
private FeedReaderApp()
{
GLib.Object(application_id: "org.gnome.FeedReader", flags : ApplicationFlags.HANDLES_COMMAND_LINE);
}
-
+
private void SetupActions()
{
var quit_action = new SimpleAction("quit", null);
quit_action.activate.connect(() => {
-
+
MainWindow.get_default().writeInterfaceState(true);
m_window.close();
-
+
if(Settings.state().get_boolean("currently-updating"))
{
Logger.debug("Quit: FeedReader seems to be syncing -> trying to cancel");
@@ -255,20 +255,20 @@ namespace FeedReader {
{
Gtk.main_iteration();
}
-
+
Logger.debug("Quit: Sync cancelled -> shutting down");
}
else
{
Logger.debug("No Sync ongoing -> Quit right away");
}
-
+
FeedReaderApp.get_default().quit();
});
this.add_action(quit_action);
}
}
-
+
public static void show_about(string[] args)
{
Gtk.init(ref args);
@@ -279,12 +279,12 @@ namespace FeedReader {
Gtk.main_quit();
}
});
-
+
dialog.artists = AboutInfo.artists;
dialog.authors = AboutInfo.authors;
dialog.documenters = null;
dialog.translator_credits = AboutInfo.translators;
-
+
dialog.program_name = AboutInfo.programmName;
dialog.comments = AboutInfo.comments;
dialog.copyright = AboutInfo.copyright;
@@ -292,11 +292,11 @@ namespace FeedReader {
dialog.logo_icon_name = AboutInfo.iconName;
dialog.license_type = Gtk.License.GPL_3_0;
dialog.wrap_license = true;
-
+
dialog.website = AboutInfo.website;
dialog.present();
-
+
Gtk.main();
}
-
+
}
diff --git a/src/FeedReaderMain.vala b/src/FeedReaderMain.vala
index 6fc77411..992cdec3 100644
--- a/src/FeedReaderMain.vala
+++ b/src/FeedReaderMain.vala
@@ -14,7 +14,7 @@ namespace FeedReader.Main {
{ "unreadCount", 0, 0, OptionArg.NONE, ref unreadCount, "current count of unread articles in the database", null },
{ null }
};
-
+
private static bool version = false;
private static bool about = false;
private static bool verbose = false;
@@ -25,11 +25,11 @@ namespace FeedReader.Main {
private static string? grabImages = null;
private static string? articleUrl = null;
private static bool unreadCount = false;
-
+
public static int main (string[] args)
{
Ivy.Stacktrace.register_handlers();
-
+
try
{
var opt_context = new OptionContext();
@@ -42,28 +42,28 @@ namespace FeedReader.Main {
print(e.message + "\n");
return 0;
}
-
+
FeedReaderApp.m_verbose = verbose;
-
+
if(version)
{
stdout.printf("Version: %s\n", AboutInfo.version);
stdout.printf("Git Commit: %s\n", Constants.GIT_SHA1);
return 0;
}
-
+
if(about)
{
FeedReader.show_about(args);
return 0;
}
-
+
if(media != null)
{
Utils.playMedia(args, media);
return 0;
}
-
+
if(pingURL != null)
{
Logger.init(verbose);
@@ -73,7 +73,7 @@ namespace FeedReader.Main {
}
return 0;
}
-
+
if(feedURL != null)
{
Logger.init(verbose);
@@ -81,21 +81,21 @@ namespace FeedReader.Main {
FeedReaderBackend.get_default().addFeed(feedURL, "", false);
return 0;
}
-
+
if(grabImages != null && articleUrl != null)
{
Logger.init(verbose);
FeedServer.grabImages(grabImages, articleUrl);
return 0;
}
-
+
if(grabArticle != null)
{
Logger.init(verbose);
FeedServer.grabArticle(grabArticle);
return 0;
}
-
+
if(unreadCount)
{
var old_stdout =(owned)stdout;
@@ -105,7 +105,7 @@ namespace FeedReader.Main {
stdout.printf("%u\n", DataBase.readOnly().get_unread_total());
return 0;
}
-
+
try
{
Gst.init_check(ref args);
@@ -114,10 +114,10 @@ namespace FeedReader.Main {
{
Logger.error("Gst.init: " + e.message);
}
-
+
var app = FeedReaderApp.get_default();
app.run(args);
-
+
return 0;
}
}
diff --git a/src/Logger.vala b/src/Logger.vala
index 5e9480d9..e0dd4ba8 100644
--- a/src/Logger.vala
+++ b/src/Logger.vala
@@ -15,29 +15,29 @@
public class FeedReader.Logger : GLib.Object {
const string LOG_DOMAIN = "feedreader";
-
+
private static bool m_log_debug_information = false;
-
+
private static void log(LogLevelFlags level, string message)
{
GLib.log_structured(LOG_DOMAIN, level, "MESSAGE", "%s", message);
}
-
+
public static void error(string message)
{
log(GLib.LogLevelFlags.LEVEL_CRITICAL, message);
}
-
+
public static void warning(string message)
{
log(GLib.LogLevelFlags.LEVEL_WARNING, message);
}
-
+
public static void info(string message)
{
log(GLib.LogLevelFlags.LEVEL_INFO, message);
}
-
+
public static void debug(string message)
{
if(m_log_debug_information)
@@ -45,7 +45,7 @@ public class FeedReader.Logger : GLib.Object {
log(GLib.LogLevelFlags.LEVEL_DEBUG, message);
}
}
-
+
public static void init(bool verbose)
{
m_log_debug_information = verbose;
diff --git a/src/Model/Article.vala b/src/Model/Article.vala
index eeb6a3c7..1888ab62 100644
--- a/src/Model/Article.vala
+++ b/src/Model/Article.vala
@@ -14,7 +14,7 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.Article : GLib.Object {
-
+
private string m_articleID;
private string m_title;
private string m_url;
@@ -31,10 +31,10 @@ public class FeedReader.Article : GLib.Object {
private string m_guidHash;
private int m_lastModified;
private int m_pos;
-
+
private static GLib.Settings? m_gnome_settings;
private static bool m_clock_12_hour = false;
-
+
static construct
{
// Lookup the schema in a complicated way so we don't require users
@@ -50,7 +50,7 @@ public class FeedReader.Article : GLib.Object {
});
}
}
-
+
public Article (string articleID,
string? title,
string? url,
@@ -80,102 +80,102 @@ public class FeedReader.Article : GLib.Object {
m_date = date != null ? date : new DateTime.now_utc();
m_guidHash = guidHash;
m_lastModified = lastModified;
-
+
m_tags = tags == null ? Gee.List.empty<string>() : tags;
m_enclosures = enclosures == null ? Gee.List.empty<Enclosure>() : enclosures;
}
-
+
public string getArticleID()
{
return m_articleID;
}
-
+
public string getArticleFileName()
{
return GLib.Base64.encode(m_articleID.data);
}
-
+
public string getFeedFileName()
{
return GLib.Base64.encode(m_articleID.data);
}
-
+
public string getTitle()
{
return m_title;
}
-
+
public void setTitle(string title)
{
m_title = title;
}
-
+
public string getHTML()
{
return m_html;
}
-
+
public void setHTML(string html)
{
m_html = html;
}
-
+
public string getPreview()
{
return m_preview;
}
-
+
public void setPreview(string preview)
{
m_preview = preview;
}
-
+
public string? getAuthor()
{
return m_author;
}
-
+
public void setAuthor(string? author)
{
m_author = author;
}
-
+
public string getURL()
{
return m_url;
}
-
+
public void setURL(string url)
{
m_url = url;
}
-
+
public int getSortID()
{
return m_sortID;
}
-
+
public GLib.DateTime getDate()
{
return m_date;
}
-
+
public void SetDate(GLib.DateTime date)
{
m_date = date;
}
-
+
public string getDateNice(bool addTime = false)
{
var now = new GLib.DateTime.now_local();
var now_year = now.get_year();
var now_day = now.get_day_of_year();
var now_week = now.get_week_of_year();
-
+
var date_year = m_date.get_year();
var date_day = m_date.get_day_of_year();
var date_week = m_date.get_week_of_year();
-
+
var formats = new Gee.ArrayList<string>();
if(date_year == now_year)
{
@@ -201,7 +201,7 @@ public class FeedReader.Article : GLib.Object {
{
formats.add("%Y-%m-%d");
}
-
+
if(addTime)
{
if(m_clock_12_hour)
@@ -213,46 +213,46 @@ public class FeedReader.Article : GLib.Object {
formats.add("%H:%M");
}
}
-
+
string format = StringUtils.join(formats, ", ");
return m_date.format(format);
}
-
+
public string getFeedID()
{
return m_feedID;
}
-
+
public ArticleStatus getUnread()
{
return m_unread;
}
-
+
public void setUnread(ArticleStatus unread)
{
m_unread = unread;
}
-
+
public ArticleStatus getMarked()
{
return m_marked;
}
-
+
public void setMarked(ArticleStatus marked)
{
m_marked = marked;
}
-
+
public unowned Gee.List<string> getTagIDs()
{
return m_tags;
}
-
+
public void setTags(Gee.List<string> tags)
{
m_tags = tags;
}
-
+
public void addTag(string tagID)
{
if(!m_tags.contains(tagID))
@@ -260,7 +260,7 @@ public class FeedReader.Article : GLib.Object {
m_tags.add(tagID);
}
}
-
+
public void removeTag(string tagID)
{
if(m_tags.contains(tagID))
@@ -268,17 +268,17 @@ public class FeedReader.Article : GLib.Object {
m_tags.remove(tagID);
}
}
-
+
public unowned Gee.List<Enclosure> getEnclosures()
{
return m_enclosures;
}
-
+
public void setImages(Gee.List<Enclosure> enclosures)
{
m_enclosures = enclosures;
}
-
+
public void addEnclosure(Enclosure enc)
{
if(!m_enclosures.contains(enc))
@@ -286,7 +286,7 @@ public class FeedReader.Article : GLib.Object {
m_enclosures.add(enc);
}
}
-
+
public bool haveMedia()
{
foreach(Enclosure enc in m_enclosures)
@@ -297,25 +297,25 @@ public class FeedReader.Article : GLib.Object {
return true;
}
}
-
+
return false;
}
-
+
public string getHash()
{
return m_guidHash;
}
-
+
public int getLastModified()
{
return m_lastModified;
}
-
+
public int getPos()
{
return m_pos;
}
-
+
public void setPos(int pos)
{
m_pos = pos;
diff --git a/src/Model/CachedAction.vala b/src/Model/CachedAction.vala
index cd484a63..3340e75e 100644
--- a/src/Model/CachedAction.vala
+++ b/src/Model/CachedAction.vala
@@ -14,47 +14,47 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.CachedAction : GLib.Object {
-
+
private CachedActions m_action;
private string m_id;
private string m_argument;
-
+
public CachedAction(CachedActions action, string id, string argument) {
m_action = action;
m_id = id;
m_argument = argument;
}
-
+
public string getID()
{
return m_id;
}
-
+
public void setID(string id)
{
m_id = id;
}
-
+
public CachedActions getType()
{
return m_action;
}
-
+
public void setType(CachedActions action)
{
m_action = action;
}
-
+
public string getArgument()
{
return m_argument;
}
-
+
public void setArgument(string argument)
{
m_argument = argument;
}
-
+
public CachedActions opposite()
{
switch(m_action)
@@ -68,10 +68,10 @@ public class FeedReader.CachedAction : GLib.Object {
case CachedActions.MARK_UNSTARRED:
return CachedActions.MARK_STARRED;
}
-
+
return CachedActions.NONE;
}
-
+
public void print()
{
Logger.debug("CachedAction: %s %s".printf(m_action.to_string(), m_id));
diff --git a/src/Model/Category.vala b/src/Model/Category.vala
index 220becf8..dcb794f9 100644
--- a/src/Model/Category.vala
+++ b/src/Model/Category.vala
@@ -14,14 +14,14 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.Category : GLib.Object {
-
+
private string m_categorieID;
private string m_title;
private uint m_unread_count;
private int m_orderID;
private string m_parent;
private int m_level;
-
+
public Category (string categorieID, string title, uint unread_count, int orderID, string parent, int level) {
m_categorieID = categorieID;
m_title = title;
@@ -30,42 +30,42 @@ public class FeedReader.Category : GLib.Object {
m_parent = parent;
m_level = level;
}
-
+
public string getCatID()
{
return m_categorieID;
}
-
+
public string getFileName()
{
return GLib.Base64.encode(m_categorieID.data);
}
-
+
public string getTitle()
{
return m_title;
}
-
+
public uint getUnreadCount()
{
return m_unread_count;
}
-
+
public int getOrderID()
{
return m_orderID;
}
-
+
public string getParent()
{
return m_parent;
}
-
+
public int getLevel()
{
return m_level;
}
-
+
public void print()
{
Logger.debug("\ntitle: %s\nid: %s\nunread: %u".printf(m_title, m_categorieID, m_unread_count));
diff --git a/src/Model/Enclosure.vala b/src/Model/Enclosure.vala
index 9bc3a87b..3506cb8c 100644
--- a/src/Model/Enclosure.vala
+++ b/src/Model/Enclosure.vala
@@ -14,23 +14,23 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.Enclosure : GLib.Object {
-
+
private string m_article_id;
private string m_url;
private EnclosureType m_type;
-
+
public Enclosure(string article_id, string url, EnclosureType type)
{
m_article_id = article_id;
m_url = url;
m_type = type;
}
-
+
public string get_url()
{
return m_url;
}
-
+
public EnclosureType get_enclosure_type()
{
return m_type;
diff --git a/src/Model/Feed.vala b/src/Model/Feed.vala
index c21de71d..c01dace9 100644
--- a/src/Model/Feed.vala
+++ b/src/Model/Feed.vala
@@ -14,7 +14,7 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.Feed : GLib.Object {
-
+
private string m_feedID;
private string m_title;
private string m_url;
@@ -22,7 +22,7 @@ public class FeedReader.Feed : GLib.Object {
private uint m_unread;
private Gee.List<string> m_catIDs;
private string? m_iconURL;
-
+
public Feed(string feedID, string? title, string? url, uint unread, Gee.List<string>? catIDs = null, string? iconURL = null, string? xmlURL = null)
{
m_feedID = feedID;
@@ -33,110 +33,110 @@ public class FeedReader.Feed : GLib.Object {
m_iconURL = iconURL == "" ? null : iconURL;
m_xmlURL = xmlURL;
}
-
+
public string getFeedID()
{
return m_feedID;
}
-
+
public string getFeedFileName()
{
return GLib.Base64.encode(m_feedID.data);
}
-
+
public string getTitle()
{
return m_title;
}
-
+
public void setTitle(string title)
{
m_title = title;
}
-
+
public string getURL()
{
return m_url;
}
-
+
public void setURL(string url)
{
m_url = url;
}
-
+
public uint getUnread()
{
return m_unread;
}
-
+
public void setUnread(uint unread)
{
m_unread = unread;
}
-
+
public Gee.List<string> getCatIDs()
{
return m_catIDs;
}
-
+
public string getCatString()
{
return StringUtils.join(m_catIDs, ",");
}
-
+
public bool hasCat(string catID)
{
return m_catIDs.contains(catID);
}
-
+
public void addCat(string catID)
{
m_catIDs.add(catID);
}
-
+
public void setCats(Gee.Collection<string> catIDs)
{
m_catIDs.clear();
m_catIDs.add_all(catIDs);
}
-
+
// Helper function for backends that only support one category per feed
public void setCategory(string id)
{
m_catIDs.clear();
m_catIDs.add(id);
}
-
+
public bool isUncategorized()
{
if(m_catIDs.size == 0)
{
return true;
}
-
+
if(m_catIDs.size == 1 && m_catIDs[0].contains("global.must"))
{
return true;
}
-
+
return false;
}
-
+
public string? getIconURL()
{
return m_iconURL;
}
-
+
public void setIconURL(string? url)
{
m_iconURL = url;
}
-
+
public string? getXmlUrl()
{
return m_xmlURL;
}
-
+
public void print()
{
Logger.debug("\ntitle: %s\nid: %s\nurl: %s\nunread: %u".printf(m_title, m_feedID, m_url, m_unread));
diff --git a/src/Model/InterfaceState.vala b/src/Model/InterfaceState.vala
index 69898701..1c3272d1 100644
--- a/src/Model/InterfaceState.vala
+++ b/src/Model/InterfaceState.vala
@@ -14,7 +14,7 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.InterfaceState : GLib.Object {
-
+
private int m_WindowHeight = 900;
private int m_WindowWidth = 1600;
private int m_FeedsAndArticleWidth = 600;
@@ -30,12 +30,12 @@ public class FeedReader.InterfaceState : GLib.Object {
private string? m_ArticleListTopRow = null;
private string[] m_ExpandedCategories = {};
private ArticleListState m_ArticleListState = ArticleListState.ALL;
-
+
public InterfaceState()
{
-
+
}
-
+
public void write(bool shutdown)
{
Settings.state().set_int ("window-width", m_WindowWidth);
@@ -57,93 +57,93 @@ public class FeedReader.InterfaceState : GLib.Object {
Settings.state().set_int ("articlelist-row-offset", m_ArticleListRowOffset);
}
}
-
+
public void setWindowSize(int height, int width)
{
m_WindowHeight = height;
m_WindowWidth = width;
}
-
+
public int getWindowHeight()
{
return m_WindowHeight;
}
-
+
public int getWindowWidth()
{
return m_WindowWidth;
}
-
+
public void setFeedsAndArticleWidth(int size)
{
m_FeedsAndArticleWidth = size;
}
-
+
public int getFeedsAndArticleWidth()
{
return m_FeedsAndArticleWidth;
}
-
+
public void setFeedListWidth(int size)
{
m_FeedListWidth = size;
}
-
+
public int getFeedListWidth()
{
return m_FeedListWidth;
}
-
+
public void setFeedListScrollPos(double pos)
{
m_FeedListScrollPos = pos;
}
-
+
public double getFeedListScrollPos()
{
return m_FeedListScrollPos;
}
-
+
public void setArticleViewScrollPos(int pos)
{
m_ArticleViewScrollPos = pos;
}
-
+
public int getArticleViewScrollPos()
{
return m_ArticleViewScrollPos;
}
-
+
public void setArticleListScrollPos(double pos)
{
m_ArticleListScrollPos = pos;
}
-
+
public double getArticleListScrollPos()
{
return m_ArticleListScrollPos;
}
-
+
public void setArticleListRowOffset(int count)
{
m_ArticleListRowOffset = count;
}
-
+
public int getArticleListRowOffset()
{
return m_ArticleListRowOffset;
}
-
+
public void setArticleListSelectedRow(string articleID)
{
m_ArticleListSelectedRow = articleID;
}
-
+
public string getArticleListSelectedRow()
{
return m_ArticleListSelectedRow;
}
-
+
public void setArticleListTopRow(Article? article)
{
if(article == null)
@@ -155,60 +155,60 @@ public class FeedReader.InterfaceState : GLib.Object {
m_ArticleListTopRow = article.getArticleID();
}
}
-
+
public string getArticleListTopRow()
{
return m_ArticleListTopRow;
}
-
+
public void setWindowMaximized(bool max)
{
m_WindowMaximized = max;
}
-
+
public bool getWindowMaximized()
{
return m_WindowMaximized;
}
-
+
public void setSearchTerm(string search)
{
m_SearchTerm = search;
}
-
+
public string getSearchTerm()
{
return m_SearchTerm;
}
-
+
public void setFeedListSelectedRow(string code)
{
m_FeedListSelectedRow = code;
}
-
+
public string getFeedListSelectedRow()
{
return m_FeedListSelectedRow;
}
-
+
public void setExpandedCategories(string[] array)
{
m_ExpandedCategories = array;
}
-
+
public string[] getExpandedCategories()
{
return m_ExpandedCategories;
}
-
+
public void setArticleListState(ArticleListState state)
{
m_ArticleListState = state;
}
-
+
public ArticleListState getArticleListState()
{
return m_ArticleListState;
}
-
+
}
diff --git a/src/Model/ShareAccount.vala b/src/Model/ShareAccount.vala
index 74b61cf3..f629360b 100644
--- a/src/Model/ShareAccount.vala
+++ b/src/Model/ShareAccount.vala
@@ -14,14 +14,14 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.ShareAccount : GLib.Object {
-
+
private string m_id;
private string m_type;
private string m_accountName;
private string m_username;
private string m_iconName;
private bool m_systemAccount;
-
+
public ShareAccount(string id, string type, string username, string iconName, string accountName, bool system = false)
{
m_id = id;
@@ -31,32 +31,32 @@ public class FeedReader.ShareAccount : GLib.Object {
m_accountName = accountName;
m_systemAccount = system;
}
-
+
public string getID()
{
return m_id;
}
-
+
public string getType()
{
return m_type;
}
-
+
public string getUsername()
{
return m_username;
}
-
+
public string getIconName()
{
return m_iconName;
}
-
+
public string getAccountName()
{
return m_accountName;
}
-
+
public bool isSystemAccount()
{
return m_systemAccount;
diff --git a/src/Model/Tag.vala b/src/Model/Tag.vala
index d1f6e347..19f88656 100644
--- a/src/Model/Tag.vala
+++ b/src/Model/Tag.vala
@@ -14,37 +14,37 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.Tag : GLib.Object {
-
+
private string m_tagID;
private string m_title;
private int m_color;
-
+
public Tag (string tagID, string title, int color) {
m_tagID = tagID;
m_title = title;
m_color = color;
}
-
+
public string getTagID()
{
return m_tagID;
}
-
+
public string getTitle()
{
return m_title;
}
-
+
public void setTitle(string title)
{
m_title = title;
}
-
+
public int getColor()
{
return m_color;
}
-
+
public void setColor(int color)
{
m_color = color;
diff --git a/src/Notification.vala b/src/Notification.vala
index 05731cf2..2478dfba 100644
--- a/src/Notification.vala
+++ b/src/Notification.vala
@@ -14,13 +14,13 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.Notification : GLib.Object {
-
+
public static void send(uint new_articles, int new_and_unread)
{
string message = "";
string summary = _("New articles");
uint unread = DataBase.readOnly().get_unread_total();
-
+
if(new_articles > 0 && new_and_unread > 0)
{
if(new_articles == 1)
@@ -31,18 +31,18 @@ public class FeedReader.Notification : GLib.Object {
{
message = _("There are %u new articles (%u unread)").printf(new_articles, unread);
}
-
+
var notification = new GLib.Notification(summary);
notification.set_body(message);
notification.set_priority(GLib.NotificationPriority.NORMAL);
notification.set_icon(new GLib.ThemedIcon("org.gnome.FeedReader"));
-
+
GLib.Application.get_default().send_notification("feedreader_default", notification);
}
}
-
+
private Notification()
{
-
+
}
}
diff --git a/src/Password.vala b/src/Password.vala
index a43b7ce1..db28c8a8 100644
--- a/src/Password.vala
+++ b/src/Password.vala
@@ -14,14 +14,14 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.Password : GLib.Object {
-
+
public delegate HashTable<string, string> GetAttributesFunc();
-
+
private Secret.Collection m_secrets;
private Secret.Schema m_schema;
private GetAttributesFunc m_get_attributes;
private string m_label;
-
+
public Password(Secret.Collection secrets, Secret.Schema schema, string label, owned GetAttributesFunc get_attributes)
{
m_secrets = secrets;
@@ -29,39 +29,39 @@ public class FeedReader.Password : GLib.Object {
m_label = label;
m_get_attributes = (owned)get_attributes;
}
-
+
private void unlock_keyring(Cancellable? cancellable = null) throws Error
{
if (!m_secrets.get_locked())
{
return;
}
-
+
var collections_to_unlock = new List<Secret.Collection>();
collections_to_unlock.append(m_secrets);
var service = m_secrets.get_service();
service.unlock_sync(collections_to_unlock, cancellable, null);
}
-
+
public string get_password(Cancellable? cancellable = null)
{
var attributes = m_get_attributes();
try
{
unlock_keyring(cancellable);
-
+
if(cancellable != null && cancellable.is_cancelled())
{
return "";
}
-
+
var secrets = m_secrets.search_sync(m_schema, attributes, Secret.SearchFlags.NONE, cancellable);
-
+
if(cancellable != null && cancellable.is_cancelled())
{
return "";
}
-
+
if(secrets.length() != 0)
{
var item = secrets.data;
@@ -70,7 +70,7 @@ public class FeedReader.Password : GLib.Object {
{
return "";
}
-
+
var secret = item.get_secret();
if(secret == null)
{
@@ -92,19 +92,19 @@ public class FeedReader.Password : GLib.Object {
}
return "";
}
-
+
public void set_password(string password, Cancellable? cancellable = null)
{
var attributes = m_get_attributes();
try
{
unlock_keyring(cancellable);
-
+
if(cancellable != null && cancellable.is_cancelled())
{
return;
}
-
+
var value = new Secret.Value(password, password.length, "text/plain");
Secret.Item.create_sync(m_secrets, m_schema, attributes, m_label, value, Secret.ItemCreateFlags.REPLACE, cancellable);
}
@@ -113,26 +113,26 @@ public class FeedReader.Password : GLib.Object {
Logger.error("Password.setPassword: " + e.message);
}
}
-
+
public bool delete_password(Cancellable? cancellable = null)
{
var attributes = m_get_attributes();
try
{
unlock_keyring(cancellable);
-
+
if(cancellable != null && cancellable.is_cancelled())
{
return false;
}
-
+
var secrets = m_secrets.search_sync(m_schema, attributes, Secret.SearchFlags.NONE, cancellable);
-
+
if(cancellable != null && cancellable.is_cancelled())
{
return false;
}
-
+
if(secrets.length() != 0)
{
var item = secrets.data;
diff --git a/src/QueryBuilder.vala b/src/QueryBuilder.vala
index a9e0dd05..6a41f836 100644
--- a/src/QueryBuilder.vala
+++ b/src/QueryBuilder.vala
@@ -32,13 +32,13 @@ public class FeedReader.QueryBuilder : GLib.Object {
private bool m_order_descending = false;
private uint? m_limit = null;
private uint? m_offset = null;
-
+
public QueryBuilder(QueryType type, string table)
{
m_type = type;
m_table = table;
}
-
+
private void insert_value_pair(string field, string value)
requires (m_type == QueryType.INSERT
|| m_type == QueryType.INSERT_OR_IGNORE
@@ -47,72 +47,72 @@ public class FeedReader.QueryBuilder : GLib.Object {
m_fields.add(field);
m_values.add(value);
}
-
+
public void insert_param(string field, string value)
requires (value.has_prefix("$") && !value.contains("'"))
{
insert_value_pair(field, value);
}
-
+
public void insert_int(string field, int64 value)
{
insert_value_pair(field, value.to_string());
}
-
+
public void select_field(string field)
requires (m_type == QueryType.SELECT)
{
m_fields.add(field);
}
-
+
private void update(string field, string value)
requires (m_type == QueryType.UPDATE)
{
m_fields.add(field);
m_values.add(value);
}
-
+
public void update_param(string field, string value)
requires (value.has_prefix("$") && !value.contains("'"))
{
update(field, value);
}
-
+
public void update_string(string field, string value)
{
update(field, SQLite.quote_string(value));
}
-
+
public void update_int(string field, int64 value)
{
update(field, value.to_string());
}
-
+
private void where_equal(string field, string safe_value)
requires (m_type == QueryType.UPDATE
|| m_type == QueryType.SELECT
|| m_type == QueryType.DELETE)
{
-
+
m_conditions.add("%s = %s".printf(field, safe_value));
}
-
+
public void where_equal_param(string field, string value)
requires (value.has_prefix("$") && !value.contains("'"))
{
where_equal(field, value);
}
-
+
public void where_equal_int(string field, int64 value)
{
where_equal(field, value.to_string());
}
-
+
public void where_equal_string(string field, string value)
{
where_equal(field, SQLite.quote_string(value));
}
-
+
public void where(string condition)
requires (m_type == QueryType.UPDATE
|| m_type == QueryType.SELECT
@@ -120,7 +120,7 @@ public class FeedReader.QueryBuilder : GLib.Object {
{
m_conditions.add(condition);
}
-
+
public void where_in_strings(string field, Gee.List<string> values)
requires (m_type == QueryType.UPDATE
|| m_type == QueryType.SELECT
@@ -142,26 +142,26 @@ public class FeedReader.QueryBuilder : GLib.Object {
m_conditions.add("%s IN (%s)".printf(field, compound_values.str));
}
}
-
+
public void order_by(string field, bool desc)
requires (m_type == QueryType.SELECT)
{
m_order_by_column = field;
m_order_descending = desc;
}
-
+
public void limit(uint limit)
requires (m_type == QueryType.SELECT)
{
m_limit = limit;
}
-
+
public void offset(uint offset)
requires (m_type == QueryType.SELECT)
{
m_offset = offset;
}
-
+
public string to_string()
{
var query = new GLib.StringBuilder();
@@ -171,7 +171,7 @@ public class FeedReader.QueryBuilder : GLib.Object {
case QueryType.INSERT_OR_IGNORE:
case QueryType.INSERT_OR_REPLACE:
query.append("INSERT ");
-
+
if(m_type == QueryType.INSERT_OR_IGNORE)
{
query.append("OR IGNORE ");
@@ -180,17 +180,17 @@ public class FeedReader.QueryBuilder : GLib.Object {
{
query.append("OR REPLACE ");
}
-
+
query.append_printf("INTO %s (", m_table);
StringUtils.stringbuilder_append_join(query, m_fields, ", ");
query.append(") VALUES (");
StringUtils.stringbuilder_append_join(query, m_values, ", ");
query.append_c(')');
break;
-
+
case QueryType.UPDATE:
query.append_printf("UPDATE %s SET ", m_table);
-
+
assert(m_fields.size > 0);
for(int i = 0; i < m_fields.size; i++)
{
@@ -198,30 +198,30 @@ public class FeedReader.QueryBuilder : GLib.Object {
{
query.append(", ");
}
-
+
query.append(m_fields.get(i));
query.append(" = ");
query.append(m_values.get(i));
}
-
+
append_conditions(query);
break;
-
-
+
+
case QueryType.DELETE:
query.append("DELETE FROM ");
query.append(m_table);
append_conditions(query);
break;
-
-
+
+
case QueryType.SELECT:
query.append("SELECT ");
StringUtils.stringbuilder_append_join(query, m_fields, ", ");
query.append_printf(" FROM %s", m_table);
-
+
append_conditions(query);
-
+
if (m_order_by_column != null)
{
query.append_printf(
@@ -229,33 +229,33 @@ public class FeedReader.QueryBuilder : GLib.Object {
m_order_by_column,
m_order_descending ? "DESC" : "ASC");
}
-
+
if (m_limit != null)
{
query.append_printf(" LIMIT %u", m_limit);
}
-
+
if (m_offset != null)
{
query.append_printf(" OFFSET %u", m_offset);
}
break;
}
-
+
return query.str;
}
-
+
private void append_conditions(StringBuilder query)
{
if(m_conditions.size == 0)
{
return;
}
-
+
query.append(" WHERE ");
StringUtils.stringbuilder_append_join(query, m_conditions, " AND ");
}
-
+
public void print()
{
Logger.debug(to_string());
diff --git a/src/Rfc822.vala b/src/Rfc822.vala
index 053c035a..021a3f5e 100644
--- a/src/Rfc822.vala
+++ b/src/Rfc822.vala
@@ -1,5 +1,5 @@
namespace FeedReader.Rfc822 {
-
+
/**
* Parse a date string in RFC 822 format
* Note that we don't use Time.strptime because it uses the current locale
@@ -14,7 +14,7 @@ namespace FeedReader.Rfc822 {
{
return null;
}
-
+
Regex re;
try {
re = new Regex("""
@@ -39,16 +39,16 @@ namespace FeedReader.Rfc822 {
assert(false);
return null;
}
-
+
MatchInfo info;
if (!re.match(str, 0, out info))
{
return null;
}
-
+
var dayStr = info.fetch_named("day");
var day = int.parse(dayStr);
-
+
var monthStr = info.fetch_named("month").ascii_down();
int month;
switch(monthStr) {
@@ -93,7 +93,7 @@ namespace FeedReader.Rfc822 {
assert(false);
return null;
}
-
+
var yearStr = info.fetch_named("year");
var year = int.parse(yearStr);
// Two-digit years from 00 to 49 should be interpreted as 2000 to 2049
@@ -112,7 +112,7 @@ namespace FeedReader.Rfc822 {
var minute = int.parse(minuteStr);
var secondStr = info.fetch_named("second");
var second = secondStr == null || secondStr == "" ? 0 : int.parse(secondStr);
-
+
var zoneStr = info.fetch_named("zone");
TimeZone zone;
switch(zoneStr.ascii_up()) {
@@ -136,7 +136,7 @@ namespace FeedReader.Rfc822 {
case "PST":
zone = new TimeZone("-08");
break;
-
+
case "GMT":
case "UT":
case "Z":
@@ -146,7 +146,7 @@ namespace FeedReader.Rfc822 {
zone = new TimeZone(zoneStr);
break;
}
-
+
return new DateTime(zone, year, month, day, hour, minute, second);
}
}
diff --git a/src/SQLite.vala b/src/SQLite.vala
index fdfa87cd..2e85fa16 100644
--- a/src/SQLite.vala
+++ b/src/SQLite.vala
@@ -16,7 +16,7 @@
/* A wrapper around the low-level SQLite API */
public class FeedReader.SQLite : GLib.Object {
private Sqlite.Database m_db;
-
+
public SQLite(string db_path, int busy_timeout = 1000)
{
var path = GLib.File.new_for_path(db_path);
@@ -35,16 +35,16 @@ public class FeedReader.SQLite : GLib.Object {
Logger.error("SQLite: " + e.message);
}
}
-
+
int rc = Sqlite.Database.open_v2(db_path, out m_db);
if(rc != Sqlite.OK)
{
error("Can't open database: %d: %s".printf(m_db.errcode(), m_db.errmsg()));
}
-
+
m_db.busy_timeout(busy_timeout);
}
-
+
// Backwards compatibility interface
public Sqlite.Statement prepare(string query)
requires (query != "")
@@ -57,17 +57,17 @@ public class FeedReader.SQLite : GLib.Object {
}
return stmt;
}
-
+
public string errmsg()
{
return m_db.errmsg();
}
-
+
public void checkpoint()
{
m_db.wal_checkpoint("");
}
-
+
public void simple_query(string query)
requires (query != "")
{
@@ -78,7 +78,7 @@ public class FeedReader.SQLite : GLib.Object {
error("Failed to execute simple query: %d: %s\nSQL is: %s".printf(ec, errmsg, query));
}
}
-
+
public Gee.List<Gee.List<Sqlite.Value?>> execute(string query, GLib.Value?[]? params = null)
requires (query != "")
{
@@ -88,7 +88,7 @@ public class FeedReader.SQLite : GLib.Object {
{
error("Can't prepare statement: %d: %s\nSQL is: %s".printf(m_db.errcode(), m_db.errmsg(), query));
}
-
+
if(params != null)
{
int i = 1;
@@ -125,7 +125,7 @@ public class FeedReader.SQLite : GLib.Object {
++i;
}
}
-
+
var rows = new Gee.ArrayList<Gee.List<Sqlite.Value?>>();
while(stmt.step() == Sqlite.ROW)
{
@@ -137,10 +137,10 @@ public class FeedReader.SQLite : GLib.Object {
rows.add(row);
}
stmt.reset ();
-
+
return rows;
}
-
+
public static string quote_string(string str)
{
var escaped = str.replace("'", "''");
diff --git a/src/Settings.vala b/src/Settings.vala
index 9365ef97..f320ebb0 100644
--- a/src/Settings.vala
+++ b/src/Settings.vala
@@ -14,60 +14,60 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.Settings : GLib.Object {
-
+
private static GLib.Settings? m_general = null;
private static GLib.Settings? m_tweaks = null;
private static GLib.Settings? m_state = null;
private static GLib.Settings? m_keys = null;
private static Gee.HashMap<string, GLib.Settings>? m_share = null;
-
+
public static GLib.Settings general()
{
if(m_general == null)
{
m_general = new GLib.Settings("org.gnome.feedreader");
}
-
+
return m_general;
}
-
+
public static GLib.Settings tweaks()
{
if(m_tweaks == null)
{
m_tweaks = new GLib.Settings("org.gnome.feedreader.tweaks");
}
-
+
return m_tweaks;
}
-
+
public static GLib.Settings state()
{
if(m_state == null)
{
m_state = new GLib.Settings("org.gnome.feedreader.saved-state");
}
-
+
return m_state;
}
-
+
public static GLib.Settings keybindings()
{
if(m_keys == null)
{
m_keys = new GLib.Settings("org.gnome.feedreader.keybindings");
}
-
+
return m_keys;
}
-
+
public static GLib.Settings? share(string pluginName)
{
if(m_share == null)
{
m_share = new Gee.HashMap<string, GLib.Settings>();
}
-
+
if(m_share.has_key(pluginName))
{
return m_share.get(pluginName);
@@ -79,9 +79,9 @@ public class FeedReader.Settings : GLib.Object {
return settings;
}
}
-
+
private Settings()
{
-
+
}
}
diff --git a/src/Share/ServiceSetup.vala b/src/Share/ServiceSetup.vala
index 02ca116d..096c7288 100644
--- a/src/Share/ServiceSetup.vala
+++ b/src/Share/ServiceSetup.vala
@@ -14,7 +14,7 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.ServiceSetup : Gtk.ListBoxRow {
-
+
protected string m_name;
protected Gtk.Revealer m_revealer;
protected Gtk.Label m_label;
@@ -32,7 +32,7 @@ public class FeedReader.ServiceSetup : Gtk.ListBoxRow {
protected bool m_systemAccount;
public signal void removeRow();
public signal void showInfoBar(string text);
-
+
public ServiceSetup(string name, string iconName, bool loggedIn, string username, bool system = false)
{
m_name = name;
@@ -42,7 +42,7 @@ public class FeedReader.ServiceSetup : Gtk.ListBoxRow {
m_iconStack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT);
m_iconStack.set_transition_duration(300);
m_labelStack = new Gtk.Stack();
-
+
m_eventbox = new Gtk.EventBox();
m_eventbox.set_events(Gdk.EventMask.ENTER_NOTIFY_MASK);
m_eventbox.set_events(Gdk.EventMask.LEAVE_NOTIFY_MASK);
@@ -52,37 +52,37 @@ public class FeedReader.ServiceSetup : Gtk.ListBoxRow {
m_eventbox.leave_notify_event.connect(onLeave);
}
m_eventbox.add(m_iconStack);
-
+
m_login_button = new Gtk.Button.with_label(_("Login"));
m_login_button.hexpand = false;
m_login_button.margin = 10;
m_login_button.clicked.connect(login);
-
+
m_logout_button = new Gtk.Button.with_label(_("Logout"));
m_logout_button.hexpand = false;
m_logout_button.margin = 10;
m_logout_button.clicked.connect(logout);
m_logout_button.get_style_context().add_class(Gtk.STYLE_CLASS_DESTRUCTIVE_ACTION);
-
+
var loggedIN = new Gtk.Image.from_icon_name("feed-status-ok", Gtk.IconSize.LARGE_TOOLBAR);
m_spinner = new Gtk.Spinner();
m_spinner.set_size_request(24, 24);
-
+
m_iconStack.add_named(m_login_button, "button");
m_iconStack.add_named(loggedIN, "loggedIN");
m_iconStack.add_named(m_logout_button, "logOUT");
m_iconStack.add_named(m_spinner, "spinner");
m_iconStack.set_size_request(100, 0);
-
+
m_box = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 0);
m_box.set_size_request(0, 50);
-
+
var icon = new Gtk.Image.from_icon_name(iconName, Gtk.IconSize.DND);
icon.set_size_request(100, 0);
-
+
var label = new Gtk.Label(m_name);
label.set_alignment(0.5f, 0.5f);
-
+
var label1 = new Gtk.Label(m_name);
m_label = new Gtk.Label(username);
label1.set_alignment(0.5f, 1.0f);
@@ -91,28 +91,28 @@ public class FeedReader.ServiceSetup : Gtk.ListBoxRow {
m_labelBox = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
m_labelBox.pack_start(label1, true, true, 0);
m_labelBox.pack_start(m_label, true, true, 0);
-
+
m_labelStack.add_named(label, "loggedOUT");
m_labelStack.add_named(m_labelBox, "loggedIN");
-
+
m_box.pack_start(icon, false, false, 0);
m_box.pack_start(m_labelStack, true, true, 0);
m_box.pack_end(m_eventbox, false, false, 0);
-
+
m_seperator_box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
var separator = new Gtk.Separator(Gtk.Orientation.HORIZONTAL);
m_seperator_box.pack_start(m_box, true, true, 0);
m_seperator_box.pack_end(separator, false, false, 0);
-
-
+
+
m_revealer = new Gtk.Revealer();
m_revealer.set_transition_type(Gtk.RevealerTransitionType.SLIDE_DOWN);
m_revealer.add(m_seperator_box);
m_revealer.set_reveal_child(false);
-
+
this.add(m_revealer);
this.show_all();
-
+
if(m_isLoggedIN)
{
m_iconStack.set_visible_child_name("loggedIN");
@@ -124,17 +124,17 @@ public class FeedReader.ServiceSetup : Gtk.ListBoxRow {
m_labelStack.set_visible_child_name("loggedOUT");
}
}
-
+
public virtual void login()
{
-
+
}
-
+
public virtual void logout()
{
-
+
}
-
+
private bool onEnter()
{
if(m_isLoggedIN)
@@ -143,7 +143,7 @@ public class FeedReader.ServiceSetup : Gtk.ListBoxRow {
}
return false;
}
-
+
private bool onLeave()
{
if(m_isLoggedIN)
@@ -152,46 +152,46 @@ public class FeedReader.ServiceSetup : Gtk.ListBoxRow {
}
return false;
}
-
+
public void reveal(bool animate = true)
{
if(!animate)
{
m_revealer.set_transition_type(Gtk.RevealerTransitionType.NONE);
}
-
+
m_revealer.set_reveal_child(true);
this.show_all();
}
-
+
public void unreveal()
{
m_revealer.set_reveal_child(false);
}
-
+
public bool isLoggedIn()
{
return m_isLoggedIN;
}
-
+
public string getID()
{
return m_id;
}
-
+
public bool isSystemAccount()
{
return m_systemAccount;
}
-
+
public string getUserName()
{
return m_label.get_text();
}
-
+
public string getName()
{
return m_name;
}
-
+
}
diff --git a/src/Share/ShareAccountInterface.vala b/src/Share/ShareAccountInterface.vala
index b6246779..a179ec36 100644
--- a/src/Share/ShareAccountInterface.vala
+++ b/src/Share/ShareAccountInterface.vala
@@ -14,36 +14,36 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public interface FeedReader.ShareAccountInterface : GLib.Object {
-
+
public signal void addAccount(string id, string type, string username, string iconName, string accountName);
-
+
public signal void deleteAccount(string id);
-
+
public abstract void setupSystemAccounts(Gee.List<ShareAccount> accounts);
-
+
public abstract bool useSystemAccounts();
-
+
public abstract string pluginID();
-
+
public abstract string pluginName();
-
+
public abstract bool addBookmark(string id, string url, bool system);
-
+
public abstract bool logout(string id);
-
+
public abstract string getIconName();
-
+
public abstract string getUsername(string id);
-
+
public abstract bool needSetup();
-
+
public abstract bool singleInstance();
-
+
public abstract ServiceSetup? newSetup_withID(string id, string username);
-
+
public abstract ServiceSetup? newSetup();
-
+
public abstract ServiceSetup? newSystemAccount(string id, string username);
-
+
public abstract ShareForm? shareWidget(string url);
}
diff --git a/src/Share/share.vala b/src/Share/share.vala
index 331d1274..5862f36a 100644
--- a/src/Share/share.vala
+++ b/src/Share/share.vala
@@ -14,30 +14,30 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.Share : GLib.Object {
-
+
private Gee.List<ShareAccount> m_accounts;
private Peas.ExtensionSet m_plugins;
private static Share? m_share = null;
private Goa.Client? m_client = null;
-
+
public static Share get_default()
{
if(m_share == null)
{
m_share = new Share();
}
-
+
return m_share;
}
-
+
private Share()
{
var engine = Peas.Engine.get_default();
engine.add_search_path(Constants.INSTALL_LIBDIR + "/pluginsShare/", null);
engine.enable_loader("python3");
-
+
m_plugins = new Peas.ExtensionSet(engine, typeof(ShareAccountInterface));
-
+
m_plugins.extension_added.connect((info, extension) => {
var plugin = (extension as ShareAccountInterface);
plugin.addAccount.connect(accountAdded);
@@ -45,19 +45,19 @@ public class FeedReader.Share : GLib.Object {
refreshAccounts();
});
});
-
+
//m_plugins.extension_removed.connect((info, extension) => {});
-
+
checkSystemAccounts();
-
+
foreach(var plugin in engine.get_plugin_list())
{
engine.try_load_plugin(plugin);
}
-
+
refreshAccounts();
}
-
+
public void refreshAccounts()
{
Logger.debug("Share: refreshAccounts");
@@ -96,35 +96,35 @@ public class FeedReader.Share : GLib.Object {
);
}
});
-
+
// load gresource-icons from the plugins
Gtk.IconTheme.get_default().add_resource_path("/org/gnome/FeedReader/icons");
}
-
+
private ShareAccountInterface? getInterface(string type)
{
ShareAccountInterface? plug = null;
-
+
m_plugins.foreach((@set, info, exten) => {
var plugin = (exten as ShareAccountInterface);
-
+
if(plugin.pluginID() == type)
{
plug = plugin;
}
});
-
+
return plug;
}
-
+
public Gee.List<ShareAccount> getAccountTypes()
{
var accounts = new Gee.ArrayList<ShareAccount>();
-
+
m_plugins.foreach((@set, info, exten) => {
var plugin = (exten as ShareAccountInterface);
var pluginID = plugin.pluginID();
-
+
bool singleInstance = false;
if(plugin.singleInstance())
{
@@ -137,27 +137,27 @@ public class FeedReader.Share : GLib.Object {
{
singleInstance = true;
}
-
+
if(plugin.needSetup() && !plugin.useSystemAccounts() && singleInstance)
{
accounts.add(new ShareAccount("", pluginID, "", plugin.getIconName(), plugin.pluginName()));
}
});
-
+
return accounts;
}
-
-
+
+
public Gee.List<ShareAccount> getAccounts()
{
return m_accounts;
}
-
+
public string generateNewID()
{
string id = Utils.string_random(12);
bool unique = true;
-
+
m_plugins.foreach((@set, info, exten) => {
var plugin = (exten as ShareAccountInterface);
var plugID = plugin.pluginID();
@@ -174,22 +174,22 @@ public class FeedReader.Share : GLib.Object {
}
}
});
-
+
if(!unique)
{
return generateNewID();
}
-
+
return id;
}
-
+
public void accountAdded(string id, string type, string username, string iconName, string accountName)
{
Logger.debug("Share: %s account added for user: %s".printf(type, username));
m_accounts.add(new ShareAccount(id, type, username, iconName, accountName));
}
-
-
+
+
public string getUsername(string accountID)
{
foreach(var account in m_accounts)
@@ -199,11 +199,11 @@ public class FeedReader.Share : GLib.Object {
return getInterface(account.getType()).getUsername(accountID);
}
}
-
+
return "";
}
-
-
+
+
public bool addBookmark(string accountID, string url)
{
foreach(var account in m_accounts)
@@ -213,10 +213,10 @@ public class FeedReader.Share : GLib.Object {
return getInterface(account.getType()).addBookmark(accountID, url, account.isSystemAccount());
}
}
-
+
return false;
}
-
+
public bool needSetup(string accountID)
{
foreach(var account in m_accounts)
@@ -226,10 +226,10 @@ public class FeedReader.Share : GLib.Object {
return getInterface(account.getType()).needSetup();
}
}
-
+
return false;
}
-
+
public ServiceSetup? newSetup_withID(string accountID)
{
foreach(var account in m_accounts)
@@ -239,15 +239,15 @@ public class FeedReader.Share : GLib.Object {
return getInterface(account.getType()).newSetup_withID(account.getID(), account.getUsername());
}
}
-
+
return null;
}
-
+
public ServiceSetup? newSetup(string type)
{
return getInterface(type).newSetup();
}
-
+
public ServiceSetup? newSystemAccount(string accountID)
{
foreach(var account in m_accounts)
@@ -257,26 +257,26 @@ public class FeedReader.Share : GLib.Object {
return getInterface(account.getType()).newSystemAccount(account.getID(), account.getUsername());
}
}
-
+
return null;
}
-
+
public ShareForm? shareWidget(string type, string url)
{
ShareForm? form = null;
-
+
m_plugins.foreach((@set, info, exten) => {
var plugin = (exten as ShareAccountInterface);
-
+
if(plugin.pluginID() == type)
{
form = plugin.shareWidget(url);
}
});
-
+
return form;
}
-
+
private void checkSystemAccounts()
{
try
@@ -307,7 +307,7 @@ public class FeedReader.Share : GLib.Object {
Logger.error("share.checkSystemAccounts: %s".printf(e.message));
}
}
-
+
private void accountsChanged(Goa.Object object)
{
refreshAccounts();
diff --git a/src/StringUtils.vala b/src/StringUtils.vala
index ce4ecfda..95b02b64 100644
--- a/src/StringUtils.vala
+++ b/src/StringUtils.vala
@@ -21,7 +21,7 @@ public class FeedReader.StringUtils {
{
return new Gee.ArrayList<string>.wrap(items);
}
-
+
var res = new Gee.ArrayList<string>();
foreach(string item in items)
{
@@ -29,16 +29,16 @@ public class FeedReader.StringUtils {
{
res.add(item);
}
-
+
}
return res;
}
-
+
public static string join(Gee.Collection<string> l, string sep)
{
return string.joinv(sep, l.to_array());
}
-
+
public static void stringbuilder_append_join(StringBuilder out, Gee.Collection<string> l, string sep)
{
bool first = true;
@@ -52,7 +52,7 @@ public class FeedReader.StringUtils {
first = false;
}
}
-
+
public static Gee.List<string> sql_quote(Gee.List<string> l)
ensures (result.size == l.size)
{
@@ -60,7 +60,7 @@ public class FeedReader.StringUtils {
{
l[i] = SQLite.quote_string(l[i]);
}
-
+
return l;
}
}
diff --git a/src/Structs.vala b/src/Structs.vala
index a7383c40..f0ab106a 100644
--- a/src/Structs.vala
+++ b/src/Structs.vala
@@ -14,7 +14,7 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
namespace FeedReader {
-
+
public struct BackendInfo {
string ID;
string name;
@@ -22,33 +22,33 @@ namespace FeedReader {
string website;
string iconName;
}
-
+
public struct Response {
uint status;
string data;
Soup.MessageHeaders headers;
-
+
public bool is_ok()
{
return status >= 200 && status < 400;
}
}
-
+
public struct ResourceMetadata
{
private const string CACHE_GROUP = "cache";
private const string ETAG_KEY = "etag";
private const string LAST_MODIFIED_KEY = "last_modified";
private const string EXPIRES_KEY = "last_checked";
-
+
string? etag;
string? last_modified;
DateTime? expires;
-
+
public ResourceMetadata()
{
}
-
+
public ResourceMetadata.from_data(string data)
{
try
@@ -61,7 +61,7 @@ namespace FeedReader {
try { this.last_modified = config.get_string(CACHE_GROUP, LAST_MODIFIED_KEY); }
catch (KeyFileError.KEY_NOT_FOUND e) {}
catch (KeyFileError.GROUP_NOT_FOUND e) {}
-
+
int64? expires = null;
try { expires = config.get_int64(CACHE_GROUP, EXPIRES_KEY); }
catch (KeyFileError.KEY_NOT_FOUND e) {}
@@ -76,7 +76,7 @@ namespace FeedReader {
Logger.warning(@"FaviconMetadata.from_file: Failed to load from $data");
}
}
-
+
public static async ResourceMetadata from_file_async(string filename)
{
try
@@ -95,7 +95,7 @@ namespace FeedReader {
}
return ResourceMetadata();
}
-
+
public async void save_to_file_async(string filename)
{
var file = File.new_for_path(filename);
@@ -147,21 +147,21 @@ namespace FeedReader {
}
}
}
-
+
public bool is_expired()
{
if(expires == null)
{
return true;
}
-
+
if(expires.compare(new DateTime.now_utc()) == 1)
{
return false;
}
-
+
return true;
}
}
-
+
}
diff --git a/src/TestQueryBuilder.vala b/src/TestQueryBuilder.vala
index 2aec8310..78d11062 100644
--- a/src/TestQueryBuilder.vala
+++ b/src/TestQueryBuilder.vala
@@ -3,54 +3,54 @@ using FeedReader;
void main(string[] args)
{
Test.init(ref args);
-
+
Test.add_data_func("/querybuilder/simple-select", () => {
var query = new QueryBuilder(QueryType.SELECT, "example");
query.select_field("column1");
query.select_field("column2");
-
+
assert(query.to_string() == "SELECT column1, column2 FROM example");
});
-
+
Test.add_data_func("/querybuilder/simple-insert", () => {
var query = new QueryBuilder(QueryType.INSERT, "example");
query.insert_param("asdf", "$VALUE");
query.insert_int("othercol", 5);
-
+
assert(query.to_string() == "INSERT INTO example (asdf, othercol) VALUES ($VALUE, 5)");
});
-
+
Test.add_data_func("/querybuilder/simple-insert-or-ignore", () => {
var query = new QueryBuilder(QueryType.INSERT_OR_IGNORE, "example");
query.insert_param("asdf", "$VALUE");
query.insert_int("othercol", 5);
-
+
assert(query.to_string() == "INSERT OR IGNORE INTO example (asdf, othercol) VALUES ($VALUE, 5)");
});
-
+
Test.add_data_func("/querybuilder/simple-insert-or-replace", () => {
var query = new QueryBuilder(QueryType.INSERT_OR_REPLACE, "example");
query.insert_param("asdf", "$VALUE");
query.insert_int("othercol", 5);
-
+
assert(query.to_string() == "INSERT OR REPLACE INTO example (asdf, othercol) VALUES ($VALUE, 5)");
});
-
+
Test.add_data_func("/querybuilder/simple-update", () => {
var query = new QueryBuilder(QueryType.UPDATE, "example");
query.update_int("asdf", 5);
query.update_string("othercol", "asd'");
query.update_param("test", "$TEST");
-
+
assert(query.to_string() == "UPDATE example SET asdf = 5, othercol = 'asd''', test = $TEST");
});
-
+
Test.add_data_func("/querybuilder/simple-delete", () => {
var query = new QueryBuilder(QueryType.DELETE, "example");
-
+
assert(query.to_string() == "DELETE FROM example");
});
-
+
Test.add_data_func("/querybuilder/complex-select", () => {
var query = new QueryBuilder(QueryType.SELECT, "test");
query.select_field("column1");
@@ -68,7 +68,7 @@ void main(string[] args)
}));
query.limit(100);
query.offset(5);
-
+
assert(query.to_string() == "SELECT column1, column2, column3 " +
"FROM test " +
"WHERE column3 = '\"something''' " +
@@ -80,6 +80,6 @@ void main(string[] args)
"LIMIT 100 " +
"OFFSET 5");
});
-
+
Test.run();
}
diff --git a/src/TestStringUtils.vala b/src/TestStringUtils.vala
index 6784802f..648bc457 100644
--- a/src/TestStringUtils.vala
+++ b/src/TestStringUtils.vala
@@ -3,61 +3,61 @@ using FeedReader;
void main(string[] args)
{
Test.init(ref args);
-
+
Test.add_data_func("/stringutils/join", () => {
var inputs = new Gee.ArrayList<string>();
inputs.add("one");
inputs.add("two");
-
+
var output = StringUtils.join(inputs, ",");
assert(output == "one,two");
-
+
output = StringUtils.join(inputs, " ");
assert(output == "one two");
});
-
+
Test.add_data_func("/stringutils/split", () => {
var output = StringUtils.split("", ",");
assert(output.is_empty);
-
+
output = StringUtils.split(" ", ",");
assert(output.size == 1);
assert(output[0] == " ");
-
+
output = StringUtils.split(" ", " ");
assert(output.size == 2);
assert(output[0] == "");
assert(output[1] == "");
-
+
output = StringUtils.split(" ", " ", true);
assert(output.size == 0);
-
+
output = StringUtils.split("$one#$t#wo#$", "#$");
assert(output.size == 3);
assert(output[0] == "$one");
assert(output[1] == "t#wo");
assert(output[2] == "");
-
+
output = StringUtils.split("$one#$t#wo#$", "#$", true);
assert(output.size == 2);
assert(output[0] == "$one");
assert(output[1] == "t#wo");
});
-
+
Test.add_data_func("/stringutils/sqlquote", () => {
var inputs = new Gee.ArrayList<string>();
assert(StringUtils.sql_quote(inputs).size == 0);
-
+
inputs.add("one");
inputs.add("t'wo");
inputs.add("''");
-
+
var output = StringUtils.sql_quote(inputs);
assert(output.size == inputs.size);
assert(output[0] == "'one'");
assert(output[1] == "'t''wo'");
assert(output[2] == "''''''");
});
-
+
Test.run();
}
diff --git a/src/Utils.vala b/src/Utils.vala
index 02e91837..92d9e458 100644
--- a/src/Utils.vala
+++ b/src/Utils.vala
@@ -14,9 +14,9 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.Utils : GLib.Object {
-
+
private static Soup.Session? m_session;
-
+
public static Soup.Session getSession()
{
if(m_session == null)
@@ -26,10 +26,10 @@ public class FeedReader.Utils : GLib.Object {
m_session.ssl_strict = false;
m_session.timeout = 5;
}
-
+
return m_session;
}
-
+
public static void generatePreviews(Gee.List<Article> articles)
{
string noPreview = _("No Preview Available");
@@ -54,26 +54,26 @@ public class FeedReader.Utils : GLib.Object {
{
output = output.strip();
}
-
+
if(output == "" || output == null)
{
Logger.info("generatePreviews: no Preview");
Article.setPreview(noPreview);
continue;
}
-
+
string xml = "<?xml";
-
+
while(output.has_prefix(xml))
{
int end = output.index_of_char('>');
output = output.slice(end+1, output.length).chug();
output = output.strip();
}
-
+
output = output.replace("\n"," ");
output = output.replace("_"," ");
-
+
Article.setPreview(output.chug());
}
else
@@ -85,7 +85,7 @@ public class FeedReader.Utils : GLib.Object {
}
}
}
-
+
public static void checkHTML(Gee.List<Article> articles)
{
var db = DataBase.readOnly();
@@ -102,7 +102,7 @@ public class FeedReader.Utils : GLib.Object {
}
}
}
-
+
public static string UTF8fix(string? old_string, bool remove_html = false)
{
if(old_string == null)
@@ -110,7 +110,7 @@ public class FeedReader.Utils : GLib.Object {
Logger.warning("Utils.UTF8fix: string is NULL");
return "NULL";
}
-
+
string output = old_string;
if (remove_html)
{
@@ -121,12 +121,12 @@ public class FeedReader.Utils : GLib.Object {
output = output.make_valid().replace("\n"," ").strip();
return output;
}
-
+
public static string[] getDefaultExpandedCategories()
{
return {CategoryID.MASTER.to_string(), CategoryID.TAGS.to_string()};
}
-
+
/*public static GLib.DateTime convertStringToDate(string date)
{
return new GLib.DateTime(
@@ -139,42 +139,42 @@ public class FeedReader.Utils : GLib.Object {
int.parse(date.substring(date.index_of_nth_char(17), date.index_of_nth_char(19) - date.index_of_nth_char(17))) // sec
);
}*/
-
+
public static bool springCleaningNecessary()
{
var lastClean = new DateTime.from_unix_local(Settings.state().get_int("last-spring-cleaning"));
var now = new DateTime.now_local();
-
+
var difference = now.difference(lastClean);
bool doCleaning = false;
-
+
Logger.debug("last clean: %s".printf(lastClean.format("%Y-%m-%d %H:%M:%S")));
Logger.debug("now: %s".printf(now.format("%Y-%m-%d %H:%M:%S")));
Logger.debug("difference: %f".printf(difference/GLib.TimeSpan.DAY));
-
+
if((difference/GLib.TimeSpan.DAY) >= Settings.general().get_int("spring-clean-after"))
{
doCleaning = true;
}
-
+
return doCleaning;
}
-
+
// thanks to
// http://kuikie.com/snippet/79-8/vala/strings/vala-generate-random-string/%7B$ROOT_URL%7D/terms/
public static string string_random(int length = 8, string charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890")
{
string random = "";
-
+
for(int i=0; i<length; i++) {
int random_index = Random.int_range(0,charset.length);
string ch = charset.get_char(charset.index_of_nth_char(random_index)).to_string();
random += ch;
}
-
+
return random;
}
-
+
public static bool arrayContains(string[] array, string key)
{
foreach(string s in array)
@@ -184,16 +184,16 @@ public class FeedReader.Utils : GLib.Object {
return true;
}
}
-
+
return false;
}
-
+
public static void copyAutostart()
{
string desktop = "org.gnome.FeedReader-autostart.desktop";
string filename = GLib.Environment.get_user_data_dir() + "/" + desktop;
-
-
+
+
if(Settings.tweaks().get_boolean("feedreader-autostart") && !FileUtils.test(filename, GLib.FileTest.EXISTS))
{
try
@@ -208,117 +208,117 @@ public class FeedReader.Utils : GLib.Object {
}
}
}
-
+
public static string printTlsCertificateFlags(GLib.TlsCertificateFlags flag)
{
string errors = "";
int flags = flag;
-
+
if(flags - GLib.TlsCertificateFlags.GENERIC_ERROR >= 0)
{
errors += "GENERIC_ERROR ";
flags -= GLib.TlsCertificateFlags.VALIDATE_ALL;
}
-
+
if(flags - GLib.TlsCertificateFlags.INSECURE >= 0)
{
errors += "INSECURE ";
flags -= GLib.TlsCertificateFlags.INSECURE;
}
-
+
if(flags - GLib.TlsCertificateFlags.REVOKED >= 0)
{
errors += "REVOKED ";
flags -= GLib.TlsCertificateFlags.REVOKED;
}
-
+
if(flags - GLib.TlsCertificateFlags.EXPIRED >= 0)
{
errors += "EXPIRED ";
flags -= GLib.TlsCertificateFlags.EXPIRED;
}
-
+
if(flags - GLib.TlsCertificateFlags.NOT_ACTIVATED >= 0)
{
errors += "NOT_ACTIVATED ";
flags -= GLib.TlsCertificateFlags.NOT_ACTIVATED;
}
-
+
if(flags - GLib.TlsCertificateFlags.BAD_IDENTITY >= 0)
{
errors += "BAD_IDENTITY ";
flags -= GLib.TlsCertificateFlags.BAD_IDENTITY;
}
-
+
if(flags - GLib.TlsCertificateFlags.UNKNOWN_CA >= 0)
{
errors += "UNKNOWN_CA ";
flags -= GLib.TlsCertificateFlags.UNKNOWN_CA;
}
-
+
return errors;
}
-
+
public static bool ping(string link)
{
Logger.debug("Ping: " + link);
var uri = new Soup.URI(link);
-
+
if(uri == null)
{
Logger.error(@"Ping failed: can't parse url $link! Seems to be not valid.");
return false;
}
-
+
var message = new Soup.Message.from_uri("HEAD", uri);
-
+
if(message == null)
{
Logger.error(@"Ping failed: can't send message to $link! Seems to be not valid.");
return false;
}
-
+
var status = getSession().send_message(message);
-
+
Logger.debug(@"Ping: status $status");
-
+
if(status >= 200 && status <= 208)
{
Logger.debug("Ping successful");
return true;
}
-
+
Logger.error(@"Ping: failed %u - %s".printf(status, Soup.Status.get_phrase(status)));
-
+
return false;
}
-
-
+
+
public static bool remove_directory(string path, uint level = 0)
{
++level;
bool flag = false;
-
+
try
{
var directory = GLib.File.new_for_path(path);
-
+
var enumerator = directory.enumerate_children(GLib.FileAttribute.STANDARD_NAME, 0);
-
+
GLib.FileInfo file_info;
while((file_info = enumerator.next_file()) != null)
{
string file_name = file_info.get_name();
-
+
if((file_info.get_file_type()) == GLib.FileType.DIRECTORY)
{
remove_directory(path + file_name + "/", level);
}
-
+
var file = directory.get_child(file_name);
file.delete();
}
-
+
if(level == 1)
{
directory.delete();
@@ -331,12 +331,12 @@ public class FeedReader.Utils : GLib.Object {
{
Logger.error("Utils - remove_directory: " + e.message);
}
-
-
+
+
return flag;
}
-
-
+
+
public static string shortenURL(string url)
{
string longURL = url;
@@ -348,20 +348,20 @@ public class FeedReader.Utils : GLib.Object {
{
longURL = longURL.substring(7);
}
-
+
if(longURL.has_prefix("www."))
{
longURL = longURL.substring(4);
}
-
+
if(longURL.has_suffix("api/"))
{
longURL = longURL.substring(0, longURL.length - 4);
}
-
+
return longURL;
}
-
+
// thx to geary :)
public static string prepareSearchQuery(string raw_query)
{
@@ -390,14 +390,14 @@ StringBuilder prepared_query = new StringBuilder();
foreach(string s in words)
{
s = s.strip();
-
+
int quotes = countChar(s, '"');
if(!in_quote && quotes > 0)
{
in_quote = true;
--quotes;
}
-
+
if(!in_quote)
{
string lower = s.down();
@@ -405,25 +405,25 @@ foreach(string s in words)
{
continue;
}
-
+
if(s.has_prefix("-"))
{
s = s.substring(1);
}
-
+
if(s == "")
{
continue;
}
-
+
s = "\"" + s + "*\"";
}
-
+
if(in_quote && quotes % 2 != 0)
{
in_quote = false;
}
-
+
prepared_query.append(s);
prepared_query.append(" ");
}
@@ -677,15 +677,15 @@ 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;
@@ -876,18 +876,18 @@ try
{
articleName = DataBase.readOnly().read_article(articleID).getTitle();
}
-
+
var file = GLib.File.new_for_path(imagePath);
var mimeType = file.query_info("standard::content-type", 0, null).get_content_type();
var filter = new Gtk.FileFilter();
filter.add_mime_type(mimeType);
-
+
var map = new Gee.HashMap<string, string>();
map.set("image/gif", ".gif");
map.set("image/jpeg", ".jpeg");
map.set("image/png", ".png");
map.set("image/x-icon", ".ico");
-
+
var save_dialog = new Gtk.FileChooserDialog("Save Image",
MainWindow.get_default(),
Gtk.FileChooserAction.SAVE,
@@ -917,7 +917,7 @@ try
Logger.debug("imagePopup: save file: " + e.message);
}
break;
-
+
case Gtk.ResponseType.CANCEL:
default:
break;
@@ -1006,11 +1006,11 @@ switch(selectedRow[0])
case "feed":
IDtype = FeedListType.FEED;
break;
-
+
case "cat":
IDtype = FeedListType.CATEGORY;
break;
-
+
case "tag":
IDtype = FeedListType.TAG;
break;
diff --git a/src/Widgets/AddPopover.vala b/src/Widgets/AddPopover.vala
index 505c9f2a..df751582 100644
--- a/src/Widgets/AddPopover.vala
+++ b/src/Widgets/AddPopover.vala
@@ -14,7 +14,7 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.AddPopover : Gtk.Popover {
-
+
private Gtk.Stack m_stack;
private Gtk.Box m_box;
private Gtk.Grid m_feedGrid;
@@ -24,12 +24,12 @@ public class FeedReader.AddPopover : Gtk.Popover {
private Gtk.FileChooserButton m_chooser;
private Gtk.EntryCompletion m_complete;
private Gee.List<Category> m_cats;
-
+
public AddPopover(Gtk.Widget parent)
{
this.relative_to = parent;
this.position = Gtk.PositionType.TOP;
-
+
m_urlEntry = new Gtk.Entry();
m_urlEntry.activate.connect(() => {
m_catEntry.grab_focus();
@@ -52,7 +52,7 @@ public class FeedReader.AddPopover : Gtk.Popover {
addButton.get_style_context().add_class("suggested-action");
addButton.halign = Gtk.Align.END;
addButton.clicked.connect(addFeed);
-
+
m_feedGrid = new Gtk.Grid();
m_feedGrid.row_spacing = 5;
m_feedGrid.column_spacing = 8;
@@ -61,7 +61,7 @@ public class FeedReader.AddPopover : Gtk.Popover {
m_feedGrid.attach(catLabel, 0, 1, 1, 1);
m_feedGrid.attach(m_catEntry, 1, 1, 1, 1);
m_feedGrid.attach(addButton, 0, 2, 2, 1);
-
+
var opmlLabel = new Gtk.Label(_("OPML File:"));
opmlLabel.expand = true;
m_chooser = new Gtk.FileChooserButton(_("Select OPML File"), Gtk.FileChooserAction.OPEN);
@@ -69,47 +69,47 @@ public class FeedReader.AddPopover : Gtk.Popover {
filter.add_mime_type("text/x-opml");
m_chooser.set_filter(filter);
m_chooser.expand = true;
-
+
var importButton = new Gtk.Button.with_label(_("Import"));
importButton.get_style_context().add_class("suggested-action");
importButton.halign = Gtk.Align.END;
importButton.clicked.connect(importOPML);
importButton.sensitive = false;
-
+
m_chooser.file_set.connect(() => {
importButton.sensitive = true;
});
-
+
m_opmlGrid = new Gtk.Grid();
m_opmlGrid.row_spacing = 10;
m_opmlGrid.column_spacing = 8;
m_opmlGrid.attach(opmlLabel, 0, 0, 1, 1);
m_opmlGrid.attach(m_chooser, 1, 0, 1, 1);
m_opmlGrid.attach(importButton, 0, 1, 2, 1);
-
-
+
+
m_stack = new Gtk.Stack();
m_stack.add_titled(m_feedGrid, "feeds", _("Add feed"));
m_stack.add_titled(m_opmlGrid, "opml", _("Import OPML"));
-
+
var switcher = new Gtk.StackSwitcher();
switcher.halign = Gtk.Align.CENTER;
switcher.set_stack(m_stack);
-
+
m_box = new Gtk.Box(Gtk.Orientation.VERTICAL, 10);
m_box.margin = 10;
m_box.pack_start(switcher);
m_box.pack_start(m_stack);
-
+
this.add(m_box);
this.show_all();
m_urlEntry.grab_focus();
-
+
GLib.Idle.add(() => {
Gtk.ListStore list_store = new Gtk.ListStore(1, typeof (string));
Gtk.TreeIter iter;
m_cats = DataBase.readOnly().read_categories();
-
+
foreach(var cat in m_cats)
{
list_store.append(out iter);
@@ -122,7 +122,7 @@ public class FeedReader.AddPopover : Gtk.Popover {
return false;
}, GLib.Priority.HIGH_IDLE);
}
-
+
private void addFeed()
{
string url = m_urlEntry.text;
@@ -131,28 +131,28 @@ public class FeedReader.AddPopover : Gtk.Popover {
m_urlEntry.grab_focus();
return;
}
-
+
string? catID = DataBase.readOnly().getCategoryID(m_catEntry.text);
bool isID = true;
-
+
if(catID == null)
{
catID = m_catEntry.text;
isID = false;
}
-
-
+
+
if (GLib.Uri.parse_scheme(url) == null)
{
url = "http://" + url;
}
-
+
Logger.debug("addFeed: %s, %s".printf(url, (catID == "") ? "null" : catID));
FeedReaderBackend.get_default().addFeed(url, catID, isID);
-
+
setBusy();
}
-
+
private void importOPML()
{
try
@@ -170,7 +170,7 @@ public class FeedReader.AddPopover : Gtk.Popover {
}
setBusy();
}
-
+
private void setBusy()
{
ColumnView.get_default().footerSetBusy();
diff --git a/src/Widgets/ArticleList/ArticleList.vala b/src/Widgets/ArticleList/ArticleList.vala
index 81f0bd3c..e4db6369 100644
--- a/src/Widgets/ArticleList/ArticleList.vala
+++ b/src/Widgets/ArticleList/ArticleList.vala
@@ -15,7 +15,7 @@
public class FeedReader.ArticleList : Gtk.Overlay {
-
+
private Gtk.Stack m_stack;
private ArticleListEmptyLabel m_emptyList;
private FeedListType m_selectedFeedListType = FeedListType.FEED;
@@ -37,9 +37,9 @@ public class FeedReader.ArticleList : Gtk.Overlay {
private ulong m_handlerID1 = 0;
private ulong m_handlerID2 = 0;
private ulong m_handlerID3 = 0;
-
+
public signal void row_activated(ArticleRow? row);
-
+
public ArticleList()
{
m_emptyList = new ArticleListEmptyLabel();
@@ -57,7 +57,7 @@ public class FeedReader.ArticleList : Gtk.Overlay {
syncingBox.set_margin_right(30);
syncingBox.pack_start(m_syncSpinner);
syncingBox.pack_start(syncingLabel);
-
+
m_scroll1 = new ArticleListScroll();
m_scroll2 = new ArticleListScroll();
m_scroll1.scrolledTop.connect(dismissOverlay);
@@ -84,10 +84,10 @@ public class FeedReader.ArticleList : Gtk.Overlay {
m_List2.drag_failed.connect((context, result) => {drag_failed(context, result); return false;});
m_scroll1.add(m_List1);
m_scroll2.add(m_List2);
-
+
m_currentList = m_List1;
m_currentScroll = m_scroll1;
-
+
m_stack = new Gtk.Stack();
m_stack.set_transition_type(Gtk.StackTransitionType.CROSSFADE);
m_stack.set_transition_duration(100);
@@ -114,16 +114,16 @@ public class FeedReader.ArticleList : Gtk.Overlay {
}
});
}
-
+
public void newList(Gtk.StackTransitionType transition = Gtk.StackTransitionType.CROSSFADE)
{
Logger.debug("ArticleList: newList");
-
+
if(m_overlay != null)
{
m_overlay.dismiss();
}
-
+
Logger.debug("ArticleList: disallow signals from scroll");
m_currentScroll.allowSignals(false);
Gee.List<Article> articles = new Gee.ArrayList<Article>();
@@ -131,7 +131,7 @@ public class FeedReader.ArticleList : Gtk.Overlay {
int height = this.get_allocated_height();
uint limit = height / 100 + 5;
offset = getListOffset();
-
+
Logger.debug("load articles from db");
articles = DataBase.readOnly().read_articles(m_selectedFeedListID,
m_selectedFeedListType,
@@ -140,7 +140,7 @@ public class FeedReader.ArticleList : Gtk.Overlay {
limit,
offset);
Logger.debug("actual articles loaded: " + articles.size.to_string());
-
+
if(articles.size == 0)
{
m_currentList.emptyList();
@@ -163,7 +163,7 @@ public class FeedReader.ArticleList : Gtk.Overlay {
m_currentList.disconnect(m_handlerID1);
m_handlerID1 = 0;
}
-
+
// switch up lists
if(m_currentList == m_List1)
{
@@ -179,27 +179,27 @@ public class FeedReader.ArticleList : Gtk.Overlay {
m_currentScroll = m_scroll1;
m_stack.set_visible_child_full("list1", transition);
}
-
+
m_currentScroll.scrollToPos(0, false);
-
+
// restore the previous selected row
m_handlerID1 = m_currentList.loadDone.connect(() => {
restoreSelectedRow();
restoreScrollPos();
Logger.debug("ArticleList: allow signals from scroll");
m_currentScroll.allowSignals(true);
-
+
if(m_handlerID1 != 0)
{
m_currentList.disconnect(m_handlerID1);
m_handlerID1 = 0;
}
});
-
+
m_currentList.newList(articles);
}
}
-
+
private void checkForNewRows()
{
Logger.debug("ArticleList: checkForNewRows");
@@ -211,19 +211,19 @@ public class FeedReader.ArticleList : Gtk.Overlay {
loadNewer(count, offset);
}
}
-
+
private void loadMore()
{
if(m_currentList == null)
{
return;
}
-
+
Logger.debug("ArticleList.loadmore()");
-
+
Logger.debug("load articles from db");
uint offset = m_currentList.getSizeForState() + determineNewRowCount(null, null);
-
+
var articles = DataBase.readOnly().read_articles(m_selectedFeedListID,
m_selectedFeedListType,
m_state,
@@ -231,7 +231,7 @@ public class FeedReader.ArticleList : Gtk.Overlay {
m_dynamicRowThreshold,
offset);
Logger.debug("actual articles loaded: " + articles.size.to_string());
-
+
if(articles.size > 0)
{
m_currentScroll.valueChanged.disconnect(updateVisibleRows);
@@ -239,7 +239,7 @@ public class FeedReader.ArticleList : Gtk.Overlay {
m_handlerID2 = m_currentList.loadDone.connect(() => {
m_currentScroll.startScrolledDownCooldown();
m_currentScroll.valueChanged.connect(updateVisibleRows);
-
+
if(m_handlerID2 != 0)
{
m_currentList.disconnect(m_handlerID2);
@@ -252,11 +252,11 @@ public class FeedReader.ArticleList : Gtk.Overlay {
m_currentScroll.startScrolledDownCooldown();
}
}
-
+
private void loadNewer(int newCount, int offset)
{
Logger.debug(@"ArticleList: loadNewer($newCount)");
-
+
Logger.debug("load articles from db");
var articles = DataBase.readOnly().read_articles(m_selectedFeedListID,
m_selectedFeedListType,
@@ -265,7 +265,7 @@ public class FeedReader.ArticleList : Gtk.Overlay {
newCount,
offset);
Logger.debug("actual articles loaded: " + articles.size.to_string());
-
+
if(articles.size > 0)
{
if(m_stack.get_visible_child_name() == "empty")
@@ -279,12 +279,12 @@ public class FeedReader.ArticleList : Gtk.Overlay {
m_stack.set_visible_child_full("list2", Gtk.StackTransitionType.CROSSFADE);
}
}
-
+
m_currentScroll.valueChanged.disconnect(updateVisibleRows);
m_currentList.addTop(articles);
m_handlerID3 = m_currentList.loadDone.connect(() => {
m_currentScroll.valueChanged.connect(updateVisibleRows);
-
+
if(m_handlerID3 != 0)
{
m_currentList.disconnect(m_handlerID3);
@@ -296,13 +296,13 @@ public class FeedReader.ArticleList : Gtk.Overlay {
{
m_stack.set_visible_child_full("empty", Gtk.StackTransitionType.CROSSFADE);
}
-
+
}
-
+
public void updateArticleList()
{
Logger.debug(@"ArticleList: updateArticleList()");
-
+
if(m_stack.get_visible_child_name() == "empty"
|| m_stack.get_visible_child_name() == "syncing")
{
@@ -310,11 +310,11 @@ public class FeedReader.ArticleList : Gtk.Overlay {
newList(Gtk.StackTransitionType.CROSSFADE);
return;
}
-
+
m_currentList.setAllUpdated(false);
var articles = DataBase.readOnly().read_article_stats(m_currentList.getIDs());
var children = m_currentList.get_children();
-
+
foreach(var row in children)
{
var tmpRow = row as ArticleRow;
@@ -326,21 +326,21 @@ public class FeedReader.ArticleList : Gtk.Overlay {
tmpRow.setUpdated(true);
}
}
-
+
m_currentList.removeObsoleteRows();
int length = (int)m_currentList.get_children().length();
-
+
for(int i = 1; i < length; i++)
{
ArticleRow? first = m_currentList.get_row_at_index(i-1) as ArticleRow;
ArticleRow? second = m_currentList.get_row_at_index(i) as ArticleRow;
-
+
if(first == null
|| second == null)
{
continue;
}
-
+
var insertArticles = DataBase.readOnly().read_article_between( m_selectedFeedListID,
m_selectedFeedListType,
m_state,
@@ -349,7 +349,7 @@ public class FeedReader.ArticleList : Gtk.Overlay {
first.getDate(),
second.getID(),
second.getDate());
-
+
foreach(Article a in insertArticles)
{
if(m_currentList.insertArticle(a, i))
@@ -359,15 +359,15 @@ public class FeedReader.ArticleList : Gtk.Overlay {
}
}
}
-
+
checkForNewRows();
}
-
+
private int determineNewRowCount(int? newCount, out int? offset)
{
int count = 0;
ArticleRow? firstRow = m_currentList.getFirstRow();
-
+
if(firstRow != null)
{
count = DataBase.readOnly().getArticleCountNewerThanID(
@@ -377,7 +377,7 @@ public class FeedReader.ArticleList : Gtk.Overlay {
m_state,
m_searchTerm);
}
-
+
if(newCount != null && newCount < count)
{
offset = count - newCount;
@@ -387,10 +387,10 @@ public class FeedReader.ArticleList : Gtk.Overlay {
{
offset = 0;
}
-
+
return count;
}
-
+
private void removeInvisibleRows(ScrollDirection direction)
{
if(m_scrollChangedTimeout != 0)
@@ -398,7 +398,7 @@ public class FeedReader.ArticleList : Gtk.Overlay {
GLib.Source.remove(m_scrollChangedTimeout);
m_scrollChangedTimeout = 0;
}
-
+
// remove lower ArticleRows only after scrolling up
if(direction == ScrollDirection.UP)
{
@@ -406,7 +406,7 @@ public class FeedReader.ArticleList : Gtk.Overlay {
Logger.debug("ArticleList: remove invisible rows below");
var children = m_currentList.get_children();
children.reverse();
-
+
foreach(var r in children)
{
var row = r as ArticleRow;
@@ -427,7 +427,7 @@ public class FeedReader.ArticleList : Gtk.Overlay {
});
}
}
-
+
private void updateVisibleRows(ScrollDirection direction)
{
if(direction == ScrollDirection.DOWN && Settings.general().get_boolean("articlelist-mark-scrolling"))
@@ -435,7 +435,7 @@ public class FeedReader.ArticleList : Gtk.Overlay {
var children = m_currentList.get_children();
children.reverse();
var visibleArticles = new Gee.HashSet<string>();
-
+
foreach(var r in children)
{
var row = r as ArticleRow;
@@ -454,10 +454,10 @@ public class FeedReader.ArticleList : Gtk.Overlay {
}
m_currentList.setVisibleRows(visibleArticles);
}
-
+
removeInvisibleRows(direction);
}
-
+
private bool keyPressed(Gdk.EventKey event)
{
switch(event.keyval)
@@ -469,7 +469,7 @@ public class FeedReader.ArticleList : Gtk.Overlay {
m_currentScroll.scrollDiff(diff);
}
break;
-
+
case Gdk.Key.Up:
int diff = m_currentList.move(false);
if(m_state != ArticleListState.UNREAD)
@@ -477,30 +477,30 @@ public class FeedReader.ArticleList : Gtk.Overlay {
m_currentScroll.scrollDiff(diff);
}
break;
-
+
case Gdk.Key.Page_Down:
m_currentScroll.scrollToPos(-1);
break;
-
+
case Gdk.Key.Page_Up:
m_currentScroll.scrollToPos(0);
break;
}
return true;
}
-
+
public int move(bool down)
{
int diff = m_currentList.move(down);
-
+
if(m_state != ArticleListState.UNREAD)
{
m_currentScroll.scrollDiff(diff);
}
-
+
return diff;
}
-
+
public void showOverlay()
{
Logger.debug("ArticleList: showOverlay");
@@ -509,7 +509,7 @@ public class FeedReader.ArticleList : Gtk.Overlay {
showNotification();
}
}
-
+
private void showNotification()
{
if(m_overlay != null
@@ -517,7 +517,7 @@ public class FeedReader.ArticleList : Gtk.Overlay {
{
return;
}
-
+
m_overlay = new InAppNotification.withIcon(
_("New articles"),
"feed-arrow-up-symbolic",
@@ -531,7 +531,7 @@ public class FeedReader.ArticleList : Gtk.Overlay {
this.add_overlay(m_overlay);
this.show_all();
}
-
+
public void dismissOverlay()
{
if(m_overlay != null)
@@ -539,7 +539,7 @@ public class FeedReader.ArticleList : Gtk.Overlay {
m_overlay.dismiss();
}
}
-
+
public Article? getSelectedArticle()
{
if(m_stack.get_visible_child_name() == "empty"
@@ -547,10 +547,10 @@ public class FeedReader.ArticleList : Gtk.Overlay {
{
return null;
}
-
+
return m_currentList.getSelectedArticle();
}
-
+
public Article? getFirstArticle()
{
ArticleRow? selectedRow = m_currentList.getFirstRow();
@@ -558,32 +558,32 @@ public class FeedReader.ArticleList : Gtk.Overlay {
{
return null;
}
-
+
return selectedRow.getArticle();
}
-
+
public ArticleStatus toggleReadSelected()
{
return m_currentList.toggleReadSelected();
}
-
+
public ArticleStatus toggleMarkedSelected()
{
return m_currentList.toggleMarkedSelected();
}
-
+
public void getSavedState(out double scrollPos, out int rowOffset)
{
Logger.debug("ArticleList: get State");
-
+
// get current scroll position
scrollPos = m_currentScroll.getScroll();
-
+
// the amount of rows that are above the the current viewport
// and thus are not visible at the moment
// they can be skipped on startup and lazy-loaded later
rowOffset = 0;
-
+
var children = m_currentList.get_children();
foreach(var row in children)
{
@@ -591,7 +591,7 @@ public class FeedReader.ArticleList : Gtk.Overlay {
if(tmpRow != null)
{
var height = tmpRow.get_allocated_height();
-
+
if((scrollPos-height) >= 0)
{
scrollPos -= height;
@@ -603,33 +603,33 @@ public class FeedReader.ArticleList : Gtk.Overlay {
}
}
}
-
+
rowOffset += determineNewRowCount(null, null);
Logger.debug("scrollpos %f".printf(scrollPos));
Logger.debug("offset %i".printf(rowOffset));
}
-
+
private uint getListOffset()
{
uint offset = (uint)Settings.state().get_int("articlelist-row-offset");
Settings.state().set_int("articlelist-row-offset", 0);
return offset;
}
-
+
private void restoreSelectedRow()
{
string selectedRow = Settings.state().get_string("articlelist-selected-row");
-
+
if(selectedRow != "")
{
m_currentList.selectRow(selectedRow, 300);
}
if(!m_currentList.has_id(selectedRow))
{
- Settings.state().set_string("articlelist-selected-row", "");
+ Settings.state().set_string("articlelist-selected-row", "");
}
}
-
+
private void restoreScrollPos()
{
var pos = Settings.state().get_double("articlelist-scrollpos");
@@ -640,27 +640,27 @@ public class FeedReader.ArticleList : Gtk.Overlay {
Settings.state().set_double("articlelist-scrollpos", 0);
}
}
-
+
public void removeTagFromSelectedRow(string tagID)
{
m_currentList.removeTagFromSelectedRow(tagID);
}
-
+
public string getSelectedURL()
{
return m_currentList.getSelectedURL();
}
-
+
public bool selectedIsFirst()
{
return m_currentList.selectedIsFirst();
}
-
+
public bool selectedIsLast()
{
return m_currentList.selectedIsLast();
}
-
+
public Gdk.RGBA getBackgroundColor()
{
// code according to: https://blogs.gnome.org/mclasen/2015/11/20/a-gtk-update/
@@ -671,43 +671,43 @@ public class FeedReader.ArticleList : Gtk.Overlay {
context.restore();
return color;
}
-
+
public void setSelectedFeed(string feedID)
{
m_selectedFeedListID = feedID;
m_List1.setSelectedFeed(feedID);
m_List2.setSelectedFeed(feedID);
}
-
+
public void setSelectedType(FeedListType type)
{
m_selectedFeedListType = type;
m_List1.setSelectedType(type);
m_List2.setSelectedType(type);
}
-
+
public void setState(ArticleListState state)
{
m_state = state;
m_List1.setState(state);
m_List2.setState(state);
}
-
+
public ArticleListState getState()
{
return m_state;
}
-
+
public void setSearchTerm(string searchTerm)
{
m_searchTerm = searchTerm;
}
-
+
public void markAllAsRead()
{
m_currentList.markAllAsRead();
}
-
+
public void openSelected()
{
Article? selectedArticle = m_currentList.getSelectedArticle();
@@ -723,14 +723,14 @@ public class FeedReader.ArticleList : Gtk.Overlay {
}
}
}
-
+
public void centerSelectedRow()
{
int scroll = -(int)(m_currentScroll.getPageSize()/2);
scroll += m_currentList.selectedRowPosition();
m_currentScroll.scrollToPos(scroll);
}
-
+
public void syncStarted()
{
m_syncing = true;
@@ -740,7 +740,7 @@ public class FeedReader.ArticleList : Gtk.Overlay {
m_syncSpinner.start();
}
}
-
+
public void syncFinished()
{
m_syncing = false;
@@ -749,7 +749,7 @@ public class FeedReader.ArticleList : Gtk.Overlay {
m_stack.set_visible_child_full("empty", Gtk.StackTransitionType.CROSSFADE);
}
}
-
+
private void rowActivated(Gtk.ListBoxRow row)
{
var article_row = row as ArticleRow;
@@ -757,7 +757,7 @@ public class FeedReader.ArticleList : Gtk.Overlay {
Settings.state().set_string("articlelist-selected-row", article_row.getID());
row_activated(article_row);
}
-
+
public void clear()
{
m_currentList.emptyList();
diff --git a/src/Widgets/ArticleList/ArticleListBox.vala b/src/Widgets/ArticleList/ArticleListBox.vala
index f20a1108..d47dc9d4 100644
--- a/src/Widgets/ArticleList/ArticleListBox.vala
+++ b/src/Widgets/ArticleList/ArticleListBox.vala
@@ -14,7 +14,7 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.ArticleListBox : Gtk.ListBox {
-
+
private Gee.List<Article> m_lazyQeue;
private uint m_idleID = 0;
private string m_name;
@@ -25,10 +25,10 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
private string m_selectedArticle = "";
private Gee.HashMap<string, ArticleRow> m_articles;
private Gee.HashSet<string> m_visibleArticles;
-
+
public signal void balanceNextScroll(ArticleListBalance mode);
public signal void loadDone();
-
+
public ArticleListBox(string name)
{
m_name = name;
@@ -38,7 +38,7 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
this.set_selection_mode(Gtk.SelectionMode.BROWSE);
this.row_activated.connect(rowActivated);
}
-
+
public void newList(Gee.List<Article> articles)
{
stopLoading();
@@ -47,7 +47,7 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
m_lazyQeue = articles;
addRow(ArticleListBalance.NONE);
}
-
+
public void addTop(Gee.List<Article> articles)
{
stopLoading();
@@ -55,7 +55,7 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
m_lazyQeue = articles;
addRow(ArticleListBalance.TOP, true);
}
-
+
public void addBottom(Gee.List<Article> articles)
{
stopLoading();
@@ -63,7 +63,7 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
m_lazyQeue = articles;
addRow(ArticleListBalance.NONE);
}
-
+
private bool stopLoading()
{
if(m_idleID > 0)
@@ -72,10 +72,10 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
m_idleID = 0;
return true;
}
-
+
return false;
}
-
+
private void setPos(Gee.List<Article> articles, int pos)
{
foreach(Article a in articles)
@@ -83,7 +83,7 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
a.setPos(pos);
}
}
-
+
private void addRow(ArticleListBalance balance, bool reverse = false, bool animate = false)
{
if(m_lazyQeue.size == 0)
@@ -91,23 +91,23 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
Logger.debug(@"ArticleListbox$m_name: lazyQueu == 0 -> return");
return;
}
-
-
+
+
var priority = GLib.Priority.DEFAULT_IDLE;
if(ColumnView.get_default().playingMedia())
{
priority = GLib.Priority.HIGH_IDLE;
}
-
+
m_idleID = GLib.Idle.add(() => {
-
+
if(m_lazyQeue == null || m_lazyQeue.size == 0)
{
return false;
}
-
+
Article item;
-
+
if(reverse)
{
item = m_lazyQeue.last();
@@ -116,7 +116,7 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
{
item = m_lazyQeue.first();
}
-
+
// check if row is already there
if(m_articles.has_key(item.getArticleID()))
{
@@ -124,9 +124,9 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
checkQueue(item, balance, reverse, animate);
return false;
}
-
+
balanceNextScroll(balance);
-
+
var newRow = new ArticleRow(item);
newRow.rowStateChanged.connect(rowStateChanged);
newRow.drag_begin.connect((widget, context) => {
@@ -141,15 +141,15 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
drag_failed(context, result);
return false;
});
-
+
newRow.realize.connect(() => {
checkQueue(item, balance, reverse, animate);
});
-
+
m_articles.set(item.getArticleID(), newRow);
-
+
this.insert(newRow, item.getPos());
-
+
if(animate)
{
newRow.reveal(true, 150);
@@ -158,11 +158,11 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
{
newRow.reveal(true, 0);
}
-
+
return false;
}, priority);
}
-
+
private void checkQueue(Article item, ArticleListBalance balance, bool reverse = false, bool animate = false)
{
if(m_lazyQeue.size > 1)
@@ -182,7 +182,7 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
m_idleID = 0;
}
}
-
+
public void emptyList()
{
var children = get_children();
@@ -193,28 +193,28 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
}
m_articles.clear();
}
-
+
public void setSelectedFeed(string feedID)
{
m_selectedFeedListID = feedID;
}
-
+
public void setSelectedType(FeedListType type)
{
m_selectedFeedListType = type;
}
-
+
private void selectAfter(ArticleRow row, int time)
{
this.select_row(row);
setRead(row);
-
+
if(m_selectSourceID > 0)
{
GLib.Source.remove(m_selectSourceID);
m_selectSourceID = 0;
}
-
+
m_selectSourceID = Timeout.add(time, () => {
if(!ColumnView.get_default().searchFocused())
{
@@ -224,7 +224,7 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
return false;
});
}
-
+
private void setRead(ArticleRow row)
{
if(row.getArticle().getUnread() == ArticleStatus.UNREAD)
@@ -233,36 +233,36 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
FeedReaderBackend.get_default().updateArticleRead(row.getArticle());
}
}
-
+
public ArticleStatus toggleReadSelected()
{
ArticleRow selectedRow = this.get_selected_row() as ArticleRow;
-
+
if(selectedRow == null)
{
return ArticleStatus.READ;
}
-
+
return selectedRow.toggleUnread();
}
-
+
public ArticleStatus toggleMarkedSelected()
{
ArticleRow selectedRow = this.get_selected_row() as ArticleRow;
-
+
if(selectedRow == null)
{
return ArticleStatus.UNMARKED;
}
-
+
return selectedRow.toggleMarked();
}
-
+
public void setState(ArticleListState state)
{
m_state = state;
}
-
+
public Article? getSelectedArticle()
{
ArticleRow selectedRow = this.get_selected_row() as ArticleRow;
@@ -270,10 +270,10 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
{
return selectedRow.getArticle();
}
-
+
return null;
}
-
+
public string getSelectedURL()
{
ArticleRow selectedRow = this.get_selected_row() as ArticleRow;
@@ -281,15 +281,15 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
{
return selectedRow.getURL();
}
-
+
if(this.get_children().length() == 0)
{
return "empty";
}
-
+
return "";
}
-
+
public int move(bool down)
{
int time = 300;
@@ -307,21 +307,21 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
return 0;
}
}
-
+
var selectedRow = this.get_selected_row() as ArticleRow;
var height = selectedRow.get_allocated_height();
ArticleRow nextRow = null;
-
+
var rows = this.get_children();
-
+
if(!down)
{
rows.reverse();
}
-
+
int current = rows.index(selectedRow);
uint length = rows.length();
-
+
do
{
current++;
@@ -329,23 +329,23 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
{
return 0;
}
-
+
nextRow = rows.nth_data(current) as ArticleRow;
}
while(!nextRow.isBeingRevealed());
-
+
selectAfter(nextRow, time);
-
+
Logger.debug(@"ArticleListBox.move: height: $height");
-
+
if(down)
{
return height;
}
-
+
return -height;
}
-
+
public void removeRow(ArticleRow row, int animateDuration = 700)
{
var id = row.getID();
@@ -359,13 +359,13 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
return false;
});
}
-
+
private void rowActivated(Gtk.ListBoxRow row)
{
var selectedRow = (ArticleRow)row;
string selectedID = selectedRow.getID();
setRead(selectedRow);
-
+
if(m_selectedArticle != selectedID)
{
if(m_state != ArticleListState.ALL || m_selectedFeedListType == FeedListType.TAG)
@@ -389,10 +389,10 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
}
}
}
-
+
m_selectedArticle = selectedID;
}
-
+
private void rowStateChanged(ArticleStatus status)
{
Logger.debug("state changed");
@@ -428,7 +428,7 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
break;
}
}
-
+
public void setVisibleRows(Gee.HashSet<string> visibleArticles)
{
var invisibleRows = new Gee.HashSet<string>();
@@ -440,9 +440,9 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
}
return true;
});
-
+
m_visibleArticles = visibleArticles;
-
+
var children = this.get_children();
foreach(var row in children)
{
@@ -458,64 +458,64 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
}
}
}
-
+
public void removeTagFromSelectedRow(string tagID)
{
ArticleRow selectedRow = this.get_selected_row() as ArticleRow;
-
+
if(selectedRow == null)
{
return;
}
-
+
selectedRow.removeTag(tagID);
}
-
+
public ArticleRow? getFirstRow()
{
var children = this.get_children();
-
+
if(children == null)
{
return null;
}
-
+
var firstRow = children.first().data as ArticleRow;
-
+
if(firstRow == null)
{
return null;
}
-
+
return firstRow;
}
-
+
public ArticleRow? getLastRow()
{
var children = this.get_children();
-
+
if(children == null)
{
return null;
}
-
+
var lastRow = children.last().data as ArticleRow;
-
+
if(lastRow == null)
{
return null;
}
-
+
return lastRow;
}
-
+
public bool selectedIsFirst()
{
var selectedRow = this.get_selected_row() as ArticleRow;
var children = this.get_children();
int n = children.index(selectedRow);
var lastRow = children.first().data as ArticleRow;
-
+
if(n == 0)
{
return true;
@@ -524,10 +524,10 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
{
return true;
}
-
+
return false;
}
-
+
public bool selectedIsLast()
{
var selectedRow = this.get_selected_row() as ArticleRow;
@@ -535,7 +535,7 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
int n = children.index(selectedRow);
uint length = children.length();
var lastRow = children.last().data as ArticleRow;
-
+
if(n + 1 == length)
{
return true;
@@ -544,14 +544,14 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
{
return true;
}
-
+
return false;
}
-
+
public void markAllAsRead()
{
var children = this.get_children();
-
+
foreach(var row in children)
{
var tmpRow = row as ArticleRow;
@@ -561,17 +561,17 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
}
}
}
-
+
public int selectedRowPosition()
{
ArticleRow selectedRow = this.get_selected_row() as ArticleRow;
-
+
int scroll = 0;
if(selectedRow == null)
{
return scroll;
}
-
+
var FeedChildList = this.get_children();
foreach(Gtk.Widget row in FeedChildList)
{
@@ -606,7 +606,7 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
selectAfter(m_articles.get(articleID), time);
}
}
-
+
private void highlightRow(string articleID)
{
var children = this.get_children();
@@ -619,7 +619,7 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
}
}
}
-
+
private void unHighlightRow()
{
var children = this.get_children();
@@ -632,12 +632,12 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
}
}
}
-
+
public int getSize()
{
return m_articles.size;
}
-
+
public int getSizeForState()
{
if(m_state == ArticleListState.UNREAD)
@@ -654,14 +654,14 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
}
return unread;
}
-
+
return getSize();
}
-
+
public bool needLoadMore(int height)
{
int rowHeight = 0;
-
+
var children = this.get_children();
foreach(var row in children)
{
@@ -671,15 +671,15 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
rowHeight += tmpRow.get_allocated_height();
}
}
-
+
if(rowHeight < height + 100)
{
return true;
}
-
+
return false;
}
-
+
public Gee.List<string> getIDs()
{
var tmp = new Gee.LinkedList<string>();
@@ -689,7 +689,7 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
});
return tmp;
}
-
+
public void setAllUpdated(bool updated = false)
{
var children = this.get_children();
@@ -702,7 +702,7 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
}
}
}
-
+
public void removeObsoleteRows()
{
var children = this.get_children();
@@ -715,7 +715,7 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
}
}
}
-
+
public bool insertArticle(Article a, int pos)
{
if(m_articles.has_key(a.getArticleID()))
@@ -723,7 +723,7 @@ public class FeedReader.ArticleListBox : Gtk.ListBox {
Logger.debug(@"ArticleListbox$m_name: row with ID %s is already present".printf(a.getArticleID()));
return false;
}
-
+
a.setPos(pos);
stopLoading();
var list = new Gee.LinkedList<Article>();
diff --git a/src/Widgets/ArticleList/ArticleListEmptyLabel.vala b/src/Widgets/ArticleList/ArticleListEmptyLabel.vala
index 5a3aab11..ddf18c74 100644
--- a/src/Widgets/ArticleList/ArticleListEmptyLabel.vala
+++ b/src/Widgets/ArticleList/ArticleListEmptyLabel.vala
@@ -14,7 +14,7 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.ArticleListEmptyLabel : Gtk.Label {
-
+
public ArticleListEmptyLabel()
{
this.set_text(_("No Articles"));
@@ -28,7 +28,7 @@ public class FeedReader.ArticleListEmptyLabel : Gtk.Label {
this.set_justify(Gtk.Justification.CENTER);
this.show_all();
}
-
+
public void build(string selectedID, FeedListType type, ArticleListState state, string searchTerm)
{
string message = "";
@@ -184,10 +184,10 @@ public class FeedReader.ArticleListEmptyLabel : Gtk.Label {
message = _("No articles");
}
}
-
+
}
this.get_style_context().add_class("dim-label");
this.set_text(message);
}
-
+
}
diff --git a/src/Widgets/ArticleList/ArticleListScroll.vala b/src/Widgets/ArticleList/ArticleListScroll.vala
index fdfc647f..dbbd6be5 100644
--- a/src/Widgets/ArticleList/ArticleListScroll.vala
+++ b/src/Widgets/ArticleList/ArticleListScroll.vala
@@ -14,22 +14,22 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.ArticleListScroll : Gtk.ScrolledWindow {
-
+
public signal void scrolledTop();
public signal void scrolledBottom();
public signal void valueChanged(ScrollDirection direction);
-
+
private double m_upperCache = 0.0;
private double m_valueCache = 0.0;
private double m_valueThreshold = 50.0;
private double m_bottomThreshold = 200.0;
private ArticleListBalance m_balance = ArticleListBalance.NONE;
-
+
private bool m_allowSignals = true;
private bool m_scrolledTopOnCooldown = false;
private bool m_scrolledBottomOnCooldown = false;
private int m_scrollCooldown = 500; // cooldown in ms
-
+
//Transition times
private int64 m_startTime = 0;
private int64 m_endTime = 0;
@@ -39,16 +39,16 @@ public class FeedReader.ArticleListScroll : Gtk.ScrolledWindow {
private uint m_scrollCallbackID = 0;
private uint m_savetyFallbackID = 0;
private uint m_scrollCooldownID = 0;
-
-
-
+
+
+
public ArticleListScroll()
{
vadjustment.notify["upper"].connect(trackUpper);
vadjustment.notify["value"].connect(trackValue);
this.set_size_request(250, 0);
}
-
+
private void trackUpper()
{
double upper = vadjustment.upper;
@@ -66,16 +66,16 @@ public class FeedReader.ArticleListScroll : Gtk.ScrolledWindow {
this.vadjustment.value -= inc;
m_balance = ArticleListBalance.NONE;
}
-
+
if(GLib.Math.fabs(vadjustment.upper - m_upperCache) > 2.0)
{
checkScrolledDown();
}
-
+
m_upperCache = vadjustment.upper;
m_valueCache = vadjustment.value;
}
-
+
private void trackValue()
{
if(vadjustment.value > (m_valueCache + m_valueThreshold))
@@ -86,14 +86,14 @@ public class FeedReader.ArticleListScroll : Gtk.ScrolledWindow {
{
valueChanged(ScrollDirection.UP);
}
-
+
checkScrolledTop();
checkScrolledDown();
-
+
m_upperCache = vadjustment.upper;
m_valueCache = vadjustment.value;
}
-
+
private void checkScrolledTop()
{
if(m_allowSignals
@@ -112,7 +112,7 @@ public class FeedReader.ArticleListScroll : Gtk.ScrolledWindow {
});
}
}
-
+
private void checkScrolledDown()
{
double max = vadjustment.upper - vadjustment.page_size;
@@ -132,7 +132,7 @@ public class FeedReader.ArticleListScroll : Gtk.ScrolledWindow {
});
}
}
-
+
public void startScrolledDownCooldown()
{
if(m_scrollCooldownID != 0)
@@ -140,7 +140,7 @@ public class FeedReader.ArticleListScroll : Gtk.ScrolledWindow {
GLib.Source.remove(m_scrollCooldownID);
m_scrollCooldownID = 0;
}
-
+
m_scrollCooldownID = GLib.Timeout.add(m_scrollCooldown, () => {
Logger.debug("ArticleListScroll: scrolled down off cooldown");
m_scrollCooldownID = 0;
@@ -156,22 +156,22 @@ public class FeedReader.ArticleListScroll : Gtk.ScrolledWindow {
Logger.debug("ArticleListScroll: trigger scrolledBottom()");
scrolledBottom();
}
-
+
return GLib.Source.REMOVE;
});
}
-
+
public void balanceNextScroll(ArticleListBalance mode)
{
m_balance = mode;
}
-
+
public void scrollDiff(double diff, bool animate = true)
{
Logger.debug("ArticleListScroll.scrollDiff: value: %f - diff: %f".printf(this.vadjustment.value, diff));
scrollToPos(this.vadjustment.value + diff, animate);
}
-
+
public void scrollToPos(double pos, bool animate = true)
{
if(!this.get_mapped())
@@ -179,13 +179,13 @@ public class FeedReader.ArticleListScroll : Gtk.ScrolledWindow {
setScroll(pos);
return;
}
-
+
if(Gtk.Settings.get_default().gtk_enable_animations && animate)
{
Logger.debug(@"ArticleListScroll.scrollToPos: $pos");
m_startTime = this.get_frame_clock().get_frame_time();
m_endTime = m_startTime + m_transitionDuration;
-
+
double leftOverScroll = 0.0;
if(m_scrollCallbackID != 0)
{
@@ -193,10 +193,10 @@ public class FeedReader.ArticleListScroll : Gtk.ScrolledWindow {
this.remove_tick_callback(m_scrollCallbackID);
m_scrollCallbackID = 0;
}
-
+
Logger.debug(@"ArticleListScroll.scrollToPos: leftOverScroll $leftOverScroll");
Logger.debug(@"ArticleListScroll.scrollToPos: %f".printf(pos+leftOverScroll));
-
+
if(pos == -1)
{
m_transitionDiff = (vadjustment.upper - vadjustment.page_size - vadjustment.value);
@@ -205,7 +205,7 @@ public class FeedReader.ArticleListScroll : Gtk.ScrolledWindow {
{
m_transitionDiff = (pos-this.vadjustment.value)+leftOverScroll;
}
-
+
m_transitionStartValue = this.vadjustment.value;
Logger.debug(@"ArticleListScroll.scrollDiff: startValue $m_transitionStartValue");
m_scrollCallbackID = this.add_tick_callback(scrollTick);
@@ -215,12 +215,12 @@ public class FeedReader.ArticleListScroll : Gtk.ScrolledWindow {
setScroll(pos);
}
}
-
+
public double getScroll()
{
return this.vadjustment.value;
}
-
+
private void setScroll(double pos)
{
if(pos == -1)
@@ -232,36 +232,36 @@ public class FeedReader.ArticleListScroll : Gtk.ScrolledWindow {
this.vadjustment.value = pos;
}
}
-
+
public double getPageSize()
{
return this.vadjustment.page_size;
}
-
+
public int isVisible(Gtk.ListBoxRow row, int additionalRows = 0)
{
var rowHeight = row.get_allocated_height();
var scrollHeight = this.get_allocated_height();
int x, y = 0;
-
+
row.translate_coordinates(this, 0, 0, out x, out y);
-
+
// row is (additionalRows * rowHeight) above the current viewport
if(y < -( (1+additionalRows) * rowHeight))
{
return -1;
}
-
+
// row is (additionalRows * rowHeight) below the current viewport
if(y > additionalRows * rowHeight + scrollHeight)
{
return 1;
}
-
+
// row is visible
return 0;
}
-
+
private bool scrollTick(Gtk.Widget widget, Gdk.FrameClock frame_clock)
{
if(!this.get_mapped())
@@ -269,19 +269,19 @@ public class FeedReader.ArticleListScroll : Gtk.ScrolledWindow {
vadjustment.value = m_transitionStartValue + m_transitionDiff;
return false;
}
-
+
int64 now = frame_clock.get_frame_time();
double t = 1.0;
-
+
if(now < this.m_endTime)
{
t = (now - m_startTime) / (double)(m_endTime - m_startTime);
}
-
+
t = easeOutCubic(t);
-
+
this.vadjustment.value = m_transitionStartValue + (t * m_transitionDiff);
-
+
if(this.vadjustment.value <= 0 || now >= m_endTime)
{
this.queue_draw();
@@ -289,19 +289,19 @@ public class FeedReader.ArticleListScroll : Gtk.ScrolledWindow {
m_scrollCallbackID = 0;
return false;
}
-
+
return true;
}
-
+
inline double easeOutCubic(double t)
{
double p = t - 1;
return p * p * p +1;
}
-
+
public void allowSignals(bool allow)
{
m_allowSignals = allow;
}
-
+
}
diff --git a/src/Widgets/ArticleRow.vala b/src/Widgets/ArticleRow.vala
index 94eee403..9b20a005 100644
--- a/src/Widgets/ArticleRow.vala
+++ b/src/Widgets/ArticleRow.vala
@@ -14,7 +14,7 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.ArticleRow : Gtk.ListBoxRow {
-
+
private Article m_article;
private Gtk.Label m_label;
private Gtk.Image m_icon;
@@ -30,21 +30,21 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
private bool m_hovering_row = false;
private bool m_populated = false;
public signal void rowStateChanged(ArticleStatus status);
-
+
public ArticleRow(Article article)
{
m_article = article;
-
+
m_revealer = new Gtk.Revealer();
m_revealer.set_transition_type(Gtk.RevealerTransitionType.SLIDE_DOWN);
m_revealer.set_reveal_child(false);
this.set_size_request(0, 100);
this.add(m_revealer);
this.show_all();
-
+
GLib.Idle.add(populate, GLib.Priority.HIGH_IDLE);
}
-
+
~ArticleRow()
{
if(m_unread_eventbox != null)
@@ -53,26 +53,26 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
m_unread_eventbox.leave_notify_event.disconnect(unreadIconLeave);
m_unread_eventbox.button_press_event.disconnect(unreadIconClicked);
}
-
+
if(m_marked_eventbox != null)
{
m_marked_eventbox.enter_notify_event.disconnect(markedIconEnter);
m_marked_eventbox.leave_notify_event.disconnect(markedIconLeave);
m_marked_eventbox.button_press_event.disconnect(markedIconClicked);
}
-
+
if(m_eventBox != null)
{
m_eventBox.enter_notify_event.disconnect(rowEnter);
m_eventBox.leave_notify_event.disconnect(rowLeave);
m_eventBox.button_press_event.disconnect(rowClick);
}
-
+
this.drag_begin.disconnect(onDragBegin);
this.drag_data_get.disconnect(onDragDataGet);
this.drag_failed.disconnect(onDragFailed);
}
-
+
private bool populate()
{
m_unread_stack = new Gtk.Stack();
@@ -81,7 +81,7 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
m_marked_stack.set_transition_type(Gtk.StackTransitionType.CROSSFADE);
m_unread_stack.set_transition_duration(50);
m_marked_stack.set_transition_duration(50);
-
+
m_label = new Gtk.Label(m_article.getTitle());
m_label.set_line_wrap_mode(Pango.WrapMode.WORD);
m_label.set_line_wrap(true);
@@ -97,22 +97,22 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
m_label.set_ellipsize(Pango.EllipsizeMode.END);
m_label.set_alignment(0.0f, 0.2f);
m_label.set_tooltip_text(m_article.getTitle());
-
+
var icon_box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
icon_box.set_size_request(24, 0);
-
+
var marked_icon = new Gtk.Image.from_icon_name("feed-starred", Gtk.IconSize.SMALL_TOOLBAR);
var unread_icon = new Gtk.Image.from_icon_name("feed-article-unread", Gtk.IconSize.SMALL_TOOLBAR);
var unmarked_icon = new Gtk.Image.from_icon_name("feed-non-starred", Gtk.IconSize.SMALL_TOOLBAR);
var read_icon = new Gtk.Image.from_icon_name("feed-article-read", Gtk.IconSize.SMALL_TOOLBAR);
-
+
m_unread_stack.add_named(unread_icon, "unread");
m_unread_stack.add_named(read_icon, "read");
m_unread_stack.add_named(new Gtk.Label(""), "empty");
m_marked_stack.add_named(marked_icon, "marked");
m_marked_stack.add_named(unmarked_icon, "unmarked");
m_marked_stack.add_named(new Gtk.Label(""), "empty");
-
+
m_unread_eventbox = new Gtk.EventBox();
m_unread_eventbox.set_events(Gdk.EventMask.BUTTON_PRESS_MASK);
m_unread_eventbox.set_events(Gdk.EventMask.ENTER_NOTIFY_MASK);
@@ -132,12 +132,12 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
{
Logger.warning("ArticleRow: id %s - unread status undefined %i".printf(m_article.getArticleID(), m_article.getUnread()));
}
-
+
m_unread_eventbox.enter_notify_event.connect(unreadIconEnter);
m_unread_eventbox.leave_notify_event.connect(unreadIconLeave);
m_unread_eventbox.button_press_event.connect(unreadIconClicked);
-
-
+
+
m_marked_eventbox = new Gtk.EventBox();
m_marked_eventbox.set_events(Gdk.EventMask.BUTTON_PRESS_MASK);
m_marked_eventbox.set_events(Gdk.EventMask.ENTER_NOTIFY_MASK);
@@ -157,19 +157,19 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
{
Logger.warning("ArticleRow: id %s - unread status undefined %i".printf(m_article.getArticleID(), m_article.getMarked()));
}
-
+
m_marked_eventbox.enter_notify_event.connect(markedIconEnter);
m_marked_eventbox.leave_notify_event.connect(markedIconLeave);
m_marked_eventbox.button_press_event.connect(markedIconClicked);
-
+
m_icon = createFavIcon();
-
+
icon_box.pack_start(m_icon, true, true, 0);
icon_box.pack_end(m_unread_eventbox, false, false, 10);
icon_box.pack_end(m_marked_eventbox, false, false, 0);
-
+
string short_preview = "";
-
+
if(m_article.getPreview() != "")
{
if(m_article.getPreview().length > 300)
@@ -183,8 +183,8 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
short_preview = m_article.getPreview();
}
}
-
-
+
+
var body_label = new Gtk.Label(short_preview);
body_label.opacity = 0.7;
body_label.get_style_context().add_class("preview");
@@ -193,7 +193,7 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
body_label.set_line_wrap_mode(Pango.WrapMode.WORD_CHAR);
body_label.set_line_wrap(true);
body_label.set_lines(2);
-
+
var feed = DataBase.readOnly().read_feed(m_article.getFeedID());
var feedLabel = new Gtk.Label(feed != null ? feed.getTitle() : "");
feedLabel.get_style_context().add_class("preview");
@@ -207,8 +207,8 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
var date_box = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 10);
date_box.pack_start(feedLabel, true, true, 0);
date_box.pack_end(dateLabel, true, true, 0);
-
-
+
+
var text_box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
text_box.margin_end = 15;
text_box.margin_top = 8;
@@ -216,11 +216,11 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
text_box.pack_start(date_box, true, true, 0);
text_box.pack_start(m_label, true, true, 0);
text_box.pack_end(body_label, true, true, 0);
-
+
var box = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 0);
box.pack_start(icon_box, false, false, 8);
box.pack_start(text_box, true, true, 0);
-
+
m_eventBox = new Gtk.EventBox();
m_eventBox.set_events(Gdk.EventMask.ENTER_NOTIFY_MASK);
m_eventBox.set_events(Gdk.EventMask.LEAVE_NOTIFY_MASK);
@@ -230,7 +230,7 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
m_eventBox.button_press_event.connect(rowClick);
m_eventBox.add(box);
m_eventBox.show_all();
-
+
// Make the this widget a DnD source.
if(!Settings.general().get_boolean("only-feeds")
&& FeedReaderBackend.get_default().isOnline()
@@ -239,34 +239,34 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
const Gtk.TargetEntry[] provided_targets = {
{ "STRING", 0, DragTarget.TAG }
};
-
+
Gtk.drag_source_set(
this,
Gdk.ModifierType.BUTTON1_MASK,
provided_targets,
Gdk.DragAction.COPY
);
-
+
this.drag_begin.connect(onDragBegin);
this.drag_data_get.connect(onDragDataGet);
this.drag_failed.connect(onDragFailed);
}
-
+
m_revealer.add(m_eventBox);
m_populated = true;
return false;
}
-
+
private void onDragBegin(Gtk.Widget widget, Gdk.DragContext context)
{
Logger.debug("ArticleRow: onDragBegin");
Gtk.drag_set_icon_widget(context, getFeedIconWindow(), 0, 0);
}
-
+
public void onDragDataGet(Gtk.Widget widget, Gdk.DragContext context, Gtk.SelectionData selection_data, uint target_type, uint time)
{
Logger.debug("ArticleRow: onDragDataGet");
-
+
if(target_type == DragTarget.TAG)
{
selection_data.set_text(m_article.getArticleID(), -1);
@@ -276,17 +276,17 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
selection_data.set_text("ERROR!!!!!1111eleven", -1);
}
}
-
+
private bool onDragFailed(Gdk.DragContext context, Gtk.DragResult result)
{
Logger.debug("ArticleRow: onDragFailed " + result.to_string());
return false;
}
-
+
private Gtk.Image createFavIcon()
{
var icon = new Gtk.Image.from_icon_name("feed-rss-symbolic", Gtk.IconSize.LARGE_TOOLBAR);
-
+
Feed? feed = DataBase.readOnly().read_feed(m_article.getFeedID());
var favicon = FavIcon.for_feed(feed);
favicon.get_surface.begin((obj, res) => {
@@ -302,10 +302,10 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
icon.destroy.connect(() => {
favicon.disconnect(handler_id);
});
-
+
return icon;
}
-
+
private Gtk.Window getFeedIconWindow()
{
var icon = createFavIcon();
@@ -317,17 +317,17 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
window.show_all();
return window;
}
-
-
+
+
private bool rowEnter(Gdk.EventCrossing event)
{
if(event.detail == Gdk.NotifyType.INFERIOR)
{
return true;
}
-
+
m_hovering_row = true;
-
+
switch(m_article.getUnread())
{
case ArticleStatus.READ:
@@ -337,7 +337,7 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
m_unread_stack.set_visible_child_name("unread");
break;
}
-
+
switch(m_article.getMarked())
{
case ArticleStatus.MARKED:
@@ -347,19 +347,19 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
m_marked_stack.set_visible_child_name("unmarked");
break;
}
-
+
return true;
}
-
+
private bool rowLeave(Gdk.EventCrossing event)
{
if(event.detail == Gdk.NotifyType.INFERIOR)
{
return true;
}
-
+
m_hovering_row = false;
-
+
switch(m_article.getUnread())
{
case ArticleStatus.READ:
@@ -369,7 +369,7 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
m_unread_stack.set_visible_child_name("unread");
break;
}
-
+
switch(m_article.getMarked())
{
case ArticleStatus.MARKED:
@@ -379,10 +379,10 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
m_marked_stack.set_visible_child_name("empty");
break;
}
-
+
return true;
}
-
+
private bool rowClick(Gdk.EventButton event)
{
switch (event.button) {
@@ -392,7 +392,7 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
{
return false;
}
-
+
try{
Gtk.show_uri_on_window(MainWindow.get_default(), m_article.getURL(), Gdk.CURRENT_TIME);
}
@@ -400,20 +400,20 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
Logger.debug("could not open the link in an external browser: %s".printf(e.message));
}
break;
-
+
//If right clicked, show context menu:
case 3:
this.onRightClick();
break;
-
+
//Otherwise return false;
default:
return false;
}
-
+
return true;
}
-
+
private void onRightClick()
{
var pop = new Gtk.Popover(this);
@@ -423,21 +423,21 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
});
copyArticleURL_action.set_enabled(true);
FeedReaderApp.get_default().add_action(copyArticleURL_action);
-
+
var menu = new GLib.Menu();
menu.append(_("Copy URL"), "copyArticleURL");
-
+
pop.set_position(Gtk.PositionType.BOTTOM);
pop.bind_model(menu, "app");
pop.closed.connect(() => {
this.unset_state_flags(Gtk.StateFlags.PRELIGHT);
});
-
+
pop.show();
this.set_state_flags(Gtk.StateFlags.PRELIGHT, true);
}
-
-
+
+
private bool unreadIconClicked(Gdk.EventButton event)
{
switch(event.type)
@@ -451,12 +451,12 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
rowStateChanged(m_article.getUnread());
return true;
}
-
+
public ArticleStatus toggleUnread()
{
var view = ColumnView.get_default();
Article? selectedArticle = ColumnView.get_default().getSelectedArticle();
-
+
switch(m_article.getUnread())
{
case ArticleStatus.READ:
@@ -466,17 +466,17 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
updateUnread(ArticleStatus.READ);
break;
}
-
+
if(selectedArticle != null && selectedArticle.getArticleID() == m_article.getArticleID())
{
view.getHeader().setRead(m_article.getUnread());
}
-
+
FeedReaderBackend.get_default().updateArticleRead(m_article);
show_all();
return m_article.getUnread();
}
-
+
public void updateUnread(ArticleStatus unread)
{
if(m_article.getUnread() != unread)
@@ -506,7 +506,7 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
}
}
}
-
+
private bool unreadIconEnter()
{
m_hovering_unread = true;
@@ -521,8 +521,8 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
this.show_all();
return true;
}
-
-
+
+
private bool unreadIconLeave()
{
m_hovering_unread = false;
@@ -537,7 +537,7 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
this.show_all();
return true;
}
-
+
private bool markedIconClicked(Gdk.EventButton event)
{
switch(event.type)
@@ -551,12 +551,12 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
rowStateChanged(m_article.getMarked());
return true;
}
-
+
public ArticleStatus toggleMarked()
{
var view = ColumnView.get_default();
Article? selectedArticle = ColumnView.get_default().getSelectedArticle();
-
+
switch(m_article.getMarked())
{
case ArticleStatus.MARKED:
@@ -566,17 +566,17 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
updateMarked(ArticleStatus.MARKED);
break;
}
-
+
if(selectedArticle != null && selectedArticle.getArticleID() == m_article.getArticleID())
{
view.getHeader().setMarked(m_article.getMarked());
}
-
+
FeedReaderBackend.get_default().updateArticleMarked(m_article);
this.show_all();
return m_article.getMarked();
}
-
+
public void updateMarked(ArticleStatus marked)
{
if(m_article.getMarked() != marked)
@@ -587,7 +587,7 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
case ArticleStatus.MARKED:
m_marked_stack.set_visible_child_name("marked");
break;
-
+
case ArticleStatus.UNMARKED:
if(m_hovering_row)
{
@@ -601,7 +601,7 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
}
}
}
-
+
private bool markedIconEnter()
{
m_hovering_marked = true;
@@ -616,8 +616,8 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
this.show_all();
return true;
}
-
-
+
+
private bool markedIconLeave()
{
m_hovering_marked = false;
@@ -632,57 +632,57 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
this.show_all();
return true;
}
-
+
public Article getArticle()
{
return m_article;
}
-
+
public string getName()
{
return m_article.getTitle();
}
-
+
public string getID()
{
return m_article.getArticleID();
}
-
+
public GLib.DateTime getDate()
{
return m_article.getDate();
}
-
+
public string getDateStr()
{
return m_article.getDate().format("%Y-%m-%d %H:%M:%S");
}
-
+
public bool getUpdated()
{
return m_updated;
}
-
+
public void setUpdated(bool updated)
{
m_updated = updated;
}
-
+
public bool isHoveringUnread()
{
return m_hovering_unread;
}
-
+
public bool isHoveringMarked()
{
return m_hovering_marked;
}
-
+
public string getURL()
{
return m_article.getURL();
}
-
+
public void copyArticleURL(string article_id){
/*
Copy selected article url to clipboard
@@ -695,12 +695,12 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
string article_url = article.getURL();
Gdk.Display display = MainWindow.get_default().get_display ();
Gtk.Clipboard clipboard = Gtk.Clipboard.get_for_display (display, Gdk.SELECTION_CLIPBOARD);
-
+
clipboard.set_text(article_url, article_url.length);
}
}
}
-
+
public void reveal(bool reveal, uint duration = 500)
{
if(!reveal)
@@ -710,17 +710,17 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
m_revealer.set_transition_duration(duration);
m_revealer.set_reveal_child(reveal);
}
-
+
public bool isRevealed()
{
return m_revealer.get_child_revealed();
}
-
+
public bool isBeingRevealed()
{
return m_revealer.get_reveal_child();
}
-
+
public bool hasTag(string tagID)
{
foreach(string tag in m_article.getTagIDs())
@@ -730,20 +730,20 @@ public class FeedReader.ArticleRow : Gtk.ListBoxRow {
return true;
}
}
-
+
return false;
}
-
+
public void removeTag(string tagID)
{
m_article.getTagIDs().remove(tagID);
}
-
+
public int getSortID()
{
return m_article.getSortID();
}
-
+
public bool haveMedia()
{
return m_article.haveMedia();
diff --git a/src/Widgets/ArticleView.vala b/src/Widgets/ArticleView.vala
index 57f7bc56..495e0d9b 100644
--- a/src/Widgets/ArticleView.vala
+++ b/src/Widgets/ArticleView.vala
@@ -22,7 +22,7 @@ interface FeedReaderWebExtension : Object
}
public class FeedReader.ArticleView : Gtk.Overlay {
-
+
private Gtk.Overlay m_videoOverlay;
private ArticleViewUrlOverlay m_UrlOverlay;
private Gtk.Stack m_stack;
@@ -53,16 +53,16 @@ public class FeedReader.ArticleView : Gtk.Overlay {
private bool m_FullscreenArticle = false;
private double m_FullscreenZoomLevel = 1.25;
private uint m_animationDuration = 150;
-
-
+
+
public ArticleView()
{
WebKit.WebContext.get_default().set_cache_model(WebKit.CacheModel.DOCUMENT_BROWSER);
-
+
var emptyView = new Gtk.Label(_("No Article selected."));
emptyView.get_style_context().add_class("h2");
emptyView.get_style_context().add_class("dim-label");
-
+
var crashLabel = new Gtk.Label(_("WebKit has crashed"));
crashLabel.get_style_context().add_class("h2");
var crashIcon = new Gtk.Image.from_icon_name("face-crying-symbolic", Gtk.IconSize.BUTTON);
@@ -83,17 +83,17 @@ public class FeedReader.ArticleView : Gtk.Overlay {
crashView.set_valign(Gtk.Align.CENTER);
crashView.pack_start(crashLabelBox);
crashView.pack_start(crashButton);
-
-
+
+
m_UrlOverlay = new ArticleViewUrlOverlay();
m_stack = new Gtk.Stack();
m_stack.add_named(emptyView, "empty");
m_stack.add_named(crashView, "crash");
-
+
m_stack.set_visible_child_name("empty");
setTransition(Gtk.StackTransitionType.CROSSFADE, m_animationDuration);
m_stack.set_size_request(450, 0);
-
+
this.size_allocate.connect((allocation) => {
if(allocation.width != m_width
|| allocation.height != m_height)
@@ -105,18 +105,18 @@ public class FeedReader.ArticleView : Gtk.Overlay {
recalculate();
}
});
-
+
m_fsHead = new FullscreenHeader();
-
+
m_progress = new ArticleViewLoadProgress();
var progressOverlay = new Gtk.Overlay();
progressOverlay.add(m_stack);
progressOverlay.add_overlay(m_progress);
-
+
var fullscreenHeaderOverlay = new Gtk.Overlay();
fullscreenHeaderOverlay.add(progressOverlay);
fullscreenHeaderOverlay.add_overlay(m_fsHead);
-
+
m_prevButton = new fullscreenButton("go-previous-symbolic", Gtk.Align.START);
m_prevButton.click.connect(() => {
ColumnView.get_default().ArticleListPREV();
@@ -124,7 +124,7 @@ public class FeedReader.ArticleView : Gtk.Overlay {
var prevOverlay = new Gtk.Overlay();
prevOverlay.add(fullscreenHeaderOverlay);
prevOverlay.add_overlay(m_prevButton);
-
+
m_nextButton = new fullscreenButton("go-next-symbolic", Gtk.Align.END);
m_nextButton.click.connect(() => {
ColumnView.get_default().ArticleListNEXT();
@@ -132,25 +132,25 @@ public class FeedReader.ArticleView : Gtk.Overlay {
var nextOverlay = new Gtk.Overlay();
nextOverlay.add(prevOverlay);
nextOverlay.add_overlay(m_nextButton);
-
+
m_videoOverlay = new Gtk.Overlay();
m_videoOverlay.add(nextOverlay);
-
+
this.add(m_videoOverlay);
this.add_overlay(m_UrlOverlay);
-
+
Gtk.Settings.get_default().notify["gtk-theme-name"].connect(() => {
setBackgroundColor();
});
-
+
Gtk.Settings.get_default().notify["gtk-application-prefer-dark-theme"].connect(() => {
setBackgroundColor();
});
-
+
Bus.watch_name(BusType.SESSION, "org.gnome.FeedReader.ArticleView", GLib.BusNameWatcherFlags.NONE,
(connection, name, owner) => { on_extension_appeared(connection, name, owner); }, null);
}
-
+
private WebKit.WebView getNewView()
{
bool smoothScroll = Settings.tweaks().get_boolean("smooth-scrolling");
@@ -168,7 +168,7 @@ public class FeedReader.ArticleView : Gtk.Overlay {
settings.set_javascript_can_open_windows_automatically(false);
settings.set_media_playback_requires_user_gesture(true);
settings.set_user_agent_with_application_details("FeedReader", AboutInfo.version);
-
+
var view = new WebKit.WebView();
view.set_settings(settings);
view.set_events(Gdk.EventMask.POINTER_MOTION_MASK);
@@ -194,36 +194,36 @@ public class FeedReader.ArticleView : Gtk.Overlay {
{
view.set_background_color(m_color);
}
-
+
view.show();
return view;
}
-
+
public void fillContent(string articleID)
{
Logger.debug(@"ArticleView: load article $articleID");
-
+
if(m_busy)
{
Logger.debug(@"ArticleView: currently busy - next article in line is $articleID");
m_nextArticle = articleID;
return;
}
-
+
m_currentArticle = articleID;
-
+
if(m_OngoingScrollID > 0)
{
GLib.Source.remove(m_OngoingScrollID);
m_OngoingScrollID = 0;
}
-
+
Article article = DataBase.readOnly().read_article(articleID);
-
+
GLib.Idle.add(() => {
Logger.debug("ArticleView: WebView load html");
switchViews();
-
+
if(m_FullscreenArticle)
{
m_currentView.zoom_level = m_FullscreenZoomLevel;
@@ -232,15 +232,15 @@ public class FeedReader.ArticleView : Gtk.Overlay {
{
m_currentView.zoom_level = 1.0;
}
-
+
m_fsHead.setTitle(article.getTitle());
m_fsHead.setMarked(article.getMarked());
m_fsHead.setRead(article.getUnread());
-
+
m_progress.reset();
m_progress.setPercentage(0);
m_progress.reveal(true);
-
+
m_currentView.load_html(
Utils.buildArticle(
article.getHTML(),
@@ -255,18 +255,18 @@ public class FeedReader.ArticleView : Gtk.Overlay {
return false;
}, GLib.Priority.HIGH_IDLE);
}
-
+
private void switchViews()
{
m_busy = true;
string? visible = m_stack.get_visible_child_name();
-
+
if(visible == null)
{
Logger.error("ArticleView: ");
return;
}
-
+
switch(visible)
{
case "empty":
@@ -277,8 +277,8 @@ public class FeedReader.ArticleView : Gtk.Overlay {
m_stack.set_visible_child_name("view1");
m_busy = false;
break;
-
-
+
+
case "view1":
Logger.debug("ArticleView: view1 -> view2");
m_currentView = getNewView();
@@ -291,7 +291,7 @@ public class FeedReader.ArticleView : Gtk.Overlay {
return false;
}, GLib.Priority.HIGH);
break;
-
+
case "view2":
Logger.debug("ArticleView: view2 -> view1");
m_currentView = getNewView();
@@ -305,7 +305,7 @@ public class FeedReader.ArticleView : Gtk.Overlay {
}, GLib.Priority.HIGH);
break;
}
-
+
if(m_FullscreenArticle)
{
if(ColumnView.get_default().ArticleListSelectedIsLast())
@@ -316,7 +316,7 @@ public class FeedReader.ArticleView : Gtk.Overlay {
{
m_prevButton.reveal(true);
}
-
+
if(ColumnView.get_default().ArticleListSelectedIsFirst())
{
m_nextButton.reveal(false);
@@ -327,7 +327,7 @@ public class FeedReader.ArticleView : Gtk.Overlay {
}
}
}
-
+
private void removeFromStack(string childName)
{
Gtk.Widget? widget = m_stack.get_child_by_name(childName);
@@ -336,7 +336,7 @@ public class FeedReader.ArticleView : Gtk.Overlay {
m_stack.remove(widget);
}
}
-
+
private void checkQueue()
{
m_busy = false;
@@ -348,7 +348,7 @@ public class FeedReader.ArticleView : Gtk.Overlay {
load(id);
}
}
-
+
public void clearContent()
{
m_busy = true;
@@ -370,12 +370,12 @@ public class FeedReader.ArticleView : Gtk.Overlay {
}, GLib.Priority.HIGH);
m_currentArticle = "";
}
-
+
public string getCurrentArticle()
{
return m_currentArticle;
}
-
+
public void open_link(WebKit.LoadEvent load_event)
{
switch (load_event)
@@ -420,7 +420,7 @@ public class FeedReader.ArticleView : Gtk.Overlay {
break;
}
}
-
+
/*private bool loadFailed(WebKit.LoadEvent event, string failing_uri, void* error)
{
GLib.Error e = (GLib.Error)error;
@@ -433,7 +433,7 @@ public class FeedReader.ArticleView : Gtk.Overlay {
}
return true;
}*/
-
+
public void setScrollPos(int pos)
{
if(m_stack.get_visible_child_name() == "empty"
@@ -442,7 +442,7 @@ public class FeedReader.ArticleView : Gtk.Overlay {
{
return;
}
-
+
m_busy = true;
m_currentView.run_javascript.begin("window.scrollTo(0,%i);".printf(pos), null, (obj, res) => {
try
@@ -456,7 +456,7 @@ public class FeedReader.ArticleView : Gtk.Overlay {
checkQueue();
});
}
-
+
private int getScollUpper()
{
if(m_stack.get_visible_child_name() == "empty"
@@ -465,7 +465,7 @@ public class FeedReader.ArticleView : Gtk.Overlay {
{
return 0;
}
-
+
string javascript = """
document.title = Math.max (
document.body.scrollHeight,
@@ -477,7 +477,7 @@ public class FeedReader.ArticleView : Gtk.Overlay {
""";
int upper = -1;
var loop = new MainLoop();
-
+
m_busy = true;
m_currentView.run_javascript.begin(javascript, null, (obj, res) => {
try
@@ -492,11 +492,11 @@ public class FeedReader.ArticleView : Gtk.Overlay {
checkQueue();
loop.quit();
});
-
+
loop.run();
return upper;
}
-
+
public int getScrollPos()
{
if(m_stack.get_visible_child_name() == "empty"
@@ -505,14 +505,14 @@ public class FeedReader.ArticleView : Gtk.Overlay {
{
return 0;
}
-
+
// use mainloop to prevent app from shutting down before the result can be fetched
// ugly but works =/
// better solution welcome
-
+
int scrollPos = -1;
var loop = new MainLoop();
-
+
m_busy = true;
m_currentView.run_javascript.begin("document.title = window.scrollY;", null, (obj, res) => {
try
@@ -527,18 +527,18 @@ public class FeedReader.ArticleView : Gtk.Overlay {
checkQueue();
loop.quit();
});
-
+
loop.run();
return scrollPos;
}
-
-
+
+
public void setSearchTerm(string searchTerm)
{
m_searchTerm = Utils.parseSearchTerm(searchTerm);
}
-
-
+
+
private void on_extension_appeared(GLib.DBusConnection connection, string name, string owner)
{
try
@@ -559,7 +559,7 @@ public class FeedReader.ArticleView : Gtk.Overlay {
Logger.error("ArticleView.on_extension_appeared: " + e.message);
}
}
-
+
private void recalculate()
{
try
@@ -577,7 +577,7 @@ public class FeedReader.ArticleView : Gtk.Overlay {
Logger.warning("ArticleView: recalculate " + e.message);
}
}
-
+
private bool onClick(Gdk.EventButton event)
{
if(event.button == MouseButton.MIDDLE)
@@ -588,12 +588,12 @@ public class FeedReader.ArticleView : Gtk.Overlay {
m_dragBuffer[i] = m_posY;
}
m_inDrag = true;
-
+
var display = Gdk.Display.get_default();
var seat = display.get_default_seat();
var pointer = seat.get_pointer();
var cursor = new Gdk.Cursor.for_display(display, Gdk.CursorType.FLEUR);
-
+
seat.grab(
m_currentView.get_window(),
Gdk.SeatCapabilities.POINTER,
@@ -602,16 +602,16 @@ public class FeedReader.ArticleView : Gtk.Overlay {
null,
null
);
-
+
Gtk.device_grab_add(this, pointer, false);
GLib.Timeout.add(10, updateDragMomentum, GLib.Priority.HIGH);
m_currentView.motion_notify_event.connect(updateScroll);
return true;
}
-
+
return false;
}
-
+
private bool onRelease(Gdk.EventButton event)
{
if(event.button == MouseButton.MIDDLE)
@@ -619,26 +619,26 @@ public class FeedReader.ArticleView : Gtk.Overlay {
m_currentView.motion_notify_event.disconnect(updateScroll);
m_inDrag = false;
m_OngoingScrollID = GLib.Timeout.add(20, ScrollDragRelease, GLib.Priority.HIGH);
-
+
var display = Gdk.Display.get_default();
var seat = display.get_default_seat();
var pointer = seat.get_pointer();
Gtk.device_grab_remove(this, pointer);
seat.ungrab();
-
+
return true;
}
-
+
return false;
}
-
+
private bool onMouseMotion(Gdk.EventMotion event)
{
m_posX2 = event.x;
m_posY2 = event.y;
return false;
}
-
+
private bool onScroll(Gdk.EventScroll event)
{
if((event.state & Gdk.ModifierType.CONTROL_MASK) == Gdk.ModifierType.CONTROL_MASK)
@@ -648,22 +648,22 @@ public class FeedReader.ArticleView : Gtk.Overlay {
case Gdk.ScrollDirection.UP:
m_currentView.zoom_level -= 0.25;
break;
-
+
case Gdk.ScrollDirection.DOWN:
m_currentView.zoom_level += 0.25;
break;
-
+
case Gdk.ScrollDirection.SMOOTH:
m_currentView.zoom_level -= 10 * (event.delta_y / event.y_root);
break;
}
-
+
return true;
}
-
+
return false;
}
-
+
private bool onKeyPress(Gdk.EventKey event)
{
if((event.state & Gdk.ModifierType.CONTROL_MASK) == Gdk.ModifierType.CONTROL_MASK)
@@ -680,79 +680,79 @@ public class FeedReader.ArticleView : Gtk.Overlay {
m_currentView.zoom_level = 1.0;
}
return true;
-
+
case Gdk.Key.KP_Add:
m_currentView.zoom_level += 0.25;
return true;
-
+
case Gdk.Key.KP_Subtract:
m_currentView.zoom_level -= 0.25;
return true;
}
}
-
+
return false;
}
-
+
private bool updateScroll(Gdk.EventMotion event)
{
double scroll = m_posY - event.y;
m_posY = event.y;
setScrollPos(getScrollPos() + (int)scroll);
-
+
return false;
}
-
+
public void load(string? id = null)
{
string articleID = (id == null) ? m_currentArticle : id;
fillContent(articleID);
}
-
+
private bool updateDragMomentum()
{
if(!m_inDrag)
{
return false;
}
-
+
for(int i = 9; i > 0; --i)
{
m_dragBuffer[i] = m_dragBuffer[i-1];
}
-
+
m_dragBuffer[0] = m_posY;
m_momentum = m_dragBuffer[9] - m_dragBuffer[0];
-
+
return true;
}
-
+
private bool ScrollDragRelease()
{
if(m_inDrag)
{
return true;
}
-
+
m_momentum /= 1.2;
-
+
Gtk.Allocation allocation;
m_currentView.get_allocation(out allocation);
-
+
double pageSize = m_currentView.get_allocated_height();
double adjValue = pageSize * m_momentum / allocation.height;
double oldAdj = getScrollPos();
double upper = getScollUpper() * m_currentView.zoom_level;
-
+
if ((oldAdj + adjValue) > (upper - pageSize)
|| (oldAdj + adjValue) < 0)
{
m_momentum = 0;
}
-
+
double newScrollPos = double.min(oldAdj + adjValue, upper - pageSize);
setScrollPos((int)newScrollPos);
-
+
if (m_momentum < 1 && m_momentum > -1)
{
m_OngoingScrollID = 0;
@@ -763,7 +763,7 @@ public class FeedReader.ArticleView : Gtk.Overlay {
return true;
}
}
-
+
private void setBackgroundColor()
{
Logger.debug("ArticleView.setBackgroundColor()");
@@ -774,7 +774,7 @@ public class FeedReader.ArticleView : Gtk.Overlay {
m_color = background;
}
}
-
+
private bool onContextMenu(WebKit.ContextMenu menu, Gdk.Event event, WebKit.HitTestResult hitTest)
{
var menuItems = menu.get_items().copy();
@@ -785,17 +785,17 @@ public class FeedReader.ArticleView : Gtk.Overlay {
menu.remove(menuItem);
continue;
}
-
+
if((menuItem.get_gaction().name != "context-menu-action-3") // copy link location
&& (menuItem.get_gaction().name != "context-menu-action-9") // copy text
&& (menuItem.get_gaction().name != "context-menu-action-6") // copy image
&& (menuItem.get_gaction().name != "context-menu-action-7")) // copy image address
-
+
{
menu.remove(menuItem);
}
}
-
+
if(hitTest.context_is_image())
{
var uri = hitTest.get_image_uri().substring("file://".length);
@@ -805,15 +805,15 @@ public class FeedReader.ArticleView : Gtk.Overlay {
});
menu.append(new WebKit.ContextMenuItem.from_gaction(action, _("Save image as"), null));
}
-
+
if(menu.first() == null)
{
return true;
}
-
+
return false;
}
-
+
private void onMouseOver(WebKit.HitTestResult hitTest, uint modifiers)
{
if(hitTest.context_is_link())
@@ -821,12 +821,12 @@ public class FeedReader.ArticleView : Gtk.Overlay {
var align = Gtk.Align.START;
double relX = m_posX2/this.get_allocated_height();
double relY = m_posY2/this.get_allocated_width();
-
+
if(relY >= 0.85 && relX <= 0.5)
{
align = Gtk.Align.END;
}
-
+
m_UrlOverlay.setURL(hitTest.get_link_uri(), align);
m_UrlOverlay.reveal(true);
}
@@ -835,7 +835,7 @@ public class FeedReader.ArticleView : Gtk.Overlay {
m_UrlOverlay.reveal(false);
}
}
-
+
private bool leaveFullscreenVideo()
{
Logger.debug("ArticleView: leave fullscreen Video");
@@ -844,22 +844,22 @@ public class FeedReader.ArticleView : Gtk.Overlay {
ColumnView.get_default().showPane();
return false;
}
-
+
private bool enterFullscreenVideo()
{
Logger.debug("ArticleView: enter fullscreen Video");
m_FullscreenVideo = true;
-
+
// don't try to recalculate imagesizes when playing fullscreen video
m_connected = false;
-
+
ColumnView.get_default().hidePane();
m_fsHead.hide();
m_prevButton.reveal(false);
m_nextButton.reveal(false);
return false;
}
-
+
public void exitFullscreenVideo()
{
if(m_currentView != null)
@@ -867,35 +867,35 @@ public class FeedReader.ArticleView : Gtk.Overlay {
m_currentView.leave_fullscreen();
}
}
-
+
public bool fullscreenVideo()
{
return m_FullscreenVideo;
}
-
+
public bool fullscreenArticle()
{
return m_FullscreenArticle;
}
-
+
public void enterFullscreenArticle()
{
Logger.debug("ArticleView: enter fullscreen Article");
m_FullscreenArticle = true;
m_fsHead.show();
m_currentView.zoom_level = m_FullscreenZoomLevel;
-
+
if(!ColumnView.get_default().ArticleListSelectedIsFirst())
{
m_nextButton.reveal(true);
}
-
+
if(!ColumnView.get_default().ArticleListSelectedIsLast())
{
m_prevButton.reveal(true);
}
}
-
+
public void leaveFullscreenArticle()
{
Logger.debug("ArticleView: enter fullscreen Article");
@@ -906,47 +906,47 @@ public class FeedReader.ArticleView : Gtk.Overlay {
m_prevButton.reveal(false);
m_nextButton.reveal(false);
}
-
+
public void setTransition(Gtk.StackTransitionType trans, uint time)
{
m_stack.set_transition_type(trans);
m_stack.set_transition_duration(time);
m_animationDuration = time;
}
-
+
private void printProgress()
{
double progress = m_currentView.estimated_load_progress;
Logger.debug("ArticleView: loading %u %%".printf((uint)(progress*100)));
-
+
m_progress.setPercentageF(progress);
-
+
if(progress == 1.0)
{
m_progress.reveal(false);
}
}
-
+
public void setMarked(ArticleStatus marked)
{
m_fsHead.setMarked(marked);
}
-
+
public void setRead(ArticleStatus read)
{
m_fsHead.setRead(read);
}
-
+
public void nextButtonVisible(bool vis)
{
m_nextButton.reveal(vis);
}
-
+
public void prevButtonVisible(bool vis)
{
m_prevButton.reveal(vis);
}
-
+
private void onCrash(WebKit.WebProcessTerminationReason reason)
{
m_busy = true;
@@ -972,14 +972,14 @@ public class FeedReader.ArticleView : Gtk.Overlay {
uint micro = WebKit.get_micro_version();
Logger.debug(@"Running WebKit $major.$minor.$micro");
}
-
+
public void addMedia(MediaPlayer media)
{
killMedia();
m_videoOverlay.add_overlay(media);
m_currentMedia = media;
}
-
+
public void killMedia()
{
if(m_currentMedia != null)
@@ -987,51 +987,51 @@ public class FeedReader.ArticleView : Gtk.Overlay {
m_currentMedia.kill();
}
}
-
+
public bool playingMedia()
{
if(m_currentMedia == null)
{
return false;
}
-
+
return true;
}
-
+
public void print()
{
if(m_currentView == null)
{
return;
}
-
+
string articleName = DataBase.readOnly().read_article(m_currentArticle).getTitle() + ".pdf";
-
+
var settings = new Gtk.PrintSettings();
settings.set_printer("Print to File");
settings.set("output-file-format", "pdf");
settings.set("output-uri", articleName);
-
+
var setup = new Gtk.PageSetup();
setup.set_left_margin(0, Gtk.Unit.MM);
setup.set_right_margin(0, Gtk.Unit.MM);
-
+
var op = new WebKit.PrintOperation(m_currentView);
op.set_print_settings(settings);
op.set_page_setup(setup);
-
+
op.failed.connect((error) => {
Logger.debug("ArticleView: print failed: "+ error.message);
});
-
+
op.finished.connect(() => {
Logger.debug("ArticleView: print finished");
});
-
+
//op.print();
op.run_dialog(MainWindow.get_default());
}
-
+
private bool decidePolicy(WebKit.PolicyDecision decision, WebKit.PolicyDecisionType type)
{
Logger.debug("ArticleView: Policy decision");
@@ -1054,18 +1054,18 @@ public class FeedReader.ArticleView : Gtk.Overlay {
return true;
}
}
-
+
return false;
}
-
+
public void showMediaButton(bool show)
{
m_fsHead.showMediaButton(show);
}
-
+
public void sendEvent(Gdk.EventKey event)
{
m_currentView.key_press_event(event);
}
-
+
}
diff --git a/src/Widgets/ArticleViewHeader.vala b/src/Widgets/ArticleViewHeader.vala
index 3f73d69f..efbbbc97 100644
--- a/src/Widgets/ArticleViewHeader.vala
+++ b/src/Widgets/ArticleViewHeader.vala
@@ -15,7 +15,7 @@
public class FeedReader.ArticleViewHeader : Gtk.HeaderBar {
-
+
private Gtk.Button m_share_button;
private Gtk.Button m_tag_button;
private Gtk.Button m_print_button;
@@ -29,7 +29,7 @@ public class FeedReader.ArticleViewHeader : Gtk.HeaderBar {
public signal void fsClick();
public signal void popClosed();
public signal void popOpened();
-
+
public ArticleViewHeader(string fsIcon, string fsTooltip)
{
var share_icon = Utils.checkIcon("emblem-shared-symbolic", "feed-share-symbolic", Gtk.IconSize.SMALL_TOOLBAR);
@@ -39,7 +39,7 @@ public class FeedReader.ArticleViewHeader : Gtk.HeaderBar {
var read_icon = new Gtk.Image.from_icon_name("feed-read-symbolic", Gtk.IconSize.SMALL_TOOLBAR);
var unread_icon = new Gtk.Image.from_icon_name("feed-unread-symbolic", Gtk.IconSize.SMALL_TOOLBAR);
var fs_icon = new Gtk.Image.from_icon_name(fsIcon, Gtk.IconSize.SMALL_TOOLBAR);
-
+
m_mark_button = new HoverButton(unmarked_icon, marked_icon, false);
m_mark_button.sensitive = false;
m_mark_button.clicked.connect(() => {
@@ -50,7 +50,7 @@ public class FeedReader.ArticleViewHeader : Gtk.HeaderBar {
m_read_button.clicked.connect(() => {
toggledRead();
});
-
+
m_fullscreen_button = new Gtk.Button();
m_fullscreen_button.add(fs_icon);
m_fullscreen_button.set_relief(Gtk.ReliefStyle.NONE);
@@ -60,7 +60,7 @@ public class FeedReader.ArticleViewHeader : Gtk.HeaderBar {
m_fullscreen_button.clicked.connect(() => {
fsClick();
});
-
+
m_tag_button = new Gtk.Button();
m_tag_button.add(tag_icon);
m_tag_button.set_relief(Gtk.ReliefStyle.NONE);
@@ -74,8 +74,8 @@ public class FeedReader.ArticleViewHeader : Gtk.HeaderBar {
popClosed();
});
});
-
-
+
+
m_print_button = new Gtk.Button.from_icon_name("printer-symbolic");
m_print_button.set_relief(Gtk.ReliefStyle.NONE);
m_print_button.set_focus_on_click(false);
@@ -84,15 +84,15 @@ public class FeedReader.ArticleViewHeader : Gtk.HeaderBar {
m_print_button.clicked.connect(() => {
ColumnView.get_default().print();
});
-
-
+
+
m_share_button = new Gtk.Button();
m_share_button.add(share_icon);
m_share_button.set_relief(Gtk.ReliefStyle.NONE);
m_share_button.set_focus_on_click(false);
m_share_button.set_tooltip_text(_("Share article"));
m_share_button.sensitive = false;
-
+
var shareSpinner = new Gtk.Spinner();
var shareStack = new Gtk.Stack();
shareStack.set_transition_type(Gtk.StackTransitionType.CROSSFADE);
@@ -100,7 +100,7 @@ public class FeedReader.ArticleViewHeader : Gtk.HeaderBar {
shareStack.add_named(m_share_button, "button");
shareStack.add_named(shareSpinner, "spinner");
shareStack.set_visible_child_name("button");
-
+
m_share_button.clicked.connect(() => {
popOpened();
m_sharePopover = new SharePopover(m_share_button);
@@ -117,7 +117,7 @@ public class FeedReader.ArticleViewHeader : Gtk.HeaderBar {
popClosed();
});
});
-
+
m_media_button = new AttachedMediaButton();
m_media_button.popOpened.connect(() => {
popOpened();
@@ -125,7 +125,7 @@ public class FeedReader.ArticleViewHeader : Gtk.HeaderBar {
m_media_button.popClosed.connect(() => {
popClosed();
});
-
+
this.pack_start(m_fullscreen_button);
this.pack_start(m_mark_button);
this.pack_start(m_read_button);
@@ -134,7 +134,7 @@ public class FeedReader.ArticleViewHeader : Gtk.HeaderBar {
this.pack_end(m_print_button);
this.pack_end(m_media_button);
}
-
+
public void showArticleButtons(bool show)
{
Logger.debug("HeaderBar: showArticleButtons %s".printf(sensitive ? "true" : "false"));
@@ -143,14 +143,14 @@ public class FeedReader.ArticleViewHeader : Gtk.HeaderBar {
m_fullscreen_button.sensitive = show;
m_share_button.sensitive = (show && FeedReaderApp.get_default().isOnline());
m_print_button.sensitive = show;
-
+
if(FeedReaderBackend.get_default().supportTags()
&& Utils.canManipulateContent())
{
m_tag_button.sensitive = (show && FeedReaderApp.get_default().isOnline());
}
}
-
+
public void setMarked(ArticleStatus marked)
{
switch(marked)
@@ -164,12 +164,12 @@ public class FeedReader.ArticleViewHeader : Gtk.HeaderBar {
break;
}
}
-
+
public void toggleMarked()
{
m_mark_button.toggle();
}
-
+
public void setRead(ArticleStatus read)
{
switch(read)
@@ -183,12 +183,12 @@ public class FeedReader.ArticleViewHeader : Gtk.HeaderBar {
break;
}
}
-
+
public void toggleRead()
{
m_read_button.toggle();
}
-
+
public void setOffline()
{
m_share_button.sensitive = false;
@@ -198,7 +198,7 @@ public class FeedReader.ArticleViewHeader : Gtk.HeaderBar {
m_tag_button.sensitive = false;
}
}
-
+
public void setOnline()
{
if(m_mark_button.sensitive)
@@ -211,21 +211,21 @@ public class FeedReader.ArticleViewHeader : Gtk.HeaderBar {
}
}
}
-
+
public void showMediaButton(bool show)
{
m_media_button.update();
m_media_button.visible = show;
}
-
+
public void refreshSahrePopover()
{
if(m_sharePopover == null)
{
return;
}
-
+
m_sharePopover.refreshList();
}
-
+
}
diff --git a/src/Widgets/ArticleViewLoadProgress.vala b/src/Widgets/ArticleViewLoadProgress.vala
index 69a6b816..7f0bd068 100644
--- a/src/Widgets/ArticleViewLoadProgress.vala
+++ b/src/Widgets/ArticleViewLoadProgress.vala
@@ -14,10 +14,10 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.ArticleViewLoadProgress : Gtk.Revealer {
-
+
private Gtk.ProgressBar m_progress;
private uint m_timeout_source_id = 0;
-
+
public ArticleViewLoadProgress()
{
m_progress = new Gtk.ProgressBar();
@@ -28,17 +28,17 @@ public class FeedReader.ArticleViewLoadProgress : Gtk.Revealer {
this.no_show_all = true;
this.add(m_progress);
}
-
+
public void setPercentage(uint percentage)
{
m_progress.set_fraction(percentage);
}
-
+
public void setPercentageF(double percentage)
{
m_progress.set_fraction(percentage);
}
-
+
public void reveal(bool show)
{
if(m_timeout_source_id > 0)
@@ -46,7 +46,7 @@ public class FeedReader.ArticleViewLoadProgress : Gtk.Revealer {
GLib.Source.remove(m_timeout_source_id);
m_timeout_source_id = 0;
}
-
+
if(show)
{
this.visible = true;
@@ -62,11 +62,11 @@ public class FeedReader.ArticleViewLoadProgress : Gtk.Revealer {
this.set_reveal_child(false);
}
}
-
+
public void reset()
{
reveal(false);
}
-
-
+
+
}
diff --git a/src/Widgets/ArticleViewUrlOverlay.vala b/src/Widgets/ArticleViewUrlOverlay.vala
index 11ee534b..18fa68fd 100644
--- a/src/Widgets/ArticleViewUrlOverlay.vala
+++ b/src/Widgets/ArticleViewUrlOverlay.vala
@@ -14,15 +14,15 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.ArticleViewUrlOverlay : Gtk.Revealer {
-
+
private Gtk.Label m_label;
-
+
public ArticleViewUrlOverlay()
{
m_label = new Gtk.Label("dummy");
m_label.get_style_context().add_class("osd");
m_label.height_request = 30;
-
+
this.valign = Gtk.Align.END;
this.halign = Gtk.Align.START;
this.margin = 10;
@@ -31,7 +31,7 @@ public class FeedReader.ArticleViewUrlOverlay : Gtk.Revealer {
this.no_show_all = true;
this.add(m_label);
}
-
+
public void setURL(string uri, Gtk.Align align)
{
int length = 45;
@@ -44,7 +44,7 @@ public class FeedReader.ArticleViewUrlOverlay : Gtk.Revealer {
m_label.width_chars = url.length;
this.halign = align;
}
-
+
public void reveal(bool show)
{
if(show)
@@ -52,7 +52,7 @@ public class FeedReader.ArticleViewUrlOverlay : Gtk.Revealer {
this.visible = true;
m_label.show();
}
-
+
this.set_reveal_child(show);
}
}
diff --git a/src/Widgets/BackendInfoPopover.vala b/src/Widgets/BackendInfoPopover.vala
index ea8ad9bd..7a5811a2 100644
--- a/src/Widgets/BackendInfoPopover.vala
+++ b/src/Widgets/BackendInfoPopover.vala
@@ -14,33 +14,33 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.BackendInfoPopover : Gtk.Popover {
-
+
private BackendInfo m_info;
-
+
public BackendInfoPopover(Gtk.Widget widget, BackendInfo info)
{
m_info = info;
-
+
int space = 25;
-
+
var typeLabel = new Gtk.Label("Type:");
typeLabel.hexpand = true;
typeLabel.get_style_context().add_class("h3");
typeLabel.set_alignment(0.0f, 0.5f);
-
-
+
+
var licenseLabel = new Gtk.Label("License:");
licenseLabel.hexpand = true;
licenseLabel.get_style_context().add_class("h3");
licenseLabel.set_alignment(0.0f, 0.5f);
-
-
+
+
var priceLabel = new Gtk.Label("Price:");
priceLabel.hexpand = true;
priceLabel.get_style_context().add_class("h3");
priceLabel.set_alignment(0.0f, 0.5f);
-
-
+
+
var grid = new Gtk.Grid();
grid.set_column_spacing(20);
grid.set_row_spacing(5);
@@ -48,9 +48,9 @@ public class FeedReader.BackendInfoPopover : Gtk.Popover {
grid.attach(typeLabel, 0, 0, 1, 1);
grid.attach(licenseLabel, 0, 1, 1, 1);
grid.attach(priceLabel, 0, 2, 1, 1);
-
-
-
+
+
+
if(BackendFlags.LOCAL in m_info.flags)
{
var icon = getIcon("feed-local-symbolic", "Local Files only");
@@ -72,8 +72,8 @@ public class FeedReader.BackendInfoPopover : Gtk.Popover {
space = 50;
}
}
-
-
+
+
if(BackendFlags.FREE_SOFTWARE in m_info.flags)
{
var icon = getIcon("feed-gpl-symbolic", "Free Software");
@@ -84,7 +84,7 @@ public class FeedReader.BackendInfoPopover : Gtk.Popover {
var icon = getIcon("feed-copyright-symbolic", "Proprietary Software");
grid.attach(icon, 1, 1, 1, 1);
}
-
+
if(BackendFlags.FREE in m_info.flags)
{
var icon = getIcon("feed-free-symbolic", "Free Service");
@@ -100,15 +100,15 @@ public class FeedReader.BackendInfoPopover : Gtk.Popover {
var icon = getIcon("feed-nonfree-symbolic", "Free basic usage with paid Premium");
grid.attach(icon, 1, 2, 1, 1);
}
-
-
+
+
var nameLabel = new Gtk.Label(m_info.name);
nameLabel.get_style_context().add_class("h2");
nameLabel.set_alignment(0.0f, 0.5f);
-
+
var eventbox = new Gtk.EventBox();
eventbox.set_events(Gdk.EventMask.BUTTON_PRESS_MASK);
-
+
eventbox.button_press_event.connect(websiteClicked);
eventbox.add(getIcon("feed-website-symbolic", m_info.website));
var nameBox = new Gtk.Box(Gtk.Orientation.HORIZONTAL, space);
@@ -116,24 +116,24 @@ public class FeedReader.BackendInfoPopover : Gtk.Popover {
nameBox.pack_end(eventbox, false, false, 0);
nameBox.margin = 10;
nameBox.margin_bottom = 5;
-
+
var separator = new Gtk.Separator(Gtk.Orientation.HORIZONTAL);
-
+
var box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
box.pack_start(nameBox, false, false, 0);
box.pack_start(separator, false, false, 0);
box.pack_start(grid, true, true, 0);
-
-
+
+
this.add(box);
this.set_relative_to(widget);
this.set_position(Gtk.PositionType.BOTTOM);
this.show_all();
-
+
var cursor = new Gdk.Cursor.for_display(Gdk.Display.get_default(), Gdk.CursorType.HAND1);
eventbox.get_window().set_cursor(cursor);
}
-
+
private bool websiteClicked(Gdk.EventButton event)
{
// only accept left mouse button
@@ -141,7 +141,7 @@ public class FeedReader.BackendInfoPopover : Gtk.Popover {
{
return false;
}
-
+
switch(event.type)
{
case Gdk.EventType.BUTTON_RELEASE:
@@ -149,7 +149,7 @@ public class FeedReader.BackendInfoPopover : Gtk.Popover {
case Gdk.EventType.@3BUTTON_PRESS:
return false;
}
-
+
try
{
Gtk.show_uri_on_window(MainWindow.get_default(), m_info.website, Gdk.CURRENT_TIME);
@@ -160,7 +160,7 @@ public class FeedReader.BackendInfoPopover : Gtk.Popover {
}
return true;
}
-
+
private Gtk.Image getIcon(string name, string tooltip)
{
var icon = new Gtk.Image.from_icon_name(name, Gtk.IconSize.MENU);
@@ -168,6 +168,6 @@ public class FeedReader.BackendInfoPopover : Gtk.Popover {
icon.set_tooltip_text(tooltip);
return icon;
}
-
-
+
+
}
diff --git a/src/Widgets/CategorieRow.vala b/src/Widgets/CategorieRow.vala
index c1f0dbe9..05259ee2 100644
--- a/src/Widgets/CategorieRow.vala
+++ b/src/Widgets/CategorieRow.vala
@@ -14,7 +14,7 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.CategoryRow : Gtk.ListBoxRow {
-
+
private Gtk.Box m_box;
private string m_name;
private Gtk.Label m_label;
@@ -42,7 +42,7 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
public signal void moveUP();
public signal void deselectRow();
public signal void removeRow();
-
+
public CategoryRow(string name, string categorieID, int orderID, uint unread_count, string parentID, int level, bool expanded)
{
this.get_style_context().add_class("fr-sidebar-row");
@@ -55,24 +55,24 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
m_unread_count = unread_count;
var rowhight = 30;
m_box = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 0);
-
-
+
+
m_icon_collapsed = new Gtk.Image.from_icon_name("feed-sidebar-arrow-side-symbolic", Gtk.IconSize.SMALL_TOOLBAR);
m_icon_collapsed.get_style_context().add_class("fr-sidebar-symbolic");
m_icon_collapsed.opacity = m_opacity;
-
+
m_icon_expanded = new Gtk.Image.from_icon_name("feed-sidebar-arrow-down-symbolic", Gtk.IconSize.SMALL_TOOLBAR);
m_icon_expanded.get_style_context().add_class("fr-sidebar-symbolic");
m_icon_expanded.opacity = m_opacity;
-
-
-
+
+
+
m_stack = new Gtk.Stack();
m_stack.set_transition_type(Gtk.StackTransitionType.NONE);
m_stack.set_transition_duration(0);
m_stack.add_named(m_icon_expanded, "expanded");
m_stack.add_named(m_icon_collapsed, "collapsed");
-
+
m_expandBox = new Gtk.EventBox();
m_expandBox.set_events(Gdk.EventMask.BUTTON_PRESS_MASK);
m_expandBox.set_events(Gdk.EventMask.ENTER_NOTIFY_MASK);
@@ -83,17 +83,17 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
m_expandBox.button_press_event.connect(onExpandClick);
m_expandBox.enter_notify_event.connect(onExpandEnter);
m_expandBox.leave_notify_event.connect(onExpandLeave);
-
+
m_label = new Gtk.Label(m_name);
m_label.set_size_request (0, rowhight);
m_label.set_ellipsize (Pango.EllipsizeMode.END);
m_label.set_alignment(0, 0.5f);
-
-
+
+
m_unread = new Gtk.Label("");
m_unread.set_size_request (0, rowhight);
m_unread.set_alignment(0.8f, 0.5f);
-
+
m_unreadStack = new Gtk.Stack();
m_unreadStack.set_transition_type(Gtk.StackTransitionType.NONE);
m_unreadStack.set_transition_duration(0);
@@ -102,18 +102,18 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
var markIcon = new Gtk.Image.from_icon_name("feed-mark-read-symbolic", Gtk.IconSize.LARGE_TOOLBAR);
markIcon.get_style_context().add_class("fr-sidebar-symbolic");
m_unreadStack.add_named(markIcon, "mark");
-
+
m_unreadBox = new Gtk.EventBox();
m_unreadBox.set_events(Gdk.EventMask.BUTTON_PRESS_MASK);
m_unreadBox.set_events(Gdk.EventMask.ENTER_NOTIFY_MASK);
m_unreadBox.set_events(Gdk.EventMask.LEAVE_NOTIFY_MASK);
m_unreadBox.add(m_unreadStack);
activateUnreadEventbox(true);
-
+
m_box.pack_start(m_expandBox, false, false, 0);
m_box.pack_start(m_label, true, true, 0);
m_box.pack_end(m_unreadBox, false, false, 8);
-
+
m_eventBox = new Gtk.EventBox();
if(m_categorieID != CategoryID.MASTER.to_string()
&& m_categorieID != CategoryID.TAGS.to_string())
@@ -122,16 +122,16 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
m_eventBox.button_press_event.connect(onClick);
}
m_eventBox.add(m_box);
-
+
m_revealer = new Gtk.Revealer();
m_revealer.set_transition_type(Gtk.RevealerTransitionType.SLIDE_DOWN);
m_revealer.add(m_eventBox);
m_revealer.set_reveal_child(false);
this.add(m_revealer);
this.show_all();
-
+
set_unread_count(m_unread_count);
-
+
if(m_collapsed)
{
m_stack.set_visible_child_name("collapsed");
@@ -140,7 +140,7 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
{
m_stack.set_visible_child_name("expanded");
}
-
+
if(Utils.canManipulateContent())
{
if(m_categorieID != CategoryID.MASTER.to_string()
@@ -150,32 +150,32 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
{ "text/plain", 0, DragTarget.FEED },
{ "STRING", 0, DragTarget.CAT }
};
-
+
Gtk.drag_dest_set (
this,
Gtk.DestDefaults.MOTION,
accepted_targets,
Gdk.DragAction.MOVE
);
-
+
this.drag_motion.connect(onDragMotion);
this.drag_leave.connect(onDragLeave);
this.drag_drop.connect(onDragDrop);
this.drag_data_received.connect(onDragDataReceived);
-
+
if(FeedReaderBackend.get_default().supportMultiLevelCategories())
{
const Gtk.TargetEntry[] provided_targets = {
{ "STRING", 0, DragTarget.CAT }
};
-
+
Gtk.drag_source_set (
this,
Gdk.ModifierType.BUTTON1_MASK,
provided_targets,
Gdk.DragAction.MOVE
);
-
+
this.drag_begin.connect(onDragBegin);
this.drag_data_get.connect(onDragDataGet);
}
@@ -185,14 +185,14 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
const Gtk.TargetEntry[] accepted_targets = {
{ "STRING", 0, DragTarget.CAT }
};
-
+
Gtk.drag_dest_set (
this,
Gtk.DestDefaults.MOTION,
accepted_targets,
Gdk.DragAction.MOVE
);
-
+
this.drag_motion.connect(onDragMotion);
this.drag_leave.connect(onDragLeave);
this.drag_drop.connect(onDragDrop);
@@ -200,89 +200,89 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
}
}
}
-
+
~CategoryRow()
{
activateUnreadEventbox(false);
-
+
m_expandBox.button_press_event.disconnect(onExpandClick);
m_expandBox.enter_notify_event.disconnect(onExpandEnter);
m_expandBox.leave_notify_event.disconnect(onExpandLeave);
-
+
m_eventBox.button_press_event.disconnect(onClick);
-
+
this.drag_begin.disconnect(onDragBegin);
this.drag_data_get.disconnect(onDragDataGet);
-
+
this.drag_motion.disconnect(onDragMotion);
this.drag_leave.disconnect(onDragLeave);
this.drag_drop.disconnect(onDragDrop);
this.drag_data_received.disconnect(onDragDataReceived);
-
+
this.drag_motion.disconnect(onDragMotion);
this.drag_leave.disconnect(onDragLeave);
this.drag_drop.disconnect(onDragDrop);
this.drag_data_received.disconnect(onDragDataReceived);
}
-
+
//------------- Drag Source Functions ----------------------------------------------
-
+
private void onDragBegin(Gtk.Widget widget, Gdk.DragContext context)
{
Logger.debug("categoryRow: onDragBegin");
Gtk.drag_set_icon_widget(context, getDragWindow(), 0, 0);
-
+
}
-
+
public void onDragDataGet(Gtk.Widget widget, Gdk.DragContext context, Gtk.SelectionData selection_data, uint target_type, uint time)
{
Logger.debug("categoryRow: onDragDataGet");
-
+
if(target_type == DragTarget.CAT)
{
selection_data.set_text(m_categorieID, -1);
}
}
-
-
+
+
//------------- Drag Target Functions ----------------------------------------------
-
+
private bool onDragMotion(Gtk.Widget widget, Gdk.DragContext context, int x, int y, uint time)
{
this.set_state_flags(Gtk.StateFlags.PRELIGHT, false);
return true;
}
-
+
private void onDragLeave(Gtk.Widget widget, Gdk.DragContext context, uint time)
{
this.unset_state_flags(Gtk.StateFlags.PRELIGHT);
}
-
-
+
+
private bool onDragDrop(Gtk.Widget widget, Gdk.DragContext context, int x, int y, uint time)
{
Logger.debug("categoryRow: onDragDrop");
-
+
// If the source offers a target
if(context.list_targets() != null)
{
var target_type = (Gdk.Atom)context.list_targets().nth_data(0);
-
+
// Request the data from the source.
Gtk.drag_get_data(widget, context, target_type, time);
return true;
}
-
+
return false;
}
-
+
private void onDragDataReceived(Gtk.Widget widget, Gdk.DragContext context, int x, int y,
Gtk.SelectionData selection_data, uint target_type, uint time)
{
Logger.debug("categoryRow: onDragDataReceived");
-
+
var dataString = selection_data.get_text();
-
+
if(dataString != null
&& selection_data.get_length() >= 0)
{
@@ -293,7 +293,7 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
string[] data = dataString.split(",");
string feedID = data[0];
string currentCat = data[1];
-
+
showRenamePopover(context, time, feedID, currentCat);
}
else if(target_type == DragTarget.CAT)
@@ -309,7 +309,7 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
string feedID = data[0];
string currentCat = data[1];
Logger.debug("drag feedID: " + feedID + " currentCat: " + currentCat);
-
+
if(currentCat == m_categorieID)
{
Logger.debug("categoryRow: drag current parent -> drag_failed");
@@ -320,13 +320,13 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
{
FeedReaderBackend.get_default().moveFeed(feedID, currentCat, m_categorieID);
}
-
+
Gtk.drag_finish(context, true, false, time);
}
else if(target_type == DragTarget.CAT)
{
Logger.debug("drag catID: " + dataString);
-
+
if(dataString == m_categorieID)
{
Logger.debug("categoryRow: drag on self -> drag_failed");
@@ -337,14 +337,14 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
{
FeedReaderBackend.get_default().moveCategory(dataString, m_categorieID);
}
-
+
Gtk.drag_finish(context, true, false, time);
}
}
}
-
+
}
-
+
private Gtk.Window getDragWindow()
{
var window = new Gtk.Window(Gtk.WindowType.POPUP);
@@ -359,7 +359,7 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
window.show_all();
return window;
}
-
+
private bool onClick(Gdk.EventButton event)
{
// only right click allowed
@@ -367,13 +367,13 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
{
return false;
}
-
+
if(!Utils.canManipulateContent())
{
return false;
}
-
-
+
+
switch(event.type)
{
case Gdk.EventType.BUTTON_RELEASE:
@@ -381,25 +381,25 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
case Gdk.EventType.@3BUTTON_PRESS:
return false;
}
-
+
var remove_action = new GLib.SimpleAction("deleteCat", null);
remove_action.activate.connect(() => {
bool wasExpanded = false;
-
+
if(!m_collapsed)
{
wasExpanded = true;
expand_collapse();
}
-
+
if(this.is_selected())
{
moveUP();
}
-
+
uint time = 300;
this.reveal(false, time);
-
+
string text = _("Category \"%s\" removed").printf(m_name);
var notification = MainWindow.get_default().showNotification(text);
ulong eventID = notification.dismissed.connect(() => {
@@ -421,12 +421,12 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
{
expand_collapse();
}
-
+
if(this.is_selected())
{
moveUP();
}
-
+
uint time = 300;
this.reveal(false, time);
GLib.Timeout.add(time, () => {
@@ -450,19 +450,19 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
rename_action.activate.connect(() => {
showRenamePopover();
});
-
+
var app = FeedReaderApp.get_default();
app.add_action(markAsRead_action);
app.add_action(rename_action);
app.add_action(remove_action);
app.add_action(removeWithChildren_action);
-
+
var menu = new GLib.Menu();
menu.append(_("Mark as read"), "markCatAsRead");
menu.append(_("Rename"), "renameCat");
menu.append(_("Remove"), "deleteCat");
menu.append(_("Remove (with Feeds)"), "deleteAllCat");
-
+
var pop = new Gtk.Popover(this);
pop.set_position(Gtk.PositionType.BOTTOM);
pop.bind_model(menu, "app");
@@ -471,10 +471,10 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
});
pop.show();
this.set_state_flags(Gtk.StateFlags.PRELIGHT, false);
-
+
return true;
}
-
+
private void showRenamePopover(Gdk.DragContext? context = null, uint time = 0, string? id1 = null, string? id2 = null)
{
var popRename = new Gtk.Popover(this);
@@ -486,7 +486,7 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
this.drag_failed(context, Gtk.DragResult.NO_TARGET);
}
});
-
+
var renameEntry = new Gtk.Entry();
renameEntry.set_text(m_name);
renameEntry.activate.connect(() => {
@@ -498,46 +498,46 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
{
Logger.debug("categoryRow: create new Category " + renameEntry.get_text());
m_categorieID = FeedReaderBackend.get_default().addCategory(renameEntry.get_text(), "", true);
-
+
if(id2 == null) // move feed
-
+
{
FeedReaderBackend.get_default().moveCategory(id1, m_categorieID);
}
else // move category
-
+
{
FeedReaderBackend.get_default().moveFeed(id1, id2, m_categorieID);
}
-
+
Gtk.drag_finish(context, true, false, time);
}
-
+
popRename.hide();
});
-
+
string label = _("rename");
if(m_categorieID == CategoryID.NEW.to_string() && context != null)
{
label = _("add");
}
-
+
var renameButton = new Gtk.Button.with_label(label);
renameButton.get_style_context().add_class("suggested-action");
renameButton.clicked.connect(() => {
renameEntry.activate();
});
-
+
var renameBox = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 5);
renameBox.margin = 5;
renameBox.pack_start(renameEntry, true, true, 0);
renameBox.pack_start(renameButton, false, false, 0);
-
+
popRename.add(renameBox);
popRename.show_all();
this.set_state_flags(Gtk.StateFlags.PRELIGHT, false);
}
-
+
private bool onUnreadClick(Gdk.EventButton event)
{
if(m_unreadHovered && m_unread_count > 0)
@@ -546,7 +546,7 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
}
return true;
}
-
+
private bool onUnreadEnter(Gdk.EventCrossing event)
{
m_unreadHovered = true;
@@ -556,7 +556,7 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
}
return true;
}
-
+
private bool onUnreadLeave(Gdk.EventCrossing event)
{
m_unreadHovered = false;
@@ -570,7 +570,7 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
}
return true;
}
-
+
private bool onExpandClick(Gdk.EventButton event)
{
// only accept left mouse button
@@ -578,7 +578,7 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
{
return false;
}
-
+
switch(event.type)
{
case Gdk.EventType.BUTTON_RELEASE:
@@ -589,7 +589,7 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
expand_collapse();
return true;
}
-
+
public bool expand_collapse(bool selectParent = true)
{
if(m_collapsed)
@@ -602,11 +602,11 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
m_collapsed = true;
m_stack.set_visible_child_name("collapsed");
}
-
+
collapse(m_collapsed, m_categorieID, selectParent);
return true;
}
-
+
private bool onExpandEnter(Gdk.EventCrossing event)
{
m_hovered = true;
@@ -614,7 +614,7 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
m_icon_collapsed.opacity = 1.0;
return true;
}
-
+
private bool onExpandLeave(Gdk.EventCrossing event)
{
if(event.detail != Gdk.NotifyType.VIRTUAL
@@ -622,18 +622,18 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
{
return false;
}
-
+
m_hovered = false;
-
+
m_icon_expanded.opacity = m_opacity;
m_icon_collapsed.opacity = m_opacity;
return true;
}
-
+
public void set_unread_count(uint unread_count)
{
m_unread_count = unread_count;
-
+
if(m_unread_count > 0 && !m_unreadHovered)
{
m_unreadStack.set_visible_child_name("unreadCount");
@@ -648,12 +648,12 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
m_unreadStack.set_visible_child_name("mark");
}
}
-
+
public void upUnread()
{
set_unread_count(m_unread_count+1);
}
-
+
public void downUnread()
{
if(m_unread_count > 0)
@@ -661,68 +661,68 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
set_unread_count(m_unread_count-1);
}
}
-
+
public string getID()
{
return m_categorieID;
}
-
+
public string getName()
{
return m_name;
}
-
+
public string getParent()
{
return m_parentID;
}
-
+
public int getOrder()
{
return m_orderID;
}
-
+
public int getLevel()
{
return m_level;
}
-
+
public void setExist(bool exists)
{
m_exists = exists;
}
-
+
public bool doesExist()
{
return m_exists;
}
-
+
public bool isExpanded()
{
return !m_collapsed;
}
-
+
public uint getUnreadCount()
{
return m_unread_count;
}
-
+
public bool isRevealed()
{
return m_revealer.get_reveal_child();
}
-
+
public void reveal(bool reveal, uint duration = 500)
{
if(!reveal && this.is_selected())
{
deselectRow();
}
-
+
m_revealer.set_transition_duration(duration);
m_revealer.set_reveal_child(reveal);
}
-
+
public void activateUnreadEventbox(bool activate)
{
if(activate)
@@ -738,5 +738,5 @@ public class FeedReader.CategoryRow : Gtk.ListBoxRow {
m_unreadBox.leave_notify_event.disconnect(onUnreadLeave);
}
}
-
+
}
diff --git a/src/Widgets/ColorCircle.vala b/src/Widgets/ColorCircle.vala
index f1ebb712..024acf08 100644
--- a/src/Widgets/ColorCircle.vala
+++ b/src/Widgets/ColorCircle.vala
@@ -14,42 +14,42 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.ColorCircle : Gtk.EventBox {
-
+
private Gtk.Image m_icon;
private Gtk.Image m_icon_light;
private int m_color;
public signal void clicked(int color);
-
+
public ColorCircle(int color, bool clickable = true)
{
m_color = color;
m_icon = new Gtk.Image.from_surface(drawIcon());
m_icon_light = new Gtk.Image.from_surface(drawIcon(true));
-
+
this.set_events(Gdk.EventMask.BUTTON_PRESS_MASK);
this.set_events(Gdk.EventMask.ENTER_NOTIFY_MASK);
this.set_events(Gdk.EventMask.LEAVE_NOTIFY_MASK);
this.set_size_request(16, 16);
-
+
if(clickable)
{
this.enter_notify_event.connect(IconEnter);
this.leave_notify_event.connect(IconLeave);
this.button_press_event.connect(IconClicked);
}
-
+
this.add(m_icon);
this.show_all();
}
-
+
public void newColor(int color)
{
m_color = color;
m_icon.set_from_surface(drawIcon());
m_icon_light.set_from_surface(drawIcon(true));
}
-
-
+
+
private bool IconEnter()
{
this.remove(m_icon);
@@ -57,7 +57,7 @@ public class FeedReader.ColorCircle : Gtk.EventBox {
this.show_all();
return true;
}
-
+
private bool IconLeave()
{
this.remove(m_icon_light);
@@ -65,14 +65,14 @@ public class FeedReader.ColorCircle : Gtk.EventBox {
this.show_all();
return true;
}
-
+
private bool IconClicked(Gdk.EventButton event)
{
if(event.button != 1)
{
return false;
}
-
+
switch(event.type)
{
case Gdk.EventType.BUTTON_RELEASE:
@@ -80,13 +80,13 @@ public class FeedReader.ColorCircle : Gtk.EventBox {
case Gdk.EventType.@3BUTTON_PRESS:
return false;
}
-
+
Logger.debug("ColorCircle: click");
clicked(m_color);
return true;
}
-
-
+
+
private Cairo.Surface drawIcon(bool light = false)
{
int scaleFactor = this.get_scale_factor();
@@ -98,22 +98,22 @@ public class FeedReader.ColorCircle : Gtk.EventBox {
{
lighten = 0.7;
}
-
+
var surface = this.get_window().create_similar_image_surface(0, size, size, 0);
Cairo.Context context = new Cairo.Context(surface);
-
+
context.set_line_width(2);
context.set_fill_rule(Cairo.FillRule.EVEN_ODD);
-
+
double half = size/(2*scaleFactor);
context.set_source_rgba(color.red, color.green, color.blue, 0.6*lighten);
context.arc(half, half, half, 0, 2*Math.PI);
context.fill_preserve();
-
+
context.arc(half, half, half-(half/4), 0, 2*Math.PI);
context.set_source_rgba(color.red, color.green, color.blue, 0.6*lighten);
context.fill_preserve();
-
+
return surface;
}
}
diff --git a/src/Widgets/ColorPopover.vala b/src/Widgets/ColorPopover.vala
index 695ff34c..a4ed993b 100644
--- a/src/Widgets/ColorPopover.vala
+++ b/src/Widgets/ColorPopover.vala
@@ -16,8 +16,8 @@
public class FeedReader.ColorPopover : Gtk.Popover {
private Gtk.Grid m_grid;
public signal void newColorSelected(int color);
-
-
+
+
public ColorPopover(Gtk.Widget widget)
{
m_grid = new Gtk.Grid();
@@ -32,7 +32,7 @@ public class FeedReader.ColorPopover : Gtk.Popover {
int rows = Constants.COLORS.length/4;
int color = 0;
ColorCircle tmpCircle;
-
+
for(int i = 0; i < rows; ++i)
{
for(int j = 0; j < columns; ++j)
@@ -46,7 +46,7 @@ public class FeedReader.ColorPopover : Gtk.Popover {
++color;
}
}
-
+
m_grid.show_all();
this.add(m_grid);
this.set_modal(true);
diff --git a/src/Widgets/ColumnView.vala b/src/Widgets/ColumnView.vala
index b6c812af..58e6c142 100644
--- a/src/Widgets/ColumnView.vala
+++ b/src/Widgets/ColumnView.vala
@@ -14,27 +14,27 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.ColumnView : Gtk.Paned {
-
+
private Gtk.Paned m_pane;
private ArticleView m_article_view;
private ArticleList m_articleList;
private feedList m_feedList;
private FeedListFooter m_footer;
private ColumnViewHeader m_headerbar;
-
+
private static ColumnView? m_columnView = null;
-
+
public static ColumnView get_default()
{
if(m_columnView == null)
{
m_columnView = new ColumnView();
}
-
+
return m_columnView;
}
-
-
+
+
private ColumnView()
{
Logger.debug("ColumnView: setup");
@@ -43,16 +43,16 @@ public class FeedReader.ColumnView : Gtk.Paned {
var feedListBox = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
feedListBox.pack_start(m_feedList);
feedListBox.pack_end(m_footer, false, false);
-
+
m_pane = new Gtk.Paned(Gtk.Orientation.HORIZONTAL);
m_pane.set_size_request(0, 300);
m_pane.set_position(Settings.state().get_int("feed-row-width"));
m_pane.pack1(feedListBox, false, false);
-
+
m_feedList.clearSelected.connect(() => {
m_footer.setRemoveButtonSensitive(false);
});
-
+
m_feedList.newFeedSelected.connect((feedID) => {
Logger.debug("ContentPage: new Feed selected");
m_articleList.setSelectedType(FeedListType.FEED);
@@ -61,7 +61,7 @@ public class FeedReader.ColumnView : Gtk.Paned {
m_headerbar.clearTitle();
m_articleList.setSelectedFeed(feedID);
newArticleList();
-
+
if(feedID == FeedID.ALL.to_string())
{
m_footer.setRemoveButtonSensitive(false);
@@ -72,7 +72,7 @@ public class FeedReader.ColumnView : Gtk.Paned {
m_footer.setSelectedRow(FeedListType.FEED, feedID);
}
});
-
+
m_feedList.newTagSelected.connect((tagID) => {
Logger.debug("ContentPage: new Tag selected");
m_articleList.setSelectedType(FeedListType.TAG);
@@ -84,7 +84,7 @@ public class FeedReader.ColumnView : Gtk.Paned {
m_footer.setRemoveButtonSensitive(true);
m_footer.setSelectedRow(FeedListType.TAG, tagID);
});
-
+
m_feedList.newCategorieSelected.connect((categorieID) => {
Logger.debug("ContentPage: new Category selected");
m_articleList.setSelectedType(FeedListType.CATEGORY);
@@ -93,7 +93,7 @@ public class FeedReader.ColumnView : Gtk.Paned {
m_headerbar.clearTitle();
m_articleList.setSelectedFeed(categorieID);
newArticleList();
-
+
if(categorieID != CategoryID.MASTER.to_string()
&& categorieID != CategoryID.TAGS.to_string())
{
@@ -105,10 +105,10 @@ public class FeedReader.ColumnView : Gtk.Paned {
m_footer.setRemoveButtonSensitive(false);
}
});
-
+
m_feedList.markAllArticlesAsRead.connect(markAllArticlesAsRead);
-
-
+
+
m_articleList = new ArticleList();
m_articleList.drag_begin.connect((context) => {
if(DataBase.readOnly().read_tags().is_empty)
@@ -136,10 +136,10 @@ public class FeedReader.ColumnView : Gtk.Paned {
return false;
});
setArticleListState((ArticleListState)Settings.state().get_enum("show-articles"));
-
+
m_pane.pack2(m_articleList, false, false);
-
-
+
+
m_articleList.row_activated.connect((row) => {
if(m_article_view.getCurrentArticle() != row.getID())
{
@@ -153,10 +153,10 @@ public class FeedReader.ColumnView : Gtk.Paned {
m_article_view.showMediaButton(row.haveMedia());
}
});
-
+
m_article_view = new ArticleView();
-
-
+
+
this.orientation = Gtk.Orientation.HORIZONTAL;
this.set_position(Settings.state().get_int("feeds-and-articles-width"));
this.pack1(m_pane, false, false);
@@ -164,84 +164,84 @@ public class FeedReader.ColumnView : Gtk.Paned {
this.notify["position"].connect(() => {
m_headerbar.set_position(this.get_position());
});
-
+
m_headerbar = new ColumnViewHeader();
m_headerbar.refresh.connect(() => {
syncStarted();
var app = FeedReaderApp.get_default();
app.sync();
});
-
+
m_headerbar.cancel.connect(() => {
FeedReaderApp.get_default().cancelSync();
});
-
+
m_headerbar.change_state.connect((state, transition) => {
setArticleListState(state);
clearArticleView();
newArticleList(transition);
});
-
+
m_headerbar.search_term.connect((searchTerm) => {
Logger.debug("MainWindow: new search term");
setSearchTerm(searchTerm);
clearArticleView();
newArticleList();
});
-
+
m_headerbar.notify["position"].connect(() => {
this.set_position(m_headerbar.get_position());
});
-
+
m_headerbar.toggledMarked.connect(() => {
toggleMarkedSelectedArticle();
});
-
+
m_headerbar.toggledRead.connect(() => {
toggleReadSelectedArticle();
});
}
-
+
public void hidePane()
{
m_pane.set_visible(false);
}
-
+
public void showPane()
{
m_pane.set_visible(true);
}
-
+
public int ArticleListNEXT()
{
if(m_article_view.fullscreenArticle())
{
m_article_view.setTransition(Gtk.StackTransitionType.SLIDE_LEFT, 500);
}
-
+
return m_articleList.move(false);
}
-
+
public int ArticleListPREV()
{
if(m_article_view.fullscreenArticle())
{
m_article_view.setTransition(Gtk.StackTransitionType.SLIDE_RIGHT, 500);
}
-
+
return m_articleList.move(true);
}
-
+
public void FeedListNEXT()
{
m_feedList.move(false);
}
-
+
public void FeedListPREV()
{
m_feedList.move(true);
}
-
+
public void newArticleList(Gtk.StackTransitionType transition = Gtk.StackTransitionType.CROSSFADE)
{
Logger.debug("ContentPage.newArticleList");
@@ -260,140 +260,140 @@ public class FeedReader.ColumnView : Gtk.Paned {
m_articleList.newList(transition);
}
}
-
+
public void newFeedList(bool defaultSettings = false)
{
m_feedList.newFeedlist(m_articleList.getState(), defaultSettings);
}
-
+
public void refreshFeedListCounter()
{
m_feedList.refreshCounters(m_articleList.getState());
}
-
+
public void reloadArticleView()
{
m_article_view.load();
}
-
+
public void updateArticleList()
{
m_articleList.updateArticleList();
}
-
+
private void setArticleListState(ArticleListState state)
{
var oldState = m_articleList.getState();
m_articleList.setState(state);
-
+
if(oldState == ArticleListState.MARKED
|| state == ArticleListState.MARKED)
{
m_feedList.refreshCounters(state);
}
}
-
+
private void setSearchTerm(string searchTerm)
{
m_articleList.setSearchTerm(searchTerm);
m_article_view.setSearchTerm(searchTerm);
}
-
+
private void clearArticleView()
{
m_headerbar.showArticleButtons(false);
m_headerbar.clearTitle();
m_article_view.clearContent();
}
-
+
public string getSelectedFeedListRow()
{
return m_feedList.getSelectedRow();
}
-
+
public Article getSelectedArticle()
{
return m_articleList.getSelectedArticle();
}
-
+
public void markAllArticlesAsRead()
{
m_headerbar.setRead(ArticleStatus.READ);
m_articleList.markAllAsRead();
}
-
+
public void toggleReadSelectedArticle()
{
m_headerbar.toggleRead();
m_article_view.setRead(m_articleList.toggleReadSelected());
}
-
+
public void toggleMarkedSelectedArticle()
{
m_headerbar.toggleMarked();
m_article_view.setMarked(m_articleList.toggleMarkedSelected());
}
-
+
public void openSelectedArticle()
{
m_articleList.openSelected();
}
-
+
public void centerSelectedRow()
{
m_articleList.centerSelectedRow();
}
-
+
public void removeTagFromSelectedRow(string tagID)
{
m_articleList.removeTagFromSelectedRow(tagID);
}
-
+
public void syncStarted()
{
m_articleList.syncStarted();
}
-
+
public void syncFinished()
{
m_articleList.syncFinished();
}
-
+
public Gdk.RGBA getBackgroundColor()
{
return m_articleList.getBackgroundColor();
}
-
+
public void showArticleListOverlay()
{
m_articleList.showOverlay();
}
-
+
public void setOffline()
{
m_headerbar.setOffline();
m_feedList.setOffline();
-
+
if(!Utils.canManipulateContent(false))
{
m_footer.setAddButtonSensitive(false);
m_feedList.newFeedlist(m_articleList.getState(), false);
}
}
-
+
public void setOnline()
{
m_headerbar.setOnline();
m_feedList.setOnline();
-
+
if(Utils.canManipulateContent(true))
{
m_footer.setAddButtonSensitive(true);
m_feedList.newFeedlist(m_articleList.getState(), false);
-
+
var selected_row = m_feedList.getSelectedRow();
string[] selected = selected_row.split(" ");
-
+
if((selected[0] == "feed" && selected[1] == FeedID.ALL.to_string())
|| (selected[0] == "cat" && (selected[1] == CategoryID.MASTER.to_string() || selected[1] == CategoryID.TAGS.to_string())))
{
@@ -401,93 +401,93 @@ public class FeedReader.ColumnView : Gtk.Paned {
}
}
}
-
+
public void footerSetBusy()
{
m_footer.setBusy();
}
-
+
public void footerSetReady()
{
m_footer.setReady();
}
-
+
public void footerShowError(string errmsg)
{
m_footer.showError(errmsg);
}
-
+
public feedList getFeedList()
{
return m_feedList;
}
-
+
public void enterFullscreenArticle()
{
m_article_view.enterFullscreenArticle();
}
-
+
public void leaveFullscreenArticle()
{
m_article_view.leaveFullscreenArticle();
}
-
+
public bool isFullscreen()
{
return m_article_view.fullscreenArticle();
}
-
+
public void exitFullscreenVideo()
{
m_article_view.exitFullscreenVideo();
}
-
+
public bool isFullscreenVideo()
{
return m_article_view.fullscreenVideo();
}
-
+
public bool ArticleListSelectedIsFirst()
{
return m_articleList.selectedIsFirst();
}
-
+
public bool ArticleListSelectedIsLast()
{
return m_articleList.selectedIsLast();
}
-
+
public void ArticleViewAddMedia(MediaPlayer media)
{
m_article_view.addMedia(media);
}
-
+
public void articleViewKillMedia()
{
m_article_view.killMedia();
}
-
+
public void print()
{
m_article_view.print();
}
-
+
public bool playingMedia()
{
return m_article_view.playingMedia();
}
-
+
public string? displayedArticle()
{
return m_article_view.getCurrentArticle();
}
-
+
public void saveState(ref InterfaceState state)
{
int offset = 0;
double scrollPos = 0.0;
m_articleList.getSavedState(out scrollPos, out offset);
-
+
state.setArticleListScrollPos(scrollPos);
state.setArticleListRowOffset(offset);
state.setFeedListSelectedRow(m_feedList.getSelectedRow());
@@ -502,25 +502,25 @@ public class FeedReader.ColumnView : Gtk.Paned {
state.setArticleListSelectedRow(selectedArticle.getArticleID());
}
state.setArticleListTopRow(m_articleList.getFirstArticle());
-
+
m_headerbar.saveState(ref state);
}
-
+
public bool searchFocused()
{
return m_headerbar.searchFocused();
}
-
+
public ColumnViewHeader getHeader()
{
return m_headerbar;
}
-
+
public void ArticleViewSendEvent(Gdk.EventKey event)
{
m_article_view.sendEvent(event);
}
-
+
public void clear()
{
m_articleList.clear();
diff --git a/src/Widgets/ColumnViewHeader.vala b/src/Widgets/ColumnViewHeader.vala
index f1b2b391..4e6aa43f 100644
--- a/src/Widgets/ColumnViewHeader.vala
+++ b/src/Widgets/ColumnViewHeader.vala
@@ -14,7 +14,7 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.ColumnViewHeader : Gtk.Paned {
-
+
private ModeButton m_modeButton;
private UpdateButton m_refresh_button;
private Gtk.SearchEntry m_search;
@@ -27,18 +27,18 @@ public class FeedReader.ColumnViewHeader : Gtk.Paned {
public signal void search_term(string searchTerm);
public signal void toggledMarked();
public signal void toggledRead();
-
-
+
+
public ColumnViewHeader()
{
m_state = (ArticleListState)Settings.state().get_enum("show-articles");
-
+
m_modeButton = new ModeButton();
m_modeButton.append_text(_("All"), _("Show all articles"));
m_modeButton.append_text(_("Unread"), _("Show only unread articles"));
m_modeButton.append_text(_("Starred"), _("Show only starred articles"));
m_modeButton.set_active(m_state, true);
-
+
m_modeButton.mode_changed.connect(() => {
var transition = Gtk.StackTransitionType.CROSSFADE;
if(m_state == ArticleListState.ALL
@@ -51,11 +51,11 @@ public class FeedReader.ColumnViewHeader : Gtk.Paned {
{
transition = Gtk.StackTransitionType.SLIDE_RIGHT;
}
-
+
m_state = (ArticleListState)m_modeButton.selected;
change_state(m_state, transition);
});
-
+
bool updating = Settings.state().get_boolean("currently-updating");
m_refresh_button = new UpdateButton.from_icon_name("feed-refresh-symbolic", _("Update feeds"), true, true);
m_refresh_button.updating(updating);
@@ -70,16 +70,16 @@ public class FeedReader.ColumnViewHeader : Gtk.Paned {
m_refresh_button.setSensitive(false);
}
});
-
-
-
+
+
+
m_search = new Gtk.SearchEntry();
m_search.placeholder_text = _("Search Articles");
if(Settings.tweaks().get_boolean("restore-searchterm"))
{
m_search.text = Settings.state().get_string("search-term");
}
-
+
// connect after 160ms because Gtk.SearchEntry fires search_changed with 150ms delay
// with the timeout the signal should not trigger a newList() when restoring the state at startup
GLib.Timeout.add(160, () => {
@@ -88,23 +88,23 @@ public class FeedReader.ColumnViewHeader : Gtk.Paned {
});
return false;
});
-
+
m_header_left = new Gtk.HeaderBar();
m_header_left.show_close_button = true;
m_header_left.get_style_context().add_class("header_right");
m_header_left.get_style_context().add_class("titlebar");
m_header_left.set_size_request(500, 0);
-
+
var menubutton = new Gtk.MenuButton();
menubutton.image = new Gtk.Image.from_icon_name("open-menu-symbolic", Gtk.IconSize.MENU);
menubutton.set_use_popover(true);
menubutton.set_menu_model(Utils.getMenu());
m_header_left.pack_end(menubutton);
-
+
m_header_left.pack_end(m_search);
m_header_left.pack_start(m_modeButton);
m_header_left.pack_start(m_refresh_button);
-
+
m_header_right = new ArticleViewHeader("view-fullscreen-symbolic", _("Read article fullscreen"));
m_header_right.show_close_button = true;
m_header_right.get_style_context().add_class("header_left");
@@ -122,18 +122,18 @@ public class FeedReader.ColumnViewHeader : Gtk.Paned {
ColumnView.get_default().enterFullscreenArticle();
MainWindow.get_default().fullscreen();
});
-
+
Gtk.Settings.get_default().notify["gtk-decoration-layout"].connect(set_window_buttons);
realize.connect(set_window_buttons);
set_window_buttons();
-
-
+
+
this.pack1(m_header_left, true, false);
this.pack2(m_header_right, true, false);
this.get_style_context().add_class("headerbar_pane");
this.set_position(Settings.state().get_int("feeds-and-articles-width"));
}
-
+
private void set_window_buttons()
{
string[] buttons = Gtk.Settings.get_default().gtk_decoration_layout.split(":");
@@ -142,16 +142,16 @@ public class FeedReader.ColumnViewHeader : Gtk.Paned {
buttons = {buttons[0], ""};
Logger.warning("gtk_decoration_layout in unexpected format");
}
-
+
m_header_left.set_decoration_layout(buttons[0] + ":");
m_header_right.set_decoration_layout(":" + buttons[1]);
}
-
+
public void setRefreshButton(bool status)
{
m_refresh_button.updating(status, false);
}
-
+
public void setButtonsSensitive(bool sensitive)
{
Logger.debug("HeaderBar: setButtonsSensitive %s".printf(sensitive ? "true" : "false"));
@@ -159,67 +159,67 @@ public class FeedReader.ColumnViewHeader : Gtk.Paned {
m_refresh_button.setSensitive(sensitive);
m_search.sensitive = sensitive;
}
-
+
public void showArticleButtons(bool show)
{
m_header_right.showArticleButtons(show);
}
-
+
public bool searchFocused()
{
return m_search.has_focus;
}
-
+
public void setMarked(ArticleStatus marked)
{
m_header_right.setMarked(marked);
}
-
+
public void toggleMarked()
{
m_header_right.toggleMarked();
}
-
+
public void setRead(ArticleStatus read)
{
m_header_right.setRead(read);
}
-
+
public void toggleRead()
{
m_header_right.toggleRead();
}
-
+
public void focusSearch()
{
m_search.grab_focus();
}
-
+
public void setOffline()
{
m_header_right.setOffline();
}
-
+
public void setOnline()
{
m_header_right.setOnline();
}
-
+
public void showMediaButton(bool show)
{
m_header_right.showMediaButton(show);
}
-
+
public void updateSyncProgress(string progress)
{
m_refresh_button.setProgress(progress);
}
-
+
public void refreshSahrePopover()
{
m_header_right.refreshSahrePopover();
}
-
+
public void saveState(ref InterfaceState state)
{
state.setSearchTerm(m_search.text);
@@ -233,5 +233,5 @@ public class FeedReader.ColumnViewHeader : Gtk.Paned {
{
m_header_right.set_title("FeedReader");
}
-
+
}
diff --git a/src/Widgets/FeedList.vala b/src/Widgets/FeedList.vala
index be2d6192..9d814805 100644
--- a/src/Widgets/FeedList.vala
+++ b/src/Widgets/FeedList.vala
@@ -14,7 +14,7 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.feedList : Gtk.ScrolledWindow {
-
+
private Gtk.ListBox m_list;
private string? m_selectedID = null;
private FeedListType m_selectedType = FeedListType.ALL_FEEDS;
@@ -29,7 +29,7 @@ public class FeedReader.feedList : Gtk.ScrolledWindow {
public signal void newCategorieSelected(string categorieID);
public signal void markAllArticlesAsRead();
public signal void clearSelected();
-
+
public feedList () {
m_spinner = new Gtk.Spinner();
m_list = new Gtk.ListBox();
@@ -39,10 +39,10 @@ public class FeedReader.feedList : Gtk.ScrolledWindow {
var feedlist_box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
feedlist_box.pack_start(m_branding, false, false, 0);
feedlist_box.pack_start(m_list);
-
+
this.set_size_request(100, 0);
this.add(feedlist_box);
-
+
m_list.row_activated.connect(() => {
FeedRow selected_feed = m_list.get_selected_row() as FeedRow;
if(selected_feed != null)
@@ -52,13 +52,13 @@ public class FeedReader.feedList : Gtk.ScrolledWindow {
{
return;
}
-
+
m_selectedID = selected_feed.getID();
m_selectedType = FeedListType.FEED;
newFeedSelected(selected_feed.getID());
return;
}
-
+
CategoryRow selected_categorie = m_list.get_selected_row() as CategoryRow;
if(selected_categorie != null)
{
@@ -67,13 +67,13 @@ public class FeedReader.feedList : Gtk.ScrolledWindow {
{
return;
}
-
+
m_selectedID = selected_categorie.getID();
m_selectedType = FeedListType.CATEGORY;
newCategorieSelected(selected_categorie.getID());
return;
}
-
+
TagRow selected_tag = m_list.get_selected_row() as TagRow;
if(selected_tag != null)
{
@@ -82,15 +82,15 @@ public class FeedReader.feedList : Gtk.ScrolledWindow {
{
return;
}
-
+
m_selectedID = selected_tag.getTag().getTagID();
m_selectedType = FeedListType.TAG;
newTagSelected(selected_tag.getTag().getTagID());
return;
}
});
-
-
+
+
m_list.key_press_event.connect((event) => {
if(event.keyval == Gdk.Key.Down)
{
@@ -107,12 +107,12 @@ public class FeedReader.feedList : Gtk.ScrolledWindow {
{
selected_categorie.expand_collapse();
}
-
+
}
return true;
});
}
-
+
public void collapseSelectedCat()
{
CategoryRow selected_categorie = m_list.get_selected_row() as CategoryRow;
@@ -121,21 +121,21 @@ public class FeedReader.feedList : Gtk.ScrolledWindow {
selected_categorie.expand_collapse();
}
}
-
+
public void move(bool down)
{
FeedRow selected_feed = m_list.get_selected_row() as FeedRow;
CategoryRow selected_categorie = m_list.get_selected_row() as CategoryRow;
TagRow selected_tag = m_list.get_selected_row() as TagRow;
-
+
var FeedListChildren = m_list.get_children();
-
+
if(!down)
{
FeedListChildren.reverse();
}
-
-
+
+
int current = -1;
if(selected_feed != null)
{
@@ -149,14 +149,14 @@ public class FeedReader.feedList : Gtk.ScrolledWindow {
{
current = FeedListChildren.index(selected_tag);
}
-
+
current++;
while(current < FeedListChildren.length())
{
FeedRow current_feed = FeedListChildren.nth_data(current) as FeedRow;
CategoryRow current_categorie = FeedListChildren.nth_data(current) as CategoryRow;
TagRow current_tag = FeedListChildren.nth_data(current) as TagRow;
-
+
if(current_feed != null)
{
if(current_feed.getID() != FeedID.SEPARATOR.to_string() && current_feed.isRevealed() && current_feed.getName() != "")
@@ -166,7 +166,7 @@ public class FeedReader.feedList : Gtk.ScrolledWindow {
break;
}
}
-
+
if(current_categorie != null)
{
if(current_categorie.isRevealed())
@@ -176,7 +176,7 @@ public class FeedReader.feedList : Gtk.ScrolledWindow {
break;
}
}
-
+
if(current_tag != null)
{
if(current_tag.isRevealed())
@@ -186,25 +186,25 @@ public class FeedReader.feedList : Gtk.ScrolledWindow {
break;
}
}
-
+
current++;
}
}
-
-
+
+
public void newFeedlist(ArticleListState state, bool defaultSettings, bool masterCat = false)
{
Logger.debug("FeedList: new FeedList");
-
+
if(m_busy)
{
Logger.debug("FeedList: busy");
return;
}
-
+
m_busy = true;
m_branding.refresh();
-
+
if(!isEmpty())
{
if(!defaultSettings)
@@ -212,15 +212,15 @@ public class FeedReader.feedList : Gtk.ScrolledWindow {
Settings.state().set_strv("expanded-categories", getExpandedCategories());
Settings.state().set_string("feedlist-selected-row", getSelectedRow());
}
-
+
Settings.state().set_double("feed-row-scrollpos", vadjustment.value);
}
-
+
clear();
createFeedlist(state, defaultSettings, masterCat);
m_busy = false;
}
-
+
public void clear()
{
var FeedChildList = m_list.get_children();
@@ -230,7 +230,7 @@ public class FeedReader.feedList : Gtk.ScrolledWindow {
row.destroy();
}
}
-
+
private bool isEmpty()
{
var FeedChildList = m_list.get_children();
@@ -238,15 +238,15 @@ public class FeedReader.feedList : Gtk.ScrolledWindow {
{
return true;
}
-
+
return false;
}
-
-
+
+
private void createFeedlist(ArticleListState state, bool defaultSettings, bool masterCat)
{
var separatorFeed = new Feed(FeedID.SEPARATOR.to_string(), "", "", 0);
-
+
uint unread = 0;
if(state == ArticleListState.MARKED)
{
@@ -257,7 +257,7 @@ public class FeedReader.feedList : Gtk.ScrolledWindow {
unread = DataBase.readOnly().get_unread_total();
}
var allFeed = new Feed(FeedID.ALL.to_string(), _("All Articles"), "", unread);
-
+
var row_separator1 = new FeedRow(separatorFeed, "-1", 0);
var separator1 = new Gtk.Separator(Gtk.Orientation.HORIZONTAL);
separator1.get_style_context().add_class("fr-sidebar-separator");
@@ -265,8 +265,8 @@ public class FeedReader.feedList : Gtk.ScrolledWindow {
row_separator1.add(separator1);
row_separator1.sensitive = false;
m_list.add(row_separator1);
-
-
+
+
var row_all = new FeedRow(allFeed, "-1", 0);
row_all.margin_top = 8;
row_all.margin_bottom = 8;
@@ -274,7 +274,7 @@ public class FeedReader.feedList : Gtk.ScrolledWindow {
row_all.activateUnreadEventbox((state == ArticleListState.MARKED) ? false : true);
row_all.setAsRead.connect(markSelectedRead);
row_all.reveal(true, 0);
-
+
var row_separator = new FeedRow(separatorFeed, "-1", 0);
var separator = new Gtk.Separator(Gtk.Orientation.HORIZONTAL);
separator.get_style_context().add_class("fr-sidebar-separator");
@@ -282,17 +282,17 @@ public class FeedReader.feedList : Gtk.ScrolledWindow {
row_separator.add(separator);
row_separator.sensitive = false;
m_list.add(row_separator);
-
+
//-------------------------------------------------------------------
-
+
var feeds = DataBase.readOnly().read_feeds((state == ArticleListState.MARKED) ? true : false);
-
+
if(!Utils.onlyShowFeeds())
{
createCategories(ref feeds, masterCat, state);
createTags();
}
-
+
foreach(var item in feeds)
{
if(!Utils.onlyShowFeeds())
@@ -303,7 +303,7 @@ public class FeedReader.feedList : Gtk.ScrolledWindow {
{
pos++;
var tmpRow = row as CategoryRow;
-
+
if(tmpRow != null)
{
if(item.getCatIDs().contains(tmpRow.getID())
@@ -351,20 +351,20 @@ public class FeedReader.feedList : Gtk.ScrolledWindow {
feedrow.activateUnreadEventbox((state == ArticleListState.MARKED) ? false : true);
}
}
-
+
initCollapseCategories();
restoreSelectedRow();
this.show_all();
vadjustment.notify["upper"].connect(restoreScrollPos);
}
-
+
private void restoreSelectedRow()
{
Logger.debug("FeedList.restoreSelectedRow: " + Settings.state().get_string("feedlist-selected-row"));
string[] selectedRow = Settings.state().get_string("feedlist-selected-row").split(" ", 2);
-
+
var FeedChildList = m_list.get_children();
-
+
if(selectedRow[0] == "feed")
{
foreach(Gtk.Widget row in FeedChildList)
@@ -381,7 +381,7 @@ public class FeedReader.feedList : Gtk.ScrolledWindow {
}
}
}
-
+
if(selectedRow[0] == "cat")
{
foreach(Gtk.Widget row in FeedChildList)
@@ -398,7 +398,7 @@ public class FeedReader.feedList : Gtk.ScrolledWindow {
}
}
}
-
+
if(selectedRow[0] == "tag")
{
foreach(Gtk.Widget row in FeedChildList)
@@ -415,8 +415,8 @@ public class FeedReader.feedList : Gtk.ScrolledWindow {
}
}
}
-
-
+
+
// row not found: default select "ALL ARTICLES"
Logger.debug("FeedList: restoreSelectedRow: no selected row found, selectin default");
foreach(Gtk.Widget row in FeedChildList)
@@ -431,14 +431,14 @@ public class FeedReader.feedList : Gtk.ScrolledWindow {
}
}
}
-
-
+
+
void restoreScrollPos(Object sender, ParamSpec property)
{
vadjustment.notify["upper"].disconnect(restoreScrollPos);
vadjustment.set_value(Settings.state().get_double("feed-row-scrollpos"));
}
-
+
private void addMasterCategory(int length, string name)
{
var CategoryRow = new CategoryRow(
@@ -467,7 +467,7 @@ public class FeedReader.feedList : Gtk.ScrolledWindow {
CategoryRow.moveUP.connect(moveUP);
CategoryRow.reveal(true, 0);
}
-
+
private void addTagCategory(int length)
{
var tagrow = new CategoryRow(
@@ -496,8 +496,8 @@ public class FeedReader.feedList : Gtk.ScrolledWindow {
tagrow.reveal(true, 0);
m_TagsDisplayed = true;
}
-
-
+
+
private void createCategories(ref Gee.List<Feed> feeds, bool masterCat, ArticleListState state)
{
var db = DataBase.readOnly();
@@ -507,12 +507,12 @@ public class FeedReader.feedList : Gtk.ScrolledWindow {
bool supportCategories = true;
bool supportMultiLevelCategories = false;
string uncategorizedID = "";
-
+
supportTags = FeedReaderBackend.get_default().supportTags();
supportCategories = FeedReaderBackend.get_default().supportCategories();
uncategorizedID = FeedReaderBackend.get_default().uncategorizedID();
supportMultiLevelCategories = FeedReaderBackend.get_default().supportMultiLevelCategories();
-
+
if((supportTags
&& !db.isTableEmpty("tags"))
|| masterCat)
@@ -530,11 +530,11 @@ public class FeedReader.feedList : Gtk.ScrolledWindow {
m_TagsDisplayed = false;
Logger.debug("FeedList: no tags");
}
-
+
for(int i = 1; i <= maxCatLevel; i++)
{
var categories = db.read_categories_level(i, feeds);
-
+
if(db.haveFeedsWithoutCat())
{
categories.insert(
@@ -549,7 +549,7 @@ public class FeedReader.feedList : Gtk.ScrolledWindow {
)
);
}
-
+
foreach(var item in categories)
{
var FeedChildList = m_list.get_children();
@@ -572,7 +572,7 @@ public class FeedReader.feedList : Gtk.ScrolledWindow {
}
level++;
}
-
+
var CategoryRow = new CategoryRow(
item.getTitle(),
item.getCatID(),
@@ -642,7 +642,7 @@ public void refreshCounters(ArticleListState state)
uint allCount = (state == ArticleListState.MARKED) ? db.get_marked_total() : db.get_unread_total();
var feeds = db.read_feeds((state == ArticleListState.MARKED) ? true : false);
var categories = db.read_categories(feeds);
-
+
// double-check
uint feedCount = 0;
foreach(var feed in feeds)
@@ -653,9 +653,9 @@ public void refreshCounters(ArticleListState state)
{
Logger.warning(@"FeedList.refreshCounters: counts don't match - allCount: $allCount - feedCount: $feedCount");
}
-
+
var FeedChildList = m_list.get_children();
-
+
// update "All Articles"
foreach(Gtk.Widget row in FeedChildList)
{
@@ -667,7 +667,7 @@ public void refreshCounters(ArticleListState state)
break;
}
}
-
+
// update feeds
foreach(Gtk.Widget row in FeedChildList)
{
@@ -691,14 +691,14 @@ public void refreshCounters(ArticleListState state)
tmpFeedRow.reveal(true);
}
}
-
-
+
+
break;
}
}
}
}
-
+
// update categories
foreach(Gtk.Widget row in FeedChildList)
{
@@ -722,13 +722,13 @@ public void refreshCounters(ArticleListState state)
tmpCatRow.reveal(true);
}
}
-
+
break;
}
}
}
}
-
+
if(db.haveFeedsWithoutCat())
{
foreach(Gtk.Widget row in FeedChildList)
@@ -750,7 +750,7 @@ public void refreshCounters(ArticleListState state)
{
tmpCatRow.reveal(true);
}
-
+
break;
}
}
@@ -778,7 +778,7 @@ private void collapseCategorieInternal(string catID, bool selectParent, bool ani
{
var FeedChildList = m_list.get_children();
var selected_row = m_list.get_selected_row();
-
+
foreach(Gtk.Widget row in FeedChildList)
{
var tmpFeedRow = row as FeedRow;
@@ -799,13 +799,13 @@ private void collapseCategorieInternal(string catID, bool selectParent, bool ani
tmpTagRow.reveal(false, animationTime);
}
}
-
+
if(selectParent)
{
var selected_feed = selected_row as FeedRow;
var selected_cat = selected_row as CategoryRow;
var selected_tag = selected_row as TagRow;
-
+
if((selected_feed != null && !selected_feed.isRevealed())
|| (selected_cat != null && !selected_cat.isRevealed())
|| (selected_tag != null && !selected_tag.isRevealed()))
@@ -829,7 +829,7 @@ private void collapseCategorieInternal(string catID, bool selectParent, bool ani
private void expandCategorieInternal(string catID)
{
var FeedChildList = m_list.get_children();
-
+
foreach(Gtk.Widget row in FeedChildList)
{
var tmpFeedRow = row as FeedRow;
@@ -881,7 +881,7 @@ public void expand_collapse_category(string catID, bool expand = true)
private bool isCategorieExpanded(string catID)
{
var FeedChildList = m_list.get_children();
-
+
foreach(Gtk.Widget row in FeedChildList)
{
var tmpCatRow = row as CategoryRow;
@@ -890,7 +890,7 @@ private bool isCategorieExpanded(string catID)
return true;
}
}
-
+
return false;
}
@@ -902,7 +902,7 @@ public string getSelectedFeed()
{
return selected_row.getID();
}
-
+
return "";
}
@@ -911,7 +911,7 @@ public string[] getExpandedCategories()
{
var FeedChildList = m_list.get_children();
string[] e = {};
-
+
foreach(Gtk.Widget row in FeedChildList)
{
var tmpCatRow = row as CategoryRow;
@@ -932,7 +932,7 @@ public string getSelectedRow()
var feedrow = m_list.get_selected_row() as FeedRow;
var catrow = m_list.get_selected_row() as CategoryRow;
var tagrow = m_list.get_selected_row() as TagRow;
-
+
if(feedrow != null)
{
return "feed " + feedrow.getID();
@@ -945,7 +945,7 @@ public string getSelectedRow()
{
return "tag " + tagrow.getTag().getTagID();
}
-
+
return "";
}
@@ -953,7 +953,7 @@ public string getSelectedRow()
private void markSelectedRead(FeedListType type, string id)
{
Logger.debug("FeedList: mark all articles as read");
-
+
if(type == FeedListType.FEED)
{
if(id == FeedID.ALL.to_string())
@@ -986,7 +986,7 @@ private void markSelectedRead(FeedListType type, string id)
private bool getCatState(string id)
{
string[] list = Settings.state().get_strv("expanded-categories");
-
+
foreach(string str in list)
{
if(id == str)
@@ -994,7 +994,7 @@ private bool getCatState(string id)
return true;
}
}
-
+
return false;
}
@@ -1029,7 +1029,7 @@ public void copySelectedFeedURL(string feed_id){
{
Gdk.Display display = MainWindow.get_default().get_display();
Gtk.Clipboard clipboard = Gtk.Clipboard.get_for_display(display, Gdk.SELECTION_CLIPBOARD);
-
+
clipboard.set_text(feed_url, feed_url.length);
}
}
@@ -1044,7 +1044,7 @@ public void moveUP()
public void revealRow(string id, FeedListType type, bool reveal, uint time)
{
var FeedChildList = m_list.get_children();
-
+
switch(type)
{
case FeedListType.CATEGORY:
@@ -1099,13 +1099,13 @@ public void addEmptyTagRow()
public void removeEmptyTagRow()
{
Logger.debug("removeEmptyTagRow");
-
+
if(m_busy)
{
Logger.debug("FeedList: busy");
return;
}
-
+
if(m_emptyTagRow != null)
{
removeRow(m_emptyTagRow, 250);
@@ -1126,7 +1126,7 @@ private void removeRow(Gtk.Widget? row, int duration = 700)
var tagRow = row as TagRow;
var catRow = row as CategoryRow;
var feedRow = row as FeedRow;
-
+
if(tagRow != null)
{
tagRow.reveal(false, duration);
@@ -1157,10 +1157,10 @@ private void removeRow(Gtk.Widget? row, int duration = 700)
private void onDragBegin(Gdk.DragContext context)
{
Logger.debug("FeedList: onDragBegin");
-
+
// save current state
MainWindow.get_default().writeInterfaceState();
-
+
// collapse all feeds and show all Categories
var FeedChildList = m_list.get_children();
foreach(Gtk.Widget row in FeedChildList)
@@ -1168,7 +1168,7 @@ private void onDragBegin(Gdk.DragContext context)
var tmpCat = row as CategoryRow;
var tmpFeed = row as FeedRow;
var tmpTag = row as TagRow;
-
+
if(tmpCat != null)
{
tmpCat.reveal(true);
@@ -1192,7 +1192,7 @@ private void showNewCategory()
{
int level = 1;
int pos = -1;
-
+
if(FeedReaderBackend.get_default().supportTags())
{
var FeedChildList = m_list.get_children();
@@ -1211,7 +1211,7 @@ private void showNewCategory()
{
level = 1;
}
-
+
var newRow = new CategoryRow(_("New Category"), CategoryID.NEW.to_string(), 99, 0, CategoryID.MASTER.to_string(), level, false);
newRow.drag_failed.connect(onDragEnd);
m_list.insert(newRow, pos);
@@ -1228,7 +1228,7 @@ private bool onDragEnd(Gdk.DragContext context, Gtk.DragResult result)
var tmpCat = row as CategoryRow;
var tmpFeed = row as FeedRow;
var tmpTag = row as TagRow;
-
+
if(tmpCat != null)
{
if(tmpCat.getID() == CategoryID.NEW.to_string())
@@ -1236,7 +1236,7 @@ private bool onDragEnd(Gdk.DragContext context, Gtk.DragResult result)
removeRow(tmpCat, 250);
continue;
}
-
+
if(tmpCat.getID() != CategoryID.MASTER.to_string()
&& tmpCat.getID() != CategoryID.TAGS.to_string()
&& tmpCat.getParent() != CategoryID.MASTER.to_string()
@@ -1261,7 +1261,7 @@ private bool onDragEnd(Gdk.DragContext context, Gtk.DragResult result)
tmpTag.reveal(true);
}
}
-
+
return false;
}
}
diff --git a/src/Widgets/FeedListFooter.vala b/src/Widgets/FeedListFooter.vala
index 2edcf863..cd85c7f2 100644
--- a/src/Widgets/FeedListFooter.vala
+++ b/src/Widgets/FeedListFooter.vala
@@ -14,13 +14,13 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.FeedListFooter : Gtk.Box {
-
+
private Gtk.Box m_box;
private Gtk.Stack m_addStack;
private Gtk.Spinner m_addSpinner;
private AddButton m_addButton;
private RemoveButton m_removeButton;
-
+
public FeedListFooter()
{
this.orientation = Gtk.Orientation.VERTICAL;
@@ -47,27 +47,27 @@ public class FeedReader.FeedListFooter : Gtk.Box {
m_box.pack_start(m_removeButton);
this.pack_start(sep2, false, false);
this.pack_start(m_box);
-
+
if(!FeedReaderBackend.get_default().supportFeedManipulation())
{
m_addButton.set_sensitive(false);
m_removeButton.set_sensitive(false);
}
}
-
+
public void setBusy()
{
m_addStack.set_visible_child_name("spinner");
m_addStack.show_all();
}
-
+
public void setReady()
{
m_addStack.set_visible_child_name("button");
m_addSpinner.start();
m_addStack.show_all();
}
-
+
public void setRemoveButtonSensitive(bool sensitive)
{
if(FeedReaderApp.get_default().isOnline() && FeedReaderBackend.get_default().supportFeedManipulation())
@@ -75,12 +75,12 @@ public class FeedReader.FeedListFooter : Gtk.Box {
m_removeButton.set_sensitive(sensitive);
}
}
-
+
public void setSelectedRow(FeedListType type, string id)
{
m_removeButton.setSelectedRow(type, id);
}
-
+
public void setAddButtonSensitive(bool active)
{
if(FeedReaderBackend.get_default().supportFeedManipulation())
@@ -89,12 +89,12 @@ public class FeedReader.FeedListFooter : Gtk.Box {
m_removeButton.set_sensitive(active);
}
}
-
+
public void showError(string errmsg)
{
var label = new Gtk.Label(errmsg);
label.margin = 20;
-
+
var pop = new Gtk.Popover(m_addStack);
pop.add(label);
pop.show_all();
@@ -114,7 +114,7 @@ public class FeedReader.AddButton : Gtk.Button {
this.relief = Gtk.ReliefStyle.NONE;
this.set_tooltip_text(_("Add feed"));
}
-
+
public void onClick()
{
this.get_style_context().add_class("footer-popover");
@@ -131,7 +131,7 @@ public class FeedReader.AddButton : Gtk.Button {
public class FeedReader.RemoveButton : Gtk.Button {
private FeedListType m_type;
private string m_id;
-
+
public RemoveButton()
{
var image = new Gtk.Image.from_icon_name("feed-remove-symbolic", Gtk.IconSize.SMALL_TOOLBAR);
@@ -143,7 +143,7 @@ public class FeedReader.RemoveButton : Gtk.Button {
this.relief = Gtk.ReliefStyle.NONE;
this.set_tooltip_text(_("Remove feed"));
}
-
+
public void onClick()
{
this.get_style_context().add_class("footer-popover");
diff --git a/src/Widgets/FeedRow.vala b/src/Widgets/FeedRow.vala
index 2cc86000..e730e016 100644
--- a/src/Widgets/FeedRow.vala
+++ b/src/Widgets/FeedRow.vala
@@ -14,7 +14,7 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.FeedRow : Gtk.ListBoxRow {
-
+
private Feed m_feed;
private string m_parentCatID;
private Gtk.Box m_box;
@@ -32,29 +32,29 @@ public class FeedReader.FeedRow : Gtk.ListBoxRow {
public signal void copyFeedURL(string id);
public signal void moveUP();
public signal void deselectRow();
-
+
public FeedRow(Feed feed, string parentCat, int level)
{
m_subscribed = true;
m_parentCatID = parentCat;
m_feed = feed;
-
+
if(m_feed.getFeedID() != FeedID.SEPARATOR.to_string())
{
var rowhight = 30;
m_box = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 0);
m_icon = createFavIcon();
m_icon.margin_start = level * 24;
-
+
m_label = new Gtk.Label(m_feed.getTitle());
m_label.set_size_request (0, rowhight);
m_label.set_ellipsize (Pango.EllipsizeMode.END);
m_label.set_alignment(0, 0.5f);
-
+
m_unread = new Gtk.Label(null);
m_unread.set_size_request (0, rowhight);
m_unread.set_alignment(0.8f, 0.5f);
-
+
m_unreadStack = new Gtk.Stack();
m_unreadStack.set_transition_type(Gtk.StackTransitionType.NONE);
m_unreadStack.set_transition_duration(0);
@@ -63,15 +63,15 @@ public class FeedReader.FeedRow : Gtk.ListBoxRow {
var markIcon = new Gtk.Image.from_icon_name("feed-mark-read-symbolic", Gtk.IconSize.LARGE_TOOLBAR);
markIcon.get_style_context().add_class("fr-sidebar-symbolic");
m_unreadStack.add_named(markIcon, "mark");
-
+
m_unreadBox = new Gtk.EventBox();
m_unreadBox.set_events(Gdk.EventMask.BUTTON_PRESS_MASK);
m_unreadBox.set_events(Gdk.EventMask.ENTER_NOTIFY_MASK);
m_unreadBox.set_events(Gdk.EventMask.LEAVE_NOTIFY_MASK);
m_unreadBox.add(m_unreadStack);
activateUnreadEventbox(true);
-
-
+
+
if(!Utils.onlyShowFeeds() && m_feed.getFeedID() != FeedID.ALL.to_string())
{
this.get_style_context().add_class("fr-sidebar-feed");
@@ -80,11 +80,11 @@ public class FeedReader.FeedRow : Gtk.ListBoxRow {
{
this.get_style_context().add_class("fr-sidebar-row");
}
-
+
m_box.pack_start(m_icon, false, false, 8);
m_box.pack_start(m_label, true, true, 0);
m_box.pack_end (m_unreadBox, false, false, 8);
-
+
m_eventBox = new Gtk.EventBox();
if(m_feed.getFeedID() != FeedID.ALL.to_string())
{
@@ -92,7 +92,7 @@ public class FeedReader.FeedRow : Gtk.ListBoxRow {
m_eventBox.button_press_event.connect(onClick);
}
m_eventBox.add(m_box);
-
+
m_revealer = new Gtk.Revealer();
m_revealer.set_transition_type(Gtk.RevealerTransitionType.SLIDE_DOWN);
m_revealer.add(m_eventBox);
@@ -100,9 +100,9 @@ public class FeedReader.FeedRow : Gtk.ListBoxRow {
this.add(m_revealer);
this.no_show_all = true;;
m_revealer.show_all();
-
+
set_unread_count(m_feed.getUnread());
-
+
if(m_feed.getFeedID() != FeedID.ALL.to_string()
&& !Settings.general().get_boolean("only-feeds")
&& Utils.canManipulateContent()
@@ -111,20 +111,20 @@ public class FeedReader.FeedRow : Gtk.ListBoxRow {
const Gtk.TargetEntry[] provided_targets = {
{ "text/plain", 0, DragTarget.FEED }
};
-
+
Gtk.drag_source_set (
this,
Gdk.ModifierType.BUTTON1_MASK,
provided_targets,
Gdk.DragAction.MOVE
);
-
+
this.drag_begin.connect(onDragBegin);
this.drag_data_get.connect(onDragDataGet);
}
}
}
-
+
~FeedRow()
{
activateUnreadEventbox(false);
@@ -135,29 +135,29 @@ public class FeedReader.FeedRow : Gtk.ListBoxRow {
this.drag_begin.disconnect(onDragBegin);
this.drag_data_get.disconnect(onDragDataGet);
}
-
+
private void onDragBegin(Gtk.Widget widget, Gdk.DragContext context)
{
Logger.debug("FeedRow: onDragBegin");
Gtk.drag_set_icon_widget(context, getFeedIconWindow(), 0, 0);
-
+
}
-
+
public void onDragDataGet(Gtk.Widget widget, Gdk.DragContext context, Gtk.SelectionData selection_data, uint target_type, uint time)
{
Logger.debug("FeedRow: onDragDataGet");
-
+
if(target_type == DragTarget.FEED)
{
selection_data.set_text(m_feed.getFeedID() + "," + m_parentCatID, -1);
}
}
-
+
public Gtk.Image createFavIcon()
{
var icon = new Gtk.Image.from_icon_name("feed-rss-symbolic", Gtk.IconSize.LARGE_TOOLBAR);
icon.get_style_context().add_class("fr-sidebar-symbolic");
-
+
var favicon = FavIcon.for_feed(m_feed);
favicon.get_surface.begin((obj, res) => {
var surface = favicon.get_surface.end(res);
@@ -174,10 +174,10 @@ public class FeedReader.FeedRow : Gtk.ListBoxRow {
icon.destroy.connect(() => {
favicon.disconnect(handler_id);
});
-
+
return icon;
}
-
+
private Gtk.Window getFeedIconWindow()
{
var icon = createFavIcon();
@@ -189,7 +189,7 @@ public class FeedReader.FeedRow : Gtk.ListBoxRow {
window.show_all();
return window;
}
-
+
private bool onClick(Gdk.EventButton event)
{
// only right click allowed
@@ -197,12 +197,12 @@ public class FeedReader.FeedRow : Gtk.ListBoxRow {
{
return false;
}
-
+
if(!Utils.canManipulateContent())
{
return false;
}
-
+
switch(event.type)
{
case Gdk.EventType.BUTTON_RELEASE:
@@ -210,20 +210,20 @@ public class FeedReader.FeedRow : Gtk.ListBoxRow {
case Gdk.EventType.@3BUTTON_PRESS:
return false;
}
-
+
var remove_action = new GLib.SimpleAction("deleteFeed", null);
remove_action.activate.connect(RemoveThisFeed);
-
+
var markAsRead_action = new GLib.SimpleAction("markFeedAsRead", null);
markAsRead_action.activate.connect(() => {
setAsRead(FeedListType.FEED, m_feed.getFeedID());
});
-
+
var copyFeedURL_action = new GLib.SimpleAction("copyFeedURL", null);
copyFeedURL_action.activate.connect(() => {
copyFeedURL(m_feed.getFeedID());
});
-
+
if(m_feed.getUnread() != 0)
{
markAsRead_action.set_enabled(true);
@@ -232,17 +232,17 @@ public class FeedReader.FeedRow : Gtk.ListBoxRow {
{
markAsRead_action.set_enabled(false);
}
-
+
var rename_action = new GLib.SimpleAction("renameFeed", null);
rename_action.activate.connect(showRenamePopover);
-
+
FeedReaderApp.get_default().add_action(markAsRead_action);
FeedReaderApp.get_default().add_action(copyFeedURL_action);
FeedReaderApp.get_default().add_action(rename_action);
FeedReaderApp.get_default().add_action(remove_action);
-
-
-
+
+
+
var menu = new GLib.Menu();
menu.append(_("Mark as read"), "markFeedAsRead");
menu.append(_("Copy URL"), "copyFeedURL");
@@ -253,19 +253,19 @@ public class FeedReader.FeedRow : Gtk.ListBoxRow {
menu.append(_("Remove only from %s").printf(cat.getTitle()), "deleteFeed");
}
menu.append(_("Remove"), "deleteFeed");
-
+
var pop = new Gtk.Popover(this);
pop.set_position(Gtk.PositionType.BOTTOM);
pop.bind_model(menu, "app");
pop.closed.connect(() => {
this.unset_state_flags(Gtk.StateFlags.PRELIGHT);
});
-
+
pop.show();
this.set_state_flags(Gtk.StateFlags.PRELIGHT, false);
return true;
}
-
+
private void showRenamePopover()
{
var popRename = new Gtk.Popover(this);
@@ -273,34 +273,34 @@ public class FeedReader.FeedRow : Gtk.ListBoxRow {
popRename.closed.connect(() => {
this.unset_state_flags(Gtk.StateFlags.PRELIGHT);
});
-
+
var renameEntry = new Gtk.Entry();
renameEntry.set_text(m_feed.getTitle());
renameEntry.activate.connect(() => {
popRename.hide();
FeedReaderBackend.get_default().renameFeed(m_feed.getFeedID(), renameEntry.get_text());
});
-
+
var renameButton = new Gtk.Button.with_label(_("rename"));
renameButton.get_style_context().add_class("suggested-action");
renameButton.clicked.connect(() => {
renameEntry.activate();
});
-
+
var renameBox = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 5);
renameBox.margin = 5;
renameBox.pack_start(renameEntry, true, true, 0);
renameBox.pack_start(renameButton, false, false, 0);
-
+
popRename.add(renameBox);
popRename.show_all();
this.set_state_flags(Gtk.StateFlags.PRELIGHT, false);
}
-
+
public void set_unread_count(uint unread_count)
{
m_feed.setUnread(unread_count);
-
+
if(m_feed.getUnread() > 0 && !m_unreadHovered)
{
m_unreadStack.set_visible_child_name("unreadCount");
@@ -315,7 +315,7 @@ public class FeedReader.FeedRow : Gtk.ListBoxRow {
m_unreadStack.set_visible_child_name("mark");
}
}
-
+
private bool onUnreadClick(Gdk.EventButton event)
{
if(m_unreadHovered && m_feed.getUnread() > 0)
@@ -324,7 +324,7 @@ public class FeedReader.FeedRow : Gtk.ListBoxRow {
}
return true;
}
-
+
private bool onUnreadEnter(Gdk.EventCrossing event)
{
m_unreadHovered = true;
@@ -334,7 +334,7 @@ public class FeedReader.FeedRow : Gtk.ListBoxRow {
}
return true;
}
-
+
private bool onUnreadLeave(Gdk.EventCrossing event)
{
m_unreadHovered = false;
@@ -348,12 +348,12 @@ public class FeedReader.FeedRow : Gtk.ListBoxRow {
}
return true;
}
-
+
public void upUnread()
{
set_unread_count(m_feed.getUnread() + 1);
}
-
+
public void downUnread()
{
if(m_feed.getUnread() > 0)
@@ -361,48 +361,48 @@ public class FeedReader.FeedRow : Gtk.ListBoxRow {
set_unread_count(m_feed.getUnread() - 1);
}
}
-
+
public void update(string text, uint unread_count)
{
m_label.set_text(text.replace("&","&amp;"));
set_unread_count(unread_count);
}
-
+
public void setSubscribed(bool subscribed)
{
m_subscribed = subscribed;
}
-
+
public string getCatID()
{
return m_parentCatID;
}
-
+
public string getID()
{
return m_feed.getFeedID();
}
-
+
public string getName()
{
return m_feed.getTitle();
}
-
+
public bool isSubscribed()
{
return m_subscribed;
}
-
+
public uint getUnreadCount()
{
return m_feed.getUnread();
}
-
+
public bool isRevealed()
{
return m_revealer.get_reveal_child();
}
-
+
public void reveal(bool reveal, uint duration = 500)
{
if(m_timeout_source_id > 0)
@@ -410,12 +410,12 @@ public class FeedReader.FeedRow : Gtk.ListBoxRow {
GLib.Source.remove(m_timeout_source_id);
m_timeout_source_id = 0;
}
-
+
if(reveal)
{
this.show();
}
-
+
m_revealer.set_transition_duration(duration);
m_revealer.set_reveal_child(reveal);
if(!reveal)
@@ -424,7 +424,7 @@ public class FeedReader.FeedRow : Gtk.ListBoxRow {
{
deselectRow();
}
-
+
m_timeout_source_id = GLib.Timeout.add(duration, () => {
this.hide();
m_timeout_source_id = 0;
@@ -432,14 +432,14 @@ public class FeedReader.FeedRow : Gtk.ListBoxRow {
});
}
}
-
+
public void activateUnreadEventbox(bool activate)
{
if(m_unreadBox == null)
{
return;
}
-
+
if(activate)
{
m_unreadBox.button_press_event.connect(onUnreadClick);
@@ -453,17 +453,17 @@ public class FeedReader.FeedRow : Gtk.ListBoxRow {
m_unreadBox.leave_notify_event.disconnect(onUnreadLeave);
}
}
-
+
private void RemoveThisFeed(Variant? parameter)
{
if(this.is_selected())
{
moveUP();
}
-
+
uint time = 300;
this.reveal(false, time);
-
+
var notification = MainWindow.get_default().showNotification(_("Feed removed: %s").printf(m_feed.getTitle()));
ulong eventID = notification.dismissed.connect(() => {
FeedReaderBackend.get_default().removeFeed(m_feed.getFeedID());
diff --git a/src/Widgets/FullscreenButton.vala b/src/Widgets/FullscreenButton.vala
index fb9f7447..c5eb60ea 100644
--- a/src/Widgets/FullscreenButton.vala
+++ b/src/Widgets/FullscreenButton.vala
@@ -14,10 +14,10 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.fullscreenButton : Gtk.Revealer {
-
+
private Gtk.Button m_button;
public signal void click();
-
+
public fullscreenButton(string iconName, Gtk.Align align)
{
this.valign = Gtk.Align.CENTER;
@@ -27,7 +27,7 @@ public class FeedReader.fullscreenButton : Gtk.Revealer {
this.no_show_all = true;
this.set_transition_type(Gtk.RevealerTransitionType.CROSSFADE);
this.set_transition_duration(300);
-
+
m_button = new Gtk.Button.from_icon_name(iconName, Gtk.IconSize.DIALOG);
m_button.clicked.connect(() => {
click();
@@ -35,7 +35,7 @@ public class FeedReader.fullscreenButton : Gtk.Revealer {
m_button.margin = 20;
this.add(m_button);
}
-
+
public void reveal(bool show)
{
if(show)
@@ -43,8 +43,8 @@ public class FeedReader.fullscreenButton : Gtk.Revealer {
this.visible = true;
m_button.show();
}
-
+
this.set_reveal_child(show);
}
-
+
}
diff --git a/src/Widgets/FullscreenHeader.vala b/src/Widgets/FullscreenHeader.vala
index abd52ee4..2215e9ae 100644
--- a/src/Widgets/FullscreenHeader.vala
+++ b/src/Widgets/FullscreenHeader.vala
@@ -14,13 +14,13 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.FullscreenHeader : Gtk.EventBox {
-
+
private Gtk.Revealer m_revealer;
private ArticleViewHeader m_header;
private bool m_hover = false;
private bool m_popover = false;
private uint m_timeout_source_id = 0;
-
+
public FullscreenHeader()
{
m_header = new ArticleViewHeader("view-restore-symbolic", _("Leave fullscreen mode"));
@@ -54,7 +54,7 @@ public class FeedReader.FullscreenHeader : Gtk.EventBox {
m_revealer.set_transition_duration(300);
m_revealer.valign = Gtk.Align.START;
m_revealer.add(m_header);
-
+
this.set_size_request(0, 80);
this.no_show_all = true;
this.enter_notify_event.connect((event) => {
@@ -70,20 +70,20 @@ public class FeedReader.FullscreenHeader : Gtk.EventBox {
{
return false;
}
-
+
if(event.detail == Gdk.NotifyType.NONLINEAR_VIRTUAL)
{
return false;
}
-
+
m_hover = false;
-
+
if(m_popover)
{
return false;
}
-
-
+
+
removeTimeout();
m_timeout_source_id = GLib.Timeout.add(500, () => {
m_revealer.set_transition_duration(800);
@@ -91,28 +91,28 @@ public class FeedReader.FullscreenHeader : Gtk.EventBox {
m_timeout_source_id = 0;
return false;
});
-
+
return true;
});
this.add(m_revealer);
this.valign = Gtk.Align.START;
}
-
+
public void setTitle(string title)
{
m_header.set_title(title);
}
-
+
public void setMarked(ArticleStatus marked)
{
m_header.setMarked(marked);
}
-
+
public void setRead(ArticleStatus read)
{
m_header.setRead(read);
}
-
+
private void removeTimeout()
{
if(m_timeout_source_id > 0)
@@ -121,7 +121,7 @@ public class FeedReader.FullscreenHeader : Gtk.EventBox {
m_timeout_source_id = 0;
}
}
-
+
public void showMediaButton(bool show)
{
m_header.showMediaButton(show);
diff --git a/src/Widgets/HoverButton.vala b/src/Widgets/HoverButton.vala
index 97352a55..f2ad10e4 100644
--- a/src/Widgets/HoverButton.vala
+++ b/src/Widgets/HoverButton.vala
@@ -14,14 +14,14 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.HoverButton : Gtk.EventBox {
-
+
private Gtk.Button m_button;
private Gtk.Stack m_stack;
private Gtk.Image m_inactive;
private Gtk.Image m_active;
private bool m_isActive;
public signal void clicked(bool active);
-
+
public HoverButton(Gtk.Image inactive, Gtk.Image active, bool isActive)
{
m_inactive = inactive;
@@ -35,11 +35,11 @@ public class FeedReader.HoverButton : Gtk.EventBox {
toggle();
clicked(m_isActive);
});
-
+
m_stack.add_named(inactive, "inactive");
m_stack.add_named(active, "active");
m_button.add(m_stack);
-
+
if(isActive)
{
m_stack.set_visible_child_name("active");
@@ -48,39 +48,39 @@ public class FeedReader.HoverButton : Gtk.EventBox {
{
m_stack.set_visible_child_name("inactive");
}
-
-
-
+
+
+
this.set_events(Gdk.EventMask.ENTER_NOTIFY_MASK);
this.set_events(Gdk.EventMask.LEAVE_NOTIFY_MASK);
this.set_size_request(16, 16);
this.add(m_button);
-
+
this.enter_notify_event.connect(onEnter);
this.leave_notify_event.connect(onLeave);
}
-
+
private void setActiveIcon()
{
m_stack.set_visible_child_name("active");
m_active.show();
}
-
+
private void setInactiveIcon()
{
m_stack.set_visible_child_name("inactive");
m_inactive.show();
}
-
+
public void toggle()
{
setActive(!m_isActive);
}
-
+
public void setActive(bool active)
{
m_isActive = active;
-
+
if(m_isActive)
{
setActiveIcon();
@@ -90,8 +90,8 @@ public class FeedReader.HoverButton : Gtk.EventBox {
setInactiveIcon();
}
}
-
-
+
+
private bool onEnter(Gdk.EventCrossing event)
{
if(m_isActive)
@@ -104,14 +104,14 @@ public class FeedReader.HoverButton : Gtk.EventBox {
}
return true;
}
-
+
private bool onLeave(Gdk.EventCrossing event)
{
if(event.detail == Gdk.NotifyType.INFERIOR)
{
return false;
}
-
+
if(m_isActive)
{
setActiveIcon();
@@ -120,9 +120,9 @@ public class FeedReader.HoverButton : Gtk.EventBox {
{
setInactiveIcon();
}
-
+
return true;
}
-
-
+
+
}
diff --git a/src/Widgets/ImagePopup.vala b/src/Widgets/ImagePopup.vala
index 64fbe714..bf05cd93 100644
--- a/src/Widgets/ImagePopup.vala
+++ b/src/Widgets/ImagePopup.vala
@@ -14,7 +14,7 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.imagePopup : Gtk.Window {
-
+
private Gtk.ScrolledWindow m_scroll;
private string m_imagePath;
private Gtk.ImageView m_image;
@@ -43,7 +43,7 @@ public class FeedReader.imagePopup : Gtk.Window {
private double m_maxZoom = 5.0;
private double m_minZoom = 0.2;
private double m_initZoom = 1.0;
-
+
public imagePopup(string imagePath, string? url, Gtk.Window parent, double img_height, double img_width)
{
this.title = "";
@@ -61,14 +61,14 @@ public class FeedReader.imagePopup : Gtk.Window {
}
return false;
});
-
+
m_imagePath = imagePath;
-
+
var file = GLib.File.new_for_path(m_imagePath);
m_image = new Gtk.ImageView();
m_image.zoomable = true;
m_image.load_from_file_async.begin(file, 0);
-
+
m_scale = new Gtk.Scale.with_range(Gtk.Orientation.HORIZONTAL, m_minZoom, m_maxZoom, 0.2);
m_scale.draw_value = false;
m_scale.set_size_request(200, 0);
@@ -76,22 +76,22 @@ public class FeedReader.imagePopup : Gtk.Window {
m_scale.value_changed.connect(() => {
m_image.scale = m_scale.get_value();
});
-
+
m_scaleRevealer = new Gtk.Revealer();
m_scaleRevealer.valign = Gtk.Align.FILL;
m_scaleRevealer.set_transition_type(Gtk.RevealerTransitionType.SLIDE_RIGHT);
m_scaleRevealer.add(m_scale);
-
+
var geo = Gdk.Display.get_default().get_monitor_at_window(this.get_root_window()).get_geometry();
double win_width = (int)(geo.width*0.8);
double win_height = (int)(geo.height*0.8);
double min_height = 300;
double min_widht = 500;
-
+
m_scroll = new Gtk.ScrolledWindow(null, null);
m_scroll.add(m_image);
-
-
+
+
if(img_width <= win_width)
{
if(img_width < min_widht)
@@ -108,7 +108,7 @@ public class FeedReader.imagePopup : Gtk.Window {
m_initZoom = win_width/img_width;
m_image.scale = m_initZoom;
}
-
+
if(img_height * m_initZoom <= win_height)
{
if(img_height < min_height)
@@ -120,12 +120,12 @@ public class FeedReader.imagePopup : Gtk.Window {
win_height = img_height * m_initZoom;
}
}
-
+
m_saveButton = new Gtk.Button.from_icon_name("document-save-symbolic", Gtk.IconSize.BUTTON);
m_saveButton.clicked.connect(() => {
Utils.saveImageDialog(m_imagePath);
});
-
+
m_image.notify["scale"].connect(onImageScrolled);
m_zoomButton = new Gtk.ToggleButton();
m_zoomButton.add(new Gtk.Image.from_icon_name("zoom-in-symbolic", Gtk.IconSize.BUTTON));
@@ -144,7 +144,7 @@ public class FeedReader.imagePopup : Gtk.Window {
m_image.scale = m_initZoom;
m_scaleRevealer.set_reveal_child(false);
}
-
+
if(!m_zoomButton.get_active())
{
GLib.Timeout.add(150, () => {
@@ -153,7 +153,7 @@ public class FeedReader.imagePopup : Gtk.Window {
});
}
});
-
+
var header = new Gtk.HeaderBar ();
header.show_close_button = true;
header.set_size_request(0, 30);
@@ -174,12 +174,12 @@ public class FeedReader.imagePopup : Gtk.Window {
{
return false;
}
-
+
m_hoverHeader = false;
return false;
});
headerEvents.add(header);
-
+
if(url != null && url != "")
{
var urlButton = new Gtk.Button.with_label("Open URL");
@@ -195,17 +195,17 @@ public class FeedReader.imagePopup : Gtk.Window {
});
header.pack_start(urlButton);
}
-
+
m_revealer = new Gtk.Revealer();
m_revealer.valign = Gtk.Align.START;
m_revealer.set_transition_type(Gtk.RevealerTransitionType.SLIDE_DOWN);
m_revealer.add(headerEvents);
-
+
m_overlay = new Gtk.Overlay();
m_overlay.add(m_scroll);
m_overlay.add_overlay(m_revealer);
-
-
+
+
m_eventBox = new Gtk.EventBox();
m_eventBox.button_press_event.connect(eventButtonPressed);
m_eventBox.button_release_event.connect(eventButtonReleased);
@@ -213,12 +213,12 @@ public class FeedReader.imagePopup : Gtk.Window {
m_eventBox.leave_notify_event.connect(onLeave);
m_eventBox.key_press_event.connect(keyPressed);
m_eventBox.add(m_overlay);
-
+
this.add(m_eventBox);
this.set_size_request((int)win_width, (int)win_height);
this.show_all();
}
-
+
public void onImageScrolled()
{
if(m_image.scale > m_maxZoom)
@@ -226,18 +226,18 @@ public class FeedReader.imagePopup : Gtk.Window {
m_image.scale = m_maxZoom;
return;
}
-
+
if(m_image.scale < m_minZoom)
{
m_image.scale = m_minZoom;
return;
}
-
+
m_zoomButton.set_active(true);
m_scaleRevealer.set_reveal_child(true);
m_scale.set_value(m_image.scale);
}
-
+
private bool headerButtonPressed(Gdk.EventButton evt)
{
if(evt.button == MouseButton.LEFT)
@@ -248,7 +248,7 @@ public class FeedReader.imagePopup : Gtk.Window {
}
return false;
}
-
+
private bool motionNotify(Gdk.EventMotion evt)
{
if((evt.state & Gdk.ModifierType.MODIFIER_MASK) >= Gdk.ModifierType.BUTTON2_MASK)
@@ -263,7 +263,7 @@ public class FeedReader.imagePopup : Gtk.Window {
}
return false;
}
-
+
private bool eventButtonPressed(Gdk.EventButton evt)
{
if(!m_hoverHeader)
@@ -287,7 +287,7 @@ public class FeedReader.imagePopup : Gtk.Window {
var seat = display.get_default_seat();
var pointer = seat.get_pointer();
var cursor = new Gdk.Cursor.for_display(display, Gdk.CursorType.FLEUR);
-
+
seat.grab(
this.get_window(),
Gdk.SeatCapabilities.POINTER,
@@ -296,9 +296,9 @@ public class FeedReader.imagePopup : Gtk.Window {
null,
null
);
-
+
Gtk.device_grab_add(m_eventBox, pointer, false);
-
+
m_dndX = evt.x;
m_dndY = evt.y;
m_adjX = m_scroll.hadjustment.value;
@@ -314,7 +314,7 @@ public class FeedReader.imagePopup : Gtk.Window {
}
return false;
}
-
+
private bool eventButtonReleased(Gdk.EventButton evt)
{
if(evt.button == MouseButton.MIDDLE)
@@ -333,8 +333,8 @@ public class FeedReader.imagePopup : Gtk.Window {
}
return false;
}
-
-
+
+
private bool keyPressed(Gdk.EventKey evt)
{
if(evt.keyval == Gdk.Key.Escape)
@@ -343,7 +343,7 @@ public class FeedReader.imagePopup : Gtk.Window {
}
return false;
}
-
+
private bool onEnter(Gdk.EventCrossing event)
{
m_hoverImage = true;
@@ -351,55 +351,55 @@ public class FeedReader.imagePopup : Gtk.Window {
m_revealer.show();
return true;
}
-
+
private bool onLeave(Gdk.EventCrossing event)
{
if(event.detail != Gdk.NotifyType.VIRTUAL && event.mode != Gdk.CrossingMode.NORMAL)
{
return false;
}
-
+
if(m_dragWindow)
{
return false;
}
-
+
m_hoverImage = false;
m_revealer.set_reveal_child(false);
return true;
}
-
+
private bool updateDragMomentum()
{
if(!m_inDrag)
{
return false;
}
-
+
for(int i = 9; i > 0; --i)
{
m_dragBufferX[i] = m_dragBufferX[i-1];
m_dragBufferY[i] = m_dragBufferY[i-1];
}
-
+
m_dragBufferX[0] = m_posX;
m_dragBufferY[0] = m_posY;
m_momentumX = (m_dragBufferX[9] - m_dragBufferX[0])/2;
m_momentumY = (m_dragBufferY[9] - m_dragBufferY[0])/2;
-
+
return true;
}
-
+
private bool ScrollDragRelease()
{
if(m_inDrag)
{
return true;
}
-
+
Gtk.Allocation allocation;
this.get_allocation(out allocation);
-
+
if(m_momentumX != 0)
{
m_momentumX /= 1.2;
@@ -415,7 +415,7 @@ public class FeedReader.imagePopup : Gtk.Window {
double newXScrollPos = double.min(oldhAdj + adjhValue, upperH - pageWidth);
m_scroll.hadjustment.value = (int)newXScrollPos;
}
-
+
if(m_momentumY != 0)
{
m_momentumY /= 1.2;
@@ -431,7 +431,7 @@ public class FeedReader.imagePopup : Gtk.Window {
double newYScrollPos = double.min(oldvAdj + adjvValue, upperV - pageHeight);
m_scroll.vadjustment.value = (int)newYScrollPos;
}
-
+
if((m_momentumX < 1 && m_momentumX > -1) && (m_momentumY < 1 && m_momentumY > -1))
{
m_OngoingScrollID = 0;
@@ -442,7 +442,7 @@ public class FeedReader.imagePopup : Gtk.Window {
return true;
}
}
-
+
private void closeWindow()
{
if(m_OngoingScrollID != 0)
diff --git a/src/Widgets/InAppNotification.vala b/src/Widgets/InAppNotification.vala
index cb665199..b72fe73c 100644
--- a/src/Widgets/InAppNotification.vala
+++ b/src/Widgets/InAppNotification.vala
@@ -14,31 +14,31 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.InAppNotification : Gd.Notification {
-
+
private Gtk.Box m_box;
private Gtk.Button m_Button;
public signal void action();
-
+
public InAppNotification(string message, string buttonText, string? tooltip = null, int timeout = 5)
{
m_Button = new Gtk.Button.with_label(buttonText);
setup(message, tooltip);
}
-
+
public InAppNotification.withIcon(string message, string icon, string? tooltip = null, int timeout = 5)
{
m_Button = new Gtk.Button.from_icon_name(icon, Gtk.IconSize.BUTTON);
setup(message, tooltip);
}
-
+
public InAppNotification.withIcon_from_resource(string message, string icon, string? tooltip = null, int timeout = 5)
{
m_Button = new Gtk.Button();
m_Button.set_image(new Gtk.Image.from_resource(icon));
setup(message, tooltip);
}
-
-
+
+
private void setup(string message, string? tooltip)
{
m_Button.set_tooltip_text(tooltip);
@@ -48,15 +48,15 @@ public class FeedReader.InAppNotification : Gd.Notification {
this.set_timeout(5);
this.set_show_close_button(false);
this.add(m_box);
-
+
this.unrealize.connect(() => {
Logger.debug("InAppNotification: destroy");
dismissed();
});
-
+
m_Button.clicked.connect(() => {
action();
});
}
-
+
}
diff --git a/src/Widgets/InfoBar.vala b/src/Widgets/InfoBar.vala
index c8e6b03c..3ec55414 100644
--- a/src/Widgets/InfoBar.vala
+++ b/src/Widgets/InfoBar.vala
@@ -14,16 +14,16 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.InfoBar : Gtk.Revealer {
-
+
// THIS IS BASICALLY A WORKAROUND FOR THIS GTK+ BUG:
// https://bugzilla.gnome.org/show_bug.cgi?id=710888
-
+
private Gtk.Label m_Label;
-
+
public InfoBar(string text)
{
m_Label = new Gtk.Label(text);
-
+
var bar = new Gtk.InfoBar();
bar.valign = Gtk.Align.START;
bar.get_content_area().add(m_Label);
@@ -35,22 +35,22 @@ public class FeedReader.InfoBar : Gtk.Revealer {
this.set_reveal_child(false);
}
});
-
+
this.set_transition_duration(200);
this.set_transition_type(Gtk.RevealerTransitionType.SLIDE_DOWN);
this.valign = Gtk.Align.START;
this.add(bar);
}
-
+
public void reveal()
{
this.show_all();
this.set_reveal_child(true);
}
-
+
public void setText(string text)
{
m_Label.set_text(text);
}
-
+
}
diff --git a/src/Widgets/LoginPage.vala b/src/Widgets/LoginPage.vala
index d9853f51..67800fe9 100644
--- a/src/Widgets/LoginPage.vala
+++ b/src/Widgets/LoginPage.vala
@@ -14,56 +14,56 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.LoginPage : Gtk.Stack {
-
+
private Gtk.Box m_layout;
private Gtk.ListBox m_accountList;
private WebLoginPage m_page;
private Gtk.Box? m_activeWidget = null;
public signal void submit_data();
public signal void loginError(LoginResponse errorCode);
-
-
+
+
public LoginPage()
{
FeedReaderBackend.get_default().tryLogin.connect(() => {
writeLoginData();
});
-
+
m_layout = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
m_layout.set_size_request(700, 410);
m_layout.set_halign(Gtk.Align.CENTER);
m_layout.margin = 20;
m_layout.margin_bottom = 50;
m_layout.margin_top = 50;
-
+
var welcomeText = new Gtk.Label(_("Where are your feeds?"));
welcomeText.get_style_context().add_class("h1");
welcomeText.set_justify(Gtk.Justification.CENTER);
-
+
var welcomeText2 = new Gtk.Label(_("Please select the RSS service you are using and log in to get going."));
welcomeText2.get_style_context().add_class("h2");
welcomeText2.set_justify(Gtk.Justification.CENTER);
welcomeText2.set_lines(3);
-
-
+
+
m_accountList = new Gtk.ListBox();
m_accountList.set_selection_mode(Gtk.SelectionMode.NONE);
m_accountList.row_activated.connect(serviceSelected);
-
+
RefreshPlugins();
FeedServer.get_default().PluginsChanedEvent.connect(RefreshPlugins);
-
+
var scroll = new Gtk.ScrolledWindow(null, null);
scroll.set_size_request(450, 0);
scroll.set_halign(Gtk.Align.CENTER);
scroll.get_style_context().add_class(Gtk.STYLE_CLASS_FRAME);
scroll.add(m_accountList);
-
-
+
+
m_layout.pack_start(welcomeText, false, true, 0);
m_layout.pack_start(welcomeText2, false, true, 2);
m_layout.pack_start(scroll, true, true, 20);
-
+
m_page = new WebLoginPage();
this.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT);
this.add_named(m_page, "web");
@@ -71,7 +71,7 @@ public class FeedReader.LoginPage : Gtk.Stack {
this.show_all();
reset();
}
-
+
private void RefreshPlugins()
{
var children = m_accountList.get_children();
@@ -80,7 +80,7 @@ public class FeedReader.LoginPage : Gtk.Stack {
m_accountList.remove(row);
row.destroy();
}
-
+
FeedServer.get_default().getPlugins().foreach((extSet, info, ext) => {
var plug = ext as FeedServerInterface;
if(plug != null)
@@ -97,15 +97,15 @@ public class FeedReader.LoginPage : Gtk.Stack {
m_accountList.add(new LoginRow(pluginfo));
}
});
-
+
m_accountList.show_all();
}
-
+
public void reset()
{
var visible = this.get_visible_child_name();
this.set_visible_child_name("selectScreen");
-
+
if(visible == "loginWidget"
&& m_activeWidget != null)
{
@@ -117,17 +117,17 @@ public class FeedReader.LoginPage : Gtk.Stack {
m_page.reset();
}
}
-
+
private void serviceSelected(Gtk.ListBoxRow row)
{
var serviceRow = (row as LoginRow);
Logger.debug("serviceSelected: %s".printf(serviceRow.getInfo().name));
-
+
var window = MainWindow.get_default();
window.getSimpleHeader().showBackButton(true);
FeedServer.get_default().setActivePlugin(serviceRow.getInfo().ID);
FeedServerInterface? plug = FeedServer.get_default().getActivePlugin();
-
+
if(plug != null)
{
if(plug.needWebLogin())
@@ -139,7 +139,7 @@ public class FeedReader.LoginPage : Gtk.Stack {
login(plug.getID());
});
this.set_visible_child_name("web");
-
+
window.getSimpleHeader().back.connect(() => {
this.set_visible_child_full("selectScreen", Gtk.StackTransitionType.SLIDE_RIGHT);
window.getSimpleHeader().showBackButton(false);
@@ -150,10 +150,10 @@ public class FeedReader.LoginPage : Gtk.Stack {
{
m_activeWidget = plug.getWidget();
m_activeWidget.show_all();
-
+
this.add_named(m_activeWidget, "loginWidget");
this.set_visible_child_name("loginWidget");
-
+
window.getSimpleHeader().back.connect(() => {
this.set_visible_child_full("selectScreen", Gtk.StackTransitionType.SLIDE_RIGHT);
window.getSimpleHeader().showBackButton(false);
@@ -166,13 +166,13 @@ public class FeedReader.LoginPage : Gtk.Stack {
}
}
}
-
-
+
+
public void showHtAccess()
{
FeedServer.get_default().getActivePlugin().showHtAccess();
}
-
+
public void writeLoginData()
{
Logger.debug("write login data");
@@ -183,7 +183,7 @@ public class FeedReader.LoginPage : Gtk.Stack {
login(ext.getID());
}
}
-
+
private void login(string id)
{
LoginResponse status = FeedReaderBackend.get_default().login(id);
@@ -201,7 +201,7 @@ public class FeedReader.LoginPage : Gtk.Stack {
}
return;
}
-
+
loginError(status);
}
}
diff --git a/src/Widgets/LoginRow.vala b/src/Widgets/LoginRow.vala
index 3460f5d3..f7248161 100644
--- a/src/Widgets/LoginRow.vala
+++ b/src/Widgets/LoginRow.vala
@@ -14,21 +14,21 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.LoginRow : Gtk.ListBoxRow {
-
+
private BackendInfo m_info;
private Gtk.Stack m_infoStack;
private bool m_hovered = false;
-
+
public LoginRow(BackendInfo info)
{
m_info = info;
-
+
var icon = new Gtk.Image.from_icon_name(info.iconName, Gtk.IconSize.MENU);
icon.margin_start = 10;
var label = new Gtk.Label(info.name);
label.set_alignment(0.0f, 0.5f);
label.get_style_context().add_class("h3");
-
+
var infoIcon = new Gtk.Image.from_icon_name("feed-backend-info", Gtk.IconSize.LARGE_TOOLBAR);
var infoButton = new Gtk.Button();
infoButton.set_image(infoIcon);
@@ -36,7 +36,7 @@ public class FeedReader.LoginRow : Gtk.ListBoxRow {
infoButton.set_focus_on_click(false);
infoButton.valign = Gtk.Align.CENTER;
infoButton.clicked.connect(infoClicked);
-
+
m_infoStack = new Gtk.Stack();
m_infoStack.set_transition_type(Gtk.StackTransitionType.CROSSFADE);
m_infoStack.set_transition_duration(50);
@@ -44,7 +44,7 @@ public class FeedReader.LoginRow : Gtk.ListBoxRow {
m_infoStack.add_named(new Gtk.Label(""), "empty");
m_infoStack.add_named(infoButton, "button");
m_infoStack.set_visible_child_name("empty");
-
+
var box = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 15);
box.margin_top = 2;
box.margin_bottom = 2;
@@ -54,34 +54,34 @@ public class FeedReader.LoginRow : Gtk.ListBoxRow {
var box2 = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
box2.pack_start(box);
box2.pack_start(new Gtk.Separator(Gtk.Orientation.HORIZONTAL));
-
+
var eventbox = new Gtk.EventBox();
eventbox.set_events(Gdk.EventMask.ENTER_NOTIFY_MASK);
eventbox.set_events(Gdk.EventMask.LEAVE_NOTIFY_MASK);
eventbox.enter_notify_event.connect(rowEnter);
eventbox.leave_notify_event.connect(rowLeave);
eventbox.add(box2);
-
+
this.add(eventbox);
}
-
+
public BackendInfo getInfo()
{
return m_info;
}
-
+
private bool rowEnter(Gdk.EventCrossing event)
{
if(event.detail == Gdk.NotifyType.INFERIOR)
{
return true;
}
-
+
m_hovered = true;
m_infoStack.set_visible_child_name("button");
return true;
}
-
+
private bool rowLeave(Gdk.EventCrossing event)
{
if(event.detail == Gdk.NotifyType.INFERIOR
@@ -93,13 +93,13 @@ public class FeedReader.LoginRow : Gtk.ListBoxRow {
}
return true;
}
-
-
+
+
m_hovered = false;
m_infoStack.set_visible_child_name("empty");
return true;
}
-
+
private void infoClicked()
{
var pop = new BackendInfoPopover(m_infoStack, m_info);
diff --git a/src/Widgets/MainWindow.vala b/src/Widgets/MainWindow.vala
index 6c01e8e9..487ddd78 100644
--- a/src/Widgets/MainWindow.vala
+++ b/src/Widgets/MainWindow.vala
@@ -28,42 +28,42 @@ public class FeedReader.MainWindow : Gtk.ApplicationWindow
private SpringCleanPage m_SpringClean;
private Gtk.CssProvider m_cssProvider;
private uint m_stackTransitionTime = 100;
-
+
private static MainWindow? m_window = null;
-
+
public static MainWindow get_default()
{
if(m_window == null)
{
m_window = new MainWindow();
}
-
+
return m_window;
}
-
+
private MainWindow()
{
Object(application: FeedReaderApp.get_default(), title: _("FeedReader"), show_menubar: false);
this.window_position = WindowPosition.CENTER;
-
+
m_stack = new Gtk.Stack();
m_stack.set_transition_type(Gtk.StackTransitionType.CROSSFADE);
m_stack.set_transition_duration(m_stackTransitionTime);
-
+
m_overlay = new Gtk.Overlay();
m_overlay.add(m_stack);
-
+
setupCSS();
setupLoginPage();
setupResetPage();
setupContentPage();
setupSpringCleanPage();
-
+
var shortcutsAction = new SimpleAction("shortcuts", null);
shortcutsAction.activate.connect(showShortcutWindow);
this.add_action(shortcutsAction);
shortcutsAction.set_enabled(true);
-
+
var reportBugAction = new SimpleAction("bugs", null);
reportBugAction.activate.connect(() => {
try{
@@ -75,7 +75,7 @@ public class FeedReader.MainWindow : Gtk.ApplicationWindow
});
this.add_action(reportBugAction);
reportBugAction.set_enabled(true);
-
+
var bountyAction = new SimpleAction("bounty", null);
bountyAction.activate.connect(() => {
try{
@@ -87,21 +87,21 @@ public class FeedReader.MainWindow : Gtk.ApplicationWindow
});
this.add_action(bountyAction);
bountyAction.set_enabled(true);
-
+
var settingsAction = new SimpleAction("settings", null);
settingsAction.activate.connect(() => {
SettingsDialog.get_default().showDialog("ui");
});
this.add_action(settingsAction);
settingsAction.set_enabled(true);
-
+
var login_action = new SimpleAction("reset", null);
login_action.activate.connect(() => {
showReset(Gtk.StackTransitionType.SLIDE_RIGHT);
});
this.add_action(login_action);
login_action.set_enabled(true);
-
+
var about_action = new SimpleAction("about", null);
about_action.activate.connect(() => {
Gtk.AboutDialog dialog = new Gtk.AboutDialog();
@@ -111,7 +111,7 @@ public class FeedReader.MainWindow : Gtk.ApplicationWindow
dialog.authors = AboutInfo.authors;
dialog.documenters = null;
dialog.translator_credits = AboutInfo.translators;
-
+
dialog.program_name = AboutInfo.programmName;
dialog.comments = AboutInfo.comments;
dialog.copyright = AboutInfo.copyright;
@@ -120,27 +120,27 @@ public class FeedReader.MainWindow : Gtk.ApplicationWindow
dialog.license_type = Gtk.License.GPL_3_0;
dialog.wrap_license = true;
dialog.website = AboutInfo.website;
-
+
dialog.response.connect((response_id) => {
if (response_id == Gtk.ResponseType.CANCEL || response_id == Gtk.ResponseType.DELETE_EVENT)
{
dialog.hide_on_delete();
}
});
-
+
dialog.present();
});
this.add_action(about_action);
about_action.set_enabled(true);
-
+
m_simpleHeader = new SimpleHeader();
-
+
if(Settings.state().get_boolean("window-maximized"))
{
Logger.debug("MainWindow: maximize");
this.maximize();
}
-
+
this.window_state_event.connect(onStateEvent);
this.key_press_event.connect(shortcuts);
this.add(m_overlay);
@@ -149,7 +149,7 @@ public class FeedReader.MainWindow : Gtk.ApplicationWindow
this.set_title("FeedReader");
this.set_default_size(Settings.state().get_int("window-width"), Settings.state().get_int("window-height"));
this.show_all();
-
+
Logger.debug("MainWindow: determining state");
if(FeedReaderBackend.get_default().isOnline())
{
@@ -164,13 +164,13 @@ public class FeedReader.MainWindow : Gtk.ApplicationWindow
showLogin();
}
}
-
+
public override bool delete_event(Gdk.EventAny event)
{
this.hide();
return true;
}
-
+
private bool onStateEvent(Gdk.EventWindowState event)
{
if(event.type == Gdk.EventType.WINDOW_STATE)
@@ -182,19 +182,19 @@ public class FeedReader.MainWindow : Gtk.ApplicationWindow
{
return true;
}
-
+
if(ColumnView.get_default().isFullscreenVideo())
{
if((event.new_window_state & Gdk.WindowState.FULLSCREEN) != Gdk.WindowState.FULLSCREEN)
{
ColumnView.get_default().exitFullscreenVideo();
}
-
+
base.window_state_event(event);
return true;
}
-
-
+
+
if((event.new_window_state & Gdk.WindowState.FULLSCREEN) == Gdk.WindowState.FULLSCREEN)
{
Logger.debug("MainWindow: fullscreen event");
@@ -208,17 +208,17 @@ public class FeedReader.MainWindow : Gtk.ApplicationWindow
}
}
}
-
+
base.window_state_event(event);
return false;
}
-
+
public void showOfflineContent()
{
showContent();
ColumnView.get_default().setOffline();
}
-
+
public void showContent(Gtk.StackTransitionType transition = Gtk.StackTransitionType.CROSSFADE, bool noNewFeedList = false)
{
Logger.debug("MainWindow: show content");
@@ -228,14 +228,14 @@ public class FeedReader.MainWindow : Gtk.ApplicationWindow
}
m_stack.set_visible_child_full("content", transition);
ColumnView.get_default().getHeader().setButtonsSensitive(true);
-
+
if(!ColumnView.get_default().isFullscreen())
{
ColumnView.get_default().getHeader().show_all();
this.set_titlebar(ColumnView.get_default().getHeader());
}
}
-
+
private void showLogin(Gtk.StackTransitionType transition = Gtk.StackTransitionType.CROSSFADE)
{
Logger.debug("MainWindow: show login");
@@ -245,19 +245,19 @@ public class FeedReader.MainWindow : Gtk.ApplicationWindow
ColumnView.get_default().getHeader().setButtonsSensitive(false);
this.set_titlebar(m_simpleHeader);
}
-
+
private void showReset(Gtk.StackTransitionType transition = Gtk.StackTransitionType.CROSSFADE)
{
Logger.debug("MainWindow: show reset");
-
+
// kill playing media
ColumnView.get_default().articleViewKillMedia();
-
+
m_stack.set_visible_child_full("reset", transition);
ColumnView.get_default().getHeader().setButtonsSensitive(false);
this.set_titlebar(m_simpleHeader);
}
-
+
public void showSpringClean(Gtk.StackTransitionType transition = Gtk.StackTransitionType.CROSSFADE)
{
Logger.debug("MainWindow: show springClean");
@@ -265,57 +265,57 @@ public class FeedReader.MainWindow : Gtk.ApplicationWindow
ColumnView.get_default().getHeader().setButtonsSensitive(false);
this.set_titlebar(m_simpleHeader);
}
-
+
public InterfaceState getInterfaceState()
{
int windowWidth = 0;
int windowHeight = 0;
this.get_size(out windowWidth, out windowHeight);
-
+
var state = new InterfaceState();
state.setWindowSize(windowHeight, windowWidth);
state.setWindowMaximized(this.is_maximized);
ColumnView.get_default().saveState(ref state);
return state;
}
-
+
public void writeInterfaceState(bool shutdown = false)
{
getInterfaceState().write(shutdown);
}
-
+
public void reloadCSS()
{
Logger.debug("MainWindow: reloadCSS");
removeProvider(m_cssProvider);
setupCSS();
}
-
+
private void setupCSS()
{
Logger.debug("MainWindow: setupCSS");
string path = "/org/gnome/FeedReader/gtk-css/";
-
+
addProvider(path + "basics.css");
-
+
FeedListTheme theme = (FeedListTheme)Settings.general().get_enum("feedlist-theme");
-
+
switch(theme)
{
case FeedListTheme.GTK:
m_cssProvider = addProvider(path + "gtk.css");
break;
-
+
case FeedListTheme.DARK:
m_cssProvider = addProvider(path + "dark.css");
break;
-
+
case FeedListTheme.ELEMENTARY:
m_cssProvider = addProvider(path + "elementary.css");
break;
}
}
-
+
private Gtk.CssProvider? addProvider(string path)
{
Gtk.CssProvider provider = new Gtk.CssProvider();
@@ -325,14 +325,14 @@ public class FeedReader.MainWindow : Gtk.ApplicationWindow
Gtk.StyleContext.add_provider_for_screen(screen, provider, Gtk.STYLE_PROVIDER_PRIORITY_USER);
return provider;
}
-
+
private void removeProvider(Gtk.CssProvider provider)
{
weak Gdk.Display display = Gdk.Display.get_default();
weak Gdk.Screen screen = display.get_default_screen();
Gtk.StyleContext.remove_provider_for_screen(screen, provider);
}
-
+
private void setupLoginPage()
{
m_error_bar = new Gtk.InfoBar();
@@ -342,12 +342,12 @@ public class FeedReader.MainWindow : Gtk.ApplicationWindow
error_content.add(m_ErrorMessage);
m_error_bar.set_message_type(Gtk.MessageType.WARNING);
m_error_bar.set_show_close_button(true);
-
+
m_ignore_tls_errors = m_error_bar.add_button("Ignore", Gtk.ResponseType.APPLY);
m_ignore_tls_errors.get_style_context().add_class(Gtk.STYLE_CLASS_DESTRUCTIVE_ACTION);
m_ignore_tls_errors.set_tooltip_text(_("Ignore all TLS errors from now on"));
m_ignore_tls_errors.set_visible(false);
-
+
m_error_bar.response.connect((response_id) => {
switch(response_id)
{
@@ -362,14 +362,14 @@ public class FeedReader.MainWindow : Gtk.ApplicationWindow
break;
}
});
-
+
m_login = new LoginPage();
-
+
var loginBox = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
-
+
loginBox.pack_start(m_error_bar, false, false, 0);
loginBox.pack_start(m_login, true, true, 0);
-
+
m_login.submit_data.connect(() => {
Settings.state().set_strv("expanded-categories", Utils.getDefaultExpandedCategories());
Settings.state().set_string("feedlist-selected-row", "feed -4");
@@ -382,7 +382,7 @@ public class FeedReader.MainWindow : Gtk.ApplicationWindow
m_stack.add_named(loginBox, "login");
m_error_bar.set_visible(false);
}
-
+
private void setupResetPage()
{
var reset = new ResetPage();
@@ -394,18 +394,18 @@ public class FeedReader.MainWindow : Gtk.ApplicationWindow
showLogin(Gtk.StackTransitionType.SLIDE_LEFT);
});
}
-
+
private void setupSpringCleanPage()
{
m_SpringClean = new SpringCleanPage();
m_stack.add_named(m_SpringClean, "springClean");
}
-
+
private void setupContentPage()
{
m_stack.add_named(ColumnView.get_default(), "content");
}
-
+
private void showErrorBar(int ErrorCode)
{
Logger.debug("MainWindow: show error bar - errorCode = " + ErrorCode.to_string());
@@ -461,12 +461,12 @@ public class FeedReader.MainWindow : Gtk.ApplicationWindow
m_error_bar.set_visible(false);
return;
}
-
+
Logger.debug("MainWindow: show error bar");
m_error_bar.set_visible(true);
m_ErrorMessage.show();
}
-
+
private void loadContent()
{
Logger.debug("MainWindow: load content");
@@ -474,12 +474,12 @@ public class FeedReader.MainWindow : Gtk.ApplicationWindow
showContent(Gtk.StackTransitionType.NONE);
m_stack.set_transition_duration(m_stackTransitionTime);
}
-
+
private void markSelectedRead()
{
ColumnView.get_default().markAllArticlesAsRead();
string[] selectedRow = ColumnView.get_default().getSelectedFeedListRow().split(" ", 2);
-
+
if(selectedRow[0] == "feed")
{
if(selectedRow[1] == FeedID.ALL.to_string())
@@ -491,7 +491,7 @@ public class FeedReader.MainWindow : Gtk.ApplicationWindow
FeedReaderBackend.get_default().markFeedAsRead(cat.getCatID(), true);
Logger.debug("MainWindow: mark all articles as read cat: %s".printf(cat.getTitle()));
}
-
+
var feeds = db.read_feeds_without_cat();
foreach(Feed feed in feeds)
{
@@ -509,15 +509,15 @@ public class FeedReader.MainWindow : Gtk.ApplicationWindow
FeedReaderBackend.get_default().markFeedAsRead(selectedRow[1], true);
}
}
-
-
+
+
private bool checkShortcut(Gdk.EventKey event, string gsettingKey)
{
uint? key;
Gdk.ModifierType? mod;
string setting = Settings.keybindings().get_string(gsettingKey);
Gtk.accelerator_parse(setting, out key, out mod);
-
+
if(key != null && Gdk.keyval_to_lower(event.keyval) == key)
{
if(mod == null || mod == 0)
@@ -533,50 +533,50 @@ public class FeedReader.MainWindow : Gtk.ApplicationWindow
return true;
}
}
-
+
return false;
}
-
+
private bool shortcuts(Gdk.EventKey event)
{
if(m_stack.get_visible_child_name() != "content")
{
return false;
}
-
+
if(ColumnView.get_default().searchFocused())
{
return false;
}
-
+
if(checkShortcut(event, "articlelist-prev"))
{
Logger.debug("shortcut: articlelist prev");
ColumnView.get_default().ArticleListPREV();
return true;
}
-
+
if(checkShortcut(event, "articlelist-next"))
{
Logger.debug("shortcut: articlelist next");
ColumnView.get_default().ArticleListNEXT();
return true;
}
-
+
if(checkShortcut(event, "feedlist-prev"))
{
Logger.debug("shortcut: feedlist prev");
ColumnView.get_default().FeedListPREV();
return true;
}
-
+
if(checkShortcut(event, "feedlist-next"))
{
Logger.debug("shortcut: feedlist next");
ColumnView.get_default().FeedListNEXT();
return true;
}
-
+
if(event.keyval == Gdk.Key.Left || event.keyval == Gdk.Key.Right)
{
if(ColumnView.get_default().isFullscreen())
@@ -589,7 +589,7 @@ public class FeedReader.MainWindow : Gtk.ApplicationWindow
{
ColumnView.get_default().ArticleListNEXT();
}
-
+
return true;
}
else
@@ -597,49 +597,49 @@ public class FeedReader.MainWindow : Gtk.ApplicationWindow
return false;
}
}
-
+
if(checkShortcut(event, "articleview-up"))
{
event.keyval = Gdk.Key.Up;
ColumnView.get_default().ArticleViewSendEvent(event);
return true;
}
-
+
if(checkShortcut(event, "articleview-down"))
{
event.keyval = Gdk.Key.Down;
ColumnView.get_default().ArticleViewSendEvent(event);
return true;
}
-
+
if(checkShortcut(event, "articlelist-toggle-read"))
{
Logger.debug("shortcut: toggle read");
ColumnView.get_default().toggleReadSelectedArticle();
return true;
}
-
+
if(checkShortcut(event, "articlelist-toggle-marked"))
{
Logger.debug("shortcut: toggle marked");
ColumnView.get_default().toggleMarkedSelectedArticle();
return true;
}
-
+
if(checkShortcut(event, "articlelist-open-url"))
{
Logger.debug("shortcut: open in browser");
ColumnView.get_default().openSelectedArticle();
return true;
}
-
+
if(checkShortcut(event, "feedlist-mark-read"))
{
Logger.debug("shortcut: mark all as read");
markSelectedRead();
return true;
}
-
+
if(checkShortcut(event, "global-sync"))
{
Logger.debug("shortcut: sync");
@@ -647,28 +647,28 @@ public class FeedReader.MainWindow : Gtk.ApplicationWindow
app.sync();
return true;
}
-
+
if(checkShortcut(event, "articlelist-center-selected"))
{
Logger.debug("shortcut: scroll to selcted row");
ColumnView.get_default().centerSelectedRow();
return true;
}
-
+
if(checkShortcut(event, "global-search"))
{
Logger.debug("shortcut: focus search");
ColumnView.get_default().getHeader().focusSearch();
return true;
}
-
+
if(checkShortcut(event, "global-quit"))
{
Logger.debug("shortcut: quit");
FeedReaderApp.get_default().activate_action("quit", null);
return true;
}
-
+
if(event.keyval == Gdk.Key.Escape && ColumnView.get_default().isFullscreen())
{
this.unfullscreen();
@@ -676,27 +676,27 @@ public class FeedReader.MainWindow : Gtk.ApplicationWindow
ColumnView.get_default().leaveFullscreenArticle();
return true;
}
-
+
if(checkShortcut(event, "global-help"))
{
Logger.debug("shortcut: showShortcutWindow");
showShortcutWindow();
return true;
}
-
+
return false;
}
-
+
private void showShortcutWindow()
{
new ShortcutsWindow(this);
}
-
+
public SimpleHeader getSimpleHeader()
{
return m_simpleHeader;
}
-
+
public InAppNotification showNotification(string message, string buttonText = "undo")
{
var notification = new InAppNotification(message, buttonText);
@@ -704,5 +704,5 @@ public class FeedReader.MainWindow : Gtk.ApplicationWindow
this.show_all();
return notification;
}
-
+
}
diff --git a/src/Widgets/MediaButton.vala b/src/Widgets/MediaButton.vala
index aeb3fd2d..2508a5a2 100644
--- a/src/Widgets/MediaButton.vala
+++ b/src/Widgets/MediaButton.vala
@@ -14,7 +14,7 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.AttachedMediaButton : Gtk.Button {
-
+
private Gtk.ListBox m_list;
private Gtk.Image m_filesIcon;
private Gtk.Spinner m_spinner;
@@ -25,13 +25,13 @@ public class FeedReader.AttachedMediaButton : Gtk.Button {
public signal void play(string url);
public signal void popClosed();
public signal void popOpened();
-
+
public AttachedMediaButton()
{
m_filesIcon = new Gtk.Image.from_icon_name("mail-attachment-symbolic", Gtk.IconSize.SMALL_TOOLBAR);
m_spinner = new Gtk.Spinner();
m_spinner.set_size_request(16,16);
-
+
m_stack = new Gtk.Stack();
m_stack.set_transition_duration(100);
m_stack.set_transition_type(Gtk.StackTransitionType.CROSSFADE);
@@ -41,7 +41,7 @@ public class FeedReader.AttachedMediaButton : Gtk.Button {
this.set_relief(Gtk.ReliefStyle.NONE);
this.set_events(Gdk.EventMask.ENTER_NOTIFY_MASK);
this.set_focus_on_click(false);
-
+
m_list = new Gtk.ListBox();
m_list.margin = 10;
m_list.set_selection_mode(Gtk.SelectionMode.NONE);
@@ -58,7 +58,7 @@ public class FeedReader.AttachedMediaButton : Gtk.Button {
Logger.error("MediaPopover: invalid row clicked");
}
});
-
+
m_pop = new Gtk.Popover(this);
m_pop.add(m_list);
m_pop.set_modal(true);
@@ -67,7 +67,7 @@ public class FeedReader.AttachedMediaButton : Gtk.Button {
popClosed();
});
}
-
+
public void update()
{
m_enclosures = new Gee.ArrayList<Enclosure>();
@@ -76,13 +76,13 @@ public class FeedReader.AttachedMediaButton : Gtk.Button {
{
m_enclosures = selectedArticle.getEnclosures();
}
-
+
if(m_signalID != 0)
{
this.disconnect(m_signalID);
m_signalID = 0;
}
-
+
if(m_enclosures.size != 0)
{
m_stack.set_visible_child_name("files");
@@ -106,7 +106,7 @@ public class FeedReader.AttachedMediaButton : Gtk.Button {
// no media
}
}
-
+
private void playMedia(string url)
{
Logger.debug(@"MediaButton.playMedia: $url");
diff --git a/src/Widgets/MediaPlayer.vala b/src/Widgets/MediaPlayer.vala
index dca881aa..df5fd596 100644
--- a/src/Widgets/MediaPlayer.vala
+++ b/src/Widgets/MediaPlayer.vala
@@ -14,7 +14,7 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.MediaPlayer : Gtk.Box {
-
+
private dynamic Gst.Element m_player;
private dynamic Gtk.Widget m_videoWidget;
private Gtk.Stack m_playStack;
@@ -38,24 +38,24 @@ public class FeedReader.MediaPlayer : Gtk.Box {
private string m_URL;
private DisplayPosition m_display = DisplayPosition.ALL;
public signal void loaded();
-
+
public MediaPlayer(string url)
{
m_type = MediaType.AUDIO;
m_URL = url;
-
+
inspectMedia();
buildUI();
loaded();
}
-
+
private void inspectMedia()
{
try
{
var discoverer = new Gst.PbUtils.Discoverer((Gst.ClockTime)(10*Gst.SECOND));
var info = discoverer.discover_uri(m_URL);
-
+
foreach(Gst.PbUtils.DiscovererStreamInfo i in info.get_stream_list())
{
if(i is Gst.PbUtils.DiscovererVideoInfo)
@@ -71,7 +71,7 @@ public class FeedReader.MediaPlayer : Gtk.Box {
Logger.error("Unable discover_uri: " + e.message);
}
}
-
+
private void buildUI()
{
var gtksink = Gst.ElementFactory.make("gtksink", "sink");
@@ -80,15 +80,15 @@ public class FeedReader.MediaPlayer : Gtk.Box {
m_videoWidget.margin_end = m_margin;
m_videoWidget.margin_top = m_margin;
m_videoWidget.size_allocate.connect(onAllocation);
-
+
m_player = Gst.ElementFactory.make("playbin", "player");
m_player["video_sink"] = gtksink;
m_player["volume"] = 1.0;
m_player["uri"] = m_URL;
-
+
Gst.Bus bus = m_player.get_bus();
bus.add_watch(GLib.Priority.LOW, busCallback);
-
+
GLib.Timeout.add(500, () => {
Gst.State state;
Gst.State pending;
@@ -110,13 +110,13 @@ public class FeedReader.MediaPlayer : Gtk.Box {
}
return true;
}, GLib.Priority.LOW);
-
+
m_playIcon = new Gtk.Image.from_icon_name("media-playback-start-symbolic", Gtk.IconSize.LARGE_TOOLBAR);
m_pauseIcon = new Gtk.Image.from_icon_name("media-playback-pause-symbolic", Gtk.IconSize.LARGE_TOOLBAR);
m_muteIcon = new Gtk.Image.from_icon_name("audio-volume-muted-symbolic", Gtk.IconSize.DND);
m_noiseIcon = new Gtk.Image.from_icon_name("audio-volume-high-symbolic", Gtk.IconSize.DND);
m_closeIcon = new Gtk.Image.from_icon_name("window-close-symbolic", Gtk.IconSize.SMALL_TOOLBAR);
-
+
m_playButton = new Gtk.Button();
m_playButton.set_image(m_playIcon);
m_playButton.clicked.connect(togglePause);
@@ -124,13 +124,13 @@ public class FeedReader.MediaPlayer : Gtk.Box {
m_playButton.valign = Gtk.Align.CENTER;
m_playButton.halign = Gtk.Align.CENTER;
m_playButton.set_size_request(48, 48);
-
+
m_playSpinner = new Gtk.Spinner();
m_playStack = new Gtk.Stack();
m_playStack.add_named(m_playButton, "button");
m_playStack.add_named(m_playSpinner, "spinner");
m_playStack.set_visible_child_name("button");
-
+
m_muteButton = new Gtk.Button();
m_muteButton.set_image(m_noiseIcon);
m_muteButton.set_tooltip_text(MediaButton.MUTE);
@@ -138,7 +138,7 @@ public class FeedReader.MediaPlayer : Gtk.Box {
m_muteButton.valign = Gtk.Align.CENTER;
m_muteButton.halign = Gtk.Align.CENTER;
m_muteButton.set_size_request(48, 48);
-
+
m_closeButton = new Gtk.Button();
m_closeButton.set_image(m_closeIcon);
m_closeButton.clicked.connect(() => {
@@ -148,12 +148,12 @@ public class FeedReader.MediaPlayer : Gtk.Box {
m_closeButton.valign = Gtk.Align.CENTER;
m_closeButton.halign = Gtk.Align.CENTER;
m_closeButton.set_size_request(48, 48);
-
+
m_scale = new Gtk.Scale.with_range(Gtk.Orientation.HORIZONTAL, 0.0, 100.0, 5.0);
m_scale.draw_value = false;
m_scale.set_size_request(200, 48);
m_scale.change_value.connect(valueChanged);
-
+
m_labelButton = new Gtk.Button.with_label("00:00");
m_labelButton.set_relief(Gtk.ReliefStyle.NONE);
m_labelButton.get_style_context().add_class("h3");
@@ -161,7 +161,7 @@ public class FeedReader.MediaPlayer : Gtk.Box {
m_labelButton.valign = Gtk.Align.CENTER;
m_labelButton.halign = Gtk.Align.CENTER;
m_labelButton.set_size_request(48, 48);
-
+
var hBox = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 10);
hBox.margin = m_margin;
hBox.pack_start(m_playStack, false, false);
@@ -169,17 +169,17 @@ public class FeedReader.MediaPlayer : Gtk.Box {
hBox.pack_start(m_scale);
hBox.pack_start(m_labelButton, false, false);
hBox.pack_start(m_closeButton, false, false);
-
+
m_bufferLabel = new Gtk.Label("0%");
m_bufferLabel.valign = Gtk.Align.CENTER;
m_bufferLabel.halign = Gtk.Align.CENTER;
m_bufferLabel.set_size_request(48, 48);
m_bufferLabel.no_show_all = true;
-
+
var bufferOverlay = new Gtk.Overlay();
bufferOverlay.add(m_videoWidget);
bufferOverlay.add_overlay(m_bufferLabel);
-
+
this.orientation = Gtk.Orientation.VERTICAL;
this.get_style_context().add_class("osd");
this.margin = 40;
@@ -191,13 +191,13 @@ public class FeedReader.MediaPlayer : Gtk.Box {
this.valign = Gtk.Align.END;
this.show_all();
}
-
+
private void togglePause()
{
Gst.State state;
Gst.State pending;
m_player.get_state(out state, out pending, 1000);
-
+
switch(state)
{
case Gst.State.PLAYING:
@@ -205,7 +205,7 @@ public class FeedReader.MediaPlayer : Gtk.Box {
m_playButton.set_tooltip_text(MediaButton.PLAY);
m_player.set_state(Gst.State.PAUSED);
break;
-
+
case Gst.State.PAUSED:
case Gst.State.READY:
default:
@@ -214,7 +214,7 @@ public class FeedReader.MediaPlayer : Gtk.Box {
m_player.set_state(Gst.State.PLAYING);
break;
}
-
+
if(m_muted)
{
m_player["volume"] = 0.0;
@@ -224,7 +224,7 @@ public class FeedReader.MediaPlayer : Gtk.Box {
m_player["volume"] = 1.0;
}
}
-
+
private void switchDisplay()
{
switch(m_display)
@@ -232,18 +232,18 @@ public class FeedReader.MediaPlayer : Gtk.Box {
case DisplayPosition.ALL:
m_display = DisplayPosition.POS;
break;
-
+
case DisplayPosition.POS:
m_display = DisplayPosition.LEFT;
break;
-
+
case DisplayPosition.LEFT:
m_display = DisplayPosition.ALL;
break;
}
calcTime();
}
-
+
private void calcTime()
{
int64 pos;
@@ -252,106 +252,106 @@ public class FeedReader.MediaPlayer : Gtk.Box {
m_player.query_duration(Gst.Format.TIME, out dur);
double position = (int)((double)pos/1000000000);
double duration = (int)((double)dur/1000000000);
-
-
-
+
+
+
double? sd = duration;
double? md = null;
double? hd = null;
-
+
if( ((int)sd) >= 60)
{
md = (int)(sd/60);
sd = sd - (md*60);
-
+
if( ((int)md) >= 60)
{
hd = (int)(md/60);
md = md - (hd*60);
}
}
-
+
double? sp = position;
double? mp = null;
double? hp = null;
-
+
if( ((int)sp) >= 60)
{
mp = (int)(sp/60);
sp = sp - (mp*60);
-
+
if( ((int)mp) >= 60)
{
hp = (int)(mp/60);
mp = mp - (hp*60);
}
}
-
+
double? sr = duration - position;
double? mr = null;
double? hr = null;
-
+
if( ((int)sr) >= 60)
{
mr = (int)(sr/60);
sr = sr - (mr*60);
-
+
if( ((int)mr) >= 60)
{
hr = (int)(mr/60);
mr = mr - (hr*60);
}
}
-
+
var pLabel = "";
(hp != null) ? pLabel += "%02.0f:".printf(hp) : null;
(mp != null) ? pLabel += "%02.0f".printf(mp) : null;
(mp != null) ? pLabel += ":" : pLabel += "0:";
pLabel += "%02.0f".printf(sp);
-
+
var dLabel = "";
(hd != null) ? dLabel += "%02.0f:".printf(hd) : null;
(md != null) ? dLabel += "%02.0f".printf(md) : null;
(md != null) ? dLabel += ":" : dLabel += "0:";
dLabel += "%02.0f".printf(sd);
-
+
var rLabel = "-";
(hr != null) ? rLabel += "%02.0f:".printf(hr) : null;
(mr != null) ? rLabel += "%02.0f".printf(mr) : null;
(mr != null) ? rLabel += ":" : rLabel += "0:";
rLabel += "%02.0f".printf(sr);
-
+
if(dur == -1)
{
m_labelButton.set_label(pLabel);
return;
}
-
-
+
+
switch(m_display)
{
case DisplayPosition.ALL:
m_labelButton.set_label(pLabel + " / " + dLabel);
break;
-
+
case DisplayPosition.POS:
m_labelButton.set_label(pLabel);
break;
-
+
case DisplayPosition.LEFT:
m_labelButton.set_label(rLabel);
break;
}
}
-
+
private bool valueChanged(Gtk.ScrollType scroll, double new_value)
{
m_scale.set_value(new_value);
-
+
if (m_seek_source_id == 0)
{
double startValue = new_value;
-
+
m_seek_source_id = GLib.Timeout.add_full(GLib.Priority.DEFAULT, 500, () => {
if(m_scale.get_value() != startValue)
{
@@ -368,7 +368,7 @@ public class FeedReader.MediaPlayer : Gtk.Box {
}
return true;
}
-
+
private void seek(double new_value)
{
int64 dur;
@@ -380,7 +380,7 @@ public class FeedReader.MediaPlayer : Gtk.Box {
m_playButton.set_image(m_pauseIcon);
m_player.set_state(Gst.State.PLAYING);
}
-
+
private void toggleMute()
{
if(m_muted)
@@ -398,7 +398,7 @@ public class FeedReader.MediaPlayer : Gtk.Box {
m_muted = true;
}
}
-
+
private bool busCallback(Gst.Bus bus, Gst.Message message)
{
switch (message.type)
@@ -410,19 +410,19 @@ public class FeedReader.MediaPlayer : Gtk.Box {
Logger.error("MediaPlayer: " + err.message);
m_player.set_state(Gst.State.NULL);
break;
-
+
case Gst.MessageType.EOS:
m_player.set_state(Gst.State.READY);
m_playButton.set_image(m_playIcon);
break;
-
+
case Gst.MessageType.BUFFERING:
int percent = 0;
message.parse_buffering(out percent);
if(percent < 100)
{
m_player.set_state(Gst.State.PAUSED);
-
+
if(m_type == MediaType.VIDEO)
{
m_bufferLabel.set_text(percent.to_string() + "%");
@@ -447,7 +447,7 @@ public class FeedReader.MediaPlayer : Gtk.Box {
}
}
break;
-
+
case Gst.MessageType.STATE_CHANGED:
Gst.State oldstate;
Gst.State newstate;
@@ -457,7 +457,7 @@ public class FeedReader.MediaPlayer : Gtk.Box {
}
return true;
}
-
+
private void onAllocation(Gtk.Allocation allocation)
{
if(m_aspectRatio != 0)
@@ -467,11 +467,11 @@ public class FeedReader.MediaPlayer : Gtk.Box {
m_videoWidget.set_size_request(-1, height);
}
}
-
+
public void kill()
{
m_player.set_state(Gst.State.NULL);
this.destroy();
}
-
+
}
diff --git a/src/Widgets/MediaRow.vala b/src/Widgets/MediaRow.vala
index 352ab2ba..11466044 100644
--- a/src/Widgets/MediaRow.vala
+++ b/src/Widgets/MediaRow.vala
@@ -14,52 +14,52 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.mediaRow : Gtk.ListBoxRow {
-
+
private Enclosure m_enc;
-
+
public mediaRow(Enclosure enc)
{
m_enc = enc;
-
+
int lastSlash = m_enc.get_url().last_index_of_char('/');
string fileName = m_enc.get_url().substring(lastSlash + 1);
string icon_name = "image-x-generic-symbolic";
-
+
switch(enc.get_enclosure_type())
{
case EnclosureType.IMAGE:
icon_name = "image-x-generic-symbolic";
break;
-
+
case EnclosureType.AUDIO:
icon_name = "audio-speakers-symbolic";
break;
-
+
case EnclosureType.VIDEO:
icon_name = "media-playback-start-symbolic";
break;
}
var icon = new Gtk.Image.from_icon_name(icon_name, Gtk.IconSize.SMALL_TOOLBAR);
-
+
var label = new Gtk.Label(GLib.Uri.unescape_string(fileName));
label.set_line_wrap_mode(Pango.WrapMode.WORD);
label.set_ellipsize(Pango.EllipsizeMode.END);
label.set_alignment(0.0f, 0.5f);
label.get_style_context().add_class("h4");
-
+
var box = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 3);
box.margin = 3;
box.pack_start(icon, false, false, 8);
box.pack_start(label, true, true, 0);
-
+
this.add(box);
this.margin = 2;
this.show_all();
}
-
+
public string getURL()
{
return m_enc.get_url();
}
-
+
}
diff --git a/src/Widgets/ModeButton.vala b/src/Widgets/ModeButton.vala
index f3b6903f..9517fd8d 100644
--- a/src/Widgets/ModeButton.vala
+++ b/src/Widgets/ModeButton.vala
@@ -21,14 +21,14 @@
*/
namespace FeedReader {
-
+
/**
* This widget is a multiple option modal switch
*
* {{../../doc/images/ModeButton.png}}
*/
public class ModeButton : Gtk.Box {
-
+
private class Item : Gtk.ToggleButton {
public int index { get; construct; }
public Item (int index) {
@@ -37,11 +37,11 @@ namespace FeedReader {
add_events (Gdk.EventMask.SCROLL_MASK);
}
}
-
+
public signal void mode_added (int index, Gtk.Widget widget);
public signal void mode_removed (int index, Gtk.Widget widget);
public signal void mode_changed (Gtk.Widget widget);
-
+
/**
* Index of currently selected item.
*/
@@ -49,18 +49,18 @@ namespace FeedReader {
get { return _selected; }
set { set_active (value); }
}
-
+
/**
* Read-only length of current ModeButton
*/
public uint n_items {
get { return item_map.size; }
}
-
+
private int _selected = -1;
private Gee.HashMap<int, Item> item_map;
private uint m_timeout_source_id = 0;
-
+
/**
* Makes new ModeButton
*/
@@ -68,14 +68,14 @@ namespace FeedReader {
homogeneous = true;
spacing = 0;
can_focus = false;
-
+
item_map = new Gee.HashMap<int, Item> ();
-
+
var style = get_style_context ();
style.add_class (Gtk.STYLE_CLASS_LINKED);
style.add_class ("raised"); // needed for toolbars
}
-
+
/**
* Appends Pixbuf to ModeButton
*
@@ -84,7 +84,7 @@ namespace FeedReader {
public int append_pixbuf (Gdk.Pixbuf pixbuf, string tooltip = "") {
return append (new Gtk.Image.from_pixbuf (pixbuf), tooltip);
}
-
+
/**
* Appends text to ModeButton
*
@@ -94,7 +94,7 @@ namespace FeedReader {
public int append_text (string text, string tooltip = "") {
return append (new Gtk.Label(text), tooltip);
}
-
+
/**
* Appends icon to ModeButton
*
@@ -105,7 +105,7 @@ namespace FeedReader {
public int append_icon (string icon_name, Gtk.IconSize size, string tooltip = "") {
return append (new Gtk.Image.from_icon_name (icon_name, size), tooltip);
}
-
+
/**
* Appends given widget to ModeButton
*
@@ -116,28 +116,28 @@ namespace FeedReader {
int index;
for (index = item_map.size; item_map.has_key (index); index++);
assert (item_map[index] == null);
-
+
w.set_tooltip_text(tooltip);
-
+
var item = new Item (index);
item.scroll_event.connect (on_scroll_event);
item.add (w);
-
+
item.button_press_event.connect (() => {
set_active (item.index);
return true;
});
-
+
item_map[index] = item;
-
+
add (item);
item.show_all ();
-
+
mode_added (index, w);
-
+
return index;
}
-
+
/**
* Sets item of given index's activity
*
@@ -146,26 +146,26 @@ namespace FeedReader {
public void set_active (int new_active_index, bool initSet = false) {
return_if_fail (item_map.has_key (new_active_index));
var new_item = item_map[new_active_index] as Item;
-
+
if (new_item != null)
{
assert (new_item.index == new_active_index);
new_item.set_active (true);
-
+
if (_selected == new_active_index)
{
return;
}
-
+
// Unselect the previous item
var old_item = item_map[_selected] as Item;
if (old_item != null)
{
old_item.set_active (false);
}
-
+
_selected = new_active_index;
-
+
if(!initSet)
{
if(m_timeout_source_id > 0)
@@ -173,7 +173,7 @@ namespace FeedReader {
GLib.Source.remove(m_timeout_source_id);
m_timeout_source_id = 0;
}
-
+
m_timeout_source_id = GLib.Timeout.add(50, () => {
mode_changed(new_item.get_child());
m_timeout_source_id = 0;
@@ -182,7 +182,7 @@ namespace FeedReader {
}
}
}
-
+
/**
* Changes visibility of item of given index
*
@@ -192,7 +192,7 @@ namespace FeedReader {
public void set_item_visible (int index, bool val) {
return_if_fail (item_map.has_key (index));
var item = item_map[index] as Item;
-
+
if (item != null)
{
assert (item.index == index);
@@ -200,7 +200,7 @@ namespace FeedReader {
item.visible = val;
}
}
-
+
/**
* Removes item at given index
*
@@ -209,7 +209,7 @@ namespace FeedReader {
public new void remove (int index) {
return_if_fail (item_map.has_key (index));
var item = item_map[index] as Item;
-
+
if (item != null)
{
assert (item.index == index);
@@ -218,7 +218,7 @@ namespace FeedReader {
item.destroy ();
}
}
-
+
/**
* Clears all children
*/
@@ -230,15 +230,15 @@ namespace FeedReader {
base.remove (button);
}
}
-
+
item_map.clear ();
-
+
_selected = -1;
}
-
+
private bool on_scroll_event (Gtk.Widget widget, Gdk.EventScroll ev) {
int offset;
-
+
switch (ev.direction) {
case Gdk.ScrollDirection.DOWN:
case Gdk.ScrollDirection.RIGHT:
@@ -251,36 +251,36 @@ namespace FeedReader {
default:
return false;
}
-
+
// Try to find a valid item, since there could be invisible items in
// the middle and those shouldn't be selected. We use the children list
// instead of item_map because order matters here.
var children = get_children ();
uint n_children = children.length ();
-
+
var selected_item = item_map[selected];
if (selected_item == null)
{
return false;
}
-
+
int new_item = children.index (selected_item);
if (new_item < 0)
{
return false;
}
-
+
do {
new_item += offset;
var item = children.nth_data (new_item) as Item;
-
+
if (item != null && item.visible && item.sensitive)
{
selected = item.index;
break;
}
} while (new_item >= 0 && new_item < n_children);
-
+
return false;
}
}
diff --git a/src/Widgets/RemovePopover.vala b/src/Widgets/RemovePopover.vala
index 4b3d8cc3..b4450bf2 100644
--- a/src/Widgets/RemovePopover.vala
+++ b/src/Widgets/RemovePopover.vala
@@ -14,36 +14,36 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.RemovePopover : Gtk.Popover {
-
+
private string m_id;
private FeedListType m_type;
private feedList m_feedlist;
private uint m_time = 300;
private string m_name;
-
+
public RemovePopover(Gtk.Widget parent, FeedListType type, string id)
{
this.relative_to = parent;
this.position = Gtk.PositionType.TOP;
m_type = type;
m_id = id;
-
+
switch(m_type)
{
case FeedListType.TAG:
m_name = DataBase.readOnly().getTagName(m_id);
break;
-
+
case FeedListType.FEED:
var feed = DataBase.readOnly().read_feed(m_id);
m_name = feed != null ? feed.getTitle() : "";
break;
-
+
case FeedListType.CATEGORY:
m_name = DataBase.readOnly().getCategoryName(m_id);
break;
}
-
+
var removeButton = new Gtk.Button.with_label(_("Remove \"%s\"").printf(m_name));
removeButton.get_style_context().add_class(Gtk.STYLE_CLASS_DESTRUCTIVE_ACTION);
removeButton.clicked.connect(removeX);
@@ -51,36 +51,36 @@ public class FeedReader.RemovePopover : Gtk.Popover {
this.add(removeButton);
this.show_all();
}
-
+
public void removeX()
{
m_feedlist = ColumnView.get_default().getFeedList();
m_feedlist.moveUP();
m_feedlist.revealRow(m_id, m_type, false, m_time);
-
+
switch(m_type)
{
case FeedListType.TAG:
removeTag();
break;
-
+
case FeedListType.FEED:
removeFeed();
break;
-
+
case FeedListType.CATEGORY:
removeCategory();
break;
}
-
+
this.hide();
}
-
+
private void removeTag()
{
string text = _("Tag \"%s\" removed").printf(m_name);
var notification = MainWindow.get_default().showNotification(text);
-
+
ulong eventID = notification.dismissed.connect(() => {
var tag = DataBase.readOnly().read_tag(m_id);
if(tag != null)
@@ -94,12 +94,12 @@ public class FeedReader.RemovePopover : Gtk.Popover {
notification.dismiss();
});
}
-
+
private void removeFeed()
{
string text = _("Feed \"%s\" removed").printf(m_name);
var notification = MainWindow.get_default().showNotification(text);
-
+
ulong eventID = notification.dismissed.connect(() => {
FeedReaderBackend.get_default().removeFeed(m_id);
});
@@ -109,13 +109,13 @@ public class FeedReader.RemovePopover : Gtk.Popover {
notification.dismiss();
});
}
-
+
private void removeCategory()
{
m_feedlist.expand_collapse_category(m_id, false);
string text = _("Category \"%s\" removed").printf(m_name);
var notification = MainWindow.get_default().showNotification(text);
-
+
ulong eventID = notification.dismissed.connect(() => {
FeedReaderBackend.get_default().removeCategory(m_id);
});
diff --git a/src/Widgets/ResetPage.vala b/src/Widgets/ResetPage.vala
index 5daab6c4..29b2422d 100644
--- a/src/Widgets/ResetPage.vala
+++ b/src/Widgets/ResetPage.vala
@@ -14,7 +14,7 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.ResetPage : Gtk.Bin {
-
+
private Gtk.Box m_layout;
private Gtk.Button m_newAccountButton;
private Gtk.Label m_deleteLabel;
@@ -23,28 +23,28 @@ public class FeedReader.ResetPage : Gtk.Bin {
private Gtk.Spinner m_spinner;
public signal void cancel();
public signal void reset();
-
+
public ResetPage()
{
m_reset = false;
m_layout = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
m_layout.set_size_request(700, 410);
-
+
var titleText = new Gtk.Label(_("Change Account?"));
titleText.get_style_context().add_class("h1");
titleText.set_justify(Gtk.Justification.CENTER);
-
+
var describtionText = new Gtk.Label(_("You are about to change the account you want FeedReader to use.\n This means deleting all local data of your old account."));
describtionText.get_style_context().add_class("h2");
describtionText.set_justify(Gtk.Justification.CENTER);
-
+
m_deleteLabel = new Gtk.Label(_("New account"));
m_waitingBox = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 2);
m_spinner = new Gtk.Spinner();
var waitingLabel = new Gtk.Label(_("Waiting for current sync to finish"));
m_waitingBox.pack_start(m_spinner, false, false, 0);
m_waitingBox.pack_start(waitingLabel, false, true, 0);
-
+
var buttonBox = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 0);
m_newAccountButton = new Gtk.Button();
m_newAccountButton.add(m_deleteLabel);
@@ -56,20 +56,20 @@ public class FeedReader.ResetPage : Gtk.Bin {
cancelButton.clicked.connect(abortReset);
buttonBox.pack_start(cancelButton, false, false, 0);
buttonBox.pack_end(m_newAccountButton, false, false, 0);
-
+
m_layout.pack_start(titleText, false, true, 0);
m_layout.pack_start(describtionText, true, true, 0);
m_layout.pack_end(buttonBox, false, true, 0);
-
-
+
+
this.set_halign(Gtk.Align.CENTER);
this.set_valign(Gtk.Align.CENTER);
this.margin = 20;
this.add(m_layout);
this.show_all();
}
-
-
+
+
private void resetAllData()
{
if(Settings.state().get_boolean("currently-updating"))
@@ -81,40 +81,40 @@ public class FeedReader.ResetPage : Gtk.Bin {
m_spinner.start();
m_newAccountButton.set_sensitive(false);
FeedReaderBackend.get_default().cancelSync();
-
+
while(Settings.state().get_boolean("currently-updating"))
{
Gtk.main_iteration();
}
-
+
if(!m_reset)
{
return;
}
}
-
+
// set "currently-updating" ourself to prevent the backend to start sync
Settings.state().set_boolean("currently-updating", true);
-
+
// clear all data from UI
ColumnView.get_default().clear();
-
+
Settings.general().reset("plugin");
Utils.resetSettings(Settings.state());
FeedReaderBackend.get_default().resetDB();
FeedReaderBackend.get_default().resetAccount();
-
+
Utils.remove_directory(GLib.Environment.get_user_data_dir() + "/feedreader/data/images/");
-
+
Settings.state().set_boolean("currently-updating", false);
FeedReaderBackend.get_default().login("none");
-
+
// Load all available plugins, to present them on the login page
FeedServer.get_default().LoadAllPlugins();
-
+
reset();
}
-
+
private void abortReset()
{
m_reset = false;
diff --git a/src/Widgets/ServiceInfo.vala b/src/Widgets/ServiceInfo.vala
index 886171fb..1a0de37e 100644
--- a/src/Widgets/ServiceInfo.vala
+++ b/src/Widgets/ServiceInfo.vala
@@ -20,7 +20,7 @@ public class FeedReader.ServiceInfo : Gtk.Overlay {
private Gtk.Label m_label;
private Gtk.Label m_offline;
private Gtk.Box m_box;
-
+
public ServiceInfo()
{
m_logo = new Gtk.Image();
@@ -30,22 +30,22 @@ public class FeedReader.ServiceInfo : Gtk.Overlay {
m_label.margin_start = 10;
m_label.margin_end = 10;
m_label.set_ellipsize(Pango.EllipsizeMode.END);
-
+
m_box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
m_box.pack_start(m_logo, false, false, 0);
m_box.pack_start(m_label, false, false, 5);
m_box.margin_top = 20;
m_box.margin_bottom = 5;
-
+
m_spinner = new Gtk.Spinner();
m_spinner.set_size_request(32,32);
-
+
m_stack = new Gtk.Stack();
m_stack.add_named(m_box, "info");
m_stack.add_named(m_spinner, "spinner");
m_stack.get_style_context().add_class("fr-sidebar");
this.add(m_stack);
-
+
m_offline = new Gtk.Label("OFFLINE");
m_offline.margin_start = 40;
m_offline.margin_end = 40;
@@ -55,13 +55,13 @@ public class FeedReader.ServiceInfo : Gtk.Overlay {
m_offline.no_show_all = true;
this.add_overlay(m_offline);
}
-
+
public void refresh()
{
string? service_icon = FeedReaderBackend.get_default().symbolicIcon();
string? user_name = FeedReaderBackend.get_default().accountName();
string? server = FeedReaderBackend.get_default().getServerURL();
-
+
if(this.is_visible())
{
if(user_name == "none" || service_icon == "none")
@@ -81,15 +81,15 @@ public class FeedReader.ServiceInfo : Gtk.Overlay {
}
}
}
-
+
show_all();
}
-
+
public void setOffline()
{
m_offline.show();
}
-
+
public void setOnline()
{
m_offline.hide();
diff --git a/src/Widgets/ServiceSettingsPopover.vala b/src/Widgets/ServiceSettingsPopover.vala
index c8dcefea..ed65c4bf 100644
--- a/src/Widgets/ServiceSettingsPopover.vala
+++ b/src/Widgets/ServiceSettingsPopover.vala
@@ -14,10 +14,10 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.ServiceSettingsPopover : Gtk.Popover {
-
+
public signal void newAccount(string type);
-
-
+
+
public ServiceSettingsPopover(Gtk.Widget widget)
{
var list = new Gtk.ListBox();
@@ -27,61 +27,61 @@ public class FeedReader.ServiceSettingsPopover : Gtk.Popover {
newAccount(((ServiceSettingsPopoverRow)row).getType());
this.hide();
});
-
+
foreach(var account in Share.get_default().getAccountTypes())
{
var row = new ServiceSettingsPopoverRow(account.getAccountName(), account.getType(), account.getIconName());
list.add(row);
}
-
+
this.add(list);
this.set_modal(true);
this.set_relative_to(widget);
this.set_position(Gtk.PositionType.BOTTOM);
this.show_all();
}
-
+
}
public class FeedReader.ServiceSettingsPopoverRow : Gtk.ListBoxRow {
-
+
private string m_name;
private Gtk.Label m_label;
private Gtk.Box m_box;
private string m_type;
-
+
public ServiceSettingsPopoverRow(string serviceName, string type, string iconName)
{
m_type = type;
m_name = serviceName;
m_box = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 3);
m_box.margin = 3;
-
+
var icon = new Gtk.Image.from_icon_name(iconName, Gtk.IconSize.DND);
-
+
m_label = new Gtk.Label(serviceName);
m_label.set_line_wrap_mode(Pango.WrapMode.WORD);
m_label.set_ellipsize(Pango.EllipsizeMode.END);
m_label.set_alignment(0.5f, 0.5f);
m_label.set_justify(Gtk.Justification.LEFT);
m_label.set_halign(Gtk.Align.START);
-
+
m_box.pack_start(icon, false, false, 8);
m_box.pack_start(m_label, true, true, 0);
-
+
this.add(m_box);
this.show_all();
}
-
+
public string getType()
{
return m_type;
}
-
+
public string getName()
{
return m_name;
}
-
+
}
diff --git a/src/Widgets/Setting.vala b/src/Widgets/Setting.vala
index 34f5d33e..45801cb5 100644
--- a/src/Widgets/Setting.vala
+++ b/src/Widgets/Setting.vala
@@ -14,30 +14,30 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.Setting : Gtk.Box {
-
+
public signal void changed();
private Gtk.Label m_label;
-
-
+
+
public Setting(string name, string? tooltip = null)
{
this.orientation = Gtk.Orientation.HORIZONTAL;
this.spacing = 0;
-
+
m_label = new Gtk.Label(name);
m_label.set_alignment(0, 0.5f);
m_label.margin_start = 15;
m_label.set_tooltip_text(tooltip);
-
+
this.pack_start(m_label, true, true, 0);
}
-
-
+
+
}
public class FeedReader.SettingFont : FeedReader.Setting {
-
+
public SettingFont(string name, GLib.Settings settings, string key){
base(name, null);
var current_font = settings.get_value(key).get_maybe();
@@ -46,33 +46,33 @@ public class FeedReader.SettingFont : FeedReader.Setting {
{
font_button.font = current_font.get_string();
}
-
+
font_button.set_use_size(false);
font_button.set_show_size(true);
font_button.font_set.connect(() => {
var new_font = new Variant.string(font_button.get_font_name());
settings.set_value(key, new Variant.maybe(VariantType.STRING, new_font));
});
-
+
this.pack_end(font_button, false, false, 0);
}
-
+
}
public class FeedReader.SettingDropbox : FeedReader.Setting {
-
+
public SettingDropbox(string name, GLib.Settings settings, string key, string[] values, string? tooltip = null)
{
base(name, tooltip);
var liststore = new Gtk.ListStore(1, typeof(string));
-
+
foreach(string val in values)
{
Gtk.TreeIter iter;
liststore.append(out iter);
liststore.set(iter, 0, val);
}
-
+
var dropbox = new Gtk.ComboBox.with_model(liststore);
var renderer = new Gtk.CellRendererText();
dropbox.pack_start(renderer, false);
@@ -82,45 +82,45 @@ public class FeedReader.SettingDropbox : FeedReader.Setting {
settings.set_enum(key, dropbox.get_active());
changed();
});
-
+
this.pack_end(dropbox, false, false, 0);
}
}
public class FeedReader.SettingSwitch : FeedReader.Setting {
-
+
public SettingSwitch(string name, GLib.Settings settings, string key, string? tooltip = null)
{
base(name, tooltip);
-
+
var Switch = new Gtk.Switch();
Switch.active = settings.get_boolean(key);
-
+
Switch.notify["active"].connect(() => {
settings.set_boolean(key, Switch.active);
changed();
});
-
+
this.pack_end(Switch, false, false, 0);
}
}
public class FeedReader.SettingSpin : FeedReader.Setting {
-
+
public SettingSpin(string name, GLib.Settings settings, string key, int min, int max, int step, string? tooltip = null)
{
base(name, tooltip);
-
+
var spin = new Gtk.SpinButton.with_range(min, max, step);
spin.set_value(settings.get_int(key));
-
+
spin.value_changed.connect(() => {
settings.set_int(key, spin.get_value_as_int());
changed();
});
-
+
this.pack_end(spin, false, false, 0);
}
}
diff --git a/src/Widgets/SettingsDialog.vala b/src/Widgets/SettingsDialog.vala
index a00ff6d5..726c8aff 100644
--- a/src/Widgets/SettingsDialog.vala
+++ b/src/Widgets/SettingsDialog.vala
@@ -14,23 +14,23 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.SettingsDialog : Gtk.Dialog {
-
+
private Gtk.ListBox m_serviceList;
private Gtk.Stack m_stack;
private InfoBar m_errorBar;
private Gtk.HeaderBar m_headerbar;
private static SettingsDialog? m_dialog = null;
-
+
public static SettingsDialog get_default()
{
if(m_dialog == null)
{
m_dialog = new SettingsDialog();
}
-
+
return m_dialog;
}
-
+
private SettingsDialog()
{
this.border_width = 20;
@@ -38,11 +38,11 @@ public class FeedReader.SettingsDialog : Gtk.Dialog {
this.set_modal(true);
this.delete_event.connect(hide_on_delete);
set_default_size(550, 450);
-
+
m_headerbar = new Gtk.HeaderBar();
m_headerbar.set_show_close_button(true);
set_titlebar(m_headerbar);
-
+
m_stack = new Gtk.Stack();
m_stack.set_transition_duration(50);
m_stack.set_transition_type(Gtk.StackTransitionType.CROSSFADE);
@@ -50,76 +50,76 @@ public class FeedReader.SettingsDialog : Gtk.Dialog {
m_stack.add_titled(setup_UI(), "ui", _("Interface"));
m_stack.add_titled(setup_Internal(), "internal", _("Internals"));
m_stack.add_titled(setup_Service(), "service", _("Share"));
-
+
Gtk.StackSwitcher switcher = new Gtk.StackSwitcher();
switcher.set_halign(Gtk.Align.CENTER);
switcher.set_valign(Gtk.Align.CENTER);
switcher.set_stack(m_stack);
-
+
m_headerbar.set_custom_title(switcher);
-
+
var content = get_content_area() as Gtk.Box;
content.add(m_stack);
}
-
+
public void showDialog(string panel)
{
this.show_all();
m_stack.set_visible_child_name(panel);
}
-
+
private Gtk.Box setup_UI()
{
var feed_settings = headline(_("Feed List:"));
-
+
var only_feeds = new SettingSwitch(_("Only show feeds"), Settings.general(), "only-feeds");
only_feeds.changed.connect(() => {
Settings.state().set_strv("expanded-categories", Utils.getDefaultExpandedCategories());
Settings.state().set_string("feedlist-selected-row", "feed -4");
ColumnView.get_default().newFeedList(true);
});
-
+
var only_unread = new SettingSwitch(_("Only show unread"), Settings.general(), "feedlist-only-show-unread");
only_unread.changed.connect(() => {
ColumnView.get_default().newFeedList();
});
-
+
var feedlist_sort = new SettingDropbox(_("Sort Feed List by"), Settings.general(), "feedlist-sort-by", {_("Received"), _("Alphabetically")});
feedlist_sort.changed.connect(() => {
ColumnView.get_default().newFeedList();
});
-
+
var feedlist_theme = new SettingDropbox(_("Theme"), Settings.general(), "feedlist-theme", {_("Gtk+"), _("Dark"), _("elementary")});
feedlist_theme.changed.connect(() => {
MainWindow.get_default().reloadCSS();
});
-
+
var article_settings = headline(_("Article List:"));
-
+
var article_sort = new SettingDropbox(_("Sort articles by"), Settings.general(), "articlelist-sort-by", {_("Received"), _("Date")});
article_sort.changed.connect(() => {
ColumnView.get_default().newArticleList();
});
-
+
var newest_first = new SettingSwitch(_("Oldest first"), Settings.general(), "articlelist-oldest-first", _("Only affects \"Unread\" column"));
newest_first.changed.connect(() => {
ColumnView.get_default().newArticleList();
});
-
+
var scroll_marked = new SettingSwitch(_("Mark read by scrolling past"), Settings.general(), "articlelist-mark-scrolling");
-
+
var articleview_settings = headline(_("Article View:"));
-
+
var article_theme = new SettingDropbox(_("Theme"), Settings.general(), "article-theme", {_("Default"), _("Spring"), _("Midnight"), _("Parchment")});
article_theme.changed.connect(() => {
ColumnView.get_default().reloadArticleView();
});
-
+
var fontfamilly = new SettingFont(_("Font Familly"), Settings.general(), "font");
fontfamilly.changed.connect(() => {
ColumnView.get_default().reloadArticleView();
});
-
+
var uiBox = new Gtk.Box(Gtk.Orientation.VERTICAL, 5);
uiBox.expand = true;
uiBox.pack_start(feed_settings, false, true, 0);
@@ -136,33 +136,33 @@ public class FeedReader.SettingsDialog : Gtk.Dialog {
uiBox.pack_start(fontfamilly, false, true, 0);
return uiBox;
}
-
-
+
+
private Gtk.Box setup_Internal()
{
var sync_settings = headline(_("Sync:"));
-
+
var sync_count = new SettingSpin(_("Number of articles"), Settings.general(), "max-articles", 10, 5000, 10);
-
+
var sync_time = new SettingSpin(_("Interval in Minutes (0 = OFF)"), Settings.general(), "sync", 0, 600, 5);
sync_time.changed.connect(() => {
FeedReaderBackend.get_default().scheduleSync(Settings.general().get_int("sync"));
});
-
+
var db_settings = headline(_("Database:"));
-
+
var drop_articles = new SettingDropbox(_("Delete articles after"), Settings.general(), "drop-articles-after",
{_("Never"), _("1 Week"), _("1 Month"), _("6 Months")});
-
+
var service_settings = headline(_("Additional Functionality:"));
-
+
var grabber = new SettingSwitch(_("Content Grabber"), Settings.general(),"content-grabber");
-
+
var images = new SettingSwitch(_("Download Images"), Settings.general(),"download-images");
-
+
var mediaplayer = new SettingSwitch(_("Internal Media Player"), Settings.general(),"mediaplayer");
-
-
+
+
var internalsBox = new Gtk.Box(Gtk.Orientation.VERTICAL, 5);
internalsBox.expand = true;
internalsBox.pack_start(sync_settings, false, true, 0);
@@ -177,42 +177,42 @@ public class FeedReader.SettingsDialog : Gtk.Dialog {
internalsBox.pack_start(grabber, false, true, 0);
internalsBox.pack_start(images, false, true, 0);
internalsBox.pack_start(mediaplayer, false, true, 0);
-
+
return internalsBox;
}
-
-
+
+
private Gtk.Box setup_Service()
{
m_serviceList = new Gtk.ListBox();
m_serviceList.set_selection_mode(Gtk.SelectionMode.NONE);
m_serviceList.set_sort_func(sortFunc);
-
+
m_errorBar = new InfoBar("");
-
+
var service_scroll = new Gtk.ScrolledWindow(null, null);
service_scroll.expand = true;
-
+
var overlay = new Gtk.Overlay();
overlay.add(service_scroll);
overlay.add_overlay(m_errorBar);
overlay.margin_top = 10;
overlay.margin_bottom = 10;
-
+
var viewport = new Gtk.Viewport(null, null);
viewport.get_style_context().add_class("servicebox");
viewport.add(m_serviceList);
service_scroll.add(viewport);
-
+
refreshAccounts();
-
+
var serviceBox = new Gtk.Box(Gtk.Orientation.VERTICAL, 5);
serviceBox.expand = true;
serviceBox.pack_start(overlay, false, true, 0);
-
+
return serviceBox;
}
-
+
public void refreshAccounts()
{
m_serviceList.set_header_func(null);
@@ -222,9 +222,9 @@ public class FeedReader.SettingsDialog : Gtk.Dialog {
m_serviceList.remove(row);
row.destroy();
}
-
+
var list = Share.get_default().getAccounts();
-
+
foreach(var account in list)
{
if(account.isSystemAccount())
@@ -243,14 +243,14 @@ public class FeedReader.SettingsDialog : Gtk.Dialog {
row.reveal(false);
}
}
-
+
var addAccount = new Gtk.Button.from_icon_name("list-add-symbolic", Gtk.IconSize.DND);
addAccount.set_relief(Gtk.ReliefStyle.NONE);
addAccount.get_style_context().add_class("addServiceButton");
addAccount.set_size_request(0, 48);
addAccount.show();
m_serviceList.add(addAccount);
-
+
addAccount.clicked.connect(() => {
children = m_serviceList.get_children();
foreach(Gtk.Widget row in children)
@@ -262,7 +262,7 @@ public class FeedReader.SettingsDialog : Gtk.Dialog {
removeRow(tmpRow, m_serviceList);
}
}
-
+
var popover = new ServiceSettingsPopover(addAccount);
popover.newAccount.connect((type) => {
ServiceSetup row = Share.get_default().newSetup(type);
@@ -277,10 +277,10 @@ public class FeedReader.SettingsDialog : Gtk.Dialog {
row.reveal();
});
});
-
+
m_serviceList.set_header_func(headerFunc);
}
-
+
public void removeRow(ServiceSetup row, Gtk.ListBox list)
{
row.unreveal();
@@ -289,12 +289,12 @@ public class FeedReader.SettingsDialog : Gtk.Dialog {
return false;
});
}
-
+
private int sortFunc(Gtk.ListBoxRow row1, Gtk.ListBoxRow row2)
{
var r1 = row1 as ServiceSetup;
var r2 = row2 as ServiceSetup;
-
+
if(r1 == null && r2 == null)
{
return 0;
@@ -307,7 +307,7 @@ public class FeedReader.SettingsDialog : Gtk.Dialog {
{
return -1;
}
-
+
if(r1.getUserName() == ""
&& r2.getUserName() == "")
{
@@ -321,10 +321,10 @@ public class FeedReader.SettingsDialog : Gtk.Dialog {
{
return -1;
}
-
+
bool sys1 = r1.isSystemAccount();
bool sys2 = r2.isSystemAccount();
-
+
if(sys1 && sys2)
{
return 0;
@@ -333,32 +333,32 @@ public class FeedReader.SettingsDialog : Gtk.Dialog {
{
return -1;
}
-
+
return 1;
}
-
+
private void headerFunc(Gtk.ListBoxRow row, Gtk.ListBoxRow? before)
{
var label = new Gtk.Label(_("System Accounts"));
label.get_style_context().add_class("bold");
label.margin_top = 20;
label.margin_bottom = 5;
-
+
var box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
box.pack_start(label, true, true, 0);
box.pack_end(new Gtk.Separator(Gtk.Orientation.HORIZONTAL), false, false, 0);
box.show_all();
-
+
var r1 = row as ServiceSetup;
-
+
// this is the plus-button
if(r1 == null)
{
return;
}
-
+
bool sys1 = r1.isSystemAccount();
-
+
if(before == null)
{
if(sys1)
@@ -373,11 +373,11 @@ public class FeedReader.SettingsDialog : Gtk.Dialog {
return;
}
}
-
-
+
+
var r2 = before as ServiceSetup;
bool sys2 = r2.isSystemAccount();
-
+
if(r1 != null && r2 != null)
{
if(!sys1 && sys2)
@@ -387,7 +387,7 @@ public class FeedReader.SettingsDialog : Gtk.Dialog {
}
}
}
-
+
private Gtk.Label headline(string name)
{
var headline = new Gtk.Label(name);
diff --git a/src/Widgets/SharePopover.vala b/src/Widgets/SharePopover.vala
index b8357f4b..0998f92a 100644
--- a/src/Widgets/SharePopover.vala
+++ b/src/Widgets/SharePopover.vala
@@ -14,12 +14,12 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.SharePopover : Gtk.Popover {
-
+
private Gtk.ListBox m_list;
private Gtk.Stack m_stack;
public signal void startShare();
public signal void shareDone();
-
+
public SharePopover(Gtk.Widget widget)
{
m_list = new Gtk.ListBox();
@@ -31,14 +31,14 @@ public class FeedReader.SharePopover : Gtk.Popover {
m_stack.set_transition_duration(150);
m_stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT);
m_stack.add_named(m_list, "list");
-
+
this.add(m_stack);
this.set_modal(true);
this.set_relative_to(widget);
this.set_position(Gtk.PositionType.BOTTOM);
this.show_all();
}
-
+
public void refreshList()
{
var children = m_list.get_children();
@@ -47,29 +47,29 @@ public class FeedReader.SharePopover : Gtk.Popover {
m_list.remove(row);
row.destroy();
}
-
+
var list = Share.get_default().getAccounts();
-
+
foreach(var account in list)
{
m_list.add(new ShareRow(account.getType(), account.getID(), account.getUsername(), account.getIconName()));
}
-
+
var addRow = new Gtk.ListBoxRow();
addRow.margin = 2;
-
+
var addIcon = new Gtk.Image.from_icon_name("list-add-symbolic", Gtk.IconSize.DND);
var addLabel = new Gtk.Label(_("Add accounts"));
addLabel.set_line_wrap_mode(Pango.WrapMode.WORD);
addLabel.set_ellipsize(Pango.EllipsizeMode.END);
addLabel.set_alignment(0.0f, 0.5f);
addLabel.get_style_context().add_class("h4");
-
+
var addBox = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 5);
addBox.margin = 3;
addBox.pack_start(addIcon, false, false, 8);
addBox.pack_start(addLabel, true, true, 0);
-
+
if(list.size > 0)
{
var seperatorBox = new Gtk.Box(Gtk.Orientation.VERTICAL, 5);
@@ -81,15 +81,15 @@ public class FeedReader.SharePopover : Gtk.Popover {
{
addRow.add(addBox);
}
-
+
addRow.show_all();
m_list.add(addRow);
}
-
+
private void clicked(Gtk.ListBoxRow row)
{
ShareRow? shareRow = row as ShareRow;
-
+
if(shareRow == null)
{
this.hide();
@@ -97,10 +97,10 @@ public class FeedReader.SharePopover : Gtk.Popover {
Logger.debug("SharePopover: open Settings");
return;
}
-
+
string id = shareRow.getID();
Article? selectedArticle = ColumnView.get_default().getSelectedArticle();
-
+
if(selectedArticle != null)
{
var widget = Share.get_default().shareWidget(shareRow.getType(), selectedArticle.getURL());
@@ -121,14 +121,14 @@ public class FeedReader.SharePopover : Gtk.Popover {
});
}
}
-
+
}
-
+
private void shareInternal(string id, string url)
{
Share.get_default().addBookmark(id, url);
}
-
+
private void shareURL(string id, string url)
{
this.hide();
@@ -140,13 +140,13 @@ public class FeedReader.SharePopover : Gtk.Popover {
}
public class FeedReader.ShareForm : Gtk.Box {
-
+
public signal void share();
public signal void goBack();
-
+
public ShareForm()
{
-
+
}
-
+
}
diff --git a/src/Widgets/ShareRow.vala b/src/Widgets/ShareRow.vala
index 3a0bd686..b900f0f2 100644
--- a/src/Widgets/ShareRow.vala
+++ b/src/Widgets/ShareRow.vala
@@ -14,10 +14,10 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.ShareRow : Gtk.ListBoxRow {
-
+
private string m_id;
private string m_type;
-
+
public ShareRow(string type, string id, string username, string iconName)
{
m_id = id;
@@ -29,25 +29,25 @@ public class FeedReader.ShareRow : Gtk.ListBoxRow {
serviceLabel.set_ellipsize(Pango.EllipsizeMode.END);
serviceLabel.set_alignment(0.0f, 0.5f);
serviceLabel.get_style_context().add_class("h4");
-
+
var box = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 3);
box.margin = 3;
box.pack_start(icon, false, false, 8);
box.pack_start(serviceLabel, true, true, 0);
-
+
this.add(box);
this.margin = 2;
this.show_all();
}
-
+
public string getID()
{
return m_id;
}
-
+
public string getType()
{
return m_type;
}
-
+
}
diff --git a/src/Widgets/ShortcutsWindow.vala b/src/Widgets/ShortcutsWindow.vala
index 3b5e88fb..a74e61aa 100644
--- a/src/Widgets/ShortcutsWindow.vala
+++ b/src/Widgets/ShortcutsWindow.vala
@@ -14,10 +14,10 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.ShortcutsWindow : Gtk.ShortcutsWindow {
-
+
public ShortcutsWindow(Gtk.Window parent)
{
-
+
//--------------------------------------------------
var general = newGroup(_("General"));
//--------------------------------------------------
@@ -31,8 +31,8 @@ public class FeedReader.ShortcutsWindow : Gtk.ShortcutsWindow {
general.add(search);
general.add(quit);
//--------------------------------------------------
-
-
+
+
//--------------------------------------------------
var feedList = newGroup(_("Feed List"));
//--------------------------------------------------
@@ -48,8 +48,8 @@ public class FeedReader.ShortcutsWindow : Gtk.ShortcutsWindow {
feedList.add(expCol);
feedList.add(flmark);
//--------------------------------------------------
-
-
+
+
//--------------------------------------------------
var articleList = newGroup(_("Article List"));
//--------------------------------------------------
@@ -73,8 +73,8 @@ public class FeedReader.ShortcutsWindow : Gtk.ShortcutsWindow {
articleList.add(upDown);
articleList.add(centerSelected);
//--------------------------------------------------
-
-
+
+
//--------------------------------------------------
var articleView = newGroup(_("Article View"));
//--------------------------------------------------
@@ -84,8 +84,8 @@ public class FeedReader.ShortcutsWindow : Gtk.ShortcutsWindow {
var AVupdown = newShortcut(_("Scroll up/down"), AVupDown);
articleView.add(AVupdown);
//--------------------------------------------------
-
-
+
+
//--------------------------------------------------
var section = newSection("test", "section", 10);
//--------------------------------------------------
@@ -94,33 +94,33 @@ public class FeedReader.ShortcutsWindow : Gtk.ShortcutsWindow {
section.add(articleList);
section.add(articleView);
//--------------------------------------------------
-
-
+
+
this.add(section);
this.set_transient_for(parent);
this.set_modal(true);
this.show_all();
}
-
+
private Gtk.ShortcutsSection newSection(string title, string section_name, int maxHeight)
{
var section = (Gtk.ShortcutsSection)Object.new(typeof(Gtk.ShortcutsSection), title : title, section_name : section_name, max_height : maxHeight);
section.show();
return section;
}
-
+
private Gtk.ShortcutsGroup newGroup(string title)
{
var group = (Gtk.ShortcutsGroup)Object.new(typeof(Gtk.ShortcutsGroup), title : title);
group.show();
return group;
}
-
+
private Gtk.ShortcutsShortcut newShortcut(string title, string key)
{
var shortcut = (Gtk.ShortcutsShortcut)Object.new(typeof(Gtk.ShortcutsShortcut), title : title, accelerator : key);
shortcut.show();
return shortcut;
}
-
+
}
diff --git a/src/Widgets/SimpleHeader.vala b/src/Widgets/SimpleHeader.vala
index 78277584..9dac6efc 100644
--- a/src/Widgets/SimpleHeader.vala
+++ b/src/Widgets/SimpleHeader.vala
@@ -16,9 +16,9 @@
public class FeedReader.SimpleHeader : Gtk.HeaderBar
{
private Gtk.Button m_backButton;
-
+
public signal void back();
-
+
public SimpleHeader()
{
m_backButton = new Gtk.Button.from_icon_name("go-previous-symbolic");
@@ -26,15 +26,15 @@ public class FeedReader.SimpleHeader : Gtk.HeaderBar
m_backButton.clicked.connect(() => {
back();
});
-
+
this.pack_start(m_backButton);
this.show_close_button = true;
this.set_title("FeedReader");
}
-
+
public void showBackButton(bool show)
{
m_backButton.visible = show;
}
-
+
}
diff --git a/src/Widgets/SpringCleanPage.vala b/src/Widgets/SpringCleanPage.vala
index cb69d173..bfcd3ce6 100644
--- a/src/Widgets/SpringCleanPage.vala
+++ b/src/Widgets/SpringCleanPage.vala
@@ -14,17 +14,17 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.SpringCleanPage : Gtk.Bin {
-
+
private Gtk.Spinner m_spinner;
private Gtk.Box m_spinnerBox;
-
+
public SpringCleanPage() {
m_spinnerBox = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 20);
-
+
m_spinner = new Gtk.Spinner();
m_spinner.set_size_request(40, 40);
m_spinner.start();
-
+
var label = new Gtk.Label(_("FeedReader is cleaning the database.\nThis shouldn't take too long."));
label.get_style_context().add_class("h2");
label.set_alignment(0, 0.5f);
@@ -32,10 +32,10 @@ public class FeedReader.SpringCleanPage : Gtk.Bin {
label.set_line_wrap_mode(Pango.WrapMode.WORD_CHAR);
label.set_line_wrap(true);
label.set_lines(2);
-
+
m_spinnerBox.pack_start(m_spinner, false, false, 0);
m_spinnerBox.pack_end(label, false, false, 0);
-
+
this.set_halign(Gtk.Align.CENTER);
this.set_valign(Gtk.Align.CENTER);
this.margin = 20;
diff --git a/src/Widgets/TagPopover.vala b/src/Widgets/TagPopover.vala
index 82f5ffe8..ccb31c17 100644
--- a/src/Widgets/TagPopover.vala
+++ b/src/Widgets/TagPopover.vala
@@ -14,7 +14,7 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.TagPopover : Gtk.Popover {
-
+
private Gtk.ListBox m_list;
private Gtk.Box m_box;
private Gtk.Viewport m_viewport;
@@ -23,7 +23,7 @@ public class FeedReader.TagPopover : Gtk.Popover {
private Gee.List<Tag> m_tags;
private Gtk.EntryCompletion m_complete;
private Gee.List<Tag> m_availableTags;
-
+
public TagPopover(Gtk.Widget widget)
{
m_availableTags = new Gee.ArrayList<Tag>();
@@ -45,23 +45,23 @@ public class FeedReader.TagPopover : Gtk.Popover {
}
}
}
-
+
m_stack = new Gtk.Stack();
m_stack.set_transition_type(Gtk.StackTransitionType.NONE);
m_stack.set_transition_duration(0);
-
+
var empty_label = new Gtk.Label(_("Add Tag:"));
empty_label.get_style_context().add_class("h4");
empty_label.set_alignment(0, 0.5f);
m_stack.add_named(empty_label, "empty");
-
+
m_list = new Gtk.ListBox();
m_list.margin = 2;
m_list.set_size_request(150, 0);
m_list.set_selection_mode(Gtk.SelectionMode.NONE);
m_box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
m_box.margin = 10;
-
+
var tag_label = new Gtk.Label(_("Tags:"));
tag_label.get_style_context().add_class("h4");
tag_label.set_alignment(0, 0.5f);
@@ -73,20 +73,20 @@ public class FeedReader.TagPopover : Gtk.Popover {
box.pack_start(tag_label);
box.pack_start(m_viewport);
m_stack.add_named(box, "tags");
-
-
+
+
setupEntry();
populateList();
-
-
+
+
m_box.pack_start(m_stack);
m_box.pack_start(m_entry);
-
+
this.add(m_box);
this.set_relative_to(widget);
this.set_position(Gtk.PositionType.BOTTOM);
this.show_all();
-
+
if(m_tags.size == 0)
{
m_stack.set_visible_child_name("empty");
@@ -96,8 +96,8 @@ public class FeedReader.TagPopover : Gtk.Popover {
m_stack.set_visible_child_name("tags");
}
}
-
-
+
+
private void populateList()
{
foreach(Tag t in m_tags)
@@ -107,23 +107,23 @@ public class FeedReader.TagPopover : Gtk.Popover {
m_list.add(row);
}
}
-
+
private void prepareCompletion()
{
m_complete = new Gtk.EntryCompletion();
m_entry.set_completion(m_complete);
-
+
Gtk.ListStore list_store = new Gtk.ListStore(1, typeof (string));
m_complete.set_model(list_store);
m_complete.set_text_column(0);
Gtk.TreeIter iter;
-
+
var tags = DataBase.readOnly().read_tags();
-
+
foreach(Tag tag in tags)
{
bool alreadyHasTag = false;
-
+
foreach(Tag tag2 in m_tags)
{
if(tag2.getTitle() == tag.getTitle())
@@ -131,7 +131,7 @@ public class FeedReader.TagPopover : Gtk.Popover {
alreadyHasTag = true;
}
}
-
+
if(!alreadyHasTag)
{
list_store.append(out iter);
@@ -140,7 +140,7 @@ public class FeedReader.TagPopover : Gtk.Popover {
}
}
}
-
+
private void setupEntry()
{
m_entry = new Gtk.Entry();
@@ -161,7 +161,7 @@ public class FeedReader.TagPopover : Gtk.Popover {
}
bool available = false;
Tag? selectedTag = null;
-
+
foreach(Tag tag in m_tags)
{
if(str == tag.getTitle())
@@ -171,7 +171,7 @@ public class FeedReader.TagPopover : Gtk.Popover {
return;
}
}
-
+
foreach(Tag tag in m_availableTags)
{
if(str == tag.getTitle())
@@ -182,30 +182,30 @@ public class FeedReader.TagPopover : Gtk.Popover {
break;
}
}
-
+
if(!available)
{
selectedTag = FeedReaderBackend.get_default().createTag(str);
Logger.debug("TagPopover: %s created with id %s".printf(str, selectedTag.getTagID()));
}
FeedReaderBackend.get_default().tagArticle(getActiveArticleID(), selectedTag, true);
-
-
+
+
var row = new TagPopoverRow(selectedTag);
row.remove_tag.connect(removeTag);
m_list.add(row);
m_stack.set_visible_child_name("tags");
m_entry.set_text("");
});
-
+
prepareCompletion();
}
-
+
private void removeTag(TagPopoverRow row)
{
FeedReaderBackend.get_default().tagArticle(getActiveArticleID(), row.getTag(), false);
m_list.remove(row);
-
+
foreach(Tag tag in m_tags)
{
if(tag.getTagID() == row.getTagID())
@@ -214,24 +214,24 @@ public class FeedReader.TagPopover : Gtk.Popover {
break;
}
}
-
+
if(m_list.get_children().length() == 0)
{
m_stack.set_visible_child_name("empty");
this.show_all();
}
-
+
ColumnView.get_default().removeTagFromSelectedRow(row.getTagID());
}
-
+
private Article getActiveArticleID()
{
return ColumnView.get_default().getSelectedArticle();
}
-
+
public bool entryFocused()
{
return m_entry.has_focus;
}
-
+
}
diff --git a/src/Widgets/TagPopoverRow.vala b/src/Widgets/TagPopoverRow.vala
index b41bd006..4b659f8d 100644
--- a/src/Widgets/TagPopoverRow.vala
+++ b/src/Widgets/TagPopoverRow.vala
@@ -14,14 +14,14 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.TagPopoverRow : Gtk.ListBoxRow {
-
+
private Gtk.Revealer m_revealer;
private Gtk.Box m_box;
private Tag m_tag;
private Gtk.Image m_clear;
private Gtk.EventBox m_eventbox;
public signal void remove_tag(TagPopoverRow row);
-
+
public TagPopoverRow(Tag tag)
{
m_tag = tag;
@@ -34,7 +34,7 @@ public class FeedReader.TagPopoverRow : Gtk.ListBoxRow {
m_clear = new Gtk.Image.from_icon_name("edit-clear-symbolic", Gtk.IconSize.MENU);
m_clear.margin_end = 5;
m_clear.opacity = 0.7;
-
+
m_eventbox = new Gtk.EventBox();
m_eventbox.set_events(Gdk.EventMask.ENTER_NOTIFY_MASK);
m_eventbox.set_events(Gdk.EventMask.LEAVE_NOTIFY_MASK);
@@ -43,47 +43,47 @@ public class FeedReader.TagPopoverRow : Gtk.ListBoxRow {
m_eventbox.leave_notify_event.connect(onLeave);
m_eventbox.button_press_event.connect(onClick);
m_eventbox.add(m_clear);
-
+
m_box.pack_start(circle, false, false, 0);
m_box.pack_start(label, true, true, 0);
m_box.pack_end(m_eventbox, false, false, 0);
-
+
m_revealer = new Gtk.Revealer();
m_revealer.set_transition_type(Gtk.RevealerTransitionType.SLIDE_DOWN);
m_revealer.set_transition_duration(150);
m_revealer.add(m_box);
m_revealer.set_reveal_child(true);
-
+
this.add(m_revealer);
this.margin_top = 1;
this.margin_bottom = 1;
this.show_all();
}
-
+
private bool onEnter()
{
m_clear.opacity = 1.0;
return false;
}
-
+
private bool onLeave()
{
m_clear.opacity = 0.7;
return false;
}
-
+
private bool onClick()
{
m_revealer.set_reveal_child(false);
remove_tag(this);
return false;
}
-
+
public string getTagID()
{
return m_tag.getTagID();
}
-
+
public Tag getTag()
{
return m_tag;
diff --git a/src/Widgets/TagRow.vala b/src/Widgets/TagRow.vala
index d3ed59d1..4a823f11 100644
--- a/src/Widgets/TagRow.vala
+++ b/src/Widgets/TagRow.vala
@@ -14,7 +14,7 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.TagRow : Gtk.ListBoxRow {
-
+
private Gtk.Box m_box;
private Gtk.Label m_label;
private bool m_exits;
@@ -27,7 +27,7 @@ public class FeedReader.TagRow : Gtk.ListBoxRow {
public Tag m_tag;
public signal void moveUP();
public signal void removeRow();
-
+
public TagRow (Tag tag)
{
m_tag = tag;
@@ -35,92 +35,92 @@ public class FeedReader.TagRow : Gtk.ListBoxRow {
m_exits = true;
m_name = m_tag.getTitle().replace("&","&amp;");
m_catID = CategoryID.TAGS.to_string();
-
+
var rowhight = 30;
m_box = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 0);
-
+
m_circle = new ColorCircle(m_tag.getColor());
m_circle.margin_start = 24;
m_pop = new ColorPopover(m_circle);
-
+
m_circle.clicked.connect((color) => {
m_pop.show_all();
});
-
+
m_pop.newColorSelected.connect((color) => {
m_circle.newColor(color);
m_tag.setColor(color);
FeedReaderBackend.get_default().updateTagColor(m_tag);
});
-
+
m_label = new Gtk.Label(m_name);
m_label.set_use_markup (true);
m_label.set_size_request (0, rowhight);
m_label.set_ellipsize (Pango.EllipsizeMode.END);
m_label.set_alignment(0, 0.5f);
-
+
m_box.pack_start(m_circle, false, false, 8);
m_box.pack_start(m_label, true, true, 0);
-
+
m_revealer = new Gtk.Revealer();
m_revealer.set_transition_type(Gtk.RevealerTransitionType.SLIDE_DOWN);
m_revealer.add(m_box);
m_revealer.set_reveal_child(false);
-
+
m_eventBox = new Gtk.EventBox();
m_eventBox.set_events(Gdk.EventMask.BUTTON_PRESS_MASK);
m_eventBox.button_press_event.connect(onClick);
m_eventBox.add(m_revealer);
-
+
this.add(m_eventBox);
this.show_all();
-
+
if(Utils.canManipulateContent())
{
const Gtk.TargetEntry[] accepted_targets = {
{ "STRING", 0, DragTarget.TAG }
};
-
+
Gtk.drag_dest_set (
this,
Gtk.DestDefaults.MOTION,
accepted_targets,
Gdk.DragAction.COPY
);
-
+
this.drag_motion.connect(onDragMotion);
this.drag_leave.connect(onDragLeave);
this.drag_drop.connect(onDragDrop);
this.drag_data_received.connect(onDragDataReceived);
}
}
-
+
private bool onDragMotion(Gtk.Widget widget, Gdk.DragContext context, int x, int y, uint time)
{
this.set_state_flags(Gtk.StateFlags.PRELIGHT, false);
return false;
}
-
+
private void onDragLeave(Gtk.Widget widget, Gdk.DragContext context, uint time)
{
this.unset_state_flags(Gtk.StateFlags.PRELIGHT);
}
-
+
private bool onDragDrop(Gtk.Widget widget, Gdk.DragContext context, int x, int y, uint time)
{
// If the source offers a target
if(context.list_targets() != null)
{
var target_type = (Gdk.Atom)context.list_targets().nth_data(0);
-
+
// Request the data from the source.
Gtk.drag_get_data(widget, context, target_type, time);
return true;
}
-
+
return false;
}
-
+
private void onDragDataReceived(Gtk.Widget widget, Gdk.DragContext context, int x, int y,
Gtk.SelectionData selection_data, uint target_type, uint time)
{
@@ -131,7 +131,7 @@ public class FeedReader.TagRow : Gtk.ListBoxRow {
string articleID = (string)selection_data.get_data();
Article article = DataBase.readOnly().read_article(articleID);
Logger.debug(@"drag articleID: $articleID");
-
+
if(m_tag.getTagID() != TagID.NEW)
{
FeedReaderBackend.get_default().tagArticle(article, m_tag, true);
@@ -143,7 +143,7 @@ public class FeedReader.TagRow : Gtk.ListBoxRow {
}
}
}
-
+
private bool onClick(Gdk.EventButton event)
{
// only right click allowed
@@ -151,12 +151,12 @@ public class FeedReader.TagRow : Gtk.ListBoxRow {
{
return false;
}
-
+
if(!Utils.canManipulateContent())
{
return false;
}
-
+
switch(event.type)
{
case Gdk.EventType.BUTTON_RELEASE:
@@ -164,17 +164,17 @@ public class FeedReader.TagRow : Gtk.ListBoxRow {
case Gdk.EventType.@3BUTTON_PRESS:
return false;
}
-
+
var remove_action = new GLib.SimpleAction("deleteTag", null);
remove_action.activate.connect(() => {
if(this.is_selected())
{
moveUP();
}
-
+
uint time = 300;
this.reveal(false, time);
-
+
string text = _("Tag \"%s\" removed").printf(m_name);
var notification = MainWindow.get_default().showNotification(text);
ulong eventID = notification.dismissed.connect(() => {
@@ -191,15 +191,15 @@ public class FeedReader.TagRow : Gtk.ListBoxRow {
rename_action.activate.connect(() => {
showRenamePopover();
});
-
+
var app = FeedReaderApp.get_default();
app.add_action(rename_action);
app.add_action(remove_action);
-
+
var menu = new GLib.Menu();
menu.append(_("Rename"), "renameTag");
menu.append(_("Remove"), "deleteTag");
-
+
var pop = new Gtk.Popover(this);
pop.set_position(Gtk.PositionType.BOTTOM);
pop.bind_model(menu, "app");
@@ -208,42 +208,42 @@ public class FeedReader.TagRow : Gtk.ListBoxRow {
});
pop.show();
this.set_state_flags(Gtk.StateFlags.PRELIGHT, false);
-
+
return true;
}
-
+
public void update(string name)
{
m_label.set_text(name.replace("&","&amp;"));
m_label.set_use_markup (true);
}
-
+
public Tag getTag()
{
return m_tag;
}
-
+
public void setExits(bool subscribed)
{
m_exits = subscribed;
}
-
+
public bool stillExits()
{
return m_exits;
}
-
+
public bool isRevealed()
{
return m_revealer.get_reveal_child();
}
-
+
public void reveal(bool reveal, uint duration = 500)
{
m_revealer.set_transition_duration(duration);
m_revealer.set_reveal_child(reveal);
}
-
+
private void showRenamePopover(Gdk.DragContext? context = null, uint time = 0, Article? article = null)
{
var popRename = new Gtk.Popover(this);
@@ -256,7 +256,7 @@ public class FeedReader.TagRow : Gtk.ListBoxRow {
Gtk.drag_finish(context, false, false, time);
}
});
-
+
var renameEntry = new Gtk.Entry();
renameEntry.set_text(m_name);
renameEntry.activate.connect(() => {
@@ -273,28 +273,28 @@ public class FeedReader.TagRow : Gtk.ListBoxRow {
Gtk.drag_finish(context, true, false, time);
}
});
-
-
+
+
string label = _("rename");
if(m_tag.getTagID() == TagID.NEW && context != null)
{
label = _("add");
}
-
+
var renameButton = new Gtk.Button.with_label(label);
renameButton.get_style_context().add_class("suggested-action");
renameButton.clicked.connect(() => {
renameEntry.activate();
});
-
+
var renameBox = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 5);
renameBox.margin = 5;
renameBox.pack_start(renameEntry, true, true, 0);
renameBox.pack_start(renameButton, false, false, 0);
-
+
popRename.add(renameBox);
popRename.show_all();
this.set_state_flags(Gtk.StateFlags.PRELIGHT, false);
}
-
+
}
diff --git a/src/Widgets/UpdateButton.vala b/src/Widgets/UpdateButton.vala
index 3f93d58f..1b40c35f 100644
--- a/src/Widgets/UpdateButton.vala
+++ b/src/Widgets/UpdateButton.vala
@@ -14,7 +14,7 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.UpdateButton : Gtk.Button {
-
+
private Gtk.Image m_icon;
private Gtk.Spinner m_spinner;
private bool m_status;
@@ -24,19 +24,19 @@ public class FeedReader.UpdateButton : Gtk.Button {
private bool m_isCancellable;
private Gtk.Popover m_Popover;
private string m_tooltip;
-
+
public UpdateButton.from_icon_name(string iconname, string tooltip, bool progressPopup = false, bool cancellable = false)
{
m_icon = new Gtk.Image.from_icon_name(iconname, Gtk.IconSize.SMALL_TOOLBAR);
setup(tooltip, cancellable, progressPopup);
}
-
+
public UpdateButton.from_resource(string iconname, string tooltip, bool progressPopup = false, bool cancellable = false)
{
m_icon = new Gtk.Image.from_resource(iconname);
setup(tooltip, cancellable, progressPopup);
}
-
+
private void setup(string tooltip, bool progressPopup, bool cancellable)
{
m_hasPopup = progressPopup;
@@ -44,13 +44,13 @@ public class FeedReader.UpdateButton : Gtk.Button {
m_tooltip = tooltip;
m_spinner = new Gtk.Spinner();
m_spinner.set_size_request(16,16);
-
+
m_stack = new Gtk.Stack();
m_stack.set_transition_duration(100);
m_stack.set_transition_type(Gtk.StackTransitionType.CROSSFADE);
m_stack.add_named(m_spinner, "spinner");
m_stack.add_named(m_icon, "icon");
-
+
if(m_hasPopup)
{
m_ProgressText = new Gtk.Label(Settings.state().get_string("sync-status"));
@@ -59,7 +59,7 @@ public class FeedReader.UpdateButton : Gtk.Button {
m_Popover.add(m_ProgressText);
this.button_press_event.connect(onClick);
}
-
+
this.add(m_stack);
this.set_relief(Gtk.ReliefStyle.NONE);
this.set_events(Gdk.EventMask.ENTER_NOTIFY_MASK);
@@ -67,7 +67,7 @@ public class FeedReader.UpdateButton : Gtk.Button {
this.set_tooltip_text(tooltip);
this.show_all();
}
-
+
public void updating(bool status, bool insensitive = true)
{
Logger.debug("UpdateButton: update status");
@@ -90,19 +90,19 @@ public class FeedReader.UpdateButton : Gtk.Button {
m_spinner.stop();
}
}
-
+
public bool getStatus()
{
return m_status;
}
-
+
public void setSensitive(bool sensitive)
{
// FIXME: dont set sensitive if canceling
Logger.debug("UpdateButton: setSensitive %s".printf(sensitive ? "true" : "false"));
this.sensitive = sensitive;
}
-
+
public void setProgress(string text)
{
if(m_hasPopup)
@@ -110,26 +110,26 @@ public class FeedReader.UpdateButton : Gtk.Button {
m_ProgressText.set_text(text);
}
}
-
+
private bool onClick(Gdk.EventButton event)
{
if(event.button != 3)
{
return false;
}
-
+
if(m_status && !m_Popover.get_visible())
{
m_Popover.show_all();
return true;
}
-
+
return false;
}
-
+
public void setIcon(Gtk.Image icon)
{
m_icon = icon;
}
-
+
}
diff --git a/src/Widgets/WebLoginPage.vala b/src/Widgets/WebLoginPage.vala
index f5cb8055..d0068938 100644
--- a/src/Widgets/WebLoginPage.vala
+++ b/src/Widgets/WebLoginPage.vala
@@ -14,13 +14,13 @@
// along with FeedReader. If not, see <http://www.gnu.org/licenses/>.
public class FeedReader.WebLoginPage : Gtk.Bin {
-
+
private WebKit.WebView m_view;
private bool m_success = false;
public signal bool getApiCode(string url);
public signal void success();
-
-
+
+
public WebLoginPage()
{
var settings = new WebKit.Settings();
@@ -32,14 +32,14 @@ public class FeedReader.WebLoginPage : Gtk.Bin {
this.add(m_view);
this.show_all();
}
-
-
+
+
public void loadPage(string url)
{
Logger.debug("WebLoginPage: load URL: " + url);
m_view.load_uri(url);
}
-
+
public void redirection(WebKit.LoadEvent load_event)
{
switch(load_event)
@@ -56,7 +56,7 @@ public class FeedReader.WebLoginPage : Gtk.Bin {
break;
}
}
-
+
private void check()
{
if(m_success)
@@ -64,18 +64,18 @@ public class FeedReader.WebLoginPage : Gtk.Bin {
// code already successfully extracted
return;
}
-
+
string url = m_view.get_uri();
-
+
if(getApiCode(url))
{
m_view.stop_loading();
m_success = true;
success();
-
+
}
}
-
+
public void reset()
{
m_view.load_uri("about:blank");