From 0249db446b59cbcf7d8f75929fe06f59ad4d1467 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Wed, 8 Jan 2020 18:04:39 +0800 Subject: [PATCH] bugfix --- kivyblocks/blocks.bak.py | 520 ++++++++++++++++++++++++++++++++ kivyblocks/blocks.py | 119 ++------ kivyblocks/blocksapp.py | 4 + kivyblocks/boxViewer.py | 1 + kivyblocks/form.py | 67 ++-- kivyblocks/gps.py | 15 + kivyblocks/i18n.py | 17 +- kivyblocks/localFolderLoader.py | 36 +++ kivyblocks/login.py | 16 +- kivyblocks/paging.py | 56 +++- kivyblocks/playlist.py | 20 ++ kivyblocks/threadcall.py | 19 +- test/conf/config.json | 2 +- 13 files changed, 738 insertions(+), 154 deletions(-) create mode 100644 kivyblocks/blocks.bak.py create mode 100644 kivyblocks/gps.py create mode 100644 kivyblocks/localFolderLoader.py create mode 100644 kivyblocks/playlist.py diff --git a/kivyblocks/blocks.bak.py b/kivyblocks/blocks.bak.py new file mode 100644 index 0000000..c57d50b --- /dev/null +++ b/kivyblocks/blocks.bak.py @@ -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:, + 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 + diff --git a/kivyblocks/blocks.py b/kivyblocks/blocks.py index 27d7067..1e1f638 100755 --- a/kivyblocks/blocks.py +++ b/kivyblocks/blocks.py @@ -181,93 +181,6 @@ class Blocks: 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 @@ -376,9 +289,6 @@ class %s(%s): widget.built() def buildBind(self,widget,desc): - body=""" - - """ wid = desc.get('wid','self') w = self.getWidgetByIdPath(widget,wid) event = desc.get('event') @@ -389,6 +299,8 @@ class %s(%s): 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': @@ -399,6 +311,22 @@ class %s(%s): 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') @@ -437,8 +365,15 @@ class %s(%s): def scriptAction(self, widget, desc): script = desc.get('script') - if script: - self.eval(script, {'self': widget}) + if not script: + 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): method = desc.get('method') diff --git a/kivyblocks/blocksapp.py b/kivyblocks/blocksapp.py index 28a0bdb..a4d7c68 100644 --- a/kivyblocks/blocksapp.py +++ b/kivyblocks/blocksapp.py @@ -51,6 +51,7 @@ class BlocksApp(App): self.hc = HttpClient() WindowBase.softinput_mode='below_target' Clock.schedule_once(self.build1) + print('build() called......') return x def setUserInfo(self,uinfo): @@ -60,6 +61,9 @@ class BlocksApp(App): d['authcode'] = uinfo.get('authcode','') self.userinfo = d + def on_start(self): + print('on_start() called ...') + def build1(self,t): x = None x = self.blocks.widgetBuild(self.config.root) diff --git a/kivyblocks/boxViewer.py b/kivyblocks/boxViewer.py index c64616d..2d5fb1a 100644 --- a/kivyblocks/boxViewer.py +++ b/kivyblocks/boxViewer.py @@ -103,4 +103,5 @@ class BoxViewer(BoxLayout): self.dispatch('on_selected',o.getRecord()) def getData(self): + self.selected_data['__dataloader__'] = self.dataloader return self.selected_data diff --git a/kivyblocks/form.py b/kivyblocks/form.py index 7eb9c25..39141c4 100644 --- a/kivyblocks/form.py +++ b/kivyblocks/form.py @@ -1,12 +1,14 @@ from kivy.uix.textinput import TextInput from kivy.uix.boxlayout import BoxLayout from kivy.core.window import Window +from kivycalendar import DatePicker +from .responsivelayout import VResponsiveLayout from .widgetExt.inputext import FloatInput,IntegerInput, \ StrInput,SelectInput, BoolInput, AmountInput, Password from .baseWidget import * -from kivycalendar import DatePicker from .utils import * -from .i18n import getI18n +from .i18n import I18nText, I18n +from .toolbar import Toolbar """ form options { @@ -43,6 +45,10 @@ uitypes = { "orientation":"horizontal", "wclass":StrInput, }, + "password":{ + "orientation":"horizontal", + "wclass":Password, + }, "number":{ "orientation":"horizontal", "wclass":IntegerInput, @@ -92,7 +98,7 @@ class InputBox(BoxLayout): def __init__(self, form, **options): self.form = form self.options = options - self.uitype = options.get('uityoe','string') + self.uitype = options.get('uitype','string') self.uidef = uitypes[self.uitype] orientation = self.uidef['orientation'] width = self.form.inputwidth @@ -101,7 +107,7 @@ class InputBox(BoxLayout): kwargs = { "orientation":orientation, "size_hint_y":None, - "height":CSzie(height) + "height":height } if width <= 1: kwargs['size_hint_x'] = width @@ -114,8 +120,11 @@ class InputBox(BoxLayout): pos=self.setSize) self.register_event_type("on_datainput") + def on_datainput(self,o,v=None): + print('on_datainput fired ...',o,v) + def init(self): - i18n = getI18n() + i18n = I18n() if self.initflag: return label = self.options.get('label',self.options.get('name')) @@ -123,7 +132,9 @@ class InputBox(BoxLayout): label = label + '*' kwargs = { "otext":label, - "font_size":CSize(1) + "font_size":CSize(1), + "size_hint_y":None, + "height":CSize(2) } if self.labelwidth<=1: kwargs['size_hint_x'] = self.labelwidth @@ -139,6 +150,7 @@ class InputBox(BoxLayout): if 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) if self.options.get('readonly'): self.input_widget.disabled = True @@ -166,13 +178,13 @@ class InputBox(BoxLayout): self.input_widget.setValue(v) def getValue(self): - return self.input_widget.getValue() + return {self.options.get('name'):self.input_widget.getValue()} def defaultToolbar(): return { - img_size:1.5, - text_size:0.7, - tools:[ + "img_size":1.5, + "text_size":0.7, + "tools":[ { "name":"__submit", "img_src":blockImage("clear.png"), @@ -197,12 +209,6 @@ class Form(BoxLayout): self.cols = 1 self.inputwidth = Window.width / self.cols 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.bind(size=self.on_size, pos=self.on_size) @@ -210,20 +216,41 @@ class Form(BoxLayout): def init(self): if self.initflag: 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=[] 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.fieldWidgets.append(w) 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 = getWidgetById(self,'__clear') + # wid = getWidgetById(self,'__clear') + wid = self.widget_ids['__clear'] wid.bind(on_press=self.on_clear_button) 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): - self.dispatch('on_submit') + d = self.getData() + self.dispatch('on_submit',self,d) def on_clear_button(self,o,v=None): for fw in self.fieldWidgets: diff --git a/kivyblocks/gps.py b/kivyblocks/gps.py new file mode 100644 index 0000000..d953740 --- /dev/null +++ b/kivyblocks/gps.py @@ -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() + diff --git a/kivyblocks/i18n.py b/kivyblocks/i18n.py index d330922..73bab39 100644 --- a/kivyblocks/i18n.py +++ b/kivyblocks/i18n.py @@ -7,9 +7,8 @@ from .baseWidget import Text @SingletonDecorator class I18n: - def __init__(self,url): + def __init__(self): self.kvlang={} - self.loadUrl = url self.lang = locale.getdefaultlocale()[0] self.loadI18n(self.lang) self.i18nWidgets = [] @@ -18,11 +17,11 @@ class I18n: self.i18nWidgets.append(w) def loadI18n(self,lang): - if not self.loadUrl: - self.kvlang[lang] = {} - return 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 def __call__(self,msg,lang=None): @@ -39,10 +38,6 @@ class I18n: for w in self.i18nWidgets: w.changeLang(lang) -def getI18n(url=None): - i18n=I18n(url) - return i18n - class I18nText(Text): lang=StringProperty('') otext=StringProperty('') @@ -53,7 +48,7 @@ class I18nText(Text): if kw.get('otext'): del kw['otext'] super().__init__(**kw) - self.i18n = getI18n() + self.i18n = I18n() self.i18n.addI18nWidget(self) self.otext = otext diff --git a/kivyblocks/localFolderLoader.py b/kivyblocks/localFolderLoader.py new file mode 100644 index 0000000..91c63f3 --- /dev/null +++ b/kivyblocks/localFolderLoader.py @@ -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] + + diff --git a/kivyblocks/login.py b/kivyblocks/login.py index 26842f8..ab629da 100644 --- a/kivyblocks/login.py +++ b/kivyblocks/login.py @@ -15,7 +15,7 @@ logformdesc = { "name":"userid", "label":"user name", "datatype":"str", - "uitype":"str" + "uitype":"string" }, { "name":"passwd", @@ -26,12 +26,14 @@ logformdesc = { ] }, "binds":[ - "wid":"self", - "event":"on_submit", - "datawidegt":"self", - "actiontype":"registedfunction", - "rfname":"setupUserInfo" - } + { + "wid":"self", + "event":"on_submit", + "datawidegt":"self", + "actiontype":"registedfunction", + "rfname":"setupUserInfo" + } + ] } @SingletonDecorator diff --git a/kivyblocks/paging.py b/kivyblocks/paging.py index 1f01315..8bc7024 100644 --- a/kivyblocks/paging.py +++ b/kivyblocks/paging.py @@ -28,6 +28,25 @@ class PagingButton(Button): 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: def __init__(self, **options): self.loading = False @@ -36,12 +55,9 @@ class PageLoader: self.filter = StrSearchForm(**options['filter']) 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.url = options.get('dataurl') - if not self.url: - raise Exception('dataurl must be present:options=%s' % str(options)) self.total_cnt = 0 self.total_page = 0 self.page_rows = options.get('page_rows',0) @@ -83,12 +99,14 @@ class PageLoader: self.dir = 'up' 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']: r['__posInSet__'] = p p += 1 def loadPage(self,p): + if not self.url: + raise Exception('dataurl must be present:options=%s' % str(options)) self.curpage = p self.loading = True params = self.params.copy() @@ -123,6 +141,7 @@ class RelatedLoader(PageLoader): def __init__(self, **options): super().__init__(**options) self.adder = options.get('adder') + self.locater = options.get('locater',None) self.remover = options.get('remover') self.clearer = options.get('clearer') self.target = options.get('target') @@ -139,8 +158,6 @@ class RelatedLoader(PageLoader): self.calculateTotalPage() self.reload() - pass - def doBufferMaintain(self): siz = len(self.objectPages.keys()) if siz >= self.MaxbufferPage: @@ -179,12 +196,13 @@ class RelatedLoader(PageLoader): self.objectPages[self.curpage] = widgets pages = len(self.objectPages.keys()) loc = 1.0 / float(pages) - if pages == 1: - self.locater(1) - elif self.dir == 'up': - self.locater(1 - loc) - else: - self.locater(loc) + if self.locater: + if pages == 1: + self.locater(1) + elif self.dir == 'up': + self.locater(1 - loc) + else: + self.locater(loc) self.loading = False print('buffer pages=',len(self.objectPages.keys()),'pages=',self.objectPages.keys()) @@ -289,3 +307,15 @@ class Paging(PageLoader): return 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]) + diff --git a/kivyblocks/playlist.py b/kivyblocks/playlist.py new file mode 100644 index 0000000..8a63660 --- /dev/null +++ b/kivyblocks/playlist.py @@ -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 + + diff --git a/kivyblocks/threadcall.py b/kivyblocks/threadcall.py index a58b89c..cbdd752 100644 --- a/kivyblocks/threadcall.py +++ b/kivyblocks/threadcall.py @@ -5,6 +5,7 @@ import requests from kivy.event import EventDispatcher from kivy.clock import Clock from kivy.app import App +from .login import LoginForm class NeedLogin(Exception): pass @@ -30,9 +31,6 @@ class ThreadCall(Thread,EventDispatcher): try: self.rez = self.target(*self.args,**self.kwargs) self.dispatch('on_result',self.rez) - except NeedLogin as e: - lf = LoginForm() - lf.needlogin(url,method,params,headers,callback,errback) except Exception as e: self.dispatch('on_error',e) @@ -86,13 +84,13 @@ class HttpClient: self.s = requests.Session() 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']: req = requests.Request(method,url, params=params,headers=headers) else: req = requests.Request(method,url, - data=params,headers=headers) + data=params,files=files,headers=headers) prepped = self.s.prepare_request(req) resp = self.s.send(prepped) if resp.status_code == 200: @@ -114,18 +112,18 @@ class HttpClient: print('Error', url, method, params, resp.status_code,type(resp.status_code)) 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): return resp if callback is None: try: resp = self.webcall(url, method=method, - params=params, headers=headers) + params=params, files=files, headers=headers) return cb(None,resp) except NeedLogin as e: lf = LoginForm() - lf.needlogin(url,method,params,headers,callback,errback) + lf.needlogin(url,method,params,files,headers,callback,errback) return None except Exception as e: if errback is not None: @@ -135,6 +133,7 @@ class HttpClient: "url":url, "method":method, "params":params, + "files":files, "headers":headers } self.workers.add(self.webcall,callback,errback,kwargs=kwargs) @@ -143,8 +142,8 @@ class HttpClient: return self.__call__(url,method='GET',params=params, headers=headers, callback=callback, errback=errback) - def post(self, url, params={}, headers={}, callback=None, errback=None): - return self.__call__(url,method='POST',params=params, + def post(self, url, params={}, headers={}, files={}, callback=None, errback=None): + return self.__call__(url,method='POST',params=params, files=files, headers=headers, callback=callback, errback=errback) diff --git a/test/conf/config.json b/test/conf/config.json index efcd31e..7b6884d 100644 --- a/test/conf/config.json +++ b/test/conf/config.json @@ -15,7 +15,7 @@ "root":{ "widgettype":"urlwidget", "options":{ - "url":"/toolpage.ui" + "url":"/test/loginform.ui" } } }