This commit is contained in:
yumoqing 2021-03-05 17:15:51 +08:00
parent 4a9de787c7
commit 3580406e13
6 changed files with 200 additions and 115 deletions

View File

@ -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):

View File

@ -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'):

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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()