From e2c7716ce256e32eb25c6b8e1c4aa7dfedd72b92 Mon Sep 17 00:00:00 2001 From: Calum Lind Date: Sun, 21 Oct 2018 14:07:48 +0100 Subject: [PATCH] [#1903|UI] Add super seeding option to interfaces - Fix applying the setting to libtorrent, passing the value without modification so it decide when to enable it. - Enable super_seeding option when adding torrents to core. - Update UIs with option in tabs and add dialogs. --- deluge/core/torrent.py | 7 +-- deluge/core/torrentmanager.py | 4 ++ deluge/ui/common.py | 1 + deluge/ui/console/cmdline/commands/manage.py | 24 +++------- deluge/ui/console/modes/torrentdetail.py | 3 ++ .../modes/torrentlist/torrentactions.py | 20 ++------- deluge/ui/console/utils/common.py | 23 ++++++++++ deluge/ui/gtkui/addtorrentdialog.py | 10 +++++ deluge/ui/gtkui/glade/add_torrent_dialog.ui | 44 ++++++++++++++----- deluge/ui/gtkui/glade/main_window.tabs.ui | 23 +++++++++- deluge/ui/gtkui/glade/torrent_menu.options.ui | 9 ++++ deluge/ui/gtkui/options_tab.py | 1 + deluge/ui/web/js/deluge-all/Keys.js | 1 + deluge/ui/web/js/deluge-all/add/OptionsTab.js | 12 ++++- .../web/js/deluge-all/details/OptionsTab.js | 8 ++++ 15 files changed, 134 insertions(+), 56 deletions(-) create mode 100644 deluge/ui/console/utils/common.py diff --git a/deluge/core/torrent.py b/deluge/core/torrent.py index 0a7e7eba8..d9fc2afa6 100644 --- a/deluge/core/torrent.py +++ b/deluge/core/torrent.py @@ -454,11 +454,8 @@ class Torrent(object): Args: super_seeding (bool): Enable super seeding. """ - if self.status.is_seeding: - self.options['super_seeding'] = super_seeding - self.handle.super_seeding(super_seeding) - else: - self.options['super_seeding'] = False + self.options['super_seeding'] = super_seeding + self.handle.super_seeding(super_seeding) def set_stop_ratio(self, stop_ratio): """The seeding ratio to stop (or remove) the torrent at. diff --git a/deluge/core/torrentmanager.py b/deluge/core/torrentmanager.py index edab21fa1..021859bdd 100644 --- a/deluge/core/torrentmanager.py +++ b/deluge/core/torrentmanager.py @@ -489,6 +489,10 @@ class TorrentManager(component.Component): ) ^ lt.add_torrent_params_flags_t.flag_auto_managed if options['seed_mode']: add_torrent_params['flags'] |= lt.add_torrent_params_flags_t.flag_seed_mode + if options['super_seeding']: + add_torrent_params[ + 'flags' + ] |= lt.add_torrent_params_flags_t.flag_super_seeding return torrent_id, add_torrent_params diff --git a/deluge/ui/common.py b/deluge/ui/common.py index 2a266d029..e545822a2 100644 --- a/deluge/ui/common.py +++ b/deluge/ui/common.py @@ -115,6 +115,7 @@ TORRENT_DATA_FIELD = { 'owner': {'name': _('Owner'), 'status': ['owner']}, 'pieces': {'name': _('Pieces'), 'status': ['num_pieces', 'piece_length']}, 'seed_rank': {'name': _('Seed Rank'), 'status': ['seed_rank']}, + 'super_seeding': {'name': _('Super Seeding'), 'status': ['super_seeding']}, } TRACKER_STATUS_TRANSLATION = [ diff --git a/deluge/ui/console/cmdline/commands/manage.py b/deluge/ui/console/cmdline/commands/manage.py index 2de921969..6375a74c3 100644 --- a/deluge/ui/console/cmdline/commands/manage.py +++ b/deluge/ui/console/cmdline/commands/manage.py @@ -16,26 +16,12 @@ from twisted.internet import defer import deluge.component as component from deluge.ui.client import client +from deluge.ui.console.utils.common import TORRENT_OPTIONS from . import BaseCommand log = logging.getLogger(__name__) -torrent_options = { - 'max_download_speed': float, - 'max_upload_speed': float, - 'max_connections': int, - 'max_upload_slots': int, - 'private': bool, - 'prioritize_first_last': bool, - 'is_auto_managed': bool, - 'stop_at_ratio': bool, - 'stop_ratio': float, - 'remove_at_ratio': bool, - 'move_completed': bool, - 'move_completed_path': str, -} - class Command(BaseCommand): """Show and manage per-torrent options""" @@ -92,12 +78,12 @@ class Command(BaseCommand): request_options = [] for opt in options.values: - if opt not in torrent_options: + if opt not in TORRENT_OPTIONS: self.console.write('{!error!}Unknown torrent option: %s' % opt) return request_options.append(opt) if not request_options: - request_options = list(torrent_options) + request_options = list(TORRENT_OPTIONS) request_options.append('name') d = client.core.get_torrents_status({'id': torrent_ids}, request_options) @@ -110,11 +96,11 @@ class Command(BaseCommand): val = ' '.join(options.values) torrent_ids = self.console.match_torrent(options.torrent) - if key not in torrent_options: + if key not in TORRENT_OPTIONS: self.console.write('{!error!}Invalid key: %s' % key) return - val = torrent_options[key](val) + val = TORRENT_OPTIONS[key](val) def on_set_config(result): self.console.write('{!success!}Torrent option successfully updated.') diff --git a/deluge/ui/console/modes/torrentdetail.py b/deluge/ui/console/modes/torrentdetail.py index cbe3d16c9..f1fe2c5fd 100644 --- a/deluge/ui/console/modes/torrentdetail.py +++ b/deluge/ui/console/modes/torrentdetail.py @@ -116,6 +116,7 @@ class TorrentDetail(BaseMode, PopupsHandler): 'last_seen_complete', 'completed_time', 'time_since_transfer', + 'super_seeding', ] self.file_list = None self.current_file = None @@ -587,6 +588,8 @@ class TorrentDetail(BaseMode, PopupsHandler): row = add_field('download_location', row) # Seed Rank row = add_field('seed_rank', row) + # Super Seeding + row = add_field('super_seeding', row) # Last seen complete row = add_field('last_seen_complete', row) # Last activity diff --git a/deluge/ui/console/modes/torrentlist/torrentactions.py b/deluge/ui/console/modes/torrentlist/torrentactions.py index 1d49929eb..4d483870c 100644 --- a/deluge/ui/console/modes/torrentlist/torrentactions.py +++ b/deluge/ui/console/modes/torrentlist/torrentactions.py @@ -19,27 +19,13 @@ from deluge.ui.client import client from deluge.ui.common import TORRENT_DATA_FIELD from deluge.ui.console.modes.torrentlist.queue_mode import QueueMode from deluge.ui.console.utils import colors +from deluge.ui.console.utils.common import TORRENT_OPTIONS from deluge.ui.console.widgets.popup import InputPopup, MessagePopup, SelectablePopup from . import ACTION log = logging.getLogger(__name__) -torrent_options = [ - 'max_download_speed', - 'max_upload_speed', - 'max_connections', - 'max_upload_slots', - 'prioritize_first_last', - 'sequential_download', - 'is_auto_managed', - 'stop_at_ratio', - 'stop_ratio', - 'remove_at_ratio', - 'move_completed', - 'move_completed_path', -] - def action_error(error, mode): mode.report_message('Error Occurred', error.getErrorMessage()) @@ -156,7 +142,7 @@ def action_torrent_info(mode=None, torrent_ids=None, **kwargs): border_off_north=1, base_popup=kwargs.get('base_popup', None), ) - for field in torrent_options: + for field in TORRENT_OPTIONS: caption = '{!info!}' + TORRENT_DATA_FIELD[field]['name'] value = options[field] if isinstance(value, ''.__class__): @@ -178,7 +164,7 @@ def action_torrent_info(mode=None, torrent_ids=None, **kwargs): callbacks = [] for tid in torrents: deferred = component.get('SessionProxy').get_torrent_status( - tid, torrent_options + tid, list(TORRENT_OPTIONS) ) callbacks.append(deferred.addCallback(on_torrent_status)) diff --git a/deluge/ui/console/utils/common.py b/deluge/ui/console/utils/common.py new file mode 100644 index 000000000..df1c07917 --- /dev/null +++ b/deluge/ui/console/utils/common.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +# +# 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 + +TORRENT_OPTIONS = { + 'max_download_speed': float, + 'max_upload_speed': float, + 'max_connections': int, + 'max_upload_slots': int, + 'prioritize_first_last': bool, + 'is_auto_managed': bool, + 'stop_at_ratio': bool, + 'stop_ratio': float, + 'remove_at_ratio': bool, + 'move_completed': bool, + 'move_completed_path': str, + 'super_seeding': bool, +} diff --git a/deluge/ui/gtkui/addtorrentdialog.py b/deluge/ui/gtkui/addtorrentdialog.py index 365d0f301..a108b1e6a 100644 --- a/deluge/ui/gtkui/addtorrentdialog.py +++ b/deluge/ui/gtkui/addtorrentdialog.py @@ -145,6 +145,7 @@ class AddTorrentDialog(component.Component): 'move_completed', 'move_completed_path', 'move_completed_paths_list', + 'super_seeding', ] # self.core_keys += self.move_completed_path_chooser.get_config_keys() self.builder.get_object('notebook1').connect( @@ -471,6 +472,9 @@ class AddTorrentDialog(component.Component): self.builder.get_object('chk_move_completed').set_active( options['move_completed'] ) + self.builder.get_object('chk_super_seeding').set_active( + options['super_seeding'] + ) def save_torrent_options(self, row=None): # Keeps the torrent options dictionary up-to-date with what the user has @@ -519,6 +523,9 @@ class AddTorrentDialog(component.Component): 'chk_move_completed' ).get_active() options['seed_mode'] = self.builder.get_object('chk_seed_mode').get_active() + options['super_seeding'] = self.builder.get_object( + 'chk_super_seeding' + ).get_active() self.options[torrent_id] = options @@ -578,6 +585,9 @@ class AddTorrentDialog(component.Component): self.core_config['move_completed'] ) self.builder.get_object('chk_seed_mode').set_active(False) + self.builder.get_object('chk_super_seeding').set_active( + self.core_config['super_seeding'] + ) def get_file_priorities(self, torrent_id): # A list of priorities diff --git a/deluge/ui/gtkui/glade/add_torrent_dialog.ui b/deluge/ui/gtkui/glade/add_torrent_dialog.ui index 4151876b4..664393e38 100644 --- a/deluge/ui/gtkui/glade/add_torrent_dialog.ui +++ b/deluge/ui/gtkui/glade/add_torrent_dialog.ui @@ -503,6 +503,17 @@ 1 + + + True + False + + + False + True + 2 + + True @@ -589,6 +600,22 @@ used sparingly. 3 + + + Super Seeding + True + True + False + Useful if adding a complete torrent for seeding. + 0 + True + + + True + True + 4 + + Preallocate Disk Space @@ -601,22 +628,15 @@ used sparingly. False False - 4 + 5 - - - True - False - General - - - - + + @@ -806,7 +826,7 @@ used sparingly. False False - 2 + 3 @@ -923,7 +943,7 @@ used sparingly. False False - 3 + 4 diff --git a/deluge/ui/gtkui/glade/main_window.tabs.ui b/deluge/ui/gtkui/glade/main_window.tabs.ui index 0857cb11e..ba99cfbe3 100644 --- a/deluge/ui/gtkui/glade/main_window.tabs.ui +++ b/deluge/ui/gtkui/glade/main_window.tabs.ui @@ -1475,6 +1475,25 @@ 3 + + + + + + Super Seeding + False + True + True + False + True + + + + False + True + 4 + + Move completed: @@ -1487,7 +1506,7 @@ False False - 4 + 5 @@ -1501,7 +1520,7 @@ False True - 5 + 6 diff --git a/deluge/ui/gtkui/glade/torrent_menu.options.ui b/deluge/ui/gtkui/glade/torrent_menu.options.ui index 1d339d0f5..9fc56f8df 100644 --- a/deluge/ui/gtkui/glade/torrent_menu.options.ui +++ b/deluge/ui/gtkui/glade/torrent_menu.options.ui @@ -89,6 +89,15 @@ True + + + True + False + False + _Super Seeding + True + + False diff --git a/deluge/ui/gtkui/options_tab.py b/deluge/ui/gtkui/options_tab.py index 0f5794a5b..5a68e57a9 100644 --- a/deluge/ui/gtkui/options_tab.py +++ b/deluge/ui/gtkui/options_tab.py @@ -46,6 +46,7 @@ class OptionsTab(Tab): self.add_tab_widget('chk_move_completed', 'active', ['move_completed']) self.add_tab_widget('chk_shared', 'active', ['shared']) self.add_tab_widget('summary_owner', 'text', ['owner']) + self.add_tab_widget('chk_super_seeding', 'active', ['super_seeding']) # Connect key press event for spin widgets. for widget_id in self.tab_widgets: diff --git a/deluge/ui/web/js/deluge-all/Keys.js b/deluge/ui/web/js/deluge-all/Keys.js index 28a18a627..25cf38bc3 100644 --- a/deluge/ui/web/js/deluge-all/Keys.js +++ b/deluge/ui/web/js/deluge-all/Keys.js @@ -127,6 +127,7 @@ Deluge.Keys = { 'prioritize_first_last', 'move_completed', 'move_completed_path', + 'super_seeding', ], }; diff --git a/deluge/ui/web/js/deluge-all/add/OptionsTab.js b/deluge/ui/web/js/deluge-all/add/OptionsTab.js index 66a53127d..e897b1783 100644 --- a/deluge/ui/web/js/deluge-all/add/OptionsTab.js +++ b/deluge/ui/web/js/deluge-all/add/OptionsTab.js @@ -113,7 +113,7 @@ Deluge.add.OptionsTab = Ext.extend(Ext.form.FormPanel, { ); fieldset = panel.add({ - title: _('General'), + // title: _('General'), border: false, autoHeight: true, defaultType: 'checkbox', @@ -154,6 +154,15 @@ Deluge.add.OptionsTab = Ext.extend(Ext.form.FormPanel, { labelSeparator: '', }) ); + this.optionsManager.bind( + 'super_seeding', + fieldset.add({ + name: 'super_seeding', + boxLabel: _('Super Seed'), + fieldLabel: '', + labelSeparator: '', + }) + ); this.optionsManager.bind( 'pre_allocate_storage', fieldset.add({ @@ -197,6 +206,7 @@ Deluge.add.OptionsTab = Ext.extend(Ext.form.FormPanel, { prioritize_first_last_pieces: config.prioritize_first_last_pieces, seed_mode: false, + super_seeding: false, }; this.optionsManager.options = options; this.optionsManager.resetAll(); diff --git a/deluge/ui/web/js/deluge-all/details/OptionsTab.js b/deluge/ui/web/js/deluge-all/details/OptionsTab.js index 669fbf905..b11486bfd 100644 --- a/deluge/ui/web/js/deluge-all/details/OptionsTab.js +++ b/deluge/ui/web/js/deluge-all/details/OptionsTab.js @@ -48,6 +48,7 @@ Deluge.details.OptionsTab = Ext.extend(Ext.form.FormPanel, { move_completed_path: '', private: false, prioritize_first_last: false, + super_seeding: false, }, }); @@ -287,6 +288,13 @@ Deluge.details.OptionsTab = Ext.extend(Ext.form.FormPanel, { id: 'prioritize_first_last', }); + this.fields.super_seeding = this.fieldsets.general.add({ + fieldLabel: '', + labelSeparator: '', + boxLabel: _('Super Seeding'), + id: 'super_seeding', + }); + // Bind the fields so the options manager can manage them. for (var id in this.fields) { this.optionsManager.bind(id, this.fields[id]);