bugfix
This commit is contained in:
parent
17f605e24b
commit
1d4adac3a3
31627
kivyblocks/blocks.c
31627
kivyblocks/blocks.c
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -1,748 +0,0 @@
|
|||||||
import os
|
|
||||||
import sys
|
|
||||||
import codecs
|
|
||||||
import json
|
|
||||||
from traceback import print_exc
|
|
||||||
|
|
||||||
import kivy
|
|
||||||
from functools import partial
|
|
||||||
|
|
||||||
from appPublic.dictExt import dictExtend
|
|
||||||
from appPublic.folderUtils import ProgramPath
|
|
||||||
from appPublic.dictObject import DictObject
|
|
||||||
from appPublic.Singleton import SingletonDecorator, GlobalEnv
|
|
||||||
from appPublic.datamapping import keyMapping
|
|
||||||
from appPublic.registerfunction import RegisterFunction
|
|
||||||
|
|
||||||
from kivy.logger import Logger
|
|
||||||
from kivy.config import Config
|
|
||||||
from kivy.metrics import sp,dp,mm
|
|
||||||
from kivy.core.window import WindowBase, Window
|
|
||||||
from kivy.properties import BooleanProperty
|
|
||||||
from kivy.uix.widget import Widget
|
|
||||||
from kivy.app import App
|
|
||||||
from kivy.factory import Factory
|
|
||||||
from kivy.uix.video import Video
|
|
||||||
from .baseWidget import *
|
|
||||||
from .toolbar import *
|
|
||||||
from .dg import DataGrid
|
|
||||||
from .utils import *
|
|
||||||
from .serverImageViewer import ServerImageViewer
|
|
||||||
from .vplayer import VPlayer
|
|
||||||
from .form import InputBox, Form, StrSearchForm
|
|
||||||
from .boxViewer import BoxViewer
|
|
||||||
from .tree import Tree, TextTree
|
|
||||||
from .newvideo import Video
|
|
||||||
from .bgcolorbehavior import BGColorBehavior
|
|
||||||
from .orientationlayout import OrientationLayout
|
|
||||||
from .threadcall import HttpClient
|
|
||||||
from .register import *
|
|
||||||
|
|
||||||
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__()
|
|
||||||
|
|
||||||
def registerWidget(name,widget):
|
|
||||||
globals()[name] = widget
|
|
||||||
|
|
||||||
|
|
||||||
class Blocks(EventDispatcher):
|
|
||||||
def __init__(self):
|
|
||||||
EventDispatcher.__init__(self)
|
|
||||||
self.action_id = 0
|
|
||||||
self.register_event_type('on_built')
|
|
||||||
self.register_event_type('on_failed')
|
|
||||||
self.env = GlobalEnv()
|
|
||||||
|
|
||||||
def set(self,k,v):
|
|
||||||
self.env[k] = v
|
|
||||||
|
|
||||||
def register_widget(self,name,widget):
|
|
||||||
globals()[name] = widget
|
|
||||||
|
|
||||||
def buildAction(self,widget,desc):
|
|
||||||
conform_desc = desc.get('conform')
|
|
||||||
blocks = Blocks()
|
|
||||||
if not conform_desc:
|
|
||||||
return partial(blocks.uniaction, widget, desc)
|
|
||||||
l = {
|
|
||||||
}
|
|
||||||
body="""def action(widget, *args, **kw):
|
|
||||||
jsonstr='''%s'''
|
|
||||||
desc = json.loads(jsonstr)
|
|
||||||
conform_desc = desc.get('conform')
|
|
||||||
blocks = Blocks()
|
|
||||||
if not conform_desc:
|
|
||||||
blocks.uniaction(widget, desc,*args, **kw)
|
|
||||||
return
|
|
||||||
w = blocks.widgetBuild({
|
|
||||||
"widgettype":"Conform",
|
|
||||||
"options":conform_desc
|
|
||||||
})
|
|
||||||
w.bind(on_conform=partial(blocks.uniaction, widget, desc))
|
|
||||||
w.open()
|
|
||||||
print('Conform show.....')
|
|
||||||
""" % (json.dumps(desc))
|
|
||||||
exec(body,globals(),l)
|
|
||||||
f = l.get('action',None)
|
|
||||||
if f is None:
|
|
||||||
raise Exception('None Function')
|
|
||||||
func =partial(f,widget)
|
|
||||||
return func
|
|
||||||
|
|
||||||
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
|
|
||||||
g.update(self.env)
|
|
||||||
return eval(s,g,l)
|
|
||||||
|
|
||||||
def getUrlData(self,url,method='GET',params={}, files={},
|
|
||||||
callback=None,
|
|
||||||
errback=None,**kw):
|
|
||||||
|
|
||||||
if url is None:
|
|
||||||
if errback:
|
|
||||||
errback(None,Exception('url is None'))
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
if url.startswith('file://'):
|
|
||||||
filename = url[7:]
|
|
||||||
with codecs.open(filename,'r','utf-8') as f:
|
|
||||||
b = f.read()
|
|
||||||
dic = json.loads(b)
|
|
||||||
return dic
|
|
||||||
elif url.startswith('http://') or url.startswith('https://'):
|
|
||||||
try:
|
|
||||||
hc = HttpClient()
|
|
||||||
resp=hc(url,method=method,params=params,files=files)
|
|
||||||
# print('Blocks.py :resp=',resp)
|
|
||||||
return resp
|
|
||||||
except Exception as e:
|
|
||||||
print_exc()
|
|
||||||
if errback:
|
|
||||||
return errback(None,e)
|
|
||||||
return None
|
|
||||||
else:
|
|
||||||
config = getConfig()
|
|
||||||
url = config.uihome + url
|
|
||||||
return self.getUrlData(url,method=method,
|
|
||||||
params=params,
|
|
||||||
files=files,
|
|
||||||
**kw)
|
|
||||||
|
|
||||||
def strValueExpr(self,s:str,localnamespace:dict={}):
|
|
||||||
if not s.startswith('py::'):
|
|
||||||
return s
|
|
||||||
s = s[4:]
|
|
||||||
try:
|
|
||||||
v = self.eval(s,localnamespace)
|
|
||||||
return v
|
|
||||||
except Exception as e:
|
|
||||||
print('Exception .... ',e,'script=',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) == type({}):
|
|
||||||
return self.dictValueExpr(obj,localnamespace)
|
|
||||||
if isinstance(obj,DictObject):
|
|
||||||
return self.dictValueExpr(obj,localnamespace)
|
|
||||||
return obj
|
|
||||||
|
|
||||||
def w_build(self,desc:dict):
|
|
||||||
# print('w_build(),desc=',desc)
|
|
||||||
widgetClass = desc.get('widgettype',None)
|
|
||||||
if not widgetClass:
|
|
||||||
Logger.info("Block: w_build(), desc invalid", desc)
|
|
||||||
raise Exception(desc)
|
|
||||||
|
|
||||||
widgetClass = desc['widgettype']
|
|
||||||
opts = self.valueExpr(desc.get('options',{}).copy())
|
|
||||||
widget = None
|
|
||||||
try:
|
|
||||||
klass = Factory.get(widgetClass)
|
|
||||||
widget = klass(**opts)
|
|
||||||
except Exception as e:
|
|
||||||
print('Error:',widgetClass,'contructon error')
|
|
||||||
print_exc()
|
|
||||||
raise NotExistsObject(widgetClass)
|
|
||||||
|
|
||||||
if desc.get('id'):
|
|
||||||
id = desc.get('id')
|
|
||||||
if id.startswith('app.'):
|
|
||||||
app = App.get_running_app()
|
|
||||||
id = id[4:]
|
|
||||||
setattr(app, id, widget)
|
|
||||||
if id.startswith('root.'):
|
|
||||||
app = App.get_running_app()
|
|
||||||
id = id[5:]
|
|
||||||
setattr(app.root, id, widget)
|
|
||||||
|
|
||||||
if '.' in id:
|
|
||||||
Logger.info('widget id(%s) can not contain "."', id)
|
|
||||||
else:
|
|
||||||
widget.widget_id = id
|
|
||||||
|
|
||||||
widget.build_desc = desc
|
|
||||||
self.build_attributes(widget,desc)
|
|
||||||
self.build_rest(widget,desc)
|
|
||||||
return widget
|
|
||||||
|
|
||||||
def build_attributes(self,widget,desc,t=None):
|
|
||||||
excludes = ['widgettype','options','subwidgets','binds']
|
|
||||||
for k,v in [(k,v) for k,v in desc.items() if k not in excludes]:
|
|
||||||
if isinstance(v,dict) and v.get('widgettype'):
|
|
||||||
b = Blocks()
|
|
||||||
v = self.valueExpr(v, localnamespace={'self':widget})
|
|
||||||
w = b.w_build(v)
|
|
||||||
if hasattr(widget,k):
|
|
||||||
aw = getattr(widget,k)
|
|
||||||
if isinstance(aw,Layout):
|
|
||||||
aw.add_widget(w)
|
|
||||||
continue
|
|
||||||
setattr(widget,k,w)
|
|
||||||
continue
|
|
||||||
setattr(widget,k,self.valueExpr(v,\
|
|
||||||
localnamespace={'self':widget}))
|
|
||||||
|
|
||||||
def build_rest(self, widget,desc,t=None):
|
|
||||||
self.subwidget_total = len(desc.get('subwidgets',[]))
|
|
||||||
self.subwidgets = [ None for i in range(self.subwidget_total)]
|
|
||||||
pos = 0
|
|
||||||
for pos,sw in enumerate(desc.get('subwidgets',[])):
|
|
||||||
b = Blocks()
|
|
||||||
kw = self.valueExpr(sw.copy(),
|
|
||||||
localnamespace={'self':widget})
|
|
||||||
w = b.widgetBuild(kw)
|
|
||||||
widget.add_widget(w)
|
|
||||||
|
|
||||||
for b in desc.get('binds',[]):
|
|
||||||
kw = self.valueExpr(b.copy(), \
|
|
||||||
localnamespace={'self':widget})
|
|
||||||
self.buildBind(widget,kw)
|
|
||||||
|
|
||||||
def buildBind(self,widget,desc):
|
|
||||||
wid = desc.get('wid','self')
|
|
||||||
w = Blocks.getWidgetById(desc.get('wid','self'),from_widget=widget)
|
|
||||||
if not w:
|
|
||||||
Logger.info('Block: %s %s',desc.get('wid','self'),
|
|
||||||
'not found via Blocks.getWidgetById()')
|
|
||||||
return
|
|
||||||
event = desc.get('event')
|
|
||||||
if event is None:
|
|
||||||
Logger.info('Block: binds desc miss event, desc=%s',str(desc))
|
|
||||||
return
|
|
||||||
f = self.buildAction(widget,desc)
|
|
||||||
if f is None:
|
|
||||||
Logger.info('Block: get a null function,%s',str(desc))
|
|
||||||
return
|
|
||||||
w.bind(**{event:f})
|
|
||||||
# Logger.info('Block: %s bind built', str(desc))
|
|
||||||
|
|
||||||
def multipleAction(self, widget, desc, *args):
|
|
||||||
desc1 = {k:v for k, v in desc.items() if k != 'actions'}
|
|
||||||
mydesc = desc1.copy()
|
|
||||||
for a in desc['actions']:
|
|
||||||
new_desc = mydesc.copy()
|
|
||||||
new_desc.update(a)
|
|
||||||
self.uniaction(widget,new_desc, *args)
|
|
||||||
|
|
||||||
def uniaction(self,widget,desc, *args):
|
|
||||||
Logger.info('Block: uniaction() called, desc=%s', str(desc))
|
|
||||||
|
|
||||||
acttype = desc.get('actiontype')
|
|
||||||
if acttype=='blocks':
|
|
||||||
return self.blocksAction(widget,desc, *args)
|
|
||||||
if acttype=='urlwidget':
|
|
||||||
return self.urlwidgetAction(widget,desc, *args)
|
|
||||||
if acttype == 'registedfunction':
|
|
||||||
return self.registedfunctionAction(widget,desc, *args)
|
|
||||||
if acttype == 'script':
|
|
||||||
return self.scriptAction(widget, desc, *args)
|
|
||||||
if acttype == 'method':
|
|
||||||
return self.methodAction(widget, desc, *args)
|
|
||||||
if acttype == 'event':
|
|
||||||
return self.eventAction(widget, desc, *args)
|
|
||||||
if acttype == 'multiple':
|
|
||||||
return self.multipleAction(widget, desc, *args)
|
|
||||||
|
|
||||||
alert("actiontype(%s) invalid" % acttype,title='error')
|
|
||||||
|
|
||||||
def eventAction(self, widget, desc, *args):
|
|
||||||
target = self.get_target(widget, desc)
|
|
||||||
event = desc.get('dispatch_event')
|
|
||||||
if not event:
|
|
||||||
Logger.info('Block: eventAction():desc(%s) miss dispatch_event',
|
|
||||||
str(desc))
|
|
||||||
return
|
|
||||||
params = desc.get('params',{})
|
|
||||||
d = self.getActionData(widget,desc, *args)
|
|
||||||
if d:
|
|
||||||
params.update(d)
|
|
||||||
try:
|
|
||||||
target.dispatch(event, params)
|
|
||||||
except Exception as e:
|
|
||||||
Logger.info(f'Block: eventAction():dispatch {event} error')
|
|
||||||
print_exc()
|
|
||||||
return
|
|
||||||
|
|
||||||
def get_target(self, widget, desc):
|
|
||||||
if not desc.get('target'):
|
|
||||||
return None
|
|
||||||
return Blocks.getWidgetById(desc.get('target'),from_widget=widget)
|
|
||||||
|
|
||||||
def blocksAction(self,widget,desc, *args):
|
|
||||||
target = self.get_target(widget, desc)
|
|
||||||
add_mode = desc.get('mode','replace')
|
|
||||||
opts = desc.get('options').copy()
|
|
||||||
d = self.getActionData(widget,desc, *args)
|
|
||||||
p = opts.get('options',{}).copy()
|
|
||||||
if d:
|
|
||||||
p.update(d)
|
|
||||||
opts['options'] = p
|
|
||||||
def doit(target,add_mode,o,w):
|
|
||||||
if target:
|
|
||||||
if add_mode == 'replace':
|
|
||||||
target.clear_widgets()
|
|
||||||
target.add_widget(w)
|
|
||||||
|
|
||||||
def doerr(o,e):
|
|
||||||
Logger.info('Block: blocksAction(): desc=%s widgetBuild error'
|
|
||||||
,str(desc))
|
|
||||||
raise e
|
|
||||||
|
|
||||||
b = Blocks()
|
|
||||||
b.bind(on_built=partial(doit,target,add_mode))
|
|
||||||
b.bind(on_failed=doerr)
|
|
||||||
b.widgetBuild(opts)
|
|
||||||
|
|
||||||
def urlwidgetAction(self,widget,desc, *args):
|
|
||||||
target = self.get_target(widget, desc)
|
|
||||||
add_mode = desc.get('mode','replace')
|
|
||||||
opts = desc.get('options').copy()
|
|
||||||
p = opts.get('params',{}).copy()
|
|
||||||
if len(args) >= 1 and isinstance(args[0],dict):
|
|
||||||
p.update(args[0])
|
|
||||||
d = self.getActionData(widget, desc, *args)
|
|
||||||
if d:
|
|
||||||
p.update(d)
|
|
||||||
opts['params'] = p
|
|
||||||
d = {
|
|
||||||
'widgettype' : 'urlwidget',
|
|
||||||
'options': opts
|
|
||||||
}
|
|
||||||
|
|
||||||
def doit(target,add_mode,o,w):
|
|
||||||
if target:
|
|
||||||
if add_mode == 'replace':
|
|
||||||
target.clear_widgets()
|
|
||||||
target.add_widget(w)
|
|
||||||
|
|
||||||
def doerr(o,e):
|
|
||||||
Logger.info('Block: urlwidgetAction(): desc=%s widgetBuild error'
|
|
||||||
,str(desc))
|
|
||||||
|
|
||||||
b = Blocks()
|
|
||||||
b.bind(on_built=partial(doit,target,add_mode))
|
|
||||||
b.bind(on_failed=doerr)
|
|
||||||
b.widgetBuild(d)
|
|
||||||
|
|
||||||
def getActionData(self,widget,desc,*args):
|
|
||||||
data = {}
|
|
||||||
rtdesc = self.build_rtdesc(desc)
|
|
||||||
rt = self.get_rtdata(widget, rtdesc, *args)
|
|
||||||
data.update(rt)
|
|
||||||
if desc.get('keymapping'):
|
|
||||||
data = keyMapping(data, desc.get('keymapping'))
|
|
||||||
return data
|
|
||||||
|
|
||||||
def registedfunctionAction(self, widget, desc, *args):
|
|
||||||
target = self.get_target(widget, desc)
|
|
||||||
rf = RegisterFunction()
|
|
||||||
name = desc.get('rfname')
|
|
||||||
func = rf.get(name)
|
|
||||||
if func is None:
|
|
||||||
Logger.info('Block: desc=%s rfname(%s) not found',
|
|
||||||
str(desc), name)
|
|
||||||
raise Exception('rfname(%s) not found' % name)
|
|
||||||
|
|
||||||
params = desc.get('params',{}).copy()
|
|
||||||
d = self.getActionData(widget,desc, *args)
|
|
||||||
if d:
|
|
||||||
params.update(d)
|
|
||||||
func(target, *args, **params)
|
|
||||||
|
|
||||||
def scriptAction(self, widget, desc, *args):
|
|
||||||
script = desc.get('script')
|
|
||||||
if not script:
|
|
||||||
Logger.info('Block: scriptAction():desc(%s) target not found',
|
|
||||||
str(desc))
|
|
||||||
return
|
|
||||||
target = self.get_target(widget, desc)
|
|
||||||
d = self.getActionData(widget,desc, *args)
|
|
||||||
ns = {
|
|
||||||
"self":target,
|
|
||||||
"args":args
|
|
||||||
}
|
|
||||||
if d:
|
|
||||||
ns.update(d)
|
|
||||||
try:
|
|
||||||
self.eval(script, ns)
|
|
||||||
except Exception as e:
|
|
||||||
print_exc()
|
|
||||||
print(e)
|
|
||||||
|
|
||||||
def build_rtdesc(self, desc):
|
|
||||||
rtdesc = desc.get('rtdata')
|
|
||||||
if not rtdesc:
|
|
||||||
if desc.get('datawidget'):
|
|
||||||
rtdesc = {}
|
|
||||||
rtdesc['target'] = desc['datawidget']
|
|
||||||
if desc.get('datascript'):
|
|
||||||
rtdesc['script'] = desc.get('datacript')
|
|
||||||
else:
|
|
||||||
rtdesc['method'] = desc.get('datamethod', 'getValue')
|
|
||||||
rtdesc['kwargs'] = desc.get('datakwargs', {})
|
|
||||||
else:
|
|
||||||
return {}
|
|
||||||
return rtdesc
|
|
||||||
|
|
||||||
def get_rtdata(self, widget, desc, *args):
|
|
||||||
"""
|
|
||||||
desc descript follow attributes
|
|
||||||
{
|
|
||||||
"target", a target name from widget
|
|
||||||
"method", a method name, default is 'getValue',
|
|
||||||
"script", script to handle the data
|
|
||||||
"kwargs":" a dict arguments, default is {}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
if desc is None or desc == {}:
|
|
||||||
print('get_rtdata():desc is None')
|
|
||||||
return {}
|
|
||||||
kwargs = desc.get('kwargs', {})
|
|
||||||
if not isinstance(kwargs, dict):
|
|
||||||
kwargs = {}
|
|
||||||
w = None
|
|
||||||
if len(args) > 0:
|
|
||||||
w = args[0]
|
|
||||||
target = desc.get('target')
|
|
||||||
if target:
|
|
||||||
w = self.getWidgetById(target, from_widget=widget)
|
|
||||||
if w is None:
|
|
||||||
print('get_rtdata():w is None', desc)
|
|
||||||
return {}
|
|
||||||
script = desc.get('script')
|
|
||||||
if script:
|
|
||||||
ns = {
|
|
||||||
"self":w,
|
|
||||||
"args":args,
|
|
||||||
"kwargs":kwargs
|
|
||||||
}
|
|
||||||
d = self.eval(script, ns)
|
|
||||||
return d
|
|
||||||
|
|
||||||
method = desc.get('method', 'getValue')
|
|
||||||
if not hasattr(w, method):
|
|
||||||
print('get_rtdata():method is None', desc, type(w))
|
|
||||||
return {}
|
|
||||||
f = getattr(w, method)
|
|
||||||
try:
|
|
||||||
r = f(**kwargs)
|
|
||||||
if isinstance(r, dict):
|
|
||||||
return r
|
|
||||||
if isinstance(r, DictObject):
|
|
||||||
return r.to_dict()
|
|
||||||
print('get_rtdata():method return is not dict', desc, 'ret=', r, type(r))
|
|
||||||
return {}
|
|
||||||
except:
|
|
||||||
print_exc()
|
|
||||||
return {}
|
|
||||||
|
|
||||||
def methodAction(self, widget, desc, *args):
|
|
||||||
method = desc.get('method')
|
|
||||||
target = self.get_target(widget, desc)
|
|
||||||
if target is None:
|
|
||||||
Logger.info('Block: methodAction():desc(%s) target not found',
|
|
||||||
str(desc))
|
|
||||||
return
|
|
||||||
if method is None:
|
|
||||||
Logger.info('Block: methodAction():desc(%s) method not found',
|
|
||||||
str(desc))
|
|
||||||
return
|
|
||||||
if hasattr(target,method):
|
|
||||||
f = getattr(target, method)
|
|
||||||
kwargs = desc.get('options',{}).copy()
|
|
||||||
d = self.getActionData(widget,desc, *args)
|
|
||||||
if d:
|
|
||||||
kwargs.update(d)
|
|
||||||
f(*args, **kwargs)
|
|
||||||
else:
|
|
||||||
alert('%s method not found' % method)
|
|
||||||
|
|
||||||
def widgetBuild(self,desc):
|
|
||||||
"""
|
|
||||||
desc format:
|
|
||||||
{
|
|
||||||
widgettype:<registered widget>,
|
|
||||||
id:widget id,
|
|
||||||
options:{}
|
|
||||||
subwidgets:[
|
|
||||||
]
|
|
||||||
binds:[
|
|
||||||
]
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
def doit(desc):
|
|
||||||
if isinstance(desc,DictObject):
|
|
||||||
desc = desc.to_dict()
|
|
||||||
if not isinstance(desc,dict):
|
|
||||||
Logger.info('Block: desc(%s) must be a dict object(%s)',
|
|
||||||
desc,type(desc))
|
|
||||||
return None
|
|
||||||
|
|
||||||
# desc = self.valueExpr(desc)
|
|
||||||
try:
|
|
||||||
widget = self.w_build(desc)
|
|
||||||
self.dispatch('on_built',widget)
|
|
||||||
if hasattr(widget,'ready'):
|
|
||||||
widget.ready = True
|
|
||||||
return widget
|
|
||||||
except Exception as e:
|
|
||||||
print_exc()
|
|
||||||
self.dispatch('on_failed',e)
|
|
||||||
return None
|
|
||||||
|
|
||||||
if isinstance(desc,DictObject):
|
|
||||||
desc = desc.to_dict()
|
|
||||||
if not isinstance(desc, dict):
|
|
||||||
print('widgetBuild1: desc must be a dict object',
|
|
||||||
desc,type(desc))
|
|
||||||
self.dispatch('on_failed',Exception('miss url'))
|
|
||||||
return
|
|
||||||
|
|
||||||
widgettype = desc.get('widgettype')
|
|
||||||
while widgettype == "urlwidget":
|
|
||||||
opts = desc.get('options',{}).copy()
|
|
||||||
extend = desc.get('extend')
|
|
||||||
addon = None
|
|
||||||
if desc.get('extend'):
|
|
||||||
addon = desc.get('extend').copy()
|
|
||||||
url = opts.get('url')
|
|
||||||
if url is None:
|
|
||||||
self.dispatch('on_failed',Exception('miss url'))
|
|
||||||
return
|
|
||||||
|
|
||||||
if opts.get('url'):
|
|
||||||
del opts['url']
|
|
||||||
rtdesc = self.build_rtdesc(opts)
|
|
||||||
if rtdesc:
|
|
||||||
rtdata = self.get_rtdata(None, rtdesc)
|
|
||||||
params = opts.get('params', {})
|
|
||||||
params.update(rtdata)
|
|
||||||
opts['params'] = params
|
|
||||||
|
|
||||||
desc = self.getUrlData(url,**opts)
|
|
||||||
if not (isinstance(desc, DictObject) or \
|
|
||||||
isinstance(desc, dict)):
|
|
||||||
print('Block2: desc must be a dict object',
|
|
||||||
desc,type(desc))
|
|
||||||
self.dispatch('on_failed',Exception('miss url'))
|
|
||||||
return
|
|
||||||
|
|
||||||
if addon:
|
|
||||||
desc = dictExtend(desc,addon)
|
|
||||||
widgettype = desc.get('widgettype')
|
|
||||||
if widgettype is None:
|
|
||||||
print('Block3: desc must be a dict object not None')
|
|
||||||
return None
|
|
||||||
return doit(desc)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def getWidgetById(self,id,from_widget=None):
|
|
||||||
def find_widget_by_id(id, from_widget):
|
|
||||||
if id=='self':
|
|
||||||
return from_widget
|
|
||||||
if hasattr(from_widget,'widget_id'):
|
|
||||||
if from_widget.widget_id == id:
|
|
||||||
return from_widget
|
|
||||||
if id[0] == '-' and from_widget.widget_id == id[1:]:
|
|
||||||
return from_widget
|
|
||||||
if hasattr(from_widget, id):
|
|
||||||
w = getattr(from_widget,id)
|
|
||||||
return w
|
|
||||||
|
|
||||||
if id[0] == '-':
|
|
||||||
print('find_widget_by_id(), id=', id,
|
|
||||||
'widget=', from_widget)
|
|
||||||
if isinstance(from_widget, WindowBase):
|
|
||||||
return None
|
|
||||||
if from_widget.parent:
|
|
||||||
return find_widget_by_id(id,
|
|
||||||
from_widget=from_widget.parent)
|
|
||||||
return None
|
|
||||||
else:
|
|
||||||
for c in from_widget.children:
|
|
||||||
ret = find_widget_by_id(id,from_widget=c)
|
|
||||||
if ret:
|
|
||||||
return ret
|
|
||||||
return None
|
|
||||||
|
|
||||||
ids = id.split('.')
|
|
||||||
app = App.get_running_app()
|
|
||||||
fid = ids[0]
|
|
||||||
if fid == '/self' or fid == 'root':
|
|
||||||
from_widget = app.root
|
|
||||||
if len(ids) == 1:
|
|
||||||
return from_widget
|
|
||||||
ids = ids[1:]
|
|
||||||
if fid == 'Window':
|
|
||||||
from_widget == Window
|
|
||||||
if len(ids) == 1:
|
|
||||||
return from_widget
|
|
||||||
ids = ids[1:]
|
|
||||||
if fid == 'app':
|
|
||||||
return app
|
|
||||||
|
|
||||||
if from_widget is None:
|
|
||||||
from_widget = app.root
|
|
||||||
for id in ids:
|
|
||||||
w = find_widget_by_id(id,from_widget=from_widget)
|
|
||||||
if w is None \
|
|
||||||
and id == ids[0] \
|
|
||||||
and Window.fullscreen == True \
|
|
||||||
and app.root != app.fs_widget:
|
|
||||||
w = find_widget_by_id(id, app.fs_widget)
|
|
||||||
if w is None:
|
|
||||||
print(id, 'not found ....')
|
|
||||||
return None
|
|
||||||
from_widget = w
|
|
||||||
return w
|
|
||||||
|
|
||||||
def on_built(self,v=None):
|
|
||||||
return
|
|
||||||
|
|
||||||
def on_failed(self,e=None):
|
|
||||||
return
|
|
||||||
|
|
||||||
Factory.register('Blocks',Blocks)
|
|
||||||
Factory.register('Video',Video)
|
|
||||||
Factory.register('OrientationLayout', OrientationLayout)
|
|
@ -1,742 +0,0 @@
|
|||||||
import os
|
|
||||||
import sys
|
|
||||||
import codecs
|
|
||||||
import ujson as json
|
|
||||||
from traceback import print_exc
|
|
||||||
|
|
||||||
from functools import partial
|
|
||||||
|
|
||||||
from appPublic.dictExt import dictExtend
|
|
||||||
from appPublic.folderUtils import ProgramPath
|
|
||||||
from appPublic.dictObject import DictObject
|
|
||||||
from appPublic.Singleton import SingletonDecorator, GlobalEnv
|
|
||||||
from appPublic.datamapping import keyMapping
|
|
||||||
from appPublic.registerfunction import RegisterFunction
|
|
||||||
|
|
||||||
from kivy.logger import Logger
|
|
||||||
from kivy.config import Config
|
|
||||||
from kivy.metrics import sp,dp,mm
|
|
||||||
from kivy.core.window import WindowBase, Window
|
|
||||||
from kivy.properties import BooleanProperty
|
|
||||||
from kivy.uix.widget import Widget
|
|
||||||
from kivy.uix.modalview import ModalView
|
|
||||||
from kivy.app import App
|
|
||||||
from kivy.factory import Factory
|
|
||||||
from kivy.uix.video import Video
|
|
||||||
from .utils import *
|
|
||||||
from .newvideo import Video
|
|
||||||
from .orientationlayout import OrientationLayout
|
|
||||||
from .threadcall import HttpClient
|
|
||||||
from .register import *
|
|
||||||
|
|
||||||
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:str):
|
|
||||||
super().__init__()
|
|
||||||
self.widget_name = name
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
s = 'not reigsted widget(%s)' % self.name
|
|
||||||
return s
|
|
||||||
|
|
||||||
def __expr__(self):
|
|
||||||
return self.__str__()
|
|
||||||
|
|
||||||
def registerWidget(name:str,widget):
|
|
||||||
globals()[name] = widget
|
|
||||||
|
|
||||||
|
|
||||||
class Blocks(EventDispatcher):
|
|
||||||
def __init__(self):
|
|
||||||
EventDispatcher.__init__(self)
|
|
||||||
self.action_id = 0
|
|
||||||
self.register_event_type('on_built')
|
|
||||||
self.register_event_type('on_failed')
|
|
||||||
self.env = GlobalEnv()
|
|
||||||
|
|
||||||
def set(self, k:str, v):
|
|
||||||
self.env[k] = v
|
|
||||||
|
|
||||||
def register_widget(self, name:str, widget:Widget):
|
|
||||||
globals()[name] = widget
|
|
||||||
|
|
||||||
def buildAction(self, widget:Widget, desc):
|
|
||||||
conform_desc = desc.get('conform')
|
|
||||||
blocks = Blocks()
|
|
||||||
if not conform_desc:
|
|
||||||
return partial(blocks.uniaction, widget, desc)
|
|
||||||
func =partial(blocks.conform_action,widget, desc)
|
|
||||||
return func
|
|
||||||
|
|
||||||
def eval(self, s:str, l:dict):
|
|
||||||
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__']
|
|
||||||
g['__builtins__']['__import__'] = None
|
|
||||||
g['__builtins__']['__loader__'] = None
|
|
||||||
g['__builtins__']['open'] = None
|
|
||||||
"""
|
|
||||||
g.update(self.env)
|
|
||||||
return eval(s,g,l)
|
|
||||||
|
|
||||||
def getUrlData(self, url:str, method:str='GET',
|
|
||||||
params:dict={}, files:dict={},
|
|
||||||
callback=None,
|
|
||||||
errback=None,**kw):
|
|
||||||
|
|
||||||
if url is None:
|
|
||||||
if errback:
|
|
||||||
errback(None,Exception('url is None'))
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
if url.startswith('file://'):
|
|
||||||
filename = url[7:]
|
|
||||||
with codecs.open(filename,'r','utf-8') as f:
|
|
||||||
b = f.read()
|
|
||||||
dic = json.loads(b)
|
|
||||||
return dic
|
|
||||||
elif url.startswith('http://') or url.startswith('https://'):
|
|
||||||
try:
|
|
||||||
hc = HttpClient()
|
|
||||||
resp=hc(url,method=method,params=params,files=files)
|
|
||||||
# print('Blocks.py :resp=',resp)
|
|
||||||
return resp
|
|
||||||
except Exception as e:
|
|
||||||
print_exc()
|
|
||||||
if errback:
|
|
||||||
return errback(None,e)
|
|
||||||
return None
|
|
||||||
else:
|
|
||||||
config = getConfig()
|
|
||||||
url = config.uihome + url
|
|
||||||
return self.getUrlData(url,method=method,
|
|
||||||
params=params,
|
|
||||||
files=files,
|
|
||||||
**kw)
|
|
||||||
|
|
||||||
def strValueExpr(self,s:str,localnamespace:dict={}):
|
|
||||||
if not s.startswith('py::'):
|
|
||||||
return s
|
|
||||||
s = s[4:]
|
|
||||||
try:
|
|
||||||
v = self.eval(s,localnamespace)
|
|
||||||
return v
|
|
||||||
except Exception as e:
|
|
||||||
print('Exception .... ',e,'script=',s)
|
|
||||||
print_exc()
|
|
||||||
return s
|
|
||||||
|
|
||||||
def arrayValueExpr(self,arr:list,localnamespace:dict={}) -> list:
|
|
||||||
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={}) -> 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:dict={}):
|
|
||||||
if type(obj) == type(''):
|
|
||||||
return self.strValueExpr(obj,localnamespace)
|
|
||||||
if type(obj) == type([]):
|
|
||||||
return self.arrayValueExpr(obj,localnamespace)
|
|
||||||
if type(obj) == type({}):
|
|
||||||
return self.dictValueExpr(obj,localnamespace)
|
|
||||||
if isinstance(obj,DictObject):
|
|
||||||
return self.dictValueExpr(obj,localnamespace)
|
|
||||||
return obj
|
|
||||||
|
|
||||||
def w_build(self,desc) -> Widget:
|
|
||||||
# print('w_build(),desc=',desc)
|
|
||||||
widgetClass = desc.get('widgettype',None)
|
|
||||||
if not widgetClass:
|
|
||||||
Logger.info("Block: w_build(), desc invalid", desc)
|
|
||||||
raise Exception(desc)
|
|
||||||
|
|
||||||
widgetClass = desc['widgettype']
|
|
||||||
opts = self.valueExpr(desc.get('options',{}).copy())
|
|
||||||
widget = None
|
|
||||||
try:
|
|
||||||
klass = Factory.get(widgetClass)
|
|
||||||
widget = klass(**opts)
|
|
||||||
except Exception as e:
|
|
||||||
print('Error:',widgetClass,'contructon error')
|
|
||||||
print_exc()
|
|
||||||
raise NotExistsObject(widgetClass)
|
|
||||||
|
|
||||||
if desc.get('id'):
|
|
||||||
id = desc.get('id')
|
|
||||||
if id.startswith('app.'):
|
|
||||||
app = App.get_running_app()
|
|
||||||
id = id[4:]
|
|
||||||
setattr(app, id, widget)
|
|
||||||
if id.startswith('root.'):
|
|
||||||
app = App.get_running_app()
|
|
||||||
id = id[5:]
|
|
||||||
setattr(app.root, id, widget)
|
|
||||||
|
|
||||||
if '.' in id:
|
|
||||||
Logger.info('widget id(%s) can not contain "."', id)
|
|
||||||
else:
|
|
||||||
widget.widget_id = id
|
|
||||||
|
|
||||||
widget.build_desc = desc
|
|
||||||
self.build_attributes(widget,desc)
|
|
||||||
self.build_rest(widget,desc)
|
|
||||||
return widget
|
|
||||||
|
|
||||||
def build_attributes(self, widget:Widget,desc,t=None):
|
|
||||||
excludes = ['widgettype','options','subwidgets','binds']
|
|
||||||
for k,v in [(k,v) for k,v in desc.items() if k not in excludes]:
|
|
||||||
if isinstance(v,dict) and v.get('widgettype'):
|
|
||||||
b = Blocks()
|
|
||||||
v = self.valueExpr(v, localnamespace={'self':widget})
|
|
||||||
w = b.w_build(v)
|
|
||||||
if hasattr(widget,k):
|
|
||||||
aw = getattr(widget,k)
|
|
||||||
if isinstance(aw,Layout):
|
|
||||||
aw.add_widget(w)
|
|
||||||
continue
|
|
||||||
setattr(widget,k,w)
|
|
||||||
continue
|
|
||||||
setattr(widget,k,self.valueExpr(v,\
|
|
||||||
localnamespace={'self':widget}))
|
|
||||||
|
|
||||||
def build_rest(self, widget:Widget,desc,t=None):
|
|
||||||
self.subwidget_total = len(desc.get('subwidgets',[]))
|
|
||||||
self.subwidgets = [ None for i in range(self.subwidget_total)]
|
|
||||||
cdef int pos = 0
|
|
||||||
for pos,sw in enumerate(desc.get('subwidgets',[])):
|
|
||||||
b = Blocks()
|
|
||||||
kw = self.valueExpr(sw.copy(),
|
|
||||||
localnamespace={'self':widget})
|
|
||||||
w = b.widgetBuild(kw)
|
|
||||||
widget.add_widget(w)
|
|
||||||
|
|
||||||
for b in desc.get('binds',[]):
|
|
||||||
kw = self.valueExpr(b.copy(), \
|
|
||||||
localnamespace={'self':widget})
|
|
||||||
self.buildBind(widget,kw)
|
|
||||||
|
|
||||||
def buildBind(self, widget:Widget, desc):
|
|
||||||
wid = desc.get('wid','self')
|
|
||||||
w = Blocks.getWidgetById(desc.get('wid','self'),from_widget=widget)
|
|
||||||
if not w:
|
|
||||||
Logger.info('Block: %s %s',desc.get('wid','self'),
|
|
||||||
'not found via Blocks.getWidgetById()')
|
|
||||||
return
|
|
||||||
event = desc.get('event')
|
|
||||||
if event is None:
|
|
||||||
Logger.info('Block: binds desc miss event, desc=%s',str(desc))
|
|
||||||
return
|
|
||||||
f = self.buildAction(widget,desc)
|
|
||||||
if f is None:
|
|
||||||
Logger.info('Block: get a null function,%s',str(desc))
|
|
||||||
return
|
|
||||||
w.bind(**{event:f})
|
|
||||||
|
|
||||||
def multipleAction(self, widget:Widget, desc, *args):
|
|
||||||
desc1 = {k:v for k, v in desc.items() if k != 'actions'}
|
|
||||||
mydesc = desc1.copy()
|
|
||||||
for a in desc['actions']:
|
|
||||||
new_desc = mydesc.copy()
|
|
||||||
new_desc.update(a)
|
|
||||||
self.uniaction(widget,new_desc, *args)
|
|
||||||
|
|
||||||
def conform_action(self, widget:Widget, desc, *args):
|
|
||||||
conform_desc = desc.get('conform')
|
|
||||||
blocks = Blocks()
|
|
||||||
if not conform_desc:
|
|
||||||
blocks.uniaction(widget, desc,*args, **kw)
|
|
||||||
return
|
|
||||||
w = blocks.widgetBuild({
|
|
||||||
"widgettype":"Conform",
|
|
||||||
"options":conform_desc
|
|
||||||
})
|
|
||||||
w.bind(on_conform=partial(blocks.uniaction, widget, desc))
|
|
||||||
w.open()
|
|
||||||
|
|
||||||
def uniaction(self, widget:Widget, desc, *args):
|
|
||||||
acttype = desc.get('actiontype')
|
|
||||||
if acttype=='blocks':
|
|
||||||
return self.blocksAction(widget,desc, *args)
|
|
||||||
if acttype=='urlwidget':
|
|
||||||
return self.urlwidgetAction(widget,desc, *args)
|
|
||||||
if acttype == 'registedfunction':
|
|
||||||
return self.registedfunctionAction(widget,desc, *args)
|
|
||||||
if acttype == 'script':
|
|
||||||
return self.scriptAction(widget, desc, *args)
|
|
||||||
if acttype == 'method':
|
|
||||||
return self.methodAction(widget, desc, *args)
|
|
||||||
if acttype == 'event':
|
|
||||||
return self.eventAction(widget, desc, *args)
|
|
||||||
if acttype == 'multiple':
|
|
||||||
return self.multipleAction(widget, desc, *args)
|
|
||||||
|
|
||||||
alert("actiontype(%s) invalid" % acttype,title='error')
|
|
||||||
|
|
||||||
def eventAction(self, widget:Widget, desc, *args):
|
|
||||||
target = self.get_target(widget, desc)
|
|
||||||
event = desc.get('dispatch_event')
|
|
||||||
if not event:
|
|
||||||
Logger.info('Block: eventAction():desc(%s) miss dispatch_event',
|
|
||||||
str(desc))
|
|
||||||
return
|
|
||||||
params = desc.get('params',{})
|
|
||||||
d = self.getActionData(widget,desc, *args)
|
|
||||||
if d:
|
|
||||||
params.update(d)
|
|
||||||
try:
|
|
||||||
target.dispatch(event, params)
|
|
||||||
except Exception as e:
|
|
||||||
Logger.info(f'Block: eventAction():dispatch {event} error')
|
|
||||||
print_exc()
|
|
||||||
return
|
|
||||||
|
|
||||||
def get_target(self, widget:Widget, desc):
|
|
||||||
if not desc.get('target'):
|
|
||||||
return None
|
|
||||||
return Blocks.getWidgetById(desc.get('target'),from_widget=widget)
|
|
||||||
|
|
||||||
def blocksAction(self, widget:Widget, desc, *args):
|
|
||||||
target = self.get_target(widget, desc)
|
|
||||||
add_mode = desc.get('mode','replace')
|
|
||||||
opts = desc.get('options').copy()
|
|
||||||
d = self.getActionData(widget,desc, *args)
|
|
||||||
p = opts.get('options',{}).copy()
|
|
||||||
if d:
|
|
||||||
p.update(d)
|
|
||||||
opts['options'] = p
|
|
||||||
def doit(target:Widget, add_mode:str, o, w:Widget):
|
|
||||||
if isinstance(w, ModalView):
|
|
||||||
return
|
|
||||||
|
|
||||||
if target and not w.parent:
|
|
||||||
if add_mode == 'replace':
|
|
||||||
target.clear_widgets()
|
|
||||||
target.add_widget(w)
|
|
||||||
|
|
||||||
def doerr(o,e):
|
|
||||||
Logger.info('Block: blocksAction(): desc=%s widgetBuild error'
|
|
||||||
,str(desc))
|
|
||||||
raise e
|
|
||||||
|
|
||||||
b = Blocks()
|
|
||||||
b.bind(on_built=partial(doit,target,add_mode))
|
|
||||||
b.bind(on_failed=doerr)
|
|
||||||
b.widgetBuild(opts)
|
|
||||||
|
|
||||||
def urlwidgetAction(self, widget:Widget, desc, *args):
|
|
||||||
target = self.get_target(widget, desc)
|
|
||||||
add_mode = desc.get('mode','replace')
|
|
||||||
opts = desc.get('options').copy()
|
|
||||||
p = opts.get('params',{}).copy()
|
|
||||||
if len(args) >= 1 and isinstance(args[0],dict):
|
|
||||||
p.update(args[0])
|
|
||||||
d = self.getActionData(widget, desc, *args)
|
|
||||||
if d:
|
|
||||||
p.update(d)
|
|
||||||
opts['params'] = p
|
|
||||||
d = {
|
|
||||||
'widgettype' : 'urlwidget',
|
|
||||||
'options': opts
|
|
||||||
}
|
|
||||||
|
|
||||||
def doit(target:Widget, add_mode:str, o, w:Widget):
|
|
||||||
if isinstance(w, ModalView):
|
|
||||||
return
|
|
||||||
|
|
||||||
if target and not w.parent:
|
|
||||||
if add_mode == 'replace':
|
|
||||||
target.clear_widgets()
|
|
||||||
target.add_widget(w)
|
|
||||||
|
|
||||||
def doerr(o,e):
|
|
||||||
Logger.info('Block: urlwidgetAction(): desc=%s widgetBuild error'
|
|
||||||
,str(desc))
|
|
||||||
|
|
||||||
b = Blocks()
|
|
||||||
b.bind(on_built=partial(doit,target,add_mode))
|
|
||||||
b.bind(on_failed=doerr)
|
|
||||||
b.widgetBuild(d)
|
|
||||||
|
|
||||||
def getActionData(self, widget:Widget, desc, *args):
|
|
||||||
Logger.info('Block: getActionData(): desc=%s args=%s'
|
|
||||||
,str(desc), args)
|
|
||||||
|
|
||||||
data = {}
|
|
||||||
rtdesc = self.build_rtdesc(desc)
|
|
||||||
if rtdesc:
|
|
||||||
rt = self.get_rtdata(widget, rtdesc, *args)
|
|
||||||
if rt:
|
|
||||||
data.update(rt)
|
|
||||||
if desc.get('keymapping'):
|
|
||||||
data = keyMapping(data, desc.get('keymapping'))
|
|
||||||
Logger.info('getActionData():rtdesc=%s, data=%s', rtdesc, data)
|
|
||||||
return data
|
|
||||||
|
|
||||||
def registedfunctionAction(self, widget:Widget, desc, *args):
|
|
||||||
target = self.get_target(widget, desc)
|
|
||||||
rf = RegisterFunction()
|
|
||||||
name = desc.get('rfname')
|
|
||||||
func = rf.get(name)
|
|
||||||
if func is None:
|
|
||||||
Logger.info('Block: desc=%s rfname(%s) not found',
|
|
||||||
str(desc), name)
|
|
||||||
raise Exception('rfname(%s) not found' % name)
|
|
||||||
|
|
||||||
params = desc.get('params',{}).copy()
|
|
||||||
d = self.getActionData(widget,desc, *args)
|
|
||||||
if d:
|
|
||||||
params.update(d)
|
|
||||||
func(target, *args, **params)
|
|
||||||
|
|
||||||
def scriptAction(self, widget:Widget, desc, *args):
|
|
||||||
script = desc.get('script')
|
|
||||||
if not script:
|
|
||||||
Logger.info('Block: scriptAction():desc(%s) target not found',
|
|
||||||
str(desc))
|
|
||||||
return
|
|
||||||
target = self.get_target(widget, desc)
|
|
||||||
d = self.getActionData(widget,desc, *args)
|
|
||||||
ns = {
|
|
||||||
"self":target,
|
|
||||||
"args":args,
|
|
||||||
"kwargs":d
|
|
||||||
}
|
|
||||||
if d:
|
|
||||||
ns.update(d)
|
|
||||||
try:
|
|
||||||
self.eval(script, ns)
|
|
||||||
except Exception as e:
|
|
||||||
print_exc()
|
|
||||||
print(e)
|
|
||||||
|
|
||||||
def build_rtdesc(self, desc):
|
|
||||||
rtdesc = desc.get('rtdata')
|
|
||||||
if not rtdesc:
|
|
||||||
if desc.get('datawidget'):
|
|
||||||
rtdesc = {}
|
|
||||||
rtdesc['target'] = desc['datawidget']
|
|
||||||
if desc.get('datascript'):
|
|
||||||
rtdesc['script'] = desc.get('datacript')
|
|
||||||
else:
|
|
||||||
rtdesc['method'] = desc.get('datamethod', 'getValue')
|
|
||||||
rtdesc['kwargs'] = desc.get('datakwargs', {})
|
|
||||||
return rtdesc
|
|
||||||
|
|
||||||
def get_rtdata(self, widget:Widget, desc, *args):
|
|
||||||
"""
|
|
||||||
desc descript follow attributes
|
|
||||||
{
|
|
||||||
"target", a target name from widget
|
|
||||||
"method", a method name, default is 'getValue',
|
|
||||||
"script", script to handle the data
|
|
||||||
"kwargs":" a dict arguments, default is {}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
if desc is None or desc == {}:
|
|
||||||
print('get_rtdata():desc is None')
|
|
||||||
return {}
|
|
||||||
kwargs = desc.get('kwargs', {})
|
|
||||||
if not isinstance(kwargs, dict):
|
|
||||||
kwargs = {}
|
|
||||||
w = None
|
|
||||||
if len(args) > 0:
|
|
||||||
w = args[0]
|
|
||||||
target = desc.get('target')
|
|
||||||
if target:
|
|
||||||
w = self.getWidgetById(target, from_widget=widget)
|
|
||||||
if w is None:
|
|
||||||
print('get_rtdata():w is None', desc)
|
|
||||||
return {}
|
|
||||||
script = desc.get('script')
|
|
||||||
if script:
|
|
||||||
ns = {
|
|
||||||
"self":w,
|
|
||||||
"args":args,
|
|
||||||
"kwargs":kwargs
|
|
||||||
}
|
|
||||||
d = self.eval(script, ns)
|
|
||||||
return d
|
|
||||||
|
|
||||||
method = desc.get('method', 'getValue')
|
|
||||||
if not hasattr(w, method):
|
|
||||||
print('get_rtdata():method is None', desc, type(w))
|
|
||||||
return {}
|
|
||||||
f = getattr(w, method)
|
|
||||||
try:
|
|
||||||
r = f(**kwargs)
|
|
||||||
if isinstance(r, dict):
|
|
||||||
return r
|
|
||||||
if isinstance(r, DictObject):
|
|
||||||
return r.to_dict()
|
|
||||||
print('get_rtdata():method return is not dict', desc, 'ret=', r, type(r))
|
|
||||||
return {}
|
|
||||||
except:
|
|
||||||
print_exc()
|
|
||||||
return {}
|
|
||||||
|
|
||||||
def methodAction(self, widget:Widget, desc, *args):
|
|
||||||
method = desc.get('method')
|
|
||||||
target = self.get_target(widget, desc)
|
|
||||||
if target is None:
|
|
||||||
Logger.info('Block: methodAction():desc(%s) target not found',
|
|
||||||
str(desc))
|
|
||||||
return
|
|
||||||
if method is None:
|
|
||||||
Logger.info('Block: methodAction():desc(%s) method not found',
|
|
||||||
str(desc))
|
|
||||||
return
|
|
||||||
if hasattr(target,method):
|
|
||||||
f = getattr(target, method)
|
|
||||||
kwargs = desc.get('options',{}).copy()
|
|
||||||
d = self.getActionData(widget,desc, *args)
|
|
||||||
if d:
|
|
||||||
kwargs.update(d)
|
|
||||||
f(*args, **kwargs)
|
|
||||||
else:
|
|
||||||
alert('%s method not found' % method)
|
|
||||||
|
|
||||||
def widgetBuild(self, desc):
|
|
||||||
"""
|
|
||||||
desc format:
|
|
||||||
{
|
|
||||||
widgettype:<registered widget>,
|
|
||||||
id:widget id,
|
|
||||||
options:{}
|
|
||||||
subwidgets:[
|
|
||||||
]
|
|
||||||
binds:[
|
|
||||||
]
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
def doit(desc):
|
|
||||||
if isinstance(desc,DictObject):
|
|
||||||
desc = desc.to_dict()
|
|
||||||
if not isinstance(desc,dict):
|
|
||||||
Logger.info('Block: desc(%s) must be a dict object(%s)',
|
|
||||||
desc,type(desc))
|
|
||||||
return None
|
|
||||||
|
|
||||||
# desc = self.valueExpr(desc)
|
|
||||||
try:
|
|
||||||
widget = self.w_build(desc)
|
|
||||||
self.dispatch('on_built',widget)
|
|
||||||
if hasattr(widget,'ready'):
|
|
||||||
widget.ready = True
|
|
||||||
return widget
|
|
||||||
except Exception as e:
|
|
||||||
print_exc()
|
|
||||||
self.dispatch('on_failed',e)
|
|
||||||
return None
|
|
||||||
|
|
||||||
if isinstance(desc,DictObject):
|
|
||||||
desc = desc.to_dict()
|
|
||||||
if not isinstance(desc, dict):
|
|
||||||
print('widgetBuild1: desc must be a dict object',
|
|
||||||
desc,type(desc))
|
|
||||||
self.dispatch('on_failed',Exception('miss url'))
|
|
||||||
return
|
|
||||||
|
|
||||||
widgettype = desc.get('widgettype')
|
|
||||||
while widgettype == "urlwidget":
|
|
||||||
opts = desc.get('options',{}).copy()
|
|
||||||
extend = desc.get('extend')
|
|
||||||
addon = None
|
|
||||||
if desc.get('extend'):
|
|
||||||
addon = desc.get('extend').copy()
|
|
||||||
url = opts.get('url')
|
|
||||||
if url is None:
|
|
||||||
self.dispatch('on_failed',Exception('miss url'))
|
|
||||||
return
|
|
||||||
|
|
||||||
if opts.get('url'):
|
|
||||||
del opts['url']
|
|
||||||
rtdesc = self.build_rtdesc(opts)
|
|
||||||
if rtdesc:
|
|
||||||
rtdata = self.get_rtdata(None, rtdesc)
|
|
||||||
params = opts.get('params', {})
|
|
||||||
params.update(rtdata)
|
|
||||||
opts['params'] = params
|
|
||||||
|
|
||||||
desc = self.getUrlData(url,**opts)
|
|
||||||
if not (isinstance(desc, DictObject) or \
|
|
||||||
isinstance(desc, dict)):
|
|
||||||
print('Block2: desc must be a dict object',
|
|
||||||
desc,type(desc))
|
|
||||||
self.dispatch('on_failed',Exception('miss url'))
|
|
||||||
return
|
|
||||||
|
|
||||||
if addon:
|
|
||||||
desc = dictExtend(desc,addon)
|
|
||||||
widgettype = desc.get('widgettype')
|
|
||||||
if widgettype is None:
|
|
||||||
print('Block3: desc must be a dict object not None')
|
|
||||||
return None
|
|
||||||
return doit(desc)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def getWidgetById(self, id:str, from_widget:Widget=None) -> Widget:
|
|
||||||
def find_widget_by_id(id, from_widget):
|
|
||||||
if id=='self':
|
|
||||||
return from_widget
|
|
||||||
if hasattr(from_widget,'widget_id'):
|
|
||||||
if from_widget.widget_id == id:
|
|
||||||
return from_widget
|
|
||||||
if id[0] == '-' and from_widget.widget_id == id[1:]:
|
|
||||||
return from_widget
|
|
||||||
if hasattr(from_widget, id):
|
|
||||||
w = getattr(from_widget,id)
|
|
||||||
return w
|
|
||||||
|
|
||||||
if id[0] == '-':
|
|
||||||
print('find_widget_by_id(), id=', id,
|
|
||||||
'widget=', from_widget)
|
|
||||||
if isinstance(from_widget, WindowBase):
|
|
||||||
return None
|
|
||||||
if from_widget.parent:
|
|
||||||
return find_widget_by_id(id,
|
|
||||||
from_widget=from_widget.parent)
|
|
||||||
return None
|
|
||||||
else:
|
|
||||||
children = [i for i in from_widget.children]
|
|
||||||
if hasattr(from_widget, 'get_subwidgets'):
|
|
||||||
children = from_widget.get_subwidgets()
|
|
||||||
for c in children:
|
|
||||||
ret = find_widget_by_id(id,from_widget=c)
|
|
||||||
if ret:
|
|
||||||
return ret
|
|
||||||
return None
|
|
||||||
|
|
||||||
ids = id.split('.')
|
|
||||||
app = App.get_running_app()
|
|
||||||
fid = ids[0]
|
|
||||||
if fid == '/self' or fid == 'root':
|
|
||||||
from_widget = app.root
|
|
||||||
if len(ids) == 1:
|
|
||||||
return from_widget
|
|
||||||
ids = ids[1:]
|
|
||||||
if fid == 'Window':
|
|
||||||
from_widget == Window
|
|
||||||
if len(ids) == 1:
|
|
||||||
return from_widget
|
|
||||||
ids = ids[1:]
|
|
||||||
if fid == 'app':
|
|
||||||
return app
|
|
||||||
|
|
||||||
if from_widget is None:
|
|
||||||
from_widget = app.root
|
|
||||||
for id in ids:
|
|
||||||
w = find_widget_by_id(id,from_widget=from_widget)
|
|
||||||
if w is None \
|
|
||||||
and id == ids[0] \
|
|
||||||
and Window.fullscreen == True \
|
|
||||||
and app.root != app.fs_widget:
|
|
||||||
w = find_widget_by_id(id, app.fs_widget)
|
|
||||||
|
|
||||||
if w is None:
|
|
||||||
print(id, 'not found ....')
|
|
||||||
return None
|
|
||||||
from_widget = w
|
|
||||||
return w
|
|
||||||
|
|
||||||
def on_built(self,v=None):
|
|
||||||
return
|
|
||||||
|
|
||||||
def on_failed(self,e=None):
|
|
||||||
return
|
|
||||||
|
|
||||||
Factory.register('Blocks',Blocks)
|
|
||||||
Factory.register('Video',Video)
|
|
||||||
Factory.register('OrientationLayout', OrientationLayout)
|
|
25211
kivyblocks/dg.c
25211
kivyblocks/dg.c
File diff suppressed because it is too large
Load Diff
@ -1,619 +0,0 @@
|
|||||||
import time
|
|
||||||
import ujson as json
|
|
||||||
from functools import partial
|
|
||||||
|
|
||||||
from kivy.logger import Logger
|
|
||||||
from kivy.uix.gridlayout import GridLayout
|
|
||||||
from kivy.uix.boxlayout import BoxLayout
|
|
||||||
from kivy.uix.scrollview import ScrollView
|
|
||||||
from kivy.uix.label import Label
|
|
||||||
from kivy.graphics import Fbo
|
|
||||||
from kivy.uix.button import ButtonBehavior
|
|
||||||
from kivy.clock import Clock
|
|
||||||
from kivy.properties import BooleanProperty, StringProperty, \
|
|
||||||
OptionProperty, DictProperty, NumericProperty, ListProperty
|
|
||||||
from kivy.properties import ListProperty
|
|
||||||
from kivy.graphics import Color, Rectangle
|
|
||||||
from kivy.app import App
|
|
||||||
from kivy.factory import Factory
|
|
||||||
|
|
||||||
from appPublic.dictObject import DictObject
|
|
||||||
from appPublic.uniqueID import getID
|
|
||||||
from appPublic.myTE import string_template_render
|
|
||||||
|
|
||||||
from .utils import *
|
|
||||||
from .baseWidget import Text, HBox, VBox
|
|
||||||
from .scrollpanel import ScrollPanel
|
|
||||||
from .paging import Paging, RelatedLoader
|
|
||||||
from .ready import WidgetReady
|
|
||||||
from .toolbar import Toolbar
|
|
||||||
from .bgcolorbehavior import BGColorBehavior
|
|
||||||
from .widget_css import WidgetCSS
|
|
||||||
from .uitype.factory import UiFactory
|
|
||||||
|
|
||||||
class BLabel(ButtonBehavior, Text):
|
|
||||||
def __init__(self, **kw):
|
|
||||||
ButtonBehavior.__init__(self)
|
|
||||||
Text.__init__(self,**kw)
|
|
||||||
self.csscls = 'dummy'
|
|
||||||
|
|
||||||
class Cell(ButtonBehavior, WidgetCSS, BoxLayout):
|
|
||||||
colume_name = StringProperty(None)
|
|
||||||
cell_type = OptionProperty('data', \
|
|
||||||
options=['data', 'header'])
|
|
||||||
def __init__(self,row,desc, **kw):
|
|
||||||
"""
|
|
||||||
desc:{
|
|
||||||
width,
|
|
||||||
datatype:fff
|
|
||||||
value:
|
|
||||||
format:
|
|
||||||
on_press:
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
self.desc = desc
|
|
||||||
self.row = row
|
|
||||||
super().__init__(size_hint=(None,None),
|
|
||||||
width = self.desc['width'],
|
|
||||||
height = self.row.part.datagrid.rowHeight()
|
|
||||||
)
|
|
||||||
self.csscls=self.row.part.datagrid.row_normal_css
|
|
||||||
if self.row.header:
|
|
||||||
self.csscls=self.row.part.datagrid.header_css
|
|
||||||
if desc['header']:
|
|
||||||
bl = Text(i18n=True, text=str(desc['value']),
|
|
||||||
font_size=CSize(1),wrap=True,
|
|
||||||
halign='left', valign='middle'
|
|
||||||
)
|
|
||||||
self.cell_type = 'header'
|
|
||||||
else:
|
|
||||||
self.cell_type = 'data'
|
|
||||||
bl = UiFactory.build_view_widget(desc,self.row.row_data)
|
|
||||||
self.colume_name = desc['name']
|
|
||||||
if bl:
|
|
||||||
self.add_widget(bl)
|
|
||||||
|
|
||||||
class Row(BoxLayout):
|
|
||||||
def __init__(self,part, rowdesc,header=False,data=None, **kw):
|
|
||||||
"""
|
|
||||||
rowdesc=[
|
|
||||||
{
|
|
||||||
width,
|
|
||||||
name
|
|
||||||
value
|
|
||||||
on_press
|
|
||||||
}
|
|
||||||
|
|
||||||
"""
|
|
||||||
self.part = part
|
|
||||||
self.header = header
|
|
||||||
self.row_data = data
|
|
||||||
self.row_id = None
|
|
||||||
self.linewidth = self.part.datagrid.linewidth
|
|
||||||
self.rowdesc = rowdesc
|
|
||||||
opts = kw.copy()
|
|
||||||
opts.update({
|
|
||||||
"spacing":self.linewidth,
|
|
||||||
"orientation":"horizontal"
|
|
||||||
})
|
|
||||||
super(Row, self).__init__(**opts)
|
|
||||||
self.height = self.part.datagrid.rowHeight()
|
|
||||||
self.init(0)
|
|
||||||
|
|
||||||
def on_row_press(self, *args):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def init(self,t):
|
|
||||||
w = 0
|
|
||||||
h = 0
|
|
||||||
for c in self.rowdesc:
|
|
||||||
c['header'] = self.header
|
|
||||||
cell = Cell(self,c)
|
|
||||||
self.add_widget(cell)
|
|
||||||
cell.bind(on_press=self.part.datagrid.cell_pressed)
|
|
||||||
w += cell.width
|
|
||||||
self.size_hint = None,None
|
|
||||||
self.width = w + self.linewidth * (len(self.rowdesc)+1)
|
|
||||||
|
|
||||||
def unselected(self):
|
|
||||||
self.select(False)
|
|
||||||
|
|
||||||
def selected(self):
|
|
||||||
self.select(True)
|
|
||||||
|
|
||||||
def select(self, flag):
|
|
||||||
for c in self.children:
|
|
||||||
if flag:
|
|
||||||
c.csscls = self.part.datagrid.row_selected_css
|
|
||||||
else:
|
|
||||||
c.csscls = self.part.datagrid.row_normal_css
|
|
||||||
|
|
||||||
class Header(WidgetReady, ScrollPanel):
|
|
||||||
def __init__(self,part,**kw):
|
|
||||||
SUPER(Header, self, kw)
|
|
||||||
self.part = part
|
|
||||||
self.init(1)
|
|
||||||
self.bind(on_scroll_stop=self.part.datagrid.scrollstop)
|
|
||||||
if self.part.freeze_flag:
|
|
||||||
self.bar_width = 0
|
|
||||||
self.bar_width = 0
|
|
||||||
|
|
||||||
def init(self,t):
|
|
||||||
rd = [ f.copy() for f in self.part.rowdesc ]
|
|
||||||
[ f.update({'value':self.part.fields[i].get('label', \
|
|
||||||
self.part.fields[i].get('name'))}) \
|
|
||||||
for i,f in enumerate(rd) ]
|
|
||||||
self.header = Row(self.part,rd,header=True)
|
|
||||||
self.add_widget(self.header)
|
|
||||||
self.height = self.header.height
|
|
||||||
|
|
||||||
class Body(WidgetReady, ScrollPanel):
|
|
||||||
def __init__(self,part,**kw):
|
|
||||||
self.part = part
|
|
||||||
SUPER(Body, self, kw)
|
|
||||||
self._inner.spacing = self.part.datagrid.linewidth
|
|
||||||
self.size_hint=(1,1)
|
|
||||||
self.idRow = {}
|
|
||||||
self.bind(on_scroll_stop=self.part.datagrid.scrollstop)
|
|
||||||
if self.part.freeze_flag:
|
|
||||||
self.bar_width = 0
|
|
||||||
|
|
||||||
def addRow(self,id, data,index=0):
|
|
||||||
rd = [ f.copy() for f in self.part.rowdesc ]
|
|
||||||
[ f.update({'value':data.get(f['name'])}) for f in rd ]
|
|
||||||
row = Row(self.part,rd,data=data)
|
|
||||||
row.row_id = id
|
|
||||||
self.add_widget(row,index=index)
|
|
||||||
self.idRow[id] = row
|
|
||||||
return row
|
|
||||||
|
|
||||||
def clearRows(self):
|
|
||||||
self.idRow = {}
|
|
||||||
self.clear_widgets()
|
|
||||||
|
|
||||||
def delRowById(self,id):
|
|
||||||
row = self.idRow.get(id)
|
|
||||||
if row:
|
|
||||||
self.remove_widget(row)
|
|
||||||
if self.idRow.get(id):
|
|
||||||
del self.idRow[id]
|
|
||||||
|
|
||||||
def getRowData(self,rowid):
|
|
||||||
return self.idRow[rowid].row_data
|
|
||||||
|
|
||||||
def getRowHeight(self):
|
|
||||||
return self.part.datagrid.rowHeight()
|
|
||||||
|
|
||||||
def get_row_by_id(self, rowid):
|
|
||||||
return self.idRow.get(rowid)
|
|
||||||
|
|
||||||
class DataGridPart(WidgetReady, BoxLayout):
|
|
||||||
def __init__(self,dg, freeze_flag, fields):
|
|
||||||
self.datagrid = dg
|
|
||||||
self.fields = fields
|
|
||||||
self.freeze_flag = freeze_flag
|
|
||||||
self.fields_width = None
|
|
||||||
BoxLayout.__init__(self, orientation='vertical')
|
|
||||||
WidgetReady.__init__(self)
|
|
||||||
self.init(0)
|
|
||||||
|
|
||||||
def setWidth(self):
|
|
||||||
if self.freeze_flag:
|
|
||||||
self.size_hint_x = None
|
|
||||||
self.width = self.getFieldsWidth()
|
|
||||||
|
|
||||||
def getFieldsWidth(self):
|
|
||||||
if not self.fields_width:
|
|
||||||
width = 0
|
|
||||||
for f in self.rowdesc:
|
|
||||||
width += f['width']
|
|
||||||
self.fields_width = width
|
|
||||||
return self.fields_width
|
|
||||||
|
|
||||||
def init(self,t):
|
|
||||||
rd = []
|
|
||||||
for f in self.fields:
|
|
||||||
r = f.copy()
|
|
||||||
r['width'] = CSize(f.get('width',10))
|
|
||||||
rd.append(r)
|
|
||||||
self.rowdesc = rd
|
|
||||||
self.setWidth()
|
|
||||||
kw = {}
|
|
||||||
if self.freeze_flag:
|
|
||||||
kw['width'] = self.fields_width
|
|
||||||
kw['size_hint'] = (None,None)
|
|
||||||
else:
|
|
||||||
kw['size_hint'] = (1,None)
|
|
||||||
kw['height'] = self.datagrid.rowHeight()
|
|
||||||
|
|
||||||
self.header = None
|
|
||||||
if not self.datagrid.noheader:
|
|
||||||
self.header = Header(self,**kw)
|
|
||||||
self.add_widget(self.header)
|
|
||||||
inner = {
|
|
||||||
"widgettype":"VBox",
|
|
||||||
"options":{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.body = Body(self)
|
|
||||||
self.add_widget(self.body)
|
|
||||||
if not self.freeze_flag:
|
|
||||||
self.body.bind(pos=self.datagrid.bodyOnSize,
|
|
||||||
size=self.datagrid.bodyOnSize)
|
|
||||||
|
|
||||||
def clearRows(self):
|
|
||||||
return self.body.clearRows()
|
|
||||||
|
|
||||||
def addRow(self,id, data):
|
|
||||||
return self.body.addRow(id, data)
|
|
||||||
|
|
||||||
def on_size(self, o, s=None):
|
|
||||||
if not hasattr(self, 'body'):
|
|
||||||
return
|
|
||||||
if hasattr(self, '_toolbar'):
|
|
||||||
if self._toolbar is not None:
|
|
||||||
self._toolbar.width = self.width
|
|
||||||
self.body.size_hint_y = None
|
|
||||||
if self.header:
|
|
||||||
self.body.height = self.height - self.header.height
|
|
||||||
else:
|
|
||||||
self.body.height = self.height
|
|
||||||
|
|
||||||
|
|
||||||
class DataGrid(VBox):
|
|
||||||
"""
|
|
||||||
DataGrid data format:
|
|
||||||
{
|
|
||||||
"widgettype":"DataGrid",
|
|
||||||
"dataloader":{
|
|
||||||
"page":1,
|
|
||||||
"rows":60,
|
|
||||||
"dataurl":"eeee",
|
|
||||||
"params":{
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"tailer":{
|
|
||||||
"options":{
|
|
||||||
}
|
|
||||||
"info":[
|
|
||||||
"total_cnt",
|
|
||||||
"total_page",
|
|
||||||
"page_rows",
|
|
||||||
"curpage"
|
|
||||||
],
|
|
||||||
"others":{
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"row_height": CSize,
|
|
||||||
"header_css":"default",
|
|
||||||
"body_css":"default",
|
|
||||||
"spacing":1,
|
|
||||||
"fields":[
|
|
||||||
{
|
|
||||||
"name":"field1",
|
|
||||||
"label":"Field1",
|
|
||||||
"datatype":"str",
|
|
||||||
"uitype":"code",
|
|
||||||
"value_field":,
|
|
||||||
"text_field":
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"field2",
|
|
||||||
"label":"Field2",
|
|
||||||
"viewer":{
|
|
||||||
block dic
|
|
||||||
}
|
|
||||||
}
|
|
||||||
...
|
|
||||||
]
|
|
||||||
"binds":[
|
|
||||||
]
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
row_selected = BooleanProperty(False)
|
|
||||||
row_normal_css = StringProperty('default')
|
|
||||||
row_selected_css = StringProperty('default')
|
|
||||||
header_css = StringProperty('default')
|
|
||||||
body_css = StringProperty('default')
|
|
||||||
row_height = NumericProperty(2)
|
|
||||||
noheader = BooleanProperty(False)
|
|
||||||
linewidth = NumericProperty(1)
|
|
||||||
toolbar = DictProperty(None)
|
|
||||||
dataloader = DictProperty(None)
|
|
||||||
fields = ListProperty(None)
|
|
||||||
tailer = DictProperty(None)
|
|
||||||
def __init__(self,**options):
|
|
||||||
self.select_rowid = None
|
|
||||||
self.rowheight = None
|
|
||||||
self.on_sizeTask = None
|
|
||||||
self.selected_rowid = None
|
|
||||||
self.show_rows = 0
|
|
||||||
self._toolbar = None
|
|
||||||
self.freeze_part = None
|
|
||||||
self.normal_part = None
|
|
||||||
SUPER(DataGrid, self, options)
|
|
||||||
self.freeze_fields = self.getPartFields(freeze_flag=True)
|
|
||||||
self.normal_fields = self.getPartFields(freeze_flag=False)
|
|
||||||
if not self.dataloader:
|
|
||||||
raise Exception('DataGrid need a DataLoader')
|
|
||||||
self._dataloader = RelatedLoader(target=self, **self.dataloader)
|
|
||||||
self._dataloader.bind(on_deletepage=self.delete_page)
|
|
||||||
self._dataloader.bind(on_pageloaded=self.add_page)
|
|
||||||
self._dataloader.bind(on_pageloaded=self.update_tailer_info)
|
|
||||||
self._dataloader.bind(on_newbegin=self.clearRows)
|
|
||||||
self.register_event_type('on_selected')
|
|
||||||
self.register_event_type('on_rowpress')
|
|
||||||
self.register_event_type('on_cellpress')
|
|
||||||
self.register_event_type('on_headerpress')
|
|
||||||
self.createDataGridPart()
|
|
||||||
self.createToolbar()
|
|
||||||
if self._toolbar:
|
|
||||||
self.add_widget(self._toolbar)
|
|
||||||
|
|
||||||
b = BoxLayout(orientation='horizontal')
|
|
||||||
if self.freeze_part:
|
|
||||||
b.add_widget(self.freeze_part)
|
|
||||||
if self.normal_part:
|
|
||||||
b.add_widget(self.normal_part)
|
|
||||||
self.add_widget(b)
|
|
||||||
if self.tailer:
|
|
||||||
self.tailer_widgets = {}
|
|
||||||
self.build_tailer(self.tailer)
|
|
||||||
|
|
||||||
def on_rowpress(self, *args):
|
|
||||||
print('on_rowpress fire, args=', args)
|
|
||||||
|
|
||||||
def on_cellpress(self, *args):
|
|
||||||
print('on_cesspress fire, args=', args)
|
|
||||||
|
|
||||||
def on_headerpress(self, *args):
|
|
||||||
print('on_headerpress fire, args=', args)
|
|
||||||
|
|
||||||
def cell_pressed(self, o):
|
|
||||||
if o.cell_type == 'header':
|
|
||||||
self.dispatch('on_headerpress', o.colume_name)
|
|
||||||
return
|
|
||||||
row = o.row
|
|
||||||
if self.selected_rowid:
|
|
||||||
self.unselect_row(self.selected_rowid)
|
|
||||||
|
|
||||||
self.selected_rowid = row.row_id
|
|
||||||
self.select_row(row.row_id)
|
|
||||||
self.dispatch('on_cellpress', o)
|
|
||||||
self.dispatch('on_rowpress', row)
|
|
||||||
self.dispatch('on_selected', row)
|
|
||||||
|
|
||||||
def unselect_row(self, row_id):
|
|
||||||
if self.freeze_part:
|
|
||||||
row = self.freeze_part.body.get_row_by_id(row_id)
|
|
||||||
if not row:
|
|
||||||
return
|
|
||||||
row.unselected()
|
|
||||||
row = self.normal_part.body.get_row_by_id(row_id)
|
|
||||||
if not row:
|
|
||||||
return
|
|
||||||
row.unselected()
|
|
||||||
|
|
||||||
def select_row(self, row_id):
|
|
||||||
if self.freeze_part:
|
|
||||||
row = self.freeze_part.body.get_row_by_id(row_id)
|
|
||||||
row.selected()
|
|
||||||
row = self.normal_part.body.get_row_by_id(row_id)
|
|
||||||
row.selected()
|
|
||||||
|
|
||||||
def on_ready(self, *args):
|
|
||||||
self.loadData()
|
|
||||||
|
|
||||||
def build_tailer(self, tailer_desc):
|
|
||||||
kw = tailer_desc.get('options', {})
|
|
||||||
kw.update({
|
|
||||||
'size_hint_y':None,
|
|
||||||
'height':self.rowheight
|
|
||||||
})
|
|
||||||
w = HBox(**kw)
|
|
||||||
self.add_widget(w)
|
|
||||||
self.show_infos(w, tailer_desc.get('info'))
|
|
||||||
if tailer_desc.get('others'):
|
|
||||||
w1 = self.build_tailer_other(tailer_desc.get('others'))
|
|
||||||
if w1:
|
|
||||||
w.add_widget(w1)
|
|
||||||
|
|
||||||
def update_tailer_info(self, *args):
|
|
||||||
if not hasattr(self, 'tailer_widgets'):
|
|
||||||
return
|
|
||||||
for n,w in self.tailer_widgets.items():
|
|
||||||
w.text = self.loader_info(n)
|
|
||||||
|
|
||||||
def show_infos(self, tailer_widget, info_names):
|
|
||||||
for n in info_names:
|
|
||||||
desc = {
|
|
||||||
"widgettype":"Text",
|
|
||||||
"options":{
|
|
||||||
"text":n,
|
|
||||||
"i18n":True,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w = Factory.Blocks().widgetBuild(desc)
|
|
||||||
tailer_widget.add_widget(w)
|
|
||||||
tailer_widget.add_widget(Label(text=':'))
|
|
||||||
self.tailer_widgets[n] = Label(text=self.loader_info(n))
|
|
||||||
tailer_widget.add_widget(self.tailer_widgets[n])
|
|
||||||
|
|
||||||
def build_tailer_others(desc):
|
|
||||||
return Factory.Blocks().widgetBuild(desc)
|
|
||||||
|
|
||||||
def loader_info(self, n):
|
|
||||||
if hasattr(self._dataloader, n):
|
|
||||||
txt=getattr(self._dataloader, n, 0)
|
|
||||||
if txt is None:
|
|
||||||
txt = '0'
|
|
||||||
txt = str(txt)
|
|
||||||
return txt
|
|
||||||
|
|
||||||
def locater(self,pos):
|
|
||||||
self.normal_part.body.scroll_y = pos
|
|
||||||
if self.freeze_part:
|
|
||||||
self.freeze_part.body.scroll_y = pos
|
|
||||||
|
|
||||||
def scrollstop(self,o,v=None):
|
|
||||||
if not self.noheader and o == self.normal_part.header:
|
|
||||||
self.normal_part.body.scroll_x = o.scroll_x
|
|
||||||
return
|
|
||||||
if o == self.normal_part.body:
|
|
||||||
if not self.noheader:
|
|
||||||
self.normal_part.header.scroll_x = o.scroll_x
|
|
||||||
if self.freeze_part:
|
|
||||||
self.freeze_part.body.scroll_y = o.scroll_y
|
|
||||||
if self.freeze_part and o == self.freeze_part.body:
|
|
||||||
self.normal_part.body.scroll_y = o.scroll_y
|
|
||||||
|
|
||||||
if o.scroll_y <= 0.01:
|
|
||||||
self._dataloader.loadNextPage()
|
|
||||||
if o.scroll_y >= 0.99:
|
|
||||||
self._dataloader.loadPreviousPage()
|
|
||||||
|
|
||||||
def getValue(self):
|
|
||||||
if not self.select_rowid:
|
|
||||||
return None
|
|
||||||
return self._getRowData(self.select_rowid)
|
|
||||||
|
|
||||||
def _getRowData(self, rowid):
|
|
||||||
d = {}
|
|
||||||
if self.freeze_part:
|
|
||||||
d.update(self.freeze_part.body.getRowData(rowid))
|
|
||||||
d.update(self.normal_part.body.getRowData(rowid))
|
|
||||||
return DictObject(**d)
|
|
||||||
|
|
||||||
def bodyOnSize(self,o,s):
|
|
||||||
if self.on_sizeTask is not None:
|
|
||||||
self.on_sizeTask.cancel()
|
|
||||||
self.on_sizeTask = Clock.schedule_once(self.calculateShowRows,0.3)
|
|
||||||
|
|
||||||
def rowHeight(self):
|
|
||||||
if not self.rowheight:
|
|
||||||
self.rowheight = CSize(self.row_height)
|
|
||||||
return self.rowheight
|
|
||||||
|
|
||||||
def calculateShowRows(self,t):
|
|
||||||
self.getShowRows()
|
|
||||||
self._dataloader.setPageRows(self.show_rows * 2)
|
|
||||||
|
|
||||||
def getShowRows(self):
|
|
||||||
if self.show_rows == 0:
|
|
||||||
return 60
|
|
||||||
self.show_rows = int(self.rowHeight() / self.normal_part.body.height)
|
|
||||||
return self.show_rows * 2
|
|
||||||
|
|
||||||
def clearRows(self, *args):
|
|
||||||
if self.freeze_part:
|
|
||||||
self.freeze_part.body.clearRows()
|
|
||||||
self.normal_part.body.clearRows()
|
|
||||||
|
|
||||||
def add_page(self,o,data):
|
|
||||||
dir = data['dir']
|
|
||||||
if not self.show_rows:
|
|
||||||
self.getShowRows()
|
|
||||||
|
|
||||||
ids = []
|
|
||||||
recs = data['data']
|
|
||||||
idx = 0
|
|
||||||
if dir == 'up':
|
|
||||||
recs.reverse()
|
|
||||||
idx = -1
|
|
||||||
recs1 = recs[:self.show_rows]
|
|
||||||
recs2 = recs[self.show_rows:]
|
|
||||||
self._fbo = Fbo(size=self.size)
|
|
||||||
with self._fbo:
|
|
||||||
self._background_color = Color(0,0,0,1)
|
|
||||||
self._background_rect = Rectangle(size=self.size)
|
|
||||||
for r in recs1:
|
|
||||||
id = self.addRow(r,index=idx)
|
|
||||||
ids.append(id)
|
|
||||||
with self.canvas:
|
|
||||||
self._fbo_rect = Rectangle(size=self.size,
|
|
||||||
texture=self._fbo.texture)
|
|
||||||
|
|
||||||
data['idx'] = idx
|
|
||||||
data['ids'] = ids
|
|
||||||
data['data'] = recs2
|
|
||||||
f = partial(self.add_page_delay,data)
|
|
||||||
Clock.schedule_once(f, 0)
|
|
||||||
|
|
||||||
def add_page_delay(self, data, *args):
|
|
||||||
recs = data['data']
|
|
||||||
page = data['page']
|
|
||||||
idx = data['idx']
|
|
||||||
ids = data['ids']
|
|
||||||
self._fbo = Fbo(size=self.size)
|
|
||||||
with self._fbo:
|
|
||||||
self._background_color = Color(0,0,0,1)
|
|
||||||
self._background_rect = Rectangle(size=self.size)
|
|
||||||
for r in recs:
|
|
||||||
id = self.addRow(r,index=idx)
|
|
||||||
ids.append(id)
|
|
||||||
with self.canvas:
|
|
||||||
self._fbo_rect = Rectangle(size=self.size,
|
|
||||||
texture=self._fbo.texture)
|
|
||||||
self._dataloader.bufferObjects(page,ids)
|
|
||||||
x = self._dataloader.getLocater()
|
|
||||||
self.locater(x)
|
|
||||||
|
|
||||||
def delete_page(self,o,data):
|
|
||||||
for id in data:
|
|
||||||
self.delRow(id)
|
|
||||||
|
|
||||||
def addRow(self,data, **kw):
|
|
||||||
id = getID()
|
|
||||||
f_row = None
|
|
||||||
if self.freeze_part:
|
|
||||||
self.freeze_part.body.addRow(id, data, **kw)
|
|
||||||
self.normal_part.body.addRow(id, data, **kw)
|
|
||||||
return id
|
|
||||||
|
|
||||||
def delRow(self,id,**kw):
|
|
||||||
if self.freeze_part:
|
|
||||||
self.freeze_part.body.delRowById(id)
|
|
||||||
self.normal_part.body.delRowById(id)
|
|
||||||
|
|
||||||
def createToolbar(self):
|
|
||||||
if self.toolbar:
|
|
||||||
self._toolbar = Toolbar(**self.toolbar)
|
|
||||||
|
|
||||||
def on_selected(self,row):
|
|
||||||
print("DataGrid():on_selected fire")
|
|
||||||
|
|
||||||
def loadData(self,*args, **kwargs):
|
|
||||||
kwargs['page'] = 1
|
|
||||||
self.selected_rowid = None
|
|
||||||
self._dataloader.do_search(None,kwargs)
|
|
||||||
|
|
||||||
def createDataGridPart(self):
|
|
||||||
self.freeze_part = None
|
|
||||||
self.normal_part = None
|
|
||||||
if self.freeze_fields:
|
|
||||||
self.freeze_part = DataGridPart(self,True, self.freeze_fields)
|
|
||||||
if self.normal_fields:
|
|
||||||
self.normal_part = DataGridPart(self, False, self.normal_fields)
|
|
||||||
|
|
||||||
def getPartFields(self,freeze_flag:bool=False) -> list:
|
|
||||||
fs = []
|
|
||||||
for f in self.fields:
|
|
||||||
if freeze_flag:
|
|
||||||
if f.get('freeze',False):
|
|
||||||
fs.append(f)
|
|
||||||
else:
|
|
||||||
if not f.get('freeze',False):
|
|
||||||
fs.append(f)
|
|
||||||
return fs
|
|
||||||
|
|
||||||
def get_selected_data(self):
|
|
||||||
if not self.selected_rowid:
|
|
||||||
return {}
|
|
||||||
data = {}
|
|
||||||
row_id = self.selected_rowid
|
|
||||||
if self.freeze_part:
|
|
||||||
row = self.freeze_part.body.get_row_by_id(row_id)
|
|
||||||
data.update(row.row_data)
|
|
||||||
row = self.normal_part.body.get_row_by_id(row_id)
|
|
||||||
data.update(row.row_data)
|
|
||||||
return data
|
|
@ -250,24 +250,12 @@ class Form(WidgetCSS, WidgetReady, BoxLayout):
|
|||||||
self.register_event_type('on_submit')
|
self.register_event_type('on_submit')
|
||||||
|
|
||||||
def setup_cols_and_inputwidth(self):
|
def setup_cols_and_inputwidth(self):
|
||||||
if isHandHold() and Window.width < Window.height:
|
|
||||||
self._cols = 1
|
|
||||||
self.input_width = 1
|
|
||||||
return
|
|
||||||
if self.cols is None and self.inputwidth is None:
|
|
||||||
self.input_width = 1
|
|
||||||
self._cols = 1
|
|
||||||
return
|
|
||||||
if self.inputwidth > 1:
|
if self.inputwidth > 1:
|
||||||
self.input_width = CSize(self.inputwidth)
|
self.input_width = CSize(self.inputwidth)
|
||||||
self._cols = -1 # auto calculate
|
|
||||||
return
|
return
|
||||||
self.input_width = self.inputwidth
|
self.input_width = self.inputwidth
|
||||||
self._cols = 1
|
|
||||||
|
|
||||||
def set_grid_attrs(self):
|
def set_grid_attrs(self):
|
||||||
if self._cols == 1 and self.input_width <= 1:
|
|
||||||
self.input_width = self.width
|
|
||||||
self.fsc.box_width = self.input_width
|
self.fsc.box_width = self.input_width
|
||||||
|
|
||||||
def on_size(self, *args):
|
def on_size(self, *args):
|
||||||
@ -277,13 +265,17 @@ class Form(WidgetCSS, WidgetReady, BoxLayout):
|
|||||||
if not self.notoolbar:
|
if not self.notoolbar:
|
||||||
if self.toolbar_at in ['top', 'bottom']:
|
if self.toolbar_at in ['top', 'bottom']:
|
||||||
self.fsc.height = self.height - self.toolbar_w.height
|
self.fsc.height = self.height - self.toolbar_w.height
|
||||||
|
self.fsc.width = self.width
|
||||||
else:
|
else:
|
||||||
self.fsc.width = self.width - self.toolbar_w.width
|
self.fsc.width = self.width - self.toolbar_w.width
|
||||||
|
self.fsc.height = self.height
|
||||||
else:
|
else:
|
||||||
if self.toolbar_at in ['top', 'bottom']:
|
if self.toolbar_at in ['top', 'bottom']:
|
||||||
self.fsc.height = self.height
|
self.fsc.height = self.height
|
||||||
|
self.fsc.width = self.width
|
||||||
else:
|
else:
|
||||||
self.fsc.width = self.width
|
self.fsc.width = self.width
|
||||||
|
self.fsc.height = self.height
|
||||||
self.set_grid_attrs()
|
self.set_grid_attrs()
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
|
@ -139,6 +139,12 @@ class Menu(Hierarchy):
|
|||||||
self.target_w = None
|
self.target_w = None
|
||||||
super(Menu, self).__init__(**kw)
|
super(Menu, self).__init__(**kw)
|
||||||
|
|
||||||
|
def node_selected(self, o, v):
|
||||||
|
if not v.is_leaf:
|
||||||
|
self.tree.toggle_node(v)
|
||||||
|
return
|
||||||
|
super().node_selected(o, v)
|
||||||
|
|
||||||
def on_press(self, node):
|
def on_press(self, node):
|
||||||
self.tree.deselect_node()
|
self.tree.deselect_node()
|
||||||
data = {}
|
data = {}
|
||||||
|
@ -79,7 +79,7 @@ class VResponsiveLayout(WidgetCSS, WidgetReady, ScrollView):
|
|||||||
|
|
||||||
if self.box_width is not None:
|
if self.box_width is not None:
|
||||||
if self.box_width <= 1:
|
if self.box_width <= 1:
|
||||||
sef.cols = floor(1 / self.box)
|
self.cols = floor(1 / self.box_width)
|
||||||
self.col_width = self.calculate_col_width(self.cols)
|
self.col_width = self.calculate_col_width(self.cols)
|
||||||
return self.setCols()
|
return self.setCols()
|
||||||
else:
|
else:
|
||||||
|
12
setup.py
12
setup.py
@ -12,15 +12,13 @@ from Cython.Build import cythonize
|
|||||||
# python setup.py bdist_egg generate a egg file
|
# python setup.py bdist_egg generate a egg file
|
||||||
# Release information about eway
|
# Release information about eway
|
||||||
|
|
||||||
version = "0.1.2"
|
version = "0.1.3"
|
||||||
description = "kivy blocks is a tool to build kivy ui with json format uidesc files"
|
description = "kivy blocks is a tool to build kivy ui with json format uidesc files"
|
||||||
author = "yumoqing"
|
author = "yumoqing"
|
||||||
email = "yumoqing@icloud.com"
|
email = "yumoqing@icloud.com"
|
||||||
|
|
||||||
package_data = {
|
package_data = {
|
||||||
"kivyblocks":[
|
"kivyblocks":[
|
||||||
"blocks.pyx",
|
|
||||||
"dg.pyx",
|
|
||||||
'imgs/*.png',
|
'imgs/*.png',
|
||||||
'imgs/*.atlas',
|
'imgs/*.atlas',
|
||||||
'imgs/*.gif',
|
'imgs/*.gif',
|
||||||
@ -35,13 +33,9 @@ package_data = {
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="kivyblocks",
|
name="kivyblocks",
|
||||||
ext_modules=cythonize(
|
# ext_modules= cythonize( [ ]),
|
||||||
[
|
ext_modules= [],
|
||||||
'kivyblocks/dg.pyx',
|
|
||||||
'kivyblocks/blocks.pyx'
|
|
||||||
]),
|
|
||||||
version=version,
|
version=version,
|
||||||
|
|
||||||
# uncomment the following lines if you fill them out in release.py
|
# uncomment the following lines if you fill them out in release.py
|
||||||
description=description,
|
description=description,
|
||||||
author=author,
|
author=author,
|
||||||
|
Loading…
Reference in New Issue
Block a user