This commit is contained in:
yumoqing 2021-05-24 12:25:29 +08:00
parent 37b9e3b73b
commit 703845b20d
13 changed files with 86 additions and 97 deletions

View File

@ -70,7 +70,6 @@ from .bgcolorbehavior import BGColorBehavior
from .utils import NeedLogin, InsufficientPrivilege, HTTPError from .utils import NeedLogin, InsufficientPrivilege, HTTPError
from .login import LoginForm from .login import LoginForm
from .tab import TabsPanel from .tab import TabsPanel
from .qrdata import QRCodeWidget
from .threadcall import HttpClient from .threadcall import HttpClient
from .i18n import I18n from .i18n import I18n
from .widget_css import WidgetCSS from .widget_css import WidgetCSS
@ -211,11 +210,21 @@ class Title6(Text):
Text.__init__(self, **kw) Text.__init__(self, **kw)
class Modal(ModalView): class Modal(ModalView):
def __init__(self, auto_open=False, **kw): def __init__(self, auto_open=False,
content=None,
**kw):
ModalView.__init__(self, **kw) ModalView.__init__(self, **kw)
self.auto_open = auto_open self.auto_open = auto_open
if content:
blocks = Factory.Blocks()
self.content = blocks.widgetBuild(content)
if self.content:
self.add_widget(self.content)
else:
print(content,':cannot build widget')
def add_widget(self,w, *args, **kw): def add_widget(self, w, *args, **kw):
super().add_widget(w, *args, **kw) super().add_widget(w, *args, **kw)
if self.auto_open: if self.auto_open:
self.open() self.open()

View File

@ -33,7 +33,6 @@ from .form import InputBox, Form, StrSearchForm
from .boxViewer import BoxViewer from .boxViewer import BoxViewer
from .tree import Tree, TextTree from .tree import Tree, TextTree
from .newvideo import Video from .newvideo import Video
from .ready import WidgetReady
from .bgcolorbehavior import BGColorBehavior from .bgcolorbehavior import BGColorBehavior
from .orientationlayout import OrientationLayout from .orientationlayout import OrientationLayout
from .threadcall import HttpClient from .threadcall import HttpClient
@ -42,32 +41,6 @@ from .register import *
def showError(e): def showError(e):
print('error',e) print('error',e)
def wrap_ready(klass):
try:
w = Factory.get(klass)
if hasattr(w,'ready'):
return w
Factory.unregister(klass)
globals()[klass] = w
except:
print_exc()
w = globals().get(klass)
if w is None:
return None
if hasattr(w,'ready'):
return w
script = f"""class R_{klass}(WidgetReady, {klass}):
def __init__(self, **kw):
{klass}.__init__(self, **kw)
WidgetReady.__init__(self)
"""
exec(script,globals(),globals())
newWidget = globals().get(f'R_{klass}')
Factory.register(klass,newWidget)
return newWidget
class WidgetNotFoundById(Exception): class WidgetNotFoundById(Exception):
def __init__(self, id): def __init__(self, id):
super().__init__() super().__init__()
@ -304,10 +277,10 @@ class Blocks(EventDispatcher):
opts = self.valueExpr(desc.get('options',{}).copy()) opts = self.valueExpr(desc.get('options',{}).copy())
widget = None widget = None
try: try:
klass = wrap_ready(widgetClass) klass = Factory.get(widgetClass)
widget = klass(**opts) widget = klass(**opts)
except Exception as e: except Exception as e:
print('Error:',widgetClass,'not registered') print('Error:',widgetClass,'contructon error')
print_exc() print_exc()
raise NotExistsObject(widgetClass) raise NotExistsObject(widgetClass)
@ -599,16 +572,16 @@ class Blocks(EventDispatcher):
try: try:
widget = self.w_build(desc) widget = self.w_build(desc)
self.dispatch('on_built',widget) self.dispatch('on_built',widget)
if hasattr(widget,'ready'):
widget.ready = True
return widget return widget
except Exception as e: except Exception as e:
print_exc() print_exc()
self.dispatch('on_failed',e) self.dispatch('on_failed',e)
return None return None
if not (isinstance(desc, DictObject) or isinstance(desc, dict)): if isinstance(desc,DictObject):
print('Block: desc must be a dict object', desc = desc.to_dict()
if not isinstance(desc, dict):
print('widgetBuild1: desc must be a dict object',
desc,type(desc)) desc,type(desc))
self.dispatch('on_failed',Exception('miss url')) self.dispatch('on_failed',Exception('miss url'))
return return
@ -630,7 +603,7 @@ class Blocks(EventDispatcher):
desc = self.getUrlData(url,**opts) desc = self.getUrlData(url,**opts)
if not (isinstance(desc, DictObject) or \ if not (isinstance(desc, DictObject) or \
isinstance(desc, dict)): isinstance(desc, dict)):
print('Block: desc must be a dict object', print('Block2: desc must be a dict object',
desc,type(desc)) desc,type(desc))
self.dispatch('on_failed',Exception('miss url')) self.dispatch('on_failed',Exception('miss url'))
return return
@ -639,8 +612,7 @@ class Blocks(EventDispatcher):
desc = dictExtend(desc,addon) desc = dictExtend(desc,addon)
widgettype = desc.get('widgettype') widgettype = desc.get('widgettype')
if widgettype is None: if widgettype is None:
print('Block: desc must be a dict object', print('Block3: desc must be a dict object not None')
desc,type(desc))
return None return None
return doit(desc) return doit(desc)

