Add torrent status info to torrent props
torrent props is now a window instead of inwin
This commit is contained in:
parent
cab124ca29
commit
e02a0186a0
10
TODO
10
TODO
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
|
|
Loading…
Reference in New Issue