diff options
Diffstat (limited to '')
-rw-r--r-- | deluge/ui/console/modes/connectionmanager.py | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/deluge/ui/console/modes/connectionmanager.py b/deluge/ui/console/modes/connectionmanager.py new file mode 100644 index 0000000..ce8b6f5 --- /dev/null +++ b/deluge/ui/console/modes/connectionmanager.py @@ -0,0 +1,211 @@ +# +# Copyright (C) 2011 Nick Lanham <nick@afternight.org> +# +# This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with +# the additional special exception to link portions of this program with the OpenSSL library. +# See LICENSE for more details. +# + +import logging + +import deluge.component as component +from deluge.decorators import overrides +from deluge.ui.console.modes.basemode import BaseMode +from deluge.ui.console.utils.curses_util import is_printable_chr +from deluge.ui.console.widgets.popup import InputPopup, PopupsHandler, SelectablePopup +from deluge.ui.hostlist import HostList + +try: + import curses +except ImportError: + pass + +log = logging.getLogger(__name__) + + +class ConnectionManager(BaseMode, PopupsHandler): + def __init__(self, stdscr, encoding=None): + PopupsHandler.__init__(self) + self.statuses = {} + self.all_torrents = None + self.hostlist = HostList() + BaseMode.__init__(self, stdscr, encoding=encoding) + + def update_select_host_popup(self): + if self.popup and not isinstance(self.popup, SelectablePopup): + # Ignore MessagePopup on popup stack upon connect fail + return + + selected_index = self.popup.current_selection() if self.popup else None + + popup = SelectablePopup( + self, + _('Select Host'), + self._host_selected, + border_off_west=1, + active_wrap=True, + ) + popup.add_header( + "{!white,black,bold!}'Q'=%s, 'a'=%s, 'D'=%s" + % (_('Quit'), _('Add Host'), _('Delete Host')), + space_below=True, + ) + + for host_entry in self.hostlist.get_hosts_info(): + host_id, hostname, port, user = host_entry + host_status = self.statuses.get(host_id) + + state = host_status[1] if host_status else 'Offline' + state_color = 'green' if state in ('Online', 'Connected') else 'red' + host_str = f'{hostname}:{port} [{state}]' + + args = {'data': host_id, 'foreground': state_color} + popup.add_line( + host_id, host_str, selectable=True, use_underline=True, **args + ) + + if selected_index: + popup.set_selection(selected_index) + + self.push_popup(popup, clear=True) + self.inlist = True + self.refresh() + + def update_hosts_status(self): + def on_host_status(status_info): + self.statuses[status_info[0]] = status_info + self.update_select_host_popup() + + for host_entry in self.hostlist.get_hosts_info(): + self.hostlist.get_host_status(host_entry[0]).addCallback(on_host_status) + + def _on_connected(self, result): + def on_console_start(result): + component.get('ConsoleUI').set_mode('TorrentList') + + d = component.get('ConsoleUI').start_console() + d.addCallback(on_console_start) + + def _on_connect_fail(self, result): + self.report_message('Failed to connect!', result.getErrorMessage()) + self.refresh() + if hasattr(result, 'getTraceback'): + log.exception(result) + + def _host_selected(self, selected_host, *args, **kwargs): + if selected_host in self.statuses: + d = self.hostlist.connect_host(selected_host) + d.addCallback(self._on_connected) + d.addErrback(self._on_connect_fail) + + def _do_add(self, result, **kwargs): + if not result or kwargs.get('close', False): + self.pop_popup() + else: + self.add_host( + result['hostname']['value'], + result['port']['value'], + result['username']['value'], + result['password']['value'], + ) + + def add_popup(self): + self.inlist = False + popup = InputPopup( + self, + _('Add Host (Up & Down arrows to navigate, Esc to cancel)'), + border_off_north=1, + border_off_east=1, + close_cb=self._do_add, + ) + popup.add_text_input('hostname', _('Hostname:')) + popup.add_text_input('port', _('Port:')) + popup.add_text_input('username', _('Username:')) + popup.add_text_input('password', _('Password:')) + self.push_popup(popup, clear=True) + self.refresh() + + def add_host(self, hostname, port, username, password): + log.info('Adding host: %s', hostname) + if port.isdecimal(): + port = int(port) + try: + self.hostlist.add_host(hostname, port, username, password) + except ValueError as ex: + self.report_message(_('Error adding host'), f'{hostname}: {ex}') + else: + self.pop_popup() + + def delete_host(self, host_id): + log.info('Deleting host: %s', host_id) + self.hostlist.remove_host(host_id) + self.update_select_host_popup() + + @overrides(component.Component) + def start(self): + self.refresh() + + @overrides(component.Component) + def update(self): + self.update_hosts_status() + + @overrides(BaseMode) + def pause(self): + self.pop_popup() + BaseMode.pause(self) + + @overrides(BaseMode) + def resume(self): + BaseMode.resume(self) + self.refresh() + + @overrides(BaseMode) + def refresh(self): + if self.mode_paused(): + return + + self.stdscr.erase() + self.draw_statusbars() + self.stdscr.noutrefresh() + + if not self.popup: + self.update_select_host_popup() + + if self.popup: + self.popup.refresh() + + curses.doupdate() + + @overrides(BaseMode) + def on_resize(self, rows, cols): + BaseMode.on_resize(self, rows, cols) + + if self.popup: + self.popup.handle_resize() + + self.stdscr.erase() + self.refresh() + + @overrides(BaseMode) + def read_input(self): + c = self.stdscr.getch() + + if is_printable_chr(c): + if chr(c) == 'Q': + component.get('ConsoleUI').quit() + elif self.inlist: + if chr(c) == 'q': + return + elif chr(c) == 'D': + host_index = self.popup.current_selection() + host_id = self.popup.inputs[host_index].name + self.delete_host(host_id) + return + elif chr(c) == 'a': + self.add_popup() + return + + if self.popup: + if self.popup.handle_read(c) and self.popup.closed(): + self.pop_popup() + self.refresh() |