This commit is contained in:
yumoqing 2020-01-08 18:04:39 +08:00
parent edce30e08f
commit 0249db446b
13 changed files with 738 additions and 154 deletions

520
kivyblocks/blocks.bak.py Normal file
View File

@ -0,0 +1,520 @@
import os
import sys
import codecs
import json
from traceback import print_exc
from functools import partial
from appPublic.dictExt import dictExtend
from appPublic.jsonConfig import getConfig
from appPublic.folderUtils import ProgramPath
from appPublic.dictObject import DictObject
from appPublic.Singleton import SingletonDecorator
from kivy.config import Config
from kivy.metrics import sp,dp,mm
from kivy.core.window import WindowBase
from kivy.properties import BooleanProperty
from kivy.uix.widget import Widget
from kivy.app import App
from .baseWidget import *
from .widgetExt import Messager
from .externalwidgetmanager import ExternalWidgetManager
from .threadcall import HttpClient
from .toolbar import *
from .dg import DataGrid
from .utils import *
from .ready import WidgetReady
from .serverImageViewer import ServerImageViewer
from .vplayer import VPlayer
from .form import InputBox, Form, StrSearchForm
from .boxViewer import BoxViewer
def showError(e):
print('error',e)
class WidgetNotFoundById(Exception):
def __init__(self, id):
super().__init__()
self.idstr = id
def __str__(self):
return "Widget not found by id:" + self.idstr + ':'
def __expr__(self):
return str(self)
class ClassMethodNotFound(Exception):
def __init__(self,k,m):
super().__init__()
self.kname = k
self.mname = m
def __str__(self):
s = 'Method(%s) not found in class(%s)' % (self.mname,
str(self.kname.__classname__))
return s
def __expr__(self):
return self.__str__()
class NotExistsObject(Exception):
def __init__(self,name):
super().__init__()
self.name = name
def __str__(self):
s = 'not exists widget(%s)' % self.name
return s
def __expr__(self):
return self.__str__()
class ArgumentError(Exception):
def __init__(self,argument,desc):
super().__init__()
self.argument = argument
self.desc = desc
def __str__(self):
s = 'argument(%s) missed:%s' % (self.argument,self.desc)
return s
def __expr__(self):
return self.__str__()
class NotRegistedWidget(Exception):
def __init__(self,name):
super().__init__()
self.widget_name = name
def __str__(self):
s = 'not reigsted widget(%s)' % self.name
return s
def __expr__(self):
return self.__str__()
@SingletonDecorator
class RegistedFunction:
def __init__(self):
self.rf_list = {}
def register(self,name,func):
self.rf_list[name] = func
def get(self,name):
return self.rf_list.get(name)
def registerWidget(name,widget):
globals()[name] = widget
class Blocks:
registedWidgets = {}
def __init__(self):
self.action_id = 0
def register_widget(self,name,widget):
globals()[name] = widget
def buildAction(self,widget,desc):
self.action_id += 1
fname = 'action%d' % self.action_id
l = {
}
body="""def %s(widget,obj=None, v=None):
jsonstr='''%s'''
print(type(widget), type(obj),v,'action():desc=',jsonstr)
desc = json.loads(jsonstr)
app = App.get_running_app()
app.blocks.uniaction(widget, desc)
print('finished')
""" % (fname, json.dumps(desc))
exec(body,globals(),l)
f = l.get(fname,None)
if f is None:
raise Exception('None Function')
func =partial(f,widget)
return func
setattr(widget,fname,f)
return getattr(widget,fname)
def eval(self,s,l):
g = {}
forbidens = [
"os",
"sys",
"codecs",
"json",
]
for k,v in globals().copy().items():
if k not in forbidens:
g[k] = v
g['__builtins__'] = globals()['__builtins__'].copy()
g['__builtins__']['__import__'] = None
g['__builtins__']['__loader__'] = None
g['__builtins__']['open'] = None
return eval(s,g,l)
def getUrlData(self,kw,parenturl=None):
url = kw.get('url')
method = kw.get('method','GET')
params = kw.get('params',{})
if url is None:
print('kw=',kw)
raise ArgumentError('url','getUrlData() miss a url argument')
url = absurl(url,parenturl)
if url.startswith('file://'):
filename = url[7:]
print(filename)
with codecs.open(filename,'r','utf-8') as f:
b = f.read()
dic = json.loads(b)
else:
dic = App.get_running_app().hc(url,method=method,params=params)
return dic, url
def register(self,name : str ,base:str=None,
defaultOpts:dict={},optkeys:list=[],
properties:list=[]):
"""
"""
self.registedWidgets[name] = {
"defaultOpts":defaultOpts,
"base":base,
"properties":properties, # property: 0 name, 1 type
"optkeys":optkeys,
"infos":{}
}
def buildRegistedWidgetInfo(self, widgettype:str):
"""
setup registed widget defaultOpts and optkeys
by merge its and it's bases widgets
"""
rw = self.registedWidgets.get(widgettype)
if not rw:
raise NotRegistedWidget(widgettype)
rw['infos']['defaultOpts'] = rw['defaultOpts']
rw['infos']['optkeys'] = rw['optkeys']
for b in base:
brw = self.registedWidgets.get(b)
if not brw:
raise NotRegistedWidget(b)
opts = self.getWidgetOptions(b)
opts.update(rw['defaultOpts'])
rw['infos']['defaultOpts'].update({'defaultOpts':opts})
rw['infos']['optkeys'] = list(set(self.getWidgetOptkeys(b) + rw['infos']['optkeys']))
return rw['infos']
def getWidgetOptkeys(self,widgettype:str):
"""
"""
if widgettype not in self.registedWidgets.keys():
raise NotRegistedWidget(widgettype)
infos = self.registedWidgets.get(widgettype)['infos']
if infos == {}:
infos = self.buildRegistedWidgetInfo(widgettype)
return infos['optkeys']
def getWidgetOptions(self,widgettype:str, opts:dict={}):
"""
get widget type valid options, from it's registed info
and it given argument:opts
"""
if widgettype not in self.registedWidgets.keys():
raise NotRegistedWidget(widgettype)
infos = self.registedWidgets.get(widgettype)['infos']
if infos == {}:
infos = self.buildRegistedWidgetInfo(widgettype)
opt = infos['defaultOpts']
keys = opts.keys()
for k in infos['optkeys']:
if k in keys:
opt.update({k:opts[k]})
return opt
def getObject(self,klass:str ,bases:list=[],
properties:list=[]):
pstrs = [ "%s = %s\n" % (n,t) for n, t in properties ]
if klass not in globals().keys():
script="""
class %s(%s):
%s
def __init__(self):
super().__init__()
""" % (klass, '\t'.join(pstrs),','.join(bases))
exec(script,globals(),globals())
return globals().get(klass)()
def isBaseWidget(self,widgettype):
rw = self.registedWidgets.get(widgettype)
if not rw:
raise NotRegistedWidget(widgettype)
return rw['bases'] == []
def getBases(self, widgettype:str):
rw = self.registedWidgets.get(widgettype)
if not rw:
raise NotRegistedWidget(widgettype)
return rw['bases']
def strValueExpr(self,s:str,localnamespace:dict={}):
if not s.startswith('py::'):
return s
try:
v = self.eval(s[4:],localnamespace)
return v
except Exception as e:
if s.startswith('CSize'):
print('Exception .... ',e,s)
print_exc()
return s
def arrayValueExpr(self,arr:list,localnamespace:dict={}):
d = []
for v in arr:
if type(v) == type(''):
d.append(self.strValueExpr(v,localnamespace))
continue
if type(v) == type([]):
d.append(self.arrayValueExpr(v,localnamespace))
continue
if type(v) == type({}):
d.append(self.dictValueExpr(v,localnamespace))
continue
if type(v) == type(DictObject):
d.append(self.dictValueExpr(v,localnamespace))
continue
d.append(v)
return d
def dictValueExpr(self,dic:dict,localnamespace:dict={}):
d = {}
for k,v in dic.items():
if type(v) == type(''):
d[k] = self.strValueExpr(v,localnamespace)
continue
if type(v) == type([]):
d[k] = self.arrayValueExpr(v,localnamespace)
continue
if type(v) == type({}):
d[k] = self.dictValueExpr(v,localnamespace)
continue
if type(v) == type(DictObject):
d[k] = self.dictValueExpr(v,localnamespace)
continue
d[k] = v
return d
def valueExpr(self,obj,localnamespace={}):
if type(obj) == type(''):
return self.strValueExpr(obj,localnamespace)
if type(obj) == type([]):
return self.arrayValueExpr(obj,localnamespace)
if type(obj) in [ type({}), type(DictObject) ]:
return self.dictValueExpr(obj,localnamespace)
return obj
def __build(self,desc:dict,ancestor=None):
def checkReady(w,o):
print('checkReady():w=',w,'o=',o)
w.children_ready[o] = True
if all(w.children_ready.values()):
w.ready = True
widgetClass = desc.get('widgettype',None)
if not widgetClass:
print("__build(), desc invalid", desc)
raise Exception(desc)
widgetClass = desc['widgettype']
opts = desc.get('options',{})
klass = globals().get(widgetClass)
if not klass:
raise NotExistsObject(widgetClass)
widget = klass(**opts)
if desc.get('parenturl'):
widget.parenturl = desc.get('parenturl')
ancestor = widget
if desc.get('id'):
myid = desc.get('id')
holder = ancestor
if ancestor == widget:
app = App.get_running_app()
holder = app.root
if not hasattr(holder,'widget_ids'):
setattr(holder,'widget_ids',{})
holder.widget_ids[myid] = widget
widget.build_desc = desc
self.build_rest(widget,desc,ancestor)
# f = partial(self.build_rest,widget,desc,ancestor)
# event = Clock.schedule_once(f,0)
return widget
def build_rest(self, widget,desc,ancestor,t=None):
for sw in desc.get('subwidgets',[]):
w = self.widgetBuild(sw, ancestor=ancestor)
if w is None:
continue
w.parenturl = widget.parenturl
widget.add_widget(w)
if hasattr(widget,'addChild'):
widget.addChild(w)
for b in desc.get('binds',[]):
self.buildBind(widget,b)
if hasattr(widget, 'built'):
widget.built()
def buildBind(self,widget,desc):
wid = desc.get('wid','self')
w = self.getWidgetByIdPath(widget,wid)
event = desc.get('event')
if event is None:
return
f = self.buildAction(widget,desc)
w.bind(**{event:f})
def uniaction(self,widget,desc):
acttype = desc.get('actiontype')
if acttype=='blocks':
return self.blocksAction(widget,desc)
if acttype=='urlwidget':
return self.urlwidgetAction(widget,desc)
if acttype == 'registedfunction':
return self.registedfunctionAction(widget,desc)
if acttype == 'script':
return self.scriptAction(widget, desc)
if acttype == 'method':
return self.methodAction(widget, desc)
alert(msg="actiontype invalid",title=acttype)
def blocksAction(widget,desc):
target = self.getWidgetByIdPath(widget, desc.get('target','self'))
add_mode = desc.get('mode','replace')
opts = desc.get('options')
d = self.getActionData(widget,desc)
p = opts.get('options',{})
p.update(d)
opts['options'] = p
x = self.widgetBuild(opts,ancestor=widget)
if x is None:
alert(str(opts), title='widugetBuild error')
return
if add_mode == 'replace':
target.clear_widgets()
target.add_widget(x)
def urlwidgetAction(self,widget,desc):
target = self.getWidgetByIdPath(widget, desc.get('target','self'))
add_mode = desc.get('mode','replace')
opts = desc.get('options')
d = self.getActionData(widget,desc)
p = opts.get('params',{})
p.update(d)
opts['params'] = p
d = {
'widgettype' : 'urlwidget'
}
d['options'] = opts
x = self.widgetBuild(d,ancestor=widget)
if x is None:
return
if add_mode == 'replace':
target.clear_widgets()
target.add_widget(x)
def getActionData(self,widget,desc):
data = {}
if desc.get('datawidget',False):
dwidget = self.getWidgetByIdPath(widget,
desc.get('datawidget'))
data = dwidget.getData()
return data
def registedfunctionAction(self, widget, desc):
rf = RegistedFunction()
name = desc.get('rfname')
func = rf.get(name)
params = desc.get(params,{})
d = self.getActionData(widget,desc)
params.update(d)
func(params)
def scriptAction(self, widget, desc):
script = desc.get('script')
if script:
self.eval(script, {'self': widget})
def methodAction(self, widget, desc):
method = desc.get('method')
target = self.getWidgetByIdPath(widget, desc.get('target','self'))
if hasattr(target,method):
f = getattr(target, method)
kwargs = desc.get('options',{})
d = self.getActionData(widget,desc)
kwargs.update(d)
f(**kwargs)
else:
alert('%s method not found' % method)
def widgetBuild(self,desc,ancestor=None):
"""
desc format:
{
widgettype:<registered widget>,
id:widget id,
options:
subwidgets:[
]
binds:[
]
}
"""
name = desc['widgettype']
if name == 'urlwidget':
opts = desc.get('options')
parenturl = None
if ancestor:
parenturl = ancestor.parenturl
desc, parenturl = self.getUrlData(opts,parenturl)
if not isinstance(desc,dict):
print("getUrlData() return error data",opts,parenturl)
alert(str(dict) + 'format error')
return None
desc = self.valueExpr(desc)
desc['parenturl'] = parenturl
try:
widget = self.__build(desc,ancestor=ancestor)
return widget
except:
print('widgetBuild() Error',desc)
print_exc()
alert(str(desc))
return None
def getWidgetByIdPath(self,widget,path):
ids = path.split('/')
if ids[0] == '':
app = App.get_running_app()
widget = app.root
ids = ids[1:]
for id in ids:
if id == 'self':
return widget
widget = widget.widget_ids.get(id,None)
if widget is None:
print('widget not found,path=',path,'id=',id,'ids=',ids)
raise WidgetNotFoundById(id)
return widget

