summaryrefslogtreecommitdiffstats
path: root/deluge/ui/console/modes/connectionmanager.py
diff options
context:
space:
mode:
Diffstat (limited to 'deluge/ui/console/modes/connectionmanager.py')
-rw-r--r--deluge/ui/console/modes/connectionmanager.py211
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()