diff --git a/deluge/ui/gtkui/glade/main_window.tabs.ui b/deluge/ui/gtkui/glade/main_window.tabs.ui
index b54361860..e6b959409 100644
--- a/deluge/ui/gtkui/glade/main_window.tabs.ui
+++ b/deluge/ui/gtkui/glade/main_window.tabs.ui
@@ -1597,13 +1597,13 @@
0.69999998807907104
diff --git a/deluge/ui/gtkui/options_tab.py b/deluge/ui/gtkui/options_tab.py
index 18e647504..16e323d85 100644
--- a/deluge/ui/gtkui/options_tab.py
+++ b/deluge/ui/gtkui/options_tab.py
@@ -22,8 +22,9 @@ class OptionsTab(Tab):
def __init__(self):
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.inconsistent_keys = []
# Create TabWidget items with widget id, get/set func name, status key.
self.add_tab_widget('spin_max_download', 'value', ['max_download_speed'])
@@ -66,56 +67,89 @@ class OptionsTab(Tab):
def stop(self):
pass
+ def clear(self):
+ self.prev_torrent_ids = None
+ self.prev_status = None
+ self.inconsistent_keys = []
+
def update(self):
- # Get the first selected torrent
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:
- torrent_id = torrent_ids[0]
- self._child_widget.set_sensitive(True)
+ if torrent_ids != self.prev_torrent_ids:
+ 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:
- # No torrent is selected in the torrentview
- self._child_widget.set_sensitive(False)
- return
+ for status_key in self.status_keys:
+ prev_value = None
+ 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.prev_status = None
+ self.on_get_torrent_status(status)
- component.get('SessionProxy').get_torrent_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):
+ def on_get_torrent_status(self, new_status):
# So we don't overwrite the user's unapplied changes we only
# want to update values that have been applied in the core.
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():
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', '')
- 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']:
- self.move_completed_path_chooser.set_text(
- status['move_completed_path'], cursor_end=False, default_text=True)
+ if new_status['move_completed_path'] != self.prev_status['move_completed_path']:
+ text = new_status['move_completed_path']
+ self.move_completed_path_chooser.set_text(text, cursor_end=False, default_text=True)
# Update sensitivity of widgets.
- self.tab_widgets['spin_stop_ratio'].obj.set_sensitive(status['stop_at_ratio'])
- self.tab_widgets['chk_remove_at_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(new_status['stop_at_ratio'])
# Ensure apply button sensitivity is set 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):
options = {}
@@ -124,26 +158,27 @@ class OptionsTab(Tab):
if status_key == 'owner':
continue # A label so read-only
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
if options.get('move_completed', False):
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)
def on_chk_move_completed_toggled(self, widget):
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):
- is_active = widget.get_active()
- self.tab_widgets['spin_stop_ratio'].obj.set_sensitive(is_active)
- self.tab_widgets['chk_remove_at_ratio'].obj.set_sensitive(is_active)
- self.button_apply.set_sensitive(True)
+ self.tab_widgets['spin_stop_ratio'].obj.set_sensitive(widget.get_active())
+ self.tab_widgets['chk_remove_at_ratio'].obj.set_sensitive(widget.get_active())
+ self.on_chk_toggled(widget)
def on_chk_toggled(self, widget):
+ widget.set_inconsistent(False)
self.button_apply.set_sensitive(True)
def on_spin_value_changed(self, widget):