mirror of
https://github.com/codex-storage/deluge.git
synced 2025-02-03 07:03:39 +00:00
[GTKUI] Implement multi-torrent support in Options Tab
This commit is contained in:
parent
722ca41584
commit
d01100a258
@ -1597,13 +1597,13 @@
|
|||||||
<property name="xscale">0.69999998807907104</property>
|
<property name="xscale">0.69999998807907104</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkButton" id="button_apply">
|
<object class="GtkButton" id="button_apply">
|
||||||
<property name="label">gtk-apply</property>
|
<property name="label">_Apply</property>
|
||||||
<property name="use_action_appearance">False</property>
|
<property name="use_action_appearance">False</property>
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="sensitive">False</property>
|
<property name="sensitive">False</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">True</property>
|
<property name="receives_default">True</property>
|
||||||
<property name="use_stock">True</property>
|
<property name="use_underline">True</property>
|
||||||
<signal name="clicked" handler="on_button_apply_clicked" swapped="no"/>
|
<signal name="clicked" handler="on_button_apply_clicked" swapped="no"/>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
|
@ -22,8 +22,9 @@ class OptionsTab(Tab):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(OptionsTab, self).__init__('Options', 'options_tab', 'options_tab_label')
|
super(OptionsTab, self).__init__('Options', 'options_tab', 'options_tab_label')
|
||||||
|
|
||||||
self.prev_torrent_id = None
|
self.prev_torrent_ids = None
|
||||||
self.prev_status = None
|
self.prev_status = None
|
||||||
|
self.inconsistent_keys = []
|
||||||
|
|
||||||
# Create TabWidget items with widget id, get/set func name, status key.
|
# Create TabWidget items with widget id, get/set func name, status key.
|
||||||
self.add_tab_widget('spin_max_download', 'value', ['max_download_speed'])
|
self.add_tab_widget('spin_max_download', 'value', ['max_download_speed'])
|
||||||
@ -66,56 +67,89 @@ class OptionsTab(Tab):
|
|||||||
def stop(self):
|
def stop(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def clear(self):
|
||||||
|
self.prev_torrent_ids = None
|
||||||
|
self.prev_status = None
|
||||||
|
self.inconsistent_keys = []
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
# Get the first selected torrent
|
|
||||||
torrent_ids = component.get('TorrentView').get_selected_torrents()
|
torrent_ids = component.get('TorrentView').get_selected_torrents()
|
||||||
|
|
||||||
# Only use the first torrent in the list or return if None selected
|
# Set True if torrent(s) selected in torrentview, else False.
|
||||||
|
self._child_widget.set_sensitive(bool(torrent_ids))
|
||||||
|
|
||||||
if torrent_ids:
|
if torrent_ids:
|
||||||
torrent_id = torrent_ids[0]
|
if torrent_ids != self.prev_torrent_ids:
|
||||||
self._child_widget.set_sensitive(True)
|
self.clear()
|
||||||
|
|
||||||
|
component.get('SessionProxy').get_torrents_status(
|
||||||
|
{'id': torrent_ids}, self.status_keys
|
||||||
|
).addCallback(self.parse_torrents_statuses)
|
||||||
|
|
||||||
|
self.prev_torrent_ids = torrent_ids
|
||||||
|
|
||||||
|
def parse_torrents_statuses(self, statuses):
|
||||||
|
"""Finds common status values to all torrrents in statuses.
|
||||||
|
|
||||||
|
Values which differ are replaced with config values.
|
||||||
|
|
||||||
|
|
||||||
|
Args:
|
||||||
|
statuses (dict): A status dict of {torrent_id: {key: value}}.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: A single status dict.
|
||||||
|
|
||||||
|
"""
|
||||||
|
status = {}
|
||||||
|
if len(statuses) == 1:
|
||||||
|
# A single torrent so pop torrent status.
|
||||||
|
status = statuses.popitem()[1]
|
||||||
|
self.button_apply.set_label('_Apply')
|
||||||
else:
|
else:
|
||||||
# No torrent is selected in the torrentview
|
for status_key in self.status_keys:
|
||||||
self._child_widget.set_sensitive(False)
|
prev_value = None
|
||||||
return
|
for idx, status in enumerate(statuses.values()):
|
||||||
|
if idx == 0:
|
||||||
|
prev_value = status[status_key]
|
||||||
|
continue
|
||||||
|
elif status[status_key] != prev_value:
|
||||||
|
self.inconsistent_keys.append(status_key)
|
||||||
|
break
|
||||||
|
status[status_key] = prev_value
|
||||||
|
self.button_apply.set_label(_('_Apply to selected'))
|
||||||
|
|
||||||
if torrent_id != self.prev_torrent_id:
|
self.on_get_torrent_status(status)
|
||||||
self.prev_status = None
|
|
||||||
|
|
||||||
component.get('SessionProxy').get_torrent_status(
|
def on_get_torrent_status(self, new_status):
|
||||||
torrent_id, self.status_keys
|
|
||||||
).addCallback(self.on_get_torrent_status)
|
|
||||||
|
|
||||||
self.prev_torrent_id = torrent_id
|
|
||||||
|
|
||||||
def clear(self):
|
|
||||||
self.prev_torrent_id = None
|
|
||||||
self.prev_status = None
|
|
||||||
|
|
||||||
def on_get_torrent_status(self, status):
|
|
||||||
# So we don't overwrite the user's unapplied changes we only
|
# So we don't overwrite the user's unapplied changes we only
|
||||||
# want to update values that have been applied in the core.
|
# want to update values that have been applied in the core.
|
||||||
if self.prev_status is None:
|
if self.prev_status is None:
|
||||||
self.prev_status = dict.fromkeys(status, None)
|
self.prev_status = dict.fromkeys(new_status, None)
|
||||||
|
|
||||||
if status != self.prev_status:
|
if new_status != self.prev_status:
|
||||||
for widget in self.tab_widgets.values():
|
for widget in self.tab_widgets.values():
|
||||||
status_key = widget.status_keys[0]
|
status_key = widget.status_keys[0]
|
||||||
if status[status_key] != self.prev_status[status_key]:
|
status_value = new_status[status_key]
|
||||||
|
if status_value != self.prev_status[status_key]:
|
||||||
set_func = 'set_' + widget.func.replace('_as_int', '')
|
set_func = 'set_' + widget.func.replace('_as_int', '')
|
||||||
getattr(widget.obj, set_func)(status[status_key])
|
getattr(widget.obj, set_func)(status_value)
|
||||||
|
if set_func == 'set_active':
|
||||||
|
widget.obj.set_inconsistent(status_key in self.inconsistent_keys)
|
||||||
|
|
||||||
if status['move_completed_path'] != self.prev_status['move_completed_path']:
|
if new_status['move_completed_path'] != self.prev_status['move_completed_path']:
|
||||||
self.move_completed_path_chooser.set_text(
|
text = new_status['move_completed_path']
|
||||||
status['move_completed_path'], cursor_end=False, default_text=True)
|
self.move_completed_path_chooser.set_text(text, cursor_end=False, default_text=True)
|
||||||
|
|
||||||
# Update sensitivity of widgets.
|
# Update sensitivity of widgets.
|
||||||
self.tab_widgets['spin_stop_ratio'].obj.set_sensitive(status['stop_at_ratio'])
|
self.tab_widgets['spin_stop_ratio'].obj.set_sensitive(new_status['stop_at_ratio'])
|
||||||
self.tab_widgets['chk_remove_at_ratio'].obj.set_sensitive(status['stop_at_ratio'])
|
self.tab_widgets['chk_remove_at_ratio'].obj.set_sensitive(new_status['stop_at_ratio'])
|
||||||
|
|
||||||
# Ensure apply button sensitivity is set False.
|
# Ensure apply button sensitivity is set False.
|
||||||
self.button_apply.set_sensitive(False)
|
self.button_apply.set_sensitive(False)
|
||||||
self.prev_status = status
|
self.prev_status = new_status
|
||||||
|
|
||||||
|
# === Widget signal handlers === #
|
||||||
|
|
||||||
def on_button_apply_clicked(self, button):
|
def on_button_apply_clicked(self, button):
|
||||||
options = {}
|
options = {}
|
||||||
@ -124,26 +158,27 @@ class OptionsTab(Tab):
|
|||||||
if status_key == 'owner':
|
if status_key == 'owner':
|
||||||
continue # A label so read-only
|
continue # A label so read-only
|
||||||
widget_value = getattr(widget.obj, 'get_' + widget.func)()
|
widget_value = getattr(widget.obj, 'get_' + widget.func)()
|
||||||
if widget_value != self.prev_status[status_key]:
|
if widget_value != self.prev_status[status_key] or (
|
||||||
|
status_key in self.inconsistent_keys and not widget.obj.get_inconsistent()):
|
||||||
options[status_key] = widget_value
|
options[status_key] = widget_value
|
||||||
|
|
||||||
if options.get('move_completed', False):
|
if options.get('move_completed', False):
|
||||||
options['move_completed_path'] = self.move_completed_path_chooser.get_text()
|
options['move_completed_path'] = self.move_completed_path_chooser.get_text()
|
||||||
|
|
||||||
client.core.set_torrent_options([self.prev_torrent_id], options)
|
client.core.set_torrent_options(self.prev_torrent_ids, options)
|
||||||
self.button_apply.set_sensitive(False)
|
self.button_apply.set_sensitive(False)
|
||||||
|
|
||||||
def on_chk_move_completed_toggled(self, widget):
|
def on_chk_move_completed_toggled(self, widget):
|
||||||
self.move_completed_path_chooser.set_sensitive(widget.get_active())
|
self.move_completed_path_chooser.set_sensitive(widget.get_active())
|
||||||
self.button_apply.set_sensitive(True)
|
self.on_chk_toggled(widget)
|
||||||
|
|
||||||
def on_chk_stop_at_ratio_toggled(self, widget):
|
def on_chk_stop_at_ratio_toggled(self, widget):
|
||||||
is_active = widget.get_active()
|
self.tab_widgets['spin_stop_ratio'].obj.set_sensitive(widget.get_active())
|
||||||
self.tab_widgets['spin_stop_ratio'].obj.set_sensitive(is_active)
|
self.tab_widgets['chk_remove_at_ratio'].obj.set_sensitive(widget.get_active())
|
||||||
self.tab_widgets['chk_remove_at_ratio'].obj.set_sensitive(is_active)
|
self.on_chk_toggled(widget)
|
||||||
self.button_apply.set_sensitive(True)
|
|
||||||
|
|
||||||
def on_chk_toggled(self, widget):
|
def on_chk_toggled(self, widget):
|
||||||
|
widget.set_inconsistent(False)
|
||||||
self.button_apply.set_sensitive(True)
|
self.button_apply.set_sensitive(True)
|
||||||
|
|
||||||
def on_spin_value_changed(self, widget):
|
def on_spin_value_changed(self, widget):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user