diff cagou/plugins/plugin_wid_file_sharing.py @ 222:a676cb07c1cb

core (menu): TouchMenuBehaviour: moved code showing ModernMenu on item from file sharing plugin to a generic behaviour, so it can be re-used elsewhere.
author Goffi <goffi@goffi.org>
date Tue, 26 Jun 2018 20:26:21 +0200
parents 286f14127f61
children 059c5b39032d
line wrap: on
line diff
--- a/cagou/plugins/plugin_wid_file_sharing.py	Tue Jun 26 07:36:11 2018 +0200
+++ b/cagou/plugins/plugin_wid_file_sharing.py	Tue Jun 26 20:26:21 2018 +0200
@@ -27,15 +27,14 @@
 from sat_frontends.tools import jid
 from cagou.core.constants import Const as C
 from cagou.core import cagou_widget
-from cagou.core.menu import EntitiesSelectorMenu
+from cagou.core.menu import (EntitiesSelectorMenu, TouchMenuBehaviour,
+                             TouchMenuItemBehaviour)
 from cagou.core.utils import FilterBehavior
 from cagou import G
 from kivy import properties
 from kivy.uix.label import Label
 from kivy.uix.button import Button
 from kivy.uix.boxlayout import BoxLayout
-from kivy.garden import modernmenu
-from kivy.clock import Clock
 from kivy.metrics import dp
 from kivy import utils as kivy_utils
 from functools import partial
@@ -106,53 +105,19 @@
         return self.identities.values()[0].values()[0][0]
 
 
-class ItemWidget(BoxLayout):
-    click_timeout = properties.NumericProperty(0.4)
+class ItemWidget(TouchMenuItemBehaviour, BoxLayout):
+    name = properties.StringProperty()
     base_width = properties.NumericProperty(dp(100))
 
-    def __init__(self, sharing_wid, name):
-        self.sharing_wid = sharing_wid
-        self.name = name
-        super(ItemWidget, self).__init__()
-
-    def on_touch_down(self, touch):
-        if not self.collide_point(*touch.pos):
-            return
-        t = partial(self.open_menu, touch)
-        touch.ud['menu_timeout'] = t
-        Clock.schedule_once(t, self.click_timeout)
-        return super(ItemWidget, self).on_touch_down(touch)
-
-    def do_item_action(self, touch):
-        pass
-
-    def on_touch_up(self, touch):
-        if touch.ud.get('menu_timeout'):
-            Clock.unschedule(touch.ud['menu_timeout'])
-            if self.collide_point(*touch.pos) and self.sharing_wid.menu is None:
-                self.do_item_action(touch)
-        return super(ItemWidget, self).on_touch_up(touch)
-
-    def open_menu(self, touch, dt):
-        self.sharing_wid.open_menu(self, touch)
-        del touch.ud['menu_timeout']
-
-    def getMenuChoices(self):
-        """return choice adapted to selected item
-
-        @return (list[dict]): choices ad expected by ModernMenu
-        """
-        return []
-
 
 class PathWidget(ItemWidget):
 
-    def __init__(self, sharing_wid, filepath):
+    def __init__(self, filepath, main_wid, **kw):
         name = os.path.basename(filepath)
         self.filepath = os.path.normpath(filepath)
         if self.filepath == u'.':
             self.filepath = u''
-        super(PathWidget, self).__init__(sharing_wid, name)
+        super(PathWidget, self).__init__(name=name, main_wid=main_wid, **kw)
 
     @property
     def is_dir(self):
@@ -160,7 +125,7 @@
 
     def do_item_action(self, touch):
         if self.is_dir:
-            self.sharing_wid.current_dir = self.filepath
+            self.main_wid.current_dir = self.filepath
 
     def open_menu(self, touch, dt):
         log.debug(_(u"opening menu for {path}").format(path=self.filepath))
@@ -178,19 +143,19 @@
         if self.shared:
             choices.append(dict(text=_(u'unshare'),
                                 index=len(choices)+1,
-                                callback=self.sharing_wid.unshare))
+                                callback=self.main_wid.unshare))
         else:
             choices.append(dict(text=_(u'share'),
                                 index=len(choices)+1,
-                                callback=self.sharing_wid.share))
+                                callback=self.main_wid.share))
         return choices
 
 
 class RemotePathWidget(PathWidget):
 
-    def __init__(self, sharing_wid, filepath, type_):
+    def __init__(self, main_wid, filepath, type_, **kw):
         self.type_ = type_
-        super(RemotePathWidget, self).__init__(sharing_wid, filepath)
+        super(RemotePathWidget, self).__init__(filepath, main_wid=main_wid, **kw)
 
     @property
     def is_dir(self):
@@ -199,17 +164,17 @@
     def do_item_action(self, touch):
         if self.is_dir:
             if self.filepath == u'..':
-                self.sharing_wid.remote_entity = u''
+                self.main_wid.remote_entity = u''
             else:
                 super(RemotePathWidget, self).do_item_action(touch)
         else:
-            self.sharing_wid.request_item(self)
+            self.main_wid.request_item(self)
             return True
 
 
 class DeviceWidget(ItemWidget):
 