View File

@ -111,6 +111,9 @@ class BlocksApp(App):
self.buildCsses(d) self.buildCsses(d)
Logger.info('blocksapp: csses=%s', self.csses) Logger.info('blocksapp: csses=%s', self.csses)
def get_css(self, cssname):
return self.csses.get(cssname, 'default')
def on_rotate(self,*largs): def on_rotate(self,*largs):
self.current_rotation = Window.rotation self.current_rotation = Window.rotation
Logger.info('BlocksApp:on_rotate(), largs=%s', Logger.info('BlocksApp:on_rotate(), largs=%s',
@ -140,8 +143,8 @@ class BlocksApp(App):
"fgcolor":[0.85,0.85,0.85,1] "fgcolor":[0.85,0.85,0.85,1]
}, },
"input_focus":{ "input_focus":{
"bgcolor":[1,0.35,0.35,1], "bgcolor":[0.25,0.25,0.25,1],
"fgcolor":[1,0.85,0.85,1] "fgcolor":[0.8,0.8,0.8,1]
} }
} }
self.public_headers = {} self.public_headers = {}

View File

@ -87,4 +87,8 @@ class QrReader(XCamera):
self.dispatch('on_data',self.qr_result) self.dispatch('on_data',self.qr_result)
super(QrReader, self).on_tex(self.texture) super(QrReader, self).on_tex(self.texture)
def dismiss(self, *args, **kw):
self.release()
cv2.destroyAllWindows()
Builder.load_string(btxt) Builder.load_string(btxt)

View File

@ -1,6 +1,7 @@
from kivy.event import EventDispatcher from kivy.event import EventDispatcher
from kivy.app import App from kivy.app import App
from kivy.factory import Factory
from .threadcall import HttpClient from .threadcall import HttpClient
from .utils import absurl from .utils import absurl
from appPublic.registerfunction import RegisterFunction from appPublic.registerfunction import RegisterFunction
@ -47,8 +48,9 @@ class DataGraber(EventDispatcher):
ret = self.loadRFData(*args, **kw) ret = self.loadRFData(*args, **kw)
break break
target = self.options.get('datatarget') target = self.options.get('datatarget')
ret = self.loadTargetData(*args, **kw) if target:
break ret = self.loadTargetData(*args, **kw)
break
except Exception as e: except Exception as e:
self.dispatch('on_error', e) self.dispatch('on_error', e)
return return

View File

