diff --git a/kivyblocks/baseWidget.py b/kivyblocks/baseWidget.py index 0bdbba5..c74e66e 100755 --- a/kivyblocks/baseWidget.py +++ b/kivyblocks/baseWidget.py @@ -1,6 +1,7 @@ import sys from traceback import print_exc +from kivy.properties import ObjectProperty, StringProperty from kivy.app import App from kivy.utils import platform from kivy.uix.button import Button, ButtonBehavior @@ -53,6 +54,7 @@ from kivycalendar import DatePicker from kivy.factory import Factory from appPublic.dictObject import DictObject +from appPublic.jsonConfig import getConfig from appPublic.folderUtils import listFile from .widgetExt.scrollwidget import ScrollWidget @@ -68,6 +70,7 @@ from .login import LoginForm from .tab import TabsPanel from .qrdata import QRCodeWidget from .threadcall import HttpClient +from .i18n import I18n if platform == 'android': from .widgetExt.phonebutton import PhoneButton @@ -79,9 +82,33 @@ class WrapText(Label): self.bind(width=lambda *x: self.setter('text_size')(self, (self.width, None)), texture_size=lambda *x: self.setter('height')(self, self.texture_size[1])) - class Text(Label): - pass + lang=StringProperty('') + otext = StringProperty('') + def __init__(self,i18n=False, textype='text', **kw): + self._i18n = i18n + kwargs = kw.copy() + config = getConfig() + if config.texttypes: + attrs = config.texttypes.get('texttype',{}) + kwargs.update(attrs) + super().__init__(**kwargs) + if self._i18n: + self.i18n = I18n() + self.i18n.addI18nWidget(self) + self.otext = kw.get('text','') + + def on_otext(self,o,v=None): + if self._i18n: + self.text = self.i18n(v) + else: + self.text = v + + def changeLang(self,lang): + self.lang = lang + + def on_lang(self,o,lang): + self.text = self.i18n(self.otext) class PressableImage(ButtonBehavior,AsyncImage): def on_press(self): diff --git a/kivyblocks/blocks.py b/kivyblocks/blocks.py index 45cc64c..025c31c 100755 --- a/kivyblocks/blocks.py +++ b/kivyblocks/blocks.py @@ -32,12 +32,11 @@ from .form import InputBox, Form, StrSearchForm from .boxViewer import BoxViewer from .tree import Tree, TextTree from .newvideo import Video -# from .qrcodereader import QRCodeReader from .ready import WidgetReady from .bgcolorbehavior import BGColorBehavior from .orientationlayout import OrientationLayout from .threadcall import HttpClient -from .twosides import TwoSides +from .register import * def showError(e): print('error',e) @@ -278,11 +277,11 @@ class Blocks(EventDispatcher): return self.dictValueExpr(obj,localnamespace) return obj - def __build(self,desc:dict): - # print('__build(),desc=',desc) + def w_build(self,desc:dict): + # print('w_build(),desc=',desc) widgetClass = desc.get('widgettype',None) if not widgetClass: - print("__build(), desc invalid", desc) + print("w_build(), desc invalid", desc) raise Exception(desc) widgetClass = desc['widgettype'] @@ -387,11 +386,14 @@ class Blocks(EventDispatcher): b.widgetBuild(opts) def urlwidgetAction(self,widget,desc, *args): + print('urlwidgetAction():args=',args) target = Blocks.getWidgetById(desc.get('target','self'),widget) add_mode = desc.get('mode','replace') opts = desc.get('options').copy() d = self.getActionData(widget,desc) p = opts.get('params',{}).copy() + if len(args) >= 1 and isinstance(args[0],dict): + p.update(p) p.update(d) opts['params'] = p d = { @@ -416,8 +418,8 @@ class Blocks(EventDispatcher): data = {} if desc.get('datawidget',False): dwidget = Blocks.getWidgetById(desc.get('datawidget','self'),widget) - if dwidget and hasattr(dwidget,'getData'): - data = dwidget.getData() + if dwidget and hasattr(dwidget,'getValue'): + data = dwidget.getValue() if desc.get('keymapping'): data = keyMapping(data, desc.get('keymapping')) return data @@ -476,6 +478,7 @@ class Blocks(EventDispatcher): } """ name = desc['widgettype'] + print('desc=',desc,'type=',type(desc)) def doit(desc): if not isinstance(desc,dict): @@ -483,7 +486,7 @@ class Blocks(EventDispatcher): raise Exception('desc must be a dict') desc = self.valueExpr(desc) - widget = self.__build(desc) + widget = self.w_build(desc) self.dispatch('on_built',widget) if hasattr(widget,'ready'): widget.ready() diff --git a/kivyblocks/boxViewer.py b/kivyblocks/boxViewer.py index e9a24b4..64b68f9 100644 --- a/kivyblocks/boxViewer.py +++ b/kivyblocks/boxViewer.py @@ -17,6 +17,7 @@ BoxViewer options: """ from traceback import print_exc from functools import partial +from appPublic.dictExt import dictExtend from kivy.app import App from kivy.factory import Factory from kivy.utils import platform @@ -27,24 +28,32 @@ from .paging import Paging, RelatedLoader from .utils import CSize from .ready import WidgetReady + class BoxViewer(WidgetReady, BoxLayout): def __init__(self, **options): + self.options = options + self.subwidgets = [] self.toolbar = None self.parenturl = None self.dataloader = None self.initflag = False - self.selected_box = None remind = ['toolbar', 'dataloader', 'orientation', 'viewer', 'boxwidth', - 'boxheight'] + 'boxheight', + 'color_level', + 'radius', + 'viewer_url' + 'viewer' + ] kwargs = {k:v for k,v in options.items() if k not in remind } BoxLayout.__init__(self, orientation='vertical', **kwargs) WidgetReady.__init__(self) self.selected_data = None - self.options = options + self.color_level = self.options.get('color_level',-1) + self.radius = self.options.get('radius',[]) self.box_width = CSize(options['boxwidth']) self.box_height = CSize(options['boxheight']) self.viewContainer = VResponsiveLayout(cols=2,box_width=self.box_width) @@ -81,6 +90,7 @@ class BoxViewer(WidgetReady, BoxLayout): def deleteAllWidgets(self,o): self.viewContainer.clear_widgets() + self.subwidgets = [] def addPageWidgets(self,o,data): widgets = [] @@ -94,6 +104,8 @@ class BoxViewer(WidgetReady, BoxLayout): for r in recs: self.showObject(widgets, r, index=idx) + self.subwidgets += widgets + self.dataloader.bufferObjects(page, widgets) x = self.dataloader.getLocater() self.locater(x) @@ -101,8 +113,9 @@ class BoxViewer(WidgetReady, BoxLayout): def deleteWidgets(self,o,data): for w in data: self.viewContainer.remove_widget(w) + self.subwidget = [i for i in self.subwidgets if i in data] - def on_selected(self, o, v=None): + def on_selected(self, data=None): pass def locater(self, pos): @@ -122,25 +135,46 @@ class BoxViewer(WidgetReady, BoxLayout): self.initflag = True def showObject(self, holders, rec,index=0): - def doit(self,holders,idx,o,w): - w.bind(on_press=self.select_record) - w.boxviewer = self - 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']['size_hint'] = None,None - options['options']['width'] = self.box_width - options['options']['height'] = self.box_height + opts = { + "size_hint":[None,None], + "height":self.box_height, + "width":self.box_width, + "color_level":self.color_level, + "radius":self.radius + } + desc = { + "widgettype":"PressableBox", + "options":opts + } blocks = Factory.Blocks() - blocks.bind(on_built=partial(doit,self,holders,index)) - blocks.bind(on_failed=doerr) - blocks.widgetBuild(options) + box = blocks.w_build(desc) + box.setValue(rec) + box.bind(on_press=self.select_record) + self.viewContainer.add_widget(box,index=index) + self.subwidgets.append(box) + holders.append(box) + desc = {} + if self.options.get('viewer_url'): + desc = { + "widgettype":"urlwidget", + "optons":{ + "params":rec, + "method":"GET", + "url":self.options.get('viewer_url') + } + } + else: + desc = self.options.get('viewer').copy() + if desc['widgettype'] == 'urlwidget': + desc = dictExtend(desc,{'options':{'params':rec}}) + else: + desc = dictExtend(desc,{'options':{'record':rec}}) + def add2box(p,o,w): + p.add_widget(w) + + blocks = Factory.Blocks() + blocks.bind(on_built=partial(add2box,box)) + blocks.widgetBuild(desc) def on_scroll_stop(self,o,v=None): if o.scroll_y <= 0.001: @@ -149,22 +183,19 @@ class BoxViewer(WidgetReady, BoxLayout): self.dataloader.loadPreviousPage() def select_record(self,o,v=None): - if self.selected_box: - self.selected_box.unselected() + print('BoxViewer(),on_selected() called\n', + 'normal_bgcolor=',o.normal_bgcolor,'\n', + 'selected_bgcolor=',o.selected_bgcolor,'\n', + 'bg_color=',o.bgcolor,'\n', + 'color_level=',self.color_level) + + for w in self.subwidgets: + w.unselected() o.selected() - self.selected_box = o + self.selected_data = o.getValue() + self.dispatch('on_selected',self.selected_data) - self.selected_data = o.getRecord() - d = { - "target":self.selected_box, - "page_rows":1, - "page":self.selected_data['__posInSet__'], - "dataurl":self.options['dataloader']['options']['dataurl'], - "params":self.params - } - self.dispatch('on_selected',d) - - def getData(self): + def getValue(self): return self.selected_data d = { "caller":self, diff --git a/kivyblocks/dg.py b/kivyblocks/dg.py index 5ac2282..28993f7 100644 --- a/kivyblocks/dg.py +++ b/kivyblocks/dg.py @@ -21,7 +21,6 @@ from .widgetExt import ScrollWidget from .paging import Paging, RelatedLoader from .ready import WidgetReady from .toolbar import Toolbar -from .i18n import I18nText from .bgcolorbehavior import BGColorBehavior class BLabel(ButtonBehavior, Text): @@ -59,7 +58,7 @@ class Cell(BoxLayout): self.add_widget(w) return if desc['header']: - bl = I18nText(otext=str(desc['value']), + bl = Text(i18n=True, text=str(desc['value']), font_size=CSize(1), halign='left' ) @@ -230,6 +229,7 @@ class DataGrid(WidgetReady, BGColorBehavior, BoxLayout): kw.orientation = 'vertical' self.color_level = color_level self.radius = radius + self.select_rowid = None WidgetReady.__init__(self) BoxLayout.__init__(self,**kw) BGColorBehavior.__init__(self,color_level=color_level, @@ -299,8 +299,8 @@ class DataGrid(WidgetReady, BGColorBehavior, BoxLayout): if o.scroll_y >= 0.999: self.dataloader.loadPreviousPage() - def getData(self): - if not self.row_selected: + def getValue(self): + if not self.select_rowid: return None return self._getRowData(self.select_rowid) @@ -309,7 +309,7 @@ class DataGrid(WidgetReady, BGColorBehavior, BoxLayout): if self.freeze_part: d.update(self.freeze_part.body.getRowData(rowid)) d.update(self.normal_part.body.getRowData(rowid)) - print('getData() return=',d) + print('getValue() return=',d) return DictObject(**d) def bodyOnSize(self,o,s): @@ -408,4 +408,3 @@ class DataGrid(WidgetReady, BGColorBehavior, BoxLayout): fs.append(f) return fs -Factory.register('DataGrid',DataGrid) diff --git a/kivyblocks/filebrowser.py b/kivyblocks/filebrowser.py index 6a426d6..0f30817 100644 --- a/kivyblocks/filebrowser.py +++ b/kivyblocks/filebrowser.py @@ -113,8 +113,6 @@ class FileLoaderBrowser(Popup): self.control_box.add_widget(self.btn_load) self.control_box.add_widget(self.btn_icon_view) -Factory.register('FileLoaderBrowser',FileLoaderBrowser) - if __name__ == '__main__': from kivy.app import App class Test(App): diff --git a/kivyblocks/form.py b/kivyblocks/form.py index a36b886..c240a83 100644 --- a/kivyblocks/form.py +++ b/kivyblocks/form.py @@ -10,7 +10,7 @@ from .widgetExt.inputext import FloatInput,IntegerInput, \ StrInput,SelectInput, BoolInput, AmountInput, Password from .baseWidget import * from .utils import * -from .i18n import I18nText, I18n +from .i18n import I18n from .toolbar import Toolbar from .color_definitions import getColors from .bgcolorbehavior import BGColorBehavior @@ -161,14 +161,15 @@ class InputBox(BoxLayout): self.add_widget(bl) label = self.options.get('label',self.options.get('name')) kwargs = { - "otext":label, + "i18n":True, + "text":label, "font_size":CSize(1), "size_hint_x":None, "width":CSize(len(label)), "size_hint_y":None, "height":CSize(3) } - self.labeltext = I18nText(**kwargs) + self.labeltext = Text(**kwargs) bl.add_widget(self.labeltext) Logger.info('kivyblock:label.widht=%f,label.height=%f', self.labeltext.width,self.labeltext.height) @@ -300,7 +301,7 @@ class Form(BGColorBehavior, BoxLayout): w.input_widget.focus_previous = p.input_widget p = w - def getData(self): + def getValue(self): d = {} for f in self.fieldWidgets: v = f.getValue() @@ -325,7 +326,7 @@ class Form(BGColorBehavior, BoxLayout): if not self.checkData(): Logger.info('kivyblocks: CheckData False') return - d = self.getData() + d = self.getValue() Logger.info('kivyblocks: fire on_submit') self.dispatch('on_submit',d) @@ -348,7 +349,7 @@ class StrSearchForm(BoxLayout): self.register_event_type('on_submit') self.input_widget.bind(on_text_validate=self.submit_input) - def getData(self): + def getValue(self): d = { self.name:self.input_widget.text } diff --git a/kivyblocks/i18n.py b/kivyblocks/i18n.py index 0a4314e..6339c55 100644 --- a/kivyblocks/i18n.py +++ b/kivyblocks/i18n.py @@ -1,9 +1,9 @@ import locale from kivy.app import App from kivy.properties import StringProperty +from kivy.uix.label import Label from appPublic.Singleton import SingletonDecorator from appPublic.jsonConfig import getConfig -from .baseWidget import Text from .threadcall import HttpClient @SingletonDecorator @@ -42,26 +42,3 @@ class I18n: for w in self.i18nWidgets: w.changeLang(lang) -class I18nText(Text): - lang=StringProperty('') - otext=StringProperty('') - - def __init__(self,**kw): - self.options = kw.copy() - otext = kw.get('otext',kw.get('text')) - if kw.get('otext'): - del kw['otext'] - super().__init__(**kw) - self.i18n = I18n() - self.i18n.addI18nWidget(self) - self.otext = otext - - def on_otext(self,o,v=None): - self.text = self.i18n(self.otext) - - def changeLang(self,lang): - self.lang = lang - - def on_lang(self,o,lang): - self.text = self.i18n(self.otext) - diff --git a/kivyblocks/kivycamera.py b/kivyblocks/kivycamera.py index 07dfcbe..bb0876e 100644 --- a/kivyblocks/kivycamera.py +++ b/kivyblocks/kivycamera.py @@ -86,4 +86,3 @@ class KivyCamera(Image): self.update_task = None # self.cupture.close() -Factory.register('KivyCamera',KivyCamera) diff --git a/kivyblocks/qrdata.py b/kivyblocks/qrdata.py index a0c987e..c63df84 100644 --- a/kivyblocks/qrdata.py +++ b/kivyblocks/qrdata.py @@ -132,8 +132,6 @@ class QRCodeWidget(FloatLayout): img.texture = texture img.canvas.ask_update() -Factory.register('QRCodeWidget',QRCodeWidget) - if __name__ == '__main__': from kivy.app import runTouchApp import sys diff --git a/kivyblocks/register.py b/kivyblocks/register.py index a61d956..fe5adb6 100644 --- a/kivyblocks/register.py +++ b/kivyblocks/register.py @@ -9,8 +9,20 @@ from .form import Form, StrSearchForm from .boxViewer import BoxViewer from .pagescontainer import PageContainer from .hostimage import HostImage +from .toggleitems import PressableBox, ToggleItems +from .twosides import TwoSides +from .tab import TabsPanel +from .qrdata import QRCodeWidget +from .kivycamera import KivyCamera +from .filebrowser import FileLoaderBrowser r = Factory.register +r('DataGrid',DataGrid) +r('FileLoaderBrowser',FileLoaderBrowser) +r('KivyCamera',KivyCamera) +r('QRCodeWidget',QRCodeWidget) +r('TabsPanel',TabsPanel) +r('TwoSides',TwoSides) r('PageContainer', PageContainer) r('BoxViewer', BoxViewer) r('Form', Form) @@ -41,6 +53,8 @@ r('PopupMenu',PopupMenu) r('HostImage',HostImage) r('APlayer',APlayer) r('WrapText',WrapText) +r('PressableBox',PressableBox) +r('ToggleItems',ToggleItems) if platform == 'android': r('PhoneButton',PhoneButton) r('AWebView',AWebView) diff --git a/kivyblocks/tab.py b/kivyblocks/tab.py index e5e8614..ac4890e 100644 --- a/kivyblocks/tab.py +++ b/kivyblocks/tab.py @@ -57,8 +57,6 @@ class TabsPanel(BGColorBehavior, TabbedPanel): desc = d['content'] self.add_tab(name,text,desc) -Factory.register('TabsPanel',TabsPanel) - if __name__ == '__main__': from kivy.app import App pass diff --git a/kivyblocks/toggleitems.py b/kivyblocks/toggleitems.py index feabacd..baab162 100644 --- a/kivyblocks/toggleitems.py +++ b/kivyblocks/toggleitems.py @@ -28,10 +28,10 @@ class PressableBox(BGColorBehavior, TouchRippleButtonBehavior, BoxLayout): def on_press(self,o=None): self.selected() - def set_data(self,d): + def setValue(self,d): self.user_data = d - def get_data(self): + def getValue(self): return self.user_data class ToggleItems(BGColorBehavior, BoxLayout): @@ -73,7 +73,7 @@ class ToggleItems(BGColorBehavior, BoxLayout): c = PressableBox(**kw) d = desc.get('data') if d: - c.set_data(d) + c.setValue(d) self.item_widgets.append(c) self.add_widget(c) c.bind(on_press=self.select_item) @@ -98,20 +98,18 @@ class ToggleItems(BGColorBehavior, BoxLayout): def select_item(self,o=None): [i.unselected() for i in self.item_widgets if i != o] - self.dispatch('on_press',o.get_data()) + self.dispatch('on_press',o.getValue()) def getValue(self): for i in self.item_widgets: if i.is_selected(): - return i.get_data() + return i.getValue() return None def setValue(self,v): for i in self.item_widgets: - if i.get_data() == v: + if i.getValue() == v: i.selected() self.select_iten(i) return -Factory.register('PressableBox',PressableBox) -Factory.register('ToggleItems',ToggleItems) diff --git a/kivyblocks/toolbar.py b/kivyblocks/toolbar.py index 101a87d..1dee482 100644 --- a/kivyblocks/toolbar.py +++ b/kivyblocks/toolbar.py @@ -13,9 +13,9 @@ from appPublic.dictObject import DictObject from .widgetExt.scrollwidget import ScrollWidget from .utils import * from .ready import WidgetReady -from .i18n import I18nText from .color_definitions import getColors from .bgcolorbehavior import BGColorBehavior +from .baseWidget import Text """ toobar={ @@ -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 = Text(i18n=True, + text=label, font_size=int(tsize), text_size=(CSize(len(label)), tsize), height=tsize, diff --git a/kivyblocks/twosides.py b/kivyblocks/twosides.py index 5101601..14514b1 100644 --- a/kivyblocks/twosides.py +++ b/kivyblocks/twosides.py @@ -56,5 +56,3 @@ class TwoSides(WidgetReady, BoxLayout): self.clear_widgets() self.add_widget(self.portrait_widget) - -Factory.register('TwoSides',TwoSides)