mirror of
https://git.deluge-torrent.org/deluge
synced 2025-04-23 13:04:52 +00:00
[GTKUI] Refactor torrent details Tabs code
* Move common code into Tab parent class * The Tab init now accepts creation with name, child_widget and tab_label but will still accept the 'oldstyle' contructor to keep backwards compatibility with 3rd-party plugins. * Create namedtuple TabWidget with widget, format func and status_keys. The TabWidget are stored in a tab_widgets dict making it easier to create, save and update large numbers of gtk widgets.
This commit is contained in:
parent
6d28f2c885
commit
1637da84e4
8 changed files with 197 additions and 273 deletions
|
@ -977,6 +977,7 @@ class Torrent(object):
|
|||
'download_payload_rate': lambda: self.status.download_payload_rate,
|
||||
'file_priorities': self.get_file_priorities,
|
||||
'hash': lambda: self.torrent_id,
|
||||
'auto_managed': lambda: self.options['auto_managed'],
|
||||
'is_auto_managed': lambda: self.options['auto_managed'],
|
||||
'is_finished': lambda: self.is_finished,
|
||||
'max_connections': lambda: self.options['max_connections'],
|
||||
|
|
|
@ -22,28 +22,17 @@ log = logging.getLogger(__name__)
|
|||
|
||||
class DetailsTab(Tab):
|
||||
def __init__(self):
|
||||
super(DetailsTab, self).__init__()
|
||||
# Get the labels we need to update.
|
||||
# widget name, modifier function, status keys
|
||||
main_builder = component.get('MainWindow').get_builder()
|
||||
super(DetailsTab, self).__init__('Details', 'details_tab', 'details_tab_label')
|
||||
|
||||
self._name = 'Details'
|
||||
self._child_widget = main_builder.get_object('details_tab')
|
||||
self._tab_label = main_builder.get_object('details_tab_label')
|
||||
|
||||
self.label_widgets = [
|
||||
(main_builder.get_object('summary_name'), None, ('name',)),
|
||||
(main_builder.get_object('summary_total_size'), fsize, ('total_size',)),
|
||||
(main_builder.get_object('summary_num_files'), str, ('num_files',)),
|
||||
(main_builder.get_object('summary_completed'), fdate_or_dash, ('completed_time',)),
|
||||
(main_builder.get_object('summary_date_added'), fdate, ('time_added',)),
|
||||
(main_builder.get_object('summary_torrent_path'), None, ('download_location',)),
|
||||
(main_builder.get_object('summary_hash'), str, ('hash',)),
|
||||
(main_builder.get_object('summary_comments'), str, ('comment',)),
|
||||
(main_builder.get_object('summary_pieces'), fpieces_num_size, ('num_pieces', 'piece_length')),
|
||||
]
|
||||
|
||||
self.status_keys = [status for widget in self.label_widgets for status in widget[2]]
|
||||
self.add_tab_widget('summary_name', None, ('name',))
|
||||
self.add_tab_widget('summary_total_size', fsize, ('total_size',))
|
||||
self.add_tab_widget('summary_num_files', str, ('num_files',))
|
||||
self.add_tab_widget('summary_completed', fdate_or_dash, ('completed_time',))
|
||||
self.add_tab_widget('summary_date_added', fdate, ('time_added',))
|
||||
self.add_tab_widget('summary_torrent_path', None, ('download_location',))
|
||||
self.add_tab_widget('summary_hash', str, ('hash',))
|
||||
self.add_tab_widget('summary_comments', str, ('comment',))
|
||||
self.add_tab_widget('summary_pieces', fpieces_num_size, ('num_pieces', 'piece_length'))
|
||||
|
||||
def update(self):
|
||||
# Get the first selected torrent
|
||||
|
@ -66,14 +55,14 @@ class DetailsTab(Tab):
|
|||
return
|
||||
|
||||
# Update all the label widgets
|
||||
for widget in self.label_widgets:
|
||||
txt = xml_escape(self.get_status_for_widget(widget, status))
|
||||
if widget[0].get_text() != txt:
|
||||
if widget[2][0] == 'comment' and is_url(txt):
|
||||
widget[0].set_markup('<a href="%s">%s</a>' % (txt, txt))
|
||||
for widget in self.tab_widgets.values():
|
||||
txt = xml_escape(self.widget_status_as_fstr(widget, status))
|
||||
if widget.obj.get_text() != txt:
|
||||
if 'comment' in widget.status_keys and is_url(txt):
|
||||
widget.obj.set_markup('<a href="%s">%s</a>' % (txt, txt))
|
||||
else:
|
||||
widget[0].set_markup(txt)
|
||||
widget.obj.set_markup(txt)
|
||||
|
||||
def clear(self):
|
||||
for widget in self.label_widgets:
|
||||
widget[0].set_text('')
|
||||
for widget in self.tab_widgets.values():
|
||||
widget.obj.set_text('')
|
||||
|
|
|
@ -70,14 +70,9 @@ def cell_progress(column, cell, model, row, data):
|
|||
|
||||
class FilesTab(Tab):
|
||||
def __init__(self):
|
||||
super(FilesTab, self).__init__()
|
||||
main_builder = component.get('MainWindow').get_builder()
|
||||
super(FilesTab, self).__init__('Files', 'files_tab', 'files_tab_label')
|
||||
|
||||
self._name = 'Files'
|
||||
self._child_widget = main_builder.get_object('files_tab')
|
||||
self._tab_label = main_builder.get_object('files_tab_label')
|
||||
|
||||
self.listview = main_builder.get_object('files_listview')
|
||||
self.listview = self.main_builder.get_object('files_listview')
|
||||
# filename, size, progress string, progress value, priority, file index, icon id
|
||||
self.treestore = gtk.TreeStore(str, TYPE_UINT64, str, float, int, int, str)
|
||||
self.treestore.set_sort_column_id(0, gtk.SORT_ASCENDING)
|
||||
|
@ -155,19 +150,19 @@ class FilesTab(Tab):
|
|||
|
||||
self.listview.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
|
||||
|
||||
self.file_menu = main_builder.get_object('menu_file_tab')
|
||||
self.file_menu = self.main_builder.get_object('menu_file_tab')
|
||||
self.file_menu_priority_items = [
|
||||
main_builder.get_object('menuitem_ignore'),
|
||||
main_builder.get_object('menuitem_low'),
|
||||
main_builder.get_object('menuitem_normal'),
|
||||
main_builder.get_object('menuitem_high'),
|
||||
main_builder.get_object('menuitem_priority_sep')
|
||||
self.main_builder.get_object('menuitem_ignore'),
|
||||
self.main_builder.get_object('menuitem_low'),
|
||||
self.main_builder.get_object('menuitem_normal'),
|
||||
self.main_builder.get_object('menuitem_high'),
|
||||
self.main_builder.get_object('menuitem_priority_sep')
|
||||
]
|
||||
|
||||
self.localhost_widgets = [
|
||||
main_builder.get_object('menuitem_open_file'),
|
||||
main_builder.get_object('menuitem_show_file'),
|
||||
main_builder.get_object('menuitem3')
|
||||
self.main_builder.get_object('menuitem_open_file'),
|
||||
self.main_builder.get_object('menuitem_show_file'),
|
||||
self.main_builder.get_object('menuitem3')
|
||||
]
|
||||
|
||||
self.listview.connect('row-activated', self._on_row_activated)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2008 Andrew Resch <andrewresch@gmail.com>
|
||||
# 2017 Calum Lind <calumlind+deluge@gmail.com>
|
||||
#
|
||||
# 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.
|
||||
|
@ -19,46 +20,45 @@ from deluge.ui.gtkui.torrentdetails import Tab
|
|||
|
||||
class OptionsTab(Tab):
|
||||
def __init__(self):
|
||||
super(OptionsTab, self).__init__()
|
||||
main_builder = component.get('MainWindow').get_builder()
|
||||
|
||||
self._name = 'Options'
|
||||
self._child_widget = main_builder.get_object('options_tab')
|
||||
self._tab_label = main_builder.get_object('options_tab_label')
|
||||
|
||||
self.spin_max_download = main_builder.get_object('spin_max_download')
|
||||
self.spin_max_upload = main_builder.get_object('spin_max_upload')
|
||||
self.spin_max_connections = main_builder.get_object('spin_max_connections')
|
||||
self.spin_max_upload_slots = main_builder.get_object('spin_max_upload_slots')
|
||||
self.chk_prioritize_first_last = main_builder.get_object('chk_prioritize_first_last')
|
||||
self.chk_sequential_download = main_builder.get_object('chk_sequential_download')
|
||||
self.chk_auto_managed = main_builder.get_object('chk_auto_managed')
|
||||
self.chk_stop_at_ratio = main_builder.get_object('chk_stop_at_ratio')
|
||||
self.chk_remove_at_ratio = main_builder.get_object('chk_remove_at_ratio')
|
||||
self.spin_stop_ratio = main_builder.get_object('spin_stop_ratio')
|
||||
self.chk_move_completed = main_builder.get_object('chk_move_completed')
|
||||
self.entry_move_completed = main_builder.get_object('entry_move_completed')
|
||||
self.chk_shared = main_builder.get_object('chk_shared')
|
||||
self.button_apply = main_builder.get_object('button_apply')
|
||||
self.summary_owner = main_builder.get_object('summary_owner')
|
||||
|
||||
self.move_completed_hbox = main_builder.get_object('hbox_move_completed_path_chooser')
|
||||
self.move_completed_path_chooser = PathChooser('move_completed_paths_list')
|
||||
self.move_completed_path_chooser.set_sensitive(self.chk_move_completed.get_active())
|
||||
self.move_completed_hbox.add(self.move_completed_path_chooser)
|
||||
self.move_completed_hbox.show_all()
|
||||
self.move_completed_path_chooser.connect('text-changed', self._on_path_chooser_text_changed_event)
|
||||
super(OptionsTab, self).__init__('Options', 'options_tab', 'options_tab_label')
|
||||
|
||||
self.prev_torrent_id = None
|
||||
self.prev_status = None
|
||||
|
||||
component.get('MainWindow').connect_signals(self)
|
||||
# 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_upload', 'value', ['max_upload_speed'])
|
||||
self.add_tab_widget('spin_max_connections', 'value_as_int', ['max_connections'])
|
||||
self.add_tab_widget('spin_max_upload_slots', 'value_as_int', ['max_upload_slots'])
|
||||
self.add_tab_widget('chk_prioritize_first_last', 'active', ['prioritize_first_last_pieces'])
|
||||
self.add_tab_widget('chk_sequential_download', 'active', ['sequential_download'])
|
||||
self.add_tab_widget('chk_auto_managed', 'active', ['is_auto_managed'])
|
||||
self.add_tab_widget('chk_stop_at_ratio', 'active', ['stop_at_ratio'])
|
||||
self.add_tab_widget('chk_remove_at_ratio', 'active', ['remove_at_ratio'])
|
||||
self.add_tab_widget('spin_stop_ratio', 'value', ['stop_ratio'])
|
||||
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.spin_max_download.connect('key-press-event', self._on_key_press_event)
|
||||
self.spin_max_upload.connect('key-press-event', self._on_key_press_event)
|
||||
self.spin_max_connections.connect('key-press-event', self._on_key_press_event)
|
||||
self.spin_max_upload_slots.connect('key-press-event', self._on_key_press_event)
|
||||
self.spin_stop_ratio.connect('key-press-event', self._on_key_press_event)
|
||||
# Connect key press event for spin widgets.
|
||||
for widget_id in self.tab_widgets:
|
||||
if widget_id.startswith('spin_'):
|
||||
self.tab_widgets[widget_id].obj.connect('key-press-event', self.on_key_press_event)
|
||||
|
||||
self.button_apply = self.main_builder.get_object('button_apply')
|
||||
|
||||
self.move_completed_path_chooser = PathChooser('move_completed_paths_list')
|
||||
self.move_completed_path_chooser.set_sensitive(
|
||||
self.tab_widgets['chk_move_completed'].obj.get_active())
|
||||
self.move_completed_path_chooser.connect(
|
||||
'text-changed', self.on_path_chooser_text_changed_event)
|
||||
self.status_keys.append('move_completed_path')
|
||||
|
||||
self.move_completed_hbox = self.main_builder.get_object('hbox_move_completed_path_chooser')
|
||||
self.move_completed_hbox.add(self.move_completed_path_chooser)
|
||||
self.move_completed_hbox.show_all()
|
||||
|
||||
component.get('MainWindow').connect_signals(self)
|
||||
|
||||
def start(self):
|
||||
pass
|
||||
|
@ -68,11 +68,11 @@ class OptionsTab(Tab):
|
|||
|
||||
def update(self):
|
||||
# Get the first selected torrent
|
||||
torrent_id = 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
|
||||
if torrent_id:
|
||||
torrent_id = torrent_id[0]
|
||||
if torrent_ids:
|
||||
torrent_id = torrent_ids[0]
|
||||
self._child_widget.set_sensitive(True)
|
||||
else:
|
||||
# No torrent is selected in the torrentview
|
||||
|
@ -82,147 +82,77 @@ class OptionsTab(Tab):
|
|||
if torrent_id != self.prev_torrent_id:
|
||||
self.prev_status = None
|
||||
|
||||
component.get('SessionProxy').get_torrent_status(torrent_id, [
|
||||
'max_download_speed',
|
||||
'max_upload_speed',
|
||||
'max_connections',
|
||||
'max_upload_slots',
|
||||
'prioritize_first_last',
|
||||
'is_auto_managed',
|
||||
'stop_at_ratio',
|
||||
'stop_ratio',
|
||||
'remove_at_ratio',
|
||||
'storage_mode',
|
||||
'sequential_download',
|
||||
'move_on_completed',
|
||||
'move_on_completed_path',
|
||||
'shared',
|
||||
'owner'
|
||||
]).addCallback(self._on_get_torrent_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):
|
||||
# We only want to update values that have been applied in the core. This
|
||||
# is so we don't overwrite the user changes that haven't been applied yet.
|
||||
def on_get_torrent_status(self, 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 = {}.fromkeys(list(status), None)
|
||||
self.prev_status = dict.fromkeys(status, None)
|
||||
|
||||
if status != self.prev_status:
|
||||
if status['max_download_speed'] != self.prev_status['max_download_speed']:
|
||||
self.spin_max_download.set_value(status['max_download_speed'])
|
||||
if status['max_upload_speed'] != self.prev_status['max_upload_speed']:
|
||||
self.spin_max_upload.set_value(status['max_upload_speed'])
|
||||
if status['max_connections'] != self.prev_status['max_connections']:
|
||||
self.spin_max_connections.set_value(status['max_connections'])
|
||||
if status['max_upload_slots'] != self.prev_status['max_upload_slots']:
|
||||
self.spin_max_upload_slots.set_value(status['max_upload_slots'])
|
||||
if status['prioritize_first_last'] != self.prev_status['prioritize_first_last']:
|
||||
self.chk_prioritize_first_last.set_active(status['prioritize_first_last'])
|
||||
if status['is_auto_managed'] != self.prev_status['is_auto_managed']:
|
||||
self.chk_auto_managed.set_active(status['is_auto_managed'])
|
||||
if status['stop_at_ratio'] != self.prev_status['stop_at_ratio']:
|
||||
self.chk_stop_at_ratio.set_active(status['stop_at_ratio'])
|
||||
self.spin_stop_ratio.set_sensitive(status['stop_at_ratio'])
|
||||
self.chk_remove_at_ratio.set_sensitive(status['stop_at_ratio'])
|
||||
if status['stop_ratio'] != self.prev_status['stop_ratio']:
|
||||
self.spin_stop_ratio.set_value(status['stop_ratio'])
|
||||
if status['remove_at_ratio'] != self.prev_status['remove_at_ratio']:
|
||||
self.chk_remove_at_ratio.set_active(status['remove_at_ratio'])
|
||||
if status['move_on_completed'] != self.prev_status['move_on_completed']:
|
||||
self.chk_move_completed.set_active(status['move_on_completed'])
|
||||
if status['move_on_completed_path'] != self.prev_status['move_on_completed_path']:
|
||||
self.move_completed_path_chooser.set_text(status['move_on_completed_path'],
|
||||
cursor_end=False, default_text=True)
|
||||
if status['shared'] != self.prev_status['shared']:
|
||||
self.chk_shared.set_active(status['shared'])
|
||||
if status['owner'] != self.prev_status['owner']:
|
||||
self.summary_owner.set_text(status['owner'])
|
||||
for widget in self.tab_widgets.values():
|
||||
status_key = widget.status_keys[0]
|
||||
if status[status_key] != self.prev_status[status_key]:
|
||||
set_func = 'set_' + widget.func.replace('_as_int', '')
|
||||
getattr(widget.obj, set_func)(status[status_key])
|
||||
|
||||
if status['prioritize_first_last'] != self.prev_status['prioritize_first_last']:
|
||||
self.chk_prioritize_first_last.set_active(status['prioritize_first_last'])
|
||||
if not self.chk_prioritize_first_last.get_property('visible'):
|
||||
self.chk_prioritize_first_last.show()
|
||||
if status['sequential_download'] != self.prev_status['sequential_download']:
|
||||
self.chk_sequential_download.set_active(status['sequential_download'])
|
||||
if not self.chk_sequential_download.get_property('visible'):
|
||||
self.chk_sequential_download.show()
|
||||
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 self.button_apply.is_sensitive():
|
||||
self.button_apply.set_sensitive(False)
|
||||
# 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'])
|
||||
|
||||
# Ensure apply button sensitivity is set False.
|
||||
self.button_apply.set_sensitive(False)
|
||||
self.prev_status = status
|
||||
|
||||
def on_button_apply_clicked(self, button):
|
||||
options = {}
|
||||
if self.spin_max_download.get_value() != self.prev_status['max_download_speed']:
|
||||
options['max_download_speed'] = self.spin_max_download.get_value()
|
||||
if self.spin_max_upload.get_value() != self.prev_status['max_upload_speed']:
|
||||
options['max_upload_speed'] = self.spin_max_upload.get_value()
|
||||
if self.spin_max_connections.get_value_as_int() != self.prev_status['max_connections']:
|
||||
options['max_connections'] = self.spin_max_connections.get_value_as_int()
|
||||
if self.spin_max_upload_slots.get_value_as_int() != self.prev_status['max_upload_slots']:
|
||||
options['max_upload_slots'] = self.spin_max_upload_slots.get_value_as_int()
|
||||
if self.chk_prioritize_first_last.get_active() != self.prev_status['prioritize_first_last']:
|
||||
options['prioritize_first_last_pieces'] = self.chk_prioritize_first_last.get_active()
|
||||
if self.chk_sequential_download.get_active() != self.prev_status['sequential_download']:
|
||||
options['sequential_download'] = self.chk_sequential_download.get_active()
|
||||
if self.chk_auto_managed.get_active() != self.prev_status['is_auto_managed']:
|
||||
options['auto_managed'] = self.chk_auto_managed.get_active()
|
||||
if self.chk_stop_at_ratio.get_active() != self.prev_status['stop_at_ratio']:
|
||||
options['stop_at_ratio'] = self.chk_stop_at_ratio.get_active()
|
||||
if self.spin_stop_ratio.get_value() != self.prev_status['stop_ratio']:
|
||||
options['stop_ratio'] = self.spin_stop_ratio.get_value()
|
||||
if self.chk_remove_at_ratio.get_active() != self.prev_status['remove_at_ratio']:
|
||||
options['remove_at_ratio'] = self.chk_remove_at_ratio.get_active()
|
||||
if self.chk_move_completed.get_active() != self.prev_status['move_on_completed']:
|
||||
options['move_completed'] = self.chk_move_completed.get_active()
|
||||
if self.chk_move_completed.get_active():
|
||||
for widget in self.tab_widgets.values():
|
||||
status_key = widget.status_keys[0]
|
||||
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]:
|
||||
options[status_key] = widget_value
|
||||
|
||||
if options.get('move_completed', False):
|
||||
options['move_completed_path'] = self.move_completed_path_chooser.get_text()
|
||||
if self.chk_shared.get_active() != self.prev_status['shared']:
|
||||
options['shared'] = self.chk_shared.get_active()
|
||||
|
||||
client.core.set_torrent_options([self.prev_torrent_id], options)
|
||||
self.button_apply.set_sensitive(False)
|
||||
|
||||
def on_chk_move_completed_toggled(self, widget):
|
||||
value = self.chk_move_completed.get_active()
|
||||
self.move_completed_path_chooser.set_sensitive(value)
|
||||
if not self.button_apply.is_sensitive():
|
||||
self.button_apply.set_sensitive(True)
|
||||
self.move_completed_path_chooser.set_sensitive(widget.get_active())
|
||||
self.button_apply.set_sensitive(True)
|
||||
|
||||
def on_chk_stop_at_ratio_toggled(self, widget):
|
||||
value = widget.get_active()
|
||||
|
||||
self.spin_stop_ratio.set_sensitive(value)
|
||||
self.chk_remove_at_ratio.set_sensitive(value)
|
||||
|
||||
if not self.button_apply.is_sensitive():
|
||||
self.button_apply.set_sensitive(True)
|
||||
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)
|
||||
|
||||
def on_chk_toggled(self, widget):
|
||||
if not self.button_apply.is_sensitive():
|
||||
self.button_apply.set_sensitive(True)
|
||||
self.button_apply.set_sensitive(True)
|
||||
|
||||
def on_spin_value_changed(self, widget):
|
||||
if not self.button_apply.is_sensitive():
|
||||
self.button_apply.set_sensitive(True)
|
||||
self.button_apply.set_sensitive(True)
|
||||
|
||||
def _on_key_press_event(self, widget, event):
|
||||
def on_key_press_event(self, widget, event):
|
||||
keyname = keyval_name(event.keyval).lstrip('KP_').lower()
|
||||
if keyname.isdigit() or keyname in ['period', 'minus', 'delete', 'backspace']:
|
||||
if not self.button_apply.is_sensitive():
|
||||
self.button_apply.set_sensitive(True)
|
||||
|
||||
def on_move_completed_file_set(self, widget):
|
||||
if not self.button_apply.is_sensitive():
|
||||
self.button_apply.set_sensitive(True)
|
||||
|
||||
def _on_entry_move_completed_changed(self, widget):
|
||||
if not self.button_apply.is_sensitive():
|
||||
self.button_apply.set_sensitive(True)
|
||||
|
||||
def _on_path_chooser_text_changed_event(self, widget, path):
|
||||
def on_path_chooser_text_changed_event(self, widget, path):
|
||||
self.button_apply.set_sensitive(True)
|
||||
|
|
|
@ -30,20 +30,17 @@ log = logging.getLogger(__name__)
|
|||
|
||||
class PeersTab(Tab):
|
||||
def __init__(self):
|
||||
super(PeersTab, self).__init__()
|
||||
main_builder = component.get('MainWindow').get_builder()
|
||||
super(PeersTab, self).__init__('Peers', 'peers_tab', 'peers_tab_label')
|
||||
|
||||
self._name = 'Peers'
|
||||
self._child_widget = main_builder.get_object('peers_tab')
|
||||
self._tab_label = main_builder.get_object('peers_tab_label')
|
||||
self.peer_menu = main_builder.get_object('menu_peer_tab')
|
||||
self.peer_menu = self.main_builder.get_object('menu_peer_tab')
|
||||
component.get('MainWindow').connect_signals(self)
|
||||
|
||||
self.listview = main_builder.get_object('peers_listview')
|
||||
self.listview = self.main_builder.get_object('peers_listview')
|
||||
self.listview.props.has_tooltip = True
|
||||
self.listview.connect('button-press-event', self._on_button_press_event)
|
||||
self.listview.connect('query-tooltip', self._on_query_tooltip)
|
||||
# country pixbuf, ip, client, downspeed, upspeed, country code, int_ip, seed/peer icon, progress
|
||||
|
||||
# flag, ip, client, downspd, upspd, country code, int_ip, seed/peer icon, progress
|
||||
self.liststore = ListStore(Pixbuf, str, str, int, int, str, float, Pixbuf, float)
|
||||
self.cached_flag_pixbufs = {}
|
||||
|
||||
|
|
|
@ -17,50 +17,40 @@ from deluge.configmanager import ConfigManager
|
|||
from deluge.ui.gtkui.piecesbar import PiecesBar
|
||||
from deluge.ui.gtkui.tab_data_funcs import (fdate_or_never, fpcnt, fratio, fseed_rank_or_dash, fspeed_max,
|
||||
ftime_or_dash, ftotal_sized)
|
||||
from deluge.ui.gtkui.torrentdetails import Tab
|
||||
from deluge.ui.gtkui.torrentdetails import Tab, TabWidget
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class StatusTab(Tab):
|
||||
def __init__(self):
|
||||
super(StatusTab, self).__init__()
|
||||
# Get the labels we need to update.
|
||||
# widget name, modifier function, status keys
|
||||
main_builder = component.get('MainWindow').get_builder()
|
||||
super(StatusTab, self).__init__('Status', 'status_tab', 'status_tab_label')
|
||||
|
||||
self._name = 'Status'
|
||||
self._child_widget = main_builder.get_object('status_tab')
|
||||
self._tab_label = main_builder.get_object('status_tab_label')
|
||||
self.config = ConfigManager('gtkui.conf')
|
||||
|
||||
self.progressbar = main_builder.get_object('progressbar')
|
||||
self.progressbar = self.main_builder.get_object('progressbar')
|
||||
self.piecesbar = None
|
||||
self.piecesbar_label_widget = None
|
||||
|
||||
self.label_widgets = [
|
||||
(main_builder.get_object('summary_availability'), fratio, ('distributed_copies',)),
|
||||
(main_builder.get_object('summary_total_downloaded'), ftotal_sized, ('all_time_download',
|
||||
'total_payload_download')),
|
||||
(main_builder.get_object('summary_total_uploaded'), ftotal_sized, ('total_uploaded',
|
||||
'total_payload_upload')),
|
||||
(main_builder.get_object('summary_download_speed'), fspeed_max, ('download_payload_rate',
|
||||
'max_download_speed')),
|
||||
(main_builder.get_object('summary_upload_speed'), fspeed_max, ('upload_payload_rate',
|
||||
'max_upload_speed')),
|
||||
(main_builder.get_object('summary_seeds'), fpeer, ('num_seeds', 'total_seeds')),
|
||||
(main_builder.get_object('summary_peers'), fpeer, ('num_peers', 'total_peers')),
|
||||
(main_builder.get_object('summary_eta'), ftime_or_dash, ('eta',)),
|
||||
(main_builder.get_object('summary_share_ratio'), fratio, ('ratio',)),
|
||||
(main_builder.get_object('summary_active_time'), ftime_or_dash, ('active_time',)),
|
||||
(main_builder.get_object('summary_seed_time'), ftime_or_dash, ('seeding_time',)),
|
||||
(main_builder.get_object('summary_seed_rank'), fseed_rank_or_dash, ('seed_rank', 'seeding_time')),
|
||||
(main_builder.get_object('progressbar'), fpcnt, ('progress', 'state', 'message')),
|
||||
(main_builder.get_object('summary_last_seen_complete'), fdate_or_never, ('last_seen_complete',)),
|
||||
(main_builder.get_object('summary_last_transfer'), ftime_or_dash, ('time_since_transfer',)),
|
||||
]
|
||||
self.add_tab_widget('summary_availability', fratio, ('distributed_copies',))
|
||||
self.add_tab_widget('summary_total_downloaded', ftotal_sized,
|
||||
('all_time_download', 'total_payload_download'))
|
||||
self.add_tab_widget('summary_total_uploaded', ftotal_sized,
|
||||
('total_uploaded', 'total_payload_upload'))
|
||||
self.add_tab_widget('summary_download_speed', fspeed_max,
|
||||
('download_payload_rate', 'max_download_speed'))
|
||||
self.add_tab_widget('summary_upload_speed', fspeed_max,
|
||||
('upload_payload_rate', 'max_upload_speed'))
|
||||
self.add_tab_widget('summary_seeds', fpeer, ('num_seeds', 'total_seeds'))
|
||||
self.add_tab_widget('summary_peers', fpeer, ('num_peers', 'total_peers'))
|
||||
self.add_tab_widget('summary_eta', ftime_or_dash, ('eta',))
|
||||
self.add_tab_widget('summary_share_ratio', fratio, ('ratio',))
|
||||
self.add_tab_widget('summary_active_time', ftime_or_dash, ('active_time',))
|
||||
self.add_tab_widget('summary_seed_time', ftime_or_dash, ('seeding_time',))
|
||||
self.add_tab_widget('summary_seed_rank', fseed_rank_or_dash, ('seed_rank', 'seeding_time'))
|
||||
self.add_tab_widget('progressbar', fpcnt, ('progress', 'state', 'message'))
|
||||
self.add_tab_widget('summary_last_seen_complete', fdate_or_never, ('last_seen_complete',))
|
||||
self.add_tab_widget('summary_last_transfer', ftime_or_dash, ('time_since_transfer',))
|
||||
|
||||
self.status_keys = [status for widget in self.label_widgets for status in widget[2]]
|
||||
self.config.register_set_function('show_piecesbar', self.on_show_piecesbar_config_changed, apply_now=True)
|
||||
|
||||
def update(self):
|
||||
|
@ -86,8 +76,8 @@ class StatusTab(Tab):
|
|||
return
|
||||
|
||||
# Update all the label widgets
|
||||
for widget in self.label_widgets:
|
||||
txt = self.get_status_for_widget(widget, status)
|
||||
for widget in self.tab_widgets.values():
|
||||
txt = self.widget_status_as_fstr(widget, status)
|
||||
if widget[0].get_text() != txt:
|
||||
widget[0].set_text(txt)
|
||||
|
||||
|
@ -114,10 +104,9 @@ class StatusTab(Tab):
|
|||
def show_piecesbar(self):
|
||||
if self.piecesbar is None:
|
||||
self.piecesbar = PiecesBar()
|
||||
main_builder = component.get('MainWindow').get_builder()
|
||||
main_builder.get_object('status_progress_vbox').pack_start(self.piecesbar, False, False, 0)
|
||||
self.piecesbar_label_widget = (self.piecesbar, fpcnt, ('progress', 'state', 'message'))
|
||||
self.label_widgets.append(self.piecesbar_label_widget)
|
||||
self.main_builder.get_object(
|
||||
'status_progress_vbox').pack_start(self.piecesbar, False, False, 0)
|
||||
self.tab_widgets['piecesbar'] = TabWidget(self.piecesbar, fpcnt, ('progress', 'state', 'message'))
|
||||
self.piecesbar.show()
|
||||
self.progressbar.hide()
|
||||
|
||||
|
@ -125,11 +114,11 @@ class StatusTab(Tab):
|
|||
self.progressbar.show()
|
||||
if self.piecesbar:
|
||||
self.piecesbar.hide()
|
||||
self.label_widgets.remove(self.piecesbar_label_widget)
|
||||
self.piecesbar = self.piecesbar_label_widget = None
|
||||
self.tab_widgets.pop('piecesbar', None)
|
||||
self.piecesbar = None
|
||||
|
||||
def clear(self):
|
||||
for widget in self.label_widgets:
|
||||
for widget in self.tab_widgets.values():
|
||||
widget[0].set_text('')
|
||||
|
||||
if self.config['show_piecesbar']:
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
import logging
|
||||
from collections import namedtuple
|
||||
|
||||
from gtk import CheckMenuItem, Menu, SeparatorMenuItem
|
||||
|
||||
|
@ -21,13 +22,23 @@ from deluge.ui.gtkui.common import load_pickled_state_file, save_pickled_state_f
|
|||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
TabWidget = namedtuple('TabWidget', ('obj', 'func', 'status_keys'))
|
||||
|
||||
|
||||
class Tab(object):
|
||||
def __init__(self):
|
||||
def __init__(self, name=None, child_widget=None, tab_label=None):
|
||||
self._name = name
|
||||
self.is_visible = True
|
||||
self.position = -1
|
||||
self.weight = -1
|
||||
|
||||
self.main_builder = component.get('MainWindow').get_builder()
|
||||
self._child_widget = self.main_builder.get_object(child_widget)if child_widget else None
|
||||
self._tab_label = self.main_builder.get_object(tab_label) if tab_label else None
|
||||
|
||||
self.tab_widgets = {}
|
||||
self.status_keys = []
|
||||
|
||||
def get_name(self):
|
||||
return self._name
|
||||
|
||||
|
@ -46,18 +57,41 @@ class Tab(object):
|
|||
|
||||
return self._tab_label
|
||||
|
||||
def get_status_for_widget(self, widget, status):
|
||||
def widget_status_as_fstr(self, widget, status):
|
||||
"""Use TabWidget status_key and func to format status string.
|
||||
|
||||
Args:
|
||||
widget (TabWidget): A tuple of widget object, func and status_keys.
|
||||
status (dict): Torrent status dict.
|
||||
|
||||
Returns:
|
||||
str: The formatted status string.
|
||||
"""
|
||||
try:
|
||||
if widget[1] is None:
|
||||
txt = status[widget[2][0]]
|
||||
if widget.func is None:
|
||||
txt = status[widget.status_keys[0]]
|
||||
else:
|
||||
args = [status[key] for key in widget[2]]
|
||||
txt = widget[1](*args)
|
||||
args = [status[key] for key in widget.status_keys]
|
||||
txt = widget.func(*args)
|
||||
except KeyError as ex:
|
||||
log.warn('Unable to get status value: %s', ex)
|
||||
txt = ''
|
||||
return txt
|
||||
|
||||
def add_tab_widget(self, widget_id, format_func, status_keys):
|
||||
"""Create TabWidget item in tab_widgets dictionary.
|
||||
|
||||
Args:
|
||||
widget_id (str): The widget id used to retrieve widget from mainwindow builder.
|
||||
format_func (str): A func name related to widget e.g. string label formatter.
|
||||
status_keys (list): List of status keys to lookup for the widget.
|
||||
|
||||
"""
|
||||
widget_obj = self.main_builder.get_object(widget_id)
|
||||
self.status_keys.extend(status_keys)
|
||||
# Store the widget in a tab_widgets dict with name as key for faster lookup.
|
||||
self.tab_widgets[widget_id] = TabWidget(widget_obj, format_func, status_keys)
|
||||
|
||||
|
||||
class TorrentDetails(component.Component):
|
||||
def __init__(self):
|
||||
|
|
|
@ -21,24 +21,13 @@ log = logging.getLogger(__name__)
|
|||
|
||||
class TrackersTab(Tab):
|
||||
def __init__(self):
|
||||
super(TrackersTab, self).__init__()
|
||||
# Get the labels we need to update.
|
||||
# widget name, modifier function, status keys
|
||||
main_builder = component.get('MainWindow').get_builder()
|
||||
super(TrackersTab, self).__init__('Trackers', 'trackers_tab', 'trackers_tab_label')
|
||||
|
||||
self._name = 'Trackers'
|
||||
self._child_widget = main_builder.get_object('trackers_tab')
|
||||
self._tab_label = main_builder.get_object('trackers_tab_label')
|
||||
|
||||
self.label_widgets = [
|
||||
(main_builder.get_object('summary_next_announce'), ftime, ('next_announce',)),
|
||||
(main_builder.get_object('summary_tracker'), None, ('tracker_host',)),
|
||||
(main_builder.get_object('summary_tracker_status'), ftranslate, ('tracker_status',)),
|
||||
(main_builder.get_object('summary_tracker_total'), fcount, ('trackers',)),
|
||||
(main_builder.get_object('summary_private'), fyes_no, ('private',)),
|
||||
]
|
||||
|
||||
self.status_keys = [status for widget in self.label_widgets for status in widget[2]]
|
||||
self.add_tab_widget('summary_next_announce', ftime, ('next_announce',))
|
||||
self.add_tab_widget('summary_tracker', None, ('tracker_host',))
|
||||
self.add_tab_widget('summary_tracker_status', ftranslate, ('tracker_status',))
|
||||
self.add_tab_widget('summary_tracker_total', fcount, ('trackers',))
|
||||
self.add_tab_widget('summary_private', fyes_no, ('private',))
|
||||
|
||||
component.get('MainWindow').connect_signals(self)
|
||||
|
||||
|
@ -61,15 +50,15 @@ class TrackersTab(Tab):
|
|||
if not status:
|
||||
return
|
||||
|
||||
# Update all the label widgets
|
||||
for widget in self.label_widgets:
|
||||
txt = self.get_status_for_widget(widget, status)
|
||||
if widget[0].get_text() != txt:
|
||||
widget[0].set_text(txt)
|
||||
# Update all the tab label widgets
|
||||
for widget in self.tab_widgets.values():
|
||||
txt = self.widget_status_as_fstr(widget, status)
|
||||
if widget.obj.get_text() != txt:
|
||||
widget.obj.set_text(txt)
|
||||
|
||||
def clear(self):
|
||||
for widget in self.label_widgets:
|
||||
widget[0].set_text('')
|
||||
for widget in self.tab_widgets.values():
|
||||
widget.obj.set_text('')
|
||||
|
||||
def on_button_edit_trackers_clicked(self, button):
|
||||
torrent_id = component.get('TorrentView').get_selected_torrent()
|
||||
|
|
Loading…
Add table
Reference in a new issue