# HG changeset patch # User Goffi # Date 1527103508 -7200 # Node ID 519b3a29743cc93f5579257e512fd88039089b24 # Parent cf30cb1d1c126141f949c3367b593544568d31eb 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. diff -r cf30cb1d1c12 -r 519b3a29743c cagou/core/utils.py --- /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 . + +"""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) diff -r cf30cb1d1c12 -r 519b3a29743c cagou/plugins/plugin_wid_file_sharing.py --- 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 ##