@ -13,9 +13,9 @@ from .utils import *
from .i18n import I18n from .i18n import I18n
from .toolbar import Toolbar from .toolbar import Toolbar
from .color_definitions import getColors from .color_definitions import getColors
from .bgcolorbehavior import BGColorBehavior
from .dataloader import DataGraber from .dataloader import DataGraber
from .ready import WidgetReady from .ready import WidgetReady
from .widget_css import WidgetCSS
""" """
form options form options
@ -164,8 +164,6 @@ class InputBox(BoxLayout):
opts['size_hint_x'] = None opts['size_hint_x'] = None
opts['width'] = self.labelwidth opts['width'] = self.labelwidth
bl = BoxLayout(**opts) bl = BoxLayout(**opts)
Logger.info('kivyblock:labelwidth=%f,opts=%s', self.labelwidth,str(opts))
Logger.info('kivyblock:bl.widht=%f,bl.height=%f',bl.width,bl.height)
self.add_widget(bl) self.add_widget(bl)
label = self.options.get('label',self.options.get('name')) label = self.options.get('label',self.options.get('name'))
kwargs = { kwargs = {
@ -175,8 +173,6 @@ class InputBox(BoxLayout):
} }
self.labeltext = Text(**kwargs) self.labeltext = Text(**kwargs)
bl.add_widget(self.labeltext) bl.add_widget(self.labeltext)
Logger.info('kivyblock:label.widht=%f,label.height=%f',
self.labeltext.width,self.labeltext.height)
if self.options.get('required',False): if self.options.get('required',False):
star = Label(text='*', star = Label(text='*',
color=(1,0,0,1), color=(1,0,0,1),
@ -188,6 +184,7 @@ class InputBox(BoxLayout):
options['allow_copy'] = True options['allow_copy'] = True
options['width'] = options.get('width',1) options['width'] = options.get('width',1)
options['height'] = options.get('height',1) options['height'] = options.get('height',1)
options['csscls'] = self.form.input_css
if self.options.get('hint_text'): if self.options.get('hint_text'):
options['hint_text'] = i18n(self.options.get('hint_text')) options['hint_text'] = i18n(self.options.get('hint_text'))
@ -260,11 +257,11 @@ def defaultToolbar():
} }
class Form(BGColorBehavior, WidgetReady, BoxLayout): class Form(WidgetCSS, WidgetReady, BoxLayout):
def __init__(self, def __init__(self,
color_level=1, cols=1,
radius=[], csscls='default',
cols=2, input_css='input',
inputwidth=0, inputwidth=0,
inputheight=3, inputheight=3,
labelwidth=0.3, labelwidth=0.3,
@ -277,6 +274,7 @@ class Form(BGColorBehavior, WidgetReady, BoxLayout):
toolbar={}, toolbar={},
**options): **options):
self.inputwidth = 1 self.inputwidth = 1
self.input_css = input_css
self.inputheight = inputheight self.inputheight = inputheight
self.labelwidth= labelwidth self.labelwidth= labelwidth
self.fields = fields self.fields = fields
@ -291,12 +289,12 @@ class Form(BGColorBehavior, WidgetReady, BoxLayout):
options['orientation'] = 'vertical' options['orientation'] = 'vertical'
else: else:
options['orientation'] = 'horizontal' options['orientation'] = 'horizontal'
BoxLayout.__init__(self, **options) print('options=', options)
self.color_level = color_level super(Form, self).__init__(**options)
BGColorBehavior.__init__(self, #BoxLayout.__init__(self, **options)
color_level=color_level, #WidgetReady.__init__(self)
radius=radius) #WidgetCSS.__init__(self)
WidgetReady.__init__(self) self.csscls = csscls
self.cols = self.options_cols = cols self.cols = self.options_cols = cols
if isHandHold() and Window.width < Window.height: if isHandHold() and Window.width < Window.height:
self.cols = 1 self.cols = 1
@ -450,14 +448,18 @@ class StrSearchForm(BoxLayout):
def __init__(self,img_url=None,**options): def __init__(self,img_url=None,**options):
self.name = options.get('name','search_string') self.name = options.get('name','search_string')
BoxLayout.__init__(self,orientation='horizontal',size_hint_y=None,height=CSize(3)) BoxLayout.__init__(self,orientation='horizontal',size_hint_y=None,height=CSize(3))
self.input_css = options.get('input_css', 'input')
i18n = I18n()
self.input_widget = StrInput( self.input_widget = StrInput(
text='', text='',
multiline=False, multiline=False,
csscls=self.input_css,
hint_text=i18n(options.get('tip',options.get('hint_text',''))),
allow_copy=True, allow_copy=True,
font_size=1, font_size=CSize(1),
size_hint_y=None, size_hint_y=None,
size_hint_x=1, size_hint_x=1,
height=2) height=3)
self.add_widget(self.input_widget) self.add_widget(self.input_widget)
self.register_event_type('on_submit') self.register_event_type('on_submit')
v = options.get('value',options.get('default_value','')) v = options.get('value',options.get('default_value',''))

