#!/usr/bin/python import sys from xml.sax import parse from xml.sax.handler import ContentHandler # http://wxpython.org/ from wxPython.wx import * from wxPython.html import * # http://diveintomark.org/projects/rss_parser/index.html import rssparser # simple SAX parser for OPML files. Handles Radio and Syndirella formats class opml(ContentHandler): outline={} def __init__(self,file): ContentHandler.__init__(self) parse(file, self) def startElement(self, name, attrs): if name=='outline': values=dict(attrs) self.outline[attrs['title'].lower()]=values def names(self): keys = self.outline.keys() keys.sort() return keys def text(self, name): entry = self.outline[name] if 'text' in entry: return entry['text'].encode('iso-8859-1') if 'title' in entry: return entry['title'].encode('iso-8859-1') # Yet Another 3 Paned Aggregator class wx3pa(wxApp): # model mySubs=None items=None # view tree=None list=None data=None def OnInit(self): # layout frame = wxFrame(NULL, -1, "3 Paned Aggregator Mockup-demo") split1 = wxSplitterWindow(frame,-1) split2 = wxSplitterWindow(split1,-1) # panes self.tree=wxTreeCtrl(split1,-1) self.list=wxListCtrl(split2,-1,style=wxLC_REPORT|wxSUNKEN_BORDER) self.data=wxHtmlWindow(split2,-1) # attach the panes to the frame split1.SplitVertically(self.tree, split2) split2.SplitHorizontally(self.list, self.data) self.SetTopWindow(frame) frame.Show(true) # resize split1.SetMinimumPaneSize(20) split2.SetMinimumPaneSize(20) split1.SetSashPosition(300,true) split2.SetSashPosition(200) # wire up the events EVT_TREE_SEL_CHANGED(self, self.tree.GetId(), self.selectFeed) EVT_LIST_ITEM_SELECTED(self, self.list.GetId(), self.selectItem) return true # load a list of subscriptions from an OPML file def load(self,files): root = self.tree.AddRoot("Feeds") for file in files: self.mySubs = opml(file) for name in self.mySubs.names(): child=self.tree.AppendItem(root,self.mySubs.text(name)) self.tree.SetPyData(child,self.mySubs.outline[name]) self.tree.Expand(root) # select a single feed and display titles from each item def selectFeed(self, event): self.list.DeleteAllItems() if not self.list.GetColumn(0): self.list.InsertColumn(0, 'Title') outline = self.tree.GetPyData(event.GetItem()) self.items=rssparser.parse(outline['xmlUrl'])['items'] for item in self.items: if 'title' in item: self.list.InsertStringItem(0,item['title']) self.list.SetColumnWidth(0,wxLIST_AUTOSIZE_USEHEADER) # show the html description for a single item def selectItem(self, event): item=self.items[event.GetIndex()] self.data.SetPage(item['description']) if __name__ == '__main__': app = wx3pa(0) app.load(sys.argv[1:] or [r'http://radio.weblogs.com/0101679/gems/mySubscriptions.opml']) app.MainLoop()