bugfix
This commit is contained in:
parent
4a9de787c7
commit
3580406e13
@ -170,9 +170,13 @@ class Text(Label):
|
||||
if self.bgcolor:
|
||||
self.color = self.bgcolor
|
||||
|
||||
def resize(self, size):
|
||||
def resize(self, *args):
|
||||
if not self.size_hint_y:
|
||||
self.width = size[0]
|
||||
ps = [0,0,0,0]
|
||||
if hasattr(self.parent,'padding'):
|
||||
ps = self.parent.padding
|
||||
|
||||
self.width = self.parent.width - ps[0] - ps[2]
|
||||
self.set_widget_height()
|
||||
|
||||
def set_widget_height(self, *args):
|
||||
|
@ -1,31 +1,29 @@
|
||||
from kivy.logger import Logger
|
||||
from kivy.graphics import Color, Rectangle, RoundedRectangle
|
||||
from kivy.properties import ListProperty
|
||||
from kivy.properties import ListProperty, NumericProperty
|
||||
from .color_definitions import getColors
|
||||
|
||||
_logcnt = 0
|
||||
class BGColorBehavior(object):
|
||||
def __init__(self, color_level=-1,radius=[],**kwargs):
|
||||
if color_level==-1:
|
||||
color_level = 0
|
||||
self.color_level = color_level
|
||||
color_level=NumericProperty(0)
|
||||
radius = ListProperty([])
|
||||
def __init__(self, **kwargs):
|
||||
self.bg_ready = False
|
||||
self.radius = radius
|
||||
self.bgcolor = []
|
||||
self.fgcolor = []
|
||||
fg,bg= getColors(color_level)
|
||||
fg,bg= getColors(self.color_level)
|
||||
self.fgcolor = fg
|
||||
self.bgcolor = bg
|
||||
self.normal_bgcolor = bg
|
||||
self.normal_fgcolor = fg
|
||||
fg,bg= getColors(color_level,selected=True)
|
||||
fg,bg= getColors(self.color_level,selected=True)
|
||||
self.selected_bgcolor = bg
|
||||
self.selected_fgcolor = fg
|
||||
# self.on_bgcolor()
|
||||
|
||||
self.bind(size=self.onSize_bgcolor_behavior,
|
||||
pos=self.onSize_bgcolor_behavior)
|
||||
self.bind(children=self.on_bgcolor)
|
||||
# self.bind(children=self.on_bgcolor)
|
||||
|
||||
def onSize_bgcolor_behavior(self,o,v=None):
|
||||
if not hasattr(self,'rect'):
|
||||
|
@ -42,6 +42,12 @@ class ServerInfo:
|
||||
self.publickey = None
|
||||
self.authCode = None
|
||||
|
||||
def realurl(url):
|
||||
if url.startswith('https://') or url.startswith('http://'):
|
||||
return url
|
||||
config = getConfig()
|
||||
return '%s%s' % (config.uihome, url)
|
||||
|
||||
def getServerPK(self):
|
||||
config = getConfig()
|
||||
url = '%s%s' % (config.uihome, config.publickey_url)
|
||||
|
@ -2,9 +2,11 @@ from kivy.properties import StringProperty, NumericProperty, ListProperty
|
||||
from kivy.factory import Factory
|
||||
from kivy.clock import Clock
|
||||
from kivy.logger import Logger
|
||||
from kivy.uix.scrollview import ScrollView
|
||||
from kivy.uix.label import Label
|
||||
from kivy.uix.image import AsyncImage
|
||||
|
||||
from .baseWidget import ScrollWidget, getDataHandler, CSize
|
||||
from .baseWidget import ScrollWidget, getDataHandler, VBox
|
||||
from .utils import CSize
|
||||
import re
|
||||
|
||||
@ -16,7 +18,7 @@ LINK_LEAD = "["
|
||||
REFER_SPLIT = "]("
|
||||
REFER_END = ")"
|
||||
|
||||
class MarkDownParser(object):
|
||||
class MarkdownParser(object):
|
||||
mdkeys = [
|
||||
SOURCE_DELIMITER,
|
||||
VIDEO_LEAD,
|
||||
@ -34,10 +36,13 @@ class MarkDownParser(object):
|
||||
IMAGE_LEAD:self.lead_image,
|
||||
}
|
||||
|
||||
def handle_source_delimiter(self,mdtext):
|
||||
def handle_source_delimiter(self):
|
||||
x = self.mdtext.split(SOURCE_DELIMITER,1)
|
||||
mk_p = MarkDownParser(x[0])
|
||||
self.result += mk_p.parse()
|
||||
mk_p = MarkdownParser(x[0])
|
||||
d = {
|
||||
'source':x[0]
|
||||
}
|
||||
self.result.append(d)
|
||||
if len(x) > 1:
|
||||
self.mdtext = x[1]
|
||||
|
||||
@ -67,12 +72,12 @@ class MarkDownParser(object):
|
||||
def lead_audio(self):
|
||||
x = self.mdtext.split(REFER_SPLIT,1)
|
||||
if len(x)<2:
|
||||
self.text = f'{VIDEO_LEAD}'
|
||||
self.text = f'{AUDIO_LEAD}'
|
||||
return
|
||||
title = x[0]
|
||||
y = x[1].split(REFER_END,1)
|
||||
if len(y) < 2:
|
||||
self.text = f'{VIDEO_LEAD}'
|
||||
self.text = f'{AUDIO_LEAD}'
|
||||
return
|
||||
url = y[0]
|
||||
d = {
|
||||
@ -88,12 +93,12 @@ class MarkDownParser(object):
|
||||
def lead_image(self):
|
||||
x = self.mdtext.split(REFER_SPLIT,1)
|
||||
if len(x)<2:
|
||||
self.text = f'{VIDEO_LEAD}'
|
||||
self.text = f'{IMAGE_LEAD}'
|
||||
return
|
||||
title = x[0]
|
||||
y = x[1].split(REFER_END,1)
|
||||
if len(y) < 2:
|
||||
self.text = f'{VIDEO_LEAD}'
|
||||
self.text = f'{IMAGE_LEAD}'
|
||||
return
|
||||
url = y[0]
|
||||
d = {
|
||||
@ -144,39 +149,37 @@ class MDImage(AsyncImage):
|
||||
def image_loaded(self,o, *args):
|
||||
self.image_size = self.texture.size
|
||||
|
||||
def resize(self, size):
|
||||
self.parent_width = size[0]
|
||||
Logger.info('MDImage: resize called, size=%s', size)
|
||||
def resize(self, *args):
|
||||
ps = [0,0,0,0]
|
||||
if hasattr(self.parent, 'padding'):
|
||||
ps = self.parent.padding
|
||||
self.parent_width = self.parent.width - ps[0] - ps[2]
|
||||
if self.texture:
|
||||
if self.texture.size:
|
||||
self.image_size = self.texture.size
|
||||
Logger.info('MDImage:resize called, %d', self.parent_width)
|
||||
|
||||
def on_image_size(self, *args):
|
||||
if self.parent_width:
|
||||
self.set_new_height()
|
||||
Logger.info('MDImage:on_iage_size %d, %s', self.parent_width,
|
||||
self.image_size)
|
||||
self.set_image_size()
|
||||
|
||||
def on_parent_width(self, *args):
|
||||
if self.image_size:
|
||||
self.set_new_height()
|
||||
Logger.info('MDImage:on_oarent_width %d, %s', self.parent_width,
|
||||
self.image_size)
|
||||
self.set_image_size()
|
||||
|
||||
def set_new_height(self):
|
||||
def set_image_size(self):
|
||||
self.width = self.parent_width
|
||||
self.height = self.parent_width * self.image_size[1] \
|
||||
/ self.image_size[0]
|
||||
Logger.info('MDImage: set_new_height called, size=%s', self.size)
|
||||
|
||||
Logger.info('MDImage:set_image_size %d, %d', self.width,
|
||||
self.height)
|
||||
|
||||
class Markdown(ScrollWidget):
|
||||
"""
|
||||
# Markdown
|
||||
MArkdown widget using to render a markdown file and show it
|
||||
description file format
|
||||
{
|
||||
"widgettype":"Markdown",
|
||||
"options":{
|
||||
"source": the markdown file
|
||||
other options
|
||||
}
|
||||
}
|
||||
"""
|
||||
source = StringProperty(None)
|
||||
def __init__(self, **kw):
|
||||
class MarkdownBody(VBox):
|
||||
def __init__(self, md_obj=None, padding=[10,10,10,10], **kw):
|
||||
self.part_handlers = {
|
||||
"pure_md":self.build_pure_md,
|
||||
"source":self.build_source,
|
||||
@ -184,14 +187,45 @@ description file format
|
||||
"video":self.build_video,
|
||||
"audio":self.build_audio
|
||||
}
|
||||
ScrollWidget.__init__(self, **kw)
|
||||
self.bind(source=self.load_text)
|
||||
if self.source:
|
||||
Clock.schedule_once(self.load_text, 0.3)
|
||||
self.bind(size=self.setChildMinWidth)
|
||||
self.md_obj = md_obj
|
||||
super().__init__(**kw)
|
||||
self.padding=padding
|
||||
self.size_hint = None,None
|
||||
self.bind(parent=self.resize)
|
||||
self.resize()
|
||||
|
||||
def show_mdtext(self, mdtext):
|
||||
mdp = MarkdownParser(mdtext)
|
||||
parts = mdp.parse()
|
||||
self.clear_widgets()
|
||||
for p in parts:
|
||||
for k,v in p.items():
|
||||
f = self.part_handlers.get(k)
|
||||
f(v)
|
||||
|
||||
def resize(self, *args):
|
||||
Logger.info('MDBody:resize called')
|
||||
if self.parent:
|
||||
ps = [0,0,0,0]
|
||||
if hasattr(self.parent, 'padding'):
|
||||
ps = self.parent.padding
|
||||
h = 0
|
||||
for c in self.children:
|
||||
if hasattr(c, 'resize'):
|
||||
c.resize()
|
||||
h += c.height
|
||||
self.width = self.parent.width - ps[0] - ps[2]
|
||||
self.height = h
|
||||
else:
|
||||
Logger.info('resize:parent is null')
|
||||
|
||||
def build_source(self,source_desc):
|
||||
pass
|
||||
color_level = self.color_level+1
|
||||
w = MarkdownBody(md_obj=self.md_obj,
|
||||
color_level=color_level,size_hint_y=None)
|
||||
w.show_mdtext(source_desc)
|
||||
self.add_widget(w)
|
||||
w.resize()
|
||||
|
||||
def build_pure_md(self, mdtext):
|
||||
for l in mdtext.split('\n'):
|
||||
@ -206,7 +240,7 @@ description file format
|
||||
)
|
||||
|
||||
self.add_widget(w)
|
||||
w.resize(self.size)
|
||||
w.resize()
|
||||
|
||||
def build_video(self, video_desc):
|
||||
w = Factory.NewVideo(source=video_desc['url'],
|
||||
@ -225,45 +259,13 @@ description file format
|
||||
w.bind(on_enter_focus=f1)
|
||||
w.bind(on_leave_focus=f2)
|
||||
self.add_widget(w)
|
||||
w.resize(self.size)
|
||||
w.resize()
|
||||
|
||||
def build_audio(self, audio_desc):
|
||||
w = Factory.APlayer(source=audio_desc.url)
|
||||
w.bind(minimum_height=w.setter('height'))
|
||||
self.add_widget(w)
|
||||
|
||||
def setChildMinWidth(self, *args):
|
||||
print('size changed')
|
||||
for i,c in enumerate(self._inner.children):
|
||||
c.width = self.width
|
||||
if hasattr(c, 'resize'):
|
||||
c.resize(self.size)
|
||||
|
||||
def load_text(self, *args):
|
||||
print('source fired, hahaha', *args)
|
||||
self.clear_widgets()
|
||||
h = getDataHandler(self.source)
|
||||
h.bind(on_success=self.update)
|
||||
h.bind(on_error=self.show_error)
|
||||
h.handle()
|
||||
|
||||
def show_error(self, o, e):
|
||||
print('load_text(), error=',e)
|
||||
|
||||
def update(self, o, text):
|
||||
print('text=',text, type(text))
|
||||
if not text:
|
||||
return
|
||||
text = ''.join(text.split('\r'))
|
||||
mdp = MarkDownParser(text)
|
||||
parts = mdp.parse()
|
||||
for p in parts:
|
||||
for k,v in p.items():
|
||||
print('part=', k, v)
|
||||
f = self.part_handlers.get(k)
|
||||
f(v)
|
||||
|
||||
|
||||
def parse_title(self, txt, level):
|
||||
w = Factory.Blocks().widgetBuild({
|
||||
"widgettype":f"Title{level}",
|
||||
@ -285,8 +287,7 @@ description file format
|
||||
if h1 is None or h1 < clen:
|
||||
h1 = clen
|
||||
w.height = h1
|
||||
w.bind(on_ref_press=self.open_new_md)
|
||||
# w.bind(minimum_height=w.setter('height'))
|
||||
w.bind(on_ref_press=self.md_obj.open_new_md)
|
||||
self.add_widget(w)
|
||||
|
||||
def parse_line(self, l):
|
||||
@ -328,14 +329,9 @@ description file format
|
||||
if h is None or h < clen:
|
||||
h = clen
|
||||
w.height = h
|
||||
w.bind(on_ref_press=self.open_new_md)
|
||||
# w.bind(minimum_height=w.setter('height'))
|
||||
w.bind(on_ref_press=self.md_obj.open_new_md)
|
||||
self.add_widget(w)
|
||||
|
||||
def open_new_md(self, o, value):
|
||||
print(value,'is it a link')
|
||||
self.source = value
|
||||
|
||||
def mktext2bbtext(self,mdtext):
|
||||
"""
|
||||
convert markdown text to bbtag text kivy Label Widget recognized
|
||||
@ -379,3 +375,63 @@ description file format
|
||||
mdtext)
|
||||
|
||||
return mdtext
|
||||
|
||||
|
||||
class Markdown(ScrollView):
|
||||
"""
|
||||
# Markdown
|
||||
MArkdown widget using to render a markdown file and show it
|
||||
description file format
|
||||
{
|
||||
"widgettype":"Markdown",
|
||||
"options":{
|
||||
"source": the markdown file
|
||||
other options
|
||||
}
|
||||
}
|
||||
"""
|
||||
source = StringProperty(None)
|
||||
|
||||
def __init__(self, color_level=0, **kw):
|
||||
self.color_level = color_level
|
||||
ScrollView.__init__(self, **kw)
|
||||
self.root_body = MarkdownBody(md_obj=self,
|
||||
color_level=color_level,
|
||||
size_hint_y=None
|
||||
)
|
||||
self.root_body.bind(minimum_height=self.root_body.setter('height'))
|
||||
self.add_widget(self.root_body)
|
||||
if self.source:
|
||||
self.load_text()
|
||||
self.bind(size=self.root_body.resize)
|
||||
self.bind(source=self.load_text)
|
||||
# Clock.schedule_interval(self.check_parent_window, 1)
|
||||
|
||||
def check_parent_window(self, *args):
|
||||
pw = self.get_parent_window()
|
||||
rw = self.get_root_window()
|
||||
print('MD: pw=%s,rw=%s', pw,rw)
|
||||
|
||||
def stop_media(self, *args):
|
||||
self.root_body.stp_video()
|
||||
|
||||
def load_text(self, *args):
|
||||
h = getDataHandler(self.source)
|
||||
h.bind(on_success=self.update)
|
||||
h.bind(on_error=self.show_error)
|
||||
h.handle()
|
||||
|
||||
def show_error(self, o, e):
|
||||
print('load_text(), error=',e)
|
||||
|
||||
def update(self, o, text):
|
||||
print('text=',text, type(text))
|
||||
if not text:
|
||||
return
|
||||
text = ''.join(text.split('\r'))
|
||||
self.root_body.show_mdtext(text)
|
||||
self.scroll_y = 1
|
||||
|
||||
def open_new_md(self, o, value):
|
||||
print(value,'is it a link')
|
||||
self.source = value
|
||||
|
@ -29,18 +29,23 @@ class NewVideo(BGColorBehavior, Video):
|
||||
self.register_event_type('on_enter_focus')
|
||||
self.register_event_type('on_load_success')
|
||||
self.bind(source=self.record_start_time)
|
||||
self.bind(loaded=self.on_video_loaded)
|
||||
self.load_status = None
|
||||
Clock.schedule_interval(self.check_focus,0.2)
|
||||
|
||||
def on_enter_focus(self, v=None):
|
||||
Logger.info('NewView: enter focus')
|
||||
Logger.info('NewVideo: enter focus')
|
||||
|
||||
def on_leave_focus(self, v=None):
|
||||
Logger.info('NewView: leave focus')
|
||||
Logger.info('NewVideo: leave focus')
|
||||
|
||||
def check_focus(self,*args):
|
||||
if not self.parent:
|
||||
self.center_screen = False
|
||||
return
|
||||
if not self.get_root_window():
|
||||
self.center_screen = False
|
||||
|
||||
w = self.parent
|
||||
pos = w.to_widget(*Window.center)
|
||||
if self.collide_point(*pos):
|
||||
@ -54,39 +59,39 @@ class NewVideo(BGColorBehavior, Video):
|
||||
else:
|
||||
self.dispatch('on_leave_focus')
|
||||
|
||||
def resize(self, size):
|
||||
def resize(self, *args):
|
||||
v_size = self.get_video_size()
|
||||
if v_size:
|
||||
self.height = self.width * v_size[1] / v_size[0]
|
||||
|
||||
def on_load_success(self, *args):
|
||||
Logger.info('NewVideo: pn_load_success fired, %s', args)
|
||||
pass
|
||||
|
||||
def record_start_time(self, *args):
|
||||
self.start_time = time.time()
|
||||
self.load_status = 'start'
|
||||
Logger.info('NewVideo: record_start_time() called %s',self.load_status)
|
||||
|
||||
def on_open_failed(self, source, x=None):
|
||||
Logger.error(f'NewVideo: source={self.source} open failed')
|
||||
self.load_status = 'failed'
|
||||
|
||||
def ffplayerLog(self, msg, level):
|
||||
"""
|
||||
if 'Connection to tcp' in msg and 'failed' in msg:
|
||||
self.dispatch('on_open_failed', self.source)
|
||||
self.dispatch('on_open_failed', msg)
|
||||
if 'Invalid data found when processing input' in msg:
|
||||
self.dispatch('on_open_failed', self.source)
|
||||
self.dispatch('on_open_failed', msg)
|
||||
if 'Http error 403' in msg:
|
||||
self.dispatch('on_open_failed', msg)
|
||||
if 'End of file' in msg:
|
||||
self.dispatch('on_open_failed', self.source)
|
||||
self.dispatch('on_open_failed', msg)
|
||||
if 'I/O error' in msg:
|
||||
self.dispatch('on_open_failed', self.source)
|
||||
if 'Server returned 404 Not Found' in msg:
|
||||
self.dispatch('on_open_failed', self.source)
|
||||
"""
|
||||
self.dispatch('on_open_failed', msg)
|
||||
if 'Server returned 4' in msg:
|
||||
self.dispatch('on_open_failed', self.source)
|
||||
self.dispatch('on_open_failed', msg)
|
||||
if 'Server returned 5' in msg:
|
||||
self.dispatch('on_open_failed', self.source)
|
||||
self.dispatch('on_open_failed', msg)
|
||||
|
||||
msg = msg.strip()
|
||||
if msg:
|
||||
@ -108,18 +113,22 @@ class NewVideo(BGColorBehavior, Video):
|
||||
else:
|
||||
Logger.error('NewVideo: _video has not _ffplayer, do nothong')
|
||||
|
||||
def on_video_loaded(self, *args):
|
||||
Logger.info('NewVideo: status=%s, load_status=%s', self.state,
|
||||
self.load_status)
|
||||
if self.load_status == 'start':
|
||||
self.load_status = 'success'
|
||||
t = time.time()
|
||||
self.dispatch('on_load_success',
|
||||
{
|
||||
'source':self.source,
|
||||
'time':int((t - self.start_time)*100)
|
||||
})
|
||||
|
||||
|
||||
def on_state(self,*args):
|
||||
super().on_state(*args)
|
||||
if self.state == 'play':
|
||||
if self.load_status == 'start':
|
||||
self.load_status = 'success'
|
||||
t = time.time()
|
||||
self.dispatch('on_load_success',
|
||||
{
|
||||
'source':self.source,
|
||||
'time':int((t - self.start_time)*100)
|
||||
})
|
||||
|
||||
Window.allow_screensaver = False
|
||||
else:
|
||||
Window.allow_screensaver = True
|
||||
|
@ -1,27 +1,39 @@
|
||||
from kivy.uix.popup import Popup
|
||||
from kivy.clock import Clock
|
||||
from kivy.uix.boxlayout import BoxLayout
|
||||
from kivy.uix.textinput import TextInput
|
||||
from appPublic.Singleton import SingletonDecorator
|
||||
|
||||
@SingletonDecorator
|
||||
class Messager:
|
||||
def __init__(self):
|
||||
def __init__(self, show_time=0):
|
||||
self.show_time = show_time
|
||||
self.time_task = None
|
||||
self.w = Popup(content=BoxLayout(orientation='vertical'),
|
||||
title="Error info",size_hint=(0.8,0.8))
|
||||
self.messager = TextInput(size=self.w.content.size,
|
||||
multiline=True,readonly=True)
|
||||
self.w.content.add_widget(self.messager)
|
||||
|
||||
def set_time_task(self):
|
||||
if self.show_time:
|
||||
self.time_task = Clock.schedule_once(self.hide,
|
||||
self.show_time)
|
||||
def show_error(self,e):
|
||||
self.w.title = "error"
|
||||
self.messager.text = str(e)
|
||||
self.w.open()
|
||||
self.set_time_task()
|
||||
|
||||
def show_info(self,info):
|
||||
self.w.title = "info"
|
||||
self.messager.text = str(info)
|
||||
self.w.open()
|
||||
self.set_time_task()
|
||||
|
||||
def hide_error(self):
|
||||
def hide(self, *args):
|
||||
if self.time_task:
|
||||
self.time_task.cancel()
|
||||
self.time_task = None
|
||||
self.w.dismiss()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user