bugfix
This commit is contained in:
parent
97372e8ad2
commit
e11a398439
@ -1,4 +1,6 @@
|
||||
import sys
|
||||
from traceback import print_exc
|
||||
from kivy.app import App
|
||||
from kivy.utils import platform
|
||||
from kivy.uix.button import Button, ButtonBehavior
|
||||
from kivy.uix.accordion import Accordion,AccordionItem
|
||||
@ -46,6 +48,7 @@ from kivy.uix.codeinput import CodeInput
|
||||
from kivy.graphics import Color, Rectangle
|
||||
from kivy.properties import ListProperty
|
||||
from kivycalendar import DatePicker
|
||||
from kivy.factory import Factory
|
||||
|
||||
from appPublic.dictObject import DictObject
|
||||
|
||||
@ -57,52 +60,66 @@ from .widgetExt.inputext import FloatInput,IntegerInput, \
|
||||
from .widgetExt.messager import Messager
|
||||
from .charts.bar import Bar
|
||||
from .bgcolorbehavior import BGColorBehavior
|
||||
|
||||
from .utils import NeedLogin, InsufficientPrivilege, HTTPError
|
||||
from .login import LoginForm
|
||||
if platform == 'android':
|
||||
from .widgetExt.phonebutton import PhoneButton
|
||||
from .widgetExt.androidwebview import AWebView
|
||||
|
||||
class Text(BGColorBehavior, Label):
|
||||
def __init__(self,bgcolor=[],fgcolor=[],color_level=-1,**kw):
|
||||
self.options = DictObject(**kw)
|
||||
kwargs = kw.copy()
|
||||
Label.__init__(self,**kwargs)
|
||||
BGColorBehavior.__init__(self,bgcolor=bgcolor,
|
||||
fgcolor=fgcolor,
|
||||
color_level=color_level)
|
||||
|
||||
class PressableImage(ButtonBehavior,AsyncImage):
|
||||
def on_press(self):
|
||||
pass
|
||||
|
||||
class Text(BGColorBehavior, Label):
|
||||
def __init__(self,bgcolor=[0,0,0,1],**kw):
|
||||
self.options = DictObject(**kw)
|
||||
kwargs = kw.copy()
|
||||
if kwargs.get('bgColor'):
|
||||
self.bgColor = kwargs['bgColor']
|
||||
del kwargs['bgColor']
|
||||
Label.__init__(self,**kwargs)
|
||||
BGColorBehavior.__init__(self,bgcolor=bgcolor)
|
||||
|
||||
class PressableLabel(ButtonBehavior, Text):
|
||||
def on_press(self):
|
||||
pass
|
||||
|
||||
class HTTPDataHandler(EventDispatcher):
|
||||
def __init__(self, url,method='GET',params={},headers={}):
|
||||
EventDispatcher.__init__()
|
||||
self.opts = opts
|
||||
def __init__(self, url,method='GET',params={},
|
||||
headers={},
|
||||
files={}
|
||||
):
|
||||
EventDispatcher.__init__(self)
|
||||
self.url = url
|
||||
self.method = method
|
||||
self.params = params
|
||||
self.headers = headers
|
||||
self.files=files
|
||||
self.hc = App.get_running_app().hc
|
||||
self.register_event_type('on_sucess')
|
||||
self.register_event_type('on_success')
|
||||
self.register_event_type('on_error')
|
||||
|
||||
def on_success(self,o,v):
|
||||
def on_success(self,v):
|
||||
pass
|
||||
|
||||
def on_error(self,o,e):
|
||||
def on_error(self,e):
|
||||
pass
|
||||
|
||||
def onSuccess(self,o,v):
|
||||
self.dispatch('on_sucess',v)
|
||||
print(__file__,'onSuccess():v=',v)
|
||||
self.dispatch('on_success',v)
|
||||
|
||||
def onError(self,o,e):
|
||||
if isinstance(e,NeedLogin):
|
||||
lf = LoginForm()
|
||||
lf.bind(on_setupuser=self.redo)
|
||||
lf.open()
|
||||
return
|
||||
self.dispatch('on_error',e)
|
||||
print_exc()
|
||||
print('[****][*********] onError Called',e)
|
||||
|
||||
def redo(self,o,v=None):
|
||||
self.handle()
|
||||
|
||||
def handle(self,params={},headers={}):
|
||||
p = self.params
|
||||
|
@ -1,27 +1,87 @@
|
||||
from kivy.logger import Logger
|
||||
from kivy.graphics import Color, Rectangle
|
||||
from kivy.properties import ListProperty
|
||||
from .color_definitions import getColors
|
||||
|
||||
_logcnt = 0
|
||||
class BGColorBehavior(object):
|
||||
bgcolor = ListProperty([])
|
||||
def __init__(self, bgcolor=[0,0,0,1],**kwargs):
|
||||
def __init__(self, bgcolor=[],fgcolor=[], color_level=-1,**kwargs):
|
||||
self.color_level = color_level
|
||||
self.bgcolor = bgcolor
|
||||
self.fgcolor = fgcolor
|
||||
self.normal_bgcolor = bgcolor
|
||||
self.normal_fgcolor = fgcolor
|
||||
self.selected_bgcolor = bgcolor
|
||||
self.selected_fgcolor = fgcolor
|
||||
self.useOwnColor = False
|
||||
self.useOwnBG = False
|
||||
self.useOwnFG = False
|
||||
if color_level != -1:
|
||||
fg,bg= getColors(color_level)
|
||||
self.fgcolor = fg
|
||||
self.bgcolor = bg
|
||||
self.normal_bgcolor = bg
|
||||
self.normal_fgcolor = fg
|
||||
fg,bg= getColors(color_level,selected=True)
|
||||
self.selected_bgcolor = bg
|
||||
self.selected_fgcolor = fg
|
||||
self.useOwnColor = True
|
||||
else:
|
||||
if bgcolor != [] and fgcolor != []:
|
||||
self.useOwnColor = True
|
||||
elif bgcolor != []:
|
||||
self.useOwnBG = True
|
||||
elif fgcolor != []:
|
||||
self.useOwnFG = True
|
||||
if self.fgcolor!=[]:
|
||||
self.color = self.fgcolor
|
||||
self.bind(size=self.onSize_bgcolor_behavior,
|
||||
pos=self.onSize_bgcolor_behavior)
|
||||
self.bind(parent=self.useAcestorColor)
|
||||
self.on_bgcolor()
|
||||
|
||||
def useAcestorColor(self,o,v=None):
|
||||
if self.useOwnColor:
|
||||
return
|
||||
|
||||
p = self.parent
|
||||
cnt = 0
|
||||
while p:
|
||||
if isinstance(p,BGColorBehavior):
|
||||
break
|
||||
p = p.parent
|
||||
cnt += 1
|
||||
if cnt > 100:
|
||||
return
|
||||
if not self.useOwnBG and p:
|
||||
self.bgcolor = p.bgcolor
|
||||
self.on_bgcolor()
|
||||
if not self.useOwnFG and p:
|
||||
self.fgcolor = p.bgcolor
|
||||
self.color = self.fgcolor
|
||||
|
||||
def onSize_bgcolor_behavior(self,o,v=None):
|
||||
if not hasattr(self,'rect'):
|
||||
self.on_bgcolor()
|
||||
else:
|
||||
self.rect.pos = o.pos
|
||||
self.rect.size = o.size
|
||||
self.rect.pos = self.pos
|
||||
self.rect.size = self.size
|
||||
|
||||
def on_bgcolor(self,o=None,v=None):
|
||||
if self.bgcolor == []:
|
||||
return
|
||||
if self.canvas:
|
||||
with self.canvas.before:
|
||||
Color(*self.bgcolor)
|
||||
self.rect = Rectangle(pos=self.pos,
|
||||
size=self.size)
|
||||
|
||||
def selected(self):
|
||||
self.bgcolor = self.selected_bgcolor
|
||||
Logger.info('selected:color=%s',self.bgcolor)
|
||||
self.on_bgcolor()
|
||||
|
||||
def unselected(self):
|
||||
self.bgcolor = self.normal_bgcolor
|
||||
Logger.info('unselected:color=%s',self.bgcolor)
|
||||
self.on_bgcolor()
|
||||
|
@ -10,6 +10,7 @@ from appPublic.dictExt import dictExtend
|
||||
from appPublic.folderUtils import ProgramPath
|
||||
from appPublic.dictObject import DictObject
|
||||
from appPublic.Singleton import SingletonDecorator
|
||||
from appPublic.datamapping import keyMapping
|
||||
|
||||
from kivy.config import Config
|
||||
from kivy.metrics import sp,dp,mm
|
||||
@ -17,14 +18,11 @@ from kivy.core.window import WindowBase
|
||||
from kivy.properties import BooleanProperty
|
||||
from kivy.uix.widget import Widget
|
||||
from kivy.app import App
|
||||
from kivy.factory import Factory
|
||||
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
|
||||
@ -113,10 +111,12 @@ def registerWidget(name,widget):
|
||||
globals()[name] = widget
|
||||
|
||||
|
||||
class Blocks:
|
||||
registedWidgets = {}
|
||||
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')
|
||||
|
||||
def register_widget(self,name,widget):
|
||||
globals()[name] = widget
|
||||
@ -140,8 +140,6 @@ class Blocks:
|
||||
raise Exception('None Function')
|
||||
func =partial(f,widget)
|
||||
return func
|
||||
setattr(widget,fname,f)
|
||||
return getattr(widget,fname)
|
||||
|
||||
def eval(self,s,l):
|
||||
g = {}
|
||||
@ -163,23 +161,22 @@ class Blocks:
|
||||
|
||||
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)
|
||||
def getUrlData(self,url,method='GET',params={}, files={},
|
||||
callback=None,
|
||||
errback=None,**kw):
|
||||
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)
|
||||
callback(None,dic)
|
||||
else:
|
||||
dic = App.get_running_app().hc(url,method=method,params=params)
|
||||
return dic, url
|
||||
h = HTTPDataHandler(url,method=method,params=params,
|
||||
files=files)
|
||||
h.bind(on_success=callback)
|
||||
h.bind(on_error=errback)
|
||||
h.handle()
|
||||
|
||||
def strValueExpr(self,s:str,localnamespace:dict={}):
|
||||
if not s.startswith('py::'):
|
||||
@ -239,7 +236,6 @@ class Blocks:
|
||||
|
||||
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
|
||||
@ -250,8 +246,10 @@ class Blocks:
|
||||
|
||||
widgetClass = desc['widgettype']
|
||||
opts = desc.get('options',{})
|
||||
klass = globals().get(widgetClass)
|
||||
if not klass:
|
||||
try:
|
||||
klass = Factory.get(widgetClass)
|
||||
except Exception as e:
|
||||
print('Error:',widgetClass,'not registered')
|
||||
raise NotExistsObject(widgetClass)
|
||||
widget = klass(**opts)
|
||||
if desc.get('parenturl'):
|
||||
@ -270,23 +268,34 @@ class Blocks:
|
||||
|
||||
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
|
||||
bcnt = 0
|
||||
btotal = len(desc.get('subwidgets',[]))
|
||||
def doit(self,widget,bcnt,btotal,desc,o,w):
|
||||
bcnt += 1
|
||||
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()
|
||||
if bcnt >= btotal:
|
||||
for b in desc.get('binds',[]):
|
||||
self.buildBind(widget,b)
|
||||
|
||||
def doerr(o,e):
|
||||
raise e
|
||||
|
||||
f = partial(doit,self,widget,bcnt,btotal,desc)
|
||||
for sw in desc.get('subwidgets',[]):
|
||||
b = Blocks()
|
||||
b.bind(on_built=f)
|
||||
b.bind(on_failed=doerr)
|
||||
w = b.widgetBuild(sw, ancestor=ancestor)
|
||||
|
||||
if btotal == 0:
|
||||
for b in desc.get('binds',[]):
|
||||
self.buildBind(widget,b)
|
||||
|
||||
def buildBind(self,widget,desc):
|
||||
wid = desc.get('wid','self')
|
||||
@ -309,7 +318,7 @@ class Blocks:
|
||||
return self.scriptAction(widget, desc)
|
||||
if acttype == 'method':
|
||||
return self.methodAction(widget, desc)
|
||||
alert(msg="actiontype invalid",title=acttype)
|
||||
alert("actiontype(%s) invalid" % acttype,title='error')
|
||||
|
||||
def blocksAction(widget,desc):
|
||||
target = self.getWidgetByIdPath(widget, desc.get('target','self'))
|
||||
@ -319,13 +328,18 @@ class Blocks:
|
||||
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 doit(target,add_mode,o,w):
|
||||
if add_mode == 'replace':
|
||||
target.clear_widgets()
|
||||
target.add_widget(w)
|
||||
|
||||
def doerr(o,e):
|
||||
raise e
|
||||
|
||||
b = Blocks()
|
||||
b.bind(on_built=partial(doit,target,add_mode))
|
||||
b.bind(on_failed=doerr)
|
||||
b.widgetBuild(opts,ancestor=widget)
|
||||
|
||||
def urlwidgetAction(self,widget,desc):
|
||||
target = self.getWidgetByIdPath(widget, desc.get('target','self'))
|
||||
@ -339,12 +353,19 @@ class Blocks:
|
||||
'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 doit(target,add_mode,o,w):
|
||||
if add_mode == 'replace':
|
||||
target.clear_widgets()
|
||||
target.add_widget(w)
|
||||
|
||||
def doerr(o,e):
|
||||
raise e
|
||||
|
||||
b = Blocks()
|
||||
b.bind(on_built=partial(doit,target,add_mode))
|
||||
b.bind(on_failed=doerr)
|
||||
b.widgetBuild(d,ancestor=widget)
|
||||
|
||||
def getActionData(self,widget,desc):
|
||||
data = {}
|
||||
@ -352,6 +373,8 @@ class Blocks:
|
||||
dwidget = self.getWidgetByIdPath(widget,
|
||||
desc.get('datawidget'))
|
||||
data = dwidget.getData()
|
||||
if desc.get('keymapping'):
|
||||
data = keyMapping(data, desc.get('keymapping'))
|
||||
return data
|
||||
|
||||
def registedfunctionAction(self, widget, desc):
|
||||
@ -361,7 +384,7 @@ class Blocks:
|
||||
params = desc.get(params,{})
|
||||
d = self.getActionData(widget,desc)
|
||||
params.update(d)
|
||||
func(params)
|
||||
func(**params)
|
||||
|
||||
def scriptAction(self, widget, desc):
|
||||
script = desc.get('script')
|
||||
@ -400,28 +423,44 @@ class Blocks:
|
||||
]
|
||||
}
|
||||
"""
|
||||
def doit(desc):
|
||||
desc = self.valueExpr(desc)
|
||||
try:
|
||||
widget = self.__build(desc,ancestor=ancestor)
|
||||
self.dispatch('on_built',widget)
|
||||
print('widgetBuild():&&&&&&&&&&&&&&&&&',widget)
|
||||
except Exception as e:
|
||||
print('&&&&&&&&&&&&&&&&&',e)
|
||||
doerr(None,e)
|
||||
print('&&&&&&&&&&&&&&&&&',e)
|
||||
return
|
||||
|
||||
def doerr(o,e):
|
||||
self.dispatch('on_failed',e)
|
||||
|
||||
name = desc['widgettype']
|
||||
if name == 'urlwidget':
|
||||
opts = desc.get('options')
|
||||
parenturl = None
|
||||
url=''
|
||||
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(desc) + 'format error',title='widgetBuild()')
|
||||
return None
|
||||
desc = self.valueExpr(desc)
|
||||
desc['parenturl'] = parenturl
|
||||
try:
|
||||
url = absurl(opts.get('url'),parenturl)
|
||||
except Exception as e:
|
||||
self.dispatch('on_failed',e)
|
||||
|
||||
try:
|
||||
widget = self.__build(desc,ancestor=ancestor)
|
||||
return widget
|
||||
except:
|
||||
print('widgetBuild() Error',desc)
|
||||
print_exc()
|
||||
alert(str(desc))
|
||||
return None
|
||||
def cb(o,d):
|
||||
try:
|
||||
d['parenturl'] = url
|
||||
doit(d)
|
||||
except Exception as e:
|
||||
doerr(None,e)
|
||||
|
||||
del opts['url']
|
||||
self.getUrlData(url,callback=cb,errback=doerr,**opts)
|
||||
return
|
||||
doit(desc)
|
||||
|
||||
def getWidgetByIdPath(self,widget,path):
|
||||
ids = path.split('/')
|
||||
@ -438,3 +477,10 @@ class Blocks:
|
||||
raise WidgetNotFoundById(id)
|
||||
return widget
|
||||
|
||||
def on_built(self,v=None):
|
||||
return
|
||||
|
||||
def on_failed(self,e=None):
|
||||
return
|
||||
|
||||
Factory.register('Blocks',Blocks)
|
||||
|
@ -15,7 +15,10 @@ BoxViewer options:
|
||||
}
|
||||
}
|
||||
"""
|
||||
from traceback import print_exc
|
||||
from functools import partial
|
||||
from kivy.app import App
|
||||
from kivy.factory import Factory
|
||||
from kivy.utils import platform
|
||||
from kivy.uix.boxlayout import BoxLayout
|
||||
from .responsivelayout import VResponsiveLayout
|
||||
@ -38,16 +41,11 @@ class BoxViewer(BoxLayout):
|
||||
if options.get('toolbar'):
|
||||
self.toolbar = Toolbar(options['toolbar'])
|
||||
lopts = options['dataloader'].copy()
|
||||
lopts['options']['adder'] = self.showObject
|
||||
lopts['options']['remover'] = self.viewContainer.remove_widget
|
||||
lopts['options']['clearer'] = self.viewContainer.clear_widgets
|
||||
lopts['options']['target'] = self
|
||||
lopts['options']['locater'] = self.locater
|
||||
LClass = RelatedLoader
|
||||
if lopts['widgettype'] == 'paging':
|
||||
LClass = Paging
|
||||
self.dataloader = RelatedLoader(target=self,**lopts['options'])
|
||||
self.dataloader.bind(on_deletepage=self.deleteWidgets)
|
||||
self.dataloader.bind(on_pageloaded=self.addPageWidgets)
|
||||
self.dataloader.bind(on_newbegin=self.deleteAllWidgets)
|
||||
|
||||
self.dataloader = LClass(**lopts['options'])
|
||||
if self.toolbar:
|
||||
self.add_widget(self.toolbar)
|
||||
if self.dataloader.widget:
|
||||
@ -58,6 +56,30 @@ class BoxViewer(BoxLayout):
|
||||
pos=self.resetCols)
|
||||
self.viewContainer.bind(on_scroll_stop=self.on_scroll_stop)
|
||||
|
||||
def deleteAllWidgets(self,o):
|
||||
self.viewContainer.clear_widgets()
|
||||
|
||||
def addPageWidgets(self,o,data):
|
||||
widgets = []
|
||||
recs = data['data']
|
||||
dir = data['dir']
|
||||
idx = 0
|
||||
if dir == 'up':
|
||||
recs.reverse()
|
||||
idx = -1
|
||||
print('addPageWidgets(),begin')
|
||||
for r in recs:
|
||||
self.showObject(widgets, r, index=idx)
|
||||
|
||||
print('addPageWidgets(),widgets=',len(widgets))
|
||||
self.dataloader.bufferObjects(widgets)
|
||||
x = self.dataloader.getLocater()
|
||||
self.locater(x)
|
||||
|
||||
def deleteWidgets(self,o,data):
|
||||
for w in data:
|
||||
self.viewContainer.remove_widget(w)
|
||||
|
||||
def on_selected(self, o, v=None):
|
||||
print('BoxViewer(): on_selected fired....')
|
||||
|
||||
@ -77,20 +99,29 @@ class BoxViewer(BoxLayout):
|
||||
self.dataloader.loadPage(1)
|
||||
self.initflag = True
|
||||
|
||||
def showObject(self, rec,**kw):
|
||||
blocks = App.get_running_app().blocks
|
||||
def showObject(self, holders, rec,index=0):
|
||||
def doit(self,holders,idx,o,w):
|
||||
print('showObject()...doit(),w=',w,o)
|
||||
w.bind(on_press=self.select_record)
|
||||
self.viewContainer.add_widget(w,index=idx)
|
||||
holders.append(w)
|
||||
|
||||
def doerr(o,e):
|
||||
print_exc()
|
||||
print('showObject(),error=',e)
|
||||
raise e
|
||||
options = self.options['viewer'].copy()
|
||||
options['options']['record'] = rec
|
||||
options['options']['ancestor'] = self
|
||||
options['options']['size_hint'] = None,None
|
||||
options['options']['width'] = self.box_width
|
||||
options['options']['height'] = self.box_height
|
||||
w = blocks.widgetBuild(options, ancestor=self)
|
||||
if w is None:
|
||||
return None
|
||||
w.bind(on_press=self.select_record)
|
||||
self.viewContainer.add_widget(w,**kw)
|
||||
return w
|
||||
blocks = Factory.Blocks()
|
||||
blocks.bind(on_built=partial(doit,self,holders,index))
|
||||
blocks.bind(on_failed=doerr)
|
||||
print('showObject():********here***********')
|
||||
blocks.widgetBuild(options, ancestor=self)
|
||||
print('showObject():********end ***********')
|
||||
|
||||
def on_scroll_stop(self,o,v=None):
|
||||
if o.scroll_y <= 0.001:
|
||||
|
@ -46,6 +46,10 @@ form options
|
||||
"""
|
||||
|
||||
uitypes = {
|
||||
"str":{
|
||||
"orientation":"horizontal",
|
||||
"wclass":StrInput,
|
||||
},
|
||||
"string":{
|
||||
"orientation":"horizontal",
|
||||
"wclass":StrInput,
|
||||
@ -54,6 +58,10 @@ uitypes = {
|
||||
"orientation":"horizontal",
|
||||
"wclass":Password,
|
||||
},
|
||||
"int":{
|
||||
"orientation":"horizontal",
|
||||
"wclass":IntegerInput,
|
||||
},
|
||||
"number":{
|
||||
"orientation":"horizontal",
|
||||
"wclass":IntegerInput,
|
||||
@ -87,7 +95,7 @@ uitypes = {
|
||||
"wclass":StrInput,
|
||||
"options":{
|
||||
"multiline":True,
|
||||
"height":CSize(9),
|
||||
"height":9,
|
||||
}
|
||||
},
|
||||
"teleno":{
|
||||
@ -111,9 +119,12 @@ class InputBox(BoxLayout):
|
||||
self.labelwidth = self.form.options['labelwidth']
|
||||
kwargs = {
|
||||
"orientation":orientation,
|
||||
"size_hint_y":None,
|
||||
"height":height
|
||||
}
|
||||
if height<=1:
|
||||
kwargs['size_hint_y'] = height
|
||||
else:
|
||||
kwargs['size_hint_y'] = None
|
||||
kwargs['height'] = CSize(height)
|
||||
if width <= 1:
|
||||
kwargs['size_hint_x'] = width
|
||||
else:
|
||||
@ -121,7 +132,7 @@ class InputBox(BoxLayout):
|
||||
kwargs['width'] = CSize(width)
|
||||
super().__init__(**kwargs)
|
||||
self.initflag = False
|
||||
self.bind(on_size=self.setSize,
|
||||
self.bind(size=self.setSize,
|
||||
pos=self.setSize)
|
||||
self.register_event_type("on_datainput")
|
||||
self.register_event_type("on_ready")
|
||||
@ -169,8 +180,8 @@ class InputBox(BoxLayout):
|
||||
options = self.uidef.get('options',{}).copy()
|
||||
options.update(self.options.get('uiparams',{}))
|
||||
options['allow_copy'] = True
|
||||
options['size_hint_y'] = None
|
||||
options['height'] = CSize(3)
|
||||
options['width'] = 1
|
||||
options['height'] = 2.5
|
||||
if self.options.get('tip'):
|
||||
options['hint_text'] = i18n(self.options.get('tip'))
|
||||
|
||||
@ -217,6 +228,12 @@ class InputBox(BoxLayout):
|
||||
def getValue(self):
|
||||
return {self.options.get('name'):self.input_widget.getValue()}
|
||||
|
||||
def disable(self,*args,**kwargs):
|
||||
self.input_widget.disabled = True
|
||||
|
||||
def enable(self,*args,**kwargs):
|
||||
self.input_widget.disabled = False
|
||||
|
||||
def defaultToolbar():
|
||||
return {
|
||||
"img_size":2,
|
||||
@ -241,23 +258,18 @@ class Form(BGColorBehavior, BoxLayout):
|
||||
self.options = options
|
||||
BoxLayout.__init__(self, orientation='vertical')
|
||||
self.color_level = self.options.get('color_level', 0)
|
||||
textcolor, bgcolor = getColors(self.color_level)
|
||||
BGColorBehavior.__init__(self,bgcolor=bgcolor)
|
||||
BGColorBehavior.__init__(self,color_level=self.color_level)
|
||||
self.widget_ids = {}
|
||||
self.readiedInput = 0
|
||||
self.cols = self.options_cols = self.options.get('cols',1)
|
||||
if isHandHold() and Window.width < Window.height:
|
||||
self.cols = 1
|
||||
self.inputwidth = Window.width / self.cols
|
||||
self.inputheight = CSize(self.options.get('inputheight',3))
|
||||
self.initflag = False
|
||||
self.inputheight = self.options.get('inputheight',3)
|
||||
self.init()
|
||||
self.register_event_type('on_submit')
|
||||
self.bind(size=self.on_size,
|
||||
pos=self.on_size)
|
||||
|
||||
def init(self):
|
||||
if self.initflag:
|
||||
return
|
||||
self.toolbar = Toolbar(ancestor=self,**self.options.get('toolbar',defaultToolbar()))
|
||||
self.fsc = VResponsiveLayout(
|
||||
self.inputwidth,
|
||||
@ -279,7 +291,6 @@ class Form(BGColorBehavior, BoxLayout):
|
||||
wid = blocks.getWidgetByIdPath(self,'__clear')
|
||||
# wid = self.widget_ids['__clear']
|
||||
wid.bind(on_press=self.on_clear_button)
|
||||
self.initflag = True
|
||||
|
||||
def makeInputLink(self,o,v=None):
|
||||
self.readiedInput += 1
|
||||
@ -323,10 +334,6 @@ class Form(BGColorBehavior, BoxLayout):
|
||||
for fw in self.fieldWidgets:
|
||||
fw.clear()
|
||||
|
||||
def on_size(self,o, v=None):
|
||||
self.init()
|
||||
textcolor, self.bgcolor = getColors(self.color_level)
|
||||
|
||||
class StrSearchForm(BoxLayout):
|
||||
def __init__(self,img_url=None,**options):
|
||||
self.name = options.get('name','search_string')
|
||||
|
@ -28,6 +28,8 @@ class I18n:
|
||||
if lang is None:
|
||||
lang = self.lang
|
||||
d = self.kvlang.get(lang,{})
|
||||
if d is None:
|
||||
return msg
|
||||
return d.get(msg,msg)
|
||||
|
||||
def changeLang(self,lang):
|
||||
|
@ -41,18 +41,15 @@ class KivySizes:
|
||||
return self.unitedSize(x,y=y,name=name)
|
||||
|
||||
def getScreenSize(self):
|
||||
#root = App.get_running_app().root
|
||||
#return root.width, root.height
|
||||
return Window.width, Window.height
|
||||
|
||||
def getWindowPhysicalSize(self,w):
|
||||
h_phy = float(w.height) / mm(1)
|
||||
w_phy = float(w.width) / mm(1)
|
||||
def getWindowPhysicalSize(self):
|
||||
h_phy = float(Window.height) / mm(1)
|
||||
w_phy = float(Window.width) / mm(1)
|
||||
return w_phy, h_phy
|
||||
|
||||
def getScreenPhysicalSize(self):
|
||||
return self.getWindowPhysicalSize(App.get_running_app().root)
|
||||
return self.getWindowPhysicalSize(Window)
|
||||
return self.getWindowPhysicalSize()
|
||||
|
||||
def isHandHold(self):
|
||||
return min(self.getScreenPhysicalSize()) <= 75.0
|
||||
|
@ -1,4 +1,6 @@
|
||||
from traceback import print_exc
|
||||
from kivy.logger import Logger
|
||||
from kivy.factory import Factory
|
||||
from kivy.app import App
|
||||
from kivy.core.window import Window
|
||||
from kivy.uix.popup import Popup
|
||||
@ -35,21 +37,14 @@ class LoginForm(Popup):
|
||||
def __init__(self):
|
||||
super().__init__(size_hint=(0.8,0.8))
|
||||
self.title = 'login'
|
||||
self.initflag = False
|
||||
self.bind(size=self.buildContent,
|
||||
pos=self.buildContent)
|
||||
self.buildContent(None,None)
|
||||
self.register_event_type('on_setupuser')
|
||||
|
||||
def on_setupuser(self,o=None):
|
||||
return
|
||||
|
||||
def buildContent(self,o,size):
|
||||
print('build Content. ....')
|
||||
if self.initflag:
|
||||
return
|
||||
print('build Content ....... ....')
|
||||
self.initflag = True
|
||||
app = App.get_running_app()
|
||||
try:
|
||||
self.content = app.blocks.widgetBuild(logformdesc)
|
||||
except Exception as e:
|
||||
Logger.info('login: Error %s', e)
|
||||
self.content = Factory.Form(**logformdesc['options'])
|
||||
self.content.bind(on_submit=self.on_submit)
|
||||
|
||||
def on_submit(self,o,userinfo):
|
||||
@ -61,10 +56,7 @@ class LoginForm(Popup):
|
||||
if userinfo.get('passwd',False):
|
||||
userinfo['authmethod'] = 'password'
|
||||
authinfo = app.serverinfo.encode(userinfo)
|
||||
config = getConfig()
|
||||
login_url = '%s%s' % (config.uihome, config.login_url)
|
||||
x = app.hc.get(login_url)
|
||||
print('login return=', x, login_url, authinfo)
|
||||
self.dispatch('on_setupuser')
|
||||
|
||||
def on_cancel(self,o,v):
|
||||
print('login() on_cancel fired .....')
|
||||
|
75
kivyblocks/newwidget.py
Normal file
75
kivyblocks/newwidget.py
Normal file
@ -0,0 +1,75 @@
|
||||
from kivy.logger import Logger
|
||||
from kivy.graphics import Color, Rectangle
|
||||
from kivy.properties import ListProperty, NumericProperty
|
||||
from kivy.factory import Factory
|
||||
from kivy.uix.widget import Widget
|
||||
|
||||
from .color_definitions import getColors
|
||||
|
||||
class NewWidget(Widget):
|
||||
bgcolor = ListProperty([])
|
||||
fcolor = ListProperty([])
|
||||
color_level = NumericProperty(-1)
|
||||
def __init__(self, color_level=-1,bgcolor=[],fcolor=[],**kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.bgcolor = bgcolor
|
||||
self.fcolor = fcolor
|
||||
self.color_level = color_level
|
||||
self.initColors()
|
||||
self.bind(size=self.onSize_bgcolor_behavior,
|
||||
pos=self.onSize_bgcolor_behavior)
|
||||
|
||||
def initColors(self):
|
||||
if self.color_level != -1:
|
||||
fcolor, bgcolor = getColors(self.color_level)
|
||||
if self.bgcolor == []:
|
||||
self.bgcolor = bgcolor
|
||||
if self.fcolor == []:
|
||||
self.fcolor = fcolor
|
||||
|
||||
def getParentColorLevel(self):
|
||||
if not self.parent:
|
||||
self.fcolor, self.bgcolor = getColors(self.color_level):
|
||||
|
||||
def on_color_level(self,o,v=None):
|
||||
if bgcolor != [] and fcolor != []:
|
||||
return
|
||||
|
||||
if color_level != -1:
|
||||
fcolor, bgcolor = getColors(self.color_level)
|
||||
if self.bgcolor == []:
|
||||
self.bgcolor = bgcolor
|
||||
if self.fcolor == []:
|
||||
self.fcolor = fcolor
|
||||
|
||||
def on_fcolor(self,o,v=None):
|
||||
self.color = self.fcolor
|
||||
|
||||
def on_parent(self,o,v=None):
|
||||
if self.color_level != -1:
|
||||
self.fcolor, self.bgcolor = getColors(self.color_level)
|
||||
|
||||
if self.color_level == -1:
|
||||
self.setColorsFromAncestor()
|
||||
|
||||
def onSize_bgcolor_behavior(self,o,v=None):
|
||||
if not hasattr(self,'rect'):
|
||||
self.on_bgcolor()
|
||||
else:
|
||||
self.rect.pos = o.pos
|
||||
self.rect.size = o.size
|
||||
|
||||
def on_bgcolor(self,o=None,v=None):
|
||||
if self.bgcolor == []:
|
||||
return
|
||||
if self.canvas:
|
||||
with self.canvas.before:
|
||||
Color(*self.bgcolor)
|
||||
self.rect = Rectangle(pos=self.pos,
|
||||
size=self.size)
|
||||
|
||||
try:
|
||||
Factory.unregister('Widget')
|
||||
except:
|
||||
pass
|
||||
Factory.register('Widget',cls=NewWidget)
|
@ -2,6 +2,7 @@ import traceback
|
||||
import math
|
||||
|
||||
from kivy.logger import Logger
|
||||
from kivy.event import EventDispatcher
|
||||
from kivy.uix.boxlayout import BoxLayout
|
||||
from kivy.uix.button import Button
|
||||
from kivy.clock import Clock
|
||||
@ -9,7 +10,7 @@ from kivy.app import App
|
||||
from functools import partial
|
||||
from appPublic.dictObject import DictObject
|
||||
from appPublic.jsonConfig import getConfig
|
||||
from .baseWidget import Text
|
||||
from .baseWidget import Text, HTTPDataHandler
|
||||
from .utils import CSize, absurl, alert
|
||||
from .form import StrSearchForm
|
||||
|
||||
@ -28,37 +29,22 @@ class PagingButton(Button):
|
||||
locater
|
||||
filter
|
||||
}
|
||||
|
||||
PageLoader load data in a page size once.
|
||||
it fires two type of event
|
||||
'on_newbegin':fire when start a new parameters loading series
|
||||
'on_pageloaded':fire when a page data loads success
|
||||
"""
|
||||
|
||||
class HttpLoader:
|
||||
def __init__(self, url, method, params,page_rows=60):
|
||||
self.page_rows = page_rows
|
||||
self.url = url
|
||||
self.method = method
|
||||
self.params = params
|
||||
|
||||
def setParams(self,params, url=None, page_rows=60):
|
||||
self.params = params
|
||||
if url is not None:
|
||||
self.url = url
|
||||
self.page_rows = page_rows
|
||||
|
||||
def load(self, callback, errback=None):
|
||||
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):
|
||||
class PageLoader(EventDispatcher):
|
||||
def __init__(self,target=None, **options):
|
||||
self.loading = False
|
||||
self.target = target
|
||||
self.options = options
|
||||
self.filter = None
|
||||
if options.get('filter'):
|
||||
self.filter = StrSearchForm(**options['filter'])
|
||||
self.filter.bind(on_submit=self.do_search)
|
||||
|
||||
self.params = options.get('params',{})
|
||||
self.method = options.get('method','GET')
|
||||
self.url = options.get('dataurl')
|
||||
@ -66,14 +52,34 @@ class PageLoader:
|
||||
self.total_cnt = 0
|
||||
self.total_page = 0
|
||||
self.curpage = 0
|
||||
Logger.info('kivyblocks: method=%s,type=%s',str(self.method),type(self.method))
|
||||
self.loader = HttpLoader(self.url, self.method, self.params )
|
||||
self.dir = 'down'
|
||||
self.register_event_type('on_newbegin')
|
||||
self.register_event_type('on_pageloaded')
|
||||
|
||||
def getLocater(self):
|
||||
x = 1 / self.MaxbufferPage
|
||||
if self.dir != 'down':
|
||||
x = 1 - x
|
||||
print('getLocater(),x=%f,dir=%s,self.curpage=%d' % (x,self.dir,self.curpage))
|
||||
return x
|
||||
|
||||
def on_newbegin(self):
|
||||
pass
|
||||
|
||||
def on_pageloaded(self,d):
|
||||
"""
|
||||
d={
|
||||
page:
|
||||
data:[]
|
||||
dir:'up' or 'down'
|
||||
}
|
||||
"""
|
||||
pass
|
||||
|
||||
def do_search(self,o,params):
|
||||
print('PageLoader().do_search(), on_submit handle....',params)
|
||||
self.clearer()
|
||||
self.dispatch('on_newbegin')
|
||||
self.params.update(params)
|
||||
self.loader.setParams(self.params)
|
||||
self.loadPage(1)
|
||||
|
||||
def calculateTotalPage(self):
|
||||
@ -94,21 +100,19 @@ class PageLoader:
|
||||
self.curpage = 1
|
||||
self.loadPage(self.curpage)
|
||||
|
||||
def setDir(self):
|
||||
pages = self.objectPages.keys()
|
||||
if len(pages)==0:
|
||||
self.dir = 'down'
|
||||
return
|
||||
if self.curpage >= max(self.objectPages.keys()):
|
||||
self.dir = 'down'
|
||||
else:
|
||||
self.dir = 'up'
|
||||
|
||||
def show_page(self,o,d):
|
||||
p = (self.curpage - 1) * self.page_rows + 1
|
||||
for r in d['rows']:
|
||||
r['__posInSet__'] = p
|
||||
p += 1
|
||||
self.total_cnt = d['total']
|
||||
self.calculateTotalPage()
|
||||
d = {
|
||||
"page":self.curpage,
|
||||
"dir":self.dir,
|
||||
"data":d['rows']
|
||||
}
|
||||
self.dispatch('on_pageloaded',d)
|
||||
|
||||
def httperror(self,o,e):
|
||||
traceback.print_exc()
|
||||
@ -117,6 +121,12 @@ class PageLoader:
|
||||
def loadPage(self,p):
|
||||
if not self.url:
|
||||
raise Exception('dataurl must be present:options=%s' % str(options))
|
||||
if self.curpage > p:
|
||||
self.dir = 'up'
|
||||
elif self.curpage == p:
|
||||
self.dir = 'reload'
|
||||
else:
|
||||
self.dir = 'down'
|
||||
self.curpage = p
|
||||
self.loading = True
|
||||
params = self.params.copy()
|
||||
@ -124,9 +134,11 @@ class PageLoader:
|
||||
"page":self.curpage,
|
||||
"rows":self.page_rows
|
||||
})
|
||||
url = absurl(self.url,self.target.parenturl)
|
||||
self.loader.setParams(params,url=url)
|
||||
self.loader.load(self.show_page,self.httperror)
|
||||
realurl = absurl(self.url,self.target.parenturl)
|
||||
loader = HTTPDataHandler(realurl,params=params)
|
||||
loader.bind(on_success=self.show_page)
|
||||
loader.bind(on_failed=self.httperror)
|
||||
loader.handle()
|
||||
|
||||
"""
|
||||
{
|
||||
@ -139,22 +151,25 @@ class PageLoader:
|
||||
method,
|
||||
filter
|
||||
}
|
||||
events:
|
||||
'on_bufferraise': erase
|
||||
|
||||
"""
|
||||
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')
|
||||
self.objectPages = {}
|
||||
self.totalObj = 0
|
||||
self.MaxbufferPage = 3
|
||||
self.locater = 1/self.MaxbufferPage
|
||||
if self.filter:
|
||||
self.widget = self.filter
|
||||
else:
|
||||
self.widget = None
|
||||
self.register_event_type('on_deletepage')
|
||||
|
||||
def on_deletepage(self,d):
|
||||
pass
|
||||
|
||||
def setPageRows(self,row_cnt):
|
||||
if self.total_cnt != 0:
|
||||
@ -171,42 +186,21 @@ class RelatedLoader(PageLoader):
|
||||
self.deleteBuffer(p)
|
||||
|
||||
def deleteBuffer(self,page):
|
||||
for w in self.objectPages[page]:
|
||||
self.remover(w)
|
||||
d = self.objectPages[page]
|
||||
self.dispatch('on_deletepage',d)
|
||||
self.totalObj -= len(self.objectPages[page])
|
||||
del self.objectPages[page]
|
||||
|
||||
def bufferObjects(self,objects):
|
||||
self.objectPages[self.curpage] = objects
|
||||
|
||||
def show_page(self,o,data):
|
||||
super().show_page(o,data)
|
||||
if self.objectPages.get(self.curpage):
|
||||
self.deleteBuffer(self.curpage)
|
||||
else:
|
||||
self.setDir()
|
||||
self.doBufferMaintain()
|
||||
self.total_cnt = data['total']
|
||||
self.calculateTotalPage()
|
||||
widgets = []
|
||||
rows = data['rows']
|
||||
if self.dir == 'up':
|
||||
rows.reverse()
|
||||
for r in rows:
|
||||
if self.dir == 'up':
|
||||
w = self.adder(r,index=self.totalObj)
|
||||
else:
|
||||
w = self.adder(r)
|
||||
widgets.append(w)
|
||||
self.totalObj += 1
|
||||
self.objectPages[self.curpage] = widgets
|
||||
pages = len(self.objectPages.keys())
|
||||
loc = 1.0 / float(pages)
|
||||
if self.locater:
|
||||
if pages == 1:
|
||||
self.locater(1)
|
||||
elif self.dir == 'up':
|
||||
self.locater(1 - loc)
|
||||
else:
|
||||
self.locater(loc)
|
||||
|
||||
self.totalObj += len(data['rows'])
|
||||
super().show_page(o,data)
|
||||
self.loading = False
|
||||
print('buffer pages=',len(self.objectPages.keys()),'pages=',self.objectPages.keys())
|
||||
|
||||
@ -218,12 +212,12 @@ class RelatedLoader(PageLoader):
|
||||
if len(pages) < 1:
|
||||
return
|
||||
|
||||
self.curpage = min(pages)
|
||||
if self.curpage <= 1:
|
||||
page = min(pages)
|
||||
if page <= 1:
|
||||
return
|
||||
|
||||
self.curpage -= 1
|
||||
self.loadPage(self.curpage)
|
||||
page -= 1
|
||||
self.loadPage(page)
|
||||
|
||||
def loadNextPage(self):
|
||||
if self.loading:
|
||||
@ -231,11 +225,11 @@ class RelatedLoader(PageLoader):
|
||||
pages = self.objectPages.keys()
|
||||
if len(pages) == 0:
|
||||
return
|
||||
self.curpage = max(pages)
|
||||
if self.curpage>=self.total_page:
|
||||
page = max(pages)
|
||||
if page>=self.total_page:
|
||||
return
|
||||
self.curpage += 1
|
||||
self.loadPage(self.curpage)
|
||||
page += 1
|
||||
self.loadPage(page)
|
||||
|
||||
"""
|
||||
{
|
||||
|
41
kivyblocks/register.py
Normal file
41
kivyblocks/register.py
Normal file
@ -0,0 +1,41 @@
|
||||
from kivy.utils import platform
|
||||
from .baseWidget import *
|
||||
from .tree import Tree, TextTree, PopupMenu
|
||||
from .toolbar import ToolPage, Toolbar
|
||||
from .dg import DataGrid
|
||||
from .vplayer import VPlayer
|
||||
from .form import Form, StrSearchForm
|
||||
from .boxViewer import BoxViewer
|
||||
from .pagescontainer import PageContainer
|
||||
|
||||
r = Factory.register
|
||||
r('PageContainer', PageContainer)
|
||||
r('BoxViewer', BoxViewer)
|
||||
r('Form', Form)
|
||||
r('StrSearchForm', StrSearchForm)
|
||||
r('VPlayer', VPlayer)
|
||||
r('DataGrid', DataGrid)
|
||||
r('Toolbar', Toolbar)
|
||||
r('ToolPage',ToolPage)
|
||||
r('HTTPDataHandler',HTTPDataHandler)
|
||||
r('Text',Text)
|
||||
r('ScrollWidget',ScrollWidget)
|
||||
r('BinStateImage',BinStateImage)
|
||||
r('JsonCodeInput',JsonCodeInput)
|
||||
r('FloatInput',FloatInput)
|
||||
r('IntegerInput',IntegerInput)
|
||||
r('StrInput',StrInput)
|
||||
r('SelectInput',SelectInput)
|
||||
r('BoolInput',BoolInput)
|
||||
r('AmountInput',AmountInput)
|
||||
r('Messager',Messager)
|
||||
r('Bar',Bar)
|
||||
r('LoginForm',LoginForm)
|
||||
r('PressableImage', PressableImage)
|
||||
r('PressableLabel', PressableLabel)
|
||||
r('Tree',Tree)
|
||||
r('TextTree',TextTree)
|
||||
r('PopupMenu',PopupMenu)
|
||||
if platform == 'android':
|
||||
r('PhoneButton',PhoneButton)
|
||||
r('AWebView',AWebView)
|
35
kivyblocks/tab.py
Normal file
35
kivyblocks/tab.py
Normal file
@ -0,0 +1,35 @@
|
||||
"""
|
||||
{
|
||||
"widgettype":"BLKTabbedPanel",
|
||||
"tab_pos":"top_left",
|
||||
"color_level":0,
|
||||
"width",
|
||||
"height",
|
||||
"size_hint",
|
||||
"tabs":[
|
||||
{
|
||||
"text":"tab1",
|
||||
"content":{
|
||||
"widgettype":"urlwidegt",
|
||||
"url":"reggtY",
|
||||
}
|
||||
},
|
||||
{
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
|
||||
class BLKTabItem(BGColorBehavior, TabbedPanelItem):
|
||||
def __init__(self,parent,color_level=0,text="",content={}):
|
||||
self.parent=parent
|
||||
self.color_level = color_level
|
||||
|
||||
class BLKTabedPanel(BGColorBehavior, TabbedPanel):
|
||||
def __init__(self,color_level=0, tabs=[], **kwargs):
|
||||
self.tabs_desc = tabs
|
||||
self.color_level = color_level
|
||||
TabbedPanel.__init__(**kwargs)
|
||||
BGColorBehavior.__init__(self)
|
||||
|
||||
class
|
@ -6,9 +6,7 @@ from kivy.event import EventDispatcher
|
||||
from kivy.clock import Clock
|
||||
from kivy.app import App
|
||||
from .login import LoginForm
|
||||
|
||||
class NeedLogin(Exception):
|
||||
pass
|
||||
from .utils import NeedLogin, InsufficientPrivilege, HTTPError
|
||||
|
||||
class ThreadCall(Thread,EventDispatcher):
|
||||
def __init__(self,target, args=(), kwargs={}):
|
||||
@ -95,7 +93,11 @@ class HttpClient:
|
||||
app = App.get_running_app()
|
||||
domain = self.url2domain(url)
|
||||
sessionid = hostsessions.get(domain,None)
|
||||
print('hostsessions=', hostsessions, 'sessionid=',sessionid, 'domain=',domain)
|
||||
print('hostsessions=', hostsessions,
|
||||
'sessionid=',sessionid,
|
||||
'domain=',domain,
|
||||
'url=',url
|
||||
)
|
||||
if sessionid:
|
||||
headers.update({'session':sessionid})
|
||||
elif app.getAuthHeader():
|
||||
@ -128,10 +130,16 @@ class HttpClient:
|
||||
except:
|
||||
return resp.text
|
||||
if resp.status_code == 401:
|
||||
print('NeedLogin:',url)
|
||||
raise NeedLogin
|
||||
|
||||
print('Error', url, method, params, resp.status_code,type(resp.status_code))
|
||||
raise Exception('error:%s' % url)
|
||||
if resp.status_code == 403:
|
||||
raise InsufficientPrivilege
|
||||
|
||||
print('Error', url, method,
|
||||
params, resp.status_code,
|
||||
type(resp.status_code))
|
||||
raise HTTPError(resp.status_code)
|
||||
|
||||
def __call__(self,url,method="GET",params={},headers={},files={},callback=None,errback=None):
|
||||
def cb(t,resp):
|
||||
@ -142,10 +150,8 @@ class HttpClient:
|
||||
resp = self.webcall(url, method=method,
|
||||
params=params, files=files, headers=headers)
|
||||
return cb(None,resp)
|
||||
except NeedLogin as e:
|
||||
lf = LoginForm()
|
||||
lf.open()
|
||||
return None
|
||||
except Exception as e:
|
||||
raise e
|
||||
except Exception as e:
|
||||
if errback is not None:
|
||||
errback(e)
|
||||
|
@ -42,7 +42,7 @@ class Tool(ButtonBehavior, BGColorBehavior, BoxLayout):
|
||||
ButtonBehavior.__init__(self)
|
||||
BoxLayout.__init__(self,
|
||||
size_hint_y=None)
|
||||
BGColorBehavior.__init__(self)
|
||||
BGColorBehavior.__init__(self,color_level=ancestor.color_level)
|
||||
self.bl = BoxLayout(orientation='vertical',
|
||||
size_hint_y=None)
|
||||
self.add_widget(self.bl)
|
||||
@ -62,7 +62,8 @@ class Tool(ButtonBehavior, BGColorBehavior, BoxLayout):
|
||||
|
||||
tsize = CSize(self.opts.text_size)
|
||||
label = self.opts.label or self.opts.name
|
||||
self.lbl = I18nText(otext=label,
|
||||
self.lbl = I18nText(color_level=self.ancestor.color_level,
|
||||
otext=label,
|
||||
font_size=int(tsize),
|
||||
text_size=(CSize(len(label)), tsize),
|
||||
height=tsize,
|
||||
@ -71,24 +72,21 @@ class Tool(ButtonBehavior, BGColorBehavior, BoxLayout):
|
||||
)
|
||||
self.bl.add_widget(self.lbl)
|
||||
self.height = (size + tsize)*1.1
|
||||
self.lbl.color, self.bgcolor = getColors(self.ancestor.color_level,
|
||||
selected=False)
|
||||
self.lbl.bgcolor = self.bgcolor
|
||||
|
||||
def on_size(self,obj,size):
|
||||
Logger.info('toolbar: Tool() on_size fired')
|
||||
self.lbl.color, self.bgcolor = getColors(self.ancestor.color_level,
|
||||
selected=False)
|
||||
self.lbl.bgcolor = self.bgcolor
|
||||
#self.lbl.color, self.bgcolor = getColors(self.ancestor.color_level,
|
||||
# selected=False)
|
||||
#self.lbl.bgcolor = self.bgcolor
|
||||
|
||||
def on_press(self):
|
||||
print('Tool(). pressed ...............')
|
||||
|
||||
def setActive(self,flag):
|
||||
text_color, self.bgcolor = getColors(self.ancestor.color_level,
|
||||
selected=flag)
|
||||
self.lbl.bgcolor = self.bgcolor
|
||||
self.lbl.color = text_color
|
||||
if flag:
|
||||
self.selected()
|
||||
else:
|
||||
self.unselected()
|
||||
|
||||
|
||||
"""
|
||||
@ -106,11 +104,15 @@ toolbar options
|
||||
]
|
||||
}
|
||||
"""
|
||||
class Toolbar(GridLayout):
|
||||
class Toolbar(BGColorBehavior, GridLayout):
|
||||
def __init__(self, ancestor=None,**opts):
|
||||
self.opts = DictObject(**opts)
|
||||
self.tool_widgets={}
|
||||
super().__init__(cols = len(self.opts.tools))
|
||||
GridLayout.__init__(self,cols = len(self.opts.tools))
|
||||
color_level = 0
|
||||
if isinstance(ancestor, BGColorBehavior):
|
||||
color_level = ancestor.color_level + 1
|
||||
BGColorBehavior.__init__(self,color_level=color_level)
|
||||
self.size_hint = (1,None)
|
||||
first = True
|
||||
for opt in self.opts.tools:
|
||||
@ -175,9 +177,9 @@ class ToolPage(BGColorBehavior, BoxLayout):
|
||||
orient = 'vertical'
|
||||
else:
|
||||
orient = 'horizontal'
|
||||
|
||||
color_level=self.opts.color_level or 0
|
||||
BoxLayout.__init__(self,orientation=orient)
|
||||
BGColorBehavior.__init__(self)
|
||||
BGColorBehavior.__init__(self,color_level=color_level)
|
||||
self.content = None
|
||||
self.toolbar = None
|
||||
self.init()
|
||||
@ -190,7 +192,6 @@ class ToolPage(BGColorBehavior, BoxLayout):
|
||||
self.toolbar.width = x
|
||||
self.content.width = x
|
||||
self.content.height = y - self.toolbar.height
|
||||
self.color, self.bgcolor = getColors(self.color_level)
|
||||
|
||||
def showPage(self,obj):
|
||||
self._show_page(obj.opts)
|
||||
@ -211,8 +212,6 @@ class ToolPage(BGColorBehavior, BoxLayout):
|
||||
t.img_src = absurl(t.img_src,parenturl)
|
||||
|
||||
opts = self.opts
|
||||
self.color_level = self.opts.color_level or 0
|
||||
self.color, self.bgcolor = getColors(self.color_level)
|
||||
self.toolbar = Toolbar(ancestor=self, **self.opts)
|
||||
if self.opts.tool_at in ['top','left']:
|
||||
self.add_widget(self.toolbar)
|
||||
|
@ -285,7 +285,7 @@ class Tree(BGColorBehavior, ScrollWidget):
|
||||
def __init__(self,**options):
|
||||
self.color_level = options.get('color_level',0)
|
||||
ScrollWidget.__init__(self)
|
||||
BGColorBehavior.__init__(self)
|
||||
BGColorBehavior.__init__(self,color_level=self.color_level)
|
||||
self.options = DictObject(**options)
|
||||
self.nodes = []
|
||||
self.initflag = False
|
||||
@ -377,21 +377,16 @@ class Tree(BGColorBehavior, ScrollWidget):
|
||||
self.nodes = [ i for i in self.nodes if i != node ]
|
||||
|
||||
class TextContent(PressableLabel):
|
||||
def __init__(self,level=0,**options):
|
||||
PressableLabel.__init__(self,**options)
|
||||
|
||||
def selected(self):
|
||||
pass
|
||||
|
||||
def unselected(self):
|
||||
pass
|
||||
def __init__(self,color_level=0,**options):
|
||||
PressableLabel.__init__(self,color_level=color_level,**options)
|
||||
|
||||
|
||||
class TextTreeNode(TreeNode):
|
||||
def buildContent(self):
|
||||
txt = self.data.get(self.treeObj.options.textField,
|
||||
self.data.get(self.treeObj.options.idField,'defaulttext'))
|
||||
self.content = TextContent( text=txt,
|
||||
self.content = TextContent(color_level=self.treeObj.color_level,
|
||||
text=txt,
|
||||
size_hint=(None,None),
|
||||
font_size=CSize(1),
|
||||
text_size=CSize(len(txt)-1,1),
|
||||
@ -412,18 +407,12 @@ class TextTreeNode(TreeNode):
|
||||
self.treeObj.select_row(self)
|
||||
|
||||
def selected(self):
|
||||
Logger.info('content selected ........')
|
||||
color, bgcolor = getColors(self.treeObj.color_level,
|
||||
selected=True)
|
||||
self.content.bgcolor = bgcolor
|
||||
self.content.color = color
|
||||
if hasattr(self.content,'selected'):
|
||||
self.content.selected()
|
||||
|
||||
def unselected(self):
|
||||
Logger.info('content unselected ........')
|
||||
color, bgcolor = getColors(self.treeObj.color_level,
|
||||
selected=False)
|
||||
self.content.bgcolor = bgcolor
|
||||
self.content.color = color
|
||||
if hasattr(self.content,'unselected'):
|
||||
self.content.unselected()
|
||||
|
||||
class TextTree(Tree):
|
||||
def __init__(self,**options):
|
||||
|
@ -1,4 +1,5 @@
|
||||
import os
|
||||
from traceback import print_exc
|
||||
from kivy.app import App
|
||||
from appPublic.jsonConfig import getConfig
|
||||
from kivy.uix.popup import Popup
|
||||
@ -11,6 +12,23 @@ from appPublic.dictObject import DictObject
|
||||
|
||||
from .kivysize import KivySizes
|
||||
|
||||
class NeedLogin(Exception):
|
||||
pass
|
||||
|
||||
class InsufficientPrivilege(Exception):
|
||||
pass
|
||||
|
||||
class HTTPError(Exception):
|
||||
def __init__(self,resp_code):
|
||||
self.resp_code = resp_code
|
||||
Exception.__init__(self)
|
||||
|
||||
def __expr__(self):
|
||||
return f'Exception:return code={self.resp_code}'
|
||||
|
||||
def __str__(self):
|
||||
return f'Exception:return code={self.resp_code}'
|
||||
|
||||
alert_widget= None
|
||||
|
||||
def blockImage(name):
|
||||
@ -81,6 +99,9 @@ def alert(text,title='alert'):
|
||||
x = x + ':hh'
|
||||
alert_widget.title = str(title) + x
|
||||
alert_widget.open()
|
||||
print('************')
|
||||
print_exc()
|
||||
print('************')
|
||||
|
||||
def StrConvert(s):
|
||||
if not s.startswith('py::'):
|
||||
|
@ -47,21 +47,31 @@ class StrInput(TextInput):
|
||||
kv = {}
|
||||
a = {
|
||||
"allow_copy":True,
|
||||
"font_size":1,
|
||||
"password":False,
|
||||
"multiline":False,
|
||||
"halign":"left",
|
||||
"hint_text":"",
|
||||
"size_hint_y":None,
|
||||
"width":20,
|
||||
"height":2.5
|
||||
}
|
||||
if kv.get('tip'):
|
||||
a['hint_text'] = kv['tip']
|
||||
a.update(kv)
|
||||
a['width'] = CSize(kv.get('width',20))
|
||||
a['height'] = CSize(kv.get('height',2.5))
|
||||
# a.update(kv)
|
||||
w = kv.get('width',20)
|
||||
h = kv.get('height',2.5)
|
||||
if w <= 1:
|
||||
a['size_hint_x'] = w
|
||||
else:
|
||||
a['size_hint_x'] = None
|
||||
a['width'] = CSize(w)
|
||||
if h <= 1:
|
||||
a['size_hint_y'] = h
|
||||
else:
|
||||
a['size_hint_y'] = None
|
||||
a['height'] = CSize(h)
|
||||
a['font_size'] = CSize(kv.get('font_size',1))
|
||||
a['password'] = kv.get('password',False)
|
||||
a['multiline'] = kv.get('multiline',False)
|
||||
|
||||
Logger.info('TextInput:a=%s,h=%d,w=%d,CSize(1)=%d',a,h,w,CSize(1))
|
||||
super(StrInput,self).__init__(**a)
|
||||
self.old_value = None
|
||||
self.register_event_type('on_changed')
|
||||
@ -149,13 +159,16 @@ class MyDropDown(DropDown):
|
||||
def __init__(self,**kw):
|
||||
super(MyDropDown,self).__init__()
|
||||
self.options = kw
|
||||
self.textField = kw.get('textField',None)
|
||||
self.valueField = kw.get('valueField',None)
|
||||
if kw.get('url') is not None:
|
||||
self.url = kw.get('url')
|
||||
self.textField = kw.get('textField','text')
|
||||
self.valueField = kw.get('valueField','value')
|
||||
self.loadSelectItems()
|
||||
|
||||
def loadSelectItems(self):
|
||||
if self.options.get('url') is not None:
|
||||
self.url = self.options.get('url')
|
||||
self.setDataByUrl(self.url)
|
||||
else:
|
||||
self.si_data = kw.get('data')
|
||||
self.si_data = self.options.get('data')
|
||||
self.setData(self.si_data)
|
||||
self.bind(on_select=lambda instance, x: self.selectfunc(x))
|
||||
|
||||
@ -179,12 +192,23 @@ class MyDropDown(DropDown):
|
||||
def setData(self,data):
|
||||
self.si_data = data
|
||||
self.clear_widgets()
|
||||
w = self.options.get('width',10)
|
||||
h = self.options.get('height',2.5)
|
||||
a = {}
|
||||
if w <= 1:
|
||||
a['size_hint_x'] = w
|
||||
else:
|
||||
a['size_hint_x'] = None
|
||||
a['width'] = CSize(w)
|
||||
if h <= 1:
|
||||
a['size_hint_y'] = h
|
||||
else:
|
||||
a['size_hint_y'] = None
|
||||
a['height'] = CSize(h)
|
||||
a['font_size'] = CSize(self.options.get('font_size',1))
|
||||
for d in data:
|
||||
dd = (d[self.valueField],d[self.textField])
|
||||
b = Button(text=d[self.textField],font_size=CSize(1),
|
||||
size_hint=(None,None),
|
||||
width=CSize(10),
|
||||
height=CSize(2.5))
|
||||
b = Button(text=d[self.textField],**a)
|
||||
setattr(b,'kw_data',dd)
|
||||
b.bind(on_release=lambda btn: self.select(btn.kw_data))
|
||||
self.add_widget(b)
|
||||
@ -205,10 +229,22 @@ class MyDropDown(DropDown):
|
||||
|
||||
class SelectInput(BoxLayout):
|
||||
def __init__(self,**kw):
|
||||
a={}
|
||||
w = kw.get('width',10)
|
||||
h = kw.get('height',2.5)
|
||||
if w <= 1:
|
||||
a['size_hint_x'] = w
|
||||
else:
|
||||
a['size_hint_x'] = None
|
||||
a['width'] = CSize(w)
|
||||
if h <= 1:
|
||||
a['size_hint_y'] = h
|
||||
else:
|
||||
a['size_hint_y'] = None
|
||||
a['height'] = h
|
||||
|
||||
super(SelectInput,self).__init__(orientation='horizontal',\
|
||||
size_hint=(None,None),
|
||||
width=CSize(kw.get('width',10)),
|
||||
height=CSize(kw.get('height',2.5)))
|
||||
**a)
|
||||
self.tinp = StrInput(size_hint_y=None,height=kw.get('height',2.5))
|
||||
self.tinp.readonly = True
|
||||
newkw = {}
|
||||
|
Loading…
Reference in New Issue
Block a user