View File

@ -8,20 +8,16 @@ from kivy.clock import Clock
from ffpyplayer.tools import set_log_callback from ffpyplayer.tools import set_log_callback
from kivyblocks.bgcolorbehavior import BGColorBehavior
logger_func = {'quiet': Logger.critical, 'panic': Logger.critical, logger_func = {'quiet': Logger.critical, 'panic': Logger.critical,
'fatal': Logger.critical, 'error': Logger.error, 'fatal': Logger.critical, 'error': Logger.error,
'warning': Logger.warning, 'info': Logger.info, 'warning': Logger.warning, 'info': Logger.info,
'verbose': Logger.debug, 'debug': Logger.debug} 'verbose': Logger.debug, 'debug': Logger.debug}
class NewVideo(BGColorBehavior, Video): class NewVideo(Video):
center_screen = BooleanProperty(False) center_screen = BooleanProperty(False)
def __init__(self,color_level=-1,radius=[],**kw): def __init__(self, **kw):
Video.__init__(self, **kw) Video.__init__(self, **kw)
BGColorBehavior.__init__(self,
color_level=color_level,
radius=radius)
Window.allow_screensaver = False Window.allow_screensaver = False
set_log_callback(self.ffplayerLog) set_log_callback(self.ffplayerLog)
self.register_event_type('on_open_failed') self.register_event_type('on_open_failed')

View File

@ -32,7 +32,7 @@ class QRCodeReader(Image):
self.dismiss() self.dismiss()
super().on_touch_down(touch) super().on_touch_down(touch)
def dismiss(self): def dismiss(self, *args, **kw):
if not self.opened: if not self.opened:
return return
self.opened = False self.opened = False
@ -54,7 +54,10 @@ class QRCodeReader(Image):
self.showImage(img) self.showImage(img)
data,bbox,_ = self.detector.detectAndDecode(img) data,bbox,_ = self.detector.detectAndDecode(img)
if data: if data:
self.dispatch('on_data',data) d = {
'data':data
}
self.dispatch('on_data',d)
if __name__ == '__main__': if __name__ == '__main__':
class MyApp(App): class MyApp(App):

View File

