|
|
|
@ -19,6 +19,7 @@ |
|
|
|
|
# MA 02110-1301, USA. |
|
|
|
|
# |
|
|
|
|
|
|
|
|
|
import os |
|
|
|
|
import cgi |
|
|
|
|
import logging |
|
|
|
|
from datetime import timedelta, datetime |
|
|
|
@ -38,8 +39,8 @@ from efl.elementary import Genlist, GenlistItemClass, \ |
|
|
|
|
ELM_GENLIST_ITEM_FIELD_TEXT, ELM_GENLIST_ITEM_FIELD_CONTENT, \ |
|
|
|
|
ELM_OBJECT_SELECT_MODE_NONE, ELM_OBJECT_SELECT_MODE_DEFAULT, \ |
|
|
|
|
ELM_LIST_COMPRESS |
|
|
|
|
from efl.elementary import StandardWindow |
|
|
|
|
from efl.elementary import Icon |
|
|
|
|
from efl.elementary import Window, Background, ELM_WIN_BASIC |
|
|
|
|
from efl.elementary import Icon, Image |
|
|
|
|
from efl.elementary import Box |
|
|
|
|
from efl.elementary import Label |
|
|
|
|
from efl.elementary import Panel, ELM_PANEL_ORIENT_BOTTOM |
|
|
|
@ -47,6 +48,10 @@ from efl.elementary import Table |
|
|
|
|
from efl.elementary import Menu |
|
|
|
|
from efl.elementary import Configuration |
|
|
|
|
from efl.elementary import Toolbar, ELM_TOOLBAR_SHRINK_NONE |
|
|
|
|
from efl.elementary import Theme |
|
|
|
|
from efl.elementary import Progressbar |
|
|
|
|
|
|
|
|
|
from xdg.BaseDirectory import load_data_paths |
|
|
|
|
|
|
|
|
|
from .Widgets import ConfirmExit, Error, Information, BlockGraph |
|
|
|
|
|
|
|
|
@ -62,6 +67,14 @@ scale = elm_conf.scale |
|
|
|
|
|
|
|
|
|
log = logging.getLogger("epour.gui") |
|
|
|
|
|
|
|
|
|
theme_file = None |
|
|
|
|
|
|
|
|
|
for data_path in load_data_paths("epour"): |
|
|
|
|
if os.path.exists(data_path): |
|
|
|
|
if os.path.exists(os.path.join(data_path, "themes", "default.edj")): |
|
|
|
|
theme_file = os.path.join(data_path, "themes", "default.edj") |
|
|
|
|
break |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class MainInterface(object): |
|
|
|
|
|
|
|
|
@ -71,11 +84,20 @@ class MainInterface(object): |
|
|
|
|
|
|
|
|
|
self.torrentitems = {} |
|
|
|
|
|
|
|
|
|
win = self.win = StandardWindow( |
|
|
|
|
"epour", "Epour", size=(480 * scale, 400 * scale), |
|
|
|
|
theme = Theme.default_get() |
|
|
|
|
theme.overlay_add(theme_file) |
|
|
|
|
theme.extension_add(theme_file) |
|
|
|
|
|
|
|
|
|
win = self.win = Window( |
|
|
|
|
"epour", ELM_WIN_BASIC, size=(480 * scale, 400 * scale), |
|
|
|
|
screen_constrain=True) |
|
|
|
|
win.title = "Epour" |
|
|
|
|
win.callback_delete_request_add(lambda x: self.quit()) |
|
|
|
|
|
|
|
|
|
bg = Background(win, size_hint_weight=EXPAND_BOTH, color=(0, 0, 0)) |
|
|
|
|
win.resize_object_add(bg) |
|
|
|
|
bg.show() |
|
|
|
|
|
|
|
|
|
mbox = Box(win, size_hint_weight=EXPAND_BOTH) |
|
|
|
|
win.resize_object_add(mbox) |
|
|
|
|
mbox.show() |
|
|
|
@ -88,7 +110,7 @@ class MainInterface(object): |
|
|
|
|
tb.menu_parent = win |
|
|
|
|
|
|
|
|
|
item = tb.item_append( |
|
|
|
|
"document-new", _("Add torrent"), |
|
|
|
|
"toolbar-new", _("Add torrent"), |
|
|
|
|
lambda x, y: self.add_torrent()) |
|
|
|
|
|
|
|
|
|
def pause_session(it): |
|
|
|
@ -100,10 +122,10 @@ class MainInterface(object): |
|
|
|
|
del it.state |
|
|
|
|
|
|
|
|
|
item = tb.item_append( |
|
|
|
|
"media-playback-pause", _("Pause Session"), |
|
|
|
|
"session-pause", _("Pause Session"), |
|
|
|
|
lambda tb, it: pause_session(it)) |
|
|
|
|
item.state_add( |
|
|
|
|
"media-playback-start", _("Resume Session"), |
|
|
|
|
"session-resume", _("Resume Session"), |
|
|
|
|
lambda tb, it: resume_session(it)) |
|
|
|
|
|
|
|
|
|
def prefs_general_cb(): |
|
|
|
@ -118,19 +140,19 @@ class MainInterface(object): |
|
|
|
|
from .Preferences import PreferencesSession |
|
|
|
|
PreferencesSession(self, self._session).show() |
|
|
|
|
|
|
|
|
|
item = tb.item_append("preferences-system", _("Preferences")) |
|
|
|
|
item = tb.item_append("toolbar-settings", _("Preferences")) |
|
|
|
|
item.menu = True |
|
|
|
|
item.menu.item_add( |
|
|
|
|
None, _("General"), "preferences-system", |
|
|
|
|
None, _("General"), "toolbar-settings", |
|
|
|
|
lambda o, i: prefs_general_cb()) |
|
|
|
|
item.menu.item_add( |
|
|
|
|
None, _("Proxy"), "preferences-system", |
|
|
|
|
None, _("Proxy"), "toolbar-settings", |
|
|
|
|
lambda o, i: prefs_proxy_cb()) |
|
|
|
|
item.menu.item_add( |
|
|
|
|
None, _("Session"), "preferences-system", |
|
|
|
|
None, _("Session"), "toolbar-settings", |
|
|
|
|
lambda o, i: prefs_session_cb()) |
|
|
|
|
|
|
|
|
|
item = tb.item_append("application-exit", _("Exit"), |
|
|
|
|
item = tb.item_append("toolbar-quit", _("Exit"), |
|
|
|
|
lambda tb, it: self.quit()) |
|
|
|
|
|
|
|
|
|
mbox.pack_start(tb) |
|
|
|
@ -442,6 +464,12 @@ class TorrentClass(GenlistItemClass): |
|
|
|
|
_('Downloading'), _('Finished'), _('Seeding'), _('Allocating'), |
|
|
|
|
_('Checking resume data')) |
|
|
|
|
|
|
|
|
|
state_ic = ( |
|
|
|
|
"torrent-queued", "torrent-checking-files", |
|
|
|
|
"torrent-downloading-metadata", "torrent-downloading", |
|
|
|
|
"torrent-finished", "torrent-seeding", "torrent-allocating", |
|
|
|
|
"torrent-checking-resume-data") |
|
|
|
|
|
|
|
|
|
log = logging.getLogger("epour.gui.torrent_list") |
|
|
|
|
|
|
|
|
|
def __init__(self, session, *args, **kwargs): |
|
|
|
@ -460,62 +488,79 @@ class TorrentClass(GenlistItemClass): |
|
|
|
|
return '%s' % (torrent.status.name) |
|
|
|
|
elif part == "elm.text.sub": |
|
|
|
|
status = torrent.status |
|
|
|
|
qp = handle.queue_position() |
|
|
|
|
qp = status.queue_position |
|
|
|
|
if qp == -1: |
|
|
|
|
qp = "seeding" |
|
|
|
|
|
|
|
|
|
return _( |
|
|
|
|
"{0:.0%} complete, ETA: {1} " |
|
|
|
|
"(Down: {2}/s Up: {3}/s Queue pos: {4})").format( |
|
|
|
|
status.progress, |
|
|
|
|
timedelta(seconds=self.get_eta(status)), |
|
|
|
|
intrepr(status.download_payload_rate, precision=0), |
|
|
|
|
intrepr(status.upload_payload_rate, precision=0), |
|
|
|
|
qp) |
|
|
|
|
string = "" |
|
|
|
|
|
|
|
|
|
def content_get(self, obj, part, item_data): |
|
|
|
|
if part != "elm.swallow.icon": |
|
|
|
|
return |
|
|
|
|
eta = self.get_eta(status) |
|
|
|
|
|
|
|
|
|
torrent = item_data |
|
|
|
|
handle = torrent.handle |
|
|
|
|
if eta: |
|
|
|
|
# NOTE: Estimated Time of Arrival (time until the process is finished) |
|
|
|
|
string += _("ETA: {0} ").format(timedelta(seconds=eta)) |
|
|
|
|
|
|
|
|
|
if not handle.is_valid(): |
|
|
|
|
return |
|
|
|
|
if not status.is_seeding: |
|
|
|
|
string += _("Download: {0}/s ").format(intrepr(status.download_payload_rate, precision=0)) |
|
|
|
|
|
|
|
|
|
status = torrent.status |
|
|
|
|
state = torrent.state |
|
|
|
|
ic = Icon(obj) |
|
|
|
|
try: |
|
|
|
|
string += _("Upload: {0}/s ").format(intrepr(status.upload_payload_rate, precision=0)) |
|
|
|
|
|
|
|
|
|
string += _("Queue position: {0}").format(qp) |
|
|
|
|
|
|
|
|
|
return string |
|
|
|
|
|
|
|
|
|
def reusable_content_get(self, obj, part, item_data, old_content): |
|
|
|
|
if part == "elm.swallow.icon": |
|
|
|
|
torrent = item_data |
|
|
|
|
handle = torrent.handle |
|
|
|
|
|
|
|
|
|
if not handle.is_valid(): |
|
|
|
|
return |
|
|
|
|
|
|
|
|
|
state = torrent.state |
|
|
|
|
if old_content: |
|
|
|
|
ic = old_content |
|
|
|
|
else: |
|
|
|
|
ic = Image(obj) |
|
|
|
|
group = "states/" + self.state_ic[state] |
|
|
|
|
ic.file_set(theme_file, group) |
|
|
|
|
ic.tooltip_text_set(self.state_str[state]) |
|
|
|
|
ic.size_hint_aspect_set(EVAS_ASPECT_CONTROL_VERTICAL, 1, 1) |
|
|
|
|
return ic |
|
|
|
|
elif part == "elm.swallow.end": |
|
|
|
|
torrent = item_data |
|
|
|
|
handle = torrent.handle |
|
|
|
|
|
|
|
|
|
if not handle.is_valid(): |
|
|
|
|
return |
|
|
|
|
|
|
|
|
|
status = torrent.status |
|
|
|
|
if old_content: |
|
|
|
|
ic = old_content |
|
|
|
|
else: |
|
|
|
|
ic = Image(obj) |
|
|
|
|
group = "states/" |
|
|
|
|
if status.paused: |
|
|
|
|
try: |
|
|
|
|
ic.standard = "player_pause" |
|
|
|
|
except Exception: |
|
|
|
|
try: |
|
|
|
|
ic.standard = "media-playback-pause" |
|
|
|
|
except Exception: |
|
|
|
|
pass |
|
|
|
|
elif status.is_seeding: |
|
|
|
|
try: |
|
|
|
|
ic.standard = "up" |
|
|
|
|
except Exception: |
|
|
|
|
try: |
|
|
|
|
ic.standard = "arrow-up" |
|
|
|
|
except Exception: |
|
|
|
|
pass |
|
|
|
|
group += "torrent-paused" |
|
|
|
|
else: |
|
|
|
|
try: |
|
|
|
|
ic.standard = "down" |
|
|
|
|
except Exception: |
|
|
|
|
try: |
|
|
|
|
ic.standard = "arrow-down" |
|
|
|
|
except Exception: |
|
|
|
|
pass |
|
|
|
|
except RuntimeError: |
|
|
|
|
log.debug("Setting torrent ic failed") |
|
|
|
|
ic.tooltip_text_set(self.state_str[state]) |
|
|
|
|
ic.size_hint_aspect_set(EVAS_ASPECT_CONTROL_VERTICAL, 1, 1) |
|
|
|
|
return ic |
|
|
|
|
group += "torrent-active" |
|
|
|
|
ic.file_set(theme_file, group) |
|
|
|
|
return ic |
|
|
|
|
else: |
|
|
|
|
torrent = item_data |
|
|
|
|
handle = torrent.handle |
|
|
|
|
|
|
|
|
|
if not handle.is_valid(): |
|
|
|
|
return |
|
|
|
|
status = torrent.status |
|
|
|
|
if old_content: |
|
|
|
|
pb = old_content |
|
|
|
|
else: |
|
|
|
|
pb = Progressbar(obj) |
|
|
|
|
pb.style = "simple" |
|
|
|
|
pb.unit_format = None |
|
|
|
|
pb.value = status.progress |
|
|
|
|
return pb |
|
|
|
|
|
|
|
|
|
def get_eta(self, s): |
|
|
|
|
# if s.is_seeding and self.options["stop_at_ratio"]: |
|
|
|
@ -528,9 +573,12 @@ class TorrentClass(GenlistItemClass): |
|
|
|
|
# s.all_time_upload |
|
|
|
|
# ) / s.upload_payload_rate |
|
|
|
|
|
|
|
|
|
if s.download_payload_rate == 0: |
|
|
|
|
return 0 |
|
|
|
|
|
|
|
|
|
left = s.total_wanted - s.total_wanted_done |
|
|
|
|
|
|
|
|
|
if left <= 0 or s.download_payload_rate == 0: |
|
|
|
|
if left <= 0: |
|
|
|
|
return 0 |
|
|
|
|
|
|
|
|
|
eta = int(round(left / s.download_payload_rate)) |
|
|
|
|