diff --git a/kivyblocks/baseWidget.py b/kivyblocks/baseWidget.py index 07bc132..f2c4421 100755 --- a/kivyblocks/baseWidget.py +++ b/kivyblocks/baseWidget.py @@ -65,6 +65,7 @@ from .login import LoginForm if platform == 'android': from .widgetExt.phonebutton import PhoneButton from .widgetExt.androidwebview import AWebView + from .widgetExt.camera import AndroidCamera class Text(BGColorBehavior, Label): def __init__(self,bgcolor=[],fgcolor=[],color_level=-1,**kw): diff --git a/kivyblocks/bgcolorbehavior.py b/kivyblocks/bgcolorbehavior.py index 9c2df1e..55a18e3 100644 --- a/kivyblocks/bgcolorbehavior.py +++ b/kivyblocks/bgcolorbehavior.py @@ -78,10 +78,8 @@ class BGColorBehavior(object): 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() diff --git a/kivyblocks/boxViewer.py b/kivyblocks/boxViewer.py index 558bb07..eb6b855 100644 --- a/kivyblocks/boxViewer.py +++ b/kivyblocks/boxViewer.py @@ -119,9 +119,7 @@ class BoxViewer(BoxLayout): 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: diff --git a/kivyblocks/hostimage.py b/kivyblocks/hostimage.py index 3e1f99f..84732a6 100644 --- a/kivyblocks/hostimage.py +++ b/kivyblocks/hostimage.py @@ -14,7 +14,7 @@ class HostImage(Image): super().__init__(**kwargs) self.downloadImage(url) - def downloadImage(url): + def downloadImage(self,url): realurl = absurl(url,self.target.parenturl) loader = HTTPDataHandler(url,stream=True) loader.bind(on_success=self.createTmpfile) @@ -25,9 +25,10 @@ class HostImage(Image): self.source = blockImage('broken.png') def createTmpfile(self,o,resp): - fn = tempfile.NamedTemporaryFile(delete=True) + fn = tempfile.mkstemp()[1] + print('************fn=%s',fn) with open(fn, 'wb') as f: - for chunk in r.iter_content(chunk_size=8192): + for chunk in resp.iter_content(chunk_size=8192): if chunk: # filter out keep-alive new chunks f.write(chunk) # f.flush() diff --git a/kivyblocks/pagescontainer.py b/kivyblocks/pagescontainer.py index 56ca069..43de520 100644 --- a/kivyblocks/pagescontainer.py +++ b/kivyblocks/pagescontainer.py @@ -54,7 +54,8 @@ class PageContainer(FloatLayout): w = self.pageWidgets[-1] self.pageWidgets = self.pageWidgets[:-1] self.showLastPage() - w.__del__() + if hasattr(w,'__del__'): + w.__del__() def add_widget(self,widget): self.pageWidgets.append(widget) diff --git a/kivyblocks/qrcodereader.py b/kivyblocks/qrcodereader.py new file mode 100644 index 0000000..81d86ad --- /dev/null +++ b/kivyblocks/qrcodereader.py @@ -0,0 +1,63 @@ +import numpy as np +import cv2 +from kivy.app import App +from kivy.core.window import Window +from kivy.graphics.texture import Texture +from kivy.uix.image import Image +from kivy.clock import Clock + +class QRCodeReader(Image): + def __init__(self, **kwargs): + super().__init__(**kwargs) + self.register_event_type('on_data') + self.opened = False + self.task = None + + def open(self): + self.opened = True + self.cam = cv2.VideoCapture(0) + self.detector = cv2.QRCodeDetector() + self.task = Clock.schedule_interval(self.read,1.0/30.0) + Window.add_widget(self) + + def on_data(self,d): + print('QRCodeReader().on_data(),data=',d) + self.dismiss() + + def on_touch_down(self,touch): + if not self.colide_point(*touch.pos): + self.dismiss() + super().on_touch_down(touch) + + def dismiss(self): + if not self.opened: + return + self.opened = False + self.task.cancel() + self.task = None + self.cam.release() + cv2.destroyAllWindows() + Window.remove_widget(self) + + def showImage(self,img): + image = np.rot90(np.swapaxes(img,0,1)) + tex = Texture.create(size=(image.shape[1], image.shape[0]), + colorfmt='rgb') + tex.blit_buffer(image.tostring(),colorfmt='rgb', bufferfmt='ubyte') + self.texture = tex + + def read(self,p): + _, img = self.cam.read() + self.showImage(img) + data,bbox,_ = self.detector.detectAndDecode(img) + if data: + self.dispatch('on_data',data) + +if __name__ == '__main__': + class MyApp(App): + def build(self): + r = QRCodeReader() + return r + myapp = MyApp() + myapp.run() + diff --git a/kivyblocks/register.py b/kivyblocks/register.py index b47f90d..7631398 100644 --- a/kivyblocks/register.py +++ b/kivyblocks/register.py @@ -4,6 +4,7 @@ from .tree import Tree, TextTree, PopupMenu from .toolbar import ToolPage, Toolbar from .dg import DataGrid from .vplayer import VPlayer +from .aplayer import APlayer from .form import Form, StrSearchForm from .boxViewer import BoxViewer from .pagescontainer import PageContainer @@ -38,6 +39,8 @@ r('Tree',Tree) r('TextTree',TextTree) r('PopupMenu',PopupMenu) r('HostImage',HostImage) +r('APlayer',APlayer) if platform == 'android': r('PhoneButton',PhoneButton) r('AWebView',AWebView) + r('AndroidCamera',AndroidCamera) diff --git a/kivyblocks/swipebehavior.py b/kivyblocks/swipebehavior.py new file mode 100644 index 0000000..ef7c12e --- /dev/null +++ b/kivyblocks/swipebehavior.py @@ -0,0 +1,83 @@ +import time +from kivy.logger import Logger +from kivy.event import EventDispatcher + +class SwipeBehavior(EventDispatcher): + def __init__(self, **kwargs): + self.register_event_type('on_context_menu') + self.register_event_type('on_swipe_left') + self.register_event_type('on_swipe_right') + self.register_event_type('on_swipe_up') + self.register_event_type('on_swipe_down') + self.sb_start_point = None + self.sb_end_point = None + self.sb_start_time = None + self.sb_end_time = None + self.threshold=20 + self.threshold_time = 1.5 + + def on_context_menu(self): + Logger.info('SwipeBehavior:on_context_menu fired') + + def on_swipe_left(self): + Logger.info('SwipeBehavior:on_swipe_left fired') + pass + + def on_swipe_right(self): + Logger.info('SwipeBehavior:on_swipe_right fired') + pass + + def on_swipe_up(self): + Logger.info('SwipeBehavior:on_swipe_up fired') + pass + + def on_swipe_down(self): + Logger.info('SwipeBehavior:on_swipe_down fired') + pass + + def on_touch_down(self,touch): + if self.collide_point(*touch.pos): + self.sb_start_point = pos + self.sb_start_time = time.time() + return super().on_touch_down(touch) + + def on_touch_move(self,touch): + if self.collide_point(*touch.pos): + if self.sb_start_point is None: + self.sb_start_point = touch.pos + else: + self.sb_end_point = touch.pos + return super().on_touch_move() + + def on_touch_up(self,touch): + if self.collide_point(*touch.pos): + self.sb_end_point = touch.pos + self.sb_end_time = time.time() + self.check_context_menu() + self.check_swipe() + self.sb_start_point = None + self.sb_end_point = None + self.sb_start_time = None + self.sb_end_time = None + super().on_touch_up() + + def check_context_menu(self): + if not self.sb_start_time: + return + if not self.sb_end_time: + return + if self.sb_end_time - self.sb_start_time > self.threshold_time: + self.dispatch('on_context_menu') + + def check_swipe(self): + if abs(self.sb_end_point.x - self.sb_start_point.x) > \ + abs(self.sb_end_point.y - self.sb_start_point.y): + if self.sb_end_point.x - self.sb_start_point.x > self.threshold: + self.dispatch('on_swipe_right') + elif self.sb_start_point.x - self.sb_end_point.x > self.threshold: + self.dispatch('on_swipe_left') + else: + if self.sb_end_point.y - self.sb_start_point.y > self.threshold: + self.dispatch('on_swipe_up') + elif self.sb_start_point.y - self.sb_end_point.x > self.threshold: + self.dispatch('on_swipe_down') diff --git a/kivyblocks/vplayer.py b/kivyblocks/vplayer.py index b13fe79..db42b82 100644 --- a/kivyblocks/vplayer.py +++ b/kivyblocks/vplayer.py @@ -23,6 +23,7 @@ from ffpyplayer.tools import set_log_callback from .utils import * from .paging import PageLoader from .baseWidget import PressableImage +from .swipebehavior import SwipeBehavior desktopOSs=[ "win", @@ -47,10 +48,11 @@ class UrlPlayList(PageLoader): id = d['rows'][0].id self.player.play(id) -class BaseVPlayer(FloatLayout): +class BaseVPlayer(FloatLayout, SwipeBehavior): fullscreen = BooleanProperty(False) def __init__(self,vfile=None,playlist=[]): - super().__init__() + FloatLayout.__init__(self) + SwipeBehavior.__init__(self) self.register_event_type('on_source_error') self.register_event_type('on_next') self.register_event_type('on_previous') @@ -70,6 +72,18 @@ class BaseVPlayer(FloatLayout): if hasattr(self._video._video, '_ffplayer'): self.ffplayer = self._video._video._ffplayer + def on_swipe_down(self): + self.stop() + self.dispatch('on_next') + + on_swipe_right = on_swipe_down + + def on_swipe_up(self): + self.stop() + self.dispatch('on_previous') + + on_swipe_left = on_swipe_up + def setSource(self,s): self.stop() self.curplay = 0 @@ -104,9 +118,11 @@ class BaseVPlayer(FloatLayout): self._video.state = 'play' def next(self,o=None,v=None): + self.stop() self.dispatch('on_next',self) def previous(self,o=None,v=None): + self.stop() self.dispatch('on_previous',self) def on_state(self,o=None,v=None): @@ -307,12 +323,18 @@ class VPlayer(BaseVPlayer): self.slider.max = self._video.duration self.maxposition.text = self.totime(self._video.duration) + def stop(self): + if self.update_task is not None: + self.update_task.cancel() + self.update_task = None + super().stop() + def __del__(self): self.beforeDestroy() def beforeDestroy(self): print('beforeDestroy() called') - self._video.state = 'stop' + self.stop() return True def show_hide_menu(self,obj,touch): diff --git a/kivyblocks/widgetExt/camera.py b/kivyblocks/widgetExt/camera.py index 9c31cd1..bb537a4 100644 --- a/kivyblocks/widgetExt/camera.py +++ b/kivyblocks/widgetExt/camera.py @@ -23,67 +23,33 @@ class AndroidCamera(Camera): intent.putExtra(MediaStore.EXTRA_OUTPUT, parcelable) activity.startActivityForResult(intent, 0x123) - - def _take_video(self, on_complete, filename=None): - assert(on_complete is not None) - self.on_complete = on_complete - self.filename = filename - android.activity.unbind(on_activity_result=self._on_activity_result) - android.activity.bind(on_activity_result=self._on_activity_result) - intent = Intent(MediaStore.ACTION_VIDEO_CAPTURE) - uri = Uri.parse('file://' + filename) - parcelable = cast('android.os.Parcelable', uri) - intent.putExtra(MediaStore.EXTRA_OUTPUT, parcelable) - - - # 0 = low quality, suitable for MMS messages, - # 1 = high quality - intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1) - activity.startActivityForResult(intent, 0x123) - - def _on_activity_result(self, requestCode, resultCode, intent): - if requestCode != 0x123: - return - android.activity.unbind(on_activity_result=self._on_activity_result) - if self.on_complete(self.filename): - self._remove(self.filename) - - def _remove(self, fn): - try: - remove(fn) - except OSError: - pass - - - - def instance(): return AndroidCamera()