# # This file is part of Sargasso, http://zamez.org/sargasso # Licensed under the GNU General Public License, # http://www.opensource.org/licenses/gpl-license # Copyright 2005 James Bursa # import os import urlparse import wimp import sargasso import swi import rufl # styles for text: font family, style, size, text colour, background colour style_feed_title = ('Homerton', rufl.regular, 200, 0x000000, 0xffaa99) style_feed_title_new = ('Homerton', rufl.bold, 200, 0x000000, 0xffaa99) style_feed_tagline = ('NewHall', rufl.regular, 200, 0x000000, None) style_feed_error = ('NewHall', rufl.regular, 200, 0x0000a0, None) style_feed_date = ('NewHall', rufl.slanted, 160, 0x0060ee, None) style_feed_type = ('NewHall', rufl.slanted, 160, 0x666666, None) style_entry_title = ('Homerton', rufl.regular, 200, 0x000000, 0xa0dddd) style_entry_title_new = ('Homerton', rufl.bold, 200, 0x000000, 0xa0dddd) style_entry_author = ('NewHall', rufl.slanted, 160, 0x666666, None) style_entry_date = ('NewHall', rufl.slanted, 160, 0x0060ee, None) style_entry_summary = ('NewHall', rufl.regular, 180, 0x000000, None) feed_type = { 'rss090': 'RSS 0.90', 'rss091n': 'Netscape RSS 0.91', 'rss091u': 'Userland RSS 0.91', 'rss10': 'RSS 1.0', 'rss092': 'RSS 0.92', 'rss093': 'RSS 0.93', 'rss094': 'RSS 0.94', 'rss20': 'RSS 2.0', 'rss': 'RSS', 'atom01': 'Atom 0.1', 'atom02': 'Atom 0.2', 'atom03': 'Atom 0.3', 'atom': 'Atom', 'cdf': 'CDF', 'hotrss': 'Hot RSS', '': 'Unknown', } default_feeds = ( 'http://newsrss.bbc.co.uk/rss/newsonline_uk_edition/front_page/rss.xml', 'http://today.reuters.co.uk/rss/topNews/', 'http://news.ft.com/rss/home/uk', 'http://www.drobe.co.uk/rss.php', 'http://www.iconbar.com/cgi-bin/iconbar.rss', 'http://www.theregister.co.uk/feeds/latest.rdf', 'http://www.snackspot.org.uk/rss/rss.xml', ) def init(): "Initialise program specific stuff" global main_window, add_feed_box wimp.hourglass_on() iconbar_init() main_window = MainWindow('main') add_feed_box = AddFeedBox('add_feed') wimp.poll_mask = 0 wimp.null_reason_handler = null_reason_handler load_choices() if sargasso.feeds == []: for url in default_feeds: sargasso.add_feed(url) for feed in sargasso.feeds: feed.last_status = feed.status feed.window = wimp.window('main') make_main_window() main_window.open() wimp.hourglass_off() def quit(): "Tidy up before quitting" pass def iconbar_init(): "Setup iconbar icon" global window_info, menu_iconbar wimp.iconbar_icon('!sargasso', iconbar_click) window_info = wimp.info_window() menu_iconbar = wimp.menu('iconbar', ('task', ('info', window_info), 'update', 'quit')) def null_reason_handler(): sargasso.poll() remake = False for feed in sargasso.feeds: if feed.last_status != feed.status: remake = True feed.last_status = feed.status if feed.window.is_open: make_feed_window(feed) feed.window.refresh(0, 0, 900, 10000) if remake: make_main_window() main_window.refresh(0, 0, 1000, 10000) def iconbar_click(buttons, x): "Handle click on iconbar" if buttons == 2: reopen = 1 while reopen: selection, reopen = menu_iconbar.menu(x - 64, 96 + 44 * 3) if selection is None: pass elif selection[0] == 0: window_info.open_as_menu() reopen = 0 elif selection[0] == 1: for feed in sargasso.feeds: feed.update() elif selection[0] == 2: wimp.quit() elif buttons in (1, 4): main_window.open_full_size(-1) def make_main_window(): main_window.contents = [] y = 0 for feed in sargasso.feeds: title = try_detail(feed.feed, 'title_detail') if title == '': title = feed.url if len(feed.new_entries): title_style = style_feed_title_new else: title_style = style_feed_title title = MainWindowIcon(main_window, 0, y, 700, title_style[0], title_style[1], title_style[2], title, title_style[3], title_style[4]) title.feed = feed main_window.add_content(title) status = '' if feed.status == sargasso.STATUS_DONE: if len(feed.new_entries): status = '%i items (%i new)' % (len(feed.entries), len(feed.new_entries)) else: status = '%i items' % (len(feed.entries)) elif feed.status == sargasso.STATUS_ERROR: status = 'Failed' elif feed.status in (sargasso.STATUS_IDLE, sargasso.STATUS_FETCHING): status = 'Fetching' status = MainWindowIcon(main_window, 700, y, 1000, title_style[0], title_style[1], title_style[2], status, title_style[3], title_style[4]) status.feed = feed main_window.add_content(status) status.pos[3] = title.pos[3] y = title.y1 if feed.status == sargasso.STATUS_ERROR: summary = MainWindowIcon(main_window, 0, y, 1000, style_feed_error[0], style_feed_error[1], style_feed_error[2], feed.error, style_feed_error[3], style_feed_error[4]) else: summary = MainWindowIcon(main_window, 0, y, 1000, style_feed_tagline[0], style_feed_tagline[1], style_feed_tagline[2], try_detail(feed.feed, 'tagline_detail'), style_feed_tagline[3], style_feed_tagline[4]) summary.feed = feed main_window.add_content(summary) y = summary.y1 + 10 main_window.set_extent(0, 0, 1000, y) if main_window.is_open: main_window.open_full_size() class MainWindow(wimp.window): def click(self, icon, buttons, x, y, sx, sy): self.sx = sx self.sy = sy if wimp.window.click(self, icon, buttons, x, y, sx, sy): return True if buttons == 2: menu = wimp.menu('menu', ('task', 'add_feed', '-remove_feed', 'update')) reopen = 1 while reopen: selection, reopen = menu.menu(sx - 64, sy) if selection is None: pass elif selection[0] == 0: add_feed_box.icon_text(0, 'http://') add_feed_box.open_centred() add_feed_box.put_caret(0) elif selection[0] == 2: for feed in sargasso.feeds: feed.update() return True class MainWindowIcon(wimp.paragraph): def click(self, buttons, x, y): feed = self.feed if buttons == 2: title = try_detail(feed.feed, 'title_detail') if title == '': title = feed.url title = title.encode('latin1', 'replace') if 30 < len(title): title = title[:30] + '...' else: title = title menu = wimp.menu('menu', ('task', 'add_feed', wimp.lookup('remove_feed_x') % title, 'update')) reopen = 1 while reopen: selection, reopen = menu.menu(self.window.sx - 64, self.window.sy) if selection is None: pass elif selection[0] == 0: add_feed_box.icon_text(0, 'http://') add_feed_box.open_centred() add_feed_box.put_caret(0) elif selection[0] == 1: if feed.window: feed.window.remove() sargasso.remove_feed(feed.url) make_main_window() main_window.refresh(0, 0, 1000, 10000) save_choices() elif selection[0] == 2: for feed in sargasso.feeds: feed.update() return True if feed.status == sargasso.STATUS_DONE: if feed.window.is_open: feed.window.open_centred(-1) else: make_feed_window(feed) feed.window.open_centred(-1) if feed.new_entries: feed.new_entries = [] make_main_window() main_window.refresh(0, 0, 1000, 10000) return True def make_feed_window(feed): w = feed.window w.contents = [] w.y1 = 0 link = feed.feed.get('link', '') title = try_detail(feed.feed, 'title_detail') tagline = try_detail(feed.feed, 'tagline_detail') modified = feed.feed.get('modified', '') type = feed_type[feed.version] add_para(w, style_feed_title, title, link) add_para(w, style_feed_tagline, tagline, link) add_para(w, style_feed_date, modified, link) add_para(w, style_feed_type, type, link) for entry in feed.entries: link = entry.get('link', '') entry_title = try_detail(entry, 'title_detail') entry_author = entry.get('author', '') entry_modified = entry.get('modified', '') entry_summary = try_detail(entry, 'summary_detail') if entry in feed.new_entries: add_para(w, style_entry_title_new, entry_title, link) else: add_para(w, style_entry_title, entry_title, link) add_para(w, style_entry_author, entry_author, link) add_para(w, style_entry_date, entry_modified, link) add_para(w, style_entry_summary, entry_summary, link) if 'content' in entry: for content in entry.content: value = read_detail(content) add_para(w, style_entry_summary, value, link) w.set_extent(0, 0, 900, w.y1) w.title(title[:98]) def add_para(w, style, text, url): if text == '': return icon = FeedWindowIcon(w, 0, w.y1, 900, style[0], style[1], style[2], text, style[3], style[4]) w.add_content(icon) icon.url = url w.y1 = icon.y1 class FeedWindowIcon(wimp.paragraph): def click(self, buttons, x, y): if buttons == 2: return False swi.swi('URI_Dispatch', '0s0', self.url) return True def try_detail(feed_or_item, detail_name): if detail_name not in feed_or_item: return '' return read_detail(feed_or_item[detail_name]) def read_detail(detail): if detail['type'] == 'text/plain': t = detail['value'] elif detail['type'] == 'text/html': t = remove_html(detail['value']) else: t = '' return ' '.join(t.split()) def remove_html(s): return ''.join(map(lambda z: z[-1], map(lambda z: z.split('>'), s.split('<')))) def load_choices(): try: f = open('Choices:Sargasso.Feeds') except IOError: return for line in f: sargasso.add_feed(line[:-1]) def save_choices(): os.mkdir('.Sargasso') try: f = open('.Sargasso.Feeds', 'w') except IOError: return for feed in sargasso.feeds: f.write(feed.url + '\n') f.close() class AddFeedBox(wimp.window): def click(self, icon, buttons, x, y, sx, sy): if icon == 2: self.close() return True elif icon == 1: url = self.icon_text(0) scheme, host, path, params, query, fragment = urlparse.urlparse(url) if scheme != 'http': wimp.warning(wimp.lookup('http')) return True sargasso.add_feed(url) sargasso.feeds[-1].last_status = sargasso.feeds[-1].status sargasso.feeds[-1].window = wimp.window('main') save_choices() self.close() return True return False def key(self, icon, key): if key == 0x1b: self.close() elif key == 0xd: self.click(1, 0, 0, 0, 0, 0) else: wimp.window.key(self, icon, key)