def init_ui(self, layout_cls=None, ok_text=None, cancel_text=None, modality=None): super().init_ui() layout_cls = first_valid(layout_cls=layout_cls, LAYOUT_CLS=self.LAYOUT_CLS, _self=self) modality = modality or self.WINDOW_MODALITY layout: QBoxLayout = layout_cls(self) self.inner = self.inner_template() with self.setup_provided(layout): self.inner.on_change.connect(self._inner_changed) layout.addWidget(self.inner) btn_layout = QHBoxLayout() if self.make_cancel: self.cancel_button = QPushButton(first_valid(cancel_text=cancel_text, CANCEL_TEXT=self.CANCEL_TEXT, _self=self)) self.cancel_button.clicked.connect(self._cancel_btn_clicked) btn_layout.addWidget(self.cancel_button) self.ok_button = QPushButton(first_valid(ok_text=ok_text, CANCEL_TEXT=self.OK_TEXT, _self=self)) self.ok_button.clicked.connect(self._ok_btn_clicked) btn_layout.addWidget(self.ok_button) layout.addLayout(btn_layout) self.setFocusProxy(self.inner) if modality: self.setWindowModality(modality) #if not self.make_cancel: #self.setWindowFlags(Qt.WindowMinimizeButtonHint) self.add_plaintext_delegates(self.inner) return layout
def init_ui(self, layout_cls=None): super().init_ui() layout_cls = first_valid(layout_cls=layout_cls, LAYOUT_CLS=self.LAYOUT_CLS, _self=self) layout = layout_cls(self) with self.setup_provided(layout): self.not_none_checkbox = QCheckBox() self.not_none_checkbox.toggled.connect(self._not_none_changed) layout.addWidget(self.not_none_checkbox) self.inner = self.inner_template() self.inner.on_change.connect(self.change_value) self.inner.setEnabled(False) layout.addWidget(self.inner) for p in chain(self.inner.provided_pre(), self.inner.provided_post()): p.hide() self.warden = self.MouseWarden(target=self.inner, dispatch=partial( self.not_none_checkbox.setChecked, True)) QApplication.instance().installEventFilter(self.warden) return layout
def init_ui(self, frame_style=None, layout_cls: Type[QBoxLayout] = None): super().init_ui() layout_cls = first_valid(layout_cls=layout_cls, LAYOUT_CLS=self.LAYOUT_CLS, _self=self) master_layout = layout_cls(self) frame = QFrame() if frame_style is not None: frame.setFrameStyle(frame_style) layout = layout_cls() with self.setup_provided(master_layout, layout): for inner in self.make_inners(): layout.addWidget(inner) self.value_type = namedtuple(to_identifier(self.title), (to_identifier(i.title) for i in self.inners), rename=True) frame.setLayout(layout) master_layout.addWidget(frame) return master_layout
def __init__(self, inner_template: TemplateLike[T] = None, layout_cls=None, cancel_value: C = NO_CANCEL, close_on_confirm=None, ok_text=None, cancel_text=None, window_modality=None, **kwargs): """ :param inner_template: an inner template to wrap :param layout_cls: the class of the layout :param cancel_value: the value to parse upon the cancel button being clicked. If this argument is provided, a cancel button is created. :param close_on_confirm: whether to close this widget if Ok or Cancel is clicked and the value is valid. :param ok_text: text for the ok button :param cancel_text: text for the cancel button :param window_modality: the modality of the widget, convenience parameter :param kwargs: forwarded to Fidget """ inner_template = only_valid(inner_template=inner_template, INNER_TEMPLATE=self.INNER_TEMPLATE, _self=self).template_of() super().__init__(inner_template.title, **kwargs) self.inner_template = inner_template self.inner: Fidget[T] = None self.ok_button: QPushButton = None self.cancel_button: QPushButton = None self.cancel_value = cancel_value self.make_cancel = cancel_value is not self.NO_CANCEL self.cancel_flag = False self.close_on_confirm = first_valid(close_on_confirm=close_on_confirm, CLOSE_ON_CONFIRM=self.CLOSE_ON_CONFIRM, _self=self) self.init_ui(layout_cls=layout_cls, ok_text=ok_text, cancel_text=cancel_text, modality=window_modality) self._inner_changed()
def __init__(self, title: str, pattern: Union[str, Pattern[str]] = None, allowed_characters: Container[str] = None, forbidden_characters: Container[str] = None, initial=None, **kwargs): super().__init__(title, **kwargs) pattern = optional_valid(pattern=pattern, PATTERN=self.PATTERN, _self=self) self.pattern: Optional[Pattern[str]] = re.compile( pattern) if isinstance(pattern, str) else pattern self.allowed_characters = optional_valid( allowed_characters=allowed_characters, ALLOWED_CHARACTERS=self.ALLOWED_CHARACTERS, _self=self) self.forbidden_characters = optional_valid( forbidden_characters=forbidden_characters, FORBIDDEN_CHARACTERS=self.FORBIDDEN_CHARACTERS, _self=self) self.initial = first_valid(initial=initial, INITIAL=self.INITIAL, _self=self)
def __init__(self, inner_template: TemplateLike[T] = None, layout_cls=None, rows: CountBounds = None, columns: CountBounds = None, row_button_text_func: Callable[[int], str] = None, column_button_text_func: Callable[[int], str] = None, scrollable=None, **kwargs): self.row_bounds = CountBounds[first_valid(rows=rows, ROWS=self.ROWS, _self=self)] self.column_bounds = CountBounds[first_valid(columns=columns, COLUMNS=self.COLUMNS, _self=self)] inner_template = only_valid(inner_template=inner_template, INNER_TEMPLATE=self.INNER_TEMPLATE, _self=self).template_of() super().__init__(inner_template.title, **kwargs) self.inner_template = inner_template self.row_button_text_func = first_valid( row_button_text_func=row_button_text_func, ROW_BUTTON_TEXT_FUNC=self.ROW_BUTTON_TEXT_FUNC, _self=self) self.column_button_text_func = first_valid( column_button_text_func=column_button_text_func, COLUMN_BUTTON_TEXT_FUNC=self.COLUMN_BUTTON_TEXT_FUNC, _self=self) if self.column_button_text_func is ...: self.column_button_text_func = self.row_button_text_func self.grid_layout: QGridLayout = None self.inners: List[List[Fidget[ T]]] = None # first row, then column, self.inners[row][column] self.col_btns: List[QPushButton[T]] = None self.row_btns: List[QPushButton[T]] = None self.row_offset = None self.col_offset = None self.row_count = 0 self.column_count = 0 self.init_ui(layout_cls=layout_cls, scrollable=scrollable)
def __init__(self, title, wrap=None, **kwargs): super().__init__(title, **kwargs) wrap = first_valid(wrap=wrap, WRAP=self.WRAP, _self=self) self.spin: QSpinBox = None self.init_ui(wrap=wrap) self.fill_initial()
def __init__(self, title, minimum=None, maximum=None, step=None, force_float=None, prefix=None, suffix=None, decimals=None, initial_value=None, **kwargs): super().__init__(title, **kwargs) minimum = first_valid(minimum=minimum, MINIMUM=self.MINIMUM, _self=self) maximum = first_valid(maximum=maximum, MAXIMUM=self.MAXIMUM, _self=self) step = first_valid(step=step, STEP=self.STEP, _self=self) decimals = optional_valid(decimals=decimals, DECIMALS=self.DECIMALS, _self=self) force_float = first_valid(force_float=force_float, FORCE_FLOAT=self.FORCE_FLOAT, _self=self) self.use_float = force_float or (decimals is not None) \ or any(isinstance(i, float) for i in (minimum, maximum, step)) prefix = optional_valid(prefix=prefix, PREFIX=self.PREFIX, _self=self) suffix = optional_valid(suffix=suffix, SUFFIX=self.SUFFIX, _self=self) self.spin: Union[QSpinBox, QDoubleSpinBox] = None self.init_ui(minimum=minimum, maximum=maximum, step=step, use_float=self.use_float, prefix=prefix, suffix=suffix, decimals=decimals, initial_value=initial_value)
def __init__(self, title: str, inner_templates: Iterable[TemplateLike[T]] = None, layout_cls=None, rows: CountBounds = None, row_button_text_func: Callable[[int], str] = None, scrollable=None, **kwargs): self.row_bounds = CountBounds[first_valid(rows=rows, ROWS=self.ROWS, _self=self)] inner_templates = tuple( t.template_of() for t in only_valid(inner_templates=inner_templates, INNER_TEMPLATES=self.INNER_TEMPLATES, _self=self)) super().__init__(title, **kwargs) self.inner_templates = inner_templates self.row_button_text_func = first_valid( row_button_text_func=row_button_text_func, ROW_BUTTON_TEXT_FUNC=self.ROW_BUTTON_TEXT_FUNC, _self=self) self.grid_layout: QGridLayout = None self.inners: List[List[Fidget[ T]]] = None # first row, then column, self.inners[row][column] self.col_labels: List[QLabel[T]] = None self.row_btns: List[QPushButton[T]] = None self.row_offset = 1 self.col_offset = None self.row_count = 0 self.column_count = None self.value_type: Type[NamedTuple] = None self.init_ui(layout_cls=layout_cls, scrollable=scrollable)
def __init__(self, title: str, placeholder=None, edit_cls=None, **kwargs): super().__init__(title, **kwargs) placeholder = first_valid(placeholder=placeholder, PLACEHOLDER=self.PLACEHOLDER, _self=self) self.edit: QPlainTextEdit = None self.init_ui(placeholder=placeholder, edit_cls=edit_cls) self.fill_initial()
def __init__(self, title, update_text=None, **kwargs): super().__init__(title, **kwargs) if len(self.options) != 2: raise ValueError( 'FidgetCheckBox must have exactly 2 options, got ' + str(len(self.options))) self.checkbox: QCheckBox = None self.update_text = first_valid(update_text=update_text, UPDATE_TEXT=self.UPDATE_TEXT, _self=self) self.init_ui() self.fill_initial()
def __init__(self, title, options: Iterable[Union[T, Tuple[str, T]]] = None, initial_index: int = None, initial_value=None, **kwargs): super().__init__(title, **kwargs) options = first_valid(options=options, OPTIONS=self.OPTIONS, _self=self) self.options = [parse_option(self, o) for o in options] self.name_lookup = {} for i, (names, o) in enumerate(self.options): for name in names: v = (i, o) if self.name_lookup.setdefault(name, v) != v: raise ValueError('duplicate name: ' + name) self.initial_index = first_valid(initial_index=initial_index, INITIAL_INDEX=self.INITIAL_INDEX, _self=self) self.initial_value = first_valid(initial_value=initial_value, INITIAL_VALUE=self.INITIAL_VALUE, _self=self)
def init_ui(self, frame_style=None, layout_cls=None): super().init_ui() master_layout = QVBoxLayout(self) frame = QFrame() if frame_style is not None: frame.setFrameStyle(frame_style) layout_cls = first_valid(layout_cls=layout_cls, LAYOUT_CLS=self.LAYOUT_CLS, _self=self) layout = layout_cls() with self.setup_provided(master_layout, layout): self.selector = self.selector_cls('select option') self.stacked = QStackedWidget() self.inners = {} for name, inner_template in self.inner_templates.items(): inner: Fidget[T] = inner_template() if self.inners.setdefault(name, inner) is not inner: raise TypeError(f'duplicate inner name: {name}') for p in chain(inner.provided_pre(), inner.provided_post()): p.hide() self.stacked.addWidget(inner) self.selector.add_option(name) inner.on_change.connect(self.change_value) self.selector.on_change.connect(self._selector_changed) layout.addWidget(self.selector) layout.addWidget(self.stacked) if not self.inners: raise ValueError('at least one inner fidget must be provided') self.setFocusProxy(next(iter(self.inners.values()))) frame.setLayout(layout) master_layout.addWidget(frame) return master_layout
def init_ui(self, placeholder=None, edit_cls=None): super().init_ui() layout = QHBoxLayout(self) with self.setup_provided(layout): edit_cls = first_valid(edit_cls=edit_cls, EDIT_CLS=self.EDIT_CLS, _self=self) self.edit = edit_cls() if placeholder: self.edit.setPlaceholderText(self.title) self.edit.textChanged.connect(self.change_value) layout.addWidget(self.edit) self.setFocusProxy(self.edit) return layout
def init_ui(self, dialog=None): super().init_ui() self.dialog = self._args_to_filedialog( first_valid(dialog=dialog, DIALOG=self.DIALOG, _self=self)) layout = QHBoxLayout(self) with self.setup_provided(layout): self.edit = QLineEdit() self.edit.textChanged.connect(self.change_value) layout.addWidget(self.edit) browse_btn = QPushButton('...') browse_btn.pressed.connect(self.browse) layout.addWidget(browse_btn) self.setFocusProxy(self.edit) return layout
def __init__(self, title, inner_templates: Iterable[NamedTemplate[T]] = None, frame_style=None, selector_cls: Union[Type[Selector], str] = None, layout_cls: Type[QBoxLayout] = None, **kwargs): """ :param title: the title :param inner_templates: an iterable of name-templates to act as key-value pairs :param frame_style: the frame style to apply to the encompassing frame, if any :param selector_cls: the class (or name) of a selector :param layout_cls: the class of the layout :param scrollable: whether to make the widget scrollable :param kwargs: forwarded to Fidget """ self.inner_templates = dict( self._to_name_subtemplate(o) for o in only_valid(inner_templates=inner_templates, INNER_TEMPLATES=self.INNER_TEMPLATES, _self=self)) FidgetTemplate.extract_default(*self.inner_templates.values(), sink=kwargs, upper_space=type(self), union=True) super().__init__(title, **kwargs) self.inners: Dict[str, Fidget[T]] = None self.selector: FidgetStacked.Selector = None selector_cls = first_valid(selector_cls=selector_cls, SELECTOR_CLS=self.SELECTOR_CLS, _self=self) if isinstance(selector_cls, str): selector_cls = self.selectors[selector_cls] self.selector_cls = selector_cls self.stacked: QStackedWidget = None self.init_ui(frame_style=frame_style, layout_cls=layout_cls)
def init_ui(self, layout_cls=None, ok_text=None, cancel_text=None, modality=None, pre_widget=None, post_widget=None): super().init_ui() layout_cls = first_valid(layout_cls=layout_cls, LAYOUT_CLS=self.LAYOUT_CLS, _self=self) layout: QBoxLayout = layout_cls(self) with self.setup_provided(layout): self.browse_btn = QPushButton('...') self.browse_btn.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed) self.browse_btn.clicked.connect(self._browse_btn_clicked) layout.addWidget(self.browse_btn) self.outer = self.outer_template() self.outer.on_change.connect(self.change_value) layout.addWidget(self.outer) self.question = FidgetQuestion(self.inner_template, parent=self) self.outer.add_plaintext_delegates(self.question) return layout
def __init__(self, title, options: Iterable[Union[Tuple[str, T], T]] = None, **kwargs): """ :param title: the title :param options: an iterable of options :param convert_func: a function to convert plaintext edited value to a value :param default_index: the default index of the ComboBox. ignored if a valid default_value is provided :param default_value: the default value of the ComboBox :param kwargs: forwarded to Fidget """ super().__init__(title, **kwargs) self.options = first_valid(options=options, OPTIONS=self.OPTIONS, _self=self) self._opt_lookup_name: Dict[str, Tuple[int, T]] = None self.combo_box: QComboBox = None self.init_ui()
def __init__(self, inner_template: TemplateLike[T] = None, outer_template: TemplateLike[T] = None, layout_cls=None, initial_value: T = NOT_INITIAL, **kwargs): inner_template = only_valid(inner_template=inner_template, INNER_TEMPLATE=self.INNER_TEMPLATE, _self=self).template_of() super().__init__(inner_template.title, **kwargs) self.inner_template = inner_template self.outer_template = only_valid(outer_template=outer_template, OUTER_TEMPLATE=self.OUTER_TEMPLATE, _self=self).template_of() self.browse_btn: QPushButton = None self.question: FidgetQuestion[T] = None self.outer: Fidget[T] = None self.__value = None self.init_ui(layout_cls=layout_cls) initial_value = first_valid(initial_value=initial_value, INITIAL_VALUE=self.INITIAL_VALUE, _invalid=self.NOT_INITIAL, _self=self) self.fill_value(initial_value)
def init_ui(self, layout_cls=None, scrollable=None): super().init_ui() layout_cls = first_valid(layout_cls=layout_cls, LAYOUT_CLS=self.LAYOUT_CLS, _self=self) owner = self scrollable = first_valid(scrollable=scrollable, SCROLLABLE=self.SCROLLABLE, _self=self) owner_layout = QVBoxLayout() owner.setLayout(owner_layout) if scrollable: owner = QScrollArea(owner) owner.setWidgetResizable(True) owner_layout.addWidget(owner) master = QWidget() master_layout = layout_cls(master) if scrollable: owner.setWidget(master) else: owner_layout.addWidget(master) self.inners = [] self.col_labels = [] self.row_btns = [] title_in_grid = not self.row_bounds.is_const self.col_offset = int(not self.row_bounds.is_const) if title_in_grid: exclude = (self.title_label, ) else: exclude = () with self.setup_provided( master_layout, exclude=exclude), self.suppress_update(call_on_exit=False): self.grid_layout = QGridLayout() field_names = [] for i, column_template in enumerate(self.inner_templates): title = column_template.title or '_' + str(i) label = QLabel(title) field_names.append(title) self.col_labels.append(label) self.grid_layout.addWidget(label, 0, i + self.col_offset) self.column_count = len(self.inner_templates) for i in range(self.row_bounds.initial): self.add_row(i) master_layout.addLayout(self.grid_layout) self.value_type = namedtuple(to_identifier(self.title), (to_identifier(i.title) for i in self.inners), rename=True) if title_in_grid and self.title_label: self.grid_layout.addWidget(self.title_label, 0, 0) # self.setLayout(master_layout) self.apply_matrix() return master_layout
def __init__(self, title, *args, validation_func: Callable[[T], None] = None, auto_func: Callable[[], T] = None, make_title: bool = None, make_indicator: bool = None, make_plaintext: bool = None, help: str = None, **kwargs): """ :param title: the title of the Fidget :param args: additional arguments forwarded to QWidget :param validation_func: a validation callable, that will raise ValidationError if the parsed value is invalid :param auto_func: a function that returns an automatic value, to fill in the UI :param make_title: whether to create a title widget :param make_indicator: whether to make an indicator widget :param make_plaintext: whether to make a plaintext_edit widget :param help: a help string to describe the widget :param kwargs: additional arguments forwarded to QWidget :inheritors: don't set default values for these parameters, change the uppercase class variables instead. """ if kwargs.get('flags', None) is None: kwargs['flags'] = self.FLAGS if 'flags' in kwargs and __backend__.wrapper == QtWrapper.PYSIDE: kwargs['f'] = kwargs.pop('flags') try: super().__init__(*args, **kwargs) except (TypeError, AttributeError): print(f'args: {args}, kwargs: {kwargs}') raise self.title = title self.help = help self.make_title = first_valid(make_title=make_title, MAKE_TITLE=self.MAKE_TITLE, _self=self) self.make_indicator = first_valid(make_indicator=make_indicator, MAKE_INDICATOR=self.MAKE_INDICATOR, _self=self) self.make_plaintext = first_valid(make_plaintext=make_plaintext, MAKE_PLAINTEXT=self.MAKE_PLAINTEXT, _self=self) self.indicator_label: Optional[QLabel] = None self.auto_button: Optional[QPushButton] = None self.plaintext_button: Optional[QPushButton] = None self.title_label: Optional[QLabel] = None self._plaintext_widget: Optional[PlaintextEditWidget[T]] = None self.validation_func = validation_func self.auto_func = optional_valid(auto_func=auto_func, AUTO_FUNC=self.AUTO_FUNC, _self=self) self._suppress_update = False self._value: FidgetValue[T] = None self._joined_plaintext_printer = None self._joined_plaintext_parser = None self._plaintext_printer_delegates: List[Callable[[], Iterable[PlaintextPrinter[T]]]] = [] self._plaintext_parser_delegates: List[Callable[[], Iterable[PlaintextParser[T]]]] = [] if self.auto_func: if self.fill is None: raise Exception('auto_func can only be used on a Fidget with an implemented fill method') else: self.make_auto = True else: self.make_auto = False
def init_ui(self, layout_cls=None, scrollable=None): super().init_ui() layout_cls = first_valid(layout_cls=layout_cls, LAYOUT_CLS=self.LAYOUT_CLS, _self=self) owner = self scrollable = first_valid(scrollable=scrollable, SCROLLABLE=self.SCROLLABLE, _self=self) owner_layout = QVBoxLayout() owner.setLayout(owner_layout) if scrollable: owner = QScrollArea(owner) owner.setWidgetResizable(True) owner_layout.addWidget(owner) master = QWidget() master_layout = layout_cls(master) if scrollable: owner.setWidget(master) else: owner_layout.addWidget(master) self.inners = [] self.col_btns = [] self.row_btns = [] title_in_grid = not (self.row_bounds.is_const or self.column_bounds.is_const) self.row_offset = int(not self.column_bounds.is_const) self.col_offset = int(not self.row_bounds.is_const) if title_in_grid: exclude = (self.title_label, ) else: exclude = () with self.setup_provided( master_layout, exclude=exclude), self.suppress_update(call_on_exit=False): self.grid_layout = QGridLayout() for i in range(self.row_bounds.initial): self.add_row(i) for i in range(self.column_bounds.initial): self.add_col(i) master_layout.addLayout(self.grid_layout) if title_in_grid and self.title_label: self.grid_layout.addWidget(self.title_label, 0, 0) # self.setLayout(master_layout) self.apply_matrix() return master_layout