From 6ed7ebebceb47fc2dc829b6b9cd96a8eff7fa509 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 18 Oct 2023 16:32:29 +0200 Subject: [PATCH 1/4] 'NumberAttrWidget' shows 'Multiselection' label on multiselection --- openpype/tools/attribute_defs/widgets.py | 66 ++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 4 deletions(-) diff --git a/openpype/tools/attribute_defs/widgets.py b/openpype/tools/attribute_defs/widgets.py index d9c55f4a640..738f036b80a 100644 --- a/openpype/tools/attribute_defs/widgets.py +++ b/openpype/tools/attribute_defs/widgets.py @@ -20,6 +20,7 @@ FocusSpinBox, FocusDoubleSpinBox, MultiSelectionComboBox, + ClickableFrame, ) from openpype.widgets.nice_checkbox import NiceCheckbox @@ -251,6 +252,30 @@ def _ui_init(self): self.main_layout.addWidget(input_widget, 0) +class ClickableLineEdit(QtWidgets.QLineEdit): + clicked = QtCore.Signal() + + def __init__(self, text, parent): + super(ClickableLineEdit, self).__init__(parent) + self.setText(text) + self.setReadOnly(True) + + self._mouse_pressed = False + + def mousePressEvent(self, event): + if event.button() == QtCore.Qt.LeftButton: + self._mouse_pressed = True + super(ClickableLineEdit, self).mousePressEvent(event) + + def mouseReleaseEvent(self, event): + if self._mouse_pressed: + self._mouse_pressed = False + if self.rect().contains(event.pos()): + self.clicked.emit() + + super(ClickableLineEdit, self).mouseReleaseEvent(event) + + class NumberAttrWidget(_BaseAttrDefWidget): def _ui_init(self): decimals = self.attr_def.decimals @@ -271,19 +296,23 @@ def _ui_init(self): QtWidgets.QAbstractSpinBox.ButtonSymbols.NoButtons ) + multisel_widget = ClickableLineEdit("< Multiselection >", self) + input_widget.valueChanged.connect(self._on_value_change) + multisel_widget.clicked.connect(self._on_multi_click) self._input_widget = input_widget + self._multisel_widget = multisel_widget + self._last_multivalue = None self.main_layout.addWidget(input_widget, 0) - - def _on_value_change(self, new_value): - self.value_changed.emit(new_value, self.attr_def.id) + self.main_layout.addWidget(multisel_widget, 0) def current_value(self): return self._input_widget.value() def set_value(self, value, multivalue=False): + self._last_multivalue = None if multivalue: set_value = set(value) if None in set_value: @@ -291,13 +320,42 @@ def set_value(self, value, multivalue=False): set_value.add(self.attr_def.default) if len(set_value) > 1: - self._input_widget.setSpecialValueText("Multiselection") + self._last_multivalue = next(iter(set_value), None) + self._set_multiselection_visible(True) return value = tuple(set_value)[0] + self._set_multiselection_visible(False, False) + if self.current_value != value: self._input_widget.setValue(value) + def _on_value_change(self, new_value): + self.value_changed.emit(new_value, self.attr_def.id) + + def _on_multi_click(self): + self._set_multiselection_visible(False) + + def _set_multiselection_visible(self, visible, change_focus=True): + self._input_widget.setVisible(not visible) + self._multisel_widget.setVisible(visible) + if visible: + return + + # Change value once user clicked on the input field + if self._last_multivalue is None: + value = self.attr_def.default + else: + value = self._last_multivalue + self._input_widget.setValue(value) + if not change_focus: + return + # Change focus to input field and move cursor to the end + self._input_widget.setFocus(QtCore.Qt.MouseFocusReason) + line_edit = self._input_widget.lineEdit() + if line_edit is not None: + line_edit.setCursorPosition(len(line_edit.text())) + class TextAttrWidget(_BaseAttrDefWidget): def _ui_init(self): From cd11029665ad96f6d42b260d56b8d165b4aed299 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Thu, 19 Oct 2023 11:09:00 +0200 Subject: [PATCH 2/4] do not trigger value change signal when hiding multiselection label --- openpype/tools/attribute_defs/widgets.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openpype/tools/attribute_defs/widgets.py b/openpype/tools/attribute_defs/widgets.py index 738f036b80a..e05db6bed0d 100644 --- a/openpype/tools/attribute_defs/widgets.py +++ b/openpype/tools/attribute_defs/widgets.py @@ -347,7 +347,9 @@ def _set_multiselection_visible(self, visible, change_focus=True): value = self.attr_def.default else: value = self._last_multivalue + self._input_widget.blockSignals(True) self._input_widget.setValue(value) + self._input_widget.blockSignals(False) if not change_focus: return # Change focus to input field and move cursor to the end From e3a8050ced649fb8935190ec25cd265cda507fd5 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Thu, 19 Oct 2023 11:10:11 +0200 Subject: [PATCH 3/4] show multiselection label back on lost focus --- openpype/tools/attribute_defs/widgets.py | 28 +++++++++++++++++++----- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/openpype/tools/attribute_defs/widgets.py b/openpype/tools/attribute_defs/widgets.py index e05db6bed0d..46f8da317d3 100644 --- a/openpype/tools/attribute_defs/widgets.py +++ b/openpype/tools/attribute_defs/widgets.py @@ -295,6 +295,8 @@ def _ui_init(self): input_widget.setButtonSymbols( QtWidgets.QAbstractSpinBox.ButtonSymbols.NoButtons ) + input_line_edit = input_widget.lineEdit() + input_widget.installEventFilter(self) multisel_widget = ClickableLineEdit("< Multiselection >", self) @@ -302,12 +304,23 @@ def _ui_init(self): multisel_widget.clicked.connect(self._on_multi_click) self._input_widget = input_widget + self._input_line_edit = input_line_edit self._multisel_widget = multisel_widget self._last_multivalue = None + self._multivalue = False self.main_layout.addWidget(input_widget, 0) self.main_layout.addWidget(multisel_widget, 0) + def eventFilter(self, obj, event): + if ( + self._multivalue + and obj is self._input_widget + and event.type() == QtCore.QEvent.FocusOut + ): + self._set_multiselection_visible(True) + return False + def current_value(self): return self._input_widget.value() @@ -322,21 +335,24 @@ def set_value(self, value, multivalue=False): if len(set_value) > 1: self._last_multivalue = next(iter(set_value), None) self._set_multiselection_visible(True) + self._multivalue = True return value = tuple(set_value)[0] - self._set_multiselection_visible(False, False) + self._multivalue = False + self._set_multiselection_visible(False) if self.current_value != value: self._input_widget.setValue(value) def _on_value_change(self, new_value): + self._multivalue = False self.value_changed.emit(new_value, self.attr_def.id) def _on_multi_click(self): - self._set_multiselection_visible(False) + self._set_multiselection_visible(False, True) - def _set_multiselection_visible(self, visible, change_focus=True): + def _set_multiselection_visible(self, visible, change_focus=False): self._input_widget.setVisible(not visible) self._multisel_widget.setVisible(visible) if visible: @@ -354,9 +370,9 @@ def _set_multiselection_visible(self, visible, change_focus=True): return # Change focus to input field and move cursor to the end self._input_widget.setFocus(QtCore.Qt.MouseFocusReason) - line_edit = self._input_widget.lineEdit() - if line_edit is not None: - line_edit.setCursorPosition(len(line_edit.text())) + self._input_line_edit.setCursorPosition( + len(self._input_line_edit.text()) + ) class TextAttrWidget(_BaseAttrDefWidget): From 63e983412cc2e438153c093539a679c76486c0b9 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Thu, 19 Oct 2023 11:10:19 +0200 Subject: [PATCH 4/4] removed unused import --- openpype/tools/attribute_defs/widgets.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/tools/attribute_defs/widgets.py b/openpype/tools/attribute_defs/widgets.py index 46f8da317d3..91b5b229deb 100644 --- a/openpype/tools/attribute_defs/widgets.py +++ b/openpype/tools/attribute_defs/widgets.py @@ -20,7 +20,6 @@ FocusSpinBox, FocusDoubleSpinBox, MultiSelectionComboBox, - ClickableFrame, ) from openpype.widgets.nice_checkbox import NiceCheckbox