@ -13,9 +13,11 @@ from kivy.properties import ObjectProperty, StringProperty, ListProperty,\
BooleanProperty BooleanProperty
from kivy.lang import Builder from kivy.lang import Builder
from kivy.clock import Clock from kivy.clock import Clock
from .baseWidget import VBox
import qrcode import qrcode
class QRCodeWidget(FloatLayout): class QRCodeWidget(VBox):
data = StringProperty(None, allow_none=True) data = StringProperty(None, allow_none=True)
''' Data using which the qrcode is generated. ''' Data using which the qrcode is generated.
@ -31,13 +33,12 @@ class QRCodeWidget(FloatLayout):
''' '''
def __init__(self, **kwargs): def __init__(self, **kwargs):
self.qrimage = Image(allow_stretch=True) self.qrimage = Image(allow_stretch=True, keep_ratio=True)
self.addr = None self.addr = None
super(QRCodeWidget, self).__init__(**kwargs) super(QRCodeWidget, self).__init__(**kwargs)
self.background_color = [1,1,1,1] self.background_color = [1,1,1,1]
self.qr = None self.qr = None
self._qrtexture = None self._qrtexture = None
self.qrimage.pos_hint = {'center_x':0.5, 'center_y':0.5}
self.add_widget(self.qrimage) self.add_widget(self.qrimage)
def on_size(self,o,s): def on_size(self,o,s):
@ -60,7 +61,7 @@ class QRCodeWidget(FloatLayout):
def set_addr(self, addr): def set_addr(self, addr):
if self.addr == addr: if self.addr == addr:
return return
MinSize = 210 if len(addr) < 128 else 500 MinSize = 500 #210 if len(addr) < 128 else 500
self.setMinimumSize((MinSize, MinSize)) self.setMinimumSize((MinSize, MinSize))
self.addr = addr self.addr = addr
self.qr = None self.qr = None
@ -76,7 +77,7 @@ class QRCodeWidget(FloatLayout):
version=None, version=None,
error_correction=L, error_correction=L,
box_size=10, box_size=10,
border=0, border=4,
) )
qr.add_data(addr) qr.add_data(addr)
qr.make(fit=True) qr.make(fit=True)

View File

@ -1,5 +1,6 @@
import kivy import kivy
from kivy.utils import platform from kivy.utils import platform
from kivy.uix.textinput import TextInput
from appPublic.registerfunction import RegisterFunction from appPublic.registerfunction import RegisterFunction
@ -35,6 +36,7 @@ from .camerawithmic import CameraWithMic
r = Factory.register r = Factory.register
if kivy.platform in ['win','linux', 'macosx']: if kivy.platform in ['win','linux', 'macosx']:
r('ScreenWithMic', ScreenWithMic) r('ScreenWithMic', ScreenWithMic)
r('TextInput', TextInput)
r('CameraWithMic', CameraWithMic) r('CameraWithMic', CameraWithMic)
r('CustomCamera', CustomCamera) r('CustomCamera', CustomCamera)
r('QrReader', QrReader) r('QrReader', QrReader)

View File

