tag 0.5.7rc1

This commit is contained in:
Marcos Pinto 2007-11-24 16:57:53 +00:00
parent 74f739a693
commit 8730830470
91 changed files with 58060 additions and 28656 deletions

View File

@ -5,6 +5,10 @@ Deluge 0.5.7 (xx November 2007)
* Blocklist plugin will now display errors, instead of just crashing on a bad * Blocklist plugin will now display errors, instead of just crashing on a bad
list or wrong type list or wrong type
* Add torrent in paused state option * Add torrent in paused state option
* Add advanced progress bar
* Fix bug in merging trackers
* Various updates to WebUI, including https support and advanced template by vonck7
* Add maximum connection attempts per second preference
* Fix bug where loaded plugins were forgotten if Deluge crashed * Fix bug where loaded plugins were forgotten if Deluge crashed
* Fix ratio bugs (hopefully for the last time) * Fix ratio bugs (hopefully for the last time)
* Add preference to only show file selection popup if torrent has multiple files * Add preference to only show file selection popup if torrent has multiple files
@ -18,6 +22,9 @@ Deluge 0.5.7 (xx November 2007)
* Add preference for the location of torrent files * Add preference for the location of torrent files
* Add autoload folder * Add autoload folder
* Copy translator credits from Launchpad to our about->credits * Copy translator credits from Launchpad to our about->credits
* Differentiate between queued and paused torrents. Able to pause queued
torrents - patch by yobbobandana
* Show error when writing/permission problems occur
Deluge 0.5.6.2 (31 October 2007) Deluge 0.5.6.2 (31 October 2007)
* Set default piece size to 256-KiB in TorrentCreator plugin and add 2048KiB * Set default piece size to 256-KiB in TorrentCreator plugin and add 2048KiB

1
README
View File

@ -35,6 +35,7 @@ python-all version >= 2.4
python-dbus python-dbus
python-gtk2 version >= 2.9 python-gtk2 version >= 2.9
python-notify python-notify
python-pyopenssl
librsvg2-common librsvg2-common
python-xdg python-xdg
python-support python-support

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -473,7 +473,7 @@ namespace libtorrent
// we might need more than one listen socket // we might need more than one listen socket
std::list<listen_socket_t> m_listen_sockets; std::list<listen_socket_t> m_listen_sockets;
listen_socket_t setup_listener(tcp::endpoint ep, int retries); listen_socket_t setup_listener(tcp::endpoint ep, int retries, bool v6_only = false);
// the settings for the client // the settings for the client
session_settings m_settings; session_settings m_settings;

View File

@ -171,6 +171,21 @@ namespace libtorrent
return Endpoint(addr, port); return Endpoint(addr, port);
} }
} }
struct v6only
{
v6only(bool enable): m_value(enable) {}
template<class Protocol>
int level(Protocol const&) const { return IPPROTO_IPV6; }
template<class Protocol>
int name(Protocol const&) const { return IPV6_V6ONLY; }
template<class Protocol>
int const* data(Protocol const&) const { return &m_value; }
template<class Protocol>
size_t size(Protocol const&) const { return sizeof(m_value); }
int m_value;
};
} }
#endif // TORRENT_SOCKET_HPP_INCLUDED #endif // TORRENT_SOCKET_HPP_INCLUDED

View File

