I started this as an experiment to see how hard it was to build apps using QT and Elixir. This is how it looks after two hours of coding:
  
And here's the code:  http://urssus.googlecode.com
  You will need:
  
- PyQt 4.4 or later 
- Mark Pilgrim's feedparser 
- Python 2.5 (or whenever elementtree got included) 
- A OPML file 
- The Python SQLite bindings 
- Elixir (the declarative layer over SQL Alchemy) 
You can find the real code at
  And then you can use these 131 LOC ;-)
  # -*- coding: utf-8 -*-
# Mark Pilgrim's feed parser
import feedparser as fp
# DB Classes
from elixir import *
metadata.bind = "sqlite:///urssus.sqlite"
metadata.bind.echo = True
class Feed(Entity):
  htmlUrl     = Field(Text)
  xmlUrl      = Field(Text)
  title       = Field(Text)
  text        = Field(Text)
  description = Field(Text)
  children    = OneToMany('Feed')
  parent      = ManyToOne('Feed')
  posts       = OneToMany('Post')
  def __repr__(self):
    return self.text
  def update(self):
    d=fp.parse(self.xmlUrl)
class Post(Entity):
  feed        = ManyToOne('Feed')
  title       = Field(Text)
  post_id     = Field(Text)
  content     = Field(Text)
# This is just temporary
setup_all()
create_all()
# UI Classes
from PyQt4 import QtGui, QtCore
from Ui_main import Ui_MainWindow
class MainWindow(QtGui.QMainWindow):
  def __init__(self):
    QtGui.QMainWindow.__init__(self)
    # Set up the UI from designer
    self.ui=Ui_MainWindow()
    self.ui.setupUi(self)
    # Initialize the tree from the Feeds
    self.model=QtGui.QStandardItemModel()
    # Internal function
    def addSubTree(parent, node):
      nn=QtGui.QStandardItem(unicode(node))
      parent.appendRow(nn)
      nn.feed=node
      if not node.children:
        return
      else:
        for child in node.children:
          addSubTree(nn, child)
    roots=Feed.query.filter(Feed.parent==None)
    iroot=self.model.invisibleRootItem()
    iroot.feed=None
    for root in roots:
      addSubTree(iroot, root)
    self.ui.feeds.setModel(self.model)
    QtCore.QObject.connect(self.ui.feeds, QtCore.SIGNAL("clicked(QModelIndex)"), self.openFeed)
    QtCore.QObject.connect(self.ui.posts, QtCore.SIGNAL("clicked(QModelIndex)"), self.openPost)
  def openFeed(self, index):
    item=self.model.itemFromIndex(index)
    feed=item.feed
    if not feed.xmlUrl:
      return
    d=fp.parse(feed.xmlUrl)
    posts=[]
    for post in d['entries']:
      print post
      print '----------------------------------\n\n'
      if 'content' in post:
        posts.append(Post(feed=feed, title=post['title'], post_id=post['id'], content='<hr>'.join([ c.value for c in post['content']])))
      elif 'summary' in post:
        posts.append(Post(feed=feed, title=post['title'], post_id=post['id'], content=post['summary']))
      elif 'value' in post:
        posts.append(Post(feed=feed, title=post['title'], post_id=post['id'], content=post['value']))
    session.flush()
    self.ui.posts.__model=QtGui.QStandardItemModel()
    for post in posts:
      item=QtGui.QStandardItem(post.title)
      item.post=post
      self.ui.posts.__model.appendRow(item)
    self.ui.posts.setModel(self.ui.posts.__model)
  def openPost(self, index):
    item=self.ui.posts.__model.itemFromIndex(index)
    post=item.post
    self.ui.view.setHtml(post.content)
if __name__ == "__main__":
  import sys
  # For starters, lets import a OPML file into the DB so we have some data to work with
  from xml.etree import ElementTree
  tree = ElementTree.parse(sys.argv[1])
  current=None
  for outline in tree.findall("//outline"):
    xu=outline.get('xmlUrl')
    if xu:
      f=Feed(xmlUrl=outline.get('xmlUrl'),
             htmlUrl=outline.get('htmlUrl'),
             title=outline.get('title'),
             text=outline.get('text'),
             description=outline.get('description')
             )
      if current:
        current.children.append(f)
        f.parent=current
    else:
      current=Feed(text=outline.get('text'))
    session.flush()
  app=QtGui.QApplication(sys.argv)
  window=MainWindow()
  window.show()
  sys.exit(app.exec_())