specialised_fields.py 5.17 KB
from django import forms

from django.db.models import Q

from django.utils.translation import gettext_lazy as _

import crispy_forms.bootstrap as bootstrap

from syntax.models_phrase import PhraseTypeModel

from semantics.models import (
    Frame, SemanticRole, RoleAttribute,
    PredefinedSelectionalPreference,
    Synset,
    RelationalSelectionalPreference,
    SelectionalPreferenceRelation,
)

from .generic_fields import (
    RadiosLayoutField,
    SingleRegexFilter,
    ModelChoiceFilter,
    ModelMultipleChoiceFilter,
)

from .query_managers import (
    QueryManager,
    DUMMY_LOOKUP,
)

from entries.polish_strings import PHRASE_TYPE

class PhraseTypeFilter(ModelChoiceFilter):
    
    def __init__(self, queryset=None, lex=False, **kwargs):
        
        if queryset is None:
            if lex:
                queryset = PhraseTypeModel.objects.filter(main_phrase_types__lex_phrases__isnull=False).distinct()
            else:
                queryset = PhraseTypeModel.objects.filter(main_phrase_types__positions__isnull=False).distinct()
        
        super().__init__(
            label=(_('Typ frazeologizmu') if lex else _('Typ frazy')),
            queryset=queryset,
            key='name',
            # this field is not used for filtering, only for choosing subform type
            lookup=DUMMY_LOOKUP,
            # we will want to identify the selected phrase type by name later
            to_field_name='name',
            empty_label=_('wybierz'),
            **kwargs,
        )
    def label_from_instance(self, obj):
        pt = obj.name
        return '{} ({})'.format(pt, PHRASE_TYPE().get(pt, '...'))

    
# TODO implementation without internal QueryManager subclass?
# TODO possibly refactor and check
class PhraseoFilter(forms.ChoiceField, RadiosLayoutField):
    
    class PhraseoQueryManager(QueryManager):
        def __init__(self):
            super().__init__(None, None)
        # Assumes this filter is used on either Entry or Schema and uses the
        # fact that both have the same related name for Subentry
        def _make_queries(self, _, value, op):
            if value == '1':
                return [Q(subentries__schemata__phraseologic=True)]
            if value == '0':
                return [~Q(subentries__schemata__phraseologic=True)]
            return []
    
    def __init__(self):
        super().__init__(
            label=_('Frazeologia'),
            choices=(('2', _('dowolnie')), ('1', _('zawiera')), ('0', _('nie zawiera'))),
            initial='2',
            required=False,
        )
        self.query_manager = PhraseoFilter.PhraseoQueryManager()


# crispy_forms/bootstap.py
class RoleCheckboxes(bootstrap.Field):

    template = 'role_checkboxselectmultiple.html'


class RoleFilter(ModelMultipleChoiceFilter):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # choice: (value, (label, tooltip_text))
        self.choices_index = { choice[1][0] : choice for choice in self.choices }
    
    def layout(self, x, **kwargs):
        return RoleCheckboxes(x, **kwargs)
    
    def _choices_group(self, *choice_names):
        return [self.choices_index[x] for x in choice_names]
    
    def header(self):
        raise NotImplementedError
    
    def rows(self):
        raise NotImplementedError


class RoleNameFilter(RoleFilter):

    def __init__(self, label, lookup, **kwargs):
        super().__init__(
            label=label,
            #queryset=SemanticRole.objects.filter(argumentrole__argument__isnull=False).distinct(),
            queryset=SemanticRole.objects.all(),
            key='role',
            lookup=lookup,
            **kwargs,
        )
    
    def header(self):
        return ('', _('inicjujące'), _('towarzyszące'), _('zamykające'))
    
    def rows(self):
        return (
            {
                'name': _('podstawowe'),
                'cols': (
                    self._choices_group('Initiator', 'Stimulus'),
                    self._choices_group('Theme', 'Experiencer', 'Factor', 'Instrument'),
                    self._choices_group('Recipient', 'Result'),
                )
            },
            {
                'name': _('uzupełniające'),
                'cols': (
                    self._choices_group('Condition'),
                    self._choices_group('Attribute', 'Manner', 'Measure', 'Location', 'Path', 'Time', 'Duration'),
                    self._choices_group('Purpose'),
                )
            },
        )


class RoleAttributeFilter(RoleFilter):

    def __init__(self, label, lookup, **kwargs):
        super().__init__(
            label=label,
            #queryset=RoleAttribute.objects.filter(argumentrole__argument__isnull=False).distinct(),
            queryset=RoleAttribute.objects.all(),
            key='attribute',
            lookup=lookup,
            **kwargs,
        )
    
    def header(self):
        return None
    
    def rows(self):
        return (
            {
                'name': '',
                'cols': (
                    self._choices_group('Source'),
                    self._choices_group('Foreground', 'Background'),
                    self._choices_group('Goal'),
                )
            },
        )