def __init__(self, message, even=True): """ :param message: a message :type message: alot.db.Message :param even: even entry in a pile of messages? Used for theming. :type even: bool """ self.message = message self.even = even if even: attr = settings.get_theming_attribute('thread', 'summary_even') else: attr = settings.get_theming_attribute('thread', 'summary_odd') cols = [] sumstr = self.__str__() txt = urwid.Text(sumstr) cols.append(txt) thread_tags = message.get_thread().get_tags(intersection=True) outstanding_tags = set(message.get_tags()).difference(thread_tags) tag_widgets = [TagWidget(t) for t in outstanding_tags] tag_widgets.sort(tag_cmp, lambda tag_widget: tag_widget.translated) for tag_widget in tag_widgets: if not tag_widget.hidden: cols.append(('fixed', tag_widget.width(), tag_widget)) focus_att = settings.get_theming_attribute('thread', 'summary_focus') line = urwid.AttrMap(urwid.Columns(cols, dividechars=1), attr, focus_att) urwid.WidgetWrap.__init__(self, line)
def rebuild(self): if self.isinitialized: focusposition = self.taglist.get_focus()[1] else: focusposition = 0 self.isinitialized = True lines = list() displayedtags = sorted(filter(self.filtfun, self.tags), key=unicode.lower) for (num, b) in enumerate(displayedtags): if (num % 2) == 0: attr = settings.get_theming_attribute('taglist', 'line_even') else: attr = settings.get_theming_attribute('taglist', 'line_odd') focus_att = settings.get_theming_attribute('taglist', 'line_focus') tw = TagWidget(b, attr, focus_att) rows = [('fixed', tw.width(), tw)] if tw.hidden: rows.append(urwid.Text(b + ' [hidden]')) elif tw.translated is not b: rows.append(urwid.Text('(%s)' % b)) line = urwid.Columns(rows, dividechars=1) line = urwid.AttrMap(line, attr, focus_att) lines.append(line) self.taglist = urwid.ListBox(urwid.SimpleListWalker(lines)) self.body = self.taglist self.taglist.set_focus(focusposition % len(displayedtags))
def rebuild(self): if self.isinitialized: focusposition = self.bufferlist.get_focus()[1] else: focusposition = 0 self.isinitialized = True lines = list() displayedbuffers = filter(self.filtfun, self.ui.buffers) for (num, b) in enumerate(displayedbuffers): line = BufferlineWidget(b) if (num % 2) == 0: attr = settings.get_theming_attribute('bufferlist', 'line_even') else: attr = settings.get_theming_attribute('bufferlist', 'line_odd') focus_att = settings.get_theming_attribute('bufferlist', 'line_focus') buf = urwid.AttrMap(line, attr, focus_att) num = urwid.Text('%3d:' % self.index_of(b)) lines.append(urwid.Columns([('fixed', 4, num), buf])) self.bufferlist = urwid.ListBox(urwid.SimpleListWalker(lines)) num_buffers = len(displayedbuffers) if focusposition is not None and num_buffers > 0: self.bufferlist.set_focus(focusposition % num_buffers) self.body = self.bufferlist
def __init__(self, attachment, selectable=True): self._selectable = selectable self.attachment = attachment if not isinstance(attachment, Attachment): self.attachment = Attachment(self.attachment) att = settings.get_theming_attribute("thread", "attachment") focus_att = settings.get_theming_attribute("thread", "attachment_focus") widget = urwid.AttrMap(urwid.Text(self.attachment.__str__()), att, focus_att) urwid.WidgetWrap.__init__(self, widget)
def rebuild(self): displayed_widgets = [] hidden = settings.get('envelope_headers_blacklist') # build lines lines = [] for (k, vlist) in self.envelope.headers.items(): if (k not in hidden) or self.all_headers: for value in vlist: lines.append((k, value)) # sign/encrypt lines if self.envelope.sign: description = 'Yes' sign_key = self.envelope.sign_key if sign_key is not None and len(sign_key.subkeys) > 0: description += ', with key ' + sign_key.uids[0].uid lines.append(('GPG sign', description)) if self.envelope.encrypt: description = 'Yes' encrypt_keys = self.envelope.encrypt_keys.values() if len(encrypt_keys) == 1: description += ', with key ' elif len(encrypt_keys) > 1: description += ', with keys ' first_key = True for key in encrypt_keys: if key is not None: if first_key: first_key = False else: description += ', ' if len(key.subkeys) > 0: description += key.uids[0].uid lines.append(('GPG encrypt', description)) # add header list widget iff header values exists if lines: key_att = settings.get_theming_attribute('envelope', 'header_key') value_att = settings.get_theming_attribute('envelope', 'header_value') gaps_att = settings.get_theming_attribute('envelope', 'header') self.header_wgt = HeadersList(lines, key_att, value_att, gaps_att) displayed_widgets.append(self.header_wgt) # display attachments lines = [] for a in self.envelope.attachments: lines.append(AttachmentWidget(a, selectable=False)) if lines: self.attachment_wgt = urwid.Pile(lines) displayed_widgets.append(self.attachment_wgt) self.body_wgt = urwid.Text(self.envelope.body) displayed_widgets.append(self.body_wgt) self.body = urwid.ListBox(displayed_widgets)
def __init__(self, tid, dbman): self.dbman = dbman #logging.debug('tid: %s' % tid) self.thread = dbman.get_thread(tid) #logging.debug('tid: %s' % self.thread) self.tag_widgets = [] self.display_content = settings.get('display_content_in_threadline') self.rebuild() normal = settings.get_theming_attribute('search', 'thread') focussed = settings.get_theming_attribute('search', 'thread_focus') urwid.AttrMap.__init__(self, self.columns, normal, focussed)
def __init__(self, attachment, selectable=True): self._selectable = selectable self.attachment = attachment if not isinstance(attachment, Attachment): self.attachment = Attachment(self.attachment) att = settings.get_theming_attribute('thread', 'attachment') focus_att = settings.get_theming_attribute('thread', 'attachment_focus') widget = urwid.AttrMap(urwid.Text(self.attachment.__str__()), att, focus_att) urwid.WidgetWrap.__init__(self, widget)
def __init__(self, message, even=False, folded=True, raw=False, all_headers=False, depth=0, bars_at=[]): """ :param message: the message to display :type message: alot.db.Message :param even: use messagesummary_even theme for summary :type even: bool :param folded: fold message initially :type folded: bool :param raw: show message source initially :type raw: bool :param all_headers: show all headers initially :type all_headers: bool :param depth: number of characters to shift content to the right :type depth: int :param bars_at: defines for each column of the indentation whether to use a vertical bar instead of a space. :type bars_at: list(bool) """ self.message = message self.mail = self.message.get_email() self.depth = depth self.bars_at = bars_at self.even = even self.folded = folded self.show_raw = raw self.show_all_headers = all_headers # define subwidgets that will be created on demand self.sumline = None self.headerw = None self.attachmentw = None self.bodyw = None self.sourcew = None # set available and to be displayed headers self._all_headers = list(set(self.mail.keys())) displayed = settings.get("displayed_headers") self._filtered_headers = [k for k in displayed if k in self.mail] self._displayed_headers = None bars = settings.get_theming_attribute("thread", "arrow_bars") self.arrow_bars_att = bars heads = settings.get_theming_attribute("thread", "arrow_heads") self.arrow_heads_att = heads logging.debug(self.arrow_heads_att) self.rebuild() # this will build self.pile urwid.WidgetWrap.__init__(self, self.pile)
def _get_theme(self, component, focus=False): path = ["search", "threadline", component] if focus: path.append("focus") else: path.append("normal") return settings.get_theming_attribute(path)
def build_statusbar(self): """construct and return statusbar widget""" info = {} cb = self.current_buffer btype = None if cb is not None: info = cb.get_info() btype = cb.modename info['buffer_no'] = self.buffers.index(cb) info['buffer_type'] = btype info['total_messages'] = self.dbman.count_messages('*') info['pending_writes'] = len(self.dbman.writequeue) info['input_queue'] = ' '.join(self.input_queue) lefttxt = righttxt = u'' if cb is not None: lefttxt, righttxt = settings.get(btype + '_statusbar', (u'', u'')) lefttxt = string_decode(lefttxt, 'UTF-8') lefttxt = lefttxt.format(**info) righttxt = string_decode(righttxt, 'UTF-8') righttxt = righttxt.format(**info) footerleft = urwid.Text(lefttxt, align='left') pending_writes = len(self.dbman.writequeue) if pending_writes > 0: righttxt = ('|' * pending_writes) + ' ' + righttxt footerright = urwid.Text(righttxt, align='right') columns = urwid.Columns([ footerleft, ('fixed', len(righttxt), footerright)]) footer_att = settings.get_theming_attribute('global', 'footer') return urwid.AttrMap(columns, footer_att)
def build_statusbar(self): """construct and return statusbar widget""" info = {} cb = self.current_buffer btype = None if cb is not None: info = cb.get_info() btype = cb.modename info["buffer_no"] = self.buffers.index(cb) info["buffer_type"] = btype info["total_messages"] = self.dbman.count_messages("*") info["pending_writes"] = len(self.dbman.writequeue) lefttxt = righttxt = u"" if cb is not None: lefttxt, righttxt = settings.get(btype + "_statusbar", (u"", u"")) lefttxt = string_decode(lefttxt, "UTF-8") lefttxt = lefttxt.format(**info) righttxt = string_decode(righttxt, "UTF-8") righttxt = righttxt.format(**info) footerleft = urwid.Text(lefttxt, align="left") pending_writes = len(self.dbman.writequeue) if pending_writes > 0: righttxt = ("|" * pending_writes) + " " + righttxt footerright = urwid.Text(righttxt, align="right") columns = urwid.Columns([footerleft, ("fixed", len(righttxt), footerright)]) footer_att = settings.get_theming_attribute("global", "footer") return urwid.AttrMap(columns, footer_att)
def __init__(self, dbman, initialcmd): """ :param dbman: :class:`~alot.db.DBManager` :param initialcmd: commandline applied after setting up interface :type initialcmd: str :param colourmode: determines which theme to chose :type colourmode: int in [1,16,256] """ self.dbman = dbman colourmode = int(settings.get('colourmode')) logging.info('setup gui in %d colours' % colourmode) global_att = settings.get_theming_attribute('global', 'body') self.mainframe = urwid.Frame(urwid.SolidFill()) self.mainframe_themed = urwid.AttrMap(self.mainframe, global_att) self.inputwrap = InputWrap(self, self.mainframe_themed) self.mainloop = urwid.MainLoop(self.inputwrap, handle_mouse=False, event_loop=urwid.TwistedEventLoop(), unhandled_input=self.unhandeled_input) self.mainloop.screen.set_terminal_properties(colors=colourmode) self.show_statusbar = settings.get('show_statusbar') self.notificationbar = None self.mode = 'global' self.commandprompthistory = [] logging.debug('fire first command') self.apply_command(initialcmd) self.mainloop.run()
def build_statusbar(self): """construct and return statusbar widget""" info = {} cb = self.current_buffer btype = None if cb is not None: info = cb.get_info() btype = cb.modename info['buffer_no'] = self.buffers.index(cb) info['buffer_type'] = btype info['total_messages'] = self.dbman.count_messages('*') info['pending_writes'] = len(self.dbman.writequeue) lefttxt = righttxt = u'' if cb is not None: lefttxt, righttxt = settings.get(btype + '_statusbar', (u'', u'')) lefttxt = string_decode(lefttxt, 'UTF-8') lefttxt = lefttxt.format(**info) righttxt = string_decode(righttxt, 'UTF-8') righttxt = righttxt.format(**info) footerleft = urwid.Text(lefttxt, align='left') pending_writes = len(self.dbman.writequeue) if pending_writes > 0: righttxt = ('|' * pending_writes) + ' ' + righttxt footerright = urwid.Text(righttxt, align='right') columns = urwid.Columns([ footerleft, ('fixed', len(righttxt), footerright)]) footer_att = settings.get_theming_attribute('global', 'footer') return urwid.AttrMap(columns, footer_att)
def __init__(self, headerslist, key_attr, value_attr): self.headers = headerslist self.key_attr = key_attr self.value_attr = value_attr pile = urwid.Pile(self._build_lines(headerslist)) att = settings.get_theming_attribute("thread", "header") pile = urwid.AttrMap(pile, att) urwid.WidgetWrap.__init__(self, pile)
def _build_lines(self, lines): max_key_len = 1 headerlines = [] key_att = settings.get_theming_attribute('thread', 'header_key') value_att = settings.get_theming_attribute('thread', 'header_value') #calc max length of key-string for key, value in lines: if len(key) > max_key_len: max_key_len = len(key) for key, value in lines: ##todo : even/odd keyw = ('fixed', max_key_len + 1, urwid.Text((key_att, key))) valuew = urwid.Text((value_att, value)) line = urwid.Columns([keyw, valuew]) headerlines.append(line) return headerlines
def __init__(self, headerslist, key_attr, value_attr): self.headers = headerslist self.key_attr = key_attr self.value_attr = value_attr pile = urwid.Pile(self._build_lines(headerslist)) att = settings.get_theming_attribute('thread', 'header') pile = urwid.AttrMap(pile, att) urwid.WidgetWrap.__init__(self, pile)
def choice(self, message, choices={'y': 'yes', 'n': 'no'}, select=None, cancel=None, msg_position='above'): """ prompt user to make a choice :param message: string to display before list of choices :type message: unicode :param choices: dict of possible choices :type choices: dict: keymap->choice (both str) :param select: choice to return if enter/return is hit. Ignored if set to `None`. :type select: str :param cancel: choice to return if escape is hit. Ignored if set to `None`. :type cancel: str :param msg_position: determines if `message` is above or left of the prompt. Must be `above` or `left`. :type msg_position: str :returns: a :class:`twisted.defer.Deferred` """ assert select in choices.values() + [None] assert cancel in choices.values() + [None] assert msg_position in ['left', 'above'] d = defer.Deferred() # create return deferred oldroot = self.inputwrap.get_root() def select_or_cancel(text): self.inputwrap.set_root(oldroot) self.inputwrap.select_cancel_only = False d.callback(text) #set up widgets msgpart = urwid.Text(message) choicespart = widgets.ChoiceWidget(choices, callback=select_or_cancel, select=select, cancel=cancel) # build widget if msg_position == 'left': both = urwid.Columns( [ ('fixed', len(message), msgpart), ('weight', 1, choicespart), ], dividechars=1) else: # above both = urwid.Pile([msgpart, choicespart]) att = settings.get_theming_attribute('global', 'prompt') both = urwid.AttrMap(both, att, att) # put promptwidget as overlay on main widget overlay = urwid.Overlay(both, oldroot, ('fixed left', 0), ('fixed right', 0), ('fixed bottom', 1), None) self.inputwrap.set_root(overlay) self.inputwrap.select_cancel_only = True return d # return deferred
def choice(self, message, choices={'y': 'yes', 'n': 'no'}, select=None, cancel=None, msg_position='above'): """ prompt user to make a choice. :param message: string to display before list of choices :type message: unicode :param choices: dict of possible choices :type choices: dict: keymap->choice (both str) :param select: choice to return if enter/return is hit. Ignored if set to `None`. :type select: str :param cancel: choice to return if escape is hit. Ignored if set to `None`. :type cancel: str :param msg_position: determines if `message` is above or left of the prompt. Must be `above` or `left`. :type msg_position: str :rtype: :class:`twisted.defer.Deferred` """ assert select in choices.values() + [None] assert cancel in choices.values() + [None] assert msg_position in ['left', 'above'] d = defer.Deferred() # create return deferred oldroot = self.mainloop.widget def select_or_cancel(text): self.mainloop.widget = oldroot self._passall = False d.callback(text) # set up widgets msgpart = urwid.Text(message) choicespart = ChoiceWidget(choices, callback=select_or_cancel, select=select, cancel=cancel) # build widget if msg_position == 'left': both = urwid.Columns( [ ('fixed', len(message), msgpart), ('weight', 1, choicespart), ], dividechars=1) else: # above both = urwid.Pile([msgpart, choicespart]) att = settings.get_theming_attribute('global', 'prompt') both = urwid.AttrMap(both, att, att) # put promptwidget as overlay on main widget overlay = urwid.Overlay(both, oldroot, ('fixed left', 0), ('fixed right', 0), ('fixed bottom', 1), None) self.mainloop.widget = overlay self._passall = True return d # return deferred
def prompt(self, prefix, text=u'', completer=None, tab=0, history=[]): """ prompt for text input. This returns a :class:`~twisted.defer.Deferred` that calls back with the input string. :param prefix: text to print before the input field :type prefix: str :param text: initial content of the input field :type text: str :param completer: completion object to use :type completer: :meth:`alot.completion.Completer` :param tab: number of tabs to press initially (to select completion results) :type tab: int :param history: history to be used for up/down keys :type history: list of str :rtype: :class:`twisted.defer.Deferred` """ d = defer.Deferred() # create return deferred oldroot = self.mainloop.widget def select_or_cancel(text): # restore main screen and invoke callback # (delayed return) with given text self.mainloop.widget = oldroot self._passall = False d.callback(text) prefix = prefix + settings.get('prompt_suffix') #set up widgets leftpart = urwid.Text(prefix, align='left') editpart = CompleteEdit(completer, on_exit=select_or_cancel, edit_text=text, history=history) for i in range(tab): # hit some tabs editpart.keypress((0,), 'tab') # build promptwidget both = urwid.Columns( [ ('fixed', len(prefix), leftpart), ('weight', 1, editpart), ]) att = settings.get_theming_attribute('global', 'prompt') both = urwid.AttrMap(both, att) # put promptwidget as overlay on main widget overlay = urwid.Overlay(both, oldroot, ('fixed left', 0), ('fixed right', 0), ('fixed bottom', 1), None) self.mainloop.widget = overlay self._passall = True return d # return deferred
def prompt(self, prefix, text=u'', completer=None, tab=0, history=[]): """ prompt for text input. This returns a :class:`~twisted.defer.Deferred` that calls back with the input string. :param prefix: text to print before the input field :type prefix: str :param text: initial content of the input field :type text: str :param completer: completion object to use :type completer: :meth:`alot.completion.Completer` :param tab: number of tabs to press initially (to select completion results) :type tab: int :param history: history to be used for up/down keys :type history: list of str :rtype: :class:`twisted.defer.Deferred` """ d = defer.Deferred() # create return deferred oldroot = self.mainloop.widget def select_or_cancel(text): # restore main screen and invoke callback # (delayed return) with given text self.mainloop.widget = oldroot self._passall = False d.callback(text) prefix = prefix + settings.get('prompt_suffix') # set up widgets leftpart = urwid.Text(prefix, align='left') editpart = CompleteEdit(completer, on_exit=select_or_cancel, edit_text=text, history=history) for i in range(tab): # hit some tabs editpart.keypress((0,), 'tab') # build promptwidget both = urwid.Columns( [ ('fixed', len(prefix), leftpart), ('weight', 1, editpart), ]) att = settings.get_theming_attribute('global', 'prompt') both = urwid.AttrMap(both, att) # put promptwidget as overlay on main widget overlay = urwid.Overlay(both, oldroot, ('fixed left', 0), ('fixed right', 0), ('fixed bottom', 1), None) self.mainloop.widget = overlay self._passall = True return d # return deferred
def _get_header_widget(self): """creates/returns the widget that displays the mail header""" all_shown = (self._all_headers == self._displayed_headers) if self.headerw and (self.show_all_headers == all_shown): return self.headerw if self.show_all_headers: self._displayed_headers = self._all_headers else: self._displayed_headers = self._filtered_headers mail = self.message.get_email() # normalize values if only filtered list is shown norm = not (self._displayed_headers == self._all_headers) #build lines lines = [] for key in self._displayed_headers: if key in mail: if key.lower() in ['cc', 'bcc', 'to']: values = mail.get_all(key) dvalues = [ decode_header(v, normalize=norm) for v in values ] lines.append((key, ', '.join(dvalues))) else: for value in mail.get_all(key): dvalue = decode_header(value, normalize=norm) lines.append((key, dvalue)) key_att = settings.get_theming_attribute('thread', 'header_key') value_att = settings.get_theming_attribute('thread', 'header_value') cols = [HeadersList(lines, key_att, value_att)] bc = list() if self.depth: cols.insert(0, self._get_spacer(self.bars_at[1:])) bc.append(0) cols.insert(1, self._get_arrowhead_aligner()) bc.append(1) self.headerw = urwid.Columns(cols, box_columns=bc) return self.headerw
def rebuild(self): try: self.thread.refresh() except NonexistantObjectError: self.body = urwid.SolidFill() self.message_count = 0 return self._tree = ThreadTree(self.thread) bars_att = settings.get_theming_attribute('thread', 'arrow_bars') heads_att = settings.get_theming_attribute('thread', 'arrow_heads') A = ArrowTree(self._tree, indent=2, childbar_offset=0, arrow_tip_att=heads_att, arrow_att=bars_att, ) self._nested_tree = NestedTree(A, interpret_covered=True) self.body = TreeBox(self._nested_tree) self.message_count = self.thread.get_total_messages()
def _get_header_widget(self): """creates/returns the widget that displays the mail header""" all_shown = self._all_headers == self._displayed_headers if self.headerw and (self.show_all_headers == all_shown): return self.headerw if self.show_all_headers: self._displayed_headers = self._all_headers else: self._displayed_headers = self._filtered_headers mail = self.message.get_email() # normalize values if only filtered list is shown norm = not (self._displayed_headers == self._all_headers) # build lines lines = [] for key in self._displayed_headers: if key in mail: if key.lower() in ["cc", "bcc", "to"]: values = mail.get_all(key) values = [decode_header(v, normalize=norm) for v in values] lines.append((key, ", ".join(values))) else: for value in mail.get_all(key): dvalue = decode_header(value, normalize=norm) lines.append((key, dvalue)) key_att = settings.get_theming_attribute("thread", "header_key") value_att = settings.get_theming_attribute("thread", "header_value") cols = [HeadersList(lines, key_att, value_att)] bc = list() if self.depth: cols.insert(0, self._get_spacer(self.bars_at[1:])) bc.append(0) cols.insert(1, self._get_arrowhead_aligner()) bc.append(1) self.headerw = urwid.Columns(cols, box_columns=bc) return self.headerw
def choice(self, message, choices={"y": "yes", "n": "no"}, select=None, cancel=None, msg_position="above"): """ prompt user to make a choice :param message: string to display before list of choices :type message: unicode :param choices: dict of possible choices :type choices: dict: keymap->choice (both str) :param select: choice to return if enter/return is hit. Ignored if set to `None`. :type select: str :param cancel: choice to return if escape is hit. Ignored if set to `None`. :type cancel: str :param msg_position: determines if `message` is above or left of the prompt. Must be `above` or `left`. :type msg_position: str :returns: a :class:`twisted.defer.Deferred` """ assert select in choices.values() + [None] assert cancel in choices.values() + [None] assert msg_position in ["left", "above"] d = defer.Deferred() # create return deferred oldroot = self.inputwrap.get_root() def select_or_cancel(text): self.inputwrap.set_root(oldroot) self.inputwrap.select_cancel_only = False d.callback(text) # set up widgets msgpart = urwid.Text(message) choicespart = ChoiceWidget(choices, callback=select_or_cancel, select=select, cancel=cancel) # build widget if msg_position == "left": both = urwid.Columns([("fixed", len(message), msgpart), ("weight", 1, choicespart)], dividechars=1) else: # above both = urwid.Pile([msgpart, choicespart]) att = settings.get_theming_attribute("global", "prompt") both = urwid.AttrMap(both, att, att) # put promptwidget as overlay on main widget overlay = urwid.Overlay(both, oldroot, ("fixed left", 0), ("fixed right", 0), ("fixed bottom", 1), None) self.inputwrap.set_root(overlay) self.inputwrap.select_cancel_only = True return d # return deferred
def __init__(self, dbman, initialcmd): """ :param dbman: :class:`~alot.db.DBManager` :param initialcmd: commandline applied after setting up interface :type initialcmd: str :param colourmode: determines which theme to chose :type colourmode: int in [1,16,256] """ # store database manager self.dbman = dbman # define empty notification pile self._notificationbar = None # should we show a status bar? self._show_statusbar = settings.get("show_statusbar") # pass keypresses to the root widget and never interpret bindings self._passall = False # indicates "input lock": only focus move commands are interpreted self._locked = False self._unlock_callback = None # will be called after input lock ended self._unlock_key = None # key that ends input lock # alarm handle for callback that clears input queue (to cancel alarm) self._alarm = None # create root widget global_att = settings.get_theming_attribute("global", "body") mainframe = urwid.Frame(urwid.SolidFill()) self.root_widget = urwid.AttrMap(mainframe, global_att) # set up main loop self.mainloop = urwid.MainLoop( self.root_widget, handle_mouse=False, event_loop=urwid.TwistedEventLoop(), unhandled_input=self._unhandeled_input, input_filter=self._input_filter, ) # set up colours colourmode = int(settings.get("colourmode")) logging.info("setup gui in %d colours" % colourmode) self.mainloop.screen.set_terminal_properties(colors=colourmode) logging.debug("fire first command") self.apply_command(initialcmd) # start urwids mainloop self.mainloop.run()
def __init__(self, dbman, initialcmd): """ :param dbman: :class:`~alot.db.DBManager` :param initialcmd: commandline applied after setting up interface :type initialcmd: str :param colourmode: determines which theme to chose :type colourmode: int in [1,16,256] """ # store database manager self.dbman = dbman # define empty notification pile self._notificationbar = None # should we show a status bar? self._show_statusbar = settings.get('show_statusbar') # pass keypresses to the root widget and never interpret bindings self._passall = False # indicates "input lock": only focus move commands are interpreted self._locked = False self._unlock_callback = None # will be called after input lock ended self._unlock_key = None # key that ends input lock # alarm handle for callback that clears input queue (to cancel alarm) self._alarm = None # create root widget global_att = settings.get_theming_attribute('global', 'body') mainframe = urwid.Frame(urwid.SolidFill()) self.root_widget = urwid.AttrMap(mainframe, global_att) # set up main loop self.mainloop = urwid.MainLoop(self.root_widget, handle_mouse=False, event_loop=urwid.TwistedEventLoop(), unhandled_input=self._unhandeled_input, input_filter=self._input_filter) # set up colours colourmode = int(settings.get('colourmode')) logging.info('setup gui in %d colours' % colourmode) self.mainloop.screen.set_terminal_properties(colors=colourmode) logging.debug('fire first command') self.apply_command(initialcmd) # start urwids mainloop self.mainloop.run()
def prompt(self, prefix, text=u"", completer=None, tab=0, history=[]): """prompt for text input :param prefix: text to print before the input field :type prefix: str :param text: initial content of the input field :type text: str :param completer: completion object to use :type completer: :meth:`alot.completion.Completer` :param tab: number of tabs to press initially (to select completion results) :type tab: int :param history: history to be used for up/down keys :type history: list of str :returns: a :class:`twisted.defer.Deferred` """ d = defer.Deferred() # create return deferred oldroot = self.inputwrap.get_root() def select_or_cancel(text): # restore main screen and invoke callback # (delayed return) with given text self.inputwrap.set_root(oldroot) self.inputwrap.select_cancel_only = False d.callback(text) prefix = prefix + settings.get("prompt_suffix") # set up widgets leftpart = urwid.Text(prefix, align="left") editpart = CompleteEdit(completer, on_exit=select_or_cancel, edit_text=text, history=history) for i in range(tab): # hit some tabs editpart.keypress((0,), "tab") # build promptwidget both = urwid.Columns([("fixed", len(prefix), leftpart), ("weight", 1, editpart)]) att = settings.get_theming_attribute("global", "prompt") both = urwid.AttrMap(both, att) # put promptwidget as overlay on main widget overlay = urwid.Overlay(both, oldroot, ("fixed left", 0), ("fixed right", 0), ("fixed bottom", 1), None) self.inputwrap.set_root(overlay) self.inputwrap.select_cancel_only = True return d # return deferred
def build_statusbar(self): """construct and return statusbar widget""" if self.current_buffer is not None: idx = self.buffers.index(self.current_buffer) lefttxt = '%d: %s' % (idx, self.current_buffer) else: lefttxt = '[no buffers]' footerleft = urwid.Text(lefttxt, align='left') righttxt = 'total messages: %d' % self.dbman.count_messages('*') pending_writes = len(self.dbman.writequeue) if pending_writes > 0: righttxt = ('|' * pending_writes) + ' ' + righttxt footerright = urwid.Text(righttxt, align='right') columns = urwid.Columns([ footerleft, ('fixed', len(righttxt), footerright)]) footer_att = settings.get_theming_attribute('global', 'footer') return urwid.AttrMap(columns, footer_att)
def _get_theme(self, component, focus=False): attr_key = 'thread_{0}'.format(component) if focus: attr_key += '_focus' return settings.get_theming_attribute('search', attr_key)
def __init__(self, msg): bodytxt = message.extract_body(msg) att = settings.get_theming_attribute('thread', 'body') urwid.AttrMap.__init__(self, urwid.Text(bodytxt), att)
def build_line(msg, prio): cols = urwid.Columns([urwid.Text(msg)]) att = settings.get_theming_attribute('global', 'notify_' + prio) return urwid.AttrMap(cols, att)
def __init__(self, dbman, initialcmdline): """ :param dbman: :class:`~alot.db.DBManager` :param initialcmdline: commandline applied after setting up interface :type initialcmdline: str :param colourmode: determines which theme to chose :type colourmode: int in [1,16,256] """ self.dbman = dbman """Database Manager (:class:`~alot.db.manager.DBManager`)""" self.buffers = [] """list of active buffers""" self.current_buffer = None """points to currently active :class:`~alot.buffers.Buffer`""" self.db_was_locked = False """flag used to prevent multiple 'index locked' notifications""" self.mode = 'global' """interface mode identifier - type of current buffer""" self.commandprompthistory = [] """history of the command line prompt""" self.input_queue = [] """stores partial keyboard input""" self.last_commandline = None """saves the last executed commandline""" # define empty notification pile self._notificationbar = None # should we show a status bar? self._show_statusbar = settings.get('show_statusbar') # pass keypresses to the root widget and never interpret bindings self._passall = False # indicates "input lock": only focus move commands are interpreted self._locked = False self._unlock_callback = None # will be called after input lock ended self._unlock_key = None # key that ends input lock # alarm handle for callback that clears input queue (to cancel alarm) self._alarm = None # create root widget global_att = settings.get_theming_attribute('global', 'body') mainframe = urwid.Frame(urwid.SolidFill()) self.root_widget = urwid.AttrMap(mainframe, global_att) # set up main loop self.mainloop = urwid.MainLoop(self.root_widget, handle_mouse=False, event_loop=urwid.TwistedEventLoop(), unhandled_input=self._unhandeled_input, input_filter=self._input_filter) # set up colours colourmode = int(settings.get('colourmode')) logging.info('setup gui in %d colours' % colourmode) self.mainloop.screen.set_terminal_properties(colors=colourmode) logging.debug('fire first command') self.apply_commandline(initialcmdline) # start urwids mainloop self.mainloop.run()
def __init__(self, headerslist): self.headers = headerslist pile = urwid.Pile(self._build_lines(headerslist)) att = settings.get_theming_attribute('thread', 'header') pile = urwid.AttrMap(pile, att) urwid.WidgetWrap.__init__(self, pile)