lots of new preference work

This commit is contained in:
Nick 2011-02-15 18:55:27 +01:00
parent 4a071ecba1
commit 8a9e732f95
4 changed files with 403 additions and 39 deletions

View File

@ -331,11 +331,21 @@ class AllTorrents(BaseMode):
td = TorrentDetail(self,tid,self.stdscr,self.encoding)
component.get("ConsoleUI").set_mode(td)
def show_preferences(self, core_config):
component.stop(["AllTorrentsStateUpdater"])
self.stdscr.clear()
prefs = Preferences(self,core_config,self.stdscr,self.encoding)
component.get("ConsoleUI").set_mode(prefs)
def show_preferences(self):
def _on_get_config(config):
client.core.get_listen_port().addCallback(_on_get_listen_port,config)
def _on_get_listen_port(port,config):
client.core.get_cache_status().addCallback(_on_get_cache_status,port,config)
def _on_get_cache_status(status,port,config):
component.stop(["AllTorrentsStateUpdater"])
self.stdscr.clear()
prefs = Preferences(self,config,port,status,self.stdscr,self.encoding)
component.get("ConsoleUI").set_mode(prefs)
client.core.get_config().addCallback(_on_get_config)
def __show_events(self):
component.stop(["AllTorrentsStateUpdater"])
@ -619,7 +629,7 @@ class AllTorrents(BaseMode):
for l in HELP_LINES:
self.popup.add_line(l)
elif chr(c) == 'p':
client.core.get_config().addCallback(self.show_preferences)
self.show_preferences()
return
elif chr(c) == 'e':
self.__show_events()

View File

