Re-organize for better separation between gui and internals.

This commit is contained in:
Kai Huuhko 2013-08-05 15:31:56 +03:00
parent 681932a0ef
commit 683299edce
6 changed files with 296 additions and 258 deletions

View File

@ -1,13 +1,9 @@
#!/usr/bin/env python
import sys
try:
import elementary as elm
except ImportError:
from efl import elementary as elm
import logging
import epour.Epour as Epour
elm.init()
epour = Epour.Epour(sys.argv[1:])
elm.run()
elm.shutdown()
logging.shutdown()

View File

@ -43,7 +43,8 @@ def setup_log():
log.addHandler(ch)
fh = logging.FileHandler(os.path.join(data_dir, "epour.log"))
fh_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh_formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(fh_formatter)
fh.setLevel(logging.ERROR)
log.addHandler(fh)
@ -52,7 +53,6 @@ def setup_log():
log = setup_log()
try:
from e_dbus import DBusEcoreMainLoop
except ImportError:
@ -73,11 +73,10 @@ except dbus.exceptions.DBusException:
if dbo:
if sys.argv[1:]:
for f in sys.argv[1:]:
log.info("Sending %s via dbus" % f)
self.log.info("Sending %s via dbus" % f)
dbo.AddTorrent(f, dbus_interface="net.launchpad.epour")
sys.exit()
import mimetypes
from ConfigParser import SafeConfigParser
import cPickle
@ -87,14 +86,9 @@ import HTMLParser
import libtorrent as lt
try:
from efl import elementary as elm
from efl.ecore import Timer
except:
import elementary as elm
try:
from efl.ecore import timer_add
except:
from ecore import timer_add
from ecore import Timer
from gui import MainInterface
@ -112,105 +106,12 @@ class Epour(object):
for t in torrents:
self.session.add_torrent(t)
self.dbusname = dbus.service.BusName("net.launchpad.epour", dbus.SessionBus())
self.dbusname = dbus.service.BusName(
"net.launchpad.epour", dbus.SessionBus()
)
self.dbo = EpourDBus(self)
timer = timer_add(1.0, self.update)
def update(self):
while 1:
a = self.session.pop_alert()
if not a: break
log = logging.getLogger("epour.alert")
if isinstance(a, lt.torrent_alert):
# Torrent alerts have handle
h = a.handle
if h.is_valid():
try:
i = h.get_torrent_info()
except:
pass
ihash = str(h.info_hash())
else:
continue
if isinstance(a, lt.peer_alert):
pass
elif isinstance(a, lt.state_changed_alert) \
or isinstance(a, lt.torrent_paused_alert) \
or isinstance(a, lt.torrent_resumed_alert):
self.gui.update_icon(ihash)
elif isinstance(a, lt.metadata_received_alert):
log.debug("Metadata received.")
t_path = self.write_torrent(h)
self.session.torrents[ihash] = t_path
#elif isinstance(a, lt.tracker_alert):
# Tracker alerts also have url
elif isinstance(a, lt.torrent_finished_alert):
msg = "Torrent {} has finished downloading.".format(cgi.escape(h.name()))
log.info(msg)
self.gui.show_information(msg)
else:
log.debug(a)
elif isinstance(a, lt.listen_failed_alert):
errmsg = "Cannot listen on the configured ports."
log.error(errmsg)
self.gui.show_error(
errmsg,
"Please try other listen ports in the configuration."
)
elif isinstance(a, lt.file_error_alert):
errmsg = "File error."
log.error(errmsg)
self.gui.show_error(
errmsg,
"Error with file {}, error message {}.".format(
a.file,
a.error
)
)
elif isinstance(a, lt.file_rename_failed_alert):
errmsg = "File rename failed."
log.error(errmsg)
self.gui.show_error(
errmsg,
"Renaming a file with index {} failed, error message {}.".format(
a.index,
a.error
)
)
else:
log.debug(a)
self.gui.update_texts(self.session)
return 1
def write_torrent(self, h):
t_info = h.get_torrent_info()
ihash = str(h.info_hash())
log.debug("Writing torrent file {}".format(ihash))
md = lt.bdecode(t_info.metadata())
t = {}
t["info"] = md
t_path = os.path.join(data_dir, "{}.torrent".format(t_info.info_hash()))
with open(t_path, "wb") as f:
f.write(lt.bencode(t))
return t_path
self.gui.run()
def quit(self):
session = self.session
@ -232,13 +133,13 @@ class Epour(object):
except:
log.exception("Saving conf failed")
elm.exit()
class Session(lt.session):
def __init__(self, parent):
self.parent = parent
lt.session.__init__(self)
self.log = logging.getLogger("epour.session")
self.handles = {}
self.torrents = {}
@ -254,16 +155,49 @@ class Session(lt.session):
conf = self.conf = self.setup_conf()
self.listen_on(conf.getint("Settings", "listen_low"), conf.getint("Settings", "listen_high"))
self.listen_on(
conf.getint("Settings", "listen_low"),
conf.getint("Settings", "listen_high")
)
self.alert_manager = AlertManager(self)
self.alert_manager.callback_add(lt.metadata_received_alert, self.metadata_received)
def metadata_received(self, h):
ihash = str(h.info_hash())
self.log.debug("Metadata received.")
t_path = self.write_torrent(h)
self.torrents[ihash] = t_path
def write_torrent(self, h):
t_info = h.get_torrent_info()
ihash = str(h.info_hash())
self.log.debug("Writing torrent file {}".format(ihash))
md = lt.bdecode(t_info.metadata())
t = {}
t["info"] = md
t_path = os.path.join(
data_dir, "{}.torrent".format(ihash)
)
with open(t_path, "wb") as f:
f.write(lt.bencode(t))
return t_path
def setup_conf(self):
conf = SafeConfigParser({
"storage_path": os.path.expanduser(os.path.join("~", "Downloads")),
"storage_path": os.path.expanduser(
os.path.join("~", "Downloads")
),
"confirmations": str(False),
"delete_original": str(False),
"listen_low": str(0),
"listen_high": str(0),
})
})
conf.read(conf_path)
@ -282,7 +216,7 @@ class Session(lt.session):
state = lt.bdecode(f.read())
lt.session.load_state(self, state)
except:
log.debug("Could not load previous session state.")
self.log.debug("Could not load previous session state.")
def save_state(self):
state = lt.session.save_state(self)
@ -290,30 +224,32 @@ class Session(lt.session):
with open(os.path.join(data_dir, "session"), 'wb') as f:
f.write(lt.bencode(state))
log.debug("Session state saved.")
self.log.debug("Session state saved.")
def load_torrents(self):
torrents_path = os.path.join(data_dir, "torrents")
if not os.path.exists(torrents_path):
log.debug("No list of torrents found.")
self.log.debug("No list of torrents found.")
return
try:
pkl_file = open(torrents_path, 'rb')
except IOError:
log.warning("Could not open the list of torrents.")
self.log.warning("Could not open the list of torrents.")
else:
try:
paths = cPickle.load(pkl_file)
except EOFError:
log.exception("Opening the list of torrents failed.")
self.log.exception("Opening the list of torrents failed.")
else:
log.debug("List of torrents opened, restoring torrents.")
self.log.debug("List of torrents opened, restoring torrents.")
for k, v in paths.iteritems():
try:
self.add_torrent(v)
except:
log.exception("Restoring torrent {0} failed".format(v))
self.log.exception(
"Restoring torrent {0} failed".format(v)
)
finally:
pkl_file.close()
@ -321,17 +257,20 @@ class Session(lt.session):
with open(os.path.join(data_dir, "torrents"), 'wb') as f:
cPickle.dump(self.torrents, f)
log.debug("List of torrents saved.")
self.log.debug("List of torrents saved.")
# Save fast resume data
for h in self.handles.itervalues():
if not h.is_valid() or not h.has_metadata():
continue
data = lt.bencode(h.write_resume_data())
with open(os.path.join(data_dir, '{}.fastresume'.format(h.info_hash())), 'wb') as f:
with open(os.path.join(
data_dir, '{}.fastresume'.format(h.info_hash())
), 'wb'
) as f:
f.write(data)
log.debug("Fast resume data saved.")
self.log.debug("Fast resume data saved.")
def add_torrent(self, t_uri):
if not t_uri:
@ -342,37 +281,47 @@ class Session(lt.session):
if not t_uri.startswith("magnet"):
mimetype = mimetypes.guess_type(t_uri)[0]
if not mimetype == "application/x-bittorrent":
log.error("Invalid file")
self.log.error("Invalid file")
return
with open(t_uri, 'rb') as t:
t_raw = lt.bdecode(t.read())
if self.conf.getboolean("Settings", "delete_original"):
log.debug("Deleting original torrent file {}".format(t_uri))
self.log.debug("Deleting original torrent file {}".format(t_uri))
os.remove(t_uri)
info = lt.torrent_info(t_raw)
rd = None
try:
with open(os.path.join(data_dir, "{}.fastresume".format(info.info_hash())), "rb") as f:
with open(os.path.join(
data_dir, "{}.fastresume".format(info.info_hash())
), "rb"
) as f:
rd = lt.bdecode(f.read())
except:
try:
with open(os.path.join(data_dir, "{}.fastresume".format(info.name())), "rb") as f:
with open(os.path.join(
data_dir, "{}.fastresume".format(info.name())
), "rb"
) as f:
rd = lt.bdecode(f.read())
except:
log.debug("Invalid resume data")
self.log.debug("Invalid resume data")
h = lt.session.add_torrent(self, info, storage_path, resume_data=rd)
t_uri = self.parent.write_torrent(h)
h = lt.session.add_torrent(
self, info, storage_path, resume_data=rd)
t_uri = self.write_torrent(h)
else:
t_uri = urllib.unquote(t_uri)
t_uri = str(HTMLParser.HTMLParser().unescape(t_uri))
h = lt.add_magnet_uri(self, t_uri, { "save_path": str(storage_path) })
h = lt.add_magnet_uri(
self, t_uri,
{ "save_path": str(storage_path) }
)
if not h.is_valid():
log.error("Invalid torrent handle")
self.log.error("Invalid torrent handle")
return
ihash = str(h.info_hash())
@ -384,37 +333,70 @@ class Session(lt.session):
def remove_torrent(self, h, with_data=False):
ihash = str(h.info_hash())
info = h.get_torrent_info()
fr_path1 = os.path.join(data_dir, "{}.fastresume".format(info.info_hash()))
fr_path2 = os.path.join(data_dir, "{}.fastresume".format(info.name()))
fr_path = os.path.join(
data_dir, "{}.fastresume".format(ihash)
)
t_path = self.torrents[ihash]
del self.torrents[ihash]
lt.session.remove_torrent(self, h, option=with_data)
for p in fr_path1, fr_path2:
try:
with open(p): pass
except IOError:
log.debug("Could not remove fast resume data.")
else:
os.remove(p)
break
try:
with open(fr_path): pass
except IOError:
self.log.debug("Could not remove fast resume data.")
else:
os.remove(fr_path)
try:
with open(t_path): pass
except IOError:
log.debug("Could not remove torrent file.")
self.log.debug("Could not remove torrent file.")
else:
os.remove(t_path)
return ihash
class AlertManager(object):
log = logging.getLogger("epour.alert")
update_interval = 0.2
alerts = {}
def __init__(self, session):
self.session = session
self.timer = Timer(self.update_interval, self.update)
def callback_add(self, alert_type, cb, *args, **kwargs):
if not self.alerts.has_key(alert_type):
self.alerts[alert_type] = []
self.alerts[alert_type].append((cb, args, kwargs))
def callback_del(self, alert_type, cb, *args, **kwargs):
for i, a in enumerate(self.alerts):
if a == (cb, args, kwargs):
del(self.alerts[alert_type][i])
def update(self):
while 1:
a = self.session.pop_alert()
if not a or not self.alerts.has_key(type(a)): break
for cb, args, kwargs in self.alerts[type(a)]:
try:
cb(a, *args, **kwargs)
except:
log.exception()
return True
class EpourDBus(dbus.service.Object):
def __init__(self, parent):
self.parent = parent
dbus.service.Object.__init__(self, dbus.SessionBus(), "/net/launchpad/epour", "net.launchpad.epour")
dbus.service.Object.__init__(self, dbus.SessionBus(),
"/net/launchpad/epour", "net.launchpad.epour")
self.props = {
}
@ -422,12 +404,9 @@ class EpourDBus(dbus.service.Object):
@dbus.service.method(dbus_interface='net.launchpad.epour',
in_signature='s', out_signature='')
def AddTorrent(self, f):
log.info("Adding %s from dbus" % f)
self.log.info("Adding %s from dbus" % f)
self.parent.session.add_torrent(str(f))
if __name__ == "__main__":
elm.init()
epour = Epour(sys.argv[1:])
elm.run()
elm.shutdown()
logging.shutdown()

