diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..539da74 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.py[co] diff --git a/README b/README new file mode 100644 index 0000000..dd1c429 --- /dev/null +++ b/README @@ -0,0 +1,41 @@ +============ +REQUIREMENTS +============ + +* libtorrent-rasterbar 0.15.* or later, tested and developed with 0.15.10 + + http://www.rasterbar.com/products/libtorrent/ + +* Enlightenment Foundation Libraries 1.7 or later + + http://www.enlightenment.org/ + +* Python Bindings for EFL 1.7 or later + + - 1.7 bindings: + + ecore, e_dbus and evas from E SVN: + http://svn.enlightenment.org/svn/e/trunk/BINDINGS/python/ + + elementary from E GIT: + http://git.enlightenment.org/legacy/bindings/python/python-elementary.git/ + + - 1.7.99 bindings: + + http://git.enlightenment.org/bindings/python/python-efl.git/ + +* Python 2.x + + http://www.python.org/ + +* python-distutils-extra + + https://launchpad.net/python-distutils-extra + +* If used with 1.7 bindings, you'll also need dbus-python + +======= +INSTALL +======= + +sudo ./setup.py install diff --git a/epour/Epour.py b/epour/Epour.py index 44999ed..0212d0a 100755 --- a/epour/Epour.py +++ b/epour/Epour.py @@ -47,24 +47,48 @@ def setup_log(): log = setup_log() -import dbus, e_dbus -ml = e_dbus.DBusEcoreMainLoop() -dbus.set_default_main_loop(ml) -import dbus.service -bus = dbus.SessionBus() +DBUS_ENABLED = None -dbo = None try: - dbo = bus.get_object("net.launchpad.epour", "/net/launchpad/epour") -except dbus.exceptions.DBusException: - pass + import e_dbus +except ImportError: + DBUS_ENABLED = False + log.info("e_dbus not found") +else: + DBUS_ENABLED = True + import dbus + ml = e_dbus.DBusEcoreMainLoop() + dbus.set_default_main_loop(ml) + import dbus.service + bus = dbus.SessionBus() + + dbo = None + try: + dbo = bus.get_object("net.launchpad.epour", "/net/launchpad/epour") + except dbus.exceptions.DBusException: + pass + + if dbo: + if sys.argv[1:]: + for f in sys.argv[1:]: + log.info("Sending %s via dbus" % f) + dbo.AddTorrent(f, dbus_interface="net.launchpad.epour") + sys.exit() + + 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") + + self.props = { + } + + @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.parent.session.add_torrent(str(f)) -if dbo: - if sys.argv[1:]: - for f in sys.argv[1:]: - log.info("Sending %s via dbus" % f) - dbo.AddTorrent(f, dbus_interface="net.launchpad.epour") - sys.exit() import mimetypes import ConfigParser @@ -96,8 +120,9 @@ class Epour(object): for t in torrents: self.session.add_torrent(t) - self.dbusname = dbus.service.BusName("net.launchpad.epour", dbus.SessionBus()) - self.dbo = EpourDBus(self) + if DBUS_ENABLED: + self.dbusname = dbus.service.BusName("net.launchpad.epour", dbus.SessionBus()) + self.dbo = EpourDBus(self) # Update timer timer = timer_add(1.0, self.update) @@ -300,20 +325,6 @@ class Session(lt.session): return ihash -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") - - self.props = { - } - - @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.parent.session.add_torrent(str(f)) - if __name__ == "__main__": elm.init() epour = Epour(sys.argv[1:]) diff --git a/epour/gui/Main.py b/epour/gui/Main.py index 58a1f90..3c81587 100644 --- a/epour/gui/Main.py +++ b/epour/gui/Main.py @@ -22,13 +22,28 @@ import os from evas import EVAS_ASPECT_CONTROL_VERTICAL -import elementary as elm +try: + 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.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 + from efl.elementary.label import Label + from efl.elementary.button import Button + from efl.elementary.innerwindow import InnerWindow + from efl.elementary.ctxpopup import Ctxpopup + from efl.elementary.frame import Frame + from efl.elementary.fileselector import Fileselector + from efl.elementary.entry import Entry -from TorrentInfo import TorrentInfo +#from TorrentInfo import TorrentInfo from Preferences import Preferences from Notify import ConfirmExit -class TorrentClass(elm.GenlistItemClass): +class TorrentClass(GenlistItemClass): def text_get(self, obj, part, item_data): state_str = ['Queued', 'Checking', 'Downloading metadata', \ @@ -56,7 +71,7 @@ class TorrentClass(elm.GenlistItemClass): if part == "elm.swallow.icon": h = item_data s = h.status() - ic = elm.Icon(obj) + ic = Icon(obj) if h.is_paused(): ic.standard = "player_pause" ic.tooltip_text_set("Paused") @@ -72,18 +87,18 @@ class TorrentClass(elm.GenlistItemClass): class MainInterface(object): def __init__(self, parent): self.parent = parent - self.win = elm.StandardWindow("epour", "Epour") + self.win = StandardWindow("epour", "Epour") self.win.callback_delete_request_add(self.quit) self.torrentitems = {} # GUI - box = elm.Box(self.win) + box = Box(self.win) box.size_hint_weight_set(1.0, 1.0) self.win.resize_object_add(box) box.show() - self.tlist = tlist = elm.Genlist(self.win) + self.tlist = tlist = Genlist(self.win) tlist.callback_activated_add(self.item_activated_cb) tlist.homogeneous_set(True) tlist.size_hint_weight_set(1.0, 1.0) @@ -92,29 +107,29 @@ class MainInterface(object): tlist.show() s = parent.session.status() - status = self.status = elm.Label(self.win) + status = self.status = Label(self.win) status.text_set("down: %.1f kb/s up: %.1f kB/s peers: %d" % \ (s.payload_download_rate, s.payload_upload_rate, s.num_peers)) box.pack_end(status) status.show() - btnbox = elm.Box(self.win) + btnbox = Box(self.win) btnbox.horizontal = True btnbox.size_hint_align_set(-1.0, 0.0) - addbtn = elm.Button(self.win) + addbtn = Button(self.win) addbtn.text_set("Add torrent") addbtn.callback_clicked_add(self.select_torrent) btnbox.pack_end(addbtn) addbtn.show() - togglebtn = self.togglebtn = elm.Button(self.win) + togglebtn = self.togglebtn = Button(self.win) togglebtn.text_set("Resume all" if parent.session.is_paused() else "Pause all") togglebtn.callback_clicked_add(self.toggle_paused_cb) btnbox.pack_end(togglebtn) togglebtn.show() - prefbtn = elm.Button(self.win) + prefbtn = Button(self.win) prefbtn.text = "Preferences" prefbtn.callback_clicked_add(self.prefs_cb) prefbtn.show() @@ -128,8 +143,8 @@ class MainInterface(object): def update_texts(self, session): for v in self.torrentitems.itervalues(): - v.fields_update("elm.text", elm.ELM_GENLIST_ITEM_FIELD_TEXT) - v.fields_update("elm.text.sub", elm.ELM_GENLIST_ITEM_FIELD_TEXT) + v.fields_update("elm.text", ELM_GENLIST_ITEM_FIELD_TEXT) + v.fields_update("elm.text.sub", ELM_GENLIST_ITEM_FIELD_TEXT) s = session.status() self.status.text_set("down: %.1f kB/s up: %.1f kB/s peers: %d" % ( s.payload_download_rate / 1000, @@ -138,35 +153,35 @@ class MainInterface(object): )) def update_icon(self, ihash): - self.torrentitems[ihash].fields_update("elm.swallow.icon", elm.ELM_GENLIST_ITEM_FIELD_CONTENT) + self.torrentitems[ihash].fields_update("elm.swallow.icon", ELM_GENLIST_ITEM_FIELD_CONTENT) def select_torrent(self, btn): - sel = elm.Fileselector(self.win) + sel = Fileselector(self.win) sel.path_set(os.path.expanduser("~")) sel.size_hint_weight_set(1.0, 1.0) sel.size_hint_align_set(-1.0, -1.0) sel.show() - sf = elm.Frame(self.win) + sf = Frame(self.win) sf.size_hint_weight_set(1.0, 1.0) sf.size_hint_align_set(-1.0, -1.0) sf.text = "Select torrent file" sf.content = sel sf.show() - magnet = elm.Entry(self.win) + magnet = Entry(self.win) magnet.single_line = True magnet.scrollable = True magnet.show() - mf = elm.Frame(self.win) + mf = Frame(self.win) mf.size_hint_weight_set(1.0, 0.0) mf.size_hint_align_set(-1.0, 0.0) mf.text = "Or enter magnet URI here" mf.content = magnet mf.show() - mbtn = elm.Button(self.win) + mbtn = Button(self.win) mbtn.text = "Done" mbtn.show() - mbox = elm.Box(self.win) + mbox = Box(self.win) mbox.size_hint_weight_set(1.0, 0.0) mbox.size_hint_align_set(-1.0, 0.0) mbox.horizontal = True @@ -174,14 +189,14 @@ class MainInterface(object): mbox.pack_end(mbtn) mbox.show() - box = elm.Box(self.win) + box = Box(self.win) box.size_hint_weight = (1.0, 1.0) box.size_hint_align = (-1.0, -1.0) box.pack_end(sf) box.pack_end(mbox) box.show() - self.inwin = inwin = elm.InnerWindow(self.win) + self.inwin = inwin = InnerWindow(self.win) inwin.content = box sel.callback_done_add(self.add_torrent_cb) sel.callback_done_add(lambda x, y: inwin.delete()) @@ -221,7 +236,7 @@ class MainInterface(object): def item_activated_cb(self, gl, item): h = item.data - cp = elm.Ctxpopup(self.win) + cp = Ctxpopup(self.win) cp.item_append( "Resume" if h.is_paused() else "Pause", None, diff --git a/epour/gui/Notify.py b/epour/gui/Notify.py index 2a37ac5..9eec893 100644 --- a/epour/gui/Notify.py +++ b/epour/gui/Notify.py @@ -19,12 +19,18 @@ # MA 02110-1301, USA. # -import elementary as elm +try: + from elementary import Label, Notify, Popup, Button +except ImportError: + from efl.elementary.label import Label + from efl.elementary.notify import Notify + from efl.elementary.popup import Popup + from efl.elementary.button import Button class Information(object): def __init__(self, canvas, text): - n = elm.Notify(canvas) - l = elm.Label(canvas) + n = Notify(canvas) + l = Label(canvas) l.text = text n.content = l n.timeout = 3 @@ -32,10 +38,10 @@ class Information(object): class Error(object): def __init__(self, canvas, title, text): - n = elm.Popup(canvas) + n = Popup(canvas) n.part_text_set("title,text", title) n.text = text - b = elm.Button(canvas) + b = Button(canvas) b.text = "OK" b.callback_clicked_add(lambda x: n.delete()) n.part_content_set("button1", b) @@ -43,14 +49,14 @@ class Error(object): class ConfirmExit(object): def __init__(self, canvas, exit_func): - n = elm.Popup(canvas) + n = Popup(canvas) n.part_text_set("title,text", "Confirm exit") n.text = "Are you sure you wish to exit Epour?" - b = elm.Button(canvas) + b = Button(canvas) b.text = "Yes" b.callback_clicked_add(lambda x: exit_func()) n.part_content_set("button1", b) - b = elm.Button(canvas) + b = Button(canvas) b.text = "No" b.callback_clicked_add(lambda x: n.delete()) n.part_content_set("button2", b) diff --git a/epour/gui/Preferences.py b/epour/gui/Preferences.py index 887f13d..2816fd2 100644 --- a/epour/gui/Preferences.py +++ b/epour/gui/Preferences.py @@ -23,14 +23,32 @@ import os import libtorrent as lt -import elementary as elm +try: + from elementary import Icon, Box, Label, Button, \ + InnerWindow, Frame, Entry, Check, Spinner, Hoversel, \ + FileselectorEntry, Scroller, ELM_SCROLLER_POLICY_OFF, \ + ELM_SCROLLER_POLICY_AUTO +except ImportError: + from efl.elementary.icon import Icon + from efl.elementary.box import Box + from efl.elementary.label import Label + from efl.elementary.button import Button + from efl.elementary.innerwindow import InnerWindow + from efl.elementary.frame import Frame + from efl.elementary.entry import Entry + from efl.elementary.check import Check + from efl.elementary.spinner import Spinner + from efl.elementary.hoversel import Hoversel + from efl.elementary.fileselector_entry import FileselectorEntry + from efl.elementary.scroller import Scroller, ELM_SCROLLER_POLICY_OFF, \ + ELM_SCROLLER_POLICY_AUTO import Notify -class Preferences(elm.InnerWindow): +class Preferences(InnerWindow): def __init__(self, parent, session): self.session = session - elm.InnerWindow.__init__(self, parent.win) + InnerWindow.__init__(self, parent.win) self.limit_widgets = {} self.num_widgets = {} @@ -44,32 +62,32 @@ class Preferences(elm.InnerWindow): ( "Download limit for local connections", session.local_download_rate_limit, session.set_local_download_rate_limit ), ) - mbox = elm.Box(self) + mbox = Box(self) mbox.size_hint_weight = 1.0, 1.0 mbox.size_hint_align = -1.0, -1.0 - lbl = elm.Label(self) + lbl = Label(self) lbl.text = "Click on the names to open/close configuration entry." lbl.show() mbox.pack_end(lbl) for text, rfunc, wfunc in self.limits: - f = elm.Frame(self) + f = Frame(self) f.collapse = True f.autocollapse = True f.size_hint_align = -1.0, 0.0 f.text = text - b = elm.Box(self) + b = Box(self) b.horizontal = True b.show() - s = elm.Spinner(self) + s = Spinner(self) s.min_max = 0, 1024 s.show() b.pack_end(s) - hs = elm.Hoversel(self) + hs = Hoversel(self) hs.text = limit_units[0] for u in limit_units: hs.item_add(u, None, 0, lambda x=hs, y=None, u=u: x.text_set(u)) @@ -93,22 +111,22 @@ class Preferences(elm.InnerWindow): mbox.pack_end(f) # Listen port - f = elm.Frame(self) + f = Frame(self) f.size_hint_align = -1.0, -1.0 f.collapse = True f.autocollapse = True f.text = "Listen port (range)" - b = elm.Box(self) + b = Box(self) b.horizontal = True - l = self.listenlow = elm.Spinner(self) + l = self.listenlow = Spinner(self) l.min_max = 0, 65535 l.show() l.value = session.listen_port() b.pack_end(l) - h = self.listenhigh = elm.Spinner(self) + h = self.listenhigh = Spinner(self) h.min_max = 0, 65535 h.show() h.value = session.listen_port() @@ -124,9 +142,9 @@ class Preferences(elm.InnerWindow): mbox.pack_end(pf) # Data storage - lbl = elm.Label(self) + lbl = Label(self) lbl.text = "Torrent data storage path" - self.dlsel = dlsel = elm.FileselectorEntry(self) + self.dlsel = dlsel = FileselectorEntry(self) dlsel.size_hint_align = -1.0, 0.0 dlsel.inwin_mode = True dlsel.folder_only = True @@ -137,23 +155,23 @@ class Preferences(elm.InnerWindow): mbox.pack_end(dlsel) # Ask confirmations - chk = self.confirm_chk = elm.Check(self) + chk = self.confirm_chk = Check(self) chk.text = "Ask for confirmation on exit" chk.state = True if self.session.conf.get("Settings", "confirmations") == "True" else False chk.show() mbox.pack_end(chk) - btnb = elm.Box(self) + btnb = Box(self) btnb.horizontal = True - save = elm.Button(self) + save = Button(self) save.text_set("Save") save.callback_clicked_add(self.save_cb) save.show() btnb.pack_end(save) - xbtn = elm.Button(self) + xbtn = Button(self) xbtn.text_set("Close") xbtn.callback_clicked_add(lambda x: self.delete()) xbtn.show() @@ -162,8 +180,8 @@ class Preferences(elm.InnerWindow): btnb.show() mbox.pack_end(btnb) - scr = elm.Scroller(self) - scr.policy = elm.ELM_SCROLLER_POLICY_OFF, elm.ELM_SCROLLER_POLICY_AUTO + scr = Scroller(self) + scr.policy = ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO scr.content = mbox self.content = scr @@ -194,9 +212,9 @@ class Preferences(elm.InnerWindow): self.session.listen_on(int(self.listenlow.value), int(self.listenhigh.value)) self.delete() -class ProxyConfig(elm.Frame): +class ProxyConfig(Frame): def __init__(self, parent, canvas): - elm.Frame.__init__(self, canvas) + Frame.__init__(self, canvas) session = self.session = parent.session @@ -224,7 +242,7 @@ class ProxyConfig(elm.Frame): self.size_hint_align = (-1.0, 0.0) self.text = "Proxy configuration" - mbox = elm.Box(self) + mbox = Box(self) for text, funcs in self.proxies.iteritems(): rfunc, wfunc = funcs @@ -232,20 +250,20 @@ class ProxyConfig(elm.Frame): widgets = self.widgets[text] = {} - pf = elm.Frame(self) + pf = Frame(self) pf.collapse = True pf.autocollapse = True pf.size_hint_weight = (1.0, 0.0) pf.size_hint_align = (-1.0, 0.0) pf.text = text - box = elm.Box(self) + box = Box(self) box.size_hint_weight = (1.0, 0.0) - f = elm.Frame(self) + f = Frame(self) f.size_hint_align = (-1.0, 0.0) f.text = "Proxy type" - ptype = widgets["type"] = elm.Hoversel(self) + ptype = widgets["type"] = Hoversel(self) ptype.text = settings.type.name for v in self.proxy_types.iterkeys(): ptype.item_add(v, callback=lambda x, y, z=v: x.text_set(z)) @@ -253,10 +271,10 @@ class ProxyConfig(elm.Frame): f.show() box.pack_end(f) - f = elm.Frame(self) + f = Frame(self) f.size_hint_align = (-1.0, 0.0) f.text = "Hostname" - phost = widgets["host"] = elm.Entry(self) + phost = widgets["host"] = Entry(self) phost.single_line = True phost.entry = settings.hostname phost.show() @@ -264,10 +282,10 @@ class ProxyConfig(elm.Frame): f.show() box.pack_end(f) - f = elm.Frame(self) + f = Frame(self) f.size_hint_align = (-1.0, 0.0) f.text = "Port" - pport = widgets["port"] = elm.Spinner(self) + pport = widgets["port"] = Spinner(self) pport.min_max = (0, 65535) pport.value = settings.port pport.show() @@ -275,10 +293,10 @@ class ProxyConfig(elm.Frame): f.show() box.pack_end(f) - f = elm.Frame(self) + f = Frame(self) f.size_hint_align = (-1.0, 0.0) f.text = "Username" - puser = widgets["user"] = elm.Entry(self) + puser = widgets["user"] = Entry(self) puser.single_line = True puser.entry = settings.username puser.show() @@ -286,10 +304,10 @@ class ProxyConfig(elm.Frame): f.show() box.pack_end(f) - f = elm.Frame(self) + f = Frame(self) f.size_hint_align = (-1.0, 0.0) f.text = "Password" - ppass = widgets["pass"] = elm.Entry(self) + ppass = widgets["pass"] = Entry(self) ppass.single_line = True ppass.password = True ppass.entry = settings.password diff --git a/epour/gui/TorrentInfo.py b/epour/gui/TorrentInfo.py index dfa8a09..2313229 100644 --- a/epour/gui/TorrentInfo.py +++ b/epour/gui/TorrentInfo.py @@ -21,7 +21,7 @@ import elementary as elm -class FileSelectionClass(elm.GenlistItemClass): +class FileSelectionClass(GenlistItemClass): def text_get(self, obj, part, info): return info @@ -35,22 +35,22 @@ class FileSelectionClass(elm.GenlistItemClass): pri.callback_selected_add(self.priority_selected, h) return pri -class TorrentInfo(elm.InnerWindow): +class TorrentInfo(InnerWindow): def __init__(self, parent, h): self.parentwin = parent.win - elm.InnerWindow.__init__(self, parent.win) + InnerWindow.__init__(self, parent.win) - files = elm.Genlist(self) + files = Genlist(self) files.size_hint_align_set(-1.0, -1.0) files.size_hint_weight_set(1.0, 1.0) files.show() - xbtn = elm.Button(self) + xbtn = Button(self) xbtn.text_set("Close") xbtn.callback_clicked_add(lambda x: self.delete()) xbtn.show() - box = elm.Box(self) + box = Box(self) box.size_hint_align_set(-1.0, -1.0) box.pack_end(files) box.pack_end(xbtn)