Compare commits

...

8 Commits

Author SHA1 Message Date
Marcos Pinto
ea83adefcc use system setting for toolbar text/icon style 2007-11-25 01:51:00 +00:00
Marcos Pinto
e9c28bdf13 cleanup trackers replace 2007-11-25 01:11:19 +00:00
Marcos Pinto
3c9a88f897 dont die if plugin in prefs.state is not found on the filesystem 2007-11-24 22:46:43 +00:00
Marcos Pinto
db8e4f325e fix add torrent in webui 2007-11-24 20:39:55 +00:00
Marcos Pinto
659411bab9 skip taskbar fix for win 2007-11-24 19:54:00 +00:00
Marcos Pinto
95acdf4475 language files sync 2007-11-24 19:30:42 +00:00
Marcos Pinto
0c094b95fa asio fix for win32 2007-11-24 18:39:00 +00:00
Marcos Pinto
8730830470 tag 0.5.7rc1 2007-11-24 16:57:53 +00:00
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 * 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

View File

@ -12,6 +12,12 @@
<property name="visible">True</property> <property name="visible">True</property>
<property name="n_rows">4</property> <property name="n_rows">4</property>
<property name="n_columns">3</property> <property name="n_columns">3</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child> <child>
<widget class="GtkVPaned" id="vpaned1"> <widget class="GtkVPaned" id="vpaned1">
<property name="visible">True</property> <property name="visible">True</property>
@ -1119,34 +1125,6 @@
<property name="y_options"></property> <property name="y_options"></property>
</packing> </packing>
</child> </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> <child>
<widget class="GtkToolbar" id="tb_left"> <widget class="GtkToolbar" id="tb_left">
<property name="visible">True</property> <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), system_category = ASIO_WIN_OR_POSIX(0, 0),
/// Error codes from NetDB functions. /// 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. /// 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. /// Miscellaneous error codes.
misc_category = ASIO_WIN_OR_POSIX(3, 3), misc_category = ASIO_WIN_OR_POSIX(3, 3),

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

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

View File

@ -1,5 +1,6 @@
_('# Of Files') _('# Of Files')
_('About') _('About')
_('Add')
_('Add Torrent') _('Add Torrent')
_('Add torrent') _('Add torrent')
_('Apply') _('Apply')
@ -13,6 +14,7 @@ _('Delete .torrent file')
_('Delete downloaded files.') _('Delete downloaded files.')
_('Details') _('Details')
_('Disable') _('Disable')
_('Down')
_('Down Speed') _('Down Speed')
_('Download') _('Download')
_('Downloaded') _('Downloaded')
@ -27,19 +29,20 @@ _('Next Announce')
_('Off') _('Off')
_('Password') _('Password')
_('Password is invalid,try again') _('Password is invalid,try again')
_('Pause')
_('Pause all') _('Pause all')
_('Peers') _('Peers')
_('Pieces') _('Pieces')
_('Progress') _('Progress')
_('Queue Down') _('Queue Down')
_('Queue Position')
_('Queue Up') _('Queue Up')
_('Queue pos:')
_('Ratio') _('Ratio')
_('Reannounce') _('Reannounce')
_('Refresh page every:') _('Refresh page every:')
_('Remove') _('Remove')
_('Remove %s ') _('Remove torrent')
_('Remove %s?') _('Resume')
_('Resume all') _('Resume all')
_('Seeders') _('Seeders')
_('Set') _('Set')
@ -47,11 +50,13 @@ _('Set Timeout')
_('Share Ratio') _('Share Ratio')
_('Size') _('Size')
_('Speed') _('Speed')
_('Start')
_('Submit') _('Submit')
_('Torrent list') _('Torrent list')
_('Total Size') _('Total Size')
_('Tracker') _('Tracker')
_('Tracker Status') _('Tracker Status')
_('Up')
_('Up Speed') _('Up Speed')
_('Upload') _('Upload')
_('Upload torrent') _('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 @@
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 {
} }
/* Hides from IE-mac \*/ * html .clearfix {height: 1%;} .clearfix {display: block;} /* End hide from IE-mac */ 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 */

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;
} }
/* Hides from IE-mac \*/ * html .clearfix {height: 1%;} .clearfix {display: block;} /* End hide from IE-mac */ #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 */

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 or 'unknown'
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'] 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 #/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']

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 = 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())
@ -514,7 +516,7 @@ def show_file_open_dialog(parent, title=None):
chooser.set_select_multiple(True) chooser.set_select_multiple(True)
if not common.windows_check(): if not common.windows_check():
chooser.set_icon(common.get_logo(32)) chooser.set_icon(common.get_logo(32))
chooser.set_property("skip-taskbar-hint", True) chooser.set_property("skip-taskbar-hint", True)
response = chooser.run() response = chooser.run()
if response == gtk.RESPONSE_OK: 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)) buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK))
if not common.windows_check(): if not common.windows_check():
chooser.set_icon(common.get_logo(32)) chooser.set_icon(common.get_logo(32))
chooser.set_property("skip-taskbar-hint", True) chooser.set_property("skip-taskbar-hint", True)
config = pref.Preferences() config = pref.Preferences()
chooser.set_current_folder(config.get("choose_directory_dialog_path")) chooser.set_current_folder(config.get("choose_directory_dialog_path"))
if chooser.run() == gtk.RESPONSE_OK: 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"), 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)
@ -168,23 +168,9 @@ class DelugeGTK:
if self.manager.unique_IDs[unique_ID].uploaded_memory: if self.manager.unique_IDs[unique_ID].uploaded_memory:
self.manager.unique_IDs[unique_ID].initial_uploaded_memory = \ self.manager.unique_IDs[unique_ID].initial_uploaded_memory = \
self.manager.unique_IDs[unique_ID].uploaded_memory self.manager.unique_IDs[unique_ID].uploaded_memory
try: if self.manager.unique_IDs[unique_ID].trackers_changed:
if self.manager.unique_IDs[unique_ID].trackers_changed: self.manager.replace_trackers(unique_ID, \
try: self.manager.unique_IDs[unique_ID].trackers)
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
except AttributeError: except AttributeError:
pass pass
@ -820,9 +806,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 +923,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 +949,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 +1129,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 +1347,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 +1371,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 +1501,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

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

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,