From bbab7178c7ca1637ccdbcf7291a9209ebcd5954b Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 21 Sep 2020 11:53:27 +0200 Subject: [PATCH 1/7] DictWidget can be used as widget --- .../settings/settings/widgets/item_types.py | 43 +++++++++++++------ 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/pype/tools/settings/settings/widgets/item_types.py b/pype/tools/settings/settings/widgets/item_types.py index 68cebf6642..8a88fbf829 100644 --- a/pype/tools/settings/settings/widgets/item_types.py +++ b/pype/tools/settings/settings/widgets/item_types.py @@ -2132,18 +2132,26 @@ class DictWidget(QtWidgets.QWidget, SettingObject): self, input_data, parent, as_widget=False, label_widget=None, parent_widget=None ): - if as_widget: - raise TypeError("Can't use \"{}\" as widget item.".format( - self.__class__.__name__ - )) - if parent_widget is None: parent_widget = parent super(DictWidget, self).__init__(parent_widget) - self.setObjectName("DictWidget") self.initial_attributes(input_data, parent, as_widget) + self.input_fields = [] + + self.checkbox_widget = None + self.checkbox_key = input_data.get("checkbox_key") + + self.label_widget = label_widget + + if self.as_widget: + self._ui_as_widget(input_data) + else: + self._ui_as_item(input_data) + + def _ui_as_item(self, input_data): + self.key = input_data["key"] if input_data.get("highlight_content", False): content_state = "hightlighted" bottom_margin = 5 @@ -2151,10 +2159,6 @@ class DictWidget(QtWidgets.QWidget, SettingObject): content_state = "" bottom_margin = 0 - self.input_fields = [] - - self.key = input_data["key"] - main_layout = QtWidgets.QHBoxLayout(self) main_layout.setContentsMargins(0, 0, 0, 0) main_layout.setSpacing(0) @@ -2177,9 +2181,6 @@ class DictWidget(QtWidgets.QWidget, SettingObject): self.label_widget = body_widget.label_widget - self.checkbox_widget = None - self.checkbox_key = input_data.get("checkbox_key") - for child_data in input_data.get("children", []): self.add_children_gui(child_data) @@ -2194,6 +2195,22 @@ class DictWidget(QtWidgets.QWidget, SettingObject): else: body_widget.hide_toolbox(hide_content=False) + def _ui_as_widget(self, input_data): + body = QtWidgets.QWidget(self) + body.setObjectName("DictAsWidgetBody") + + content_layout = QtWidgets.QGridLayout(body) + content_layout.setContentsMargins(5, 5, 5, 5) + self.content_layout = content_layout + + layout = QtWidgets.QHBoxLayout(self) + layout.setContentsMargins(0, 0, 0, 0) + layout.setSpacing(5) + layout.addWidget(body) + + for child_configuration in input_data["children"]: + self.add_children_gui(child_configuration) + def add_children_gui(self, child_configuration): item_type = child_configuration["type"] klass = TypeToKlass.types.get(item_type) From bd5e1ae310168996eda083fc008b190d8f671a64 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 21 Sep 2020 11:55:16 +0200 Subject: [PATCH 2/7] minor tweaks in DictWidget to be able used as widget --- .../settings/settings/widgets/item_types.py | 63 ++++++++++++------- 1 file changed, 40 insertions(+), 23 deletions(-) diff --git a/pype/tools/settings/settings/widgets/item_types.py b/pype/tools/settings/settings/widgets/item_types.py index 8a88fbf829..83805d9948 100644 --- a/pype/tools/settings/settings/widgets/item_types.py +++ b/pype/tools/settings/settings/widgets/item_types.py @@ -2297,8 +2297,12 @@ class DictWidget(QtWidgets.QWidget, SettingObject): item.set_as_overriden() def update_default_values(self, parent_values): + # Make sure this is set to False + self._state = None + self._child_state = None + value = NOT_SET - if self._as_widget: + if self.as_widget: value = parent_values elif parent_values is not NOT_SET: value = parent_values.get(self.key, NOT_SET) @@ -2307,15 +2311,21 @@ class DictWidget(QtWidgets.QWidget, SettingObject): item.update_default_values(value) def update_studio_values(self, parent_values): + # Make sure this is set to False + self._state = None + self._child_state = None value = NOT_SET - if parent_values is not NOT_SET: - value = parent_values.get(self.key, NOT_SET) + if self.as_widget: + value = parent_values + else: + if parent_values is not NOT_SET: + value = parent_values.get(self.key, NOT_SET) - self._has_studio_override = False - if self.is_group and value is not NOT_SET: - self._has_studio_override = True + self._has_studio_override = False + if self.is_group and value is not NOT_SET: + self._has_studio_override = True - self._had_studio_override = bool(self._has_studio_override) + self._had_studio_override = bool(self._has_studio_override) for item in self.input_fields: item.update_studio_values(value) @@ -2325,37 +2335,40 @@ class DictWidget(QtWidgets.QWidget, SettingObject): self._state = None self._child_state = None - metadata = {} - groups = tuple() - override_values = NOT_SET - if parent_values is not NOT_SET: - metadata = parent_values.get(METADATA_KEY) or metadata - groups = metadata.get("groups") or groups - override_values = parent_values.get(self.key, override_values) + if not self.as_widget: + metadata = {} + groups = tuple() + override_values = NOT_SET + if parent_values is not NOT_SET: + metadata = parent_values.get(METADATA_KEY) or metadata + groups = metadata.get("groups") or groups + override_values = parent_values.get(self.key, override_values) - self._is_overriden = self.key in groups + self._is_overriden = self.key in groups for item in self.input_fields: item.apply_overrides(override_values) - if not self._is_overriden: - self._is_overriden = ( - self.is_group - and self.is_overidable - and self.child_overriden - ) - self._was_overriden = bool(self._is_overriden) + if not self.as_widget: + if not self._is_overriden: + self._is_overriden = ( + self.is_group + and self.is_overidable + and self.child_overriden + ) + self._was_overriden = bool(self._is_overriden) def _on_value_change(self, item=None): if self.ignore_value_changes: return - if self.is_group and not self.any_parent_as_widget: + if self.is_group and not (self.as_widget or self.any_parent_as_widget): if self.is_overidable: self._is_overriden = True else: self._has_studio_override = True + # TODO check if this is required self.hierarchical_style_update() self.value_changed.emit(self) @@ -2368,6 +2381,10 @@ class DictWidget(QtWidgets.QWidget, SettingObject): self.update_style() def update_style(self, is_overriden=None): + # TODO add style update when used as widget + if self.as_widget: + return + child_has_studio_override = self.child_has_studio_override child_modified = self.child_modified child_invalid = self.child_invalid From cbbbefc76dd939cbd5e327086825f4eb5d508033 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 21 Sep 2020 11:56:25 +0200 Subject: [PATCH 3/7] "dict-item" is set to DictWidget for backwards compatibility --- pype/tools/settings/settings/widgets/item_types.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pype/tools/settings/settings/widgets/item_types.py b/pype/tools/settings/settings/widgets/item_types.py index 83805d9948..e6fb2d32e3 100644 --- a/pype/tools/settings/settings/widgets/item_types.py +++ b/pype/tools/settings/settings/widgets/item_types.py @@ -3387,7 +3387,8 @@ TypeToKlass.types["path-input"] = PathInputWidget TypeToKlass.types["raw-json"] = RawJsonWidget TypeToKlass.types["list"] = ListWidget TypeToKlass.types["dict-modifiable"] = ModifiableDict -TypeToKlass.types["dict-item"] = DictItemWidget +# DEPRECATED - remove when removed from schemas +TypeToKlass.types["dict-item"] = DictWidget TypeToKlass.types["dict"] = DictWidget TypeToKlass.types["dict-invisible"] = DictInvisible TypeToKlass.types["path-widget"] = PathWidget From 4bd7a6c4fa2ddabf5a90e0ec39d80c970e069da8 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 21 Sep 2020 11:56:45 +0200 Subject: [PATCH 4/7] removed DictItemWidget as is not used --- .../settings/settings/widgets/item_types.py | 95 ------------------- 1 file changed, 95 deletions(-) diff --git a/pype/tools/settings/settings/widgets/item_types.py b/pype/tools/settings/settings/widgets/item_types.py index e6fb2d32e3..3cf9cfcc74 100644 --- a/pype/tools/settings/settings/widgets/item_types.py +++ b/pype/tools/settings/settings/widgets/item_types.py @@ -1192,101 +1192,6 @@ class RawJsonWidget(QtWidgets.QWidget, InputObject): return self.text_input.json_value() -class DictItemWidget(QtWidgets.QWidget, SettingObject): - default_input_value = True - value_changed = QtCore.Signal(object) - - def __init__( - self, input_data, parent, - as_widget=False, label_widget=None, parent_widget=None - ): - if parent_widget is None: - parent_widget = parent - super(DictItemWidget, self).__init__(parent_widget) - - self.initial_attributes(input_data, parent, as_widget) - - if not self._as_widget: - raise TypeError("{} can be used only as widget.".format( - self.__class__.__name__ - )) - - self.input_fields = [] - - body = QtWidgets.QWidget(self) - body.setObjectName("DictItemWidgetBody") - - content_layout = QtWidgets.QGridLayout(body) - content_layout.setContentsMargins(5, 5, 5, 5) - self.content_layout = content_layout - - layout = QtWidgets.QHBoxLayout(self) - layout.setContentsMargins(0, 0, 0, 0) - layout.setSpacing(5) - layout.addWidget(body) - - self.label_widget = label_widget - - for child_configuration in input_data["children"]: - self.add_children_gui(child_configuration) - - def add_children_gui(self, child_configuration): - item_type = child_configuration["type"] - klass = TypeToKlass.types.get(item_type) - - row = self.content_layout.rowCount() - if not getattr(klass, "is_input_type", False): - item = klass(child_configuration, self) - self.content_layout.addWidget(item, row, 0, 1, 2) - return item - - label_widget = None - if not klass.expand_in_grid: - label = child_configuration.get("label") - if label is not None: - label_widget = QtWidgets.QLabel(label, self) - self.content_layout.addWidget( - label_widget, row, 0, 1, 1, - alignment=QtCore.Qt.AlignRight | QtCore.Qt.AlignTop - ) - - item = klass(child_configuration, self, label_widget=label_widget) - item.value_changed.connect(self._on_value_change) - - if label_widget: - self.content_layout.addWidget(item, row, 1, 1, 1) - else: - self.content_layout.addWidget(item, row, 0, 1, 2) - - self.input_fields.append(item) - return item - - def hierarchical_style_update(self): - for input_field in self.input_fields: - input_field.hierarchical_style_update() - - def _on_value_change(self, item=None): - self.value_changed.emit(self) - - def update_default_values(self, parent_values): - for input_field in self.input_fields: - input_field.update_default_values(parent_values) - - def update_studio_values(self, parent_values): - for input_field in self.input_fields: - input_field.update_studio_values(parent_values) - - def apply_overrides(self, parent_values): - for input_field in self.input_fields: - input_field.apply_overrides(parent_values) - - def item_value(self): - output = {} - for input_field in self.input_fields: - output.update(input_field.config_value()) - return output - - class ListItem(QtWidgets.QWidget, SettingObject): _btn_size = 20 value_changed = QtCore.Signal(object) From ba8b1b8015b5821996b1b4140d6d2831c1394f03 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 21 Sep 2020 11:57:00 +0200 Subject: [PATCH 5/7] changed object name in styles --- pype/tools/settings/settings/style/style.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/tools/settings/settings/style/style.css b/pype/tools/settings/settings/style/style.css index 221f297219..3f648abef8 100644 --- a/pype/tools/settings/settings/style/style.css +++ b/pype/tools/settings/settings/style/style.css @@ -152,7 +152,7 @@ QPushButton[btn-type="expand-toggle"] { background: #141a1f; } -#DictItemWidgetBody{ +#DictAsWidgetBody{ background: transparent; border: 2px solid #cccccc; border-radius: 5px; From 14a15c9a8cbedae0641583869b552a8a84af78b1 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 21 Sep 2020 11:57:35 +0200 Subject: [PATCH 6/7] current schemas in example does not have dict-item --- .../gui_schemas/projects_schema/1_plugins_gui_schema.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pype/tools/settings/settings/gui_schemas/projects_schema/1_plugins_gui_schema.json b/pype/tools/settings/settings/gui_schemas/projects_schema/1_plugins_gui_schema.json index f70495017e..f357b51dc5 100644 --- a/pype/tools/settings/settings/gui_schemas/projects_schema/1_plugins_gui_schema.json +++ b/pype/tools/settings/settings/gui_schemas/projects_schema/1_plugins_gui_schema.json @@ -172,7 +172,7 @@ "type": "list", "key": "profiles", "label": "Profiles", - "object_type": "dict-item", + "object_type": "dict", "input_modifiers": { "children": [ { @@ -192,7 +192,7 @@ "label": "Output Definitions", "type": "dict-modifiable", "highlight_content": true, - "object_type": "dict-item", + "object_type": "dict", "input_modifiers": { "children": [ { From 7361e86cb9341d9b92e092920711091a71342463 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 21 Sep 2020 12:04:50 +0200 Subject: [PATCH 7/7] added new usage to readme --- pype/tools/settings/settings/README.md | 43 +++++++++++++++++++++----- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/pype/tools/settings/settings/README.md b/pype/tools/settings/settings/README.md index db444eb3bd..969c9dc574 100644 --- a/pype/tools/settings/settings/README.md +++ b/pype/tools/settings/settings/README.md @@ -57,13 +57,18 @@ ## dict - this is another dictionary input wrapping more inputs but visually makes them different -- required keys are `"key"` under which will be stored and `"label"` which will be shown in GUI -- this input can be expandable - - that can be set with key `"expandable"` as `True`/`False` (Default: `True`) - - with key `"expanded"` as `True`/`False` can be set that is expanded when GUI is opened (Default: `False`) -- it is possible to add darker background with `"highlight_content"` (Default: `False`) - - darker background has limits of maximum applies after 3-4 nested highlighted items there is not difference in the color +- item may be used as widget (in `list` or `dict-modifiable`) + - in that case the only key modifier is `children` which is list of it's keys + - USAGE: e.g. List of dictionaries where each dictionary have same structure. +- item options if is not used as widget + - required keys are `"key"` under which will be stored and `"label"` which will be shown in GUI + - this input can be expandable + - that can be set with key `"expandable"` as `True`/`False` (Default: `True`) + - with key `"expanded"` as `True`/`False` can be set that is expanded when GUI is opened (Default: `False`) + - it is possible to add darker background with `"highlight_content"` (Default: `False`) + - darker background has limits of maximum applies after 3-4 nested highlighted items there is not difference in the color ``` +# Example { "key": "applications", "type": "dict", @@ -76,6 +81,30 @@ ...ITEMS... ] } + +# When used as widget +{ + "type": "list", + "key": "profiles", + "label": "Profiles", + "object_type": "dict-item", + "input_modifiers": { + "children": [ + { + "key": "families", + "label": "Families", + "type": "list", + "object_type": "text" + }, { + "key": "hosts", + "label": "Hosts", + "type": "list", + "object_type": "text" + } + ... + ] + } +} ``` ## Inputs for setting any kind of value (`Pure` inputs) @@ -234,7 +263,7 @@ - should wraps multiple inputs only visually - these does not have `"key"` key and do not allow to have `"is_file"` or `"is_group"` modifiers enabled -### dict-form +### form - DEPRECATED - may be used only in `dict` and `dict-invisible` where is currently used grid layout so form is not needed - item is kept as still may be used in specific cases