Compare commits
4 Commits
e6f09eb5f2
...
012c27255f
Author | SHA1 | Date |
---|---|---|
multiSnow | 012c27255f | |
multiSnow | 4f57cb763f | |
multiSnow | f9a9dde09c | |
multiSnow | ce44436091 |
|
@ -69,6 +69,8 @@ def validate(conf):
|
|||
# user_interface
|
||||
assert isinstance(conf.user_interface.cache,int),\
|
||||
f'wrong type for user_interface.cache: {user_interface.cache!r}'
|
||||
assert isinstance(conf.user_interface.numsort,bool),\
|
||||
f'wrong type for user_interface.numsort: {conf.user_interface.numsort!r}'
|
||||
assert conf.user_interface.cache>-1,\
|
||||
f'user_interface.cache should not be negative: {conf.user_interface.cache}'
|
||||
assert isinstance(conf.user_interface.usepage,bool),\
|
||||
|
|
|
@ -41,6 +41,8 @@ apng = true
|
|||
[user_interface]
|
||||
# amount of decoded image to keep as cache, 0 to disable cache
|
||||
cache = 0
|
||||
# whether using numeric sort (('a1', 'a10', 'a2') => ('a1', 'a2', 'a10'))
|
||||
numsort = false
|
||||
# start with showing page
|
||||
usepage = false
|
||||
# start with showing double image in canvas mode
|
||||
|
|
|
@ -184,12 +184,12 @@ def _writelog(epoch,ns,pid,ismt,level,levelcolor,target,usecolor,buf,blank):
|
|||
|
||||
def _recvfrompipe(pipe,append,args):
|
||||
try:
|
||||
if not (data:=pipe.recv_bytes()):
|
||||
pipe.send_bytes(b'')
|
||||
if (data:=pipe.recv_bytes())==b'stop':
|
||||
pipe.send_bytes(b'stop')
|
||||
return True
|
||||
except Exception as e:
|
||||
print('pipe failed',file=stderr)
|
||||
print(''.join(format_exception(e)),file=stderr)
|
||||
# print('pipe failed',file=stderr)
|
||||
# print(''.join(format_exception(e)),file=stderr)
|
||||
return True
|
||||
epoch,ns,pid,ismt,error=unpack(LOGHDRFMT,data[:LOGHDRFMTLEN])
|
||||
logfnerr,logfnerr_usecolor,logfnout,logfnout_usecolor=args
|
||||
|
@ -237,7 +237,14 @@ def _logloop(pipes,config,*,interval=1):
|
|||
sort=buf.sort
|
||||
clear=buf.clear
|
||||
while pipes:
|
||||
if not (conns:=waitpipe(pipes,timeout=interval)):
|
||||
try:
|
||||
if not (conns:=waitpipe(pipes,timeout=interval)):continue
|
||||
except Exception as exc:
|
||||
# print(f'wait failed {exc!r}',file=stderr)
|
||||
# remove closed pipe
|
||||
closed_pipes=set(pipe for pipe in pipes if pipe.closed)
|
||||
pipes-=closed_pipes
|
||||
closed_pipes.clear()
|
||||
continue
|
||||
for pipe in conns:
|
||||
while pipe.poll():
|
||||
|
@ -272,9 +279,12 @@ def log(modulename,*args,exc=None,devel=False,level='log',levelcolor=None,error=
|
|||
return True
|
||||
|
||||
def logend():
|
||||
_pipe.send_bytes(b'')
|
||||
_pipe.recv_bytes()
|
||||
with _pipe:
|
||||
_pipe.send_bytes(b'stop')
|
||||
_pipe.recv_bytes()
|
||||
if _locker is not None:
|
||||
for recver in _recvers:
|
||||
recver.close()
|
||||
with _locker:pass
|
||||
return True
|
||||
|
||||
|
|
|
@ -22,12 +22,14 @@ from .constants import progname
|
|||
__all__=[
|
||||
'str2bytes','bytes2str','packstr','unpackstr',
|
||||
'prettybytes','prettypath','prettycolor','prettyrect',
|
||||
'sorter_numeric',
|
||||
]
|
||||
|
||||
_LENFMT='<Q'
|
||||
_LENLEN=calcsize(_LENFMT)
|
||||
|
||||
_printable=tuple(ord(c) for c in f'{ascii_letters}{digits}')
|
||||
_nums=f'{digits}.'
|
||||
|
||||
def str2bytes(s):
|
||||
return s.encode('utf8') if isinstance(s,str) else s
|
||||
|
@ -65,6 +67,39 @@ def prettycolor(color):
|
|||
def prettyrect(rect):
|
||||
return '{2}x{3}+{0}+{1}'.format(*rect)
|
||||
|
||||
def sorter_numeric(s):
|
||||
parts=s.split('/')
|
||||
results=[]
|
||||
b,_,e=parts[-1].rpartition('.')
|
||||
if b and e.strip(_nums):
|
||||
parts[-1:]=[b,e]
|
||||
else:
|
||||
parts.append('')
|
||||
while parts[:-1]:
|
||||
results.append([])
|
||||
part=parts.pop(0)
|
||||
while part.endswith('.'):
|
||||
part=part[:-1]
|
||||
parts[0]=f'.{parts[0]}'
|
||||
while part:
|
||||
try:
|
||||
start=min(part.index(s) for s in digits if s in part)
|
||||
except ValueError:
|
||||
results[-1].append((part,0))
|
||||
break
|
||||
head,part=part[:start],part[start:]
|
||||
if head:
|
||||
results[-1].append((head,0))
|
||||
tail=part.lstrip(_nums)
|
||||
nstr,part=part[:len(part)-len(tail)],tail
|
||||
while nstr.endswith('.'):
|
||||
nstr=nstr[:-1]
|
||||
part=f'.{part}'
|
||||
results[-1].append(('',float(nstr)))
|
||||
results[-1].append(('',0))
|
||||
results.append([(parts.pop(),0)])
|
||||
return results
|
||||
|
||||
def _logger_init():
|
||||
from functools import partial
|
||||
from os import environ
|
||||
|
|
|
@ -17,6 +17,13 @@ from ..co import OrderedDict
|
|||
|
||||
__all__=['Containers']
|
||||
|
||||
def _relocate(lst,pos,step):
|
||||
# change from current position with step from pos in lst, return new position
|
||||
assert isinstance(step,int)
|
||||
if not (lst and step):return 0
|
||||
pos+=step
|
||||
return min(max(0,pos),len(lst)-1)
|
||||
|
||||
class Containers(OrderedDict):
|
||||
|
||||
__slots__=(
|
||||
|
@ -42,13 +49,6 @@ class Containers(OrderedDict):
|
|||
filenames.sort(key=self.sortkey,reverse=self.revsort)
|
||||
self._fnpos=self[container].index(filename)
|
||||
|
||||
def _relocate(self,lst,pos,step):
|
||||
# change from current position with step from pos in lst, return new position
|
||||
assert isinstance(step,int)
|
||||
if not step:return
|
||||
pos+=step
|
||||
return min(max(0,pos),len(lst)-1)
|
||||
|
||||
@property
|
||||
def sortkey(self):
|
||||
# 'key' argument that used in sorting filenames
|
||||
|
@ -106,13 +106,12 @@ class Containers(OrderedDict):
|
|||
assert isinstance(step,int)
|
||||
if not step:return
|
||||
oldpos=self._fnpos
|
||||
while True:
|
||||
try:
|
||||
self._fnpos=self._relocate(self.getvalue(self._pos),self._fnpos,step)
|
||||
break
|
||||
except IndexError:
|
||||
if not self.cross(-1):
|
||||
return False
|
||||
try:
|
||||
filenames=self.getvalue(self._pos)
|
||||
except IndexError:
|
||||
return self.cross(-1)
|
||||
else:
|
||||
self._fnpos=_relocate(filenames,self._fnpos,step)
|
||||
return self._fnpos!=oldpos
|
||||
|
||||
def cross(self,step=1,/):
|
||||
|
|
|
@ -67,7 +67,8 @@ class ENV(NonWidget):
|
|||
self._thumbnails={}
|
||||
# {container:[pathname, ...], ...}
|
||||
# any method on _containers should be locked by _containerlock
|
||||
self._containers=Containers()
|
||||
self._containers=Containers(
|
||||
key=sorter_numeric if config.user_interface.numsort else None)
|
||||
# [(target,args,kwds), ...]
|
||||
# any method on _actions should be in mainthread
|
||||
self._actions=[]
|
||||
|
@ -517,7 +518,8 @@ class ENV(NonWidget):
|
|||
path=unpackstr(data)
|
||||
scene_id,loop_count=args
|
||||
if scene_id!=self.get_scene_id() or not self.is_in_scene(path):
|
||||
assert note(__name__,f'{self}: anime stop',prettypath(*path))
|
||||
assert note(__name__,f'{self}: anime stop',
|
||||
prettypath(*path))
|
||||
self._animes.discard(path)
|
||||
return
|
||||
if (canvas:=self.getcanvas(path)) is None:
|
||||
|
@ -531,8 +533,9 @@ class ENV(NonWidget):
|
|||
self._animes.discard(path)
|
||||
return
|
||||
self.runactions()
|
||||
start_new_thread(self.update_anime,
|
||||
(path,scene_id,loop_count,canvas.current_delay()))
|
||||
start_new_thread(
|
||||
self.update_anime,
|
||||
(path,scene_id,loop_count,canvas.current_delay()))
|
||||
case SDLE_EvEmu.SDL_SDLUI_MOTIONCONTINUE:
|
||||
x,y,motion_id=args
|
||||
if motion_id!=self._motion_id:
|
||||
|
@ -542,7 +545,8 @@ class ENV(NonWidget):
|
|||
assert verb(__name__,f'{self}: motion interrupted at edge')
|
||||
self._motion_id=None
|
||||
else:
|
||||
self.puttask(SDL_SDLUI,SDL_SDLUI_MOTIONCONTINUE,(x,y,motion_id))
|
||||
self.puttask(SDL_SDLUI,SDL_SDLUI_MOTIONCONTINUE,
|
||||
(x,y,motion_id))
|
||||
case SDLE_EvEmu.SDL_TEXTINPUT|SDLE_EvEmu.SDL_TEXTEDITING:
|
||||
pass # ignore
|
||||
case _ as evtype:
|
||||
|
@ -712,7 +716,8 @@ class ENV(NonWidget):
|
|||
self._inrequire.add(('thumbnail',key))
|
||||
if canvas:
|
||||
self._inrequire.add(('canvas',key))
|
||||
self.listener.speak('load' if canvas else 'thum',*key,b'T' if cutin else b'')
|
||||
self.listener.speak('load' if canvas else 'thum',*key,
|
||||
b'T' if cutin else b'')
|
||||
def cancelrequire(self,key,is_canvas=True,/):
|
||||
with self._inrequirelock:
|
||||
if not self._inrequire:
|
||||
|
|
Loading…
Reference in New Issue