View File

@ -22,14 +22,22 @@
import os
from datetime import timedelta
import libtorrent as lt
try:
from evas import EVAS_ASPECT_CONTROL_VERTICAL
from elementary import Genlist, GenlistItemClass, StandardWindow, Icon, Box, \
Label, Button, ELM_GENLIST_ITEM_FIELD_TEXT, ELM_GENLIST_ITEM_FIELD_CONTENT, \
InnerWindow, Ctxpopup, Frame, Fileselector, Entry
from ecore import Timer
import elementary as elm
from elementary import Genlist, GenlistItemClass, StandardWindow, Icon, \
Box, Label, Button, ELM_GENLIST_ITEM_FIELD_TEXT, \
ELM_GENLIST_ITEM_FIELD_CONTENT, InnerWindow, Ctxpopup, Frame, \
Fileselector, Entry
except ImportError:
from efl.evas import EVAS_ASPECT_CONTROL_VERTICAL
from efl.elementary.genlist import Genlist, GenlistItemClass, ELM_GENLIST_ITEM_FIELD_TEXT, ELM_GENLIST_ITEM_FIELD_CONTENT
from efl.ecore import Timer
from efl import elementary as elm
from efl.elementary.genlist import Genlist, GenlistItemClass, \
ELM_GENLIST_ITEM_FIELD_TEXT, ELM_GENLIST_ITEM_FIELD_CONTENT
from efl.elementary.window import StandardWindow
from efl.elementary.icon import Icon
from efl.elementary.box import Box
@ -47,75 +55,13 @@ from Notify import ConfirmExit, Error, Information
from intrepr import intrepr
class TorrentClass(GenlistItemClass):
state_str = ['Queued', 'Checking', 'Downloading metadata', \
'Downloading', 'Finished', 'Seeding', 'Allocating', \
'Checking resume data']
def text_get(self, obj, part, item_data):
h = item_data
name = h.get_torrent_info().name() if h.has_metadata() else "-"
if part == "elm.text":
return '%s' % (
name
)
elif part == "elm.text.sub":
s = h.status()
return '{:.0%} complete, ETA: {} (Down: {}/s Up: {}/s Peers: {} Queue: {})'.format(
s.progress,
timedelta(seconds=self.get_eta(h)),
intrepr(s.download_payload_rate, precision=0),
intrepr(s.upload_payload_rate, precision=0),
s.num_peers,
h.queue_position(),
)
def content_get(self, obj, part, item_data):
if part == "elm.swallow.icon":
h = item_data
s = h.status()
ic = Icon(obj)
if h.is_paused():
ic.standard = "player_pause"
elif h.is_seed():
ic.standard = "up"
else:
ic.standard = "down"
ic.tooltip_text_set(self.state_str[s.state])
ic.size_hint_aspect_set(EVAS_ASPECT_CONTROL_VERTICAL, 1, 1)
return ic
def get_eta(self, h):
s = h.status()
if False: #self.is_finished and self.options["stop_at_ratio"]:
# We're a seed, so calculate the time to the 'stop_share_ratio'
if not s.upload_payload_rate:
return 0
stop_ratio = self.options["stop_ratio"]
return ((s.all_time_download * stop_ratio) - s.all_time_upload) / s.upload_payload_rate
left = s.total_wanted - s.total_wanted_done
if left <= 0 or s.download_payload_rate == 0:
return 0
try:
eta = left / s.download_payload_rate
except ZeroDivisionError:
eta = 0
return eta
class MainInterface(object):
def __init__(self, parent, session):
self.parent = parent
self.session = session
self.win = StandardWindow("epour", "Epour")
self.win.callback_delete_request_add(self.quit)
self.win.callback_delete_request_add(lambda x: elm.exit())
self.torrentitems = {}
@ -154,7 +100,8 @@ class MainInterface(object):
addbtn.show()
togglebtn = self.togglebtn = Button(self.win)
togglebtn.text_set("Resume all" if parent.session.is_paused() else "Pause all")
togglebtn.text = "Resume all" if \
parent.session.is_paused() else "Pause all"
togglebtn.callback_clicked_add(self.toggle_paused_cb)
btnbox.pack_end(togglebtn)
togglebtn.show()
@ -169,21 +116,39 @@ class MainInterface(object):
btnbox.show()
self.win.resize(480, 480)
for a in lt.state_changed_alert, lt.torrent_paused_alert, lt.torrent_resumed_alert:
session.alert_manager.callback_add(a, self.update_icon)
session.alert_manager.callback_add(lt.torrent_finished_alert, self.torrent_finished_cb)
def run(self):
self.win.show()
def update_texts(self, session):
self.timer = Timer(1.0, self.update)
elm.run()
self.quit()
def update(self):
for v in self.torrentitems.itervalues():
v.fields_update("elm.text", ELM_GENLIST_ITEM_FIELD_TEXT)
v.fields_update("elm.text.sub", ELM_GENLIST_ITEM_FIELD_TEXT)
s = session.status()
s = self.session.status()
self.status.text = "Down: {0}/s Up: {1}/s Peers: {2}".format(
intrepr(s.payload_download_rate),
intrepr(s.payload_upload_rate),
s.num_peers
)
return True
def update_icon(self, ihash):
self.torrentitems[ihash].fields_update("elm.swallow.icon", ELM_GENLIST_ITEM_FIELD_CONTENT)
def update_icon(self, a):
h = a.handle
if not h.is_valid(): return
ihash = str(h.info_hash())
if not self.torrentitems.has_key(ihash): return
self.torrentitems[ihash].fields_update(
"elm.swallow.icon", ELM_GENLIST_ITEM_FIELD_CONTENT
)
def select_torrent(self, btn):
sel = Fileselector(self.win)
@ -274,10 +239,14 @@ class MainInterface(object):
self.resume_torrent_cb if h.is_paused() else self.pause_torrent_cb,
h
)
cp.item_append("Remove torrent", None, self.remove_torrent_cb, item, h, False)
cp.item_append("Remove torrent and files", None, self.remove_torrent_cb, item, h, True)
cp.item_append("Force re-check", None, self.force_recheck, h)
cp.item_append("Torrent preferences", None, self.torrent_preferences_cb, h)
cp.item_append("Remove torrent", None,
self.remove_torrent_cb, item, h, False)
cp.item_append("Remove torrent and files", None,
self.remove_torrent_cb, item, h, True)
cp.item_append("Force re-check", None,
self.force_recheck, h)
cp.item_append("Torrent preferences", None,
self.torrent_preferences_cb, h)
cp.pos = self.win.evas.pointer_canvas_xy_get()
cp.show()
@ -309,12 +278,82 @@ class MainInterface(object):
def show_error(self, title, text):
Error(self.win, title, text)
def show_information(self, text):
Information(self.win, text)
def torrent_finished_cb(self, h):
msg = "Torrent {} has finished downloading.".format(
cgi.escape(h.name())
)
self.log.info(msg)
Information(self.win, msg)
def quit(self, *args):
if self.session.conf.getboolean("Settings", "confirmations"):
ConfirmExit(self.win, self.parent.quit)
ConfirmExit(self.win, self.shutdown())
else:
self.parent.quit()
self.shutdown()
def shutdown(self):
elm.shutdown()
self.parent.quit()
class TorrentClass(GenlistItemClass):
state_str = ['Queued', 'Checking', 'Downloading metadata', \
'Downloading', 'Finished', 'Seeding', 'Allocating', \
'Checking resume data']
def text_get(self, obj, part, item_data):
h = item_data
name = h.get_torrent_info().name() if h.has_metadata() else "-"
if part == "elm.text":
return '%s' % (
name
)
elif part == "elm.text.sub":
s = h.status()
return '{:.0%} complete, ETA: {} (Down: {}/s Up: {}/s Peers: {} Queue: {})'.format(
s.progress,
timedelta(seconds=self.get_eta(h)),
intrepr(s.download_payload_rate, precision=0),
intrepr(s.upload_payload_rate, precision=0),
s.num_peers,
h.queue_position(),
)
def content_get(self, obj, part, item_data):
if part == "elm.swallow.icon":
h = item_data
s = h.status()
ic = Icon(obj)
if h.is_paused():
ic.standard = "player_pause"
elif h.is_seed():
ic.standard = "up"
else:
ic.standard = "down"
ic.tooltip_text_set(self.state_str[s.state])
ic.size_hint_aspect_set(EVAS_ASPECT_CONTROL_VERTICAL, 1, 1)
return ic
def get_eta(self, h):
s = h.status()
if False: #self.is_finished and self.options["stop_at_ratio"]:
# We're a seed, so calculate the time to the 'stop_share_ratio'
if not s.upload_payload_rate:
return 0
stop_ratio = self.options["stop_ratio"]
return ((s.all_time_download * stop_ratio) - s.all_time_upload) / s.upload_payload_rate
left = s.total_wanted - s.total_wanted_done
if left <= 0 or s.download_payload_rate == 0:
return 0
try:
eta = left / s.download_payload_rate
except ZeroDivisionError:
eta = 0
return eta

