Compare commits

...

8 Commits

95 changed files with 66277 additions and 38649 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
list or wrong type
* 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 ratio bugs (hopefully for the last time)
* 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 autoload folder
* 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)
* 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-gtk2 version >= 2.9
python-notify
python-pyopenssl
librsvg2-common
python-xdg
python-support

View File

@ -12,6 +12,12 @@
<property name="visible">True</property>
<property name="n_rows">4</property>
<property name="n_columns">3</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<widget class="GtkVPaned" id="vpaned1">
<property name="visible">True</property>
@ -1119,34 +1125,6 @@
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkToolbar" id="tb_right">
<property name="visible">True</property>
<property name="show_arrow">False</property>
</widget>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options"></property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
<widget class="GtkToolbar" id="tb_middle">
<property name="visible">True</property>
<property name="show_arrow">False</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
<widget class="GtkToolbar" id="tb_left">
<property name="visible">True</property>

File diff suppressed because it is too large Load Diff

View File

@ -41,10 +41,10 @@ namespace error
system_category = ASIO_WIN_OR_POSIX(0, 0),
/// Error codes from NetDB functions.
netdb_category = ASIO_WIN_OR_POSIX(_system_category, 1),
netdb_category = ASIO_WIN_OR_POSIX(system_category, 1),
/// Error codes from getaddrinfo.
addrinfo_category = ASIO_WIN_OR_POSIX(_system_category, 2),
addrinfo_category = ASIO_WIN_OR_POSIX(system_category, 2),
/// Miscellaneous error codes.
misc_category = ASIO_WIN_OR_POSIX(3, 3),

View File

@ -473,7 +473,7 @@ namespace libtorrent
// we might need more than one listen socket
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
session_settings m_settings;

View File

@ -171,6 +171,21 @@ namespace libtorrent
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

View File

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

View File

@ -96,12 +96,7 @@ class movetorrentMenu:
if path:
self.paused_or_not = {}
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)
if not self.paused_or_not[unique_id]:
self.core.set_user_pause(unique_id, False, enforce_queue=False)
def configure(self, window):
import os.path

View File

@ -63,7 +63,7 @@ class plugin_Search:
### Note: All other plugins should use self.interface.toolbar
### when adding items to the toolbar
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.search_entry = gtk.Entry()
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"
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:
*somedude : template enhancements.
@ -203,11 +205,8 @@ class ConfigDialog(gtk.Dialog):
gtk.combo_box_new_text())
self.cache_templates = self.add_widget(_('Cache Templates'),
gtk.CheckButton())
"""
temporary disable for 0.5.7
self.use_https = self.add_widget(_('Use https://'),
self.use_https = self.add_widget(_('https://'),
gtk.CheckButton())
"""
#self.share_downloads = self.add_widget(_('Share Download Directory'),
# gtk.CheckButton())
@ -236,7 +235,7 @@ class ConfigDialog(gtk.Dialog):
# bool(self.config.get("share_downloads")))
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.vb.show_all()
@ -272,7 +271,7 @@ class ConfigDialog(gtk.Dialog):
self.config.set("template", self.template.get_active_text())
self.config.set("button_style", self.button_style.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.save(self.plugin.config_file)
self.plugin.start_server() #restarts server

View File

@ -50,7 +50,7 @@ urls = (
"/torrent/stop/(.*)", "torrent_stop",
"/torrent/start/(.*)", "torrent_start",
"/torrent/reannounce/(.*)", "torrent_reannounce",
"/torrent/add", "torrent_add",
"/torrent/add(.*)", "torrent_add",
"/torrent/delete/(.*)", "torrent_delete",
"/torrent/queue/up/(.*)", "torrent_queue_up",
"/torrent/queue/down/(.*)", "torrent_queue_down",
@ -98,21 +98,36 @@ class index:
@deluge_page
@auto_refreshed
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()]
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:
if vars.sort:
status_rows.sort(key=attrgetter(vars.sort))
torrent_list.sort(key=attrgetter(vars.sort))
if vars.order == 'up':
status_rows = reversed(status_rows)
torrent_list = reversed(torrent_list)
setcookie("order", vars.order)
setcookie("sort", vars.sort)
return ws.render.index(status_rows)
return ws.render.index(torrent_list, all_torrents)
class torrent_info:
@deluge_page
@ -213,14 +228,24 @@ class torrent_delete:
class torrent_queue_up:
@check_session
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)
do_redirect()
class torrent_queue_down:
@check_session
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)
do_redirect()

