Add torrent status info to torrent props

torrent props is now a window instead of inwin
This commit is contained in:
Kai Huuhko 2014-07-08 09:54:24 +03:00
parent cab124ca29
commit e02a0186a0
3 changed files with 203 additions and 55 deletions

10
TODO
View File

@ -8,14 +8,14 @@ Torrent-handle controls/options:
☐ Torrent properties ☐ Torrent properties
./epour/gui/TorrentProps.py ./epour/gui/TorrentProps.py
☐ save_path() move_storage() ☐ save_path() move_storage()
☐ super_seeding() (status.super_seeding) ✔ super_seeding() (status.super_seeding) @done (09:49 08.07.2014)
? ?
☐ set_upload_limit() set_download_limit() upload_limit() download_limit() ☐ set_upload_limit() set_download_limit() upload_limit() download_limit()
set_sequential_download() (status.sequential_download) set_sequential_download() (status.sequential_download) @done (09:49 08.07.2014)
? ?
☐ set_upload_mode() (status.upload_mode) ✔ set_upload_mode() (status.upload_mode) @done (09:49 08.07.2014)
? ?
☐ set_share_mode() (status.share_mode) ✔ set_share_mode() (status.share_mode) @done (09:49 08.07.2014)
? ?
☐ apply_ip_filter() (status.ip_filter_applies) ☐ apply_ip_filter() (status.ip_filter_applies)
☐ set_tracker_login() ☐ set_tracker_login()
@ -33,7 +33,7 @@ Torrent-handle controls/options:
☐ set_ssl_certificate() ☐ set_ssl_certificate()
Torrent status info: Torrent status info:
http://libtorrent.org/reference-Core.html#torrent_status http://libtorrent.org/reference-Core.html#torrent_status
☐ Torrent properties ✔ Torrent properties @done (09:49 08.07.2014)
./epour/gui/TorrentProps.py ./epour/gui/TorrentProps.py
Add Torrent-dialog: Add Torrent-dialog:
✔ Use dicts to hold torrent info between sessions. @done (15:57 30.06.2014) ✔ Use dicts to hold torrent info between sessions. @done (15:57 30.06.2014)

View File

