diff --git a/bin/epour b/bin/epour index e810c34..b367476 100755 --- a/bin/epour +++ b/bin/epour @@ -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() diff --git a/epour/Epour.py b/epour/Epour.py index c263e65..dc4bb6f 100755 --- a/epour/Epour.py +++ b/epour/Epour.py @@ -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() diff --git a/epour/gui/Main.py b/epour/gui/Main.py index 9a2d8bf..7e200b7 100644 --- a/epour/gui/Main.py +++ b/epour/gui/Main.py @@ -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 diff --git a/epour/gui/Preferences.py b/epour/gui/Preferences.py index aaaba5d..d0e1a32 100644 --- a/epour/gui/Preferences.py +++ b/epour/gui/Preferences.py @@ -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)) diff --git a/epour/gui/TorrentInfo.py b/epour/gui/TorrentInfo.py index 5017718..628bbb5 100644 --- a/epour/gui/TorrentInfo.py +++ b/epour/gui/TorrentInfo.py @@ -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.
i.e., it should not be distributed on the trackerless network
(the kademlia DHT).") + tpriv.tooltip_text_set( + "Whether this torrent is private.
i.e., it should not be\ + distributed on the trackerless network
(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) \ No newline at end of file + os.startfile(path) diff --git a/epour/gui/__init__.py b/epour/gui/__init__.py index 2a58af6..a5e66da 100644 --- a/epour/gui/__init__.py +++ b/epour/gui/__init__.py @@ -1,2 +1,9 @@ from Main import MainInterface from Preferences import Preferences + +try: + from efl import elementary +except ImportError: + import elementary + +elementary.init()