This commit is contained in:
yumoqing 2021-02-21 14:27:01 +08:00
parent d427730a06
commit 9cf729a676
4 changed files with 199 additions and 76 deletions

View File

@ -9,6 +9,7 @@ class BGColorBehavior(object):
if color_level==-1:
color_level = 0
self.color_level = color_level
self.bg_ready = False
self.radius = radius
self.bgcolor = []
self.fgcolor = []
@ -36,6 +37,7 @@ class BGColorBehavior(object):
def on_bgcolor(self,o=None,v=None):
if self.bgcolor == []:
return
if self.canvas:
with self.canvas.before:
Color(*self.bgcolor)

View File

@ -4,6 +4,98 @@ from .threadcall import HttpClient
from .utils import absurl
from appPublic.registerfunction import RegisterFunction
class DataGraber(EventDispatcher):
"""
Graber format
{
"widgettype":"DataGraber",
"options":{
"dataurl":"first",
"datarfname":"second",
"target":"third",
"params":
"method":
"pagging":"default false"
}
}
if dataurl present, the DataGraber using this dataurl to get and
return data
else if datarfname present, it find a registered function named
by 'datarfname' to return data
else if datatarget present, it find the widget and uses target
method(default is 'getValue') to return data
else it return None
"""
def __init__(self, **kw):
super().__init__()
self.options = kw
self.register_event_type('on_success')
self.register_event_type('on_error')
def load(self, *args, **kw):
dataurl = self.options.get('dataurl')
if dataurl:
return self.loadUrlData(*args, **kw)
rfname = self.options.get('datarfname')
if rfname:
return self.loadRFData(*args, **kw)
target = self.options.get('datatarget')
if target:
return self.loadTargetData(*args, **kw)
return None
def loadUrlData(self, *args, **kw):
dataurl = self.options.get('dataurl')
hc = HttpClient()
params = self.options.get('params',{}).copy()
params.update(kw)
method = self.options.get('method','GET')
d = hc.get(dataurl, params=params,method=method)
return d
def loadRFData(self, *args, **kw):
rfname = self.options.get('datarfname')
rf = RegisterFunction()
f = rf.get(rfname)
if not f:
return None
params = self.options.get('params',{}).copy()
params.update(kw)
try:
d = f(**params)
return d
except Exception as e:
Logger.info('blocks : Exception:%s',e)
print_exc()
return None
def loadTargetData(self, *args, **kw):
target = self.options.get('datatarget')
w = Factory.Blocks.getWidgetById(target)
if not w:
return None
params = self.options.get('params',{}).copy()
params.update(kw)
method = params.get('method', 'getValue')
if not has(w, method):
return None
try:
f = getattr(w, method)
d = f()
return d
except Exception as e:
Logger.info('blocks : Exception %s', e)
print_exc()
return None
def on_success(self,d):
pass
def on_error(self,e):
pass
class DataLoader(EventDispatcher):
def __init__(self,data_user):
self.data_user = data_user
@ -11,12 +103,6 @@ class DataLoader(EventDispatcher):
self.register_event_type('on_success')
self.register_event_type('on_error')
def success(self,o,d):
self.dispatch('on_success',d)
def error(self,o,e):
self.dispatch('on_error',e)
def on_success(self,d):
pass
@ -27,7 +113,7 @@ class DataLoader(EventDispatcher):
pass
class HttpDataLoader(DataLoader):
def load(self):
def load(self, *args, **kw):
url = absurl(self.data_user.url,self.data_user.target.parenturl)
method = self.data_user.method
params = self.data_user.params.copy()
@ -36,14 +122,16 @@ class HttpDataLoader(DataLoader):
"rows":self.data_user.page_rows
})
hc = HttpClient()
hc(url,
method=method,
params=params,
callback=self.success,
errback=self.error)
try:
r = hc(url, method=method, params=params)
self.dispatch('on_success', r)
return r
except Exception as e:
self.dispatch('on_error', e)
class ListDataLoader(DataLoader):
def load(self):
def load(self, *args, **kw):
p = self.data_user.curpage
r = self.data_user.page_rows
try:
@ -52,12 +140,13 @@ class ListDataLoader(DataLoader):
"total":len(self.data_user.data),
"rows":s
}
self.success(self,d)
self.dispatch('on_success', d)
return d
except Exception as e:
self.error(self,e)
self.dispatch('on_error', e)
class RegisterFunctionDataLoader(DataLoader):
def load(self):
def load(self, *args, **kw):
rf = RegisterFunction()
try:
rfname = self.data_user.rfname
@ -70,7 +159,9 @@ class RegisterFunctionDataLoader(DataLoader):
"rows":self.data_user.page_rows
})
s = func(**params)
self.success(self,s)
self.dispatch('on_success', s)
return s
except Exception as e:
self.error(self,e)
self.dispatch('on_error', e)