@ -814,13 +814,15 @@ namespace detail
return m_ipv6_interface; return m_ipv6_interface;
} }
session_impl::listen_socket_t session_impl::setup_listener(tcp::endpoint ep, int retries) session_impl::listen_socket_t session_impl::setup_listener(tcp::endpoint ep
, int retries, bool v6_only)
{ {
asio::error_code ec; asio::error_code ec;
listen_socket_t s; listen_socket_t s;
s.sock.reset(new socket_acceptor(m_io_service)); s.sock.reset(new socket_acceptor(m_io_service));
s.sock->open(ep.protocol(), ec); s.sock->open(ep.protocol(), ec);
s.sock->set_option(socket_acceptor::reuse_address(true), ec); s.sock->set_option(socket_acceptor::reuse_address(true), ec);
if (ep.protocol() == tcp::v6()) s.sock->set_option(v6only(v6_only), ec);
s.sock->bind(ep, ec); s.sock->bind(ep, ec);
while (ec && retries > 0) while (ec && retries > 0)
{ {
@ -913,7 +915,7 @@ namespace detail
s = setup_listener( s = setup_listener(
tcp::endpoint(address_v6::any(), m_listen_interface.port()) tcp::endpoint(address_v6::any(), m_listen_interface.port())
, m_listen_port_retries); , m_listen_port_retries, true);
if (s.sock) if (s.sock)
{ {
@ -2279,6 +2281,8 @@ namespace detail
INVARIANT_CHECK; INVARIANT_CHECK;
if (m_lsd) return;
m_lsd = new lsd(m_io_service m_lsd = new lsd(m_io_service
, m_listen_interface.address() , m_listen_interface.address()
, bind(&session_impl::on_lsd_peer, this, _1, _2)); , bind(&session_impl::on_lsd_peer, this, _1, _2));
@ -2290,6 +2294,8 @@ namespace detail
INVARIANT_CHECK; INVARIANT_CHECK;
if (m_natpmp) return;
m_natpmp = new natpmp(m_io_service m_natpmp = new natpmp(m_io_service
, m_listen_interface.address() , m_listen_interface.address()
, bind(&session_impl::on_port_mapping , bind(&session_impl::on_port_mapping
@ -2308,6 +2314,8 @@ namespace detail
INVARIANT_CHECK; INVARIANT_CHECK;
if (m_upnp) return;
m_upnp = new upnp(m_io_service, m_half_open m_upnp = new upnp(m_io_service, m_half_open
, m_listen_interface.address() , m_listen_interface.address()
, m_settings.user_agent , m_settings.user_agent

View File

@ -96,12 +96,7 @@ class movetorrentMenu:
if path: if path:
self.paused_or_not = {} self.paused_or_not = {}
for unique_id in unique_ids: for unique_id in unique_ids:
self.paused_or_not[unique_id] = self.core.is_user_paused(unique_id)
if not self.paused_or_not[unique_id]:
self.core.set_user_pause(unique_id, True, enforce_queue=False)
self.core.move_storage(unique_id, path) self.core.move_storage(unique_id, path)
if not self.paused_or_not[unique_id]:
self.core.set_user_pause(unique_id, False, enforce_queue=False)
def configure(self, window): def configure(self, window):
import os.path import os.path

View File

@ -63,7 +63,7 @@ class plugin_Search:
### Note: All other plugins should use self.interface.toolbar ### Note: All other plugins should use self.interface.toolbar
### when adding items to the toolbar ### when adding items to the toolbar
self.se = '' self.se = ''
self.toolbar = self.interface.wtree.get_widget("tb_right") self.toolbar = self.interface.wtree.get_widget("tb_left")
self.engines = deluge.pref.Preferences(self.conf_file, False) self.engines = deluge.pref.Preferences(self.conf_file, False)
self.search_entry = gtk.Entry() self.search_entry = gtk.Entry()
self.search_entry.connect("activate", self.torrent_search) self.search_entry.connect("activate", self.torrent_search)

View File

@ -37,7 +37,9 @@ Firefox greasemonkey script: http://userscripts.org/scripts/show/12639
Remotely add a file: "curl -F torrent=@./test1.torrent -F pwd=deluge http://localhost:8112/remote/torrent/add" Remotely add a file: "curl -F torrent=@./test1.torrent -F pwd=deluge http://localhost:8112/remote/torrent/add"
There is support for multiple templates, but just one is included. Advanced template is only tested on firefox and garanteed not to work in IE6
ssl keys are located in WebUi/ssl/
Other contributors: Other contributors:
*somedude : template enhancements. *somedude : template enhancements.
@ -203,11 +205,8 @@ class ConfigDialog(gtk.Dialog):
gtk.combo_box_new_text()) gtk.combo_box_new_text())
self.cache_templates = self.add_widget(_('Cache Templates'), self.cache_templates = self.add_widget(_('Cache Templates'),
gtk.CheckButton()) gtk.CheckButton())
""" self.use_https = self.add_widget(_('https://'),
temporary disable for 0.5.7
self.use_https = self.add_widget(_('Use https://'),
gtk.CheckButton()) gtk.CheckButton())
"""
#self.share_downloads = self.add_widget(_('Share Download Directory'), #self.share_downloads = self.add_widget(_('Share Download Directory'),
# gtk.CheckButton()) # gtk.CheckButton())
@ -236,7 +235,7 @@ class ConfigDialog(gtk.Dialog):
# bool(self.config.get("share_downloads"))) # bool(self.config.get("share_downloads")))
self.cache_templates.set_active(self.config.get("cache_templates")) self.cache_templates.set_active(self.config.get("cache_templates"))
"""0.5.7.. self.use_https.set_active(self.config.get("use_https"))""" self.use_https.set_active(self.config.get("use_https"))
self.vbox.pack_start(self.vb, True, True, 0) self.vbox.pack_start(self.vb, True, True, 0)
self.vb.show_all() self.vb.show_all()
@ -272,7 +271,7 @@ class ConfigDialog(gtk.Dialog):
self.config.set("template", self.template.get_active_text()) self.config.set("template", self.template.get_active_text())
self.config.set("button_style", self.button_style.get_active()) self.config.set("button_style", self.button_style.get_active())
self.config.set("cache_templates", self.cache_templates.get_active()) self.config.set("cache_templates", self.cache_templates.get_active())
#0.5.7.. self.config.set("use_https", self.use_https.get_active()) self.config.set("use_https", self.use_https.get_active())
#self.config.set("share_downloads", self.share_downloads.get_active()) #self.config.set("share_downloads", self.share_downloads.get_active())
self.config.save(self.plugin.config_file) self.config.save(self.plugin.config_file)
self.plugin.start_server() #restarts server self.plugin.start_server() #restarts server

View File

@ -50,7 +50,7 @@ urls = (
"/torrent/stop/(.*)", "torrent_stop", "/torrent/stop/(.*)", "torrent_stop",
"/torrent/start/(.*)", "torrent_start", "/torrent/start/(.*)", "torrent_start",
"/torrent/reannounce/(.*)", "torrent_reannounce", "/torrent/reannounce/(.*)", "torrent_reannounce",
"/torrent/add", "torrent_add", "/torrent/add(.*)", "torrent_add",
"/torrent/delete/(.*)", "torrent_delete", "/torrent/delete/(.*)", "torrent_delete",
"/torrent/queue/up/(.*)", "torrent_queue_up", "/torrent/queue/up/(.*)", "torrent_queue_up",
"/torrent/queue/down/(.*)", "torrent_queue_down", "/torrent/queue/down/(.*)", "torrent_queue_down",
@ -98,21 +98,36 @@ class index:
@deluge_page @deluge_page
@auto_refreshed @auto_refreshed
def GET(self, name): def GET(self, name):
vars = web.input(sort=None, order=None) vars = web.input(sort=None, order=None ,filter=None , category=None)
status_rows = [get_torrent_status(torrent_id) torrent_list = [get_torrent_status(torrent_id)
for torrent_id in ws.proxy.get_session_state()] for torrent_id in ws.proxy.get_session_state()]
all_torrents = torrent_list[:]
#filter-state
if vars.filter:
torrent_list = filter_torrent_state(torrent_list, vars.filter)
setcookie("filter", vars.filter)
else:
setcookie("filter", "")
#filter-cat
if vars.category:
torrent_list = [t for t in torrent_list if t.category == vars.category]
setcookie("category", vars.category)
else:
setcookie("category", "")
#sorting: #sorting:
if vars.sort: if vars.sort:
status_rows.sort(key=attrgetter(vars.sort)) torrent_list.sort(key=attrgetter(vars.sort))
if vars.order == 'up': if vars.order == 'up':
status_rows = reversed(status_rows) torrent_list = reversed(torrent_list)
setcookie("order", vars.order) setcookie("order", vars.order)
setcookie("sort", vars.sort) setcookie("sort", vars.sort)
return ws.render.index(status_rows) return ws.render.index(torrent_list, all_torrents)
class torrent_info: class torrent_info:
@deluge_page @deluge_page
@ -213,14 +228,24 @@ class torrent_delete:
class torrent_queue_up: class torrent_queue_up:
@check_session @check_session
def POST(self, name): def POST(self, name):
for torrent_id in sorted(name.split(',')): #a bit too verbose..
torrent_ids = name.split(',')
torrents = [get_torrent_status(id) for id in torrent_ids]
torrents.sort(lambda x, y : x.queue_pos - y.queue_pos)
torrent_ids = [t.id for t in torrents]
for torrent_id in torrent_ids:
ws.proxy.queue_up(torrent_id) ws.proxy.queue_up(torrent_id)
do_redirect() do_redirect()
class torrent_queue_down: class torrent_queue_down:
@check_session @check_session
def POST(self, name): def POST(self, name):
for torrent_id in reversed(sorted(name.split(','))): #a bit too verbose..
torrent_ids = name.split(',')
torrents = [get_torrent_status(id) for id in torrent_ids]
torrents.sort(lambda x, y : x.queue_pos - y.queue_pos)
torrent_ids = [t.id for t in torrents]
for torrent_id in reversed(torrent_ids):
ws.proxy.queue_down(torrent_id) ws.proxy.queue_down(torrent_id)
do_redirect() do_redirect()

View File

@ -1 +1 @@
143 155

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEA1sPXr1O6l2J9NAEvEYQ/JFDSVcJHh9YxP7kPdjsu7k9Ih845
BHMX52A3Ypbe5MHe2bCj/8dRYCixRdF1KUTAKXdzc7mw9prgf3sS3RvmfcRsln6u
x7XRg7YprZJ46hFmcHiUPRgtTFLuFO2YWBnqxu/caTtAxx3PdoK6LDVnuVjHYofC
8uD4A9k6yL/jj3Yrkf8WYQqJ6pJcMAz/2c8ZXlBuiUCb9j5xKTzYoJaiUkKN2YrA
hoxRxfI7Zc7MH2yWw8/fTZJbGXo8nrfek7coSE7yQS1M6ciwkYk5VO2mBVJBJgAT
QUR/jGfLzEqNKXghQ564v9wmuFmUMd99a0tkVwIDAQABAoIBACID6sluLYOEqefu
uBHCLG4IDwheOQ4esrYxDW3gedJs5EP+ObGmuQaAisUmuC7rNeysuYzteMoOJ+Wz
AyeCKB1pOfP+WTT12tDWIWq73InW7ov3jJ89AO4nj/pZ1KTeFKeDsZbrmWEZUXQn
HZX2pOTVYMeaBuyCoDVZBzuxSbhlON4wS6ClMhem+eBOxg351CDTZa2cbq7Ffcos
VP7LY2ORQYNDTQSLguV/dJrFSotB8Eoz2xIpg5XR7msp6lzPzyAd+Aoz/T1lYxCY
IFZCJYKnIpgoYQvmtUlhQrdD8P0J4Kth7I8NgkWvXCKazQjhpUm+wojLKD0G7Kcz
9znIV+ECgYEA+qfp1C8jWbaAn1yAeORUA9aB6aGIURfOpZjnCvtMWM0Nu0nAJYDv
X7L5GRa1ulfKhfUG1Jv/ynMKXYuBUDhyccYLpP7BHpd29Arr7YAgb52KaD1PoKNa
Z45c61dj4sFoCmJEbDoL21UGb0LX3mc4XzPzwWs8AKfLW4aZh1NwCisCgYEA21gJ
Hy3egBgMT9+nVjqsgtIXgJOnzQRhvRwT7IFf392ZyFi8iM+pDUsx1yj0zSG4XNPw
NY8VtZuTBUlG73RKcrrz31jhCMfLCnoRkQeweZv0QWzbLU3V8DleUYdjFc/t0me5
4NBR9lBlwYHgyU3GQ814vum+m0IAH0Ng1UxAVIUCgYAFOHwZTEYLN07kgtO2MOND
FTOtfwzMy5clQdMGGofTjanMjdOvtEjIEH05tYxhbjSsp5bV1M32FIFRw3cVCafw
kLRrYlb5YSQ8HwIc9z81s+1PEH/ZE63tXDy5Nh/BeE/Hb5aHPopCrjmtFZJTcojt
CrL4A1jDlrsYk+wcsnMx8wKBgEhJJQhvd2pDgps4G8+hGoUqc7Bd+OjpzsQh4rcI
k+4U+7847zkvJolJBK3hw3tu53FAL2OXOhJVqQgO9B+p9XcGAaTTh6X7IgDb5bok
DJanPMHq+/hcNGssnNbFhXQEyF2U7X8XaEuCh2ZURR5SUUq7BlX0dmp4P84NyHXC
4Vh5AoGAZYWkXxQUGzVm+H3fPpmETWGRNFDTimzi+6N+/uHkqkiDa3LGSnabmKh+
voKm//DUjEVGlAZ3CGOjO/5SlZc/zjkgh1vg7KOU4x7DqVOuZjom5Tx3ZI4xVVVt
tVtvK0qjzUTVcwAQALN/PNak+gs9534e954rmA9kmc3xBe4ho9M=
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDlzCCAn+gAwIBAgIJAPnW/GEzRy8xMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNV
BAYTAkFVMRUwEwYDVQQIEwxUaGUgSW50ZXJuZXQxFTATBgNVBAoTDERlbHVnZSBX
ZWJ1aTAeFw0wNzExMjQxMDAzNDRaFw0wODExMjMxMDAzNDRaMDsxCzAJBgNVBAYT
AkFVMRUwEwYDVQQIEwxUaGUgSW50ZXJuZXQxFTATBgNVBAoTDERlbHVnZSBXZWJ1
aTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANbD169TupdifTQBLxGE
PyRQ0lXCR4fWMT+5D3Y7Lu5PSIfOOQRzF+dgN2KW3uTB3tmwo//HUWAosUXRdSlE
wCl3c3O5sPaa4H97Et0b5n3EbJZ+rse10YO2Ka2SeOoRZnB4lD0YLUxS7hTtmFgZ
6sbv3Gk7QMcdz3aCuiw1Z7lYx2KHwvLg+APZOsi/4492K5H/FmEKieqSXDAM/9nP
GV5QbolAm/Y+cSk82KCWolJCjdmKwIaMUcXyO2XOzB9slsPP302SWxl6PJ633pO3
KEhO8kEtTOnIsJGJOVTtpgVSQSYAE0FEf4xny8xKjSl4IUOeuL/cJrhZlDHffWtL
ZFcCAwEAAaOBnTCBmjAdBgNVHQ4EFgQU1BbX1/4WtAKRKmWI1gqryIoj7BQwawYD
VR0jBGQwYoAU1BbX1/4WtAKRKmWI1gqryIoj7BShP6Q9MDsxCzAJBgNVBAYTAkFV
MRUwEwYDVQQIEwxUaGUgSW50ZXJuZXQxFTATBgNVBAoTDERlbHVnZSBXZWJ1aYIJ
APnW/GEzRy8xMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAEoiSz5x
hRCplxUG34g3F5yJe0QboqzJ/XmECfO80a980C/WVeivM2Kb1uafsKNp+WK7wD8g
mei+todYXG+fD8WmG41LG87Xi2Xe4SlAcemEpGcC5F1bpCdvqnVAWFnqoF88FOHx
NDlrq5H5lhMH9wVrX9qJvxL+StaDJ0sFk4kMGWEN+bdSYfFdBQzF903nPtm+PlvO
1Uo6gCuRTMYM5J1DC/GpNpo/Fzrkgm8mMf1MYy3rljiNgMt2rnxhtwi6jugwyMui
id6Of6gYAtvhi7kmaUpdI5PHO35dqRK7pHXH+YXaulosCPw/+bSRptFTykeEMrBj
CzotqJ+74MwXZyM=
-----END CERTIFICATE-----

Binary file not shown.

After

Width:  |  Height:  |  Size: 498 B

View File

@ -4,7 +4,10 @@
div.progress_bar_outer { /*used in table-view*/ div.progress_bar_outer { /*used in table-view*/
width:150px; width:150px;
} }
td.progress_bar { white-space: nowrap; } td.info_label { font-weight: bold; } td { font-size: 10pt; color: #d1dae5; white-space: nowrap; } tr { font-size: 10pt; color: #d1dae5; } td.progress_bar { white-space: nowrap; } td.info_label { font-weight: bold; } td { font-size: 10pt; color: #d1dae5; white-space: nowrap; } tr {
font-size: 10pt;
color: #d1dae5;
}
div.panel { div.panel {
padding:10px; padding:10px;
@ -55,9 +58,6 @@ tr.torrent_table_selected {
background-color:#900; background-color:#900;
} }
th.torrent_table:hover {
background-color:#68a;
}
img.button { img.button {
margin-bottom:0px; margin-bottom:0px;
@ -71,4 +71,21 @@ body.inner {
} }
form.pause_resume {
margin:0;
padding:0;
border:0;
}
th {
background: #1f3044;
font-size: 14px;
border: 0px;
white-space: nowrap;
}
#torrent_table {
border: #2a425c 1px solid;
}
/* Hides from IE-mac \*/ * html .clearfix {height: 1%;} .clearfix {display: block;} /* End hide from IE-mac */ /* Hides from IE-mac \*/ * html .clearfix {height: 1%;} .clearfix {display: block;} /* End hide from IE-mac */

View File

@ -1,14 +1,49 @@
$def with (torrent_list) $def with (torrent_list, all_torrents)
$:render.header(_('Torrent list')) $:render.header(_('Torrent list'))
<div class="panel" id="toolbar">
<a href='/torrent/add' >[Add]</a> <a class='toolbar_btn' href="#"
<a href='#' onclick=' toolbar_post("/torrent/queue/up/")'>[Up]</a> onclick='toolbar_get("/torrent/add/")'
<a href='#' onclick=' toolbar_post("/torrent/queue/down/")'>[Down]</a> title='$_("Add")'><img class='toolbar_btn'
<a href='#' onclick=' toolbar_get("/torrent/delete/")'>[Delete]</a> src='/static/images/tango/list-add.png'></a>
<a href='#' onclick=' toolbar_get("/torrent/info/")'>[Info]</a>
<a href='#' onclick=' toolbar_post("/torrent/stop/")'>[Pause]</a> <a class='toolbar_btn' href="#"
<a href='#' onclick=' toolbar_post("/torrent/start/")'>[Start]</a> onclick='toolbar_get("/torrent/delete/")'><img class='toolbar_btn'
src='/static/images/tango/list-remove.png'
title='$_("Remove")'></a>
<a class='toolbar_btn' href="#"
onclick='toolbar_post("/torrent/stop/")'
title='$_("Pause")'><img class='toolbar_btn'
src='/static/images/tango/pause.png'
></a>
<a class='toolbar_btn' href="#"
onclick='toolbar_post("/torrent/start/")'
title='$_("Start")'><img class='toolbar_btn'
src='/static/images/tango/start.png'></a>
<a class='toolbar_btn' href="#"
onclick='toolbar_post("/torrent/queue/up/")'
title='$_("Up")'><img class='toolbar_btn'
src='/static/images/tango/queue-up.png'></a>
<a class='toolbar_btn' href="#"
onclick='toolbar_post("/torrent/queue/down/")'
title='$_("Down")'><img class='toolbar_btn'
src='/static/images/tango/queue-down.png'></a>
<a class='toolbar_btn' href="#"
onclick='toolbar_get("/torrent/info/")'
title='$_("Details")'><img class='toolbar_btn'
src='/static/images/tango/details.png'></a>
$:category_tabs(all_torrents)
</div>
<!-- <!--
@ -21,10 +56,10 @@ $#end
--> -->
<form action="/torrent/pause" method="POST">
<div id="tableContainer" class="tableContainer"> <div id="tableContainer" class="tableContainer">
<table class="torrent_list" border=1> <table class="torrent_list" border=1 id="torrent_list">
<thead class="fixedHeader"> <thead class="fixedHeader">
<tr> <tr>
$:(sort_head('calc_state_str', 'S')) $:(sort_head('calc_state_str', 'S'))
@ -45,11 +80,14 @@ $#end
$#4-space indentation is mandatory for for-loops in templetor! $#4-space indentation is mandatory for for-loops in templetor!
$for torrent in torrent_list: $for torrent in torrent_list:
<tr class="torrent_table" onclick="on_click_row(event, '$torrent.id')" id="torrent_$torrent.id"> <tr class="torrent_table" onclick="on_click_row(event, '$torrent.id')" id="torrent_$torrent.id">
<td><input type="image" <td>
src="/static/images/$(torrent.calc_state_str)16.png" <form action="/torrent/$torrent.action/$torrent.id" method="POST"
name="$torrent.action" value="$torrent.id" class="pause_resume">
onclick="state.row_js_continue = false;"> <input type="image"
</td> src="/static/images/$(torrent.calc_state_str)16.png"
name="pauseresume" value="submit" />
</form>
</td>
<td>$torrent.queue_pos</td> <td>$torrent.queue_pos</td>
<td style="width:100px; overflow:hidden;white-space: nowrap"> <td style="width:100px; overflow:hidden;white-space: nowrap">
$(crop(torrent.name, 40))</td> $(crop(torrent.name, 40))</td>
@ -63,8 +101,18 @@ $for torrent in torrent_list:
</td> </td>
<td>$torrent.num_seeds ($torrent.total_seeds)</td> <td>$torrent.num_seeds ($torrent.total_seeds)</td>
<td>$torrent.num_peers ($torrent.total_peers)</td> <td>$torrent.num_peers ($torrent.total_peers)</td>
<td>$fspeed(torrent.download_rate)</td> <td>
<td>$fspeed(torrent.upload_rate)</td> $if (torrent.download_rate):
$fspeed(torrent.download_rate)
$else:
&nbsp;
</td>
<td>
$if (torrent.upload_rate):
$fspeed(torrent.upload_rate)
$else:
&nbsp;
</td>
<td>$torrent.eta</td> <td>$torrent.eta</td>
<td>$("%.3f" % torrent.distributed_copies)</td> <td>$("%.3f" % torrent.distributed_copies)</td>
<td>$("%.3f" % torrent.ratio)</td\> <td>$("%.3f" % torrent.ratio)</td\>
@ -73,7 +121,6 @@ $for torrent in torrent_list:
</table> </table>
</div> </div>
</form>
$:part_stats() $:part_stats()
@ -84,6 +131,8 @@ $:part_stats()
</iframe> </iframe>
</div> </div>
<br />
<script language='javascript'> <script language='javascript'>

View File

@ -0,0 +1,30 @@
$def with (filter_tabs, category_tabs)
<form method="GET" id="category_form" style="display:inline;position:relative;top:-5px;padding-left:50px;>
<input type="hidden" name="sort" value="$get('sort')">
<input type="hidden" name="order" value="$get('order')">
<select name='filter' id='filter'
onchange="document.getElementById('category_form').submit()">
$for tab in filter_tabs:
<option value="$tab.filter"
$if tab.filter == get('filter'):
selected
>
$tab.title
</option>
</select>
<select name='category' id='category'
onchange="document.getElementById('category_form').submit()">
$for tab in category_tabs:
<option value="$tab.category"
$if tab.category == get('category'):
selected
>
$tab.title
</option>
</select>
</form>

View File

@ -8,7 +8,7 @@ td {font-family: Bitstream Vera;} /* STRUCTURE */ #page { min-width: 800px;
margin: 0; margin: 0;
padding:0; } #simple_logo { background:url(../../static/images/simple_logo.jpg) no-repeat; } #main { padding:0; } #simple_logo { background:url(../../static/images/simple_logo.jpg) no-repeat; } #main {
margin: 0; margin: 0;
padding:0; padding-top: 20px; color: #fff; } #main form table { border: #2a425c 1px solid; } #main form table tr { border: 0px; } #main form table tr th { background: #1f3044; font-size: 16px; border: 0px; padding:0; padding-top: 6px; color: #fff; } #main form table { border: #2a425c 1px solid; } #main form table tr { border: 0px; } #main form table tr th { background: #1f3044; font-size: 16px; border: 0px;
white-space: nowrap; } #main form table tr td{ border: 0px; color: #fff; font-size: 12px; white-space: nowrap; } #main form table tr th a { color: #8fa6c3; font-size: 16px; white-space: nowrap; } #main form table tr th a, a:active, a:visited { color: #8fa6c3; text-decoration: none; } #main form table tr th a:hover {color: #fff; text-decoration: underline;} #main form table tr td a { color: #fff; font-size: 12px; white-space: nowrap; } #main form table tr td a, a:active, a:visited { color: #fff; text-decoration: none;} #main form table tr td a:hover {color: #fff; text-decoration: underline;} #main a { color: #fff; font-size: 12px; } #main a, a:active, a:visited { color: #fff; text-decoration: none;} #main a:hover {color: #fff; text-decoration: underline;} .info { text-align: right; padding: 0 50px 0 0; color: #8fa6c3; font-size: 16px; letter-spacing: 4px; font-weight: bold; } .title { color: #dce4ee; font-size: 32px; padding: 10px 50px 0 0; text-align: right; } .title a, a:active, a:visited { color: #dce4ee; text-decoration: none;} .title a:hover {color: #fff; text-decoration: underline;} #button { border:1px solid #23344b; background: #99acc3; color: #000; white-space: nowrap; } #main form table tr td{ border: 0px; color: #fff; font-size: 12px; white-space: nowrap; } #main form table tr th a { color: #8fa6c3; font-size: 16px; white-space: nowrap; } #main form table tr th a, a:active, a:visited { color: #8fa6c3; text-decoration: none; } #main form table tr th a:hover {color: #fff; text-decoration: underline;} #main form table tr td a { color: #fff; font-size: 12px; white-space: nowrap; } #main form table tr td a, a:active, a:visited { color: #fff; text-decoration: none;} #main form table tr td a:hover {color: #fff; text-decoration: underline;} #main a { color: #fff; font-size: 12px; } #main a, a:active, a:visited { color: #fff; text-decoration: none;} #main a:hover {color: #fff; text-decoration: underline;} .info { text-align: right; padding: 0 50px 0 0; color: #8fa6c3; font-size: 16px; letter-spacing: 4px; font-weight: bold; } .title { color: #dce4ee; font-size: 32px; padding: 10px 50px 0 0; text-align: right; } .title a, a:active, a:visited { color: #dce4ee; text-decoration: none;} .title a:hover {color: #fff; text-decoration: underline;} #button { border:1px solid #23344b; background: #99acc3; color: #000;
font-family: Bitstream Vera; font-size:10px; margin-top:5px; } INPUT{ border:1px solid #23344b; background: #99acc3; color: #000; } TEXTAREA{ border:1px solid #23344b; background: #99acc3; width:480px; } .footertext a { color: #c0c0c0; text-decoration:none;} .footertext a:visited { color: #c0c0c0; text-decoration:none;} .footertext a:active { color: #c0c0c0; text-decoration:none;} .footertext a:hover {color: #fff; text-decoration: underline;} .footertext { text-align: center; padding: 60px 0 0 0; font-size: 8pt; left: -100px; font-family: Bitstream Vera; color: #fff; position: relative; } .clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } div.progress_bar{ background-color:#4573a5; /*color:blue;*/ -moz-border-radius:5px; /*ff only setting*/ } font-family: Bitstream Vera; font-size:10px; margin-top:5px; } INPUT{ border:1px solid #23344b; background: #99acc3; color: #000; } TEXTAREA{ border:1px solid #23344b; background: #99acc3; width:480px; } .footertext a { color: #c0c0c0; text-decoration:none;} .footertext a:visited { color: #c0c0c0; text-decoration:none;} .footertext a:active { color: #c0c0c0; text-decoration:none;} .footertext a:hover {color: #fff; text-decoration: underline;} .footertext { text-align: center; padding: 60px 0 0 0; font-size: 8pt; left: -100px; font-family: Bitstream Vera; color: #fff; position: relative; } .clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } div.progress_bar{ background-color:#4573a5; /*color:blue;*/ -moz-border-radius:5px; /*ff only setting*/ }
@ -92,6 +92,12 @@ body.inner {
padding:0; padding:0;
text-align:left; text-align:left;
height:20px; height:20px;
background-color:#ddd;
color:#000;
border-style:solid;
border:0;
border-top:1px;
border-color:#000;
} }
#about { #about {
@ -110,15 +116,18 @@ body.inner {
#refresh_panel { #refresh_panel {
-moz-border-radius:0px; -moz-border-radius:0px;
width:100%; width:350px;
position:fixed; position:fixed;
bottom:20px; bottom:0px;
left:0px; right:0px;
background-color:#304663; background-color:#304663;
margin: 0; margin: 0;
padding:0; padding:0;
text-align:right; text-align:right;
height:20px; height:20px;
background-color:#ddd;
color:#000;
z-index:999;
} }
#refresh_panel button { #refresh_panel button {
@ -128,9 +137,68 @@ body.inner {
position:relative; position:relative;
top:0px; top:0px;
height:20px; height:20px;
background-color:#ddd;
color:#000;
} }
#refresh_panel button:hover { #refresh_panel button:hover {
text-decoration: underline; text-decoration: underline;
} }
#category_panel {
margin-bottom:0;
padding-bottom:0;
-moz-border-radius-bottomleft:0px;
-moz-border-radius-bottomright:0px;
padding-right:32px;
}
#toolbar {
text-align:left;
margin-top:0;
padding-top:0;
margin-bottom: 30px;
-moz-border-radius-topleft:0px;
-moz-border-radius-topright:0px;
padding-top:5px;
padding-bottom:5px;
margin-bottom: 15px;
padding-left:32px;
height:16px;
}
#toolbar select{
/*border:1px solid #68a;*/
border:0;
background-color: #37506f;
color: #FFF;
}
#toolbar select:hover{
background-color:#68a;
}
a.toolbar_btn {
width:20px;
height:20px;
padding-left:3px;
padding-top:7px;
padding-right:3px;
text-decoration: none;
}
a.toolbar_btn:hover {
background-color:#68a;
-moz-border-radius:5px;
text-decoration: none;
}
form { /*all forms!*/
margin:0;
padding:0;
border:0;
}
#torrent_list {
-moz-border-radius:7px;
}
/* Hides from IE-mac \*/ * html .clearfix {height: 1%;} .clearfix {display: block;} /* End hide from IE-mac */ /* Hides from IE-mac \*/ * html .clearfix {height: 1%;} .clearfix {display: block;} /* End hide from IE-mac */