@ -49,6 +49,7 @@ from popup import Popup
log = logging.getLogger(__name__)
class InputField:
depend = None
# render the input. return number of rows taken up
def render(self,screen,row,width,selected,col=1):
return 0
@ -61,6 +62,20 @@ class InputField:
def set_value(self, value):
pass
def set_depend(self,i,inverse=False):
if not isinstance(i,CheckedInput):
raise Exception("Can only depend on CheckedInputs")
self.depend = i
self.inverse = inverse
def depend_skip(self):
if not self.depend:
return False
if self.inverse:
return self.depend.checked
else:
return not self.depend.checked
class CheckedInput(InputField):
def __init__(self, parent, message, name, checked=False):
self.parent = parent
@ -92,6 +107,71 @@ class CheckedInput(InputField):
def set_value(self, c):
self.checked = c
class CheckedPlusInput(InputField):
def __init__(self, parent, message, name, child,checked=False):
self.parent = parent
self.chkd_inact = "[X] %s"%message
self.unchkd_inact = "[ ] %s"%message
self.chkd_act = "[{!black,white,bold!}X{!white,black!}] %s"%message
self.unchkd_act = "[{!black,white,bold!} {!white,black!}] %s"%message
self.name = name
self.checked = checked
self.msglen = len(self.chkd_inact)+1
self.child = child
self.child_active = False
def render(self, screen, row, width, active, col=1):
isact = active and not self.child_active
if self.checked and isact:
self.parent.add_string(row,self.chkd_act,screen,col,False,True)
elif self.checked:
self.parent.add_string(row,self.chkd_inact,screen,col,False,True)
elif isact:
self.parent.add_string(row,self.unchkd_act,screen,col,False,True)
else:
self.parent.add_string(row,self.unchkd_inact,screen,col,False,True)
if active and self.checked and self.child_active:
self.parent.add_string(row+1,"(esc to leave)",screen,col,False,True)
elif active and self.checked:
self.parent.add_string(row+1,"(right arrow to edit)",screen,col,False,True)
rows = 2
# show child
if self.checked:
if isinstance(self.child,(TextInput,IntSpinInput,FloatSpinInput)):
crows = self.child.render(screen,row,width-self.msglen,self.child_active and active,col+self.msglen,self.msglen)
else:
crows = self.child.render(screen,row,width-self.msglen,self.child_active and active,col+self.msglen)
rows = max(rows,crows)
else:
self.parent.add_string(row,"(enable to view/edit value)",screen,col+self.msglen,False,True)
return rows
def handle_read(self, c):
if self.child_active:
if c == 27: # leave child on esc
self.child_active = False
return
# pass keys through to child
self.child.handle_read(c)
else:
if c == 32:
self.checked = not self.checked
if c == curses.KEY_RIGHT:
self.child_active = True
def get_value(self):
return self.checked
def set_value(self, c):
self.checked = c
def get_child(self):
return self.child
class IntSpinInput(InputField):
def __init__(self, parent, message, name, move_func, value, min_val, max_val):
self.parent = parent
@ -106,7 +186,7 @@ class IntSpinInput(InputField):
self.min_val = min_val
self.max_val = max_val
def render(self, screen, row, width, active, col=1):
def render(self, screen, row, width, active, col=1, cursor_offset=0):
if not active and not self.valstr:
self.value = self.initvalue
self.valstr = "%d"%self.value
@ -119,7 +199,7 @@ class IntSpinInput(InputField):
self.parent.add_string(row,"%s [ %d ]"%(self.message,self.value),screen,col,False,True)
if active:
self.move_func(row,self.cursor+self.cursoff)
self.move_func(row,self.cursor+self.cursoff+cursor_offset)
return 1
@ -166,6 +246,112 @@ class IntSpinInput(InputField):
self.valstr = "%d"%self.value
self.cursor = len(self.valstr)
class FloatSpinInput(InputField):
def __init__(self, parent, message, name, move_func, value, inc_amt, precision, min_val, max_val):
self.parent = parent
self.message = message
self.name = name
self.precision = precision
self.inc_amt = inc_amt
self.value = round(float(value),self.precision)
self.initvalue = self.value
self.fmt = "%%.%df"%precision
self.valstr = self.fmt%self.value
self.cursor = len(self.valstr)
self.cursoff = len(self.message)+4 # + 4 for the " [ " in the rendered string
self.move_func = move_func
self.min_val = min_val
self.max_val = max_val
self.need_update = False
def render(self, screen, row, width, active, col=1, cursor_offset=0):
if not active and not self.valstr:
self.value = self.initvalue
self.valstr = self.fmt%self.value
self.cursor = len(self.valstr)
if not active and self.need_update:
self.value = round(float(self.valstr),self.precision)
self.valstr = self.fmt%self.value
self.cursor = len(self.valstr)
if not self.valstr:
self.parent.add_string(row,"%s [ ]"%self.message,screen,col,False,True)
elif active:
self.parent.add_string(row,"%s [ {!black,white,bold!}%s{!white,black!} ]"%(self.message,self.valstr),screen,col,False,True)
else:
self.parent.add_string(row,"%s [ %s ]"%(self.message,self.valstr),screen,col,False,True)
if active:
self.move_func(row,self.cursor+self.cursoff+cursor_offset)
return 1
def handle_read(self, c):
if c == curses.KEY_PPAGE:
self.value+=self.inc_amt
self.valstr = self.fmt%self.value
self.cursor = len(self.valstr)
elif c == curses.KEY_NPAGE:
self.value-=self.inc_amt
self.valstr = self.fmt%self.value
self.cursor = len(self.valstr)
elif c == curses.KEY_LEFT:
self.cursor = max(0,self.cursor-1)
elif c == curses.KEY_RIGHT:
self.cursor = min(len(self.valstr),self.cursor+1)
elif c == curses.KEY_HOME:
self.cursor = 0
elif c == curses.KEY_END:
self.cursor = len(self.value)
elif c == curses.KEY_BACKSPACE or c == 127:
if self.valstr and self.cursor > 0:
self.valstr = self.valstr[:self.cursor - 1] + self.valstr[self.cursor:]
self.cursor-=1
self.need_update = True
elif c == curses.KEY_DC:
if self.valstr and self.cursor < len(self.valstr):
self.valstr = self.valstr[:self.cursor] + self.valstr[self.cursor+1:]
self.need_update = True
elif c == 45 and self.cursor == 0 and self.min_val < 0:
minus_place = self.valstr.find('-')
if minus_place >= 0: return
self.valstr = chr(c)+self.valstr
self.cursor += 1
self.need_update = True
elif c == 46:
minus_place = self.valstr.find('-')
if self.cursor <= minus_place: return
point_place = self.valstr.find('.')
if point_place >= 0: return
if self.cursor == len(self.valstr):
self.valstr += chr(c)
else:
# Insert into string
self.valstr = self.valstr[:self.cursor] + chr(c) + self.valstr[self.cursor:]
self.need_update = True
# Move the cursor forward
self.cursor+=1
elif (c > 47 and c < 58):
minus_place = self.valstr.find('-')
if self.cursor <= minus_place: return
if self.cursor == len(self.valstr):
self.valstr += chr(c)
else:
# Insert into string
self.valstr = self.valstr[:self.cursor] + chr(c) + self.valstr[self.cursor:]
self.need_update = True
# Move the cursor forward
self.cursor+=1
def get_value(self):
return self.value
def set_value(self, val):
self.value = round(float(val),self.precision)
self.valstr = self.fmt%self.value
self.cursor = len(self.valstr)
class SelectInput(InputField):
def __init__(self, parent, message, name, opts, vals, selidx):
self.parent = parent
@ -225,23 +411,28 @@ class TextInput(InputField):
self.opts = None
self.opt_off = 0
def render(self,screen,row,width,selected,col=1):
def render(self,screen,row,width,selected,col=1,cursor_offset=0):
if self.message:
self.parent.add_string(row,self.message,screen,col,False,True)
row += 1
if selected:
if self.opts:
self.parent.add_string(row+2,self.opts[self.opt_off:],screen,col,False,True)
self.parent.add_string(row+1,self.opts[self.opt_off:],screen,col,False,True)
if self.cursor > (width-3):
self.move_func(row+1,width-2)
self.move_func(row,width-2)
else:
self.move_func(row+1,self.cursor+1)
self.parent.add_string(row,self.message,screen,col,False,True)
self.move_func(row,self.cursor+1+cursor_offset)
slen = len(self.value)+3
if slen > width:
vstr = self.value[(slen-width):]
else:
vstr = self.value.ljust(width-2)
self.parent.add_string(row+1,"{!black,white,bold!}%s"%vstr,screen,col,False,False)
self.parent.add_string(row,"{!black,white,bold!}%s"%vstr,screen,col,False,False)
return 3
if self.message:
return 3
else:
return 2
def get_value(self):
return self.value

