Source code for tagit.view.filter

"""Displays a row with filters tokens.

Part of the tagit module.
A copy of the license is provided with the project.
Author: Matthias Baumgartner, 2016

"""
# imports
from os.path import join, dirname
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.logger import Logger
from kivy.uix.behaviors import FocusBehavior
from kivy.graphics.instructions import InstructionGroup
from kivy.graphics import Rectangle, Color
from kivy.uix.textinput import TextInput

# inner-module imports
from dialogues import TextInputDialogue, ErrorDialogue
from ..controller.filter import CFilter, CFilterToken

# exports
__all__ = ('VFilter', )

# Load kv
Builder.load_file(join(dirname(__file__), 'filter.kv'))

# classes
[docs]class VFilter(BoxLayout): """A row of filter tokens (i.e. some filter text) and its management. A filter is used to search in the image database. The filter consists of several tokens. Each token adds a search constraint. Tokens can be added, changed and removed. The filter can be applied to an image source. This has effects on other parts of the UI, namely the *Browser*. """ def __init__(self, **kwargs): super(VFilter, self).__init__(**kwargs)
[docs] def on_parent(self, *args): """Set the controller.""" self.controller = self.get_controller(CFilter) super(VFilter, self).on_parent(*args)
[docs] def redraw(self, tokens, cutoff): """Redraw the tokens.""" self.tokens.redraw(tokens, cutoff)
[docs] def token_dialogue(self, text, clbk): """Show a dialogue for modifying tokens.""" keyctrl = self.controller.get_root().widget dlg = TextInputDialogue(text=text, keyboard_ctrl=keyctrl) def ok(c): try: clbk(c.text) except ValueError, e: self.error("syntax error: " + e.message) except Exception, e: self.error(e.message) dlg.bind(on_ok=ok) dlg.open()
[docs] def error(self, text): """Display an error dialogue.""" dlg = ErrorDialogue(text=text) dlg.open()
[docs] def request_add_token(self): """Ask the controller to add a token.""" self.controller.request_add_token()
[docs] def request_apply(self): """Ask the controller to apply the filter.""" self.controller.request_apply()
def show_editor(self, tokens, clbk_ok, clbk_cancel): self.tokens.editor(tokens, clbk_ok, clbk_cancel)
class TokenGroup(BoxLayout): """Group of tokens; i.e. the space where tokens are displayed. """ def redraw(self, tokens, cutoff): """Redraw the tokens.""" self.clear_widgets() for idx, tok in enumerate(tokens): wx = Token(tok) wx.default_text = tok.display() wx.active = idx < cutoff self.add_widget(wx) def editor(self, text, clbk_ok, clbk_cancel): self.clear_widgets() wx = TokenEditor( text=text , keyboard_ctrl=self.get_controller().get_root().widget , on_ok=clbk_ok , on_cancel=clbk_cancel ) self.add_widget(wx) wx.focus = True class TokenEditor(TextInput): """ When invoked -> get exclusive keyboard access when removed -> release exclusive keyboard access On press enter -> set filter, redraw normal filter, apply On press esc -> abort, redraw normal filter, apply """ def __init__(self, *args, **kwargs): self._keyboard_ctrl = kwargs.pop('keyboard_ctrl', None) self.clbk_accept = kwargs.pop('on_ok', None) self.clbk_cancel= kwargs.pop('on_cancel', None) super(TokenEditor, self).__init__(*args, **kwargs) self._keyboard_ctrl.request_exclusive_keyboard() self.accepted = False def __del__(self): self._keyboard_ctrl.release_exclusive_keyboard() def on_text_focus(self, instance, value): if not value and not self.accepted: self.cancel() def ok(self): self.accepted = True self._keyboard_ctrl.release_exclusive_keyboard() self.clbk_accept(self.text) def cancel(self): self._keyboard_ctrl.release_exclusive_keyboard() self.clbk_cancel(self.text) class Token(BoxLayout): """A single token. """ def __init__(self, token, *args, **kwargs): super(Token, self).__init__(*args, **kwargs) self._deco = None self.token = token def on_parent(self, *args): self.controller = self.get_controller(CFilterToken) super(Token, self).on_parent(*args) def on_size(self, *args): self._redraw() def on_active(self): self._redraw() def _redraw(self): if self.active: if self._deco is not None: # Remove deco self.canvas.before.remove(self._deco) # create deco self._deco = InstructionGroup() self._deco.add(Color(0, 0, 1, 0.25)) self._deco.add(Rectangle(pos=self.pos, size=self.size)) self.canvas.before.add(self._deco) def remove(self): """Remove the token (Click on remove button).""" if self.controller is not None: self.controller.parent.request_remove_token(self.token) def edit_label(self, text): """Edit the token (Click on label). Opens a dialogue for entering text. """ if self.controller is None: return keyctrl = self.controller.get_root().widget dlg = TextInputDialogue(text=self.token.edit(), keyboard_ctrl=keyctrl) dlg.bind(on_ok=lambda c: self.controller.parent.request_edit_token(self.token, c.text)) dlg.open() class TokenLabel(Label): """Label to display the token text. """ def on_touch_down(self, touch): """Change the token text by clicking onto it. """ if self.collide_point(*touch.pos): FocusBehavior.ignored_touch.append(touch) # Stops dialogue from loosing the focus self.parent.edit_label(self.text) return True return super(TokenLabel, self).on_touch_down(touch) ## EOF ##