View File

@ -29,10 +29,17 @@ function on_click_row(e,id) {
function on_click_row_js(e, id) { function on_click_row_js(e, id) {
/*real onClick event*/ /*real onClick event*/
if (!e.ctrlKey) { if (!e.ctrlKey) {
deselect_rows(); deselect_all_rows();
select_row(id);
open_inner_details(id);
}
else if (state.selected_rows.indexOf(id) != -1) {
deselect_row(id);
}
else{
select_row(id);
open_inner_details(id);
} }
select_row(id);
open_inner_details(id);
} }
function select_row(id){ function select_row(id){
@ -43,19 +50,30 @@ function select_row(id){
setCookie('selected_rows',state.selected_rows); setCookie('selected_rows',state.selected_rows);
} }
} }
function deselect_rows(){
for (i in state.selected_rows) {
deselect_row(state.selected_rows[i]);
}
state.selected_rows = new Array();
}
function deselect_row(id){ function deselect_row(id){
var row = get_row(id); var row = get_row(id);
if (row) { if (row) {
row.className = 'torrent_table' row.className = 'torrent_table'
/*TODO : remove from state.selected_rows*/ /*remove from state.selected_rows*/
var idx = state.selected_rows.indexOf(id);
state.selected_rows.splice(idx,1);
setCookie('selected_rows',state.selected_rows);
} }
} }
function deselect_all_rows(){
/*unbind state.selected_rows from for..in:
there must be a better way to do this*/
var a = new Array()
for (i in state.selected_rows) {
a[a.length] = state.selected_rows[i];
}
for (i in a){
deselect_row(a[i]);
}
}
function reselect_rows(){ function reselect_rows(){
var selected_rows = getCookie('selected_rows').split(','); var selected_rows = getCookie('selected_rows').split(',');
for (i in getCookie('selected_rows')) { for (i in getCookie('selected_rows')) {

View File

@ -1,7 +1,7 @@
$def with (torrent_list) $def with (torrent_list, all_torrents)
$:render.header(_('Torrent list')) $:render.header(_('Torrent list'))
<table class="torrent_list" border=1> <table class="torrent_list" border=0 id='torrent_table'>
<tr> <tr>
$:(sort_head('calc_state_str', 'S')) $:(sort_head('calc_state_str', 'S'))
$:(sort_head('queue_pos', '#')) $:(sort_head('queue_pos', '#'))
@ -20,13 +20,10 @@ $#4-space indentation is mandatory for for-loops in templetor!
$for torrent in torrent_list: $for torrent in torrent_list:
<tr class="torrent_table" id="torrent_$torrent.id"> <tr class="torrent_table" id="torrent_$torrent.id">
<td> <td>
<form action="/torrent/$torrent.action/$torrent.id" method="POST"> <form action="/torrent/$torrent.action/$torrent.id" method="POST" class="pause_resume">
<input type="image" <input type="image"
src="/static/images/$(torrent.calc_state_str)16.png" src="/static/images/$(torrent.calc_state_str)16.png"
name="pauseresume" value="submit" /> name="pauseresume" value="submit" /></form></td>
</form>
</td>
<td>$torrent.queue_pos</td> <td>$torrent.queue_pos</td>
<td style="width:100px; overflow:hidden;white-space: nowrap"> <td style="width:100px; overflow:hidden;white-space: nowrap">
<a href="/torrent/info/$torrent.id" > <a href="/torrent/info/$torrent.id" >
@ -53,8 +50,8 @@ $for torrent in torrent_list:
<div class="panel"> <div class="panel">
$:render.part_button('GET', '/torrent/add', _('Add torrent'), 'tango/list-add.png') $:render.part_button('GET', '/torrent/add', _('Add torrent'), 'tango/list-add.png')
$:render.part_button('POST', '/pause_all', _('Pause all'), 'tango/media-playback-pause.png') $:render.part_button('POST', '/pause_all', _('Pause all'), 'tango/pause.png')
$:render.part_button('POST', '/resume_all', _('Resume all'), 'tango/media-playback-start.png') $:render.part_button('POST', '/resume_all', _('Resume all'), 'tango/start.png')
<!--$:render.part_button('POST', '/logout', _('Logout'), 'tango/system-log-out.png')--> <!--$:render.part_button('POST', '/logout', _('Logout'), 'tango/system-log-out.png')-->
</div> </div>

View File

@ -1,6 +1,6 @@
$def with (column_id, column_name, order, active_up, active_down) $def with (column_id, column_name, order, active_up, active_down)
<th class="torrent_table"> <th class="torrent_table">
<a href="/index?sort=$column_id&order=$order"> <a href="/index?sort=$column_id&order=$order&filter=$get('filter')&category=$get('category')">
$column_name\ $column_name\
$if active_up: $if active_up:
<img src="/static/images/tango/up.png" /> <img src="/static/images/tango/up.png" />

View File

@ -12,7 +12,7 @@ $else:
$:render.part_button('POST', '/torrent/stop/' + str(torrent.id), _('Pause'), 'tango/pause.png') $:render.part_button('POST', '/torrent/stop/' + str(torrent.id), _('Pause'), 'tango/pause.png')
$:render.part_button('GET', '/torrent/delete/' + str(torrent.id), _('Remove'), 'tango/user-trash.png') $:render.part_button('GET', '/torrent/delete/' + str(torrent.id), _('Remove'), 'tango/list-remove.png')
$:render.part_button('POST', '/torrent/reannounce/' + str(torrent.id), _('Reannounce'), 'tango/view-refresh.png') $:render.part_button('POST', '/torrent/reannounce/' + str(torrent.id), _('Reannounce'), 'tango/view-refresh.png')
$:render.part_button('POST', '/torrent/queue/up/' + str(torrent.id), _('Queue Up'), 'tango/queue-up.png') $:render.part_button('POST', '/torrent/queue/up/' + str(torrent.id), _('Queue Up'), 'tango/queue-up.png')

View File

@ -211,7 +211,7 @@ class TestIntegration(TestWebUiBase):
#delete all, nice use case for refactoring delete.. #delete all, nice use case for refactoring delete..
torrent_ids = ws.proxy.get_session_state() torrent_ids = ws.proxy.get_session_state()
for torrent in torrent_ids: for torrent in torrent_ids:
ws.proxy.remove_torrent(torrent, False, False) ws.proxy.remove_torrent([torrent], False, False)
torrent_ids = ws.proxy.get_session_state() torrent_ids = ws.proxy.get_session_state()
self.assertEqual(torrent_ids, []) self.assertEqual(torrent_ids, [])
@ -237,14 +237,14 @@ class TestIntegration(TestWebUiBase):
#pause all #pause all
self.assert_303('/pause_all','/index', post=1) self.assert_303('/pause_all','/index', post=1)
#pause worked? #pause worked?
pause_status = [get_status(id)["paused"] for id in ws.proxy.get_session_state()] pause_status = [get_status(id)["user_paused"] for id in ws.proxy.get_session_state()]
for paused in pause_status: for paused in pause_status:
self.assertEqual(paused, True) self.assertEqual(paused, True)
#resume all #resume all
self.assert_303('/resume_all','/index', post=1) self.assert_303('/resume_all','/index', post=1)
#resume worked? #resume worked?
pause_status = [get_status(id)["paused"] for id in ws.proxy.get_session_state()] pause_status = [get_status(id)["user_paused"] for id in ws.proxy.get_session_state()]
for paused in pause_status: for paused in pause_status:
self.assertEqual(paused,False) self.assertEqual(paused,False)
#pause again. #pause again.
@ -253,10 +253,10 @@ class TestIntegration(TestWebUiBase):
torrent_id = self.first_torrent_id torrent_id = self.first_torrent_id
#single resume. #single resume.
self.assert_303('/torrent/start/%s' % torrent_id ,'/index', post=1) self.assert_303('/torrent/start/%s' % torrent_id ,'/index', post=1)
self.assertEqual(get_status(torrent_id)["paused"] ,False) self.assertEqual(get_status(torrent_id)["user_paused"] ,False)
#single pause #single pause
self.assert_303('/torrent/stop/%s' % torrent_id,'/index', post=1) self.assert_303('/torrent/stop/%s' % torrent_id,'/index', post=1)
self.assertEqual(get_status(torrent_id)["paused"] , True) self.assertEqual(get_status(torrent_id)["user_paused"] , True)
def testQueue(self): def testQueue(self):
#find last: #find last:

View File

@ -1,5 +1,5 @@
revision-id: mvoncken@gmail.com-20070930083408-sv8mo0mi1rbjnfvk revision-id: mvoncken@gmail.com-20070930083408-sv8mo0mi1rbjnfvk
date: 2007-11-21 15:10:08 +0200 date: 2007-11-06 15:10:08 +0200
build-date: 2007-11-21 15:34:50 +0200 build-date: 2007-11-06 15:34:50 +0200
revno: 143 revno: 155
branch-nick: WebUi branch-nick: WebUi

View File

@ -42,7 +42,7 @@ import pickle
import sys import sys
from webpy022 import template from webpy022 import template
random.seed() random.seed()
path = os.path.dirname(__file__) webui_path = os.path.dirname(__file__)
ENV = 'UNKNOWN' ENV = 'UNKNOWN'
@ -68,11 +68,11 @@ class subclassed_render(object):
""" """
def __init__(self, template_dirname, cache=False): def __init__(self, template_dirname, cache=False):
self.base_template = template.render( self.base_template = template.render(
os.path.join(path, 'templates/deluge/'), os.path.join(webui_path, 'templates/deluge/'),
cache=cache) cache=cache)
self.sub_template = template.render( self.sub_template = template.render(
os.path.join(path, 'templates/%s/' % template_dirname), os.path.join(webui_path, 'templates/%s/' % template_dirname),
cache=cache) cache=cache)
def __getattr__(self, attr): def __getattr__(self, attr):

View File

@ -56,6 +56,7 @@ from operator import attrgetter
import datetime import datetime
import pickle import pickle
from md5 import md5 from md5 import md5
from urlparse import urlparse
from deluge import common from deluge import common
from webserver_common import REVNO, VERSION from webserver_common import REVNO, VERSION
@ -97,13 +98,20 @@ def do_redirect():
"""for redirects after a POST""" """for redirects after a POST"""
vars = web.input(redir = None) vars = web.input(redir = None)
ck = cookies() ck = cookies()
url_vars = {}
if vars.redir: if vars.redir:
seeother(vars.redir) seeother(vars.redir)
elif ("order" in ck and "sort" in ck): return
seeother(url("/index", sort=ck['sort'], order=ck['order'])) #todo:cleanup
else: if ("order" in ck and "sort" in ck):
seeother(url("/index")) url_vars.update({'sort':ck['sort'] ,'order':ck['order'] })
if ("filter" in ck) and ck['filter']:
url_vars['filter'] = ck['filter']
if ("category" in ck) and ck['category']:
url_vars['category'] = ck['category']
seeother(url("/index", **url_vars))
def error_page(error): def error_page(error):
web.header("Content-Type", "text/html; charset=utf-8") web.header("Content-Type", "text/html; charset=utf-8")
@ -211,6 +219,12 @@ def get_torrent_status(torrent_id):
status["id"] = torrent_id status["id"] = torrent_id
url = urlparse(status.tracker)
if hasattr(url,'hostname'):
status.category = url.hostname
else:
status.category = 'No-tracker'
#for naming the status-images #for naming the status-images
status.calc_state_str = "downloading" status.calc_state_str = "downloading"
if status.paused: if status.paused:
@ -219,7 +233,7 @@ def get_torrent_status(torrent_id):
status.calc_state_str = "seeding" status.calc_state_str = "seeding"
#action for torrent_pause #action for torrent_pause
if status.calc_state_str == "inactive": if status.user_paused:
status.action = "start" status.action = "start"
else: else:
status.action = "stop" status.action = "stop"
@ -250,9 +264,59 @@ def get_torrent_status(torrent_id):
raise Exception('Non Unicode for key:%s' % (k, )) raise Exception('Non Unicode for key:%s' % (k, ))
return status return status
def get_categories(torrent_list):
trackers = [torrent['category'] for torrent in torrent_list]
categories = {}
for tracker in trackers:
categories[tracker] = categories.get(tracker,0) + 1
return categories
def filter_torrent_state(torrent_list,filter_name):
filters = {
'downloading': lambda t: (not t.paused and not t.is_seed)
,'queued':lambda t: (t.paused and not t.user_paused)
,'paused':lambda t: (t.user_paused)
,'seeding':lambda t:(t.is_seed and not t.paused )
}
filter_func = filters[filter_name]
return [t for t in torrent_list if filter_func(t)]
#/utils #/utils
#template-defs: #template-defs:
def category_tabs(torrent_list):
categories = get_categories(torrent_list)
filter_tabs = [Storage(title='All (%s)' % len(torrent_list),
filter=None, category=None)]
#static filters
for title, filter_name in [
(_('Downloading'),'downloading') ,
(_('Queued'),'queued') ,
(_('Paused'),'paused') ,
(_('Seeding'),'seeding')
]:
title += ' (%s)' % (
len(filter_torrent_state(torrent_list, filter_name)), )
filter_tabs.append(Storage(title=title, filter=filter_name))
categories = [x for x in get_categories(torrent_list).iteritems()]
categories.sort()
#trackers:
category_tabs = []
category_tabs.append(
Storage(title=_('Trackers'),category=None))
for title,count in categories:
category = title
title += ' (%s)' % (count, )
category_tabs.append(Storage(title=title, category=category))
return ws.render.part_categories(filter_tabs, category_tabs)
def template_crop(text, end): def template_crop(text, end):
if len(text) > end: if len(text) > end:
return text[0:end - 3] + '...' return text[0:end - 3] + '...'
@ -283,6 +347,7 @@ def get_config(var):
template.Template.globals.update({ template.Template.globals.update({
'sort_head': template_sort_head, 'sort_head': template_sort_head,
'part_stats':template_part_stats, 'part_stats':template_part_stats,
'category_tabs':category_tabs,
'crop': template_crop, 'crop': template_crop,
'_': _ , #gettext/translations '_': _ , #gettext/translations
'str': str, #because % in templetor is broken. 'str': str, #because % in templetor is broken.
@ -295,7 +360,6 @@ template.Template.globals.update({
'rev': 'rev.%s' % (REVNO, ), 'rev': 'rev.%s' % (REVNO, ),
'version': VERSION, 'version': VERSION,
'getcookie':getcookie, 'getcookie':getcookie,
'js_enabled': lambda : ws.config.get('use_javascript'),
'get': lambda (var): getattr(web.input(**{var:None}), var) # unreadable :-( 'get': lambda (var): getattr(web.input(**{var:None}), var) # unreadable :-(
}) })
#/template-defs #/template-defs
@ -304,14 +368,15 @@ def create_webserver(urls, methods):
from webpy022.request import webpyfunc from webpy022.request import webpyfunc
from webpy022 import webapi from webpy022 import webapi
from gtk_cherrypy_wsgiserver import CherryPyWSGIServer from gtk_cherrypy_wsgiserver import CherryPyWSGIServer
import os
func = webapi.wsgifunc(webpyfunc(urls, methods, False)) func = webapi.wsgifunc(webpyfunc(urls, methods, False))
server_address=("0.0.0.0", int(ws.config.get('port'))) server_address=("0.0.0.0", int(ws.config.get('port')))
server = CherryPyWSGIServer(server_address, func, server_name="localhost") server = CherryPyWSGIServer(server_address, func, server_name="localhost")
if ws.config.get('use_https'): if ws.config.get('use_https'):
server.ssl_certificate = ws.config.get('ssl_certificate') server.ssl_certificate = os.path.join(ws.webui_path,'ssl/deluge.pem')
server.ssl_private_key = ws.config.get('ssl_private_key') server.ssl_private_key = os.path.join(ws.webui_path,'ssl/deluge.key')
print "http://%s:%d/" % server_address print "http://%s:%d/" % server_address
return server return server
@ -321,4 +386,5 @@ __all__ = ['deluge_page_noauth', 'deluge_page', 'remote',
'auto_refreshed', 'check_session', 'auto_refreshed', 'check_session',
'do_redirect', 'error_page','start_session','getcookie' 'do_redirect', 'error_page','start_session','getcookie'
,'setcookie','create_webserver','end_session', ,'setcookie','create_webserver','end_session',
'get_torrent_status', 'check_pwd','static_handler'] 'get_torrent_status', 'check_pwd','static_handler','get_categories'
,'template','filter_torrent_state']

1301
po/ar.po

File diff suppressed because it is too large Load Diff

1294
po/ast.po

File diff suppressed because it is too large Load Diff

1319
po/bg.po

File diff suppressed because it is too large Load Diff

2465
po/bs.po Normal file

File diff suppressed because it is too large Load Diff

2275
po/ca.po

File diff suppressed because it is too large Load Diff

1346
po/cs.po

File diff suppressed because it is too large Load Diff

1661
po/da.po

File diff suppressed because it is too large Load Diff

1426
po/de.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1343
po/el.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1294
po/eo.po

File diff suppressed because it is too large Load Diff

1382
po/es.po

File diff suppressed because it is too large Load Diff

1325
po/et.po

File diff suppressed because it is too large Load Diff

1294
po/eu.po

File diff suppressed because it is too large Load Diff

1370
po/fi.po

File diff suppressed because it is too large Load Diff

1567
po/fr.po

File diff suppressed because it is too large Load Diff

1298
po/gl.po

File diff suppressed because it is too large Load Diff

1355
po/he.po

File diff suppressed because it is too large Load Diff

2465
po/hi.po Normal file

File diff suppressed because it is too large Load Diff

1317
po/hr.po

File diff suppressed because it is too large Load Diff

1420
po/hu.po

File diff suppressed because it is too large Load Diff

1278
po/id.po

File diff suppressed because it is too large Load Diff

1310
po/is.po

File diff suppressed because it is too large Load Diff

1688
po/it.po

File diff suppressed because it is too large Load Diff

1296
po/ja.po

File diff suppressed because it is too large Load Diff

1726
po/ka.po

File diff suppressed because it is too large Load Diff

1296
po/ko.po

File diff suppressed because it is too large Load Diff

1296
po/ku.po

File diff suppressed because it is too large Load Diff

1294
po/la.po

File diff suppressed because it is too large Load Diff

1307
po/lt.po

File diff suppressed because it is too large Load Diff

1380
po/lv.po

File diff suppressed because it is too large Load Diff

2771
po/mk.po

File diff suppressed because it is too large Load Diff

1307
po/ms.po

File diff suppressed because it is too large Load Diff

1330
po/nb.po

File diff suppressed because it is too large Load Diff

2465
po/nds.po Normal file

File diff suppressed because it is too large Load Diff

1522
po/nl.po

File diff suppressed because it is too large Load Diff

1356
po/pl.po

File diff suppressed because it is too large Load Diff

1673
po/pt.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1380
po/ro.po

File diff suppressed because it is too large Load Diff

1553
po/ru.po

File diff suppressed because it is too large Load Diff

1292
po/si.po

File diff suppressed because it is too large Load Diff

1352
po/sk.po

File diff suppressed because it is too large Load Diff

1500
po/sl.po

File diff suppressed because it is too large Load Diff

1497
po/sr.po

File diff suppressed because it is too large Load Diff

1660
po/sv.po

File diff suppressed because it is too large Load Diff

1294
po/ta.po

File diff suppressed because it is too large Load Diff

1294
po/tlh.po

File diff suppressed because it is too large Load Diff

1330
po/tr.po

File diff suppressed because it is too large Load Diff

1294
po/uk.po

File diff suppressed because it is too large Load Diff

1300
po/vi.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -113,24 +113,31 @@ def start_deluge():
interface = deluge.interface.DelugeGTK() interface = deluge.interface.DelugeGTK()
interface.start(get_cmd_line_torrents()) interface.start(get_cmd_line_torrents())
bus = dbus.SessionBus() try:
dbus_objects = dbus.Interface(bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus'), 'org.freedesktop.DBus').ListNames() bus = dbus.SessionBus()
except:
if not "org.deluge_torrent.Deluge" in dbus_objects: if not deluge.common.windows_check():
print "no existing Deluge session" pid = os.fork()
if not os.path.exists(os.path.join(deluge.common.CONFIG_DIR, 'firstrun')): if not pid:
import deluge.wizard os.popen('dbus-launch deluge')
deluge.wizard.WizardGTK()
start_deluge()
else: else:
## This connects to the deluge interface dbus_objects = dbus.Interface(bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus'), 'org.freedesktop.DBus').ListNames()
print "create proxy object"
proxy = bus.get_object('org.deluge_torrent.Deluge', '/org/deluge_torrent/DelugeObject')
print "create iface"
deluge_iface = dbus.Interface(proxy, 'org.deluge_torrent.Deluge')
print "send to iface"
for filename in get_cmd_line_torrents(): if not "org.deluge_torrent.Deluge" in dbus_objects:
deluge_iface.interactive_add_torrent(filename) print "no existing Deluge session"
if not os.path.exists(os.path.join(deluge.common.CONFIG_DIR, 'firstrun')):
import deluge.wizard
deluge.wizard.WizardGTK()
start_deluge()
else:
## This connects to the deluge interface
print "create proxy object"
proxy = bus.get_object('org.deluge_torrent.Deluge', '/org/deluge_torrent/DelugeObject')
print "create iface"
deluge_iface = dbus.Interface(proxy, 'org.deluge_torrent.Deluge')
print "send to iface"
for filename in get_cmd_line_torrents():
deluge_iface.interactive_add_torrent(filename)

View File

@ -28,7 +28,7 @@
NAME = "deluge" NAME = "deluge"
FULLNAME = "Deluge BitTorrent Client" FULLNAME = "Deluge BitTorrent Client"
VERSION = "0.5.6.25" VERSION = "0.5.6.95"
AUTHOR = "Zach Tibbitts, Alon Zakai, Marcos Pinto, Andrew Resch, Alex Dedul" AUTHOR = "Zach Tibbitts, Alon Zakai, Marcos Pinto, Andrew Resch, Alex Dedul"
EMAIL = "zach@collegegeek.org, kripkensteiner@gmail.com, marcospinto@dipconsultants.com, alonzakai@gmail.com, rotmer@gmail.com" EMAIL = "zach@collegegeek.org, kripkensteiner@gmail.com, marcospinto@dipconsultants.com, alonzakai@gmail.com, rotmer@gmail.com"
DESCRIPTION = "A GTK BitTorrent client written in Python and C++" DESCRIPTION = "A GTK BitTorrent client written in Python and C++"

View File

@ -32,7 +32,7 @@ import os
import xdg.BaseDirectory import xdg.BaseDirectory
PROGRAM_NAME = "Deluge" PROGRAM_NAME = "Deluge"
PROGRAM_VERSION = "0.5.6.25" PROGRAM_VERSION = "0.5.6.95"
CLIENT_CODE = "DE" CLIENT_CODE = "DE"
CLIENT_VERSION = "".join(PROGRAM_VERSION.split('.'))+"0"*(4 - len(PROGRAM_VERSION.split('.'))) CLIENT_VERSION = "".join(PROGRAM_VERSION.split('.'))+"0"*(4 - len(PROGRAM_VERSION.split('.')))

View File

@ -70,6 +70,7 @@ DHT_FILENAME = "dht.state"
PREF_FUNCTIONS = { PREF_FUNCTIONS = {
"listen_on" : deluge_core.set_listen_on, "listen_on" : deluge_core.set_listen_on,
"max_half_open" : deluge_core.set_max_half_open, "max_half_open" : deluge_core.set_max_half_open,
"connection_speed" : deluge_core.connection_speed,
"max_connections_global" : deluge_core.set_max_connections_global, "max_connections_global" : deluge_core.set_max_connections_global,
"max_active_torrents" : None, # no need for a function, applied constantly "max_active_torrents" : None, # no need for a function, applied constantly
"max_upload_slots_global" : deluge_core.set_max_upload_slots_global, "max_upload_slots_global" : deluge_core.set_max_upload_slots_global,
@ -543,11 +544,14 @@ class Manager:
# We have enough free space, so lets resume this torrent # We have enough free space, so lets resume this torrent
self.resume(unique_ID) self.resume(unique_ID)
else: else:
nice_need = common.fsize(total_needed)
nice_free = common.fsize(avail)
import gtk import gtk
import dialogs import dialogs
gtk.gdk.threads_enter() gtk.gdk.threads_enter()
result = dialogs.show_popup_warning(None, _("You're out \ dialogs.show_popup_warning(None, _("There is not enough \
of HD space! Oops!\nWe had to pause at least one torrent")) free disk space to complete your download.") + "\n" + _("Space Needed:") + " " \
+ nice_need + "\n" + _("Available Space:") + " " + nice_free)
gtk.gdk.threads_leave() gtk.gdk.threads_leave()
print "Not enough free space to resume this torrent!" print "Not enough free space to resume this torrent!"
else: #We're using compact allocation so lets just resume else: #We're using compact allocation so lets just resume
@ -631,6 +635,13 @@ of HD space! Oops!\nWe had to pause at least one torrent"))
# seed if client crashes # seed if client crashes
self.save_fastresume_data(event['unique_ID']) self.save_fastresume_data(event['unique_ID'])
elif event['event_type'] is self.constants['EVENT_FILE_ERROR']:
import gtk
import dialogs
gtk.gdk.threads_enter()
dialogs.show_popup_warning(None, event['message'])
gtk.gdk.threads_leave()
elif event['event_type'] is self.constants['EVENT_TRACKER_ANNOUNCE']: elif event['event_type'] is self.constants['EVENT_TRACKER_ANNOUNCE']:
self.set_supp_torrent_state_val(event['unique_ID'], self.set_supp_torrent_state_val(event['unique_ID'],
"tracker_status", "tracker_status",
@ -855,7 +866,6 @@ of HD space! Oops!\nWe had to pause at least one torrent"))
torrent.save_dir, torrent.save_dir,
torrent.compact) torrent.compact)
except DelugeError, e: except DelugeError, e:
print "Error probably bad torrent"
del self.state.torrents[torrent] del self.state.torrents[torrent]
raise e raise e

View File

@ -510,6 +510,16 @@ static PyObject *torrent_set_max_half_open(PyObject *self, PyObject *args)
Py_INCREF(Py_None); return Py_None; Py_INCREF(Py_None); return Py_None;
} }
static PyObject *torrent_connection_speed(PyObject *self, PyObject *args)
{
python_long arg;
if (!PyArg_ParseTuple(args, "i", &arg))
return NULL;
M_settings->connection_speed = arg;
M_ses->set_settings(*M_settings);
Py_INCREF(Py_None); return Py_None;
}
static PyObject *torrent_set_download_rate_limit(PyObject *self, PyObject *args) static PyObject *torrent_set_download_rate_limit(PyObject *self, PyObject *args)
{ {
@ -2022,6 +2032,7 @@ static PyMethodDef deluge_core_methods[] =
{"quit", torrent_quit, METH_VARARGS, "."}, {"quit", torrent_quit, METH_VARARGS, "."},
{"save_fastresume", torrent_save_fastresume, METH_VARARGS, "."}, {"save_fastresume", torrent_save_fastresume, METH_VARARGS, "."},
{"set_max_half_open", torrent_set_max_half_open, METH_VARARGS, "."}, {"set_max_half_open", torrent_set_max_half_open, METH_VARARGS, "."},
{"connection_speed", torrent_connection_speed, METH_VARARGS, "."},
{"set_download_rate_limit", torrent_set_download_rate_limit, METH_VARARGS, "."}, {"set_download_rate_limit", torrent_set_download_rate_limit, METH_VARARGS, "."},
{"set_upload_rate_limit", torrent_set_upload_rate_limit, METH_VARARGS, "."}, {"set_upload_rate_limit", torrent_set_upload_rate_limit, METH_VARARGS, "."},
{"set_per_upload_rate_limit", torrent_set_per_upload_rate_limit, METH_VARARGS, "."}, {"set_per_upload_rate_limit", torrent_set_per_upload_rate_limit, METH_VARARGS, "."},

View File

@ -144,6 +144,7 @@ class PreferencesDlg:
self.glade.get_widget("spin_dht_proxy_port").set_value(self.preferences.get("dht_proxy_port")) self.glade.get_widget("spin_dht_proxy_port").set_value(self.preferences.get("dht_proxy_port"))
self.glade.get_widget("spin_web_proxy_port").set_value(self.preferences.get("web_proxy_port")) self.glade.get_widget("spin_web_proxy_port").set_value(self.preferences.get("web_proxy_port"))
self.glade.get_widget("spin_max_half_open").set_value(float(self.preferences.get("max_half_open"))) self.glade.get_widget("spin_max_half_open").set_value(float(self.preferences.get("max_half_open")))
self.glade.get_widget("spin_connection_speed").set_value(float(self.preferences.get("connection_speed")))
self.glade.get_widget("spin_torrents").set_value(float(self.preferences.get("max_active_torrents"))) self.glade.get_widget("spin_torrents").set_value(float(self.preferences.get("max_active_torrents")))
self.glade.get_widget("chk_seedbottom").set_active(self.preferences.get("queue_seeds_to_bottom")) self.glade.get_widget("chk_seedbottom").set_active(self.preferences.get("queue_seeds_to_bottom"))
self.glade.get_widget("chk_queue_above_completed").set_sensitive(self.preferences.get("queue_seeds_to_bottom")) self.glade.get_widget("chk_queue_above_completed").set_sensitive(self.preferences.get("queue_seeds_to_bottom"))
@ -269,6 +270,7 @@ class PreferencesDlg:
self.preferences.set("max_connections_global", int(self.glade.get_widget("spin_max_connections_global").get_value())) self.preferences.set("max_connections_global", int(self.glade.get_widget("spin_max_connections_global").get_value()))
self.preferences.set("max_connections_per_torrent", int(self.glade.get_widget("spin_max_connections_per_torrent").get_value())) self.preferences.set("max_connections_per_torrent", int(self.glade.get_widget("spin_max_connections_per_torrent").get_value()))
self.preferences.set("max_half_open", int(self.glade.get_widget("spin_max_half_open").get_value())) self.preferences.set("max_half_open", int(self.glade.get_widget("spin_max_half_open").get_value()))
self.preferences.set("connection_speed", int(self.glade.get_widget("spin_connection_speed").get_value()))
self.preferences.set("max_active_torrents", int(self.glade.get_widget("spin_torrents").get_value())) self.preferences.set("max_active_torrents", int(self.glade.get_widget("spin_torrents").get_value()))
self.preferences.set("queue_seeds_to_bottom", self.glade.get_widget("chk_seedbottom").get_active()) self.preferences.set("queue_seeds_to_bottom", self.glade.get_widget("chk_seedbottom").get_active())
self.preferences.set("enable_dht", self.glade.get_widget("chk_dht").get_active()) self.preferences.set("enable_dht", self.glade.get_widget("chk_dht").get_active())

View File

@ -63,7 +63,7 @@ class DelugeGTK:
self.wtree = gtk.glade.XML(common.get_glade_file("delugegtk.glade"), self.wtree = gtk.glade.XML(common.get_glade_file("delugegtk.glade"),
domain='deluge') domain='deluge')
self.window = self.wtree.get_widget("main_window") self.window = self.wtree.get_widget("main_window")
self.toolbar = self.wtree.get_widget("tb_middle") self.toolbar = self.wtree.get_widget("tb_left")
self.window.drag_dest_set(gtk.DEST_DEFAULT_ALL, [('text/uri-list', 0, self.window.drag_dest_set(gtk.DEST_DEFAULT_ALL, [('text/uri-list', 0,
80)], gtk.gdk.ACTION_COPY) 80)], gtk.gdk.ACTION_COPY)
self.window.connect("delete_event", self.close) self.window.connect("delete_event", self.close)
@ -820,9 +820,9 @@ window, please enter your password"))
unique_ids = self.get_selected_torrent_rows() unique_ids = self.get_selected_torrent_rows()
try: try:
for uid in unique_ids: for uid in unique_ids:
self.manager.set_user_pause(uid, True, True)
torrent_state = self.manager.get_torrent_state(uid) torrent_state = self.manager.get_torrent_state(uid)
if torrent_state["is_paused"] == 0: if torrent_state["is_paused"] == 0:
self.manager.set_user_pause(uid, True, True)
self.manager.save_fastresume_data(uid) self.manager.save_fastresume_data(uid)
self.update() self.update()
@ -937,13 +937,16 @@ window, please enter your password"))
int(self.config.get("web_proxy_port")), self.config.get( int(self.config.get("web_proxy_port")), self.config.get(
"web_proxy_type"), "web") "web_proxy_type"), "web")
def get_message_from_state(self, torrent_state): def get_message_from_state(self, unique_id, torrent_state):
state = torrent_state['state'] state = torrent_state['state']
is_paused = torrent_state['is_paused'] is_paused = torrent_state['is_paused']
progress = torrent_state['progress'] progress = torrent_state['progress']
progress = '%d%%' % int(progress * 100) progress = '%d%%' % int(progress * 100)
if is_paused: if is_paused:
message = _("Paused %s") % progress if self.manager.is_user_paused(unique_id):
message = _("Paused %s") % progress
else:
message = _("Queued %s") % progress
else: else:
try: try:
message = core.STATE_MESSAGES[state] message = core.STATE_MESSAGES[state]
@ -960,7 +963,7 @@ window, please enter your password"))
name = state['name'] name = state['name']
size = state['total_wanted'] size = state['total_wanted']
progress = float(state['progress'] * 100) progress = float(state['progress'] * 100)
message = self.get_message_from_state(state) message = self.get_message_from_state(unique_id, state)
availability = state['distributed_copies'] availability = state['distributed_copies']
share = self.manager.calc_ratio(unique_id, state) share = self.manager.calc_ratio(unique_id, state)
@ -1140,11 +1143,13 @@ window, please enter your password"))
state = self.manager.get_torrent_state(unique_id) state = self.manager.get_torrent_state(unique_id)
if previosly_paused and state['is_paused']: if previosly_paused and state['is_paused']:
# For previosly and still paused torrents update only # For previosly and still paused torrents update only
# queue pos and selected files size, all the rest # queue pos, selected files size and status message.
# columns are unchanged for them. # All the other columns are unchanged.
dgtk.update_store(self.torrent_model, itr, (1, 4), message = self.get_message_from_state(unique_id, state)
dgtk.update_store(self.torrent_model, itr, (1, 4, 6),
(state['queue_pos'], (state['queue_pos'],
state['total_wanted'])) state['total_wanted'],
message))
else: else:
tlist = self.get_torrent_state_list(unique_id, state) tlist = self.get_torrent_state_list(unique_id, state)
dgtk.update_store(self.torrent_model, itr, dgtk.update_store(self.torrent_model, itr,
@ -1356,20 +1361,23 @@ trying to add the torrent. It's possible your .torrent file is corrupted."))
if is_duplicate: if is_duplicate:
merge_dialog = dialogs.MergeDlg() merge_dialog = dialogs.MergeDlg()
if merge_dialog.show(self.window) == 1: if merge_dialog.show(self.window) == 1:
new_trackers_as_list = self.manager.dump_trackers(torrent).\ new_trackers_as_list = self.manager.dump_trackers(torrent)\
replace(' ','').splitlines(True) .splitlines()
original_trackers_as_list = self.manager.get_trackers( original_trackers_as_list = self.manager.get_trackers(
unique_id).replace(' ','').splitlines(True) unique_id).splitlines()
for index in xrange(len(new_trackers_as_list)): merged_trackers = []
if original_trackers_as_list.count( for s in original_trackers_as_list, new_trackers_as_list:
new_trackers_as_list[index]) == 0: for x in s:
original_trackers_as_list.append( merged_trackers.append(x)
new_trackers_as_list[index]) #remove duplicates
merged_trackers_as_string = ''.join([ d = {}
original_trackers_as_list[index] for \ for k in merged_trackers:
index in xrange(len(original_trackers_as_list))]) d[k] = 1
merged_trackers_as_string = ''
for x in d.keys():
merged_trackers_as_string = merged_trackers_as_string + x + '\n'
self.manager.replace_trackers(unique_id, self.manager.replace_trackers(unique_id,
merged_trackers_as_string) merged_trackers_as_string.strip())
else: else:
dialogs.show_popup_warning(self.window, _("Unknown duplicate \ dialogs.show_popup_warning(self.window, _("Unknown duplicate \
torrent error.")) torrent error."))
@ -1377,9 +1385,8 @@ torrent error."))
nice_need = common.fsize(e.needed_space) nice_need = common.fsize(e.needed_space)
nice_free = common.fsize(e.free_space) nice_free = common.fsize(e.free_space)
dialogs.show_popup_warning(self.window, _("There is not enough free\ dialogs.show_popup_warning(self.window, _("There is not enough free\
disk space to complete your download.") + "\n" + \ disk space to complete your download.") + "\n" + _("Space Needed:") + " " + \
_("Space Needed:") + " " + nice_need + "\n" + nice_need + "\n" + _("Available Space:") + " " + nice_free)
_("Available Space:") + " " + nice_free)
else: else:
self.torrent_model_append(unique_id) self.torrent_model_append(unique_id)
@ -1508,12 +1515,8 @@ want to remove all seeding torrents?")):
def toolbar_toggle(self, widget): def toolbar_toggle(self, widget):
if widget.get_active(): if widget.get_active():
self.wtree.get_widget("tb_left").show() self.wtree.get_widget("tb_left").show()
self.wtree.get_widget("tb_middle").show()
self.wtree.get_widget("tb_right").show()
else: else:
self.wtree.get_widget("tb_left").hide() self.wtree.get_widget("tb_left").hide()
self.wtree.get_widget("tb_middle").hide()
self.wtree.get_widget("tb_right").hide()
def infopane_toggle(self, widget): def infopane_toggle(self, widget):
if widget.get_active(): if widget.get_active():

View File

@ -70,6 +70,7 @@ if common.windows_check():
"listen_on" : [6881,6889], "listen_on" : [6881,6889],
"lock_tray" : False, "lock_tray" : False,
"max_half_open" : 8, "max_half_open" : 8,
"connection_speed" : -1,
"max_active_torrents" : 8, "max_active_torrents" : 8,
"max_active_torrents_tmp" : 8, "max_active_torrents_tmp" : 8,
"max_connections_global" : 200, "max_connections_global" : 200,
@ -125,7 +126,7 @@ if common.windows_check():
"use_compact_storage" : False, "use_compact_storage" : False,
"use_default_dir" : False, "use_default_dir" : False,
"use_natpmp" : False, "use_natpmp" : False,
"use_upnp" : True, "use_upnp" : False,
"use_lsd" : False, "use_lsd" : False,
"use_utpex" : True, "use_utpex" : True,
"new_releases" : True, "new_releases" : True,
@ -182,7 +183,8 @@ else:
"gui_update_interval" : 1.0, "gui_update_interval" : 1.0,
"listen_on" : [6881,6889], "listen_on" : [6881,6889],
"lock_tray" : False, "lock_tray" : False,
"max_half_open" : 8, "max_half_open" : 20,
"connection_speed" : -1,
"max_active_torrents" : 8, "max_active_torrents" : 8,
"max_active_torrents_tmp" : 8, "max_active_torrents_tmp" : 8,
"max_connections_global" : 200, "max_connections_global" : 200,
@ -238,7 +240,7 @@ else:
"use_compact_storage" : False, "use_compact_storage" : False,
"use_default_dir" : False, "use_default_dir" : False,
"use_natpmp" : False, "use_natpmp" : False,
"use_upnp" : True, "use_upnp" : False,
"use_lsd" : False, "use_lsd" : False,
"use_utpex" : True, "use_utpex" : True,
"new_releases" : True, "new_releases" : True,