* Fixed some format upgrade issues
authorYves Marcoz <yves@marcoz.org>
Fri, 16 Jul 2010 16:11:26 +0000 (09:11 -0700)
committerYves Marcoz <yves@marcoz.org>
Fri, 16 Jul 2010 16:11:26 +0000 (09:11 -0700)
* New widget with improved functionality

src/FeedingIt.py
src/feedingit_widget.py
src/feedingitdbus.py
src/rss_sqlite.py
src/update_feeds.py

index 9fde1f5..2e53a52 100644 (file)
@@ -780,7 +780,7 @@ class DisplayFeed(hildon.StackableWindow):
     def buttonPurgeArticles(self, *widget):
         self.clear()
         self.feed.purgeReadArticles()
-        self.feed.saveFeed(CONFIGDIR)
+        #self.feed.saveFeed(CONFIGDIR)
         self.displayFeed()
 
     def destroyArticle(self, handle):
@@ -821,7 +821,7 @@ class DisplayFeed(hildon.StackableWindow):
     def onArticleDeleted(self, object, index):
         self.clear()
         self.feed.removeArticle(index)
-        self.feed.saveFeed(CONFIGDIR)
+        #self.feed.saveFeed(CONFIGDIR)
         self.displayFeed()
 
     def button_update_clicked(self, button):
@@ -842,9 +842,19 @@ class DisplayFeed(hildon.StackableWindow):
         self.updateDbusHandler.ArticleCountUpdated()
         
     def buttonReadAllClicked(self, button):
-        for index in self.feed.getIds():
-            self.feed.setEntryRead(index)
-            self.mark_item_read(index)
+        #self.clear()
+        self.feed.markAllAsRead()
+        it = self.feedItems.get_iter_first()
+        while it is not None:
+            k = self.feedItems.get_value(it, FEED_COLUMN_KEY)
+            title = self.fix_title(self.feed.getTitle(k))
+            markup = ENTRY_TEMPLATE % (self.config.getFontSize(), title)
+            self.feedItems.set_value(it, FEED_COLUMN_MARKUP, markup)
+            it = self.feedItems.iter_next(it)
+        #self.displayFeed()
+        #for index in self.feed.getIds():
+        #    self.feed.setEntryRead(index)
+        #    self.mark_item_read(index)
 
 
 class FeedingIt:
@@ -974,8 +984,9 @@ class FeedingIt:
     def button_markAll(self, button):
         for key in self.listing.getListOfFeeds():
             feed = self.listing.getFeed(key)
-            for id in feed.getIds():
-                feed.setEntryRead(id)
+            feed.markAllAsRead()
+            #for id in feed.getIds():
+            #    feed.setEntryRead(id)
             self.listing.updateUnread(key)
         self.displayListing()
 
@@ -1093,6 +1104,19 @@ class FeedingIt:
                         self.listing.getFeedTitle(key), key, \
                         self.config, self.updateDbusHandler)
                 self.disp.connect("feed-closed", self.onFeedClosed)
+                
+    def openArticle(self, key, id):
+        try:
+            self.feed_lock
+        except:
+            # If feed_lock doesn't exist, we can open the feed, else we do nothing
+            if key != None:
+                self.feed_lock = get_lock(key)
+                self.disp = DisplayFeed(self.listing, self.listing.getFeed(key), \
+                        self.listing.getFeedTitle(key), key, \
+                        self.config, self.updateDbusHandler)
+                self.disp.button_clicked(None, id)
+                self.disp.connect("feed-closed", self.onFeedClosed)
         
 
     def onFeedClosed(self, object, key):
index f6ca85c..73ed135 100644 (file)
 # ============================================================================
 #import sys
 
+import sqlite3
+from re import sub
+from htmlentitydefs import name2codepoint
+
 import gtk, pickle, gobject, dbus
 import hildondesktop, hildon
 #from rss import Listing
@@ -37,6 +41,7 @@ dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
 from os import environ, remove
 bus = dbus.bus.BusConnection(environ["DBUS_SESSION_BUS_ADDRESS"])
 from os.path import isfile