-    def __init__(self, sharing_wid, entity_jid, identities):
+    def __init__(self, main_wid, entity_jid, identities, **kw):
         self.entity_jid = entity_jid
         self.identities = identities
         own_jid = next(G.host.profiles.itervalues()).whoami
@@ -223,7 +188,7 @@
         else:
             name = _(u"sharing component")
 
-        super(DeviceWidget, self).__init__(sharing_wid, name)
+        super(DeviceWidget, self).__init__(name=name, main_wid=main_wid, **kw)
 
     def getSymbol(self):
         if self.identities.type == 'desktop':
@@ -238,21 +203,17 @@
             return 'desktop'
 
     def do_item_action(self, touch):
-        self.sharing_wid.remote_entity = self.entity_jid
-        self.sharing_wid.remote_dir = u''
+        self.main_wid.remote_entity = self.entity_jid
+        self.main_wid.remote_dir = u''
 
 
 class CategorySeparator(Label):
     pass
 
 
-class Menu(modernmenu.ModernMenu):
-    pass
-
-
-class FileSharing(quick_widgets.QuickWidget, cagou_widget.CagouWidget, FilterBehavior):
+class FileSharing(quick_widgets.QuickWidget, cagou_widget.CagouWidget, FilterBehavior,
+                  TouchMenuBehaviour):
     SINGLE=False
-    float_layout = properties.ObjectProperty()
     layout = properties.ObjectProperty()
     mode = properties.OptionProperty(MODE_LOCAL, options=[MODE_VIEW, MODE_LOCAL])
     local_dir = properties.StringProperty(expanduser(u'~'))
@@ -265,6 +226,7 @@
         quick_widgets.QuickWidget.__init__(self, host, target, profiles)
         cagou_widget.CagouWidget.__init__(self)
         FilterBehavior.__init__(self)
+        TouchMenuBehaviour.__init__(self)
         self.mode_btn = ModeBtn(self)
         self.mode_btn.bind(on_release=self.change_mode)
         self.headerInputAddExtra(self.mode_btn)
@@ -272,9 +234,6 @@
                   remote_dir=self.update_view,
                   remote_entity=self.update_view)
         self.update_view()
-        self.menu = None
-        self.menu_item = None
-        self.float_layout.bind(children=self.clean_fl_children)
         if not FileSharing.signals_registered:
             # FIXME: we use this hack (registering the signal for the whole class) now
             #        as there is currently no unregisterSignal available in bridges
@@ -375,8 +334,8 @@
         for file_data in files_data:
             filepath = os.path.join(self.current_dir, file_data[u'name'])
             item = RemotePathWidget(
-                self,
                 filepath=filepath,
+                main_wid=self,
                 type_=file_data[u'type'])
             self.layout.add_widget(item)
 
@@ -400,7 +359,7 @@
 
         if self.mode == MODE_LOCAL:
             filepath = os.path.join(self.local_dir, u'..')
-            self.layout.add_widget(LocalPathWidget(sharing_wid=self, filepath=filepath))
+            self.layout.add_widget(LocalPathWidget(filepath=filepath, main_wid=self))
             try:
                 files = sorted(os.listdir(self.local_dir))
             except OSError as e:
@@ -415,8 +374,8 @@
                 return
             for f in files:
                 filepath = os.path.join(self.local_dir, f)
-                self.layout.add_widget(LocalPathWidget(sharing_wid=self,
-                                                       filepath=filepath))
+                self.layout.add_widget(LocalPathWidget(filepath=filepath,
+                                                       main_wid=self))
         elif self.mode == MODE_VIEW:
             if not self.remote_entity:
                 self.discover_devices()
@@ -425,8 +384,8 @@
                 # so user can return to previous list even in case of error
                 parent_path = os.path.join(self.remote_dir, u'..')
                 item = RemotePathWidget(
-                    self,
                     filepath = parent_path,
+                    main_wid=self,
                     type_ = C.FILE_TYPE_DIRECTORY)
                 self.layout.add_widget(item)
                 self.host.bridge.FISList(
@@ -437,40 +396,6 @@
                     callback=self.FISListCb,
                     errback=self.FISListEb)
 
-    ## menu methods ##
-
-    def clean_fl_children(self, layout, children):
-        """insure that self.menu and self.menu_item are None when menu is dimissed"""
-        if self.menu is not None and self.menu not in children:
-            self.menu = self.menu_item = None
-
-    def clear_menu(self):
-        """remove menu if there is one"""
-        if self.menu is not None:
-            self.menu.dismiss()
-            self.menu = None
-            self.menu_item = None
-
-    def open_menu(self, item, touch):
-        """open menu for item
-
-        @param item(PathWidget): item when the menu has been requested
-        @param touch(kivy.input.MotionEvent): touch data
-        """
-        if self.menu_item == item:
-            return
-        self.clear_menu()
-        pos = self.to_widget(*touch.pos)
-        choices = item.getMenuChoices()
-        if not choices:
-            return
-        self.menu = Menu(choices=choices,
-                         center=pos,
-                         size_hint=(None, None))
-        self.float_layout.add_widget(self.menu)
-        self.menu.start_display(touch)
-        self.menu_item = item
-
     ## Share methods ##
 
     def do_share(self, entities_jids, item):