diff --git a/kivyblocks/blocks.py b/kivyblocks/blocks.py index cd9f359..bd11668 100755 --- a/kivyblocks/blocks.py +++ b/kivyblocks/blocks.py @@ -425,9 +425,10 @@ class Blocks(EventDispatcher): if d: params.update(d) try: - target.dispatch(event, **params) + target.dispatch(event, params) except Exception as e: Logger.info(f'Block: eventAction():dispatch {event} error') + print_exc() return def blocksAction(self,widget,desc, *args): diff --git a/kivyblocks/blocksapp.py b/kivyblocks/blocksapp.py index e1a0c9c..494f323 100644 --- a/kivyblocks/blocksapp.py +++ b/kivyblocks/blocksapp.py @@ -96,7 +96,7 @@ class BlocksApp(App): x = blocks.widgetBuild(config.root) if x is None: alert('buildError,Exit', title='Error') - self.on_close() + return Label(text='error') return x def get_user_data_path(self): diff --git a/kivyblocks/boxViewer.py b/kivyblocks/boxViewer.py index 9760b6f..0126850 100644 --- a/kivyblocks/boxViewer.py +++ b/kivyblocks/boxViewer.py @@ -110,6 +110,12 @@ class BoxViewer(WidgetReady, BoxLayout): x = self.dataloader.getLocater() self.locater(x) + def loadData(self, **kw): + self.params = kw + self.deleteAllWidgets(None) + self.dataloader.loadPage(1) + self.initflag = True + def deleteWidgets(self,o,data): for w in data: self.viewContainer.remove_widget(w) diff --git a/kivyblocks/dataloader.py b/kivyblocks/dataloader.py index 0d7aa13..49a3f82 100644 --- a/kivyblocks/dataloader.py +++ b/kivyblocks/dataloader.py @@ -33,18 +33,29 @@ class DataGraber(EventDispatcher): self.register_event_type('on_error') def load(self, *args, **kw): - dataurl = self.options.get('dataurl') - if dataurl: - return self.loadUrlData(*args, **kw) + ret = None + while True: + try: + dataurl = self.options.get('dataurl') + if dataurl: + ret = self.loadUrlData(*args, **kw) + break - rfname = self.options.get('datarfname') - if rfname: - return self.loadRFData(*args, **kw) - - target = self.options.get('datatarget') - if target: - return self.loadTargetData(*args, **kw) - return None + rfname = self.options.get('datarfname') + if rfname: + ret = self.loadRFData(*args, **kw) + break + target = self.options.get('datatarget') + ret = self.loadTargetData(*args, **kw) + break + except Exception as e: + self.dispatch('on_error', e) + return + if ret: + self.dispatch('on_success',ret) + else: + e = Exception('Not method to do load') + self.dispatch('on_error', e) def loadUrlData(self, *args, **kw): dataurl = self.options.get('dataurl') @@ -52,7 +63,7 @@ class DataGraber(EventDispatcher): params = self.options.get('params',{}).copy() params.update(kw) method = self.options.get('method','GET') - d = hc.get(dataurl, params=params,method=method) + d = hc(dataurl, params=params,method=method) return d def loadRFData(self, *args, **kw): diff --git a/kivyblocks/dg.py b/kivyblocks/dg.py index 5ee5297..d4da7a4 100644 --- a/kivyblocks/dg.py +++ b/kivyblocks/dg.py @@ -164,6 +164,8 @@ class Header(WidgetReady, BGColorBehavior, ScrollWidget): BGColorBehavior.__init__(self,color_level=color_level) self.init(1) self.bind(on_scroll_stop=self.part.datagrid.on_scrollstop) + if self.part.freeze_flag: + self.bar_width = 0 def init(self,t): rd = [ f.copy() for f in self.part.rowdesc ] @@ -180,6 +182,8 @@ class Body(ScrollWidget): ScrollWidget.__init__(self,**kw) self.idRow = {} self.bind(on_scroll_stop=self.part.datagrid.on_scrollstop) + if self.part.freeze_flag: + self.bar_width = 0 def addRow(self,id, data,index=0): rd = [ f.copy() for f in self.part.rowdesc ] diff --git a/kivyblocks/form.py b/kivyblocks/form.py index 158718a..35d092b 100644 --- a/kivyblocks/form.py +++ b/kivyblocks/form.py @@ -126,7 +126,7 @@ class InputBox(BoxLayout): self.options['height'] = 4 height = self.options.get('height',4) - self.labelwidth = self.form.options['labelwidth'] + self.labelwidth = self.form.labelwidth kwargs = { "orientation":orientation, } @@ -261,74 +261,146 @@ def defaultToolbar(): } class Form(BGColorBehavior, WidgetReady, BoxLayout): - def __init__(self, **options): - self.options = options - BoxLayout.__init__(self, orientation='vertical') - self.color_level = self.options.get('color_level', 0) - BGColorBehavior.__init__(self, - color_level=self.options.get('color_level',-1), - radius=self.options.get('radius',[])) - WidgetReady.__init__(self) + def __init__(self, + color_level=1, + radius=[], + cols=2, + inputwidth=0, + inputheight=3, + labelwidth=0.3, + notoolbar=False, + toolbar_at='top', #'top', 'bottom', 'left', 'right' + dataloader={}, + fields=[], + submit={}, + clear={}, + toolbar={}, + **options): + self.inputwidth = 1 + self.inputheight = inputheight + self.labelwidth= labelwidth + self.fields = fields + self.notoolbar = notoolbar + self.submit = submit + self.clear = clear + self.toolbar = toolbar + self.toolbar_at=toolbar_at + self.dataloader = dataloader self.readiedInput = 0 - self.cols = self.options_cols = self.options.get('cols',1) + if self.toolbar_at in ['top','bottom']: + options['orientation'] = 'vertical' + else: + options['orientation'] = 'horizontal' + BoxLayout.__init__(self, **options) + self.color_level = color_level + BGColorBehavior.__init__(self, + color_level=color_level, + radius=radius) + WidgetReady.__init__(self) + self.cols = self.options_cols = cols if isHandHold() and Window.width < Window.height: self.cols = 1 - self.inputwidth = Window.width / self.cols - self.inputheight = self.options.get('inputheight',3) + self.options = options self.init() self.register_event_type('on_submit') def on_size(self, *args): - pass + if not hasattr(self,'fsc'): + return + + if not self.notoolbar: + if self.toolbar_at in ['top', 'bottom']: + self.fsc.height = self.height - self.toolbar.height + else: + self.fsc.width = self.width - self.toolbar.width + else: + if self.toolbar_at in ['top', 'bottom']: + self.fsc.height = self.height + else: + self.fsc.width = self.width + self.fsc.org_box_width = self.width / self.options_cols + if self.notoolbar: + return + if self.toolbar_at in [ 'top', 'bottom' ]: + Logger.info('Form: height:tb:%d,ti:%d,fsc:%d, fm:%d', + self.toolbar.height, + self.toolbar.toggle_items.height, + self.fsc.height, self.height + ) + else: + Logger.info('Form: width:tb:%d,ti:%d,fsc:%d, fm:%d', + self.toolbar.width, + self.toolbar.toggle_items.width, + self.fsc.width, self.width + ) def init(self): - desc = defaultToolbar() - desc1 = self.options.get('toolbar') - if desc1: - tools = desc['tools'] + desc1['tools'] - desc1['tools'] = tools - desc = desc1 - if self.options.get('submit'): - kw = self.options.get('submit').copy() - if kw.get('name'): - del kw['name'] - for t in desc['tools']: - if t['name'] == '__submit': - t.update(kw) - if self.options.get('clear'): - kw = self.options.get('clear').copy() - if kw.get('name'): - del kw['name'] - for t in desc['tools']: - if t['name'] == '__clear': - t.update(kw) - - self.toolbar = Toolbar(**desc) + if not self.notoolbar: + desc = defaultToolbar() + desc1 = self.toolbar + if desc1: + tools = desc['tools'] + desc1['tools'] + desc1['tools'] = tools + desc = desc1 + if self.submit: + kw = self.submit.copy() + if kw.get('name'): + del kw['name'] + for t in desc['tools']: + if t['name'] == '__submit': + t.update(kw) + if self.clear: + kw = self.clear.copy() + if kw.get('name'): + del kw['name'] + for t in desc['tools']: + if t['name'] == '__clear': + t.update(kw) + + if self.toolbar_at in ['top', 'bottom']: + desc['orientation'] = 'horizontal' + desc['size_hint_y'] = None + desc['height'] = CSize(desc['img_size'] + desc['text_size']) + else: + desc['orientation'] = 'vertical' + desc['size_hint_x'] = None + desc['width'] = CSize(desc['img_size'] + desc['text_size']) + + self.toolbar = Toolbar(**desc) self.fsc = VResponsiveLayout( self.inputwidth, - self.cols + self.cols, + size_hint=(1,1) ) - self.add_widget(self.toolbar) + + if self.toolbar_at in ['top', 'left'] and not self.notoolbar: + self.add_widget(self.toolbar) self.add_widget(self.fsc) + if self.toolbar_at in ['bottom', 'right'] and not self.notoolbar: + self.add_widget(self.toolbar) + self.fieldWidgets=[] - for f in self.options['fields']: + for f in self.fields: w = InputBox(self, **f) self.fsc.add_widget(w) self.fieldWidgets.append(w) w.bind(on_ready=self.makeInputLink) wid = Factory.Blocks.getWidgetById('__submit',from_widget=self) - wid.bind(on_press=self.on_submit_button) + if wid: + wid.bind(on_press=self.on_submit_button) wid = Factory.Blocks.getWidgetById('__clear',from_widget=self) - wid.bind(on_press=self.on_clear_button) - if self.options.get('dataloader'): - self.dataloader = DataGraber(**self.options['dataloader']) - d = self.dataloader.load() + if wid: + wid.bind(on_press=self.on_clear_button) + if self.dataloader: + self.loader = DataGraber(**self.dataloader) + d = self.loader.load() if d: self.setValue(d) + self.on_size() def makeInputLink(self,o,v=None): self.readiedInput += 1 - if self.readiedInput >= len(self.options['fields']): + if self.readiedInput >= len(self.fields): p = self.fieldWidgets[0] for w in self.fieldWidgets[1:]: p.input_widget.focus_next = w.input_widget diff --git a/kivyblocks/newvideo.py b/kivyblocks/newvideo.py index b45663f..3b67f2c 100644 --- a/kivyblocks/newvideo.py +++ b/kivyblocks/newvideo.py @@ -23,20 +23,37 @@ class NewVideo(BGColorBehavior, Video): Window.allow_screensaver = False set_log_callback(self.ffplayerLog) self.register_event_type('on_open_failed') + self.register_event_type('on_load_success') + self.bind(source=self.record_start_time) + self.load_status = None + + def on_load_success(self, *args): + pass + + def record_start_time(self, *args): + self.start_time = time.time() + self.load_status = 'start' def on_open_failed(self, source, x=None): - print('source=',source, 'open failed') + Logger.error(f'NewVideo: source={self.source} open failed') + self.load_status = 'failed' def ffplayerLog(self, msg, level): + """ if 'Connection to tcp' in msg and 'failed' in msg: self.dispatch('on_open_failed', self.source) if 'Invalid data found when processing input' in msg: self.dispatch('on_open_failed', self.source) if 'End of file' in msg: self.dispatch('on_open_failed', self.source) + if 'I/O error' in msg: + self.dispatch('on_open_failed', self.source) if 'Server returned 404 Not Found' in msg: self.dispatch('on_open_failed', self.source) - if 'Server returned 403 Forbidden' in msg: + """ + if 'Server returned 4' in msg: + self.dispatch('on_open_failed', self.source) + if 'Server returned 5' in msg: self.dispatch('on_open_failed', self.source) msg = msg.strip() @@ -52,6 +69,15 @@ class NewVideo(BGColorBehavior, Video): def on_state(self,*args): super().on_state(*args) if self.state == 'play': + if self.load_status == 'start': + self.load_status = 'success' + t = time.time() + self.dispatch('on_load_success', + { + 'source':self.source, + 'time':int((t - self.start_time)*100) + }) + Window.allow_screensaver = False else: Window.allow_screensaver = True diff --git a/kivyblocks/toolbar.py b/kivyblocks/toolbar.py index 73d9d45..530e053 100644 --- a/kivyblocks/toolbar.py +++ b/kivyblocks/toolbar.py @@ -95,7 +95,7 @@ class Toolbar(BoxLayout): items_desc=subs_desc, orientation=opts.get('orientation','horizontal') ) - for ti in self.toggle_items.children: + for ti in self.toggle_items.item_widgets: ti.widget_id = ti.user_data self.toggle_items.bind(on_press=self.tool_press) self.add_widget(self.toggle_items) @@ -169,7 +169,7 @@ class ToolPage(BGColorBehavior, BoxLayout): 'toggleitems=',self.toolbar.toggle_items.width, \ self.toolbar.toggle_items.height) toggle_items = self.toolbar.toggle_items - for c in toggle_items.children: + for c in toggle_items.item_widgets: cvalue = c.getValue() if cvalue == self.show_name: c.dispatch('on_press') @@ -214,7 +214,7 @@ class ToolPage(BGColorBehavior, BoxLayout): self.add_widget(self.content) self.add_widget(self.toolbar) toggle_items = self.toolbar.toggle_items - for t in toggle_items.children: + for t in toggle_items.item_widgets: t.bind(on_press=self.on_press_handle) def get_tool_by_name(self,name): @@ -241,8 +241,9 @@ class ToolPage(BGColorBehavior, BoxLayout): if w is None or t.fresh: if t.url: w = self.build_widget(t.url) - self.content_widgets[name] = w - self.content.add_widget(w) + if w: + self.content_widgets[name] = w + self.content.add_widget(w) return if t.rfname: rf = RegisterFunction() diff --git a/kivyblocks/widgetExt/scrollwidget.py b/kivyblocks/widgetExt/scrollwidget.py index 0015550..61b0b7d 100755 --- a/kivyblocks/widgetExt/scrollwidget.py +++ b/kivyblocks/widgetExt/scrollwidget.py @@ -1,4 +1,5 @@ from kivy.uix.scrollview import ScrollView +from kivy.effects.scroll import ScrollEffect from kivy.uix.gridlayout import GridLayout from kivy.uix.boxlayout import BoxLayout from kivy.graphics import Color, Ellipse,Rectangle @@ -6,6 +7,7 @@ from kivy.graphics import Color, Ellipse,Rectangle class ScrollWidget(ScrollView): def __init__(self,**kw): super(ScrollWidget,self).__init__(**kw) + self.effect_cls = ScrollEffect self.sized_widgets = [] self._inner = BoxLayout(orientation='vertical',padding=5, spacing=8,size_hint=(None,None))