@ -23,6 +23,7 @@ import cgi
import sys import sys
import os import os
import pipes import pipes
from datetime import datetime, timedelta
import logging import logging
log = logging.getLogger("epour") log = logging.getLogger("epour")
@ -33,7 +34,6 @@ from efl.evas import EVAS_HINT_EXPAND, EVAS_HINT_FILL
from efl.elementary.genlist import Genlist, GenlistItemClass, \ from efl.elementary.genlist import Genlist, GenlistItemClass, \
ELM_GENLIST_ITEM_NONE, ELM_GENLIST_ITEM_TREE, ELM_GENLIST_ITEM_FIELD_TEXT ELM_GENLIST_ITEM_NONE, ELM_GENLIST_ITEM_TREE, ELM_GENLIST_ITEM_FIELD_TEXT
from efl.elementary.window import StandardWindow from efl.elementary.window import StandardWindow
from efl.elementary.innerwindow import InnerWindow
from efl.elementary.button import Button from efl.elementary.button import Button
from efl.elementary.box import Box from efl.elementary.box import Box
from efl.elementary.check import Check from efl.elementary.check import Check
@ -43,6 +43,11 @@ from efl.elementary.frame import Frame
from efl.elementary.object import ELM_SEL_FORMAT_TEXT, \ from efl.elementary.object import ELM_SEL_FORMAT_TEXT, \
ELM_SEL_TYPE_CLIPBOARD ELM_SEL_TYPE_CLIPBOARD
from efl.elementary.table import Table from efl.elementary.table import Table
from efl.elementary.progressbar import Progressbar
from efl.elementary.configuration import Configuration
elm_conf = Configuration()
SCALE = elm_conf.scale
from efl.elementary.scroller import Scroller
from intrepr import intrepr from intrepr import intrepr
from Widgets import Information from Widgets import Information
@ -52,6 +57,7 @@ EXPAND_HORIZ = EVAS_HINT_EXPAND, 0.0
FILL_BOTH = EVAS_HINT_FILL, EVAS_HINT_FILL FILL_BOTH = EVAS_HINT_FILL, EVAS_HINT_FILL
FILL_HORIZ = EVAS_HINT_FILL, 0.5 FILL_HORIZ = EVAS_HINT_FILL, 0.5
ALIGN_LEFT = 0.0, 0.5 ALIGN_LEFT = 0.0, 0.5
ALIGN_RIGHT = 1.0, 0.5
from collections import defaultdict from collections import defaultdict
@ -105,48 +111,60 @@ def attach(branch, file_entry, n, trunk):
attach(others, file_entry, n, trunk[node]) attach(others, file_entry, n, trunk[node])
class TorrentProps(InnerWindow): class TorrentProps(StandardWindow):
def __init__(self, parent, h):
def __init__(self, h):
if not h.is_valid(): if not h.is_valid():
Information(parent.win, "Invalid torrent handle.") Information(self, "Invalid torrent handle.")
return return
InnerWindow.__init__(self, parent) StandardWindow.__init__(
self, "epour", "Epour - %s" % (h.name()),
size=(SCALE * 480, SCALE * 320),
autodel=True
)
box = Box(self) scroller = Scroller(self)
box.size_hint_align = FILL_BOTH self.resize_object_add(scroller)
box.size_hint_weight = EXPAND_BOTH
tname = Label(self) box = Box(self, size_hint_weight=EXPAND_BOTH)
tname.size_hint_align = FILL_HORIZ
tname.line_wrap = ELM_WRAP_CHAR scroller.content = box
tname.ellipsis = True
tname = Label(
self, size_hint_align=FILL_HORIZ, line_wrap=ELM_WRAP_CHAR,
ellipsis=True, scale=2.0
)
tname.text = "{}".format(cgi.escape(h.name())) tname.text = "{}".format(cgi.escape(h.name()))
tname.scale = 2.0
tname.show() tname.show()
box.pack_end(tname) box.pack_end(tname)
if h.has_metadata(): if h.has_metadata():
ti = TorrentInfo(self, h, size_hint_align=FILL_HORIZ) f = Frame(self, text="Torrent info", size_hint_align=FILL_HORIZ)
box.pack_end(ti) ti = TorrentInfo(f, h, size_hint_align=FILL_HORIZ)
f.content = ti
box.pack_end(f)
ti.show() ti.show()
f.show()
f = Frame(self, text="Torrent status", size_hint_align=FILL_HORIZ)
ts = TorrentStatus(f, h, size_hint_align=FILL_HORIZ)
f.content = ts
box.pack_end(f)
ts.show()
f.show()
magnet_uri = lt.make_magnet_uri(h) magnet_uri = lt.make_magnet_uri(h)
f = Frame(self) f = Frame(self, size_hint_align=FILL_HORIZ, text="Magnet URI")
f.size_hint_align = FILL_HORIZ me_box = Box(f, horizontal=True)
f.text = "Magnet URI" me = Entry(
me_box = Box(f) me_box, size_hint_align=FILL_HORIZ, size_hint_weight=EXPAND_HORIZ,
me_box.horizontal = True editable=False, entry=magnet_uri, line_wrap=ELM_WRAP_CHAR
me = Entry(me_box) )
me.size_hint_align = FILL_HORIZ
me.size_hint_weight = EXPAND_HORIZ
me.editable = False
me.entry = magnet_uri
me_box.pack_end(me) me_box.pack_end(me)
me.show() me.show()
me_btn = Button(me_box) me_btn = Button(me_box, text="Copy")
me_btn.text = "Copy"
me_btn.callback_clicked_add( me_btn.callback_clicked_add(
lambda x: me.top_widget.cnp_selection_set( lambda x: me.top_widget.cnp_selection_set(
ELM_SEL_TYPE_CLIPBOARD, ELM_SEL_FORMAT_TEXT, me.text ELM_SEL_TYPE_CLIPBOARD, ELM_SEL_FORMAT_TEXT, me.text
@ -159,16 +177,13 @@ class TorrentProps(InnerWindow):
f.show() f.show()
box.pack_end(f) box.pack_end(f)
xbtn = Button(box) xbtn = Button(box, text="Close")
xbtn.text_set("Close")
xbtn.callback_clicked_add(lambda x: self.delete()) xbtn.callback_clicked_add(lambda x: self.delete())
box.pack_end(xbtn) box.pack_end(xbtn)
xbtn.show() xbtn.show()
box.show() box.show()
scroller.show()
self.content = box
self.activate()
class TorrentFiles(StandardWindow): class TorrentFiles(StandardWindow):
@ -177,9 +192,9 @@ class TorrentFiles(StandardWindow):
self, self,
"epour", "epour",
"Epour - Files for torrent: %s" % (h.name()), "Epour - Files for torrent: %s" % (h.name()),
size=(600, 400) size=(SCALE * 480, SCALE * 320),
autodel=True
) )
self.callback_delete_request_add(lambda x: self.delete())
box = Box(self, size_hint_weight=EXPAND_BOTH) box = Box(self, size_hint_weight=EXPAND_BOTH)
self.resize_object_add(box) self.resize_object_add(box)
@ -328,19 +343,13 @@ class TorrentFiles(StandardWindow):
os.startfile(path) os.startfile(path)
class TorrentInfo(Frame): class TorrentInfo(Box):
def __init__(self, parent, h, *args, **kwargs): def __init__(self, parent, h, *args, **kwargs):
Frame.__init__(self, parent, *args, **kwargs) Box.__init__(self, parent, *args, **kwargs)
self.text = "Torrent info"
info = h.get_torrent_info() info = h.get_torrent_info()
box = Box(self, size_hint_weight=EXPAND_HORIZ) table = Table(self, homogeneous=True, size_hint_align=FILL_HORIZ)
self.content = box
box.show()
table = Table(box, homogeneous=True, size_hint_align=FILL_HORIZ)
i = 0 i = 0
for func in info.comment, info.creation_date, info.creator: for func in info.comment, info.creation_date, info.creator:
@ -371,14 +380,153 @@ class TorrentInfo(Frame):
tpriv.disabled = True tpriv.disabled = True
tpriv.state = info.priv() tpriv.state = info.priv()
fl_btn = Button(box, size_hint_align=ALIGN_LEFT) fl_btn = Button(self, size_hint_align=ALIGN_LEFT)
fl_btn.text = "Files ->" fl_btn.text = "Files ->"
fl_btn.callback_clicked_add(lambda x: TorrentFiles(h)) fl_btn.callback_clicked_add(lambda x: TorrentFiles(h))
box.pack_end(table) self.pack_end(table)
box.pack_end(tpriv) self.pack_end(tpriv)
box.pack_end(fl_btn) self.pack_end(fl_btn)
table.show() table.show()
tpriv.show() tpriv.show()
fl_btn.show() fl_btn.show()
class TorrentStatus(Table):
state_str = (
'Queued', 'Checking', 'Downloading metadata', 'Downloading',
'Finished', 'Seeding', 'Allocating', 'Checking resume data'
)
ignored_keys = (
"progress_ppm", "distributed_copies", "states", "auto_managed"
)
byte_values = (
"all_time_download", "all_time_upload", "block_size", "total_done",
"total_wanted", "total_wanted_done", "total_failed_bytes",
"total_payload_download", "total_payload_upload", "total_download",
"total_upload", "total_redundant_bytes"
)
byte_transfer_values = (
"download_rate", "download_payload_rate", "upload_rate",
"upload_payload_rate"
)
check_enabled = (
"super_seeding"
)
check_enabled_prefixed = (
"sequential_download", "upload_mode", "share_mode"
)
timedelta_values = (
"active_time", "seeding_time", "time_since_download",
"time_since_upload", "finished_time"
)
datetime_values = (
"added_time", "last_seen_complete", "completed_time"
)
def __init__(self, parent, h, *args, **kwargs):
Table.__init__(self, parent, *args, **kwargs)
s = h.status()
self.widgets = []
for i, k in enumerate(dir(s)):
if k.startswith("__") or k in self.ignored_keys:
continue
try:
v = getattr(s, k)
except Exception as e:
log.debug(e)
continue
v = self.convert_value(k, v)
w = None
if k == "state":
pass
elif isinstance(v, lt.torrent_status.states):
continue
elif isinstance(v, list):
continue # TODO
elif k == "progress":
w = Progressbar(self)
w.size_hint_align = FILL_HORIZ
elif isinstance(v, bool):
w = Check(self)
w.size_hint_align = ALIGN_RIGHT
if k in self.check_enabled:
setter = getattr(h, k)
w.callback_changed_add(lambda x: setter(x.state))
elif k in self.check_enabled_prefixed:
setter = getattr(h, "set_" + k)
w.callback_changed_add(lambda x: setter(x.state))
else:
w.disabled = True
if not w:
try:
w = Label(self)
w.size_hint_align = ALIGN_RIGHT
except Exception as e:
log.debug(e)
continue
w.data["key"] = k
self.populate(w, v)
self.widgets.append(w)
l = Label(self)
l.size_hint_align = ALIGN_LEFT
l.text = str(k).replace("_", " ").capitalize()
self.pack(l, 0, i, 1, 1)
l.show()
self.pack(w, 1, i, 1, 1)
w.show()
def update():
s = h.status()
for w in self.widgets:
key = w.data["key"]
v = self.convert_value(key, getattr(s, key))
self.populate(w, v)
ecore.Timer(5.0, update)
@staticmethod
def populate(w, v):
if isinstance(w, Label):
w.text = str(v)
elif isinstance(w, Check):
w.state = v
elif isinstance(w, Progressbar):
w.value = v
def convert_value(self, k, v):
if k == "state":
v = str(v).replace("_", " ").capitalize()
elif k in self.datetime_values:
v = datetime.fromtimestamp(v)
elif k in self.timedelta_values:
v = timedelta(seconds=v)
elif isinstance(v, list):
pass
elif isinstance(v, lt.storage_mode_t):
v = str(v).replace("_", " ").capitalize()
elif isinstance(v, (int, long, basestring)):
if k in self.byte_values:
v = intrepr(v)
if k in self.byte_transfer_values:
v = intrepr(v) + "/s"
return v

View File

@ -383,10 +383,10 @@ class SessionStatus(Table):
class TorrentClass(GenlistItemClass): class TorrentClass(GenlistItemClass):
state_str = [ state_str = (
'Queued', 'Checking', 'Downloading metadata', 'Downloading', 'Queued', 'Checking', 'Downloading metadata', 'Downloading',
'Finished', 'Seeding', 'Allocating', 'Checking resume data' 'Finished', 'Seeding', 'Allocating', 'Checking resume data'
] )
log = logging.getLogger("epour.gui.torrent_list") log = logging.getLogger("epour.gui.torrent_list")
@ -569,7 +569,7 @@ class ItemMenu(Menu):
def torrent_props_cb(self, menu, item, h): def torrent_props_cb(self, menu, item, h):
from TorrentProps import TorrentProps from TorrentProps import TorrentProps
TorrentProps(self.top_widget, h) TorrentProps(h).show()
class TorrentTooltip(Table): class TorrentTooltip(Table):