# HG changeset patch # User Dirk Olmes # Date 1314427923 -7200 # Node ID a05719a6175e8df0ee81a6b58fc35428b27066a9 # Parent 2682db280be0e5bcfa62be65641d41d75bc8c29f move common functionality into an abstract backend class, have both backends inherit from it. Implement enough of the couchdb backend that reading feeds (and marking feed entries as read) is possible diff -r 2682db280be0 -r a05719a6175e MainWindow.py --- a/MainWindow.py Sat Aug 27 07:32:01 2011 +0200 +++ b/MainWindow.py Sat Aug 27 08:52:03 2011 +0200 @@ -74,10 +74,9 @@ self.ui.actionOpenLink.setEnabled(True) row = index.row() - feedEntry = self.backend.selectFeedEntry(row) + self.backend.selectFeedEntry(row) - # TODO this is not compatible with the couchdb backend - if feedEntry.feed.auto_load_entry_link: + if self.backend.selectedFeed.auto_load_entry_link: self.openLinkFromSelectedEntry() else: self.openSummaryFromSelectedEntry() @@ -93,9 +92,7 @@ self.ui.webView.setHtml(feedEntry.summary, baseUrl) def openLinkFromSelectedEntry(self): - feedEntry = self.backend.selectedFeedEntry - # TODO this is not compatible with the couchdb backend - if feedEntry.feed.always_open_in_browser: + if self.backend.selectedFeed.always_open_in_browser: self.openSelectedEntryInBrowser() else: self.openSelectedEntryInWebView() diff -r 2682db280be0 -r a05719a6175e backend/AbstractBackend.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/backend/AbstractBackend.py Sat Aug 27 08:52:03 2011 +0200 @@ -0,0 +1,34 @@ + +class AbstractBackend(object): + def __init__(self): + self.feeds = [] + self.selectedFeed = None + self.feedEntries = None + self.selectedFeedEntry = None + + def dispose(self): + pass + + # + # handling of feeds + # + + def selectFeed(self, index): + self.selectedFeed = self.feeds[index] + self.feedEntries = None + return self.selectedFeed + + def entriesForSelectedFeed(self): + if self.feedEntries is None: + hideReadEntries = self.preferences().hideReadFeedEntries() + self.feedEntries = self._retrieveEntriesForSelectedFeed(hideReadEntries) + return self.feedEntries + + # + # handling of the selected feed entry + # + + def selectFeedEntry(self, index): + self.selectedFeedEntry = self.feedEntries[index] + self._markSelectedFeedEntryRead() + return self.selectedFeedEntry diff -r 2682db280be0 -r a05719a6175e backend/couchdb/CouchDbBackend.py --- a/backend/couchdb/CouchDbBackend.py Sat Aug 27 07:32:01 2011 +0200 +++ b/backend/couchdb/CouchDbBackend.py Sat Aug 27 08:52:03 2011 +0200 @@ -1,14 +1,14 @@ from FeedUpdater import FeedUpdater from Preferences import Preferences +from backend.AbstractBackend import AbstractBackend from backend.couchdb.Feed import Feed from backend.couchdb.FeedEntry import FeedEntry import couchdb - DATABASE = "feedtest" -class CouchDbBackend(object): +class CouchDbBackend(AbstractBackend): ''' Backend that uses CouchDB for persistence ''' @@ -20,17 +20,43 @@ def preferences(self): return Preferences(self.database) + # + # handling of feeds + # + def getFeeds(self): if self.preferences().showOnlyUnreadFeeds(): - return self._getUnreadFeeds() + self.feeds = self._getUnreadFeeds() else: # make sure that the results are actually fetched into memory, otherwise we'll pass # a ViewResults instance around which is not what we want - return list(Feed.all(self.database)) + self.feeds = list(Feed.all(self.database)) + return self.feeds def _getUnreadFeeds(self): raise Exception("not yet implemented") + def _retrieveEntriesForSelectedFeed(self, hideReadEntries): + # TODO how to hide read entries if requested? + viewResults = FeedEntry.view(self.database, "feedtest/feedEntries_by_feed", + key=self.selectedFeed.id) + return list(viewResults) + + def markSelectedFeedAsRead(self): + for feedEntry in self.entriesForSelectedFeed(): + feedEntry.markRead(self.database) + + # + # handling of the selected feed entry + # + + def _markSelectedFeedEntryRead(self): + self.selectedFeedEntry.markRead(self.database) + + def toggleSelectedFeedEntryRead(self): + self.selectedFeedEntry.toggleRead(self.database) + + def toggleRead(self, feedEntry): raise Exception("not yet implemented") @@ -52,8 +78,10 @@ viewName = "feedtest/unread_feedEntries_by_feed" return list(FeedEntry.view(self.database, viewName)) - def markFeedEntriesAsRead(self, entries): - raise Exception("not yet implemented") + def markFeedEntriesAsRead(self, indices): + for index in indices: + feedEntry = self.entriesForSelectedFeed()[index] + feedEntry.markRead(self.database) def updateAllFeeds(self): # TODO use a view instead of iterating all feeds @@ -66,6 +94,3 @@ print("Expiring feeds is not yet implemented") # raise Exception("not yet implemented") - def dispose(self): - # nothing to do here - pass diff -r 2682db280be0 -r a05719a6175e backend/couchdb/FeedEntry.py --- a/backend/couchdb/FeedEntry.py Sat Aug 27 07:32:01 2011 +0200 +++ b/backend/couchdb/FeedEntry.py Sat Aug 27 08:52:03 2011 +0200 @@ -22,3 +22,14 @@ # return None return None + def markRead(self, database): + self.read = True + self.store(database) + + def toggleRead(self, database): + if self.read: + self.read = False + else: + self.read = True + self.store(database) + diff -r 2682db280be0 -r a05719a6175e backend/sqlalchemy/SqlAlchemyBackend.py --- a/backend/sqlalchemy/SqlAlchemyBackend.py Sat Aug 27 07:32:01 2011 +0200 +++ b/backend/sqlalchemy/SqlAlchemyBackend.py Sat Aug 27 08:52:03 2011 +0200 @@ -2,6 +2,7 @@ from Feed import Feed from FeedEntry import FeedEntry from Preferences import Preferences +from backend.AbstractBackend import AbstractBackend from datetime import datetime, timedelta from sqlalchemy.orm import joinedload from sqlalchemy.sql import and_ @@ -11,20 +12,17 @@ import logging import util -class SqlAlchemyBackend(object): +class SqlAlchemyBackend(AbstractBackend): ''' Backend that uses sqlalchemy for persistence ''' def __init__(self): + AbstractBackend.__init__(self) self._initLogging() self.session = Database.createSession() self.prefs = Preferences(self.session) self.updater = None - self.feeds = [] - self.selectedFeed = None - self.feedEntries = None - self.selectedFeedEntry = None def _initLogging(self): logging.getLogger("sqlalchemy.orm").setLevel(logging.WARN) @@ -64,16 +62,8 @@ uniqueFeeds = set(feeds) return list(uniqueFeeds) - def selectFeed(self, index): - self.selectedFeed = self.feeds[index] - self.feedEntries = None - return self.selectedFeed - - def entriesForSelectedFeed(self): - hideReadEntries = self.prefs.hideReadFeedEntries() - if self.feedEntries is None: - self.feedEntries = self.selectedFeed.entriesSortedByUpdateDate(hideReadEntries) - return self.feedEntries + def _retrieveEntriesForSelectedFeed(self, hideReadEntries): + return self.selectedFeed.entriesSortedByUpdateDate(hideReadEntries) def markSelectedFeedAsRead(self): self.selectedFeed.markAllEntriesRead() @@ -103,10 +93,9 @@ # # handling of the selected feed entry # - def selectFeedEntry(self, index): - self.selectedFeedEntry = self.feedEntries[index] + + def _markSelectedFeedEntryRead(self): self.selectedFeedEntry.markRead() - return self.selectedFeedEntry def markFeedEntriesAsRead(self, indices): for index in indices: @@ -117,7 +106,6 @@ self.selectedFeedEntry.toggleRead() self.session.commit() - def expireFeedEntries(self): logger = logging.getLogger("feedupdater") expireDate = self._calculateExpireDate()