| Philipp Le | 4071d91 | 2022-04-26 22:02:43 +0200 | [diff] [blame] | 1 | # SPDX-License-Identifier: MPL-2.0 |
| 2 | # Copyright (c) 2022 Philipp Le <philipp@philipple.de>. |
| 3 | # This Source Code Form is subject to the terms of the Mozilla Public |
| 4 | # License, v. 2.0. If a copy of the MPL was not distributed with this |
| 5 | # file, You can obtain one at https://mozilla.org/MPL/2.0/. |
| 6 | |
| 7 | from __future__ import annotations |
| 8 | |
| 9 | from typing import Type, List, Dict, Optional |
| 10 | from pydantic import BaseModel |
| 11 | |
| 12 | from .base import ConfigWidget |
| Philipp Le | cefab92 | 2022-04-26 22:06:33 +0200 | [diff] [blame] | 13 | from .num_widget import NumWidget |
| Philipp Le | cfb6d2a | 2022-04-26 22:08:48 +0200 | [diff] [blame] | 14 | from .str_widget import StrWidget |
| Philipp Le | e93a2c4 | 2022-04-26 22:11:14 +0200 | [diff] [blame^] | 15 | from .enum_widget import EnumDropdownWidget |
| Philipp Le | 4071d91 | 2022-04-26 22:02:43 +0200 | [diff] [blame] | 16 | |
| 17 | |
| 18 | _CLASS_REGISTRY: List[Type[ConfigWidget]] = [ |
| Philipp Le | cefab92 | 2022-04-26 22:06:33 +0200 | [diff] [blame] | 19 | NumWidget, |
| Philipp Le | cfb6d2a | 2022-04-26 22:08:48 +0200 | [diff] [blame] | 20 | StrWidget, |
| Philipp Le | e93a2c4 | 2022-04-26 22:11:14 +0200 | [diff] [blame^] | 21 | EnumDropdownWidget, |
| Philipp Le | 4071d91 | 2022-04-26 22:02:43 +0200 | [diff] [blame] | 22 | ] |
| 23 | |
| 24 | |
| 25 | def _find_widget_classes(tp: Type, is_list: bool = False) -> Dict[Optional[str], Type[ConfigWidget]]: |
| 26 | widget_classes: Dict[Optional[str], Type[ConfigWidget]] = {} |
| 27 | if is_list: |
| 28 | raise NotImplementedError |
| 29 | else: |
| 30 | for cls in _CLASS_REGISTRY: |
| 31 | if issubclass(tp, cls.MODEL_TYPE): |
| 32 | widget_classes[cls.FLAVOUR] = cls |
| 33 | if len(widget_classes) == 0: |
| 34 | raise TypeError(f'No widget class for {repr(tp)} found.') |
| 35 | return widget_classes |
| 36 | |
| 37 | |
| 38 | def _add_ui_create(model_cls: BaseModel, tp: Type[int], name: str, widget_type: Type[ConfigWidget], |
| 39 | flavour: Optional[str]): |
| 40 | suffix = f'_{flavour}' if flavour is not None else '' |
| 41 | setattr(model_cls, f'ui_create_{name}{suffix}', widget_type.make_ui_create_method(tp, name)) |
| 42 | |
| 43 | |
| 44 | def ui_create(cls: BaseModel): |
| 45 | for field in cls.__fields__.values(): |
| 46 | name = field.name |
| 47 | tp = field.type_ |
| 48 | is_list = isinstance(field.default, list) |
| 49 | try: |
| 50 | widget_classes = _find_widget_classes(tp, is_list) |
| 51 | for flavour, wgd_cls in widget_classes.items(): |
| 52 | _add_ui_create(cls, tp, name, wgd_cls, flavour) |
| 53 | except TypeError as e: |
| 54 | print(e) |
| 55 | return cls |