+from cgi import escape
 
 settings = gtk.settings_get_default()
 color_style = gtk.rc_get_style_by_paths( settings, 'GtkButton', 'osso-logical-colors', gtk.Button)
@@ -61,6 +66,31 @@ def get_font_desc(logicalfontname):
     font_desc = font_style.font_desc
     return font_desc
 
+def unescape(text):
+    def fixup(m):
+        text = m.group(0)
+        if text[:2] == "&#":
+            # character reference
+            try:
+                if text[:3] == "&#x":
+                    return unichr(int(text[3:-1], 16))
+                else:
+                    return unichr(int(text[2:-1]))
+            except ValueError:
+                pass
+        else:
+            # named entity
+            try:
+                text = unichr(name2codepoint[text[1:-1]])
+            except KeyError:
+                pass
+        return text # leave as is
+    return sub("&#?\w+;", fixup, text)
+
+def fix_title(title):
+    return escape(unescape(title).replace("<em>","").replace("</em>","").replace("<nobr>","").replace("</nobr>","").replace("<wbr>",""))
+
+
 class FeedingItHomePlugin(hildondesktop.HomePluginItem):
     def __init__(self):
       __gsignals__ = {
@@ -73,6 +103,9 @@ class FeedingItHomePlugin(hildondesktop.HomePluginItem):
         self.connect("show-settings", self.show_settings)
         self.feed_list = {}
         self.total = 0
+        self.status = 0 # 0=Showing feeds, 1=showing articles
+        self.updateStatus = 0 # 0=Not updating, 1=Update in progress
+        self.pageStatus = 0
         if isfile(SOURCE):
             file = open(SOURCE)
             self.autoupdateId = int(file.read())
@@ -82,26 +115,47 @@ class FeedingItHomePlugin(hildondesktop.HomePluginItem):
         
         vbox = gtk.VBox(False, 0)
         
+        ## Prepare the main HBox
+        self.hbox1 = gtk.HBox(False, 0)
         #self.button = gtk.Button()
-        self.button = hildon.Button(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
-        self.button.set_text("FeedingIt","")
-        self.button.set_sensitive(False)
-        self.label1 = self.button.child.child.get_children()[0].get_children()[0]
-        self.label2 = self.button.child.child.get_children()[0].get_children()[1]
-        self.label1.modify_fg(gtk.STATE_INSENSITIVE, default_color)
-        self.label1.modify_font(font_desc)
-        self.label2.modify_fg(gtk.STATE_INSENSITIVE, active_color)
+        self.buttonApp = hildon.Button(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
+        #self.buttonApp.set_text("FeedingIt","")
+        #self.button.set_sensitive(False)
+        #self.label1 = self.buttonApp.child.child.get_children()[0].get_children()[0]
+        #self.label2 = self.button.child.child.get_children()[0].get_children()[1]
+        #self.label1.modify_fg(gtk.STATE_INSENSITIVE, default_color)
+        #self.label1.modify_font(font_desc)
+        #self.label2.modify_fg(gtk.STATE_INSENSITIVE, active_color)
         icon_theme = gtk.icon_theme_get_default()
-        pixbuf = icon_theme.load_icon("feedingit", 32, gtk.ICON_LOOKUP_USE_BUILTIN )
+        pixbuf = icon_theme.load_icon("feedingit", 20, gtk.ICON_LOOKUP_USE_BUILTIN )
         image = gtk.Image()
         image.set_from_pixbuf(pixbuf)
-        self.button.set_image(image)
-        self.button.set_image_position(gtk.POS_LEFT)
-
+        self.buttonApp.set_image(image)
+        self.buttonApp.set_image_position(gtk.POS_RIGHT)
         #button = gtk.Button("Update")
-        self.button.connect("clicked", self.button_clicked)
+        self.buttonApp.connect("clicked", self.button_clicked)
+        
+        self.buttonUpdate = hildon.Button(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
+        self.buttonUpdate.set_image(gtk.image_new_from_icon_name('general_refresh', gtk.ICON_SIZE_BUTTON))
+        self.buttonUpdate.connect("clicked", self.buttonUpdate_clicked)
+        
+        self.buttonUp = hildon.Button(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
+        self.buttonUp.set_image(gtk.image_new_from_icon_name('keyboard_move_up', gtk.ICON_SIZE_BUTTON))
+        self.buttonUp.set_sensitive(False)
+        self.buttonUp.connect("clicked", self.buttonUp_clicked)
+        
+        self.buttonDown = hildon.Button(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
+        self.buttonDown.set_image(gtk.image_new_from_icon_name('keyboard_move_down', gtk.ICON_SIZE_BUTTON))
+        self.buttonDown.set_sensitive(False)
+        self.buttonDown.connect("clicked", self.buttonDown_clicked)
+        
+        self.hbox1.pack_start(self.buttonUpdate, expand=False)
+        self.hbox1.pack_start(self.buttonDown, expand=False)
+        self.hbox1.pack_start(self.buttonUp, expand=False)
+        self.hbox1.pack_start(self.buttonApp, expand=False)
+        
         #button.show_all()
-        vbox.pack_start(self.button, expand=False)        
+               
         
         #for feed in ["Slashdot", "Engadget", "Cheez"]:
         #    self.treestore.append([feed, "0"])
@@ -109,16 +163,18 @@ class FeedingItHomePlugin(hildondesktop.HomePluginItem):
         self.update_list()
         name_renderer = gtk.CellRendererText()
         name_renderer.set_property("font-desc", font_desc)
-        unread_renderer = gtk.CellRendererText()
-        unread_renderer.set_property("font-desc", font_desc)        
+        self.unread_renderer = gtk.CellRendererText()
+        self.unread_renderer.set_property("font-desc", font_desc)
+        self.unread_renderer.set_property("xalign", 1.0)
         self.treeview.append_column(gtk.TreeViewColumn('Feed Name', name_renderer, text = 0))
-        self.treeview.append_column(gtk.TreeViewColumn('Unread Items', unread_renderer, text = 1))
+        self.treeview.append_column(gtk.TreeViewColumn('Unread Items', self.unread_renderer, text = 1))
         #selection = self.treeview.get_selection()
         #selection.set_mode(gtk.SELECTION_NONE)
         #self.treeview.get_selection().set_mode(gtk.SELECTION_NONE)
         #hildon.hildon_gtk_tree_view_set_ui_mode(self.treeview, gtk.HILDON_UI_MODE_NORMAL)
         
         vbox.pack_start(self.treeview)
+        vbox.pack_start(self.hbox1, expand=False) 
         
         self.add(vbox)
         self.treeview.connect("hildon-row-tapped", self.row_activated)
@@ -145,71 +201,134 @@ class FeedingItHomePlugin(hildondesktop.HomePluginItem):
         #file.close()
 
     def button_clicked(self, *widget):
-        self.button.set_sensitive(False)
-        self.label1.modify_fg(gtk.STATE_NORMAL, default_color)
-        self.label2.modify_fg(gtk.STATE_NORMAL, active_color)
-        self.update_label("Stopping")
+        #self.button.set_sensitive(False)
+        #self.label1.modify_fg(gtk.STATE_NORMAL, default_color)
+        #self.label2.modify_fg(gtk.STATE_NORMAL, active_color)
+        #self.update_label("Stopping")
+        if self.status == 0:
+            remote_object = bus.get_object("org.maemo.feedingit", # Connection name
+                                   "/org/maemo/feedingit" # Object's path
+                                  )
+            iface = dbus.Interface(remote_object, 'org.maemo.feedingit')
+        else:
+            self.status = 0
+            self.pageStatus = 0
+            self.buttonUp.set_sensitive(False)
+            self.buttonDown.set_sensitive(False)
+            self.treeview.append_column(gtk.TreeViewColumn('Unread Items', self.unread_renderer, text = 1))
+            self.update_list()
+        #iface.StopUpdate()
+        
+    def buttonUpdate_clicked(self, *widget):
         remote_object = bus.get_object("org.marcoz.feedingit", # Connection name
-                               "/org/marcoz/feedingit/update" # Object's path
-                              )
+                        "/org/marcoz/feedingit/update" # Object's path
+                        )
         iface = dbus.Interface(remote_object, 'org.marcoz.feedingit')
-        iface.StopUpdate()
+        if self.updateStatus == 0:
+            iface.UpdateAll()
+        else:
+            iface.StopUpdate()
+            
+    def buttonUp_clicked(self, *widget):
+        if self.pageStatus > 0:
+            self.pageStatus -= 1
+        self.show_articles()
+        
+    def buttonDown_clicked(self, *widget):
+        self.pageStatus += 1
+        self.show_articles()
         
-    def update_label(self, title, value=None):
-        self.button.set_title(title)
+    def update_label(self, value=None):
         if value != None:
-            self.button.set_value(value)
+            self.buttonApp.set_title(str(value))
         else:
-            self.button.set_value("")
+            self.buttonApp.set_title("")
 
-    def row_activated(self, treeview, treepath): #, column):
-        (model, iter) = self.treeview.get_selection().get_selected()
-        key = model.get_value(iter, 2)
+    #def row_activated(self, treeview, treepath): #, column):
+    #    (model, iter) = self.treeview.get_selection().get_selected()
+    #    key = model.get_value(iter, 2)
         # Create an object that will proxy for a particular remote object.
-        remote_object = bus.get_object("org.maemo.feedingit", # Connection name
-                               "/org/maemo/feedingit" # Object's path
-                              )
-        iface = dbus.Interface(remote_object, 'org.maemo.feedingit')
-        iface.OpenFeed(key)
+    #    remote_object = bus.get_object("org.maemo.feedingit", # Connection name
+    #                           "/org/maemo/feedingit" # Object's path
+    #                          )
+    #    iface = dbus.Interface(remote_object, 'org.maemo.feedingit')
+    #    iface.OpenFeed(key)
+   
+    def show_articles(self):
+        db = sqlite3.connect(CONFIGDIR+self.key+".d/"+self.key+".db")
+        count = db.execute("SELECT count(*) FROM feed WHERE read=0;").fetchone()[0]
+        if count>0:
+            maxPage = count/10
+            if self.pageStatus > maxPage:
+                self.pageStatus = maxPage
+        rows = db.execute("SELECT id, title FROM feed WHERE read=0 ORDER BY date DESC LIMIT 10 OFFSET ?;", (self.pageStatus*10,) )
+        treestore = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
+        for row in rows:
+            title = fix_title(row[1][0:32])
+            id = row[0]
+            treestore.append((title, id))
+        self.treeview.set_model(treestore)
+    
+    def row_activated(self, treeview, treepath):
+        if self.status == 0:
+            self.status = 1
+            self.pageStatus = 0
+            (model, iter) = self.treeview.get_selection().get_selected()
+            self.key = model.get_value(iter, 2)
+            treeviewcolumn = self.treeview.get_column(1)
+            self.treeview.remove_column(treeviewcolumn)
+            self.show_articles()
+            self.buttonApp.set_image(gtk.image_new_from_icon_name('general_back', gtk.ICON_SIZE_BUTTON))
+            self.buttonUp.set_sensitive(True)
+            self.buttonDown.set_sensitive(True)
+        else:
+            (model, iter) = self.treeview.get_selection().get_selected()
+            id = model.get_value(iter, 1)
+            # Create an object that will proxy for a particular remote object.
+            remote_object = bus.get_object("org.maemo.feedingit", # Connection name
+                                   "/org/maemo/feedingit" # Object's path
+                                  )
+            iface = dbus.Interface(remote_object, 'org.maemo.feedingit')
+            iface.OpenArticle(self.key, id)
+
 
     def update_list(self, *widget):
         #listing = Listing(CONFIGDIR)
-        treestore = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING)
-        
-        if self.feed_list == {}:
-            self.load_config()
-
-        if self.feed_list == None:
-            treestore.append(["Start Application", "", None])
-            self.update_label("No feeds added yet")
-            self.treeview.set_model(treestore)
+        if self.status == 0:
+            treestore = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING)
             
-        else:
-            list = []
-            oldtotal = self.total
-            self.total = 0
-            #for key in listOfFeeds["feedingit-order"]:
-            for key in self.feed_list.keys():
-                try:
-                    file = open(CONFIGDIR+key+".d/unread", "r")
-                    readItems = pickle.load( file )
-                    file.close()
-                    countUnread = 0
-                    for id in readItems.keys():
-                        if readItems[id]==False:
-                            countUnread = countUnread + 1
-                    list.append([self.feed_list[key][0:18], countUnread, key])
-                    self.total += countUnread
-                except:
-                    pass
-            list = sorted(list, key=lambda item: item[1], reverse=True)
-            for item in list[0:8]:
-                treestore.append(item)
-            self.treeview.set_model(treestore)
-            if self.total > oldtotal:
-                self.update_label("%s Unread" %str(self.total), "%s more articles" %str(self.total-oldtotal))
+            if self.feed_list == {}:
+                self.load_config()
+    
+            if self.feed_list == None:
+                treestore.append(["No feeds added yet", "", None])
+                treestore.append(["Start Application", "", None])
+                #self.update_label("No feeds added yet")
+                self.treeview.set_model(treestore)
+                
             else:
-                self.update_label("%s Unread" %str(self.total))
+                list = []
+                oldtotal = self.total
+                self.total = 0
+                #for key in listOfFeeds["feedingit-order"]:
+                db = sqlite3.connect(CONFIGDIR+"feeds.db")
+                for key in self.feed_list.keys():
+                    try:
+                        countUnread = db.execute("SELECT unread FROM feeds WHERE id=?;", (key,)).fetchone()[0]
+                        list.append([self.feed_list[key][0:25], countUnread, key])
+                        self.total += countUnread
+                    except:
+                        pass
+                list = sorted(list, key=lambda item: item[1], reverse=True)
+                count = 0
+                for item in list[0:10]:
+                    count += 1
+                    treestore.append(item)
+                for i in range(count, 10):
+                    treestore.append( ("", "", None) )
+                self.treeview.set_model(treestore)
+                self.buttonApp.set_image(gtk.image_new_from_icon_name('feedingit', gtk.ICON_SIZE_BUTTON))
+                #self.update_label(self.total)
         return True
 
     def create_selector(self, choices, setting):
@@ -250,10 +369,9 @@ class FeedingItHomePlugin(hildondesktop.HomePluginItem):
             return picker
         
     def show_settings(self, widget):
-        if isfile(CONFIGDIR+"feeds.pickle"):
-            file = open(CONFIGDIR+"feeds.pickle")
-            listOfFeeds = pickle.load(file)
-            file.close()
+        if isfile(CONFIGDIR+"feeds.db"):
+            db = sqlite3.connect(CONFIGDIR+"feeds.db")
+            
             dialog = gtk.Dialog("Choose feeds to display", None, gtk.DIALOG_DESTROY_WITH_PARENT | gtk.DIALOG_NO_SEPARATOR, (gtk.STOCK_OK, gtk.RESPONSE_ACCEPT, gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL))
     
             self.pannableArea = hildon.PannableArea()
@@ -269,10 +387,12 @@ class FeedingItHomePlugin(hildondesktop.HomePluginItem):
             self.treestore_settings = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
             self.treeview_settings.set_model(self.treestore_settings)
             
-            for key in listOfFeeds["feedingit-order"]:
-                title = listOfFeeds[key]["title"]
-                item = self.treestore_settings.append([title, key])
-                if key in self.feed_list:
+            feeds = db.execute("SELECT title, id FROM feeds;")
+            
+            for feed in feeds:
+                # feed is (id, title)
+                item = self.treestore_settings.append(feed)
+                if feed[1] in self.feed_list:
                     self.treeview_settings.get_selection().select_iter(item)
                 
             self.pannableArea.add(self.treeview_settings)
@@ -315,12 +435,12 @@ class FeedingItHomePlugin(hildondesktop.HomePluginItem):
                         signal_name="UpdateFinished", path="/org/marcoz/feedingit/update")
 
     def update_started(self, *widget):
-        self.button.set_sensitive(True)
-        self.update_label("Updating...", "Click to stop update")
+        self.buttonUpdate.set_image(gtk.image_new_from_icon_name('general_stop', gtk.ICON_SIZE_BUTTON))
+        self.updateStatus = 1
 
     def update_finished(self, *widget):
-        self.button.set_sensitive(False)
-        self.update_label("Update done")
+        self.updateStatus = 0
+        self.buttonUpdate.set_image(gtk.image_new_from_icon_name('general_refresh', gtk.ICON_SIZE_BUTTON))
         
     def start_update(self):
         try:
@@ -381,15 +501,12 @@ class FeedingItHomePlugin(hildondesktop.HomePluginItem):
                 self.autoupdate = pickle.load( file )
                 file.close()
                 self.setup_autoupdate()
-            elif isfile(CONFIGDIR+"feeds.pickle"):
-                file = open(CONFIGDIR+"feeds.pickle")
-                listOfFeeds = pickle.load(file)
-                file.close()
+            elif isfile(CONFIGDIR+"feeds.db"):
+                db = sqlite3.connect(CONFIGDIR+"feeds.db")
+                feeds = db.execute("SELECT id, title FROM feeds;")
             
-                #self.feed_list = listOfFeeds["feedingit-order"]
-                for key in listOfFeeds["feedingit-order"]:
-                    self.feed_list[key] = listOfFeeds[key]["title"]
-                del listOfFeeds
+                for feed in feeds:
+                    self.feed_list[feed[0]] = feed[1]
                 self.autoupdate = 0
             else:
                 self.feed_list = None
index 1974254..145f569 100644 (file)
@@ -49,3 +49,9 @@ class ServerObject(dbus.service.Object):
         #self.app.buttonFeedClicked(None, self.app, None, key)
         self.app.openFeed(key)
         return "Done"
+    
+    @dbus.service.method('org.maemo.feedingit')
+    def OpenArticle(self, key, id):
+        #self.app.buttonFeedClicked(None, self.app, None, key)
+        self.app.openArticle(key, id)
+        return "Done"
index 3e2bf51..3fd2c4d 100644 (file)
@@ -135,7 +135,6 @@ class Feed:
                             filename = self.addImage(configdir, self.key, baseurl, img['src'])
                             img['src']=filename
                             self.db.execute("INSERT INTO images (id, imagePath) VALUES (?, ?);", (id, filename) )
-                            self.db.commit()
                           except:
                               import traceback
                               traceback.print_exc()
@@ -146,7 +145,6 @@ class Feed:
                    file.close()
                    values = (id, tmpEntry["title"], tmpEntry["contentLink"], tmpEntry["date"], currentTime, tmpEntry["link"], 0)
                    self.db.execute("INSERT INTO feed (id, title, contentLink, date, updated, link, read) VALUES (?, ?, ?, ?, ?, ?, ?);", values)
-                   self.db.commit() 
                else:
                    try:
                        filename = configdir+self.key+".d/"+id+".html"
@@ -160,6 +158,7 @@ class Feed:
                             file.close()
                    except:
                        pass
+           self.db.commit()
             
            
            rows = self.db.execute("SELECT id FROM feed WHERE (read=0 AND updated<?) OR (read=1 AND updated<?);", (2*expiry, expiry))
@@ -199,6 +198,10 @@ class Feed:
     def setEntryUnread(self, id):
         self.db.execute("UPDATE feed SET read=0 WHERE id=?;", (id,) )
         self.db.commit()     
+        
+    def markAllAsRead(self):
+        self.db.execute("UPDATE feed SET read=1 WHERE read=0;")
+        self.db.commit()
 
     def isEntryRead(self, id):
         read_status = self.db.execute("SELECT read FROM feed WHERE id=?;", (id,) ).fetchone()[0]
@@ -228,11 +231,11 @@ class Feed:
         return getId(str(entry["date"]) + str(entry["title"]))
     
     def getIds(self):
-        rows = self.db.execute("SELECT id FROM feed;").fetchall()
+        rows = self.db.execute("SELECT id FROM feed ORDER BY date DESC;").fetchall()
         ids = []
         for row in rows:
             ids.append(row[0])
-        ids.reverse()
+        #ids.reverse()
         return ids
     
     def getNextId(self, id):
@@ -316,7 +319,7 @@ class Feed:
 class ArchivedArticles(Feed):    
     def addArchivedArticle(self, title, link, date, configdir):
         id = self.generateUniqueId({"date":date, "title":title})
-        values = (id, title, None, date, 0, link, 0)
+        values = (id, title, link, date, 0, link, 0)
         self.db.execute("INSERT INTO feed (id, title, contentLink, date, updated, link, read) VALUES (?, ?, ?, ?, ?, ?, ?);", values)
         self.db.commit()
 
@@ -336,6 +339,7 @@ class ArchivedArticles(Feed):
             for img in images:
                 filename = self.addImage(configdir, self.key, baseurl, img['src'])
                 img['src']=filename
+                self.db.execute("INSERT INTO images (id, imagePath) VALUES (?, ?);", (id, filename) )
             contentLink = configdir+self.key+".d/"+id+".html"
             file = open(contentLink, "w")
             file.write(soup.prettify())
@@ -346,12 +350,20 @@ class ArchivedArticles(Feed):
         return (currentTime, None, None)
     
     def purgeReadArticles(self):
-        rows = self.db.execute("SELECT id FROM feed WHERE read=0;")
-        ids = self.getIds()
+        rows = self.db.execute("SELECT id FROM feed WHERE read=1;")
+        #ids = self.getIds()
         for row in rows:
-            self.removeEntry(row[0])
+            self.removeArticle(row[0])
                 
     def removeArticle(self, id):
+        rows = self.db.execute("SELECT imagePath FROM images WHERE id=?;", (id,) )
+        for row in rows:
+            try:
+                count = self.db.execute("SELECT count(*) FROM images WHERE id!=? and imagePath=?;", (id,row[0]) ).fetchone()[0]
+                if count == 0:
+                    os.remove(row[0])
+            except:
+                pass
         self.removeEntry(id)
 
 class Listing:
@@ -393,13 +405,19 @@ class Listing:
                             read_status = 1
                         else:
                             read_status = 0 
-                        values = (item, feed.getTitle(item), feed.getContentLink(item), time.time(), time.time(), feed.getExternalLink(item), read_status)
+                        date = time.mktime(feed.getDateTuple(item))
+                        title = feed.getTitle(item)
+                        newId = new_feed.generateUniqueId({"date":date, "title":title})
+                        values = (newId, title , feed.getContentLink(item), date, time.time(), feed.getExternalLink(item), read_status)
                         new_feed.db.execute("INSERT INTO feed (id, title, contentLink, date, updated, link, read) VALUES (?, ?, ?, ?, ?, ?, ?);", values)
                         new_feed.db.commit()
-                        images = feed.getImages(item)
-                        for image in images:
-                            new_feed.db.execute("INSERT INTO images (id, imagePath) VALUES (?, ?);", (item, image) )
-                            new_feed.db.commit()
+                        try:
+                            images = feed.getImages(item)
+                            for image in images:
+                                new_feed.db.execute("INSERT INTO images (id, imagePath) VALUES (?, ?);", (item, image) )
+                                new_feed.db.commit()
+                        except:
+                            pass
                 self.updateUnread(id)
             except:
                 import traceback
@@ -427,6 +445,7 @@ class Listing:
         (updateTime, etag, modified) = feed.updateFeed(self.configdir, url, etag, eval(modified), expiryTime, proxy, imageCache)
         db.execute("UPDATE feeds SET updateTime=?, etag=?, modified=? WHERE id=?;", (updateTime, etag, str(modified), key) )
         db.commit()
+        self.updateUnread(key, db=db)
         
     def getFeed(self, key):
         if key == "ArchivedArticles":
@@ -488,10 +507,12 @@ class Listing:
         else:
             return False
         
-    def updateUnread(self, key):
+    def updateUnread(self, key, db=None):
+        if db == None:
+            db = self.db
         feed = self.getFeed(key)
-        self.db.execute("UPDATE feeds SET unread=? WHERE id=?;", (feed.getNumberOfUnreadItems(), key))
-        self.db.commit()
+        db.execute("UPDATE feeds SET unread=? WHERE id=?;", (feed.getNumberOfUnreadItems(), key))
+        db.commit()
 
     def addFeed(self, title, url, id=None):
         if not id:
index bb6c15a..5122a5b 100644 (file)
@@ -23,7 +23,7 @@
 # Description : Simple RSS Reader
 # ============================================================================
 
-from rss import Listing
+from rss_sqlite import Listing
 from config import Config
 
 import threading
@@ -42,11 +42,10 @@ del timeout
 from updatedbus import UpdateServerObject, get_lock
 
 class Download(threading.Thread):
-    def __init__(self, listing, config, dbusHandler):
+    def __init__(self, config, dbusHandler):
         global dbug
         threading.Thread.__init__(self)
         self.running = True
-        self.listing = listing
         self.config = config
         self.dbusHandler = dbusHandler
         if dbug:
@@ -59,16 +58,17 @@ class Download(threading.Thread):
         try:
             self.dbusHandler.UpdateStarted()
             (use_proxy, proxy) = self.config.getProxy()
-            for key in self.listing.getListOfFeeds():
+            listing = Listing(CONFIGDIR)
+            for key in listing.getListOfFeeds():
                 if dbug:
                     self.dbug.write("updating %s\n" %key)
                 try:
                     if use_proxy:
                         from urllib2 import install_opener, build_opener
                         install_opener(build_opener(proxy))
-                        self.listing.updateFeed(key, self.config.getExpiry(), proxy=proxy, imageCache=self.config.getImageCache() )
+                        listing.updateFeed(key, self.config.getExpiry(), proxy=proxy, imageCache=self.config.getImageCache() )
                     else:
-                        self.listing.updateFeed(key, self.config.getExpiry(), imageCache=self.config.getImageCache() )
+                        listing.updateFeed(key, self.config.getExpiry(), imageCache=self.config.getImageCache() )
                 except:
                     import traceback
                     file = open("/home/user/.feedingit/feedingit_update.log", "a")
@@ -83,8 +83,11 @@ class Download(threading.Thread):
             if dbug:
                 self.dbug.write("Dbus ArticleCountUpdated signal sent\n")
         except:
-            pass
-        self.listing.saveConfig()
+            import traceback
+            file = open("/home/user/.feedingit/feedingit_update.log", "a")
+            traceback.print_exc(file=file)
+            file.close()
+            #pass
         if dbug:
             self.dbug.write("About to main_quit\n")
         mainloop.quit()
@@ -94,7 +97,6 @@ class Download(threading.Thread):
 
 class FeedUpdate():
     def __init__(self):
-        self.listing = Listing(CONFIGDIR)
         self.config = Config(self, CONFIGDIR+"config.ini")
         self.dbusHandler = UpdateServerObject(self)
         self.updateThread = False
@@ -102,7 +104,7 @@ class FeedUpdate():
     def automaticUpdate(self):
         #self.listing.updateFeeds()
         if self.updateThread == False:
-            self.updateThread = Download(self.listing, self.config, self.dbusHandler)
+            self.updateThread = Download(self.config, self.dbusHandler)
             self.updateThread.start()
         
     def stopUpdate(self):