def refresh(self): log.debug('Refresh: %s', self.__class__.__name__) if self.height <= 0: return if self.pos == 0: lines = self.built_lines[-self.height:] else: lines = self.built_lines[-self.height-self.pos:-self.pos] with_timestamps = config.get("show_timestamps") nick_size = config.get("max_nick_length") self._win.move(0, 0) self._win.erase() offset = 0 for y, line in enumerate(lines): if line: msg = line.msg if line.start_pos == 0: offset = self.write_pre_msg(msg, with_timestamps, nick_size) elif y == 0: offset = self.compute_offset(msg, with_timestamps, nick_size) self.write_text(y, offset, line.prepend + line.msg.txt[line.start_pos:line.end_pos]) else: self.write_line_separator(y) if y != self.height-1: self.addstr('\n') self._win.attrset(0) self._refresh()
def add_message(self, txt, time=None, nickname=None, nick_color=None, history=None, user=None, highlight=False, identifier=None, str_time=None, jid=None, ack=0): """ Create a message and add it to the text buffer """ msg = Message(txt, time, nickname, nick_color, history, user, identifier, str_time=str_time, highlight=highlight, jid=jid, ack=ack) self.messages.append(msg) while len(self.messages) > self._messages_nb_limit: self.messages.pop(0) ret_val = 0 show_timestamps = config.get('show_timestamps') nick_size = config.get('max_nick_length') for window in self._windows: # make the associated windows # build the lines from the new message nb = window.build_new_message(msg, history=history, highlight=highlight, timestamp=show_timestamps, nick_size=nick_size) if ret_val == 0: ret_val = nb if window.pos != 0: window.scroll_up(nb) return min(ret_val, 1)
def modify_message(self, old_id, message) -> None: """ Find a message, and replace it with a new one (instead of rebuilding everything in order to correct a message) """ with_timestamps = config.get('show_timestamps') nick_size = config.get('max_nick_length') for i in range(len(self.built_lines) - 1, -1, -1): current = self.built_lines[i] if current is not None and current.msg.identifier == old_id: index = i while ( index >= 0 and current is not None and current.msg.identifier == old_id ): self.built_lines.pop(index) index -= 1 if index >= 0: current = self.built_lines[index] index += 1 lines = build_lines( message, self.width, timestamp=with_timestamps, nick_size=nick_size ) for line in lines: self.built_lines.insert(index, line) index += 1 break
def refresh(self) -> None: log.debug('Refresh: %s', self.__class__.__name__) if self.height <= 0: return if self.pos == 0: lines = self.built_lines[-self.height:] else: lines = self.built_lines[-self.height - self.pos:-self.pos] with_timestamps = config.get("show_timestamps") nick_size = config.get("max_nick_length") self._win.move(0, 0) self._win.erase() offset = 0 for y, line in enumerate(lines): if line: msg = line.msg if line.start_pos == 0: offset = write_pre(msg, self, with_timestamps, nick_size) elif y == 0: offset = msg.compute_offset(with_timestamps, nick_size) self.write_text( y, offset, line.prepend + line.msg.txt[line.start_pos:line.end_pos]) else: self.write_line_separator(y) if y != self.height - 1: self.addstr('\n') self._win.attrset(0) self._refresh()
def rebuild_everything(self, room): self.built_lines = [] with_timestamps = config.get('show_timestamps') nick_size = config.get('max_nick_length') for message in room.messages: self.build_new_message(message, clean=False, timestamp=with_timestamps, nick_size=nick_size) if self.separator_after is message: self.build_new_message(None) while len(self.built_lines) > self.lines_nb_limit: self.built_lines.pop(0)
def refresh(self, roster: Roster) -> None: """ We display a number of lines from the roster cache (and rebuild it if needed) """ log.debug('Refresh: %s', self.__class__.__name__) self.build_roster_cache(roster) # make sure we are within bounds self.move_cursor_up(( self.roster_len + self.pos) if self.pos >= self.roster_len else 0) if not self.roster_cache: self.selected_row = None self._win.erase() self._win.move(0, 0) self.draw_roster_information(roster) y = 1 group = "none" # scroll down if needed if self.start_pos + self.height <= self.pos + 2: self.scroll_down(self.pos - self.start_pos - self.height + (self.height // 2)) # draw the roster from the cache roster_view = self.roster_cache[self.start_pos - 1:self.start_pos + self.height] options = { 'show_roster_sub': config.get('show_roster_subscriptions'), 'show_s2s_errors': config.get('show_s2s_errors'), 'show_roster_jids': config.get('show_roster_jids') } for item in roster_view: draw_selected = False if y - 2 + self.start_pos == self.pos: draw_selected = True self.selected_row = item if isinstance(item, RosterGroup): self.draw_group(y, item, draw_selected) group = item.name elif isinstance(item, Contact): self.draw_contact_line(y, item, draw_selected, group, **options) elif isinstance(item, Resource): self.draw_resource_line(y, item, draw_selected) y += 1 if self.start_pos > 1: self.draw_plus(1) if self.start_pos + self.height - 2 < self.roster_len: self.draw_plus(self.height - 1) self._refresh()
def refresh(self, roster: Roster) -> None: """ We display a number of lines from the roster cache (and rebuild it if needed) """ log.debug('Refresh: %s', self.__class__.__name__) self.build_roster_cache(roster) # make sure we are within bounds self.move_cursor_up((self.roster_len + self.pos) if self.pos >= self.roster_len else 0) if not self.roster_cache: self.selected_row = None self._win.erase() self._win.move(0, 0) self.draw_roster_information(roster) y = 1 group = "none" # scroll down if needed if self.start_pos + self.height <= self.pos + 2: self.scroll_down(self.pos - self.start_pos - self.height + (self.height // 2)) # draw the roster from the cache roster_view = self.roster_cache[self.start_pos - 1:self.start_pos + self.height] options = { 'show_roster_sub': config.get('show_roster_subscriptions'), 'show_s2s_errors': config.get('show_s2s_errors'), 'show_roster_jids': config.get('show_roster_jids') } for item in roster_view: draw_selected = False if y - 2 + self.start_pos == self.pos: draw_selected = True self.selected_row = item if isinstance(item, RosterGroup): self.draw_group(y, item, draw_selected) group = item.name elif isinstance(item, Contact): self.draw_contact_line(y, item, draw_selected, group, **options) elif isinstance(item, Resource): self.draw_resource_line(y, item, draw_selected) y += 1 if self.start_pos > 1: self.draw_plus(1) if self.start_pos + self.height - 2 < self.roster_len: self.draw_plus(self.height - 1) self._refresh()
def set(self, the_input): """Completion for /set""" args = common.shell_split(the_input.text) n = the_input.get_argument_position(quoted=True) if n >= len(args): args.append('') if n == 1: if '|' in args[1]: plugin_name, section = args[1].split('|')[:2] if plugin_name not in self.core.plugin_manager.plugins: return the_input.new_completion([], n, quotify=True) plugin = self.core.plugin_manager.plugins[plugin_name] end_list = ['%s|%s' % (plugin_name, section) for section in plugin.config.sections()] else: end_list = set(config.options('Poezio')) end_list.update(config.default.get('Poezio', {})) end_list = list(end_list) end_list.sort() elif n == 2: if '|' in args[1]: plugin_name, section = args[1].split('|')[:2] if plugin_name not in self.core.plugin_manager.plugins: return the_input.new_completion([''], n, quotify=True) plugin = self.core.plugin_manager.plugins[plugin_name] end_list = set(plugin.config.options(section or plugin_name)) if plugin.config.default: end_list.update(plugin.config.default.get(section or plugin_name, {})) end_list = list(end_list) end_list.sort() elif not config.has_option('Poezio', args[1]): if config.has_section(args[1]): end_list = config.options(args[1]) end_list.append('') else: end_list = [] else: end_list = [str(config.get(args[1], '')), ''] elif n == 3: if '|' in args[1]: plugin_name, section = args[1].split('|')[:2] if plugin_name not in self.core.plugin_manager.plugins: return the_input.new_completion([''], n, quotify=True) plugin = self.core.plugin_manager.plugins[plugin_name] end_list = [str(plugin.config.get(args[2], '', section or plugin_name)), ''] else: if not config.has_section(args[1]): end_list = [''] else: end_list = [str(config.get(args[2], '', args[1])), ''] else: return False return the_input.new_completion(end_list, n, quotify=True)
def set(self, the_input): """Completion for /set""" args = common.shell_split(the_input.text) n = the_input.get_argument_position(quoted=True) if n >= len(args): args.append('') if n == 1: if '|' in args[1]: plugin_name, section = args[1].split('|')[:2] if plugin_name not in self.core.plugin_manager.plugins: return Completion(the_input.new_completion, [], n, quotify=True) plugin = self.core.plugin_manager.plugins[plugin_name] end_list = ['%s|%s' % (plugin_name, section) for section in plugin.config.sections()] else: end_list = set(config.options('Poezio')) end_list.update(config.default.get('Poezio', {})) end_list = list(end_list) end_list.sort() elif n == 2: if '|' in args[1]: plugin_name, section = args[1].split('|')[:2] if plugin_name not in self.core.plugin_manager.plugins: return Completion(the_input.new_completion, [''], n, quotify=True) plugin = self.core.plugin_manager.plugins[plugin_name] end_list = set(plugin.config.options(section or plugin_name)) if plugin.config.default: end_list.update(plugin.config.default.get(section or plugin_name, {})) end_list = list(end_list) end_list.sort() elif not config.has_option('Poezio', args[1]): if config.has_section(args[1]): end_list = config.options(args[1]) end_list.append('') else: end_list = [] else: end_list = [str(config.get(args[1], '')), ''] elif n == 3: if '|' in args[1]: plugin_name, section = args[1].split('|')[:2] if plugin_name not in self.core.plugin_manager.plugins: return Completion(the_input.new_completion, [''], n, quotify=True) plugin = self.core.plugin_manager.plugins[plugin_name] end_list = [str(plugin.config.get(args[2], '', section or plugin_name)), ''] else: if not config.has_section(args[1]): end_list = [''] else: end_list = [str(config.get(args[2], '', args[1])), ''] else: return False return Completion(the_input.new_completion, end_list, n, quotify=True)
def start(self): """ Connect and process events. """ custom_host = config.get('custom_host') custom_port = config.get('custom_port', 5222) if custom_port == -1: custom_port = 5222 if custom_host: self.connect((custom_host, custom_port)) elif custom_port != 5222 and custom_port != -1: self.connect((self.boundjid.host, custom_port)) else: self.connect()
def add_message(self, txt: str, time: Optional[datetime] = None, nickname: Optional[str] = None, nick_color: Optional[Tuple] = None, history: bool = False, user: Optional[str] = None, highlight: bool = False, identifier: Optional[str] = None, str_time: Optional[str] = None, jid: Optional[str] = None, ack: int = 0) -> int: """ Create a message and add it to the text buffer """ msg = Message( txt, time, nickname, nick_color, history, user, identifier, str_time=str_time, highlight=highlight, jid=jid, ack=ack) self.messages.append(msg) while len(self.messages) > self._messages_nb_limit: self.messages.pop(0) ret_val = 0 show_timestamps = config.get('show_timestamps') nick_size = config.get('max_nick_length') for window in self._windows: # make the associated windows # build the lines from the new message nb = window.build_new_message( msg, history=history, highlight=highlight, timestamp=show_timestamps, nick_size=nick_size) if ret_val == 0: ret_val = nb if window.pos != 0: window.scroll_up(nb) return min(ret_val, 1)
def get_remote(self, xmpp, information, callback): """Add the remotely stored bookmarks to the list.""" force = config.get('force_remote_bookmarks') if xmpp.anon or not (any(self.available_storage.values()) or force): information('No remote bookmark storage available', 'Warning') return if force and not any(self.available_storage.values()): old_callback = callback method = 'pep' if self.preferred == 'pep' else 'privatexml' def new_callback(result): if result['type'] != 'error': self.available_storage[method] = True old_callback(result) else: information('No remote bookmark storage available', 'Warning') callback = new_callback if self.preferred == 'pep': self.get_pep(xmpp, callback=callback) else: self.get_privatexml(xmpp, callback=callback)
def reload_theme() -> Optional[str]: theme_name = config.get('theme') global theme if theme_name == 'default' or not theme_name.strip(): theme = Theme() return None new_theme = None exc = None try: loader = finder.find_module(theme_name, load_path) if not loader: return 'Failed to load the theme %s' % theme_name new_theme = loader.load_module() except Exception as e: log.error('Failed to load the theme %s', theme_name, exc_info=True) exc = e if not new_theme: return 'Failed to load theme: %s' % exc if hasattr(new_theme, 'theme'): theme = new_theme.theme prepare_ccolor_palette(theme) return None return 'No theme present in the theme file'
def refresh_tab_win(self): if config.get('enable_vertical_tab_list'): left_tab_win = self.core.left_tab_win if left_tab_win and not self.size.core_degrade_x: left_tab_win.refresh() elif not self.size.core_degrade_y: self.core.tab_win.refresh()
def init(self): self.key = config.get("key").encode('utf-8') length = 32 - (len(self.key) % 32) self.key += bytes([length]) * length # TODO: add real help/usage information to the commands… self.api.add_command("rot", self.command_rot, "rot n encodes the given message") self.api.add_command("bin", self.command_bin, "bin") self.api.add_command("hex", self.command_hex, "hex") self.api.add_command("enc", self.command_enc, "enc") self.api.add_command('rot_decode', self.command_rot_decode, usage='<message>', help='Decode the message you typed if it exists.', short='Decode a message.', completion=self.message_completion) self.api.add_command("mono_crack", self.command_mono_crack, usage="<message>", help="mono decode", short="decode", completion=self.message_completion) self.api.add_command("bin_decode", self.command_bin_decode, usage="<message>", help="binary decode", short='binary', completion=self.message_completion) self.api.add_command("crack", self.command_crack, usage="<message>", help="binary decode", short='binary', completion=self.message_completion) # insert event handler at the end (-1) so we're always behind the lima-gold one self.api.add_event_handler("muc_msg", self.muc_message, position=-1) # preload german dict self.get_dict("de")
def refresh(self, jid, contact, window, chatstate, information): # contact can be None, if we receive a message # from someone not in our roster. In this case, we display # only the maximum information from the message we can get. log.debug('Refresh: %s', self.__class__.__name__) jid = safeJID(jid) if contact: if jid.resource: resource = contact[jid.full] else: resource = contact.get_highest_priority_resource() else: resource = None # if contact is None, then resource is None too: # user is not in the roster so we know almost nothing about it # If contact is a Contact, then # resource can now be a Resource: user is in the roster and online # or resource is None: user is in the roster but offline self._win.erase() if config.get('show_jid_in_conversations'): self.write_contact_jid(jid) self.write_contact_information(contact) self.write_resource_information(resource) self.print_scroll_position(window) self.write_chatstate(chatstate) self.write_additional_information(information, jid) self.finish_line(get_theme().COLOR_INFORMATION_BAR) self._refresh()
def __init__(self) -> None: self._image = None # type: Optional[Image.Image] Win.__init__(self) if config.get('image_use_half_blocks'): self._display_avatar = self._display_avatar_half_blocks # type: Callable[[int, int], None] else: self._display_avatar = self._display_avatar_full_blocks
def callback(iq): if iq['type'] == 'result': self.core.information('Password updated', 'Account') if config.get('password'): config.silent_set('password', args[0]) else: self.core.information('Unable to change the password', 'Account')
def get_local(self): """Add the locally stored bookmarks to the list.""" rooms = config.get('rooms') if not rooms: return rooms = rooms.split(':') for room in rooms: try: jid = JID(room) except InvalidJID: continue if jid.bare == '': continue if jid.resource != '': nick = jid.resource else: nick = None passwd = config.get_by_tabname( 'password', jid.bare, fallback=False) or None b = Bookmark(jid.bare, jid.user, autojoin=True, nick=nick, password=passwd, method='local') self.append(b)
def __init__(self): self._image = None Win.__init__(self) if config.get('image_use_half_blocks'): self._display_avatar = self._display_avatar_half_blocks else: self._display_avatar = self._display_avatar_full_blocks
def bookmark_local(self, the_input): """Completion for /bookmark_local""" n = the_input.get_argument_position(quoted=True) args = common.shell_split(the_input.text) if n >= 2: return False if len(args) == 1: args.append('') jid = safeJID(args[1]) if jid.server and (jid.resource or jid.full.endswith('/')): tab = self.core.tabs.by_name_and_class(jid.bare, tabs.MucTab) nicks = [tab.own_nick] if tab else [] default = os.environ.get('USER') if os.environ.get( 'USER') else 'poezio' nick = config.get('default_nick') if not nick: if default not in nicks: nicks.append(default) else: if nick not in nicks: nicks.append(nick) jids_list = ['%s/%s' % (jid.bare, nick) for nick in nicks] return Completion( the_input.new_completion, jids_list, 1, quotify=True) muc_list = [tab.name for tab in self.core.get_tabs(tabs.MucTab)] muc_list.append('*') return Completion(the_input.new_completion, muc_list, 1, quotify=True)
def update_themes_dir(option: Optional[str] = None, value: Optional[str] = None): global load_path load_path = [] # import from the git sources default_dir = path.join( path.dirname(path.dirname(__file__)), 'data/themes') if path.exists(default_dir): load_path.append(default_dir) # import from the user-defined prefs themes_dir_str = config.get('themes_dir') themes_dir = Path(themes_dir_str).expanduser( ) if themes_dir_str else xdg.DATA_HOME / 'themes' try: themes_dir.mkdir(parents=True, exist_ok=True) except OSError: log.exception('Unable to create the themes dir (%s):', themes_dir) else: load_path.append(str(themes_dir)) # system-wide import try: import poezio_themes except ImportError: pass else: if poezio_themes.__path__: load_path.append(list(poezio_themes.__path__)[0]) log.debug('Theme load path: %s', load_path)
def bookmark_local(self, the_input): """Completion for /bookmark_local""" n = the_input.get_argument_position(quoted=True) args = common.shell_split(the_input.text) if n >= 2: return False if len(args) == 1: args.append('') jid = safeJID(args[1]) if jid.server and (jid.resource or jid.full.endswith('/')): tab = self.core.get_tab_by_name(jid.bare, tabs.MucTab) nicks = [tab.own_nick] if tab else [] default = os.environ.get('USER') if os.environ.get('USER') else 'poezio' nick = config.get('default_nick') if not nick: if default not in nicks: nicks.append(default) else: if nick not in nicks: nicks.append(nick) jids_list = ['%s/%s' % (jid.bare, nick) for nick in nicks] return Completion(the_input.new_completion, jids_list, 1, quotify=True) muc_list = [tab.name for tab in self.core.get_tabs(tabs.MucTab)] muc_list.append('*') return Completion(the_input.new_completion, muc_list, 1, quotify=True)
def update_themes_dir(option: Optional[str] = None, value: Optional[str] = None): global load_path load_path = [] # import from the git sources default_dir = path.join(path.dirname(path.dirname(__file__)), 'data/themes') if path.exists(default_dir): load_path.append(default_dir) # import from the user-defined prefs themes_dir_str = config.get('themes_dir') themes_dir = Path(themes_dir_str).expanduser( ) if themes_dir_str else xdg.DATA_HOME / 'themes' try: themes_dir.mkdir(parents=True, exist_ok=True) except OSError: log.exception('Unable to create the themes dir (%s):', themes_dir) else: load_path.append(str(themes_dir)) # system-wide import try: import poezio_themes except ImportError: pass else: if poezio_themes.__path__: load_path.append(list(poezio_themes.__path__)[0]) log.debug('Theme load path: %s', load_path)
def __init__(self) -> None: self._image = None # type: Optional[Image] Win.__init__(self) if config.get('image_use_half_blocks'): self._display_avatar = self._display_avatar_half_blocks # type: Callable[[int, int], None] else: self._display_avatar = self._display_avatar_full_blocks
def join(self, args): """ /join [room][/nick] [password] """ if len(args) == 0: room, nick = self._empty_join() else: room, nick = self._parse_join_jid(args[0]) if not room and not nick: return # nothing was parsed room = room.lower() if nick == '': nick = self.core.own_nick # a password is provided if len(args) == 2: password = args[1] else: password = config.get_by_tabname('password', room, fallback=False) if room in self.core.pending_invites: del self.core.pending_invites[room] tab = self.core.tabs.by_name_and_class(room, tabs.MucTab) # New tab if tab is None: tab = self.core.open_new_room(room, nick, password=password) tab.join() else: self.core.focus_tab(tab) if tab.own_nick == nick and tab.joined: self.core.information('/join: Nothing to do.', 'Info') else: tab.command_part('') tab.own_nick = nick tab.password = password tab.join() if config.get('bookmark_on_join'): method = 'remote' if config.get( 'use_remote_bookmarks') else 'local' self._add_bookmark('%s/%s' % (room, nick), True, password, method) if tab == self.core.tabs.current_tab: tab.refresh() self.core.doupdate()
def goto_build_lines(self, new_date): text_buffer = self._text_buffer built_lines = [] message_count = 0 timestamp = config.get('show_timestamps') nick_size = config.get('max_nick_length') for message in text_buffer.messages: # Build lines of a message txt = message.txt nick = truncate_nick(message.nickname, nick_size) offset = 0 theme = get_theme() if message.ack: if message.ack > 0: offset += poopt.wcswidth(theme.CHAR_ACK_RECEIVED) + 1 else: offset += poopt.wcswidth(theme.CHAR_NACK) + 1 if nick: offset += poopt.wcswidth(nick) + 2 if message.revisions > 0: offset += ceil(log10(message.revisions + 1)) if message.me: offset += 1 if timestamp: if message.str_time: offset += 1 + len(message.str_time) if theme.CHAR_TIME_LEFT and message.str_time: offset += 1 if theme.CHAR_TIME_RIGHT and message.str_time: offset += 1 lines = poopt.cut_text(txt, self.text_win.width - offset - 1) for line in lines: built_lines.append(line) # Find the message with timestamp less than or equal to the queried # timestamp and goto that location in the tab. if message.time <= new_date: message_count += 1 if len(self.text_win.built_lines ) - self.text_win.height >= len(built_lines): self.text_win.pos = len( self.text_win.built_lines ) - self.text_win.height - len(built_lines) + 1 else: self.text_win.pos = 0 if message_count == 0: self.text_win.scroll_up(len(self.text_win.built_lines)) self.core.refresh_window()
def join(self, args): """ /join [room][/nick] [password] """ if len(args) == 0: room, nick = self._empty_join() else: room, nick = self._parse_join_jid(args[0]) if not room and not nick: return # nothing was parsed room = room.lower() if nick == '': nick = self.core.own_nick # a password is provided if len(args) == 2: password = args[1] else: password = config.get_by_tabname('password', room, fallback=False) if room in self.core.pending_invites: del self.core.pending_invites[room] tab = self.core.get_tab_by_name(room, tabs.MucTab) # New tab if tab is None: tab = self.core.open_new_room(room, nick, password=password) tab.join() else: self.core.focus_tab_named(tab.name) if tab.own_nick == nick and tab.joined: self.core.information('/join: Nothing to do.', 'Info') else: tab.command_part('') tab.own_nick = nick tab.password = password tab.join() if config.get('bookmark_on_join'): method = 'remote' if config.get( 'use_remote_bookmarks') else 'local' self._add_bookmark('%s/%s' % (room, nick), True, password, method) if tab == self.core.current_tab(): tab.refresh() self.core.doupdate()
def refresh(self) -> None: height, width = self._win.getmaxyx() self._win.erase() sorted_tabs = [tab for tab in self.core.tabs if tab] theme = get_theme() if not config.get('show_inactive_tabs'): sorted_tabs = [ tab for tab in sorted_tabs if tab.vertical_color != theme.COLOR_VERTICAL_TAB_NORMAL ] nb_tabs = len(sorted_tabs) use_nicks = config.get('use_tab_nicks') if nb_tabs >= height: # TODO: As sorted_tabs filters out gap tabs this ensures pos is # always set, preventing UnboundLocalError. Now is this how this # should be fixed. pos = 0 for y, tab in enumerate(sorted_tabs): if tab.vertical_color == theme.COLOR_VERTICAL_TAB_CURRENT: pos = y break # center the current tab as much as possible if pos < height // 2: sorted_tabs = sorted_tabs[:height] elif nb_tabs - pos <= height // 2: sorted_tabs = sorted_tabs[-height:] else: sorted_tabs = sorted_tabs[pos - height // 2:pos + height // 2] asc_sort = (config.get('vertical_tab_list_sort') == 'asc') for y, tab in enumerate(sorted_tabs): color = tab.vertical_color if asc_sort: y = height - y - 1 self.addstr(y, 0, "%2d" % tab.nb, to_curses_attr(theme.COLOR_VERTICAL_TAB_NUMBER)) self.addstr('.') if use_nicks: self.addnstr("%s" % tab.get_nick(), width - 4, to_curses_attr(color)) else: self.addnstr("%s" % tab.name, width - 4, to_curses_attr(color)) separator = to_curses_attr(theme.COLOR_VERTICAL_SEPARATOR) self._win.attron(separator) self._win.vline(0, width - 1, curses.ACS_VLINE, height) self._win.attroff(separator) self._refresh()
def tab_win_height() -> int: """ Returns 1 or 0, depending on if we are using the vertical tab list or not. """ if config.get('enable_vertical_tab_list'): return 0 return 1
def __init__(self): Input.__init__(self) self.help_message = '' self.current_completed = '' self.key_func['^R'] = self.toggle_search self.search = False if config.get('separate_history'): self.history = list()
def initial_set_plugins_dir(self): """ Set the plugins_dir on start """ plugins_dir = config.get('plugins_dir') self.plugins_dir = Path(plugins_dir).expanduser( ) if plugins_dir else xdg.DATA_HOME / 'plugins' self.check_create_plugins_dir()
def initial_set_plugins_conf_dir(self): """ Create the plugins_conf_dir """ plugins_conf_dir = config.get('plugins_conf_dir') self.plugins_conf_dir = Path(plugins_conf_dir).expanduser( ) if plugins_conf_dir else xdg.CONFIG_HOME / 'plugins' self.check_create_plugins_conf_dir()
def refresh(self): log.debug('Refresh: %s', self.__class__.__name__) self._win.erase() self.addstr(0, 0, "[", to_curses_attr(get_theme().COLOR_INFORMATION_BAR)) create_gaps = config.get('create_gaps') show_names = config.get('show_tab_names') show_nums = config.get('show_tab_numbers') use_nicks = config.get('use_tab_nicks') show_inactive = config.get('show_inactive_tabs') # ignore any remaining gap tabs if the feature is not enabled if create_gaps: sorted_tabs = self.core.tabs[:] else: sorted_tabs = [tab for tab in self.core.tabs if tab] for nb, tab in enumerate(sorted_tabs): if not tab: continue color = tab.color if not show_inactive and color is get_theme().COLOR_TAB_NORMAL: continue try: if show_nums or not show_names: self.addstr("%s" % str(nb), to_curses_attr(color)) if show_names: self.addstr(' ', to_curses_attr(color)) if show_names: if use_nicks: self.addstr("%s" % str(tab.get_nick()), to_curses_attr(color)) else: self.addstr("%s" % tab.name, to_curses_attr(color)) self.addstr("|", to_curses_attr(get_theme().COLOR_INFORMATION_BAR)) except: # end of line break (y, x) = self._win.getyx() self.addstr(y, x - 1, '] ', to_curses_attr(get_theme().COLOR_INFORMATION_BAR)) (y, x) = self._win.getyx() remaining_size = self.width - x self.addnstr(' ' * remaining_size, remaining_size, to_curses_attr(get_theme().COLOR_INFORMATION_BAR)) self._refresh()
def __init__(self) -> None: Input.__init__(self) self.help_message = '' self.histo_pos = -1 self.current_completed = '' self.key_func['^R'] = self.toggle_search self.search = False if config.get('separate_history'): self.history = [] # type: List[str]
def __init__(self): Input.__init__(self) self.help_message = '' self.histo_pos = -1 self.current_completed = '' self.key_func['^R'] = self.toggle_search self.search = False if config.get('separate_history'): self.history = list()
def command_reorder(self) -> None: """ /reorder """ tabs_spec = parse_config(self.config) if not tabs_spec: self.api.information('Invalid reorder config', 'Error') return None old_tabs = self.core.tabs.get_tabs() roster = old_tabs.pop(0) create_gaps = config.get('create_gaps') new_tabs = [roster] last = 0 for pos in sorted(tabs_spec): if create_gaps and pos > last + 1: new_tabs += [ tabs.GapTab(self.core) for i in range(pos - last - 1) ] cls, jid = tabs_spec[pos] try: jid = JID(jid) tab = self.core.tabs.by_name_and_class(str(jid), cls=cls) if tab and tab in old_tabs: new_tabs.append(tab) old_tabs.remove(tab) else: self.api.information('Tab %s not found. Creating it' % jid, 'Warning') # TODO: Add support for MucTab. Requires nickname. if cls in (tabs.DynamicConversationTab, tabs.StaticConversationTab): new_tab = cls(self.core, jid) new_tabs.append(new_tab) else: new_tabs.append(tabs.GapTab(self.core)) except: self.api.information('Failed to create tab \'%s\'.' % jid, 'Error') if create_gaps: new_tabs.append(tabs.GapTab(self.core)) finally: last = pos for tab in old_tabs: if tab: new_tabs.append(tab) # TODO: Ensure we don't break poezio and call this with whatever # tablist we have. The roster tab at least needs to be in there. self.core.tabs.replace_tabs(new_tabs) self.core.refresh_window() return None
def quit(self, args): """ /quit [message] """ if not self.core.xmpp.is_connected(): self.core.exit() return msg = args[0] if config.get('enable_user_mood'): self.core.xmpp.plugin['xep_0107'].stop() if config.get('enable_user_activity'): self.core.xmpp.plugin['xep_0108'].stop() if config.get('enable_user_gaming'): self.core.xmpp.plugin['xep_0196'].stop() self.core.save_config() self.core.plugin_manager.disable_plugins() self.core.disconnect(msg) self.core.xmpp.add_event_handler("disconnected", self.core.exit, disposable=True)
def __init__(self): self.bookmarks = [] # type: List[Bookmark] preferred = config.get('use_bookmarks_method').lower() if preferred not in ('pep', 'privatexml'): preferred = 'privatexml' self.preferred = preferred self.available_storage = { 'privatexml': False, 'pep': False, }
def __init__(self) -> None: Input.__init__(self) self.help_message = '' self.histo_pos = -1 self.current_completed = '' self.key_func['^R'] = self.toggle_search self.search = False if config.get('separate_history'): # pylint: disable=assigning-non-slot self.history = [] # type: List[str]
def modify_message(self, old_id, message): """ Find a message, and replace it with a new one (instead of rebuilding everything in order to correct a message) """ with_timestamps = config.get('show_timestamps') nick_size = config.get('max_nick_length') for i in range(len(self.built_lines)-1, -1, -1): if self.built_lines[i] and self.built_lines[i].msg.identifier == old_id: index = i while index >= 0 and self.built_lines[index] and self.built_lines[index].msg.identifier == old_id: self.built_lines.pop(index) index -= 1 index += 1 lines = self.build_message(message, timestamp=with_timestamps, nick_size=nick_size) for line in lines: self.built_lines.insert(index, line) index += 1 break
def refresh(self) -> None: height, width = self._win.getmaxyx() self._win.erase() sorted_tabs = [tab for tab in self.core.tabs if tab] theme = get_theme() if not config.get('show_inactive_tabs'): sorted_tabs = [ tab for tab in sorted_tabs if tab.vertical_color != theme.COLOR_VERTICAL_TAB_NORMAL ] nb_tabs = len(sorted_tabs) use_nicks = config.get('use_tab_nicks') if nb_tabs >= height: for y, tab in enumerate(sorted_tabs): if tab.vertical_color == theme.COLOR_VERTICAL_TAB_CURRENT: pos = y break # center the current tab as much as possible if pos < height // 2: sorted_tabs = sorted_tabs[:height] elif nb_tabs - pos <= height // 2: sorted_tabs = sorted_tabs[-height:] else: sorted_tabs = sorted_tabs[pos - height // 2:pos + height // 2] asc_sort = (config.get('vertical_tab_list_sort') == 'asc') for y, tab in enumerate(sorted_tabs): color = tab.vertical_color if asc_sort: y = height - y - 1 self.addstr(y, 0, "%2d" % tab.nb, to_curses_attr(theme.COLOR_VERTICAL_TAB_NUMBER)) self.addstr('.') if use_nicks: self.addnstr("%s" % tab.get_nick(), width - 4, to_curses_attr(color)) else: self.addnstr("%s" % tab.name, width - 4, to_curses_attr(color)) separator = to_curses_attr(theme.COLOR_VERTICAL_SEPARATOR) self._win.attron(separator) self._win.vline(0, width - 1, curses.ACS_VLINE, height) self._win.attroff(separator) self._refresh()
def __init__(self, messages_nb_limit: Optional[int] = None) -> None: if messages_nb_limit is None: messages_nb_limit = config.get('max_messages_in_memory') self._messages_nb_limit = messages_nb_limit # type: int # Message objects self.messages = [] # type: List[Message] # we keep track of one or more windows # so we can pass the new messages to them, as they are added, so # they (the windows) can build the lines from the new message self._windows = []
def hl(tab): """ Make a tab beep and change its status. """ if tab.state != 'current': tab.state = 'private' conv_jid = safeJID(tab.name) if 'private' in config.get('beep_on', 'highlight private').split(): if not config.get_by_tabname('disable_beep', conv_jid.bare, default=False): curses.beep()
def refresh(self) -> None: log.debug('Refresh: %s', self.__class__.__name__) self._win.erase() theme = get_theme() self.addstr(0, 0, "[", to_curses_attr(theme.COLOR_INFORMATION_BAR)) show_names = config.get('show_tab_names') show_nums = config.get('show_tab_numbers') use_nicks = config.get('use_tab_nicks') show_inactive = config.get('show_inactive_tabs') for nb, tab in enumerate(self.core.tabs): if not tab: continue color = tab.color if not show_inactive and color is theme.COLOR_TAB_NORMAL: continue try: if show_nums or not show_names: self.addstr("%s" % str(nb), to_curses_attr(color)) if show_names: self.addstr(' ', to_curses_attr(color)) if show_names: if use_nicks: self.addstr("%s" % str(tab.get_nick()), to_curses_attr(color)) else: self.addstr("%s" % tab.name, to_curses_attr(color)) self.addstr("|", to_curses_attr(theme.COLOR_INFORMATION_BAR)) except: # end of line break (y, x) = self._win.getyx() self.addstr(y, x - 1, '] ', to_curses_attr(theme.COLOR_INFORMATION_BAR)) (y, x) = self._win.getyx() remaining_size = self.width - x self.addnstr(' ' * remaining_size, remaining_size, to_curses_attr(theme.COLOR_INFORMATION_BAR)) self._refresh()
def refresh(self): log.debug('Refresh: %s', self.__class__.__name__) self._win.erase() self.addstr(0, 0, "[", to_curses_attr(get_theme().COLOR_INFORMATION_BAR)) create_gaps = config.get('create_gaps') show_names = config.get('show_tab_names') show_nums = config.get('show_tab_numbers') use_nicks = config.get('use_tab_nicks') show_inactive = config.get('show_inactive_tabs') # ignore any remaining gap tabs if the feature is not enabled if create_gaps: sorted_tabs = self.core.tabs[:] else: sorted_tabs = [tab for tab in self.core.tabs if tab] for nb, tab in enumerate(sorted_tabs): if not tab: continue color = tab.color if not show_inactive and color is get_theme().COLOR_TAB_NORMAL: continue try: if show_nums or not show_names: self.addstr("%s" % str(nb), to_curses_attr(color)) if show_names: self.addstr(' ', to_curses_attr(color)) if show_names: if use_nicks: self.addstr("%s" % str(tab.get_nick()), to_curses_attr(color)) else: self.addstr("%s" % tab.name, to_curses_attr(color)) self.addstr("|", to_curses_attr(get_theme().COLOR_INFORMATION_BAR)) except: # end of line break (y, x) = self._win.getyx() self.addstr(y, x-1, '] ', to_curses_attr(get_theme().COLOR_INFORMATION_BAR)) (y, x) = self._win.getyx() remaining_size = self.width - x self.addnstr(' '*remaining_size, remaining_size, to_curses_attr(get_theme().COLOR_INFORMATION_BAR)) self._refresh()
def __init__(self, lines_nb_limit=None): if lines_nb_limit is None: lines_nb_limit = config.get('max_lines_in_memory') Win.__init__(self) self.lines_nb_limit = lines_nb_limit self.pos = 0 self.built_lines = [] # Each new message is built and kept here. # on resize, we rebuild all the messages self.lock = False self.lock_buffer = [] self.separator_after = None
def toggle_offline_show(self): """ Show or hide offline contacts """ option = 'roster_show_offline' value = config.get(option) success = config.silent_set(option, str(not value)) roster.modified() if not success: self.core.information('Unable to write in the config file', 'Error') return True