View File

@ -1 +1 @@
143
155

View File

@ -1,13 +1,18 @@
from __future__ import with_statement
import os
import re
template_dir = '~/prj/WebUi/templates/deluge'
template_dir = os.path.expanduser(template_dir )
template_dirs = ['~/prj/WebUi/templates/deluge',
'~/prj/WebUi/templates/advanced']
template_dirs = [os.path.expanduser(template_dir ) for template_dir in template_dirs]
files = [os.path.join(template_dir,fname)
for fname in os.listdir(template_dir)
if fname.endswith('.html')]
files = []
for template_dir in template_dirs:
files += [os.path.join(template_dir,fname)
for fname in os.listdir(template_dir)
if fname.endswith('.html')]
all_strings = []
for filename in files:

View File

@ -1,5 +1,6 @@
_('# Of Files')
_('About')
_('Add')
_('Add Torrent')
_('Add torrent')
_('Apply')
@ -13,6 +14,7 @@ _('Delete .torrent file')
_('Delete downloaded files.')
_('Details')
_('Disable')
_('Down')
_('Down Speed')
_('Download')
_('Downloaded')
@ -27,19 +29,20 @@ _('Next Announce')
_('Off')
_('Password')
_('Password is invalid,try again')
_('Pause')
_('Pause all')
_('Peers')
_('Pieces')
_('Progress')
_('Queue Down')
_('Queue Position')
_('Queue Up')
_('Queue pos:')
_('Ratio')
_('Reannounce')
_('Refresh page every:')
_('Remove')
_('Remove %s ')
_('Remove %s?')
_('Remove torrent')
_('Resume')
_('Resume all')
_('Seeders')
_('Set')
@ -47,11 +50,13 @@ _('Set Timeout')
_('Share Ratio')
_('Size')
_('Speed')
_('Start')
_('Submit')
_('Torrent list')
_('Total Size')
_('Tracker')
_('Tracker Status')
_('Up')
_('Up Speed')
_('Upload')
_('Upload torrent')

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 @@
Theme Name: Simple
Theme URI: http://deluge-torrent.org
Description: Deluge Theme
Description: Deluge Theme
Version: 1.0
-----------------------------------------------------------
*/
@ -55,9 +58,6 @@ tr.torrent_table_selected {
#main form table tr th {
background: #1f3044;
font-size: 16px;
#main form table tr th {
background: #1f3044;
font-size: 16px;
border: 0px;
white-space: nowrap;
}
@ -71,4 +71,21 @@ body.inner {
#main form table tr th a {
color: #8fa6c3;
font-size: 16px;
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;

View File

@ -1,14 +1,49 @@
$def with (torrent_list)
$def with (torrent_list, all_torrents)
$:render.header(_('Torrent list'))
<div class="panel" id="toolbar">
<a href='/torrent/add' >[Add]</a>
<a href='#' onclick=' toolbar_post("/torrent/queue/up/")'>[Up]</a>
<a href='#' onclick=' toolbar_post("/torrent/queue/down/")'>[Down]</a>
<a href='#' onclick=' toolbar_get("/torrent/delete/")'>[Delete]</a>
<a href='#' onclick=' toolbar_get("/torrent/info/")'>[Info]</a>
<a href='#' onclick=' toolbar_post("/torrent/stop/")'>[Pause]</a>
<a href='#' onclick=' toolbar_post("/torrent/start/")'>[Start]</a>
<a class='toolbar_btn' href="#"
onclick='toolbar_get("/torrent/add/")'
title='$_("Add")'><img class='toolbar_btn'
src='/static/images/tango/list-add.png'></a>
<a class='toolbar_btn' href="#"
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">
<table class="torrent_list" border=1>
<table class="torrent_list" border=1 id="torrent_list">
<thead class="fixedHeader">
<tr>
$:(sort_head('calc_state_str', 'S'))
@ -45,11 +80,14 @@ $#end
$#4-space indentation is mandatory for for-loops in templetor!
$for torrent in torrent_list:
<tr class="torrent_table" onclick="on_click_row(event, '$torrent.id')" id="torrent_$torrent.id">
<td><input type="image"
src="/static/images/$(torrent.calc_state_str)16.png"
name="$torrent.action" value="$torrent.id"
onclick="state.row_js_continue = false;">
</td>
<td>
<form action="/torrent/$torrent.action/$torrent.id" method="POST"
class="pause_resume">
<input type="image"
src="/static/images/$(torrent.calc_state_str)16.png"
name="pauseresume" value="submit" />
</form>
</td>
<td>$torrent.queue_pos</td>
<td style="width:100px; overflow:hidden;white-space: nowrap">
$(crop(torrent.name, 40))</td>
@ -63,8 +101,18 @@ $for torrent in torrent_list:
</td>
<td>$torrent.num_seeds ($torrent.total_seeds)</td>
<td>$torrent.num_peers ($torrent.total_peers)</td>
<td>$fspeed(torrent.download_rate)</td>
<td>$fspeed(torrent.upload_rate)</td>
<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>$("%.3f" % torrent.distributed_copies)</td>
<td>$("%.3f" % torrent.ratio)</td\>
@ -73,7 +121,6 @@ $for torrent in torrent_list:
</table>
</div>
</form>
$:part_stats()
@ -84,6 +131,8 @@ $:part_stats()
</iframe>
</div>
<br />
<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;
Version: 1.0
-----------------------------------------------------------
*/
*/
@ -92,6 +92,12 @@ body.inner {
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;}
@ -110,15 +116,18 @@ body.inner {
padding: 10px 50px 0 0;
text-align: right;
}
.title {
font-size: 32px;
padding: 10px 50px 0 0;
.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;
}
@ -128,9 +137,68 @@ body.inner {
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*/
}
div.progress_bar_outer { /*used in table-view*/
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;

View File

@ -29,10 +29,17 @@ function on_click_row(e,id) {
function on_click_row_js(e, id) {
/*real onClick event*/
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){
@ -43,19 +50,30 @@ function select_row(id){
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){
var row = get_row(id);
if (row) {
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(){
var selected_rows = getCookie('selected_rows').split(',');
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'))
<table class="torrent_list" border=1>
<table class="torrent_list" border=0 id='torrent_table'>
<tr>
$:(sort_head('calc_state_str', 'S'))
$:(sort_head('queue_pos', '#'))
@ -20,13 +20,10 @@ $#4-space indentation is mandatory for for-loops in templetor!
$for torrent in torrent_list:
<tr class="torrent_table" id="torrent_$torrent.id">
<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"
src="/static/images/$(torrent.calc_state_str)16.png"
name="pauseresume" value="submit" />
</form>
</td>
name="pauseresume" value="submit" /></form></td>
<td>$torrent.queue_pos</td>
<td style="width:100px; overflow:hidden;white-space: nowrap">
<a href="/torrent/info/$torrent.id" >
@ -53,8 +50,8 @@ $for torrent in torrent_list:
<div class="panel">
$: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', '/resume_all', _('Resume all'), 'tango/media-playback-start.png')
$:render.part_button('POST', '/pause_all', _('Pause all'), 'tango/pause.png')
$:render.part_button('POST', '/resume_all', _('Resume all'), 'tango/start.png')
<!--$:render.part_button('POST', '/logout', _('Logout'), 'tango/system-log-out.png')-->
</div>

View File

@ -1,6 +1,6 @@
$def with (column_id, column_name, order, active_up, active_down)
<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\
$if active_up:
<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('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/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..
torrent_ids = ws.proxy.get_session_state()
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()
self.assertEqual(torrent_ids, [])
@ -237,14 +237,14 @@ class TestIntegration(TestWebUiBase):
#pause all
self.assert_303('/pause_all','/index', post=1)
#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:
self.assertEqual(paused, True)
#resume all
self.assert_303('/resume_all','/index', post=1)
#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:
self.assertEqual(paused,False)
#pause again.
@ -253,10 +253,10 @@ class TestIntegration(TestWebUiBase):
torrent_id = self.first_torrent_id
#single resume.
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
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):
#find last:

View File

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

View File

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

View File

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

1576
po/ar.po

File diff suppressed because it is too large Load Diff

1681
po/ast.po

File diff suppressed because it is too large Load Diff

1724
po/bg.po

File diff suppressed because it is too large Load Diff

2426
po/bs.po Normal file

File diff suppressed because it is too large Load Diff

2549
po/ca.po

File diff suppressed because it is too large Load Diff

1747
po/cs.po

File diff suppressed because it is too large Load Diff

2028
po/da.po

File diff suppressed because it is too large Load Diff

1835
po/de.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1628
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

1681
po/eo.po

File diff suppressed because it is too large Load Diff

1795
po/es.po

File diff suppressed because it is too large Load Diff

1618
po/et.po

File diff suppressed because it is too large Load Diff

1681
po/eu.po

File diff suppressed because it is too large Load Diff

1777
po/fi.po

File diff suppressed because it is too large Load Diff

1936
po/fr.po

File diff suppressed because it is too large Load Diff

1705
po/gl.po

File diff suppressed because it is too large Load Diff

1750
po/he.po

File diff suppressed because it is too large Load Diff

2426
po/hi.po Normal file

File diff suppressed because it is too large Load Diff

1724
po/hr.po

File diff suppressed because it is too large Load Diff

1816
po/hu.po

File diff suppressed because it is too large Load Diff

1717
po/id.po

File diff suppressed because it is too large Load Diff

1681
po/is.po

File diff suppressed because it is too large Load Diff

2053
po/it.po

File diff suppressed because it is too large Load Diff

1683
po/ja.po

File diff suppressed because it is too large Load Diff

2053
po/ka.po

File diff suppressed because it is too large Load Diff

1683
po/ko.po

File diff suppressed because it is too large Load Diff

1687
po/ku.po

File diff suppressed because it is too large Load Diff

1681
po/la.po

File diff suppressed because it is too large Load Diff

1706
po/lt.po

File diff suppressed because it is too large Load Diff

1775
po/lv.po

File diff suppressed because it is too large Load Diff

2752
po/mk.po

File diff suppressed because it is too large Load Diff

1758
po/ms.po

File diff suppressed because it is too large Load Diff

1812
po/nb.po

File diff suppressed because it is too large Load Diff

2426
po/nds.po Normal file

File diff suppressed because it is too large Load Diff

1965
po/nl.po

File diff suppressed because it is too large Load Diff

1775
po/pl.po

File diff suppressed because it is too large Load Diff

2095
po/pt.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1822
po/ro.po

File diff suppressed because it is too large Load Diff

1980
po/ru.po

File diff suppressed because it is too large Load Diff

1679
po/si.po

File diff suppressed because it is too large Load Diff

1763
po/sk.po

File diff suppressed because it is too large Load Diff

1933
po/sl.po

File diff suppressed because it is too large Load Diff

1875
po/sr.po

File diff suppressed because it is too large Load Diff

2051
po/sv.po

File diff suppressed because it is too large Load Diff

1681
po/ta.po

File diff suppressed because it is too large Load Diff

1681
po/tlh.po

File diff suppressed because it is too large Load Diff

1593
po/tr.po

File diff suppressed because it is too large Load Diff

1681
po/uk.po

File diff suppressed because it is too large Load Diff

1717
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.start(get_cmd_line_torrents())
bus = dbus.SessionBus()
dbus_objects = dbus.Interface(bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus'), 'org.freedesktop.DBus').ListNames()
if not "org.deluge_torrent.Deluge" in dbus_objects:
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()
try:
bus = dbus.SessionBus()
except:
if not deluge.common.windows_check():
pid = os.fork()
if not pid:
os.popen('dbus-launch 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"
dbus_objects = dbus.Interface(bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus'), 'org.freedesktop.DBus').ListNames()
for filename in get_cmd_line_torrents():
deluge_iface.interactive_add_torrent(filename)
if not "org.deluge_torrent.Deluge" in dbus_objects:
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"
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"
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++"

View File

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

View File

@ -70,6 +70,7 @@ DHT_FILENAME = "dht.state"
PREF_FUNCTIONS = {
"listen_on" : deluge_core.set_listen_on,
"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_active_torrents" : None, # no need for a function, applied constantly
"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
self.resume(unique_ID)
else:
nice_need = common.fsize(total_needed)
nice_free = common.fsize(avail)
import gtk
import dialogs
gtk.gdk.threads_enter()
result = dialogs.show_popup_warning(None, _("You're out \
of HD space! Oops!\nWe had to pause at least one torrent"))
dialogs.show_popup_warning(None, _("There is not enough \
free disk space to complete your download.") + "\n" + _("Space Needed:") + " " \
+ nice_need + "\n" + _("Available Space:") + " " + nice_free)
gtk.gdk.threads_leave()
print "Not enough free space to resume this torrent!"
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
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']:
self.set_supp_torrent_state_val(event['unique_ID'],
"tracker_status",
@ -855,7 +866,6 @@ of HD space! Oops!\nWe had to pause at least one torrent"))
torrent.save_dir,
torrent.compact)
except DelugeError, e:
print "Error probably bad torrent"
del self.state.torrents[torrent]
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;
}
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)
{
@ -2022,6 +2032,7 @@ static PyMethodDef deluge_core_methods[] =
{"quit", torrent_quit, METH_VARARGS, "."},
{"save_fastresume", torrent_save_fastresume, 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_upload_rate_limit", torrent_set_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_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_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("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"))
@ -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_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("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("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())
@ -514,7 +516,7 @@ def show_file_open_dialog(parent, title=None):
chooser.set_select_multiple(True)
if not common.windows_check():
chooser.set_icon(common.get_logo(32))
chooser.set_property("skip-taskbar-hint", True)
chooser.set_property("skip-taskbar-hint", True)
response = chooser.run()
if response == gtk.RESPONSE_OK:
@ -530,7 +532,7 @@ def show_directory_chooser_dialog(parent, title):
buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK))
if not common.windows_check():
chooser.set_icon(common.get_logo(32))
chooser.set_property("skip-taskbar-hint", True)
chooser.set_property("skip-taskbar-hint", True)
config = pref.Preferences()
chooser.set_current_folder(config.get("choose_directory_dialog_path"))
if chooser.run() == gtk.RESPONSE_OK:

View File

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

View File

@ -61,9 +61,13 @@ class PluginManager:
mod = __import__(modname, globals(), locals(), [''])
if 'deluge_init' in dir(mod):
if modname != "TorrentPieces":
print "Initialising plugin",modname
mod.deluge_init(path)
self.available_plugins[mod.plugin_name] = mod
print "Initialising plugin", modname
try:
mod.deluge_init(path)
except:
print "Cant init plugin", modname
else:
self.available_plugins[mod.plugin_name] = mod
def get_available_plugins(self):
return self.available_plugins.keys()

View File

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