def render(self, screen, row, width=None, active=False, focused=True, col=0, cursor_offset=0, **kwargs): if not self.value and not active and len(self.default_value) != 0: self.value = self.default_value self.cursor = len(self.value) if self.message: self.parent.add_string(row, self.message, scr=screen, col=col, pad=False) row += 1 vstr = self.calculate_textfield_value(width, cursor_offset) if active: if self.opts: self.parent.add_string(row + 1, self.opts[self.opt_off:], scr=screen, col=col, pad=False) if focused and self.input_active: util.safe_curs_set(util.Curser.NORMAL) # Make cursor visible when text field is focused x_pos = self.calculate_cursor_pos(width, col) self.move_func(row, x_pos) fmt = '{!black,white,bold!}%s' if self.format_default and len(self.value) != 0 and self.value == self.default_value: fmt = '{!magenta,white!}%s' if not active or not focused or self.input_active: fmt = '{!white,grey,bold!}%s' self.parent.add_string(row, fmt % vstr, scr=screen, col=col, pad=False, trim=False) return self.height
def render(self, screen, row, active=False, focused=False, col=0, width=None, **kwargs): util.safe_curs_set(util.Curser.INVISIBLE ) # Make cursor invisible when text field is active fmt = self.build_fmt_string(focused, active) self.fmt_keys['msg'] = self.txt if self.fill_width: self.fmt_keys['msg'] = '' string_len = len(remove_formatting(fmt % self.fmt_keys)) fill_len = width - string_len - (len(self.txt) - 1) self.fmt_keys['msg'] = self.txt * fill_len string = fmt % self.fmt_keys self.parent.add_string(row, string, scr=screen, col=col, pad=False, trim=False) return 1
def render(self, screen, row, active=False, focused=True, col=0, cursor_offset=0, **kwargs): if active: self.last_active = True elif self.last_active: self.set_value(self.valstr, validate=True, value_on_fail=self.last_valid_value) self.last_active = False fmt_str = self.build_fmt_string(focused, active, value_key='value') value_format = '%(msg)s {!input!}' if not self.valstr: value_format += '[ ]' elif self.format_default and self.valstr == self.default_str: value_format += '[ {!magenta,black!}%(value)s{!input!} ]' else: value_format += '[ ' + fmt_str + ' ]' self.parent.add_string(row, value_format % dict({'msg': self.message, 'value': '%s' % self.valstr}, **self.fmt_keys), scr=screen, col=col, pad=False) if active: if focused: util.safe_curs_set(util.Curser.NORMAL) self.move_func(row, self.cursor + self.cursoff + cursor_offset) else: util.safe_curs_set(util.Curser.INVISIBLE) return 1
def __init__(self, stdscr, encoding=None): BaseMode.__init__(self, stdscr, encoding=encoding, do_refresh=False, depend=['SessionProxy']) PopupsHandler.__init__(self) self.messages = deque() self.last_mark = -1 self.go_top = False self.minor_mode = None self.consoleui = component.get('ConsoleUI') self.coreconfig = self.consoleui.coreconfig self.config = self.consoleui.config self.sidebar = FilterSidebar(self, self.config) self.torrentview_panel = mkwin( curses.COLOR_GREEN, curses.LINES - 1, curses.COLS - self.sidebar.width, 0, self.sidebar.width, ) self.torrentview = torrentview.TorrentView(self, self.config) util.safe_curs_set(util.Curser.INVISIBLE) self.stdscr.notimeout(0)
def __init__(self, parent_mode, stdscr, console_config, encoding=None): self.console_config = console_config self.parent_mode = parent_mode self.popup = None self.view_offset = 0 self.cursel = 0 self.marked = set() self.last_mark = -1 path = os.path.expanduser(self.console_config['addtorrents']['last_path']) self.path_stack = ['/'] + path.strip('/').split('/') self.path_stack_pos = len(self.path_stack) self.listing_files = [] self.listing_dirs = [] self.raw_rows = [] self.raw_rows_files = [] self.raw_rows_dirs = [] self.formatted_rows = [] self.sort_column = self.console_config['addtorrents']['sort_column'] self.reverse_sort = self.console_config['addtorrents']['reverse_sort'] BaseMode.__init__(self, stdscr, encoding) self._listing_space = self.rows - 5 self.__refresh_listing() util.safe_curs_set(util.Curser.INVISIBLE) self.stdscr.notimeout(0)
def update_cursor(self): util.safe_curs_set(util.Curser.VERY_VISIBLE) move_cursor( self.torrentlist.stdscr, self.torrentlist.rows - 1, len(self.search_string) + 17, )
def render_inputs(self, focused=False): self._cursor_row = -1 self._cursor_col = -1 util.safe_curs_set(util.Curser.INVISIBLE) self.ensure_active_visible() crow = self.border_off_north for i, ipt in enumerate(self.inputs): if ipt.depend_skip(): continue col = self.border_off_west field_width = self.width - self.border_off_east - self.border_off_west cursor_offset = self.border_off_west if ipt.default_col != -1: default_col = int(ipt.default_col) if isinstance(ipt.default_col, ''.__class__) and ipt.default_col[0] in ['+', '-']: col += default_col cursor_offset += default_col field_width -= default_col # Increase to col must be reflected here else: col = default_col crow += ipt.render(self.screen, crow, width=field_width, active=i == self.active_input, focused=focused, col=col, cursor_offset=cursor_offset) if self._cursor_row >= 0: util.safe_curs_set(util.Curser.VERY_VISIBLE) move_cursor(self.screen, self._cursor_row, self._cursor_col)
def render(self, screen, row, active=False, focused=False, col=0, **kwargs): util.safe_curs_set(util.Curser.INVISIBLE) # Make cursor invisible when text field is active fmt = self.build_fmt_string(focused, active) self.fmt_keys['msg'] = self.txt string = fmt % self.fmt_keys self.parent.add_string(row, string, scr=screen, col=col, pad=False, trim=False) return 1
def render(self, screen, row, col=0, **kwargs): util.safe_curs_set(util.Curser.INVISIBLE) # Make cursor invisible when text field is active color = '{!white,black!}' lines = wrap_string(self.txt, self.parent.width - 3, 3, True) for i, line in enumerate(lines): self.parent.add_string(row + i, '%s%s' % (color, line), scr=screen, col=col, pad=False, trim=False) return len(lines)
def render(self, screen, row, active=False, focused=False, col=0, width=None, **kwargs): util.safe_curs_set(util.Curser.INVISIBLE) # Make cursor invisible when text field is active fmt = self.build_fmt_string(focused, active) self.fmt_keys['msg'] = self.txt if self.fill_width: self.fmt_keys['msg'] = '' string_len = len(remove_formatting(fmt % self.fmt_keys)) fill_len = width - string_len - (len(self.txt) - 1) self.fmt_keys['msg'] = self.txt * fill_len string = fmt % self.fmt_keys self.parent.add_string(row, string, scr=screen, col=col, pad=False, trim=False) return 1
def render(self, screen, row, width=None, active=False, focused=True, col=0, cursor_offset=0, **kwargs): if not self.value and not active and len(self.default_value) != 0: self.value = self.default_value self.cursor = len(self.value) if self.message: self.parent.add_string(row, self.message, scr=screen, col=col, pad=False) row += 1 vstr = self.calculate_textfield_value(width, cursor_offset) if active: if self.opts: self.parent.add_string(row + 1, self.opts[self.opt_off:], scr=screen, col=col, pad=False) if focused and self.input_active: util.safe_curs_set( util.Curser.NORMAL ) # Make cursor visible when text field is focused x_pos = self.calculate_cursor_pos(width, col) self.move_func(row, x_pos) fmt = '{!black,white,bold!}%s' if (self.format_default and len(self.value) != 0 and self.value == self.default_value): fmt = '{!magenta,white!}%s' if not active or not focused or self.input_active: fmt = '{!white,grey,bold!}%s' self.parent.add_string(row, fmt % vstr, scr=screen, col=col, pad=False, trim=False) return self.height
def render(self, screen, row, col=0, **kwargs): util.safe_curs_set(util.Curser.INVISIBLE ) # Make cursor invisible when text field is active color = '{!white,black!}' lines = wrap_string(self.txt, self.parent.width - 3, 3, True) for i, line in enumerate(lines): self.parent.add_string(row + i, '%s%s' % (color, line), scr=screen, col=col, pad=False, trim=False) return len(lines)
def refresh(self, lines=None): # Something has requested we scroll to the top of the list if self.go_top: self.torrentview.cursel = 0 self.torrentview.curoff = 0 self.go_top = False if not lines: if not self.consoleui.is_active_mode(self): return self.stdscr.erase() self.add_string(1, self.torrentview.column_string, scr=self.torrentview_panel) # Update the status bars statusbar_args = {'scr': self.stdscr, 'bottombar_help': True} if self.torrentview.curr_filter is not None: statusbar_args[ 'topbar'] = '%s {!filterstatus!}Current filter: %s' % ( self.statusbars.topbar, self.torrentview.curr_filter, ) if self.minor_mode: self.minor_mode.set_statusbar_args(statusbar_args) self.draw_statusbars(**statusbar_args) self.torrentview.update_torrents(lines) if self.minor_mode: self.minor_mode.update_cursor() else: util.safe_curs_set(util.Curser.INVISIBLE) if not self.consoleui.is_active_mode(self): return self.stdscr.noutrefresh() self.torrentview_panel.noutrefresh() if not self.sidebar.hidden(): self.sidebar.refresh() if self.popup: self.popup.refresh() curses.doupdate()
def handle_read(self, c): ret = BaseInputPane.handle_read(self, c) if ret != util.ReadState.IGNORED: return ret if c in [curses.KEY_ENTER, util.KEY_ENTER2]: if self.close_cb: self._handle_callback(state_changed=False, close=False) util.safe_curs_set(util.Curser.INVISIBLE) return util.ReadState.READ elif c == util.KEY_ESC: # close on esc, no action self._handle_callback(state_changed=False, close=True) self.close(None) return util.ReadState.READ self.refresh() return util.ReadState.READ
def refresh(self, lines=None): # Something has requested we scroll to the top of the list if self.go_top: self.torrentview.cursel = 0 self.torrentview.curoff = 0 self.go_top = False if not lines: if not self.consoleui.is_active_mode(self): return self.stdscr.erase() self.add_string(1, self.torrentview.column_string, scr=self.torrentview_panel) # Update the status bars statusbar_args = {'scr': self.stdscr, 'bottombar_help': True} if self.torrentview.curr_filter is not None: statusbar_args['topbar'] = ('%s {!filterstatus!}Current filter: %s' % (self.statusbars.topbar, self.torrentview.curr_filter)) if self.minor_mode: self.minor_mode.set_statusbar_args(statusbar_args) self.draw_statusbars(**statusbar_args) self.torrentview.update_torrents(lines) if self.minor_mode: self.minor_mode.update_cursor() else: util.safe_curs_set(util.Curser.INVISIBLE) if not self.consoleui.is_active_mode(self): return self.stdscr.noutrefresh() self.torrentview_panel.noutrefresh() if not self.sidebar.hidden(): self.sidebar.refresh() if self.popup: self.popup.refresh() curses.doupdate()
def __init__(self, stdscr, encoding=None): BaseMode.__init__(self, stdscr, encoding=encoding, do_refresh=False, depend=['SessionProxy']) PopupsHandler.__init__(self) self.messages = deque() self.last_mark = -1 self.go_top = False self.minor_mode = None self.consoleui = component.get('ConsoleUI') self.coreconfig = self.consoleui.coreconfig self.config = self.consoleui.config self.sidebar = FilterSidebar(self, self.config) self.torrentview_panel = mkwin(curses.COLOR_GREEN, curses.LINES - 1, curses.COLS - self.sidebar.width, 0, self.sidebar.width) self.torrentview = torrentview.TorrentView(self, self.config) util.safe_curs_set(util.Curser.INVISIBLE) self.stdscr.notimeout(0)
def render(self, screen, row, active=False, focused=False, col=0, **kwargs): util.safe_curs_set(util.Curser.INVISIBLE ) # Make cursor invisible when text field is active fmt = self.build_fmt_string(focused, active) self.fmt_keys['msg'] = self.txt string = fmt % self.fmt_keys self.parent.add_string(row, string, scr=screen, col=col, pad=False, trim=False) return 1
def render(self, screen, row, active=False, focused=True, col=0, cursor_offset=0, **kwargs): if active: self.last_active = True elif self.last_active: self.set_value(self.valstr, validate=True, value_on_fail=self.last_valid_value) self.last_active = False fmt_str = self.build_fmt_string(focused, active, value_key='value') value_format = '%(msg)s {!input!}' if not self.valstr: value_format += '[ ]' elif self.format_default and self.valstr == self.default_str: value_format += '[ {!magenta,black!}%(value)s{!input!} ]' else: value_format += '[ ' + fmt_str + ' ]' self.parent.add_string( row, value_format % dict({ 'msg': self.message, 'value': '%s' % self.valstr }, **self.fmt_keys), scr=screen, col=col, pad=False, ) if active: if focused: util.safe_curs_set(util.Curser.NORMAL) self.move_func(row, self.cursor + self.cursoff + cursor_offset) else: util.safe_curs_set(util.Curser.INVISIBLE) return 1
def __init__(self, parent_mode, stdscr, console_config, encoding=None): PopupsHandler.__init__(self) self.console_config = console_config self.parent_mode = parent_mode self.torrentid = None self.torrent_state = None self._status_keys = [ 'files', 'name', 'state', 'download_payload_rate', 'upload_payload_rate', 'progress', 'eta', 'all_time_download', 'total_uploaded', 'ratio', 'num_seeds', 'total_seeds', 'num_peers', 'total_peers', 'active_time', 'seeding_time', 'time_added', 'distributed_copies', 'num_pieces', 'piece_length', 'download_location', 'file_progress', 'file_priorities', 'message', 'total_wanted', 'tracker_host', 'owner', 'seed_rank', 'last_seen_complete', 'completed_time', 'time_since_transfer' ] self.file_list = None self.current_file = None self.current_file_idx = 0 self.file_off = 0 self.more_to_draw = False self.full_names = None self.column_string = '' self.files_sep = None self.marked = {} BaseMode.__init__(self, stdscr, encoding) self.column_names = ['Filename', 'Size', 'Progress', 'Priority'] self.__update_columns() self._listing_start = self.rows // 2 self._listing_space = self._listing_start - self._listing_start client.register_event_handler('TorrentFileRenamedEvent', self._on_torrentfilerenamed_event) client.register_event_handler('TorrentFolderRenamedEvent', self._on_torrentfolderrenamed_event) client.register_event_handler('TorrentRemovedEvent', self._on_torrentremoved_event) util.safe_curs_set(util.Curser.INVISIBLE) self.stdscr.notimeout(0)
def __init__(self, parent_mode, stdscr, console_config, encoding=None): PopupsHandler.__init__(self) self.console_config = console_config self.parent_mode = parent_mode self.torrentid = None self.torrent_state = None self._status_keys = ['files', 'name', 'state', 'download_payload_rate', 'upload_payload_rate', 'progress', 'eta', 'all_time_download', 'total_uploaded', 'ratio', 'num_seeds', 'total_seeds', 'num_peers', 'total_peers', 'active_time', 'seeding_time', 'time_added', 'distributed_copies', 'num_pieces', 'piece_length', 'download_location', 'file_progress', 'file_priorities', 'message', 'total_wanted', 'tracker_host', 'owner', 'seed_rank', 'last_seen_complete', 'completed_time', 'time_since_transfer'] self.file_list = None self.current_file = None self.current_file_idx = 0 self.file_off = 0 self.more_to_draw = False self.full_names = None self.column_string = '' self.files_sep = None self.marked = {} BaseMode.__init__(self, stdscr, encoding) self.column_names = ['Filename', 'Size', 'Progress', 'Priority'] self.__update_columns() self._listing_start = self.rows // 2 self._listing_space = self._listing_start - self._listing_start client.register_event_handler('TorrentFileRenamedEvent', self._on_torrentfilerenamed_event) client.register_event_handler('TorrentFolderRenamedEvent', self._on_torrentfolderrenamed_event) client.register_event_handler('TorrentRemovedEvent', self._on_torrentremoved_event) util.safe_curs_set(util.Curser.INVISIBLE) self.stdscr.notimeout(0)
def resume(self): util.safe_curs_set(util.Curser.VERY_VISIBLE)
def __init__(self, stdscr, encoding=None): # Get a handle to the main console self.console = component.get('ConsoleUI') Commander.__init__(self, self.console._commands, interactive=True) self.batch_write = False # A list of strings to be displayed based on the offset (scroll) self.lines = [] # The offset to display lines self.display_lines_offset = 0 # Holds the user input and is cleared on 'enter' self.input = '' self.input_incomplete = '' # Keep track of where the cursor is self.input_cursor = 0 # Keep a history of inputs self.input_history = [] self.input_history_index = 0 # Keep track of double- and multi-tabs self.tab_count = 0 self.console_config = component.get('TorrentList').config # To avoid having to truncate the file every time we're writing # or doing it on exit(and therefore relying on an error-less # or in other words clean exit, we're going to have two files # that we swap around based on length config_dir = deluge.configmanager.get_config_dir() self.history_file = [ os.path.join(config_dir, 'cmd_line.hist1'), os.path.join(config_dir, 'cmd_line.hist2'), ] self._hf_lines = [0, 0] if self.console_config['cmdline']['save_command_history']: try: with open(self.history_file[0], 'r', encoding='utf8') as _file: lines1 = _file.read().splitlines() self._hf_lines[0] = len(lines1) except IOError: lines1 = [] self._hf_lines[0] = 0 try: with open(self.history_file[1], 'r', encoding='utf8') as _file: lines2 = _file.read().splitlines() self._hf_lines[1] = len(lines2) except IOError: lines2 = [] self._hf_lines[1] = 0 # The non-full file is the active one if self._hf_lines[0] > self._hf_lines[1]: self.lines = lines1 + lines2 else: self.lines = lines2 + lines1 if len(self.lines) > MAX_HISTFILE_SIZE: self.lines = self.lines[-MAX_HISTFILE_SIZE:] # Instead of having additional input history file, we can # simply scan for lines beginning with ">>> " for i, line in enumerate(self.lines): line = remove_formatting(line) if line.startswith('>>> '): console_input = line[4:] if self.console_config['cmdline']['ignore_duplicate_lines']: if len(self.input_history) > 0: if self.input_history[-1] != console_input: self.input_history.append(console_input) else: self.input_history.append(console_input) self.input_history_index = len(self.input_history) # show the cursor util.safe_curs_set(util.Curser.VERY_VISIBLE) BaseMode.__init__(self, stdscr, encoding, depend=['SessionProxy'])
def update_cursor(self): util.safe_curs_set(util.Curser.VERY_VISIBLE) move_cursor(self.torrentlist.stdscr, self.torrentlist.rows - 1, len(self.search_string) + 17)
def __init__(self, stdscr, encoding=None): # Get a handle to the main console self.console = component.get('ConsoleUI') Commander.__init__(self, self.console._commands, interactive=True) self.batch_write = False # A list of strings to be displayed based on the offset (scroll) self.lines = [] # The offset to display lines self.display_lines_offset = 0 # Holds the user input and is cleared on 'enter' self.input = '' self.input_incomplete = '' # Keep track of where the cursor is self.input_cursor = 0 # Keep a history of inputs self.input_history = [] self.input_history_index = 0 # Keep track of double- and multi-tabs self.tab_count = 0 self.console_config = component.get('TorrentList').config # To avoid having to truncate the file every time we're writing # or doing it on exit(and therefore relying on an error-less # or in other words clean exit, we're going to have two files # that we swap around based on length config_dir = deluge.configmanager.get_config_dir() self.history_file = [ os.path.join(config_dir, 'cmd_line.hist1'), os.path.join(config_dir, 'cmd_line.hist2') ] self._hf_lines = [0, 0] if self.console_config['cmdline']['save_command_history']: try: with open(self.history_file[0], 'r', encoding='utf8') as _file: lines1 = _file.read().splitlines() self._hf_lines[0] = len(lines1) except IOError: lines1 = [] self._hf_lines[0] = 0 try: with open(self.history_file[1], 'r', encoding='utf8') as _file: lines2 = _file.read().splitlines() self._hf_lines[1] = len(lines2) except IOError: lines2 = [] self._hf_lines[1] = 0 # The non-full file is the active one if self._hf_lines[0] > self._hf_lines[1]: self.lines = lines1 + lines2 else: self.lines = lines2 + lines1 if len(self.lines) > MAX_HISTFILE_SIZE: self.lines = self.lines[-MAX_HISTFILE_SIZE:] # Instead of having additional input history file, we can # simply scan for lines beginning with ">>> " for i, line in enumerate(self.lines): line = remove_formatting(line) if line.startswith('>>> '): console_input = line[4:] if self.console_config['cmdline']['ignore_duplicate_lines']: if len(self.input_history) > 0: if self.input_history[-1] != console_input: self.input_history.append(console_input) else: self.input_history.append(console_input) self.input_history_index = len(self.input_history) # show the cursor util.safe_curs_set(util.Curser.VERY_VISIBLE) BaseMode.__init__(self, stdscr, encoding, depend=['SessionProxy'])