View File

@ -181,93 +181,6 @@ class Blocks:
dic = App.get_running_app().hc(url,method=method,params=params) dic = App.get_running_app().hc(url,method=method,params=params)
return dic, url return dic, url
def register(self,name : str ,base:str=None,
defaultOpts:dict={},optkeys:list=[],
properties:list=[]):
"""
"""
self.registedWidgets[name] = {
"defaultOpts":defaultOpts,
"base":base,
"properties":properties, # property: 0 name, 1 type
"optkeys":optkeys,
"infos":{}
}
def buildRegistedWidgetInfo(self, widgettype:str):
"""
setup registed widget defaultOpts and optkeys
by merge its and it's bases widgets
"""
rw = self.registedWidgets.get(widgettype)
if not rw:
raise NotRegistedWidget(widgettype)
rw['infos']['defaultOpts'] = rw['defaultOpts']
rw['infos']['optkeys'] = rw['optkeys']
for b in base:
brw = self.registedWidgets.get(b)
if not brw:
raise NotRegistedWidget(b)
opts = self.getWidgetOptions(b)
opts.update(rw['defaultOpts'])
rw['infos']['defaultOpts'].update({'defaultOpts':opts})
rw['infos']['optkeys'] = list(set(self.getWidgetOptkeys(b) + rw['infos']['optkeys']))
return rw['infos']
def getWidgetOptkeys(self,widgettype:str):
"""
"""
if widgettype not in self.registedWidgets.keys():
raise NotRegistedWidget(widgettype)
infos = self.registedWidgets.get(widgettype)['infos']
if infos == {}:
infos = self.buildRegistedWidgetInfo(widgettype)
return infos['optkeys']
def getWidgetOptions(self,widgettype:str, opts:dict={}):
"""
get widget type valid options, from it's registed info
and it given argument:opts
"""
if widgettype not in self.registedWidgets.keys():
raise NotRegistedWidget(widgettype)
infos = self.registedWidgets.get(widgettype)['infos']
if infos == {}:
infos = self.buildRegistedWidgetInfo(widgettype)
opt = infos['defaultOpts']
keys = opts.keys()
for k in infos['optkeys']:
if k in keys:
opt.update({k:opts[k]})
return opt
def getObject(self,klass:str ,bases:list=[],
properties:list=[]):
pstrs = [ "%s = %s\n" % (n,t) for n, t in properties ]
if klass not in globals().keys():
script="""
class %s(%s):
%s
def __init__(self):
super().__init__()
""" % (klass, '\t'.join(pstrs),','.join(bases))
exec(script,globals(),globals())
return globals().get(klass)()
def isBaseWidget(self,widgettype):
rw = self.registedWidgets.get(widgettype)
if not rw:
raise NotRegistedWidget(widgettype)
return rw['bases'] == []
def getBases(self, widgettype:str):
rw = self.registedWidgets.get(widgettype)
if not rw:
raise NotRegistedWidget(widgettype)
return rw['bases']
def strValueExpr(self,s:str,localnamespace:dict={}): def strValueExpr(self,s:str,localnamespace:dict={}):
if not s.startswith('py::'): if not s.startswith('py::'):
return s return s
@ -376,9 +289,6 @@ class %s(%s):
widget.built() widget.built()
def buildBind(self,widget,desc): def buildBind(self,widget,desc):
body="""
"""
wid = desc.get('wid','self') wid = desc.get('wid','self')
w = self.getWidgetByIdPath(widget,wid) w = self.getWidgetByIdPath(widget,wid)
event = desc.get('event') event = desc.get('event')
@ -389,6 +299,8 @@ class %s(%s):
def uniaction(self,widget,desc): def uniaction(self,widget,desc):
acttype = desc.get('actiontype') acttype = desc.get('actiontype')
if acttype=='blocks':
return self.blocksAction(widget,desc)
if acttype=='urlwidget': if acttype=='urlwidget':
return self.urlwidgetAction(widget,desc) return self.urlwidgetAction(widget,desc)
if acttype == 'registedfunction': if acttype == 'registedfunction':
@ -399,6 +311,22 @@ class %s(%s):
return self.methodAction(widget, desc) return self.methodAction(widget, desc)
alert(msg="actiontype invalid",title=acttype) alert(msg="actiontype invalid",title=acttype)
def blocksAction(widget,desc):
target = self.getWidgetByIdPath(widget, desc.get('target','self'))
add_mode = desc.get('mode','replace')
opts = desc.get('options')
d = self.getActionData(widget,desc)
p = opts.get('options',{})
p.update(d)
opts['options'] = p
x = self.widgetBuild(opts,ancestor=widget)
if x is None:
alert(str(opts), title='widugetBuild error')
return
if add_mode == 'replace':
target.clear_widgets()
target.add_widget(x)
def urlwidgetAction(self,widget,desc): def urlwidgetAction(self,widget,desc):
target = self.getWidgetByIdPath(widget, desc.get('target','self')) target = self.getWidgetByIdPath(widget, desc.get('target','self'))
add_mode = desc.get('mode','replace') add_mode = desc.get('mode','replace')
@ -437,8 +365,15 @@ class %s(%s):
def scriptAction(self, widget, desc): def scriptAction(self, widget, desc):
script = desc.get('script') script = desc.get('script')
if script: if not script:
self.eval(script, {'self': widget}) return
target = self.getWidgetByIdPath(widget, desc.get('target','self'))
d = self.getActionData(widget,desc)
ns = {
"self":target
}
ns.update(d)
self.eval(script, ns)
def methodAction(self, widget, desc): def methodAction(self, widget, desc):
method = desc.get('method') method = desc.get('method')