View File

@ -70,10 +70,18 @@ class Preferences(InnerWindow):
lbl.text = "Click on a title to open/close configuration entry."
ports = ListenPorts(self, session)
ul = LimitWidget(self, "Upload limit", session.upload_rate_limit, session.set_upload_rate_limit)
dl = LimitWidget(self, "Download limit", session.download_rate_limit, session.set_download_rate_limit)
lul = LimitWidget(self, "Upload limit for local connections", session.local_upload_rate_limit, session.set_local_upload_rate_limit)
ldl = LimitWidget(self, "Download limit for local connections", session.local_download_rate_limit, session.set_local_download_rate_limit)
ul = LimitWidget(self, "Upload limit",
session.upload_rate_limit,
session.set_upload_rate_limit)
dl = LimitWidget(self, "Download limit",
session.download_rate_limit,
session.set_download_rate_limit)
lul = LimitWidget(self, "Upload limit for local connections",
session.local_upload_rate_limit,
session.set_local_upload_rate_limit)
ldl = LimitWidget(self, "Download limit for local connections",
session.local_download_rate_limit,
session.set_local_download_rate_limit)
pf = ProxyConfig(self, parent.win)
dlsel = DataStorageSelector(self, conf)
@ -88,13 +96,15 @@ class Preferences(InnerWindow):
chk1.size_hint_align = 0.0, 0.0
chk1.text = "Delete original .torrent file when added"
chk1.state = conf.getboolean("Settings", "delete_original")
chk1.callback_changed_add(lambda x: conf.set("Settings", "delete_original", str(bool(chk1.state))))
chk1.callback_changed_add(lambda x: conf.set("Settings",
"delete_original", str(bool(chk1.state))))
chk2 = Check(self)
chk2.size_hint_align = 0.0, 0.0
chk2.text = "Ask for confirmation on exit"
chk2.state = conf.getboolean("Settings", "confirmations")
chk2.callback_changed_add(lambda x: conf.set("Settings", "confirmations", str(bool(chk2.state))))
chk2.callback_changed_add(lambda x: conf.set("Settings",
"confirmations", str(bool(chk2.state))))
sep2 = Separator(self)
sep2.horizontal = True
@ -103,7 +113,8 @@ class Preferences(InnerWindow):
xbtn.text_set("Close")
xbtn.callback_clicked_add(lambda x: self.delete())
for w in lbl, ports, ul, dl, lul, ldl, pf, dlsel, ses_set, pad, sep1, chk1, chk2, sep2, xbtn:
for w in lbl, ports, ul, dl, lul, ldl, pf, dlsel, ses_set, pad, \
sep1, chk1, chk2, sep2, xbtn:
w.show()
mbox.pack_end(w)
@ -152,7 +163,8 @@ class DataStorageSelector(Frame):
return
if not os.path.exists(self.dlsel.path):
p = Notify.Error(self, "Invalid storage path", "You have selected an invalid data storage path for torrents.")
p = Notify.Error(self, "Invalid storage path",
"You have selected an invalid data storage path for torrents.")
return
self.path_lbl.text = path
@ -302,10 +314,14 @@ class ProxyConfig(Frame):
b = Box(parent)
proxies = [
["Proxy for torrent peer connections", session.peer_proxy, session.set_peer_proxy],
["Proxy for torrent web seed connections", session.web_seed_proxy, session.set_web_seed_proxy],
["Proxy for tracker connections", session.tracker_proxy, session.set_tracker_proxy],
["Proxy for DHT connections", session.dht_proxy, session.set_dht_proxy],
["Proxy for torrent peer connections",
session.peer_proxy, session.set_peer_proxy],
["Proxy for torrent web seed connections",
session.web_seed_proxy, session.set_web_seed_proxy],
["Proxy for tracker connections",
session.tracker_proxy, session.set_tracker_proxy],
["Proxy for DHT connections",
session.dht_proxy, session.set_dht_proxy],
]
for title, rfunc, wfunc in proxies:
@ -423,8 +439,6 @@ class ProxyGroup(Frame):
# encryption: in policy, out policy, allowed enc level, prefer enc
# session.settings
class SessionSettings(Frame):
def __init__(self, parent, session):
Frame.__init__(self, parent)
@ -480,7 +494,6 @@ class SessionSettings(Frame):
f = Frame(parent)
f.size_hint_align = -1.0, 0.0
f.text = k
#w.disabled = True
w.show()
widgets[k] = w
f.content = w
@ -521,4 +534,3 @@ class SessionSettings(Frame):
session.set_settings(s)
Notify.Information(self.canvas, "Session settings saved.")
#print(dir(lt.session_settings))