View File

@ -33,7 +33,7 @@
#
#
from deluge.ui.console.modes.input_popup import TextInput,SelectInput,CheckedInput,IntSpinInput
from deluge.ui.console.modes.input_popup import TextInput,SelectInput,CheckedInput,IntSpinInput,FloatSpinInput,CheckedPlusInput
try:
import curses
@ -44,12 +44,17 @@ import logging
log = logging.getLogger(__name__)
class Header:
class NoInput:
def depend_skip(self):
return False
class Header(NoInput):
def __init__(self, parent, header, space_above, space_below):
self.parent = parent
self.header = "{!white,black,bold!}%s"%header
self.space_above = space_above
self.space_below = space_below
self.name = header
def render(self, screen, row, width, active, offset):
rows = 1
@ -60,6 +65,24 @@ class Header:
if self.space_below: rows += 1
return rows
class InfoField(NoInput):
def __init__(self,parent,label,value,name):
self.parent = parent
self.label = label
self.value = value
self.txt = "%s %s"%(label,value)
self.name = name
def render(self, screen, row, width, active, offset):
self.parent.add_string(row,self.txt,screen,offset-1,False,True)
return 1
def set_value(self, v):
self.value = v
if type(v) == float:
self.txt = "%s %.2f"%(self.label,self.value)
else:
self.txt = "%s %s"%(self.label,self.value)
class BasePane:
def __init__(self, offset, parent, width):
@ -75,26 +98,45 @@ class BasePane:
def add_config_values(self,conf_dict):
for ipt in self.inputs:
if not isinstance(ipt,Header):
conf_dict[ipt.name] = ipt.get_value()
if not isinstance(ipt,NoInput):
# gross, have to special case in/out ports since they are tuples
if ipt.name in ("listen_ports_to","listen_ports_from",
"out_ports_from","out_ports_to"):
if ipt.name == "listen_ports_to":
conf_dict["listen_ports"] = (self.infrom.get_value(),self.into.get_value())
if ipt.name == "out_ports_to":
conf_dict["outgoing_ports"] = (self.outfrom.get_value(),self.outto.get_value())
else:
conf_dict[ipt.name] = ipt.get_value()
if hasattr(ipt,"get_child"):
c = ipt.get_child()
conf_dict[c.name] = c.get_value()
def update_values(self, conf_dict):
for ipt in self.inputs:
if not isinstance(ipt,Header):
if not isinstance(ipt,NoInput):
try:
ipt.set_value(conf_dict[ipt.name])
except KeyError: # just ignore if it's not in dict
pass
if hasattr(ipt,"get_child"):
try:
c = ipt.get_child()
c.set_value(conf_dict[c.name])
except KeyError: # just ignore if it's not in dict
pass
def render(self, mode, screen, width, active):
self._cursor_row = -1
if self.active_input < 0:
for i,ipt in enumerate(self.inputs):
if not isinstance(ipt,Header):
if not isinstance(ipt,NoInput):
self.active_input = i
break
crow = 1
for i,ipt in enumerate(self.inputs):
if ipt.depend_skip():
continue
act = active and i==self.active_input
crow += ipt.render(screen,crow,width, act, self.offset)
@ -104,6 +146,8 @@ class BasePane:
else:
curses.curs_set(0)
return crow
# just handles setting the active input
def handle_read(self,c):
if not self.inputs: # no inputs added yet
@ -111,18 +155,20 @@ class BasePane:
if c == curses.KEY_UP:
nc = max(0,self.active_input-1)
while isinstance(self.inputs[nc], Header):
while isinstance(self.inputs[nc], NoInput) or self.inputs[nc].depend_skip():
nc-=1
if nc <= 0: break
if not isinstance(self.inputs[nc], Header):
if not isinstance(self.inputs[nc], NoInput) or self.inputs[nc].depend_skip():
self.active_input = nc
elif c == curses.KEY_DOWN:
ilen = len(self.inputs)
nc = min(self.active_input+1,ilen-1)
while isinstance(self.inputs[nc], Header):
while isinstance(self.inputs[nc], NoInput) or self.inputs[nc].depend_skip():
nc+=1
if nc >= ilen: break
if not isinstance(self.inputs[nc], Header):
if nc >= ilen:
nc-=1
break
if not isinstance(self.inputs[nc], NoInput) or self.inputs[nc].depend_skip():
self.active_input = nc
else:
self.inputs[self.active_input].handle_read(c)
@ -131,6 +177,9 @@ class BasePane:
def add_header(self, header, space_above=False, space_below=False):
self.inputs.append(Header(self.parent, header, space_above, space_below))
def add_info_field(self, label, value, name):
self.inputs.append(InfoField(self.parent, label, value, name))
def add_text_input(self, name, msg, dflt_val):
self.inputs.append(TextInput(self.parent,self.move,self.width,msg,name,dflt_val,False))
@ -140,9 +189,15 @@ class BasePane:
def add_checked_input(self, name, message, checked):
self.inputs.append(CheckedInput(self.parent,message,name,checked))
def add_checkedplus_input(self, name, message, child, checked):
self.inputs.append(CheckedPlusInput(self.parent,message,name,child,checked))
def add_int_spin_input(self, name, message, value, min_val, max_val):
self.inputs.append(IntSpinInput(self.parent,message,name,self.move,value,min_val,max_val))
def add_float_spin_input(self, name, message, value, inc_amt, precision, min_val, max_val):
self.inputs.append(FloatSpinInput(self.parent,message,name,self.move,value,inc_amt,precision,min_val,max_val))
class DownloadsPane(BasePane):
def __init__(self, offset, parent, width):
@ -150,13 +205,21 @@ class DownloadsPane(BasePane):
self.add_header("Folders")
self.add_text_input("download_location","Download To:",parent.core_config["download_location"])
self.add_header("Allocation")
cmptxt = TextInput(self.parent,self.move,self.width,None,"move_completed_path",parent.core_config["move_completed_path"],False)
self.add_checkedplus_input("move_completed","Move completed to:",cmptxt,parent.core_config["move_completed"])
autotxt = TextInput(self.parent,self.move,self.width,None,"autoadd_location",parent.core_config["autoadd_location"],False)
self.add_checkedplus_input("autoadd_enable","Auto add .torrents from:",autotxt,parent.core_config["autoadd_enable"])
copytxt = TextInput(self.parent,self.move,self.width,None,"torrentfiles_location",parent.core_config["torrentfiles_location"],False)
self.add_checkedplus_input("copy_torrent_file","Copy of .torrent files to:",copytxt,parent.core_config["copy_torrent_file"])
self.add_checked_input("del_copy_torrent_file","Delete copy of torrent file on remove",parent.core_config["del_copy_torrent_file"])
self.add_header("Allocation",True)
if parent.core_config["compact_allocation"]:
alloc_idx = 1
else:
alloc_idx = 0
self.add_select_input("compact_allocation","Allocation:",["Use Full Allocation","Use Compact Allocation"],[False,True],alloc_idx)
self.add_select_input("compact_allocation",None,["Use Full Allocation","Use Compact Allocation"],[False,True],alloc_idx)
self.add_header("Options",True)
self.add_checked_input("prioritize_first_last_pieces","Prioritize first and last pieces of torrent",parent.core_config["prioritize_first_last_pieces"])
self.add_checked_input("add_paused","Add torrents in paused state",parent.core_config["add_paused"])
@ -165,35 +228,91 @@ class DownloadsPane(BasePane):
class NetworkPane(BasePane):
def __init__(self, offset, parent, width):
BasePane.__init__(self,offset,parent,width)
self.add_header("Incomming Ports")
inrand = CheckedInput(parent,"Use Random Ports Active Port: %d"%parent.active_port,"random_port",parent.core_config["random_port"])
self.inputs.append(inrand)
listen_ports = parent.core_config["listen_ports"]
self.infrom = IntSpinInput(self.parent," From:","listen_ports_from",self.move,listen_ports[0],0,65535)
self.infrom.set_depend(inrand,True)
self.into = IntSpinInput(self.parent," To: ","listen_ports_to",self.move,listen_ports[1],0,65535)
self.into.set_depend(inrand,True)
self.inputs.append(self.infrom)
self.inputs.append(self.into)
self.add_header("Outgoing Ports",True)
outrand = CheckedInput(parent,"Use Random Ports","random_outgoing_ports",parent.core_config["random_outgoing_ports"])
self.inputs.append(outrand)
out_ports = parent.core_config["outgoing_ports"]
self.outfrom = IntSpinInput(self.parent," From:","out_ports_from",self.move,out_ports[0],0,65535)
self.outfrom.set_depend(outrand,True)
self.outto = IntSpinInput(self.parent," To: ","out_ports_to",self.move,out_ports[1],0,65535)
self.outto.set_depend(outrand,True)
self.inputs.append(self.outfrom)
self.inputs.append(self.outto)
self.add_header("Interface",True)
self.add_text_input("listen_interface","IP address of the interface to listen on (leave empty for default):",parent.core_config["listen_interface"])
self.add_header("TOS",True)
self.add_text_input("peer_tos","Peer TOS Byte:",parent.core_config["peer_tos"])
self.add_header("Network Extras")
self.add_checked_input("upnp","UPnP",parent.core_config["upnp"])
self.add_checked_input("natpmp","NAT-PMP",parent.core_config["natpmp"])
self.add_checked_input("utpex","Peer Exchange",parent.core_config["utpex"])
self.add_checked_input("lsd","LSD",parent.core_config["lsd"])
self.add_checked_input("dht","DHT",parent.core_config["dht"])
self.add_header("Encryption",True)
self.add_select_input("enc_in_policy","Inbound:",["Forced","Enabled","Disabled"],[0,1,2],parent.core_config["enc_in_policy"])
self.add_select_input("enc_out_policy","Outbound:",["Forced","Enabled","Disabled"],[0,1,2],parent.core_config["enc_out_policy"])
self.add_select_input("enc_level","Level:",["Handshake","Full Stream","Either"],[0,1,2],parent.core_config["enc_level"])
self.add_checked_input("enc_prefer_rc4","Encrypt Entire Stream",parent.core_config["enc_prefer_rc4"])
class BandwidthPane(BasePane):
def __init__(self, offset, parent, width):
BasePane.__init__(self,offset,parent,width)
self.add_header("Global Bandwidth Usage")
self.add_int_spin_input("max_connections_global","Maximum Connections:",parent.core_config["max_connections_global"],0,1000)
self.add_int_spin_input("max_upload_slots_global","Maximum Upload Slots:",parent.core_config["max_upload_slots_global"],0,1000)
#self.add_int_spin_input("max_download_speed","Maximum Download Speed (KiB/s):",-1,0,1000)
self.add_int_spin_input("max_connections_global","Maximum Connections:",parent.core_config["max_connections_global"],-1,9000)
self.add_int_spin_input("max_upload_slots_global","Maximum Upload Slots:",parent.core_config["max_upload_slots_global"],-1,9000)
self.add_float_spin_input("max_download_speed","Maximum Download Speed (KiB/s):",parent.core_config["max_download_speed"],1.0,1,-1.0,60000.0)
self.add_float_spin_input("max_upload_speed","Maximum Upload Speed (KiB/s):",parent.core_config["max_upload_speed"],1.0,1,-1.0,60000.0)
self.add_int_spin_input("max_half_open_connections","Maximum Half-Open Connections:",parent.core_config["max_half_open_connections"],-1,9999)
self.add_int_spin_input("max_connections_per_second","Maximum Connection Attempts per Second:",parent.core_config["max_connections_per_second"],-1,9999)
self.add_checked_input("ignore_limits_on_local_network","Ignore limits on local network",parent.core_config["ignore_limits_on_local_network"])
self.add_checked_input("rate_limit_ip_overhead","Rate Limit IP Overhead",parent.core_config["rate_limit_ip_overhead"])
self.add_header("Per Torrent Bandwidth Usage",True)
self.add_int_spin_input("max_connections_per_torrent","Maximum Connections:",parent.core_config["max_connections_per_torrent"],-1,9000)
self.add_int_spin_input("max_upload_slots_per_torrent","Maximum Upload Slots:",parent.core_config["max_upload_slots_per_torrent"],-1,9000)
self.add_float_spin_input("max_download_speed_per_torrent","Maximum Download Speed (KiB/s):",parent.core_config["max_download_speed_per_torrent"],1.0,1,-1.0,60000.0)
self.add_float_spin_input("max_upload_speed_per_torrent","Maximum Upload Speed (KiB/s):",parent.core_config["max_upload_speed_per_torrent"],1.0,1,-1.0,60000.0)
class InterfacePane(BasePane):
def __init__(self, offset, parent, width):
BasePane.__init__(self,offset,parent,width)
# does classic mode make sense in console?
#self.add_header("Classic Mode")
#self.add_checked_input("classic_mode","Enable",False)
self.add_header("Interface Settings Comming Soon")
# add title bar control here
class OtherPane(BasePane):
def __init__(self, offset, parent, width):
BasePane.__init__(self,offset,parent,width)
self.add_header("GeoIP Database")
self.add_header("System Information")
self.add_info_field(" Help us improve Deluge by sending us your","","")
self.add_info_field(" Python version, PyGTK version, OS and processor","","")
self.add_info_field(" types. Absolutely no other information is sent.","","")
self.add_checked_input("send_info","Yes, please send anonymous statistics.",parent.core_config["send_info"])
self.add_header("GeoIP Database",True)
self.add_text_input("geoip_db_location","Location:",parent.core_config["geoip_db_location"])
class DaemonPane(BasePane):
def __init__(self, offset, parent, width):
BasePane.__init__(self,offset,parent,width)
self.add_header("Port")
self.add_int_spin_input("daemon_port","Daemon Port:",parent.core_config["daemon_port"],0,1000)
self.add_int_spin_input("daemon_port","Daemon Port:",parent.core_config["daemon_port"],0,65535)
self.add_header("Connections",True)
self.add_checked_input("allow_remote","Allow remote connections",parent.core_config["allow_remote"])
self.add_header("Other",True)
@ -202,11 +321,50 @@ class DaemonPane(BasePane):
class QueuePane(BasePane):
def __init__(self, offset, parent, width):
BasePane.__init__(self,offset,parent,width)
self.add_header("General")
self.add_checked_input("queue_new_to_top","Queue new torrents to top",parent.core_config["queue_new_to_top"])
self.add_header("Active Torrents",True)
self.add_int_spin_input("max_active_limit","Total active:",parent.core_config["max_active_limit"],-1,9999)
self.add_int_spin_input("max_active_downloading","Total active downloading:",parent.core_config["max_active_downloading"],-1,9999)
self.add_int_spin_input("max_active_seeding","Total active seeding:",parent.core_config["max_active_seeding"],-1,9999)
self.add_checked_input("dont_count_slow_torrents","Do not count slow torrents",parent.core_config["dont_count_slow_torrents"])
self.add_header("Seeding",True)
self.add_float_spin_input("share_ratio_limit","Share Ratio Limit:",parent.core_config["share_ratio_limit"],1.0,2,-1.0,100.0)
self.add_float_spin_input("seed_time_ratio_limit","Share Time Ratio:",parent.core_config["seed_time_ratio_limit"],1.0,2,-1.0,100.0)
self.add_int_spin_input("seed_time_limit","Seed time (m):",parent.core_config["seed_time_limit"],-1,10000)
seedratio = FloatSpinInput(self.parent,"","stop_seed_ratio",self.move,parent.core_config["stop_seed_ratio"],0.1,2,0.5,100.0)
self.add_checkedplus_input("stop_seed_at_ratio","Stop seeding when share ratio reaches:",seedratio,parent.core_config["stop_seed_at_ratio"])
self.add_checked_input("remove_seed_at_ratio","Remove torrent when share ratio reached",parent.core_config["remove_seed_at_ratio"])
class ProxyPane(BasePane):
def __init__(self, offset, parent, width):
BasePane.__init__(self,offset,parent,width)
self.add_header("Proxy Settings Comming Soon")
class CachePane(BasePane):
def __init__(self, offset, parent, width):
BasePane.__init__(self,offset,parent,width)
self.add_header("Settings")
self.add_int_spin_input("cache_size","Cache Size (16 KiB blocks):",parent.core_config["cache_size"],0,99999)
self.add_int_spin_input("cache_expiry","Cache Expiry (seconds):",parent.core_config["cache_expiry"],1,32000)
self.add_header("Status (press 'r' to refresh status)",True)
self.add_header(" Write")
self.add_info_field(" Blocks Written:",self.parent.status["blocks_written"],"blocks_written")
self.add_info_field(" Writes:",self.parent.status["writes"],"writes")
self.add_info_field(" Write Cache Hit Ratio:","%.2f"%self.parent.status["write_hit_ratio"],"write_hit_ratio")
self.add_header(" Read")
self.add_info_field(" Blocks Read:",self.parent.status["blocks_read"],"blocks_read")
self.add_info_field(" Blocks Read hit:",self.parent.status["blocks_read_hit"],"blocks_read_hit")
self.add_info_field(" Reads:",self.parent.status["reads"],"reads")
self.add_info_field(" Read Cache Hit Ratio:","%.2f"%self.parent.status["read_hit_ratio"],"read_hit_ratio")
self.add_header(" Size")
self.add_info_field(" Cache Size:",self.parent.status["cache_size"],"cache_size")
self.add_info_field(" Read Cache Size:",self.parent.status["read_cache_size"],"read_cache_size")
def update_cache_status(self, status):
for ipt in self.inputs:
if isinstance(ipt,InfoField):
try:
ipt.set_value(status[ipt.name])
except KeyError:
pass

View File

@ -59,7 +59,7 @@ class ZONE:
ACTIONS = 2
class Preferences(BaseMode):
def __init__(self, parent_mode, core_config, stdscr, encoding=None):
def __init__(self, parent_mode, core_config, active_port, status, stdscr, encoding=None):
self.parent_mode = parent_mode
self.categories = [_("Downloads"), _("Network"), _("Bandwidth"),
_("Interface"), _("Other"), _("Daemon"), _("Queue"), _("Proxy"),
@ -70,6 +70,8 @@ class Preferences(BaseMode):
self.action_input = None
self.core_config = core_config
self.active_port = active_port
self.status = status
self.active_zone = ZONE.CATEGORIES
@ -220,6 +222,9 @@ class Preferences(BaseMode):
if self.active_zone < ZONE.CATEGORIES:
self.active_zone = ZONE.ACTIONS
elif c == 114 and isinstance(self.panes[self.cur_cat],CachePane):
client.core.get_cache_status().addCallback(self.panes[self.cur_cat].update_cache_status)
else:
if self.active_zone == ZONE.CATEGORIES:
self.__category_read(c)