View File

@ -14,6 +14,8 @@ from .i18n import I18n
from .toolbar import Toolbar
from .color_definitions import getColors
from .bgcolorbehavior import BGColorBehavior
from .dataloader import DataGraber
from .ready import WidgetReady
"""
form options
@ -94,11 +96,11 @@ uitypes = {
"wclass":SelectInput,
},
"text":{
"orientation":"vertical",
"orientation":"horizontal",
"wclass":StrInput,
"options":{
"multiline":True,
"height":9,
"height":4,
}
},
"teleno":{
@ -114,11 +116,16 @@ class InputBox(BoxLayout):
def __init__(self, form, **options):
self.form = form
self.options = options
self.uitype = options.get('uitype','string')
self.uitype = options.get('uitype',options.get('datatype','string'))
self.uidef = uitypes[self.uitype]
orientation = self.uidef['orientation']
width = self.form.inputwidth
height = self.form.inputheight
if self.uitype == 'text':
if not options.get('height'):
self.options['height'] = 4
height = self.options.get('height',4)
self.labelwidth = self.form.options['labelwidth']
kwargs = {
"orientation":orientation,
@ -138,7 +145,6 @@ class InputBox(BoxLayout):
self.bind(size=self.setSize,
pos=self.setSize)
self.register_event_type("on_datainput")
self.register_event_type("on_ready")
def on_datainput(self,o,v=None):
print('on_datainput fired ...',o,v)
@ -150,7 +156,7 @@ class InputBox(BoxLayout):
opts = {
"orientation":"horizontal",
"size_hint_y":None,
"height":CSize(3)
"height":CSize(2)
}
if self.labelwidth<=1:
opts['size_hint_x'] = self.labelwidth
@ -166,10 +172,6 @@ class InputBox(BoxLayout):
"i18n":True,
"text":label,
"font_size":CSize(1),
"size_hint_x":None,
"width":CSize(len(label)),
"size_hint_y":None,
"height":CSize(3)
}
self.labeltext = Text(**kwargs)
bl.add_widget(self.labeltext)
@ -184,11 +186,12 @@ class InputBox(BoxLayout):
options = self.uidef.get('options',{}).copy()
options.update(self.options.get('uiparams',{}))
options['allow_copy'] = True
options['width'] = options.get('width',20)
options['width'] = options.get('width',1)
options['height'] = options.get('height',1)
if self.options.get('tip'):
options['hint_text'] = i18n(self.options.get('tip'))
if self.options.get('hint_text'):
options['hint_text'] = i18n(self.options.get('hint_text'))
Logger.info('Form: uitype=%s', self.uitype)
self.input_widget = self.uidef['wclass'](**options)
if self.options.get('readonly'):
self.input_widget.disabled = True
@ -201,8 +204,7 @@ class InputBox(BoxLayout):
self.add_widget(self.input_widget)
self.initflag = True
self.input_widget.bind(on_focus=self.on_focus)
self.dispatch('on_ready', self)
def check(self):
d = self.getValue()
v = d.get(self.options.get('name'))
@ -214,9 +216,6 @@ class InputBox(BoxLayout):
return True
def on_ready(self, obj):
Logger.info('kivyblocks: Form input ready')
def clear(self):
self.input_widget.setValue('')
@ -244,8 +243,8 @@ class InputBox(BoxLayout):
def defaultToolbar():
return {
"img_size":2,
"text_size":1,
"img_size":1.5,
"text_size":0.7,
"tools":[
{
"name":"__submit",
@ -261,7 +260,7 @@ def defaultToolbar():
}
class Form(BGColorBehavior, BoxLayout):
class Form(BGColorBehavior, WidgetReady, BoxLayout):
def __init__(self, **options):
self.options = options
BoxLayout.__init__(self, orientation='vertical')
@ -269,6 +268,7 @@ class Form(BGColorBehavior, BoxLayout):
BGColorBehavior.__init__(self,
color_level=self.options.get('color_level',-1),
radius=self.options.get('radius',[]))
WidgetReady.__init__(self)
self.readiedInput = 0
self.cols = self.options_cols = self.options.get('cols',1)
if isHandHold() and Window.width < Window.height:
@ -282,7 +282,28 @@ class Form(BGColorBehavior, BoxLayout):
pass
def init(self):
self.toolbar = Toolbar(**self.options.get('toolbar',defaultToolbar()))
desc = defaultToolbar()
desc1 = self.options.get('toolbar')
if desc1:
tools = desc['tools'] + desc1['tools']
desc1['tools'] = tools
desc = desc1
if self.options.get('submit'):
kw = self.options.get('submit').copy()
if kw.get('name'):
del kw['name']
for t in desc['tools']:
if t['name'] == '__submit':
t.update(kw)
if self.options.get('clear'):
kw = self.options.get('clear').copy()
if kw.get('name'):
del kw['name']
for t in desc['tools']:
if t['name'] == '__clear':
t.update(kw)
self.toolbar = Toolbar(**desc)
self.fsc = VResponsiveLayout(
self.inputwidth,
self.cols
@ -299,7 +320,12 @@ class Form(BGColorBehavior, BoxLayout):
wid.bind(on_press=self.on_submit_button)
wid = Factory.Blocks.getWidgetById('__clear',from_widget=self)
wid.bind(on_press=self.on_clear_button)
if self.options.get('dataloader'):
self.dataloader = DataGraber(**self.options['dataloader'])
d = self.dataloader.load()
if d:
self.setValue(d)
def makeInputLink(self,o,v=None):
self.readiedInput += 1
if self.readiedInput >= len(self.options['fields']):
@ -309,6 +335,12 @@ class Form(BGColorBehavior, BoxLayout):
w.input_widget.focus_previous = p.input_widget
p = w
def setValue(self,d):
for f in self.fieldWidgets:
v = f.getValue()
for k in v.keys():
f.setValue({k:d[k]})
def getValue(self):
d = {}
for f in self.fieldWidgets:
@ -367,6 +399,12 @@ class StrSearchForm(BoxLayout):
}
return d
def setValue(self, d):
if isinstance(d,str):
self.input_widget.text = d
if isinstance(d,{}):
self.input_widget.text = d.get(self.name,'')
def submit_input(self,o,v=None):
text = self.input_widget.text
if text != '':

View File

@ -15,7 +15,6 @@ from ..threadcall import HttpClient
from ..utils import CSize
class BoolInput(Switch):
change = BooleanProperty(False)
def __init__(self,**kw):
a = DictObject()
if kw.get('defaultvalue',None) is None:
@ -25,7 +24,7 @@ class BoolInput(Switch):
if kw.get('value',None) is not None:
a.active = kw.get('value')
super().__init__(**a)
super().__init__(**a.to_dict())
self.register_event_type('on_changed')
self.bind(active=on_active)
@ -52,11 +51,9 @@ class StrInput(TextInput):
"halign":"left",
"hint_text":"",
}
if kv.get('tip'):
a['hint_text'] = kv['tip']
# a.update(kv)
w = kv.get('width',20)
h = kv.get('height',2.5)
a.update(kv)
w = kv.get('width',1)
h = kv.get('height',1)
if w <= 1:
a['size_hint_x'] = w
else:
@ -67,9 +64,7 @@ class StrInput(TextInput):
else:
a['size_hint_y'] = None
a['height'] = CSize(h)
a['font_size'] = CSize(kv.get('font_size',1))
a['password'] = kv.get('password',False)
a['multiline'] = kv.get('multiline',False)
a['font_size'] = CSize(kv.get('font_size',0.9))
Logger.info('TextInput:a=%s,kv=%s',a,kv)
super(StrInput,self).__init__(**a)
@ -107,6 +102,7 @@ class Password(StrInput):
class IntegerInput(StrInput):
def __init__(self,**kw):
print("IntegerInput(), __init__()....")
a = {}
a.update(kw)
a['halign'] = 'right'
@ -114,6 +110,7 @@ class IntegerInput(StrInput):
pat = re.compile('[^0-9]')
def insert_text(self, substring, from_undo=False):
print('TTTTTTTTTTTTTTTTTTTTTTttt')
pat = self.pat
s = re.sub(pat, '', substring)
return StrInput.insert_text(self,s, from_undo=from_undo)
@ -125,6 +122,7 @@ class IntegerInput(StrInput):
class FloatInput(IntegerInput):
pat = re.compile('[^0-9]')
def filter(self,substring):
print('FloatInput(), filter():..........')
pat = self.pat
if '.' in self.text:
s = re.sub(pat, '', substring)
@ -169,7 +167,8 @@ class MyDropDown(DropDown):
self.setDataByUrl(self.url)
else:
self.si_data = self.options.get('data')
self.setData(self.si_data)
if self.si_data:
self.setData(self.si_data)
self.bind(on_select=lambda instance, x: self.selectfunc(x))
def selectfunc(self,v):
@ -192,38 +191,29 @@ class MyDropDown(DropDown):
def setData(self,data):
self.si_data = data
self.clear_widgets()
w = self.options.get('width',10)
h = self.options.get('height',2.5)
a = {}
if w <= 1:
a['size_hint_x'] = w
else:
a['size_hint_x'] = None
a['width'] = CSize(w)
if h <= 1:
a['size_hint_y'] = h
else:
a['size_hint_y'] = None
a['height'] = CSize(h)
a['size_hint_y'] = None
a['height'] = CSize(h)
a['font_size'] = CSize(self.options.get('font_size',1))
print('data=',data)
for d in data:
dd = (d[self.valueField],d[self.textField])
b = Button(text=d[self.textField],**a)
setattr(b,'kw_data',dd)
b.bind(on_release=lambda btn: self.select(btn.kw_data))
self.add_widget(b)
#print(dd)
print('setData():',dd)
def setDataByUrl(self,url,params={}):
def x(obj,d):
self.setData(d)
app = App.get_running_app()
app.hc.get(url,params=params,callback=x)
def setDataByUrl(self,url,kw={}):
hc = HttpClient()
params = self.options.get('params', {}).copy()
params.update(kw)
d = hc.get(url,params=params)
self.setData(d)
def showme(self,w):
#print('show it ',w)
print('show it ',w)
self.target = w
self.open(w)
@ -231,7 +221,7 @@ class SelectInput(BoxLayout):
def __init__(self,**kw):
a={}
w = kw.get('width',10)
h = kw.get('height',2.5)
h = kw.get('height',1.5)
if w <= 1:
a['size_hint_x'] = w
else:
@ -245,11 +235,13 @@ class SelectInput(BoxLayout):
super(SelectInput,self).__init__(orientation='horizontal',\
**a)
self.tinp = StrInput(size_hint_y=None,height=kw.get('height',2.5))
self.si_value = ''
self.tinp = StrInput()
self.tinp.readonly = True
newkw = {}
newkw.update(kw)
newkw.update({'on_select':self.setData})
print('selectinput:kw=', newkw)
self.dropdown = MyDropDown(**newkw)
if kw.get('value'):
self.si_data = kw.get('value')
@ -273,18 +265,18 @@ class SelectInput(BoxLayout):
self.old_value = self.getValue()
def setData(self,d):
self.tinp.si_data = d[0]
self.si_value = d[0]
self.tinp.text = d[1]
v = self.getValue()
if v != self.old_value:
self.dispatch('on_changed',v)
def setValue(self,v):
self.tinp.si_value = v
self.si_value = v
self.tinp.text = self.dropdown.getTextByValue(v)
def getValue(self):
return self.tinp.si_value
return self.si_value
if __name__ == '__main__':
from kivy.app import App