changeset 196:519b3a29743c

utils, plugin file sharing: new utils module, with a FilterBehavior: FilterBehavior do a smooth animation for filtering out children of a layout according to a text content.
author Goffi <goffi@goffi.org>
date Wed, 23 May 2018 21:25:08 +0200
parents cf30cb1d1c12
children c7d15ef4bfa8
files cagou/core/utils.py cagou/plugins/plugin_wid_file_sharing.py
diffstat 2 files changed, 85 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cagou/core/utils.py	Wed May 23 21:25:08 2018 +0200
@@ -0,0 +1,73 @@
+#!/usr//bin/env python2
+# -*- coding: utf-8 -*-
+
+# Cagou: desktop/mobile frontend for Salut à Toi XMPP client
+# Copyright (C) 2016-2018 Jérôme Poisson (goffi@goffi.org)
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+"""misc utils/behaviors"""
+
+
+from kivy.animation import Animation
+
+
+class FilterBehavior(object):
+    """class to handle items filtering with animation"""
+
+    def __init__(self, *args, **kwargs):
+        super(FilterBehavior, self).__init__(*args, **kwargs)
+        self._filter_last = u''
+        self._filter_anim = Animation(width = 0,
+                                      height = 0,
+                                      opacity = 0,
+                                      d = 0.5)
+
+    def do_filter(self, children, text, get_child_text, width_cb, height_cb, continue_tests=None):
+        """filter the children
+
+        filtered children will have a animation to set width, height and opacity to 0
+        @param children(kivy.uix.widget.Widget): widgets to filter
+        @param text(unicode): filter text (if this text is not present in a child,
+            the child is filtered out)
+        @param get_child_text(callable): must retrieve child text
+            child is used as sole argument
+        @param width_cb(callable, int, None): method to retrieve width when opened
+            child is used as sole argument, int can be used instead of callable
+        @param height_cb(callable, int, None): method to retrieve height when opened
+            child is used as sole argument, int can be used instead of callable
+        @param continue_tests(list[callable]): list of test to skip the item
+            all callables take child as sole argument.
+            if any of the callable return True, the child is skipped (i.e. not filtered)
+        """
+        text = text.strip().lower()
+        filtering = len(text)>len(self._filter_last)
+        self._filter_last = text
+        for child in self.layout.children:
+            if continue_tests is not None and any([t(child) for t in continue_tests]):
+                continue
+            if text in get_child_text(child).lower():
+                self._filter_anim.cancel(child)
+                for key, method in (('width', width_cb),
+                                    ('height', height_cb),
+                                    ('opacity', lambda c: 1)):
+                    try:
+                        setattr(child, key, method(child))
+                    except TypeError:
+                        # method is not a callable, must be an int
+                        setattr(child, key, method)
+            elif (filtering
+                  and child.opacity > 0
+                  and not self._filter_anim.have_properties_to_animate(child)):
+                self._filter_anim.start(child)
--- a/cagou/plugins/plugin_wid_file_sharing.py	Wed May 23 21:22:29 2018 +0200
+++ b/cagou/plugins/plugin_wid_file_sharing.py	Wed May 23 21:25:08 2018 +0200
@@ -27,6 +27,7 @@
 from sat_frontends.tools import jid
 from cagou.core.constants import Const as C
 from cagou.core import cagou_widget
+from cagou.core.utils import FilterBehavior
 from cagou import G
 from kivy import properties
 from kivy.uix.label import Label
@@ -35,7 +36,6 @@
 from kivy.garden import modernmenu
 from kivy.clock import Clock
 from kivy.metrics import dp
-from kivy.animation import Animation
 from functools import partial
 import os.path
 import json
@@ -207,7 +207,7 @@
     pass
 
 
-class FileSharing(quick_widgets.QuickWidget, cagou_widget.CagouWidget):
+class FileSharing(quick_widgets.QuickWidget, cagou_widget.CagouWidget, FilterBehavior):
     SINGLE=False
     float_layout = properties.ObjectProperty()
     layout = properties.ObjectProperty()
@@ -219,13 +219,9 @@
     signals_registered = False
 
     def __init__(self, host, target, profiles):
-        self._filter_last = u''
-        self._filter_anim = Animation(width = 0,
-                                      height = 0,
-                                      opacity = 0,
-                                      d = 0.5)
         quick_widgets.QuickWidget.__init__(self, host, target, profiles)
         cagou_widget.CagouWidget.__init__(self)
+        FilterBehavior.__init__(self)
         self.mode_btn = ModeBtn(self)
         self.mode_btn.bind(on_release=self.change_mode)
         self.headerInputAddExtra(self.mode_btn)
@@ -274,27 +270,18 @@
         if u'/' in self.header_input.text or self.header_input.text == u'~':
             self.current_dir = os.path.expanduser(self.header_input.text)
 
-    def onHeaderInputComplete(self, wid, text):
+    def onHeaderInputComplete(self, wid, text, **kwargs):
         """we filter items when text is entered in input box"""
-        text = text.strip().lower()
         if u'/' in text:
             return
-        filtering = len(text)>len(self._filter_last)
-        self._filter_last = text
-        for child in self.layout.children:
-            if not isinstance(child, ItemWidget):
-                continue
-            if child.name == u'..':
-                continue
-            if text in child.name.lower():
-                self._filter_anim.cancel(child)
-                child.width = child.base_width
-                child.height = child.minimum_height
-                child.opacity = 1
-            elif (filtering
-                  and child.opacity > 0
-                  and not self._filter_anim.have_properties_to_animate(child)):
-                self._filter_anim.start(child)
+        self.do_filter(self.layout.children,
+                       text,
+                       lambda c: c.name,
+                       width_cb=lambda c: c.base_width,
+                       height_cb=lambda c: c.minimum_height,
+                       continue_tests=[lambda c: not isinstance(c, ItemWidget),
+                                       lambda c: c.name == u'..'])
+
 
     ## remote sharing callback ##