@ -1,5 +1,6 @@
import sys import sys
import re import re
from kivy.app import App
from kivy.logger import Logger from kivy.logger import Logger
from kivy.uix.image import Image from kivy.uix.image import Image
from kivy.uix.boxlayout import BoxLayout from kivy.uix.boxlayout import BoxLayout
@ -16,7 +17,7 @@ from ..utils import CSize
from ..widget_css import WidgetCSS from ..widget_css import WidgetCSS
class BoolInput(Switch): class BoolInput(Switch):
def __init__(self,**kw): def __init__(self,csscls='input', **kw):
a = DictObject() a = DictObject()
if kw.get('defaultvalue',None) is None: if kw.get('defaultvalue',None) is None:
a.active = False a.active = False
@ -41,20 +42,26 @@ class BoolInput(Switch):
def setValue(self,v): def setValue(self,v):
self.active = v self.active = v
class StrInput(WidgetCSS, TextInput): class StrInput(TextInput):
def __init__(self,**kv): def __init__(self,csscls='default',
**kv):
if kv is None: if kv is None:
kv = {} kv = {}
app = App.get_running_app()
css = app.get_css(csscls)
a = { a = {
"allow_copy":True, "allow_copy":True,
"password":False, "password":False,
"multiline":False, "multiline":False,
"halign":"left", "halign":"left",
"hint_text":"", "hint_text":"test",
"text_language":"zh_CN", "text_language":"zh_CN",
"font_size":CSize(1),
"write_tab":False "write_tab":False
} }
a.update(kv) a.update(kv)
a['background_color'] = css['bgcolor']
a['foreground_color'] = css['fgcolor']
w = kv.get('width',1) w = kv.get('width',1)
h = kv.get('height',1) h = kv.get('height',1)
if w <= 1: if w <= 1:
@ -67,13 +74,11 @@ class StrInput(WidgetCSS, TextInput):
else: else:
a['size_hint_y'] = None a['size_hint_y'] = None
a['height'] = CSize(h) a['height'] = CSize(h)
a['font_size'] = CSize(kv.get('font_size',0.9))
Logger.info('TextInput:a=%s,kv=%s',a,kv) Logger.info('StrInput:a=%s,kv=%s',a,kv)
super(StrInput, self).__init__(**a) super(StrInput, self).__init__(**a)
self.old_value = None self.old_value = None
self.register_event_type('on_changed') self.register_event_type('on_changed')
self.bind(focus=self.on_focus)
self.bind(on_text_validate=self.checkChange) self.bind(on_text_validate=self.checkChange)
def on_changed(self,v=None): def on_changed(self,v=None):
@ -84,14 +89,6 @@ class StrInput(WidgetCSS, TextInput):
if v != self.old_value: if v != self.old_value:
self.dispatch('on_changed',v) self.dispatch('on_changed',v)
def on_focus(self,t,v):
if v:
self.old_value = self.getValue()
self.csscls = 'input_focus'
else:
self.checkChange(None)
self.csscls = 'input'
def getValue(self): def getValue(self):
return self.text return self.text
@ -156,7 +153,7 @@ class AmountInput(FloatInput):
return StrInput.insert_text(self,s, from_undo=from_undo) return StrInput.insert_text(self,s, from_undo=from_undo)
class MyDropDown(DropDown): class MyDropDown(DropDown):
def __init__(self,**kw): def __init__(self,csscls='input', **kw):
super(MyDropDown,self).__init__() super(MyDropDown,self).__init__()
self.options = kw self.options = kw
self.textField = kw.get('textField','text') self.textField = kw.get('textField','text')
@ -221,7 +218,7 @@ class MyDropDown(DropDown):
self.open(w) self.open(w)
class SelectInput(BoxLayout): class SelectInput(BoxLayout):
def __init__(self,**kw): def __init__(self,csscls='input', **kw):
a={} a={}
w = kw.get('width',10) w = kw.get('width',10)
h = kw.get('height',1.5) h = kw.get('height',1.5)

View File

@ -3,10 +3,6 @@ from kivy.clock import Clock
from kivy.uix.boxlayout import BoxLayout from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput from kivy.uix.textinput import TextInput
from ..widget_css import WidgetCSS from ..widget_css import WidgetCSS
class MyPopup(WidgetCSS, Popup):
def __init__(self,content=None, title='', **kw):
super(MyPopup, self).__init__(content=content,
title=title, **kw)
class Messager: class Messager:
def __init__(self, show_time=0, title=None, **kw): def __init__(self, show_time=0, title=None, **kw):
@ -17,6 +13,8 @@ class Messager:
title=self.title, title=self.title,
size_hint=(0.8,0.8), **kw) size_hint=(0.8,0.8), **kw)
self.messager = TextInput(size=self.w.content.size, self.messager = TextInput(size=self.w.content.size,
background_color=[0.9,0.9,0.9,1],
foreground_color=[0.3,0.3,0.3,1],
multiline=True,readonly=True) multiline=True,readonly=True)
self.w.content.add_widget(self.messager) self.w.content.add_widget(self.messager)

View File

@ -120,9 +120,9 @@ class WidgetCSS(object):
def on_radius(self, o, r): def on_radius(self, o, r):
if not self.radius: if not self.radius:
self.bg_func = Rectangle self.bg_func = Rectangle
return else:
self.bg_func = RoundedRectangle self.bg_func = RoundedRectangle
# self.set_background_color() self.set_background_color()
def set_background_color(self, *args): def set_background_color(self, *args):
if not self.bgcolor: if not self.bgcolor: