import mpdprotocol import responsedict import urwid import itertools from twisted.internet import defer class SelectableText(urwid.Text): def keypress(self, __, key): return key def selectable(self): return True class Playlist(urwid.WidgetWrap): def __init__(self, columns, plylst): self.playlist = plylst self.columns = columns self.texts = self.get_texts(self.playlist.as_table(), cols) self.titles = urwid.Columns([('weight',w,SelectableText(c)) for w,c,_ in cols],1) self.header = urwid.Pile([self.titles, urwid.Divider('-')]) widget = self.make_playlist() widget = urwid.Frame(widget, self.header) urwid.WidgetWrap.__init__(self, widget) def get_texts(self, choices, columns): texts = [] for weight,col,transform in columns: texts.append([(weight,transform(x[0])) for x in choices.get(col)]) return texts def make_playlist(self): body = [] for x in itertools.izip_longest(*self.texts): new_widg = [('weight',wgt,SelectableText(it,wrap='clip')) for wgt,it in x] new_widg = urwid.Columns(new_widg, 1) new_widg = urwid.AttrMap(new_widg, 'unselected', 'selected') body.append(new_widg) list_walker = urwid.SimpleFocusListWalker(body) return urwid.ListBox(urwid.SimpleFocusListWalker(body[:])) def exit_on_q(key): if key in ('q', 'Q'): try: raise urwid.ExitMainLoop() finally: reactor.stop() cols = [ (1,'Pos', lambda x: str(int(x)+1)), (4,'Album', lambda x:x), (3,'Artist', lambda x:x), (5,'Title', lambda x:x) ] @defer.inlineCallbacks def get_playlist(): client = yield mpdprotocol.get_client() res = yield client.sendCommand('playlistinfo') method, data = res loop.widget = Playlist(cols, data) loop.draw_screen() from twisted.internet import reactor palette = [ ('selected', 'white', 'black'), ('selected', 'black', 'white'), ] loop = urwid.MainLoop(urwid.SolidFill(), palette, event_loop=urwid.TwistedEventLoop(), unhandled_input=exit_on_q) reactor.callWhenRunning(get_playlist) loop.run()