deluge/deluge/ui/gtkui/preferences.py
2009-03-02 01:46:22 +00:00

890 lines
41 KiB
Python

#
# preferences.py
#
# Copyright (C) 2007, 2008 Andrew Resch <andrewresch@gmail.com>
#
# Deluge is free software.
#
# You may redistribute it and/or modify it under the terms of the
# GNU General Public License, as published by the Free Software
# Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# deluge is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
#
import pygtk
pygtk.require('2.0')
import gtk, gtk.glade
import pkg_resources
import deluge.component as component
from deluge.log import LOG as log
from deluge.ui.client import client
import deluge.common
import deluge.error
import deluge.ui.gtkui.common as common
from deluge.configmanager import ConfigManager
import deluge.configmanager
class Preferences(component.Component):
def __init__(self):
component.Component.__init__(self, "Preferences")
self.window = component.get("MainWindow")
self.glade = gtk.glade.XML(
pkg_resources.resource_filename("deluge.ui.gtkui",
"glade/preferences_dialog.glade"))
self.pref_dialog = self.glade.get_widget("pref_dialog")
self.pref_dialog.set_icon(common.get_logo(32))
self.treeview = self.glade.get_widget("treeview")
self.notebook = self.glade.get_widget("notebook")
self.gtkui_config = ConfigManager("gtkui.conf")
# Setup the liststore for the categories (tab pages)
self.liststore = gtk.ListStore(int, str)
self.treeview.set_model(self.liststore)
render = gtk.CellRendererText()
column = gtk.TreeViewColumn("Categories", render, text=1)
self.treeview.append_column(column)
# Add the default categories
i = 0
for category in [_("Downloads"), _("Network"), _("Bandwidth"), _("Interface"),
_("Other"), _("Daemon"), _("Queue"), _("Proxy"), _("Notification"), _("Plugins")]:
self.liststore.append([i, category])
i += 1
# Setup plugin tab listview
self.plugin_liststore = gtk.ListStore(str, bool)
self.plugin_listview = self.glade.get_widget("plugin_listview")
self.plugin_listview.set_model(self.plugin_liststore)
render = gtk.CellRendererToggle()
render.connect("toggled", self.on_plugin_toggled)
render.set_property("activatable", True)
self.plugin_listview.append_column(
gtk.TreeViewColumn(_("Enabled"), render, active=1))
self.plugin_listview.append_column(
gtk.TreeViewColumn(_("Plugin"), gtk.CellRendererText(), text=0))
# Connect to the 'changed' event of TreeViewSelection to get selection
# changes.
self.treeview.get_selection().connect("changed",
self.on_selection_changed)
self.plugin_listview.get_selection().connect("changed",
self.on_plugin_selection_changed)
self.glade.signal_autoconnect({
"on_pref_dialog_delete_event": self.on_pref_dialog_delete_event,
"on_button_ok_clicked": self.on_button_ok_clicked,
"on_button_apply_clicked": self.on_button_apply_clicked,
"on_button_cancel_clicked": self.on_button_cancel_clicked,
"on_toggle": self.on_toggle,
"on_test_port_clicked": self.on_test_port_clicked,
"on_button_plugin_install_clicked": self._on_button_plugin_install_clicked,
"on_button_rescan_plugins_clicked": self._on_button_rescan_plugins_clicked
})
# These get updated by requests done to the core
self.all_plugins = []
self.enabled_plugins = []
def __del__(self):
del self.gtkui_config
def add_page(self, name, widget):
"""Add a another page to the notebook"""
# Create a header and scrolled window for the preferences tab
parent = widget.get_parent()
if parent:
parent.remove(widget)
vbox = gtk.VBox()
label = gtk.Label()
label.set_use_markup(True)
label.set_markup("<b><i><big>" + name + "</big></i></b>")
label.set_alignment(0.05, 0.50)
label.set_padding(0, 10)
vbox.pack_start(label, False, True, 0)
sep = gtk.HSeparator()
vbox.pack_start(sep, False, True, 0)
align = gtk.Alignment()
align.set_padding(5, 0, 0, 0)
align.add(widget)
vbox.pack_start(align, False, False, 0)
scrolled = gtk.ScrolledWindow()
viewport = gtk.Viewport()
viewport.set_shadow_type(gtk.SHADOW_NONE)
viewport.add(vbox)
scrolled.add(viewport)
scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
scrolled.show_all()
# Add this page to the notebook
index = self.notebook.append_page(scrolled)
self.liststore.append([index, name])
return name
def remove_page(self, name):
"""Removes a page from the notebook"""
self.page_num_to_remove = None
self.iter_to_remove = None
def check_row(model, path, iter, user_data):
row_name = model.get_value(iter, 1)
if row_name == user_data:
# This is the row we need to remove
self.page_num_to_remove = model.get_value(iter, 0)
self.iter_to_remove = iter
return
self.liststore.foreach(check_row, name)
# Remove the page and row
if self.page_num_to_remove != None:
self.notebook.remove_page(self.page_num_to_remove)
if self.iter_to_remove != None:
self.liststore.remove(self.iter_to_remove)
def show(self, page=None):
"""Page should be the string in the left list.. ie, 'Network' or 'Bandwidth'"""
if page != None:
for (index, string) in self.liststore:
if page == string:
self.treeview.get_selection().select_path(index)
break
# Update the preferences dialog to reflect current config settings
self.core_config = {}
if client.connected():
def _on_get_config(config):
self.core_config = config
client.core.get_available_plugins().addCallback(_on_get_available_plugins)
def _on_get_available_plugins(plugins):
self.all_plugins = plugins
client.core.get_enabled_plugins().addCallback(_on_get_enabled_plugins)
def _on_get_enabled_plugins(plugins):
self.enabled_plugins = plugins
client.core.get_listen_port().addCallback(_on_get_listen_port)
def _on_get_listen_port(port):
self.active_port = port
self._show()
# This starts a series of client.core requests prior to showing the window
client.core.get_config().addCallback(_on_get_config)
else:
self._show()
def _show(self):
if self.core_config != {} and self.core_config != None:
core_widgets = {
"download_path_button": \
("filename", self.core_config["download_location"]),
"chk_move_completed": \
("active", self.core_config["move_completed"]),
"move_completed_path_button": \
("filename", self.core_config["move_completed_path"]),
"chk_copy_torrent_file": \
("active", self.core_config["copy_torrent_file"]),
"torrent_files_button": \
("filename", self.core_config["torrentfiles_location"]),
"chk_autoadd": \
("active", self.core_config["autoadd_enable"]),
"folder_autoadd": \
("filename", self.core_config["autoadd_location"]),
"radio_compact_allocation": \
("active", self.core_config["compact_allocation"]),
"radio_full_allocation": \
("not_active", self.core_config["compact_allocation"]),
"chk_prioritize_first_last_pieces": \
("active",
self.core_config["prioritize_first_last_pieces"]),
"spin_port_min": ("value", self.core_config["listen_ports"][0]),
"spin_port_max": ("value", self.core_config["listen_ports"][1]),
"active_port_label": ("text", str(self.active_port)),
"chk_random_port": ("active", self.core_config["random_port"]),
"spin_outgoing_port_min": ("value", self.core_config["outgoing_ports"][0]),
"spin_outgoing_port_max": ("value", self.core_config["outgoing_ports"][1]),
"chk_random_outgoing_ports": ("active", self.core_config["random_outgoing_ports"]),
"entry_peer_tos": ("text", self.core_config["peer_tos"]),
"chk_dht": ("active", self.core_config["dht"]),
"chk_upnp": ("active", self.core_config["upnp"]),
"chk_natpmp": ("active", self.core_config["natpmp"]),
"chk_utpex": ("active", self.core_config["utpex"]),
"chk_lsd": ("active", self.core_config["lsd"]),
"chk_new_releases": ("active", self.core_config["new_release_check"]),
"chk_send_info": ("active", self.core_config["send_info"]),
"combo_encin": ("active", self.core_config["enc_in_policy"]),
"combo_encout": ("active", self.core_config["enc_out_policy"]),
"combo_enclevel": ("active", self.core_config["enc_level"]),
"chk_pref_rc4": ("active", self.core_config["enc_prefer_rc4"]),
"spin_max_connections_global": \
("value", self.core_config["max_connections_global"]),
"spin_max_download": \
("value", self.core_config["max_download_speed"]),
"spin_max_upload": \
("value", self.core_config["max_upload_speed"]),
"spin_max_upload_slots_global": \
("value", self.core_config["max_upload_slots_global"]),
"spin_max_half_open_connections": \
("value", self.core_config["max_half_open_connections"]),
"spin_max_connections_per_second": \
("value", self.core_config["max_connections_per_second"]),
"chk_ignore_limits_on_local_network": \
("active", self.core_config["ignore_limits_on_local_network"]),
"chk_rate_limit_ip_overhead": \
("active", self.core_config["rate_limit_ip_overhead"]),
"spin_max_connections_per_torrent": \
("value", self.core_config["max_connections_per_torrent"]),
"spin_max_upload_slots_per_torrent": \
("value", self.core_config["max_upload_slots_per_torrent"]),
"spin_max_download_per_torrent": \
("value", self.core_config["max_download_speed_per_torrent"]),
"spin_max_upload_per_torrent": \
("value", self.core_config["max_upload_speed_per_torrent"]),
"spin_daemon_port": \
("value", self.core_config["daemon_port"]),
"chk_allow_remote_connections": \
("active", self.core_config["allow_remote"]),
"spin_active": ("value", self.core_config["max_active_limit"]),
"spin_seeding": ("value", self.core_config["max_active_seeding"]),
"spin_downloading": ("value", self.core_config["max_active_downloading"]),
"chk_dont_count_slow_torrents": ("active", self.core_config["dont_count_slow_torrents"]),
"chk_queue_new_top": ("active", self.core_config["queue_new_to_top"]),
"spin_share_ratio_limit": ("value", self.core_config["share_ratio_limit"]),
"spin_seed_time_ratio_limit": \
("value", self.core_config["seed_time_ratio_limit"]),
"spin_seed_time_limit": ("value", self.core_config["seed_time_limit"]),
"chk_seed_ratio": ("active", self.core_config["stop_seed_at_ratio"]),
"spin_share_ratio": ("value", self.core_config["stop_seed_ratio"]),
"chk_remove_ratio": ("active", self.core_config["remove_seed_at_ratio"]),
}
# Add proxy stuff
for t in ("peer", "web_seed", "tracker", "dht"):
core_widgets["spin_proxy_port_%s" % t] = ("value", self.core_config["proxies"][t]["port"])
core_widgets["combo_proxy_type_%s" % t] = ("active", self.core_config["proxies"][t]["type"])
core_widgets["txt_proxy_server_%s" % t] = ("text", self.core_config["proxies"][t]["hostname"])
core_widgets["txt_proxy_username_%s" % t] = ("text", self.core_config["proxies"][t]["username"])
core_widgets["txt_proxy_password_%s" % t] = ("text", self.core_config["proxies"][t]["password"])
# Change a few widgets if we're connected to a remote host
if not client.is_localhost():
self.glade.get_widget("entry_download_path").show()
self.glade.get_widget("download_path_button").hide()
core_widgets.pop("download_path_button")
core_widgets["entry_download_path"] = ("text", self.core_config["download_location"])
self.glade.get_widget("entry_move_completed_path").show()
self.glade.get_widget("move_completed_path_button").hide()
core_widgets.pop("move_completed_path_button")
core_widgets["entry_move_completed_path"] = ("text", self.core_config["move_completed_path"])
self.glade.get_widget("entry_torrents_path").show()
self.glade.get_widget("torrent_files_button").hide()
core_widgets.pop("torrent_files_button")
core_widgets["entry_torrents_path"] = ("text", self.core_config["torrentfiles_location"])
self.glade.get_widget("entry_autoadd").show()
self.glade.get_widget("folder_autoadd").hide()
core_widgets.pop("folder_autoadd")
core_widgets["entry_autoadd"] = ("text", self.core_config["autoadd_location"])
else:
self.glade.get_widget("entry_download_path").hide()
self.glade.get_widget("download_path_button").show()
self.glade.get_widget("entry_move_completed_path").hide()
self.glade.get_widget("move_completed_path_button").show()
self.glade.get_widget("entry_torrents_path").hide()
self.glade.get_widget("torrent_files_button").show()
self.glade.get_widget("entry_autoadd").hide()
self.glade.get_widget("folder_autoadd").show()
# Update the widgets accordingly
for key in core_widgets.keys():
modifier = core_widgets[key][0]
value = core_widgets[key][1]
widget = self.glade.get_widget(key)
if type(widget) == gtk.FileChooserButton:
for child in widget.get_children():
child.set_sensitive(True)
widget.set_sensitive(True)
if modifier == "filename":
if value:
try:
widget.set_current_folder(value)
except Exception, e:
log.debug("Unable to set_current_folder: %s", e)
elif modifier == "active":
widget.set_active(value)
elif modifier == "not_active":
widget.set_active(not value)
elif modifier == "value":
widget.set_value(value)
elif modifier == "text":
widget.set_text(value)
for key in core_widgets.keys():
widget = self.glade.get_widget(key)
# Update the toggle status if necessary
self.on_toggle(widget)
else:
core_widget_list = [
"download_path_button",
"chk_move_completed",
"move_completed_path_button",
"chk_copy_torrent_file",
"torrent_files_button",
"chk_autoadd",
"folder_autoadd",
"radio_compact_allocation",
"radio_full_allocation",
"chk_prioritize_first_last_pieces",
"spin_port_min",
"spin_port_max",
"active_port_label",
"chk_random_port",
"spin_outgoing_port_min",
"spin_outgoing_port_max",
"chk_random_outgoing_ports",
"entry_peer_tos",
"chk_dht",
"chk_upnp",
"chk_natpmp",
"chk_utpex",
"chk_lsd",
"chk_send_info",
"chk_new_releases",
"combo_encin",
"combo_encout",
"combo_enclevel",
"chk_pref_rc4",
"spin_max_connections_global",
"spin_max_download",
"spin_max_upload",
"spin_max_upload_slots_global",
"spin_max_half_open_connections",
"spin_max_connections_per_second",
"chk_ignore_limits_on_local_network",
"chk_rate_limit_ip_overhead",
"spin_max_connections_per_torrent",
"spin_max_upload_slots_per_torrent",
"spin_max_download_per_torrent",
"spin_max_upload_per_torrent",
"spin_daemon_port",
"chk_allow_remote_connections",
"spin_seeding",
"spin_downloading",
"spin_active",
"chk_dont_count_slow_torrents",
"chk_queue_new_top",
"chk_seed_ratio",
"spin_share_ratio",
"chk_remove_ratio",
"spin_share_ratio_limit",
"spin_seed_time_ratio_limit",
"spin_seed_time_limit",
]
for t in ("peer", "web_seed", "tracker", "dht"):
core_widget_list.append("spin_proxy_port_%s" % t)
core_widget_list.append("combo_proxy_type_%s" % t)
core_widget_list.append("txt_proxy_username_%s" % t)
core_widget_list.append("txt_proxy_password_%s" % t)
core_widget_list.append("txt_proxy_server_%s" % t)
# We don't appear to be connected to a daemon
for key in core_widget_list:
widget = self.glade.get_widget(key)
if type(widget) == gtk.FileChooserButton:
for child in widget.get_children():
child.set_sensitive(False)
widget.set_sensitive(False)
## Downloads tab ##
self.glade.get_widget("chk_show_dialog").set_active(
self.gtkui_config["interactive_add"])
self.glade.get_widget("chk_focus_dialog").set_active(
self.gtkui_config["focus_add_dialog"])
## Interface tab ##
self.glade.get_widget("chk_use_tray").set_active(
self.gtkui_config["enable_system_tray"])
self.glade.get_widget("chk_min_on_close").set_active(
self.gtkui_config["close_to_tray"])
self.glade.get_widget("chk_start_in_tray").set_active(
self.gtkui_config["start_in_tray"])
self.glade.get_widget("chk_lock_tray").set_active(
self.gtkui_config["lock_tray"])
self.glade.get_widget("chk_classic_mode").set_active(
self.gtkui_config["classic_mode"])
self.glade.get_widget("chk_show_rate_in_title").set_active(
self.gtkui_config["show_rate_in_title"])
## Other tab ##
self.glade.get_widget("chk_show_new_releases").set_active(
self.gtkui_config["show_new_releases"])
## Notification tab ##
self.glade.get_widget("chk_ntf_tray_blink").set_active(
self.gtkui_config["ntf_tray_blink"])
if deluge.common.windows_check():
self.glade.get_widget("chk_ntf_popup").set_sensitive(False)
else:
self.glade.get_widget("chk_ntf_popup").set_active(
self.gtkui_config["ntf_popup"])
self.glade.get_widget("chk_ntf_email").set_active(
self.gtkui_config["ntf_email"])
self.glade.get_widget("chk_ntf_sound").set_active(
self.gtkui_config["ntf_sound"])
if self.gtkui_config["ntf_sound_path"]:
self.glade.get_widget("combo_ntf_sound_path").set_filename(self.gtkui_config["ntf_sound_path"])
self.glade.get_widget("txt_ntf_email").set_text(
self.gtkui_config["ntf_email_add"])
self.glade.get_widget("txt_ntf_server").set_text(
self.gtkui_config["ntf_server"])
self.glade.get_widget("txt_ntf_username").set_text(
self.gtkui_config["ntf_username"])
self.glade.get_widget("txt_ntf_pass").set_text(
self.gtkui_config["ntf_pass"])
if not self.gtkui_config["ntf_security"]:
self.glade.get_widget("rad_ntf_none").set_active(True)
elif self.gtkui_config["ntf_security"] == 'SSL':
self.glade.get_widget("rad_ntf_none").set_active(True)
elif self.gtkui_config["ntf_security"] == 'TLS':
self.glade.get_widget("rad_ntf_tls").set_active(True)
## Plugins tab ##
all_plugins = self.all_plugins
enabled_plugins = self.enabled_plugins
# Clear the existing list so we don't duplicate entries.
self.plugin_liststore.clear()
# Iterate through the lists and add them to the liststore
for plugin in all_plugins:
if plugin in enabled_plugins:
enabled = True
else:
enabled = False
row = self.plugin_liststore.append()
self.plugin_liststore.set_value(row, 0, plugin)
self.plugin_liststore.set_value(row, 1, enabled)
component.get("PluginManager").run_on_show_prefs()
# Now show the dialog
self.pref_dialog.show()
def set_config(self, hide=False):
"""
Sets all altered config values in the core.
:param hide: bool, if True, will not re-show the dialog and will hide it instead
"""
try:
from hashlib import sha1 as sha_hash
except ImportError:
from sha import new as sha_hash
# Get the values from the dialog
new_core_config = {}
new_gtkui_config = {}
## Downloads tab ##
new_gtkui_config["interactive_add"] = \
self.glade.get_widget("chk_show_dialog").get_active()
new_gtkui_config["focus_add_dialog"] = \
self.glade.get_widget("chk_focus_dialog").get_active()
new_core_config["copy_torrent_file"] = \
self.glade.get_widget("chk_copy_torrent_file").get_active()
new_core_config["move_completed"] = \
self.glade.get_widget("chk_move_completed").get_active()
if client.is_localhost():
new_core_config["download_location"] = \
self.glade.get_widget("download_path_button").get_filename()
new_core_config["move_completed_path"] = \
self.glade.get_widget("move_completed_path_button").get_filename()
new_core_config["torrentfiles_location"] = \
self.glade.get_widget("torrent_files_button").get_filename()
else:
new_core_config["download_location"] = \
self.glade.get_widget("entry_download_path").get_text()
new_core_config["move_completed_path"] = \
self.glade.get_widget("entry_move_completed_path").get_text()
new_core_config["torrentfiles_location"] = \
self.glade.get_widget("entry_torrents_path").get_text()
new_core_config["autoadd_enable"] = \
self.glade.get_widget("chk_autoadd").get_active()
if client.is_localhost():
new_core_config["autoadd_location"] = \
self.glade.get_widget("folder_autoadd").get_filename()
else:
new_core_config["autoadd_location"] = \
self.glade.get_widget("entry_autoadd").get_text()
new_core_config["compact_allocation"] = \
self.glade.get_widget("radio_compact_allocation").get_active()
new_core_config["prioritize_first_last_pieces"] = \
self.glade.get_widget(
"chk_prioritize_first_last_pieces").get_active()
## Network tab ##
listen_ports = []
listen_ports.append(
self.glade.get_widget("spin_port_min").get_value_as_int())
listen_ports.append(
self.glade.get_widget("spin_port_max").get_value_as_int())
new_core_config["listen_ports"] = listen_ports
new_core_config["random_port"] = \
self.glade.get_widget("chk_random_port").get_active()
outgoing_ports = []
outgoing_ports.append(
self.glade.get_widget("spin_outgoing_port_min").get_value_as_int())
outgoing_ports.append(
self.glade.get_widget("spin_outgoing_port_max").get_value_as_int())
new_core_config["outgoing_ports"] = outgoing_ports
new_core_config["random_outgoing_ports"] = \
self.glade.get_widget("chk_random_outgoing_ports").get_active()
new_core_config["peer_tos"] = self.glade.get_widget("entry_peer_tos").get_text()
new_core_config["dht"] = self.glade.get_widget("chk_dht").get_active()
new_core_config["upnp"] = self.glade.get_widget("chk_upnp").get_active()
new_core_config["natpmp"] = \
self.glade.get_widget("chk_natpmp").get_active()
new_core_config["utpex"] = \
self.glade.get_widget("chk_utpex").get_active()
new_core_config["lsd"] = \
self.glade.get_widget("chk_lsd").get_active()
new_core_config["enc_in_policy"] = \
self.glade.get_widget("combo_encin").get_active()
new_core_config["enc_out_policy"] = \
self.glade.get_widget("combo_encout").get_active()
new_core_config["enc_level"] = \
self.glade.get_widget("combo_enclevel").get_active()
new_core_config["enc_prefer_rc4"] = \
self.glade.get_widget("chk_pref_rc4").get_active()
## Bandwidth tab ##
new_core_config["max_connections_global"] = \
self.glade.get_widget(
"spin_max_connections_global").get_value_as_int()
new_core_config["max_download_speed"] = \
self.glade.get_widget("spin_max_download").get_value()
new_core_config["max_upload_speed"] = \
self.glade.get_widget("spin_max_upload").get_value()
new_core_config["max_upload_slots_global"] = \
self.glade.get_widget(
"spin_max_upload_slots_global").get_value_as_int()
new_core_config["max_half_open_connections"] = \
self.glade.get_widget("spin_max_half_open_connections").get_value_as_int()
new_core_config["max_connections_per_second"] = \
self.glade.get_widget(
"spin_max_connections_per_second").get_value_as_int()
new_core_config["max_connections_per_torrent"] = \
self.glade.get_widget(
"spin_max_connections_per_torrent").get_value_as_int()
new_core_config["max_upload_slots_per_torrent"] = \
self.glade.get_widget(
"spin_max_upload_slots_per_torrent").get_value_as_int()
new_core_config["max_upload_speed_per_torrent"] = \
self.glade.get_widget(
"spin_max_upload_per_torrent").get_value()
new_core_config["max_download_speed_per_torrent"] = \
self.glade.get_widget(
"spin_max_download_per_torrent").get_value()
new_core_config["ignore_limits_on_local_network"] = \
self.glade.get_widget("chk_ignore_limits_on_local_network").get_active()
new_core_config["rate_limit_ip_overhead"] = \
self.glade.get_widget("chk_rate_limit_ip_overhead").get_active()
## Interface tab ##
new_gtkui_config["enable_system_tray"] = \
self.glade.get_widget("chk_use_tray").get_active()
new_gtkui_config["close_to_tray"] = \
self.glade.get_widget("chk_min_on_close").get_active()
new_gtkui_config["start_in_tray"] = \
self.glade.get_widget("chk_start_in_tray").get_active()
new_gtkui_config["lock_tray"] = \
self.glade.get_widget("chk_lock_tray").get_active()
passhex = sha_hash(\
self.glade.get_widget("txt_tray_password").get_text()).hexdigest()
if passhex != "c07eb5a8c0dc7bb81c217b67f11c3b7a5e95ffd7":
new_gtkui_config["tray_password"] = passhex
new_gtkui_config["classic_mode"] = \
self.glade.get_widget("chk_classic_mode").get_active()
new_gtkui_config["show_rate_in_title"] = \
self.glade.get_widget("chk_show_rate_in_title").get_active()
## Notification tab ##
new_gtkui_config["ntf_tray_blink"] = \
self.glade.get_widget("chk_ntf_tray_blink").get_active()
new_gtkui_config["ntf_popup"] = \
self.glade.get_widget("chk_ntf_popup").get_active()
new_gtkui_config["ntf_sound"] = \
self.glade.get_widget("chk_ntf_sound").get_active()
new_gtkui_config["ntf_email"] = \
self.glade.get_widget("chk_ntf_email").get_active()
new_gtkui_config["ntf_email_add"] = \
self.glade.get_widget("txt_ntf_email").get_text()
new_gtkui_config["ntf_username"] = \
self.glade.get_widget("txt_ntf_username").get_text()
new_gtkui_config["ntf_pass"] = \
self.glade.get_widget("txt_ntf_pass").get_text()
new_gtkui_config["ntf_server"] = \
self.glade.get_widget("txt_ntf_server").get_text()
new_gtkui_config["ntf_sound_path"] = \
self.glade.get_widget("combo_ntf_sound_path").get_filename()
if self.glade.get_widget("rad_ntf_none").get_active():
new_gtkui_config["ntf_security"] = None
elif self.glade.get_widget("rad_ntf_ssl").get_active():
new_gtkui_config["ntf_security"] = 'SSL'
elif self.glade.get_widget("rad_ntf_tls").get_active():
new_gtkui_config["ntf_security"] = 'TLS'
## Other tab ##
new_gtkui_config["show_new_releases"] = \
self.glade.get_widget("chk_show_new_releases").get_active()
new_core_config["send_info"] = \
self.glade.get_widget("chk_send_info").get_active()
## Daemon tab ##
new_core_config["daemon_port"] = \
self.glade.get_widget("spin_daemon_port").get_value_as_int()
new_core_config["allow_remote"] = \
self.glade.get_widget("chk_allow_remote_connections").get_active()
new_core_config["new_release_check"] = \
self.glade.get_widget("chk_new_releases").get_active()
## Proxy tab ##
new_core_config["proxies"] = {}
for t in ("peer", "web_seed", "tracker", "dht"):
new_core_config["proxies"][t] = {}
new_core_config["proxies"][t]["type"] = \
self.glade.get_widget("combo_proxy_type_%s" % t).get_active()
new_core_config["proxies"][t]["port"] = \
self.glade.get_widget("spin_proxy_port_%s" % t).get_value_as_int()
new_core_config["proxies"][t]["username"] = \
self.glade.get_widget("txt_proxy_username_%s" % t).get_text()
new_core_config["proxies"][t]["password"] = \
self.glade.get_widget("txt_proxy_password_%s" % t).get_text()
new_core_config["proxies"][t]["hostname"] = \
self.glade.get_widget("txt_proxy_server_%s" % t).get_text()
## Queue tab ##
new_core_config["queue_new_to_top"] = \
self.glade.get_widget("chk_queue_new_top").get_active()
new_core_config["max_active_seeding"] = \
self.glade.get_widget("spin_seeding").get_value_as_int()
new_core_config["max_active_downloading"] = \
self.glade.get_widget("spin_downloading").get_value_as_int()
new_core_config["max_active_limit"] = \
self.glade.get_widget("spin_active").get_value_as_int()
new_core_config["dont_count_slow_torrents"] = \
self.glade.get_widget("chk_dont_count_slow_torrents").get_active()
new_core_config["stop_seed_at_ratio"] = \
self.glade.get_widget("chk_seed_ratio").get_active()
new_core_config["remove_seed_at_ratio"] = \
self.glade.get_widget("chk_remove_ratio").get_active()
new_core_config["stop_seed_ratio"] = \
self.glade.get_widget("spin_share_ratio").get_value()
new_core_config["share_ratio_limit"] = \
self.glade.get_widget("spin_share_ratio_limit").get_value()
new_core_config["seed_time_ratio_limit"] = \
self.glade.get_widget("spin_seed_time_ratio_limit").get_value()
new_core_config["seed_time_limit"] = \
self.glade.get_widget("spin_seed_time_limit").get_value()
# Run plugin hook to apply preferences
component.get("PluginManager").run_on_apply_prefs()
# GtkUI
for key in new_gtkui_config.keys():
# The values do not match so this needs to be updated
if self.gtkui_config[key] != new_gtkui_config[key]:
self.gtkui_config[key] = new_gtkui_config[key]
# Core
if client.connected():
# Only do this if we're connected to a daemon
config_to_set = {}
for key in new_core_config.keys():
# The values do not match so this needs to be updated
if self.core_config[key] != new_core_config[key]:
config_to_set[key] = new_core_config[key]
# Set each changed config value in the core
client.core.set_config(config_to_set)
client.force_call(True)
# Update the configuration
self.core_config.update(config_to_set)
if hide:
self.hide()
else:
# Re-show the dialog to make sure everything has been updated
self.show()
def hide(self):
self.pref_dialog.hide()
def on_pref_dialog_delete_event(self, widget, event):
self.hide()
return True
def on_toggle(self, widget):
"""Handles widget sensitivity based on radio/check button values."""
try:
value = widget.get_active()
except:
return
dependents = {
"chk_show_dialog": {"chk_focus_dialog": True},
"chk_random_port": {"spin_port_min": False,
"spin_port_max": False},
"chk_random_outgoing_ports": {"spin_outgoing_port_min": False,
"spin_outgoing_port_max": False},
"chk_use_tray": {"chk_min_on_close": True,
"chk_start_in_tray": True,
"chk_lock_tray": True},
"chk_lock_tray": {"txt_tray_password": True,
"password_label": True},
"radio_open_folder_custom": {"combo_file_manager": False,
"txt_open_folder_location": True},
"chk_move_completed" : {"move_completed_path_button" : True},
"chk_copy_torrent_file" : {"torrent_files_button" : True},
"chk_autoadd" : {"folder_autoadd" : True},
"chk_seed_ratio" : {"spin_share_ratio": True,
"chk_remove_ratio" : True}
}
def update_dependent_widgets(name, value):
dependency = dependents[name]
for dep in dependency.keys():
depwidget = self.glade.get_widget(dep)
sensitive = [not value, value][dependency[dep]]
depwidget.set_sensitive(sensitive)
if dep in dependents:
update_dependent_widgets(dep, depwidget.get_active() and sensitive)
for key in dependents.keys():
if widget != self.glade.get_widget(key):
continue
update_dependent_widgets(key, value)
def on_button_ok_clicked(self, data):
log.debug("on_button_ok_clicked")
self.set_config(hide=True)
return True
def on_button_apply_clicked(self, data):
log.debug("on_button_apply_clicked")
self.set_config()
def on_button_cancel_clicked(self, data):
log.debug("on_button_cancel_clicked")
self.hide()
return True
def on_selection_changed(self, treeselection):
# Show the correct notebook page based on what row is selected.
(model, row) = treeselection.get_selected()
try:
self.notebook.set_current_page(model.get_value(row, 0))
except TypeError:
pass
def on_test_port_clicked(self, data):
log.debug("on_test_port_clicked")
def on_get_test(status):
if status:
self.glade.get_widget("port_img").set_from_stock(gtk.STOCK_YES, 4)
self.glade.get_widget("port_img").show()
else:
self.glade.get_widget("port_img").set_from_stock(gtk.STOCK_DIALOG_WARNING, 4)
self.glade.get_widget("port_img").show()
client.core.test_listen_port().addCallback(on_get_test)
client.force_call()
def on_plugin_toggled(self, renderer, path):
log.debug("on_plugin_toggled")
row = self.plugin_liststore.get_iter_from_string(path)
name = self.plugin_liststore.get_value(row, 0)
value = self.plugin_liststore.get_value(row, 1)
self.plugin_liststore.set_value(row, 1, not value)
if not value:
client.core.enable_plugin(name)
component.get("PluginManager").enable_plugin(name)
else:
client.core.disable_plugin(name)
component.get("PluginManager").disable_plugin(name)
def on_plugin_selection_changed(self, treeselection):
log.debug("on_plugin_selection_changed")
(model, itr) = treeselection.get_selected()
if not itr:
return
name = model[itr][0]
plugin_info = component.get("PluginManager").get_plugin_info(name)
self.glade.get_widget("label_plugin_author").set_text(plugin_info["Author"])
self.glade.get_widget("label_plugin_version").set_text(plugin_info["Version"])
self.glade.get_widget("label_plugin_email").set_text(plugin_info["Author-email"])
self.glade.get_widget("label_plugin_homepage").set_text(plugin_info["Home-page"])
self.glade.get_widget("label_plugin_details").set_text(plugin_info["Description"])
def _on_button_plugin_install_clicked(self, widget):
log.debug("_on_button_plugin_install_clicked")
chooser = gtk.FileChooserDialog(_("Select the Plugin"),
self.pref_dialog,
gtk.FILE_CHOOSER_ACTION_OPEN,
buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN,
gtk.RESPONSE_OK))
chooser.set_transient_for(self.pref_dialog)
chooser.set_select_multiple(False)
chooser.set_property("skip-taskbar-hint", True)
file_filter = gtk.FileFilter()
file_filter.set_name(_("Plugin Eggs"))
file_filter.add_pattern("*." + "egg")
chooser.add_filter(file_filter)
# Run the dialog
response = chooser.run()
if response == gtk.RESPONSE_OK:
filepath = chooser.get_filename()
else:
chooser.destroy()
return
import shutil
import os.path
filename = os.path.split(filepath)[1]
shutil.copyfile(
filepath,
os.path.join(deluge.configmanager.get_config_dir(), "plugins", filename))
component.get("PluginManager").scan_for_plugins()
if not client.is_localhost():
# We need to send this plugin to the daemon
client.core.upload_plugin(
filename,
xmlrpclib.Binary(open(filepath, "rb").read()))
client.core.rescan_plugins()
chooser.destroy()
# We need to re-show the preferences dialog to show the new plugins
self.show()
def _on_button_rescan_plugins_clicked(self, widget):
component.get("PluginManager").scan_for_plugins()
client.core.rescan_plugins()
self.show()