diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2023-02-19 14:52:21 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2023-02-19 14:52:21 +0000 |
commit | d1772d410235592b482e3b08b1863f6624d9fe6b (patch) | |
tree | accfb4b99c32e5e435089f8023d62e67a6951603 /deluge/ui/console/modes/preferences/preference_panes.py | |
parent | Initial commit. (diff) | |
download | deluge-d1772d410235592b482e3b08b1863f6624d9fe6b.tar.xz deluge-d1772d410235592b482e3b08b1863f6624d9fe6b.zip |
Adding upstream version 2.0.3.upstream/2.0.3
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'deluge/ui/console/modes/preferences/preference_panes.py')
-rw-r--r-- | deluge/ui/console/modes/preferences/preference_panes.py | 764 |
1 files changed, 764 insertions, 0 deletions
diff --git a/deluge/ui/console/modes/preferences/preference_panes.py b/deluge/ui/console/modes/preferences/preference_panes.py new file mode 100644 index 0000000..62029a6 --- /dev/null +++ b/deluge/ui/console/modes/preferences/preference_panes.py @@ -0,0 +1,764 @@ +# -*- coding: utf-8 -*- +# +# 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. +# + +from __future__ import unicode_literals + +import logging + +from deluge.common import is_ip +from deluge.decorators import overrides +from deluge.i18n import get_languages +from deluge.ui.client import client +from deluge.ui.common import DISK_CACHE_KEYS +from deluge.ui.console.widgets import BaseInputPane, BaseWindow +from deluge.ui.console.widgets.fields import FloatSpinInput, TextInput +from deluge.ui.console.widgets.popup import PopupsHandler + +log = logging.getLogger(__name__) + + +class BasePreferencePane(BaseInputPane, BaseWindow, PopupsHandler): + def __init__(self, name, preferences): + PopupsHandler.__init__(self) + self.preferences = preferences + BaseWindow.__init__( + self, + '%s' % name, + self.pane_width, + preferences.height, + posy=1, + posx=self.pane_x_pos, + ) + BaseInputPane.__init__(self, preferences, border_off_east=1) + self.name = name + + # have we scrolled down in the list + self.input_offset = 0 + + @overrides(BaseInputPane) + def handle_read(self, c): + if self.popup: + ret = self.popup.handle_read(c) + if self.popup and self.popup.closed(): + self.pop_popup() + self.refresh() + return ret + return BaseInputPane.handle_read(self, c) + + @property + def visible_content_pane_height(self): + y, x = self.visible_content_pane_size + return y + + @property + def pane_x_pos(self): + return self.preferences.sidebar_width + + @property + def pane_width(self): + return self.preferences.width + + @property + def cols(self): + return self.pane_width + + @property + def rows(self): + return self.preferences.height + + def is_active_pane(self): + return self.preferences.is_active_pane(self) + + def create_pane(self, core_conf, console_config): + pass + + def add_config_values(self, conf_dict): + for ipt in self.inputs: + if ipt.has_input(): + # Need special cases for in/out ports or proxy since they are tuples or dicts. + if ipt.name == 'listen_ports_to' or ipt.name == 'listen_ports_from': + conf_dict['listen_ports'] = ( + self.infrom.get_value(), + self.into.get_value(), + ) + elif ipt.name == 'out_ports_to' or ipt.name == 'out_ports_from': + conf_dict['outgoing_ports'] = ( + self.outfrom.get_value(), + self.outto.get_value(), + ) + elif ipt.name == 'listen_interface': + listen_interface = ipt.get_value().strip() + if is_ip(listen_interface) or not listen_interface: + conf_dict['listen_interface'] = listen_interface + elif ipt.name == 'outgoing_interface': + outgoing_interface = ipt.get_value().strip() + conf_dict['outgoing_interface'] = outgoing_interface + elif ipt.name.startswith('proxy_'): + if ipt.name == 'proxy_type': + conf_dict.setdefault('proxy', {})['type'] = ipt.get_value() + elif ipt.name == 'proxy_username': + conf_dict.setdefault('proxy', {})['username'] = ipt.get_value() + elif ipt.name == 'proxy_password': + conf_dict.setdefault('proxy', {})['password'] = ipt.get_value() + elif ipt.name == 'proxy_hostname': + conf_dict.setdefault('proxy', {})['hostname'] = ipt.get_value() + elif ipt.name == 'proxy_port': + conf_dict.setdefault('proxy', {})['port'] = ipt.get_value() + elif ipt.name == 'proxy_hostnames': + conf_dict.setdefault('proxy', {})[ + 'proxy_hostnames' + ] = ipt.get_value() + elif ipt.name == 'proxy_peer_connections': + conf_dict.setdefault('proxy', {})[ + 'proxy_peer_connections' + ] = ipt.get_value() + elif ipt.name == 'proxy_tracker_connections': + conf_dict.setdefault('proxy', {})[ + 'proxy_tracker_connections' + ] = ipt.get_value() + elif ipt.name == 'force_proxy': + conf_dict.setdefault('proxy', {})['force_proxy'] = ipt.get_value() + elif ipt.name == 'anonymous_mode': + conf_dict.setdefault('proxy', {})[ + 'anonymous_mode' + ] = ipt.get_value() + else: + conf_dict[ipt.name] = ipt.get_value() + + if hasattr(ipt, 'get_child'): + c = ipt.get_child() + conf_dict[c.name] = c.get_value() + + def update_values(self, conf_dict): + for ipt in self.inputs: + if ipt.has_input(): + try: + ipt.set_value(conf_dict[ipt.name]) + except KeyError: # just ignore if it's not in dict + pass + if hasattr(ipt, 'get_child'): + try: + c = ipt.get_child() + c.set_value(conf_dict[c.name]) + except KeyError: # just ignore if it's not in dict + pass + + def render(self, mode, screen, width, focused): + height = self.get_content_height() + self.ensure_content_pane_height(height) + self.screen.erase() + + if focused and self.active_input == -1: + self.move_active_down(1) + + self.render_inputs(focused=focused) + + @overrides(BaseWindow) + def refresh(self): + BaseWindow.refresh(self) + if self.popup: + self.popup.refresh() + + def update(self, active): + pass + + +class InterfacePane(BasePreferencePane): + def __init__(self, preferences): + BasePreferencePane.__init__(self, ' %s ' % _('Interface'), preferences) + + @overrides(BasePreferencePane) + def create_pane(self, core_conf, console_config): + self.add_header(_('General options')) + + self.add_checked_input( + 'ring_bell', + _('Ring system bell when a download finishes'), + console_config['ring_bell'], + ) + self.add_header('Console UI', space_above=True) + self.add_checked_input( + 'separate_complete', + _('List complete torrents after incomplete regardless of sorting order'), + console_config['torrentview']['separate_complete'], + ) + self.add_checked_input( + 'move_selection', + _('Move selection when moving torrents in the queue'), + console_config['torrentview']['move_selection'], + ) + + langs = get_languages() + langs.insert(0, ('', 'System Default')) + self.add_combo_input( + 'language', _('Language'), langs, default=console_config['language'] + ) + self.add_header(_('Command Line Mode'), space_above=True) + self.add_checked_input( + 'ignore_duplicate_lines', + _('Do not store duplicate input in history'), + console_config['cmdline']['ignore_duplicate_lines'], + ) + self.add_checked_input( + 'save_command_history', + _('Store and load command line history in command line mode'), + console_config['cmdline']['save_command_history'], + ) + self.add_header('') + self.add_checked_input( + 'third_tab_lists_all', + _('Third tab lists all remaining torrents in command line mode'), + console_config['cmdline']['third_tab_lists_all'], + ) + self.add_int_spin_input( + 'torrents_per_tab_press', + _('Torrents per tab press'), + console_config['cmdline']['torrents_per_tab_press'], + min_val=5, + max_val=10000, + ) + + +class DownloadsPane(BasePreferencePane): + def __init__(self, preferences): + BasePreferencePane.__init__(self, ' %s ' % _('Downloads'), preferences) + + @overrides(BasePreferencePane) + def create_pane(self, core_conf, console_config): + self.add_header(_('Folders')) + self.add_text_input( + 'download_location', + '%s:' % _('Download To'), + core_conf['download_location'], + complete=True, + activate_input=True, + col='+1', + ) + cmptxt = TextInput( + self.preferences, + 'move_completed_path', + None, + self.move, + self.pane_width, + core_conf['move_completed_path'], + False, + ) + self.add_checkedplus_input( + 'move_completed', + '%s:' % _('Move completed to'), + cmptxt, + core_conf['move_completed'], + ) + copytxt = TextInput( + self.preferences, + 'torrentfiles_location', + None, + self.move, + self.pane_width, + core_conf['torrentfiles_location'], + False, + ) + self.add_checkedplus_input( + 'copy_torrent_file', + '%s:' % _('Copy of .torrent files to'), + copytxt, + core_conf['copy_torrent_file'], + ) + self.add_checked_input( + 'del_copy_torrent_file', + _('Delete copy of torrent file on remove'), + core_conf['del_copy_torrent_file'], + ) + + self.add_header(_('Options'), space_above=True) + self.add_checked_input( + 'prioritize_first_last_pieces', + ('Prioritize first and last pieces of torrent'), + core_conf['prioritize_first_last_pieces'], + ) + self.add_checked_input( + 'sequential_download', + _('Sequential download'), + core_conf['sequential_download'], + ) + self.add_checked_input('add_paused', _('Add Paused'), core_conf['add_paused']) + self.add_checked_input( + 'pre_allocate_storage', + _('Pre-Allocate disk space'), + core_conf['pre_allocate_storage'], + ) + + +class NetworkPane(BasePreferencePane): + def __init__(self, preferences): + BasePreferencePane.__init__(self, ' %s ' % _('Network'), preferences) + + @overrides(BasePreferencePane) + def create_pane(self, core_conf, console_config): + self.add_header(_('Incomming Ports')) + inrand = self.add_checked_input( + 'random_port', + 'Use Random Ports Active Port: %d' % self.preferences.active_port, + core_conf['random_port'], + ) + listen_ports = core_conf['listen_ports'] + self.infrom = self.add_int_spin_input( + 'listen_ports_from', + ' %s:' % _('From'), + value=listen_ports[0], + min_val=0, + max_val=65535, + ) + self.infrom.set_depend(inrand, inverse=True) + self.into = self.add_int_spin_input( + 'listen_ports_to', + ' %s:' % _('To'), + value=listen_ports[1], + min_val=0, + max_val=65535, + ) + self.into.set_depend(inrand, inverse=True) + + self.add_header(_('Outgoing Ports'), space_above=True) + outrand = self.add_checked_input( + 'random_outgoing_ports', + _('Use Random Ports'), + core_conf['random_outgoing_ports'], + ) + out_ports = core_conf['outgoing_ports'] + self.outfrom = self.add_int_spin_input( + 'out_ports_from', + ' %s:' % _('From'), + value=out_ports[0], + min_val=0, + max_val=65535, + ) + self.outfrom.set_depend(outrand, inverse=True) + self.outto = self.add_int_spin_input( + 'out_ports_to', + ' %s:' % _('To'), + value=out_ports[1], + min_val=0, + max_val=65535, + ) + self.outto.set_depend(outrand, inverse=True) + + self.add_header(_('Incoming Interface'), space_above=True) + self.add_text_input( + 'listen_interface', + _('IP address of the interface to listen on (leave empty for default):'), + core_conf['listen_interface'], + ) + + self.add_header(_('Outgoing Interface'), space_above=True) + self.add_text_input( + 'outgoing_interface', + _( + 'The network interface name or IP address for outgoing ' + 'BitTorrent connections. (Leave empty for default.):' + ), + core_conf['outgoing_interface'], + ) + + self.add_header('TOS', space_above=True) + self.add_text_input('peer_tos', 'Peer TOS Byte:', core_conf['peer_tos']) + + self.add_header(_('Network Extras'), space_above=True) + self.add_checked_input('upnp', 'UPnP', core_conf['upnp']) + self.add_checked_input('natpmp', 'NAT-PMP', core_conf['natpmp']) + self.add_checked_input('utpex', 'Peer Exchange', core_conf['utpex']) + self.add_checked_input('lsd', 'LSD', core_conf['lsd']) + self.add_checked_input('dht', 'DHT', core_conf['dht']) + + self.add_header(_('Encryption'), space_above=True) + self.add_select_input( + 'enc_in_policy', + '%s:' % _('Inbound'), + [_('Forced'), _('Enabled'), _('Disabled')], + [0, 1, 2], + core_conf['enc_in_policy'], + active_default=True, + col='+1', + ) + self.add_select_input( + 'enc_out_policy', + '%s:' % _('Outbound'), + [_('Forced'), _('Enabled'), _('Disabled')], + [0, 1, 2], + core_conf['enc_out_policy'], + active_default=True, + ) + self.add_select_input( + 'enc_level', + '%s:' % _('Level'), + [_('Handshake'), _('Full Stream'), _('Either')], + [0, 1, 2], + core_conf['enc_level'], + active_default=True, + ) + + +class BandwidthPane(BasePreferencePane): + def __init__(self, preferences): + BasePreferencePane.__init__(self, ' %s ' % _('Bandwidth'), preferences) + + @overrides(BasePreferencePane) + def create_pane(self, core_conf, console_config): + self.add_header(_('Global Bandwidth Usage')) + self.add_int_spin_input( + 'max_connections_global', + '%s:' % _('Maximum Connections'), + core_conf['max_connections_global'], + min_val=-1, + max_val=9000, + ) + self.add_int_spin_input( + 'max_upload_slots_global', + '%s:' % _('Maximum Upload Slots'), + core_conf['max_upload_slots_global'], + min_val=-1, + max_val=9000, + ) + self.add_float_spin_input( + 'max_download_speed', + '%s:' % _('Maximum Download Speed (KiB/s)'), + core_conf['max_download_speed'], + min_val=-1.0, + max_val=60000.0, + ) + self.add_float_spin_input( + 'max_upload_speed', + '%s:' % _('Maximum Upload Speed (KiB/s)'), + core_conf['max_upload_speed'], + min_val=-1.0, + max_val=60000.0, + ) + self.add_int_spin_input( + 'max_half_open_connections', + '%s:' % _('Maximum Half-Open Connections'), + core_conf['max_half_open_connections'], + min_val=-1, + max_val=9999, + ) + self.add_int_spin_input( + 'max_connections_per_second', + '%s:' % _('Maximum Connection Attempts per Second'), + core_conf['max_connections_per_second'], + min_val=-1, + max_val=9999, + ) + self.add_checked_input( + 'ignore_limits_on_local_network', + _('Ignore limits on local network'), + core_conf['ignore_limits_on_local_network'], + ) + self.add_checked_input( + 'rate_limit_ip_overhead', + _('Rate Limit IP Overhead'), + core_conf['rate_limit_ip_overhead'], + ) + self.add_header(_('Per Torrent Bandwidth Usage'), space_above=True) + self.add_int_spin_input( + 'max_connections_per_torrent', + '%s:' % _('Maximum Connections'), + core_conf['max_connections_per_torrent'], + min_val=-1, + max_val=9000, + ) + self.add_int_spin_input( + 'max_upload_slots_per_torrent', + '%s:' % _('Maximum Upload Slots'), + core_conf['max_upload_slots_per_torrent'], + min_val=-1, + max_val=9000, + ) + self.add_float_spin_input( + 'max_download_speed_per_torrent', + '%s:' % _('Maximum Download Speed (KiB/s)'), + core_conf['max_download_speed_per_torrent'], + min_val=-1.0, + max_val=60000.0, + ) + self.add_float_spin_input( + 'max_upload_speed_per_torrent', + '%s:' % _('Maximum Upload Speed (KiB/s)'), + core_conf['max_upload_speed_per_torrent'], + min_val=-1.0, + max_val=60000.0, + ) + + +class OtherPane(BasePreferencePane): + def __init__(self, preferences): + BasePreferencePane.__init__(self, ' %s ' % _('Other'), preferences) + + @overrides(BasePreferencePane) + def create_pane(self, core_conf, console_config): + self.add_header(_('System Information')) + self.add_info_field('info1', ' Help us improve Deluge by sending us your', '') + self.add_info_field( + 'info2', ' Python version, PyGTK version, OS and processor', '' + ) + self.add_info_field( + 'info3', ' types. Absolutely no other information is sent.', '' + ) + self.add_checked_input( + 'send_info', + _('Yes, please send anonymous statistics.'), + core_conf['send_info'], + ) + self.add_header(_('GeoIP Database'), space_above=True) + self.add_text_input( + 'geoip_db_location', 'Location:', core_conf['geoip_db_location'] + ) + + +class DaemonPane(BasePreferencePane): + def __init__(self, preferences): + BasePreferencePane.__init__(self, ' %s ' % _('Daemon'), preferences) + + @overrides(BasePreferencePane) + def create_pane(self, core_conf, console_config): + self.add_header('Port') + self.add_int_spin_input( + 'daemon_port', + '%s:' % _('Daemon Port'), + core_conf['daemon_port'], + min_val=0, + max_val=65535, + ) + self.add_header('Connections', space_above=True) + self.add_checked_input( + 'allow_remote', _('Allow remote connections'), core_conf['allow_remote'] + ) + self.add_header('Other', space_above=True) + self.add_checked_input( + 'new_release_check', + _('Periodically check the website for new releases'), + core_conf['new_release_check'], + ) + + +class QueuePane(BasePreferencePane): + def __init__(self, preferences): + BasePreferencePane.__init__(self, ' %s ' % _('Queue'), preferences) + + @overrides(BasePreferencePane) + def create_pane(self, core_conf, console_config): + self.add_header(_('New Torrents')) + self.add_checked_input( + 'queue_new_to_top', _('Queue to top'), core_conf['queue_new_to_top'] + ) + self.add_header(_('Active Torrents'), True) + self.add_int_spin_input( + 'max_active_limit', + '%s:' % _('Total'), + core_conf['max_active_limit'], + min_val=-1, + max_val=9999, + ) + self.add_int_spin_input( + 'max_active_downloading', + '%s:' % _('Downloading'), + core_conf['max_active_downloading'], + min_val=-1, + max_val=9999, + ) + self.add_int_spin_input( + 'max_active_seeding', + '%s:' % _('Seeding'), + core_conf['max_active_seeding'], + min_val=-1, + max_val=9999, + ) + self.add_checked_input( + 'dont_count_slow_torrents', + 'Ignore slow torrents', + core_conf['dont_count_slow_torrents'], + ) + self.add_checked_input( + 'auto_manage_prefer_seeds', + 'Prefer seeding torrents', + core_conf['auto_manage_prefer_seeds'], + ) + self.add_header(_('Seeding Rotation'), space_above=True) + self.add_float_spin_input( + 'share_ratio_limit', + '%s:' % _('Share Ratio'), + core_conf['share_ratio_limit'], + precision=2, + min_val=-1.0, + max_val=100.0, + ) + self.add_float_spin_input( + 'seed_time_ratio_limit', + '%s:' % _('Time Ratio'), + core_conf['seed_time_ratio_limit'], + precision=2, + min_val=-1.0, + max_val=100.0, + ) + self.add_int_spin_input( + 'seed_time_limit', + '%s:' % _('Time (m)'), + core_conf['seed_time_limit'], + min_val=1, + max_val=10000, + ) + seedratio = FloatSpinInput( + self.mode, + 'stop_seed_ratio', + '', + self.move, + core_conf['stop_seed_ratio'], + precision=2, + inc_amt=0.1, + min_val=0.5, + max_val=100.0, + ) + self.add_checkedplus_input( + 'stop_seed_at_ratio', + '%s:' % _('Share Ratio Reached'), + seedratio, + core_conf['stop_seed_at_ratio'], + ) + self.add_checked_input( + 'remove_seed_at_ratio', + _('Remove torrent (Unchecked pauses torrent)'), + core_conf['remove_seed_at_ratio'], + ) + + +class ProxyPane(BasePreferencePane): + def __init__(self, preferences): + BasePreferencePane.__init__(self, ' %s ' % _('Proxy'), preferences) + + @overrides(BasePreferencePane) + def create_pane(self, core_conf, console_config): + proxy = core_conf['proxy'] + + self.add_header(_('Proxy Settings')) + self.add_header(_('Proxy'), space_above=True) + self.add_int_spin_input( + 'proxy_type', '%s:' % _('Type'), proxy['type'], min_val=0, max_val=5 + ) + self.add_text_input('proxy_username', '%s:' % _('Username'), proxy['username']) + self.add_text_input('proxy_password', '%s:' % _('Password'), proxy['password']) + self.add_text_input('proxy_hostname', '%s:' % _('Hostname'), proxy['hostname']) + self.add_int_spin_input( + 'proxy_port', '%s:' % _('Port'), proxy['port'], min_val=0, max_val=65535 + ) + self.add_checked_input( + 'proxy_hostnames', _('Proxy Hostnames'), proxy['proxy_hostnames'] + ) + self.add_checked_input( + 'proxy_peer_connections', _('Proxy Peers'), proxy['proxy_peer_connections'] + ) + self.add_checked_input( + 'proxy_tracker_connections', + _('Proxy Trackers'), + proxy['proxy_tracker_connections'], + ) + self.add_header('%s' % _('Force Proxy'), space_above=True) + self.add_checked_input('force_proxy', _('Force Proxy'), proxy['force_proxy']) + self.add_checked_input( + 'anonymous_mode', _('Hide Client Identity'), proxy['anonymous_mode'] + ) + self.add_header('%s' % _('Proxy Type Help'), space_above=True) + self.add_text_area( + 'proxy_text_area', + ' 0: None 1: Socks4\n' + ' 2: Socks5 3: Socks5 Auth\n' + ' 4: HTTP 5: HTTP Auth\n' + ' 6: I2P', + ) + + +class CachePane(BasePreferencePane): + def __init__(self, preferences): + BasePreferencePane.__init__(self, ' %s ' % _('Cache'), preferences) + self.created = False + + @overrides(BasePreferencePane) + def create_pane(self, core_conf, console_config): + self.core_conf = core_conf + + def build_pane(self, core_conf, status): + self.created = True + self.add_header(_('Settings'), space_below=True) + self.add_int_spin_input( + 'cache_size', + '%s:' % _('Cache Size (16 KiB blocks)'), + core_conf['cache_size'], + min_val=0, + max_val=99999, + ) + self.add_int_spin_input( + 'cache_expiry', + '%s:' % _('Cache Expiry (seconds)'), + core_conf['cache_expiry'], + min_val=1, + max_val=32000, + ) + self.add_header(' %s' % _('Write'), space_above=True) + self.add_info_field( + 'blocks_written', + ' %s:' % _('Blocks Written'), + status['disk.num_blocks_written'], + ) + self.add_info_field( + 'writes', ' %s:' % _('Writes'), status['disk.num_write_ops'] + ) + self.add_info_field( + 'write_hit_ratio', + ' %s:' % _('Write Cache Hit Ratio'), + '%.2f' % status['write_hit_ratio'], + ) + self.add_header(' %s' % _('Read')) + self.add_info_field( + 'blocks_read', ' %s:' % _('Blocks Read'), status['disk.num_blocks_read'] + ) + self.add_info_field( + 'blocks_read_hit', + ' %s:' % _('Blocks Read hit'), + status['disk.num_blocks_cache_hits'], + ) + self.add_info_field('reads', ' %s:' % _('Reads'), status['disk.num_read_ops']) + self.add_info_field( + 'read_hit_ratio', + ' %s:' % _('Read Cache Hit Ratio'), + '%.2f' % status['read_hit_ratio'], + ) + self.add_header(' %s' % _('Size')) + self.add_info_field( + 'cache_size_info', + ' %s:' % _('Cache Size'), + status['disk.disk_blocks_in_use'], + ) + self.add_info_field( + 'read_cache_size', + ' %s:' % _('Read Cache Size'), + status['disk.read_cache_blocks'], + ) + + @overrides(BasePreferencePane) + def update(self, active): + if active: + client.core.get_session_status(DISK_CACHE_KEYS).addCallback( + self.update_cache_status_fields + ) + + def update_cache_status_fields(self, status): + if not self.created: + self.build_pane(self.core_conf, status) + else: + for ipt in self.inputs: + if not ipt.has_input() and ipt.name in status: + ipt.set_value(status[ipt.name]) + self.preferences.refresh() |