View File

@ -39,8 +39,8 @@ except ImportError:
from efl.elementary.entry import Entry
else:
import ecore
from elementary import Genlist, GenlistItemClass, InnerWindow, Button, Box, \
Hoversel, Check, Label, ELM_WRAP_CHAR, ELM_WRAP_WORD, Entry
from elementary import Genlist, GenlistItemClass, InnerWindow, Button, \
Box, Hoversel, Check, Label, ELM_WRAP_CHAR, ELM_WRAP_WORD, Entry
from intrepr import intrepr
@ -87,14 +87,16 @@ class TorrentInfo(InnerWindow):
if w:
l = Label(self)
l.ellipsis = True
l.text = cgi.escape(w)
l.text = cgi.escape(str(w))
l.show()
box.pack_end(l)
tpriv = Check(self)
tpriv.size_hint_align = 0.0, 0.0
tpriv.text = "Private"
tpriv.tooltip_text_set("Whether this torrent is private.<br>i.e., it should not be distributed on the trackerless network<br>(the kademlia DHT).")
tpriv.tooltip_text_set(
"Whether this torrent is private.<br>i.e., it should not be\
distributed on the trackerless network<br>(the kademlia DHT).")
tpriv.disabled = True
tpriv.state = i.priv()
@ -107,7 +109,10 @@ class TorrentInfo(InnerWindow):
i = h.get_torrent_info()
files = i.files()
for n, file_entry in enumerate(files):
filelist.item_append(FileSelectionClass(), (file_entry, progress[n], n, h), None, 0)
filelist.item_append(
FileSelectionClass(),
(file_entry, progress[n], n, h),
None, 0)
filelist.callback_activated_add(self.item_activated_cb)
@ -142,4 +147,4 @@ class TorrentInfo(InnerWindow):
if sys.platform == 'linux2':
ecore.Exe("xdg-open '{0}'".format(path))
else:
os.startfile(path)
os.startfile(path)

View File

@ -1,2 +1,9 @@
from Main import MainInterface
from Preferences import Preferences
try:
from efl import elementary
except ImportError:
import elementary
elementary.init()