Source code for qudi.util.widgets.literal_lineedit

# -*- coding: utf-8 -*-

"""
This module provides QWidget subclasses to enter different literals (complex, dict, list, tuple,
set).

.. Copyright (c) 2021, the qudi developers. See the AUTHORS.md file at the top-level directory of this
.. distribution and on <https://github.com/Ulm-IQO/qudi-core/>
..
.. This file is part of qudi.
..
.. Qudi is free software: you can redistribute it and/or modify it under the terms of
.. the GNU Lesser General Public License as published by the Free Software Foundation,
.. either version 3 of the License, or (at your option) any later version.
..
.. Qudi 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 Lesser General Public License for more details.
..
.. You should have received a copy of the GNU Lesser General Public License along with qudi.
.. If not, see <https://www.gnu.org/licenses/>.
"""

__all__ = [
    'ComplexLineEdit',
    'ComplexValidator',
    'DictLineEdit',
    'DictValidator',
    'ListLineEdit',
    'ListValidator',
    'LiteralLineEdit',
    'LiteralValidator',
    'SetLineEdit',
    'SetValidator',
    'TupleLineEdit',
    'TupleValidator',
]

from PySide2 import QtCore, QtGui, QtWidgets
from typing import (
    Any,
    Optional,
    Mapping,
    MutableSequence,
    Sequence,
    Set,
    FrozenSet,
    Union,
    List,
)
from typing import Tuple, Dict