View File

@ -51,6 +51,7 @@ class BlocksApp(App):
self.hc = HttpClient() self.hc = HttpClient()
WindowBase.softinput_mode='below_target' WindowBase.softinput_mode='below_target'
Clock.schedule_once(self.build1) Clock.schedule_once(self.build1)
print('build() called......')
return x return x
def setUserInfo(self,uinfo): def setUserInfo(self,uinfo):
@ -60,6 +61,9 @@ class BlocksApp(App):
d['authcode'] = uinfo.get('authcode','') d['authcode'] = uinfo.get('authcode','')
self.userinfo = d self.userinfo = d
def on_start(self):
print('on_start() called ...')
def build1(self,t): def build1(self,t):
x = None x = None
x = self.blocks.widgetBuild(self.config.root) x = self.blocks.widgetBuild(self.config.root)

View File

@ -103,4 +103,5 @@ class BoxViewer(BoxLayout):
self.dispatch('on_selected',o.getRecord()) self.dispatch('on_selected',o.getRecord())
def getData(self): def getData(self):
self.selected_data['__dataloader__'] = self.dataloader
return self.selected_data return self.selected_data

View File

@ -1,12 +1,14 @@
from kivy.uix.textinput import TextInput from kivy.uix.textinput import TextInput
from kivy.uix.boxlayout import BoxLayout from kivy.uix.boxlayout import BoxLayout
from kivy.core.window import Window from kivy.core.window import Window
from kivycalendar import DatePicker
from .responsivelayout import VResponsiveLayout
from .widgetExt.inputext import FloatInput,IntegerInput, \ from .widgetExt.inputext import FloatInput,IntegerInput, \
StrInput,SelectInput, BoolInput, AmountInput, Password StrInput,SelectInput, BoolInput, AmountInput, Password
from .baseWidget import * from .baseWidget import *
from kivycalendar import DatePicker
from .utils import * from .utils import *
from .i18n import getI18n from .i18n import I18nText, I18n
from .toolbar import Toolbar
""" """
form options form options
{ {
@ -43,6 +45,10 @@ uitypes = {
"orientation":"horizontal", "orientation":"horizontal",
"wclass":StrInput, "wclass":StrInput,
}, },
"password":{
"orientation":"horizontal",
"wclass":Password,
},
"number":{ "number":{
"orientation":"horizontal", "orientation":"horizontal",
"wclass":IntegerInput, "wclass":IntegerInput,
@ -92,7 +98,7 @@ class InputBox(BoxLayout):
def __init__(self, form, **options): def __init__(self, form, **options):
self.form = form self.form = form
self.options = options self.options = options
self.uitype = options.get('uityoe','string') self.uitype = options.get('uitype','string')
self.uidef = uitypes[self.uitype] self.uidef = uitypes[self.uitype]
orientation = self.uidef['orientation'] orientation = self.uidef['orientation']
width = self.form.inputwidth width = self.form.inputwidth
@ -101,7 +107,7 @@ class InputBox(BoxLayout):
kwargs = { kwargs = {
"orientation":orientation, "orientation":orientation,
"size_hint_y":None, "size_hint_y":None,
"height":CSzie(height) "height":height
} }
if width <= 1: if width <= 1:
kwargs['size_hint_x'] = width kwargs['size_hint_x'] = width
@ -114,8 +120,11 @@ class InputBox(BoxLayout):
pos=self.setSize) pos=self.setSize)
self.register_event_type("on_datainput") self.register_event_type("on_datainput")
def on_datainput(self,o,v=None):
print('on_datainput fired ...',o,v)
def init(self): def init(self):
i18n = getI18n() i18n = I18n()
if self.initflag: if self.initflag:
return return
label = self.options.get('label',self.options.get('name')) label = self.options.get('label',self.options.get('name'))
@ -123,7 +132,9 @@ class InputBox(BoxLayout):
label = label + '*' label = label + '*'
kwargs = { kwargs = {
"otext":label, "otext":label,
"font_size":CSize(1) "font_size":CSize(1),
"size_hint_y":None,
"height":CSize(2)
} }
if self.labelwidth<=1: if self.labelwidth<=1:
kwargs['size_hint_x'] = self.labelwidth kwargs['size_hint_x'] = self.labelwidth
@ -139,6 +150,7 @@ class InputBox(BoxLayout):
if self.options.get('tip'): if self.options.get('tip'):
options['hint_text'] = i18n(self.options.get('tip')) options['hint_text'] = i18n(self.options.get('tip'))
print('uitype=',self.options['uitype'], self.uitype, 'uidef=',self.uidef)
self.input_widget = self.uidef['wclass'](**options) self.input_widget = self.uidef['wclass'](**options)
if self.options.get('readonly'): if self.options.get('readonly'):
self.input_widget.disabled = True self.input_widget.disabled = True
@ -166,13 +178,13 @@ class InputBox(BoxLayout):
self.input_widget.setValue(v) self.input_widget.setValue(v)
def getValue(self): def getValue(self):
return self.input_widget.getValue() return {self.options.get('name'):self.input_widget.getValue()}
def defaultToolbar(): def defaultToolbar():
return { return {
img_size:1.5, "img_size":1.5,
text_size:0.7, "text_size":0.7,
tools:[ "tools":[
{ {
"name":"__submit", "name":"__submit",
"img_src":blockImage("clear.png"), "img_src":blockImage("clear.png"),
@ -197,12 +209,6 @@ class Form(BoxLayout):
self.cols = 1 self.cols = 1
self.inputwidth = Window.width / self.cols self.inputwidth = Window.width / self.cols
self.inputheight = CSize(self.options.get('inputheight',3)) self.inputheight = CSize(self.options.get('inputheight',3))
self.toolbar = Toolbar(options.get('toolbar',defaultToolbar()))
self.fsc = VResponsiveLayout(cols=self.cols,
box_width=self.inputwidth)
self.add_widget(self.toolbar)
self.add_widget(self.fsc)
self.register_event_type('on_submit')
self.initflag = False self.initflag = False
self.bind(size=self.on_size, self.bind(size=self.on_size,
pos=self.on_size) pos=self.on_size)
@ -210,20 +216,41 @@ class Form(BoxLayout):
def init(self): def init(self):
if self.initflag: if self.initflag:
return return
self.toolbar = Toolbar(ancestor=self,**self.options.get('toolbar',defaultToolbar()))
self.fsc = VResponsiveLayout(cols=self.cols,
box_width=self.inputwidth)
self.add_widget(self.toolbar)
self.add_widget(self.fsc)
self.register_event_type('on_submit')
self.fieldWidgets=[] self.fieldWidgets=[]
for f in self.options['fields']: for f in self.options['fields']:
w = InputBox(self, self, **f) w = InputBox(self, **f)
# print('w size=',w.size)
self.fsc.add_widget(w) self.fsc.add_widget(w)
self.fieldWidgets.append(w) self.fieldWidgets.append(w)
blocks = App.get_running_app().blocks blocks = App.get_running_app().blocks
wid = getWidgetById(self,'__submit') wid = self.widget_ids['__submit']
# wid = getWidgetById(self,'__submit')
# print('ids=',self.widget_ids.keys())
wid.bind(on_press=self.on_submit_button) wid.bind(on_press=self.on_submit_button)
wid = getWidgetById(self,'__clear') # wid = getWidgetById(self,'__clear')
wid = self.widget_ids['__clear']
wid.bind(on_press=self.on_clear_button) wid.bind(on_press=self.on_clear_button)
self.initflag = True self.initflag = True
def getData(self):
d = {}
for f in self.fieldWidgets:
v = f.getValue()
d.update(v)
return d
def on_submit(self,o,v=None):
print(o,v)
def on_submit_button(self,o,v=None): def on_submit_button(self,o,v=None):
self.dispatch('on_submit') d = self.getData()
self.dispatch('on_submit',self,d)
def on_clear_button(self,o,v=None): def on_clear_button(self,o,v=None):
for fw in self.fieldWidgets: for fw in self.fieldWidgets:

15
kivyblocks/gps.py Normal file
View File

@ -0,0 +1,15 @@
from pyler import gps
class GPS:
def __init__(self):
gps.configure(on_location=self.on_location, on_status=self.on_status)
gps.start()
def on_location(self, **kw):
pass
def on_status(self,**kw):
def __del__(self):
gps.stop()

View File

@ -7,9 +7,8 @@ from .baseWidget import Text
@SingletonDecorator @SingletonDecorator
class I18n: class I18n:
def __init__(self,url): def __init__(self):
self.kvlang={} self.kvlang={}
self.loadUrl = url
self.lang = locale.getdefaultlocale()[0] self.lang = locale.getdefaultlocale()[0]
self.loadI18n(self.lang) self.loadI18n(self.lang)
self.i18nWidgets = [] self.i18nWidgets = []
@ -18,11 +17,11 @@ class I18n:
self.i18nWidgets.append(w) self.i18nWidgets.append(w)
def loadI18n(self,lang): def loadI18n(self,lang):
if not self.loadUrl:
self.kvlang[lang] = {}
return
app = App.get_running_app() app = App.get_running_app()
d = app.hc.get('%s?lang=%s' % (self.loadUrl,lang)) config = getConfig()
url = '%s%s/%s' % (config.uihome, config.i18n_url, lang)
d = app.hc.get(url)
print('i18n() %s get data=' % url, d, type(d))
self.kvlang[lang] = d self.kvlang[lang] = d
def __call__(self,msg,lang=None): def __call__(self,msg,lang=None):
@ -39,10 +38,6 @@ class I18n:
for w in self.i18nWidgets: for w in self.i18nWidgets:
w.changeLang(lang) w.changeLang(lang)
def getI18n(url=None):
i18n=I18n(url)
return i18n
class I18nText(Text): class I18nText(Text):
lang=StringProperty('') lang=StringProperty('')
otext=StringProperty('') otext=StringProperty('')
@ -53,7 +48,7 @@ class I18nText(Text):
if kw.get('otext'): if kw.get('otext'):
del kw['otext'] del kw['otext']
super().__init__(**kw) super().__init__(**kw)
self.i18n = getI18n() self.i18n = I18n()
self.i18n.addI18nWidget(self) self.i18n.addI18nWidget(self)
self.otext = otext self.otext = otext

View File

@ -0,0 +1,36 @@
import os
from appPublic.folderUtils import listFile
from kivy.utils import platform
from .paging import PageLoader
class FileLoader(PageLoader):
def __init__(self, folder='/DCIM',**options):
self.files = []
fold = os.path.abspath(folder)
self.params = options.get('params',{})
suffixes = self.parasm.get('suffixes',[])
rescursive = self.params.get('rescursive',True)
suffixs=[],rescursive=False
for f in listFile(fold, suffixs=suffixes, rescursive=resursive):
x = {
"id":f,
"name":f
}
self.files.append(x)
self.page_rows = options.get('page_rows',1)
self.loading = False
self.total_cnt = len(self.files)
self.total_page = self.total_cnt / self.page_rows
if self.total_cnt % self.page_rows != 0:
self.total_page += 1
self.curpage = 0
def loadPage(self,p):
if p < 1 or p > self.total_page:
return None
beg = self.page_rows * (p - 1)
end = beg + self.page_rows
return self.files[beg:end]

View File

@ -15,7 +15,7 @@ logformdesc = {
"name":"userid", "name":"userid",
"label":"user name", "label":"user name",
"datatype":"str", "datatype":"str",
"uitype":"str" "uitype":"string"
}, },
{ {
"name":"passwd", "name":"passwd",
@ -26,12 +26,14 @@ logformdesc = {
] ]
}, },
"binds":[ "binds":[
{
"wid":"self", "wid":"self",
"event":"on_submit", "event":"on_submit",
"datawidegt":"self", "datawidegt":"self",
"actiontype":"registedfunction", "actiontype":"registedfunction",
"rfname":"setupUserInfo" "rfname":"setupUserInfo"
} }
]
} }
@SingletonDecorator @SingletonDecorator

View File

@ -28,6 +28,25 @@ class PagingButton(Button):
filter filter
} }
""" """
class HttpLoader:
def __init__(self, url, method, params):
self.page_rows = page_rows
self.url = url
self.method = method,
self.params = params
def setParams(self,params):
self.params = params
def load(self, callback, errback):
hc = App.get_running_app().hc
x = hc(self.url,
method=self.method,
params=self.params,
callback=callback,
errback=errback)
class PageLoader: class PageLoader:
def __init__(self, **options): def __init__(self, **options):
self.loading = False self.loading = False
@ -36,12 +55,9 @@ class PageLoader:
self.filter = StrSearchForm(**options['filter']) self.filter = StrSearchForm(**options['filter'])
self.filter.bind(on_submit=self.do_search) self.filter.bind(on_submit=self.do_search)
self.locater = options.get('locater') self.params = options.get('params',{})
self.params = options.get('params')
self.method = options.get('method','GET') self.method = options.get('method','GET')
self.url = options.get('dataurl') self.url = options.get('dataurl')
if not self.url:
raise Exception('dataurl must be present:options=%s' % str(options))
self.total_cnt = 0 self.total_cnt = 0
self.total_page = 0 self.total_page = 0
self.page_rows = options.get('page_rows',0) self.page_rows = options.get('page_rows',0)
@ -83,12 +99,14 @@ class PageLoader:
self.dir = 'up' self.dir = 'up'
def show_page(self,o,d): def show_page(self,o,d):
p = self.curpage * self.page_rows + 1 p = (self.curpage - 1) * self.page_rows + 1
for r in d['rows']: for r in d['rows']:
r['__posInSet__'] = p r['__posInSet__'] = p
p += 1 p += 1
def loadPage(self,p): def loadPage(self,p):
if not self.url:
raise Exception('dataurl must be present:options=%s' % str(options))
self.curpage = p self.curpage = p
self.loading = True self.loading = True
params = self.params.copy() params = self.params.copy()
@ -123,6 +141,7 @@ class RelatedLoader(PageLoader):
def __init__(self, **options): def __init__(self, **options):
super().__init__(**options) super().__init__(**options)
self.adder = options.get('adder') self.adder = options.get('adder')
self.locater = options.get('locater',None)
self.remover = options.get('remover') self.remover = options.get('remover')
self.clearer = options.get('clearer') self.clearer = options.get('clearer')
self.target = options.get('target') self.target = options.get('target')
@ -139,8 +158,6 @@ class RelatedLoader(PageLoader):
self.calculateTotalPage() self.calculateTotalPage()
self.reload() self.reload()
pass
def doBufferMaintain(self): def doBufferMaintain(self):
siz = len(self.objectPages.keys()) siz = len(self.objectPages.keys())
if siz >= self.MaxbufferPage: if siz >= self.MaxbufferPage:
@ -179,6 +196,7 @@ class RelatedLoader(PageLoader):
self.objectPages[self.curpage] = widgets self.objectPages[self.curpage] = widgets
pages = len(self.objectPages.keys()) pages = len(self.objectPages.keys())
loc = 1.0 / float(pages) loc = 1.0 / float(pages)
if self.locater:
if pages == 1: if pages == 1:
self.locater(1) self.locater(1)
elif self.dir == 'up': elif self.dir == 'up':
@ -289,3 +307,15 @@ class Paging(PageLoader):
return return
self.loadPage(self.total_page) self.loadPage(self.total_page)
class OneRecordLoader(PageLoader):
def __init__(self,**options):
PageLoader.__init__(self,**options)
self.adder = options.get('adder')
self.page_rows = 1
def calculateTotalPage(self):
self.total_page = self.total_cnt
def show_page(self,o,d):
self.adder(d['rows'][0])

20
kivyblocks/playlist.py Normal file
View File

@ -0,0 +1,20 @@
class PlayListBase:
def __init__(self, player, url, params, curpos):
self.dataloader = RelatedLoader
def first(self):
pass
def next(self):
pass
def previous(self):
pass
def last(self):
pass
def getSource(self):
pass

View File

@ -5,6 +5,7 @@ import requests
from kivy.event import EventDispatcher from kivy.event import EventDispatcher
from kivy.clock import Clock from kivy.clock import Clock
from kivy.app import App from kivy.app import App
from .login import LoginForm
class NeedLogin(Exception): class NeedLogin(Exception):
pass pass
@ -30,9 +31,6 @@ class ThreadCall(Thread,EventDispatcher):
try: try:
self.rez = self.target(*self.args,**self.kwargs) self.rez = self.target(*self.args,**self.kwargs)
self.dispatch('on_result',self.rez) self.dispatch('on_result',self.rez)
except NeedLogin as e:
lf = LoginForm()
lf.needlogin(url,method,params,headers,callback,errback)
except Exception as e: except Exception as e:
self.dispatch('on_error',e) self.dispatch('on_error',e)
@ -86,13 +84,13 @@ class HttpClient:
self.s = requests.Session() self.s = requests.Session()
self.workers = App.get_running_app().workers self.workers = App.get_running_app().workers
def webcall(self,url,method="GET",params={},headers={}): def webcall(self,url,method="GET",params={},files={},headers={}):
if method in ['GET']: if method in ['GET']:
req = requests.Request(method,url, req = requests.Request(method,url,
params=params,headers=headers) params=params,headers=headers)
else: else:
req = requests.Request(method,url, req = requests.Request(method,url,
data=params,headers=headers) data=params,files=files,headers=headers)
prepped = self.s.prepare_request(req) prepped = self.s.prepare_request(req)
resp = self.s.send(prepped) resp = self.s.send(prepped)
if resp.status_code == 200: if resp.status_code == 200:
@ -114,18 +112,18 @@ class HttpClient:
print('Error', url, method, params, resp.status_code,type(resp.status_code)) print('Error', url, method, params, resp.status_code,type(resp.status_code))
raise Exception('error:%s' % url) raise Exception('error:%s' % url)
def __call__(self,url,method="GET",params={},headers={},callback=None,errback=None): def __call__(self,url,method="GET",params={},headers={},files={},callback=None,errback=None):
def cb(t,resp): def cb(t,resp):
return resp return resp
if callback is None: if callback is None:
try: try:
resp = self.webcall(url, method=method, resp = self.webcall(url, method=method,
params=params, headers=headers) params=params, files=files, headers=headers)
return cb(None,resp) return cb(None,resp)
except NeedLogin as e: except NeedLogin as e:
lf = LoginForm() lf = LoginForm()
lf.needlogin(url,method,params,headers,callback,errback) lf.needlogin(url,method,params,files,headers,callback,errback)
return None return None
except Exception as e: except Exception as e:
if errback is not None: if errback is not None:
@ -135,6 +133,7 @@ class HttpClient:
"url":url, "url":url,
"method":method, "method":method,
"params":params, "params":params,
"files":files,
"headers":headers "headers":headers
} }
self.workers.add(self.webcall,callback,errback,kwargs=kwargs) self.workers.add(self.webcall,callback,errback,kwargs=kwargs)
@ -143,8 +142,8 @@ class HttpClient:
return self.__call__(url,method='GET',params=params, return self.__call__(url,method='GET',params=params,
headers=headers, callback=callback, headers=headers, callback=callback,
errback=errback) errback=errback)
def post(self, url, params={}, headers={}, callback=None, errback=None): def post(self, url, params={}, headers={}, files={}, callback=None, errback=None):
return self.__call__(url,method='POST',params=params, return self.__call__(url,method='POST',params=params, files=files,
headers=headers, callback=callback, headers=headers, callback=callback,
errback=errback) errback=errback)

View File

@ -15,7 +15,7 @@
"root":{ "root":{
"widgettype":"urlwidget", "widgettype":"urlwidget",
"options":{ "options":{
"url":"/toolpage.ui" "url":"/test/loginform.ui"
} }
} }
} }