[docs] class LiteralValidator(QtGui.QValidator): """ """
[docs] def __init__(self, parent: Optional[QtCore.QObject] = None): super().__init__(parent=parent)
[docs] def validate(self, text: str, position: int) -> QtGui.QValidator.State: """ """ try: self.value_from_text(text) return self.Acceptable except: return self.Intermediate
[docs] def fixup(self, text: str) -> str: return text
[docs] def value_from_text(self, text: str) -> Any: return eval(text)
[docs] def text_from_value(self, value: Any) -> str: return repr(value)
[docs] class ComplexValidator(QtGui.QValidator): """ """
[docs] def __init__(self, parent: Optional[QtCore.QObject] = None): super().__init__(parent=parent)
[docs] def validate(self, text: str, position: int) -> QtGui.QValidator.State: """ """ try: self.value_from_text(text) return self.Acceptable except ValueError: return self.Intermediate
[docs] def fixup(self, text: str) -> str: return text
[docs] def value_from_text(self, text: str) -> complex: return complex(text)
[docs] def text_from_value(self, value: complex) -> str: if value is None: value = complex() return repr(complex(value))
[docs] class ListValidator(QtGui.QValidator): """ """
[docs] def __init__(self, parent: Optional[QtCore.QObject] = None): super().__init__(parent=parent)
[docs] def validate(self, text: str, position: int) -> QtGui.QValidator.State: """ """ try: self.value_from_text(text) return self.Acceptable except: return self.Intermediate
[docs] def fixup(self, text: str) -> str: return text
[docs] def value_from_text(self, text: str) -> List[Any]: tmp = eval(text) if isinstance(tmp, (list, tuple)): return list(tmp) raise ValueError
[docs] def text_from_value(self, value: MutableSequence[Any]) -> str: if value is None: value = list() return repr(list(value))
[docs] class TupleValidator(QtGui.QValidator): """ """
[docs] def __init__(self, parent: Optional[QtCore.QObject] = None): super().__init__(parent=parent)
[docs] def validate(self, text: str, position: int) -> QtGui.QValidator.State: """ """ try: self.value_from_text(text) return self.Acceptable except: return self.Intermediate
[docs] def fixup(self, text: str) -> str: return text
[docs] def value_from_text(self, text: str) -> Tuple[Any, ...]: tmp = eval(text) if isinstance(tmp, tuple): return tmp raise ValueError
[docs] def text_from_value(self, value: Sequence[Any]) -> str: if value is None: value = tuple() return repr(tuple(value))
[docs] class SetValidator(QtGui.QValidator): """ """
[docs] def __init__(self, parent: Optional[QtCore.QObject] = None): super().__init__(parent=parent)
[docs] def validate(self, text: str, position: int) -> QtGui.QValidator.State: """ """ try: self.value_from_text(text) return self.Acceptable except: return self.Intermediate
[docs] def fixup(self, text: str) -> str: return text
[docs] def value_from_text(self, text: str) -> Set[Any]: tmp = eval(text) if isinstance(tmp, (tuple, set, frozenset)): return set(tmp) raise ValueError
[docs] def text_from_value(self, value: Union[Set[Any], FrozenSet[Any]]) -> str: if value is None: value = set() return repr(set(value))
[docs] class DictValidator(QtGui.QValidator): """ """
[docs] def __init__(self, parent: Optional[QtCore.QObject] = None): super().__init__(parent=parent)
[docs] def validate(self, text: str, position: int) -> QtGui.QValidator.State: """ """ try: self.value_from_text(text) return self.Acceptable except: return self.Intermediate
[docs] def fixup(self, text: str) -> str: return text
[docs] def value_from_text(self, text: str) -> Dict[Any, Any]: tmp = eval(text) if isinstance(tmp, dict): return tmp elif isinstance(tmp, tuple): return dict(tmp) raise ValueError
[docs] def text_from_value(self, value: Mapping[Any, Any]) -> str: if value is None: value = dict() return repr(dict(value))
[docs] class LiteralLineEdit(QtWidgets.QLineEdit): """ """ valueChanged = QtCore.Signal(object)
[docs] def __init__( self, value: Optional[Any] = None, parent: Optional[QtWidgets.QWidget] = None, validator: Optional[QtGui.QValidator] = None, ): super().__init__(parent=parent) if validator is None: validator = LiteralValidator() self._last_valid_text = '' self.setValidator(validator) self.setValue(value)
[docs] def setValue(self, value: Any) -> None: """ """ validator = self.validator() text = validator.fixup(validator.text_from_value(value)) if self._new_text_valid(text): self.setText(text) self._last_valid_text = text self.valueChanged.emit(self.value()) elif text != self._last_valid_text: raise ValueError
[docs] def value(self) -> Any: """ """ return self.validator().value_from_text(self._last_valid_text)
[docs] def focusOutEvent(self, event: QtGui.QFocusEvent) -> None: self._revert_text() return super().focusOutEvent(event)
[docs] def keyPressEvent(self, event: QtGui.QKeyEvent) -> None: check_text = True if event.key() in (QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return): self._revert_text() check_text = False ret_val = super().keyPressEvent(event) if check_text: text = self.text() if self._new_text_valid(text): self._last_valid_text = text self.valueChanged.emit(self.value()) return ret_val
def _revert_text(self) -> None: text = self.text() if self.validator().validate(text, len(text)) != QtGui.QValidator.Acceptable: self.setText(self._last_valid_text) def _new_text_valid(self, text: str) -> bool: """Helper method to check if the given text is suitable to replace the current text as valid value. """ if text != self._last_valid_text: validator = self.validator() return validator.validate(text, len(text)) == QtGui.QValidator.Acceptable return False
[docs] class ComplexLineEdit(LiteralLineEdit): """ """ valueChanged = QtCore.Signal(complex)
[docs] def __init__( self, value: Optional[complex] = None, parent: Optional[QtWidgets.QWidget] = None, ): if value is None: value = complex() super().__init__(value=value, parent=parent, validator=ComplexValidator())
[docs] class ListLineEdit(LiteralLineEdit): """ """ valueChanged = QtCore.Signal(list)
[docs] def __init__( self, value: Optional[MutableSequence] = None, parent: Optional[QtWidgets.QWidget] = None, ): if value is None: value = list() super().__init__(value=value, parent=parent, validator=ListValidator())
[docs] class TupleLineEdit(LiteralLineEdit): """ """ valueChanged = QtCore.Signal(tuple)
[docs] def __init__( self, value: Optional[Sequence] = None, parent: Optional[QtWidgets.QWidget] = None, ): if value is None: value = tuple() super().__init__(value=value, parent=parent, validator=TupleValidator())
[docs] class SetLineEdit(LiteralLineEdit): """ """ valueChanged = QtCore.Signal(set)
[docs] def __init__( self, value: Optional[Union[Set, FrozenSet]] = None, parent: Optional[QtWidgets.QWidget] = None, ): if value is None: value = set() super().__init__(value=value, parent=parent, validator=SetValidator())
[docs] class DictLineEdit(LiteralLineEdit): """ """ valueChanged = QtCore.Signal(dict)
[docs] def __init__( self, value: Optional[Mapping] = None, parent: Optional[QtWidgets.QWidget] = None, ): if value is None: value = dict() super().__init__(value=value, parent=parent, validator=DictValidator())