From e24c2f853b5b976e1c441470cf6e7f435e2c0815 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 21 Nov 2022 19:15:34 +0100 Subject: [PATCH 01/27] attribute definitions can be hidden and disabled --- openpype/lib/attribute_definitions.py | 32 +++++++++++++++++++++------ 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/openpype/lib/attribute_definitions.py b/openpype/lib/attribute_definitions.py index 6baeaec045..ed151bbe4e 100644 --- a/openpype/lib/attribute_definitions.py +++ b/openpype/lib/attribute_definitions.py @@ -105,11 +105,14 @@ class AbtractAttrDef(object): How to force to set `key` attribute? Args: - key(str): Under which key will be attribute value stored. - label(str): Attribute label. - tooltip(str): Attribute tooltip. - is_label_horizontal(bool): UI specific argument. Specify if label is + key (str): Under which key will be attribute value stored. + default (Any): Default value of an attribute. + label (str): Attribute label. + tooltip (str): Attribute tooltip. + is_label_horizontal (bool): UI specific argument. Specify if label is next to value input or ahead. + hidden (bool): Will be item hidden (for UI purposes). + disabled (bool): Item will be visible but disabled (for UI purposes). """ type_attributes = [] @@ -117,16 +120,29 @@ class AbtractAttrDef(object): is_value_def = True def __init__( - self, key, default, label=None, tooltip=None, is_label_horizontal=None + self, + key, + default, + label=None, + tooltip=None, + is_label_horizontal=None, + hidden=False, + disabled=False ): if is_label_horizontal is None: is_label_horizontal = True + + if hidden is None: + hidden = False + self.key = key self.label = label self.tooltip = tooltip self.default = default self.is_label_horizontal = is_label_horizontal - self._id = uuid.uuid4() + self.hidden = hidden + self.disabled = disabled + self._id = uuid.uuid4().hex self.__init__class__ = AbtractAttrDef @@ -173,7 +189,9 @@ class AbtractAttrDef(object): "label": self.label, "tooltip": self.tooltip, "default": self.default, - "is_label_horizontal": self.is_label_horizontal + "is_label_horizontal": self.is_label_horizontal, + "hidden": self.hidden, + "disabled": self.disabled } for attr in self.type_attributes: data[attr] = getattr(self, attr) From 6abfa14e01d67eae20e7bb66c219feab99d70a37 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 21 Nov 2022 19:16:02 +0100 Subject: [PATCH 02/27] added special definition for hidden values --- openpype/lib/attribute_definitions.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/openpype/lib/attribute_definitions.py b/openpype/lib/attribute_definitions.py index ed151bbe4e..0df7b16e64 100644 --- a/openpype/lib/attribute_definitions.py +++ b/openpype/lib/attribute_definitions.py @@ -253,6 +253,26 @@ class UnknownDef(AbtractAttrDef): return value +class HiddenDef(AbtractAttrDef): + """Hidden value of Any type. + + This attribute can be used for UI purposes to pass values related + to other attributes (e.g. in multi-page UIs). + + Keep in mind the value should be possible to parse by json parser. + """ + + type = "hidden" + + def __init__(self, key, default=None, **kwargs): + kwargs["default"] = default + kwargs["hidden"] = True + super(UnknownDef, self).__init__(key, **kwargs) + + def convert_value(self, value): + return value + + class NumberDef(AbtractAttrDef): """Number definition. From fe392aa5db267ef09e0152d867eb02e45fee065e Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 21 Nov 2022 19:16:41 +0100 Subject: [PATCH 03/27] implemented hidden widget --- openpype/tools/attribute_defs/widgets.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/openpype/tools/attribute_defs/widgets.py b/openpype/tools/attribute_defs/widgets.py index dc697b08a6..7f7c20009e 100644 --- a/openpype/tools/attribute_defs/widgets.py +++ b/openpype/tools/attribute_defs/widgets.py @@ -6,6 +6,7 @@ from Qt import QtWidgets, QtCore from openpype.lib.attribute_definitions import ( AbtractAttrDef, UnknownDef, + HiddenDef, NumberDef, TextDef, EnumDef, @@ -459,6 +460,29 @@ class UnknownAttrWidget(_BaseAttrDefWidget): self._input_widget.setText(str_value) +class HiddenAttrWidget(_BaseAttrDefWidget): + def _ui_init(self): + self.setVisible(False) + self._value = None + self._multivalue = False + + def setVisible(self, visible): + if visible: + visible = False + super(HiddenAttrWidget, self).setVisible(visible) + + def current_value(self): + if self._multivalue: + raise ValueError( + "{} can't output for multivalue.".format(self.__class__.__name__) + ) + return self._value + + def set_value(self, value, multivalue=False): + self._value = copy.deepcopy(value) + self._multivalue = multivalue + + class FileAttrWidget(_BaseAttrDefWidget): def _ui_init(self): input_widget = FilesWidget( From 068ec3f89809eca1fcff32d81e36158f88dc248a Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 21 Nov 2022 19:17:09 +0100 Subject: [PATCH 04/27] enhanced attribute definitons widget --- openpype/tools/attribute_defs/widgets.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/openpype/tools/attribute_defs/widgets.py b/openpype/tools/attribute_defs/widgets.py index 7f7c20009e..6db6da58e1 100644 --- a/openpype/tools/attribute_defs/widgets.py +++ b/openpype/tools/attribute_defs/widgets.py @@ -23,6 +23,16 @@ from .files_widget import FilesWidget def create_widget_for_attr_def(attr_def, parent=None): + widget = _create_widget_for_attr_def(attr_def, parent) + if attr_def.hidden: + widget.setVisible(False) + + if attr_def.disabled: + widget.setEnabled(False) + return widget + + +def _create_widget_for_attr_def(attr_def, parent=None): if not isinstance(attr_def, AbtractAttrDef): raise TypeError("Unexpected type \"{}\" expected \"{}\"".format( str(type(attr_def)), AbtractAttrDef @@ -43,6 +53,9 @@ def create_widget_for_attr_def(attr_def, parent=None): if isinstance(attr_def, UnknownDef): return UnknownAttrWidget(attr_def, parent) + if isinstance(attr_def, HiddenDef): + return HiddenAttrWidget(attr_def, parent) + if isinstance(attr_def, FileDef): return FileAttrWidget(attr_def, parent) @@ -116,6 +129,10 @@ class AttributeDefinitionsWidget(QtWidgets.QWidget): self._current_keys.add(attr_def.key) widget = create_widget_for_attr_def(attr_def, self) + self._widgets.append(widget) + + if attr_def.hidden: + continue expand_cols = 2 if attr_def.is_value_def and attr_def.is_label_horizontal: @@ -134,7 +151,6 @@ class AttributeDefinitionsWidget(QtWidgets.QWidget): layout.addWidget( widget, row, col_num, 1, expand_cols ) - self._widgets.append(widget) row += 1 def set_value(self, value): From a606de5b76b63a6051731f292daa7b0420bfbbde Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 21 Nov 2022 19:17:56 +0100 Subject: [PATCH 05/27] don't add hidden widgets to publisher widgets --- openpype/tools/publisher/widgets/widgets.py | 26 +++++++++++++++------ 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/openpype/tools/publisher/widgets/widgets.py b/openpype/tools/publisher/widgets/widgets.py index ce3d91ce63..a0d97245ba 100644 --- a/openpype/tools/publisher/widgets/widgets.py +++ b/openpype/tools/publisher/widgets/widgets.py @@ -9,6 +9,7 @@ import collections from Qt import QtWidgets, QtCore, QtGui import qtawesome +from openpype.lib.attribute_definitions import UnknownDef from openpype.tools.attribute_defs import create_widget_for_attr_def from openpype.tools import resources from openpype.tools.flickcharm import FlickCharm @@ -1303,6 +1304,13 @@ class CreatorAttrsWidget(QtWidgets.QWidget): else: widget.set_value(values, True) + widget.value_changed.connect(self._input_value_changed) + self._attr_def_id_to_instances[attr_def.id] = attr_instances + self._attr_def_id_to_attr_def[attr_def.id] = attr_def + + if attr_def.hidden: + continue + expand_cols = 2 if attr_def.is_value_def and attr_def.is_label_horizontal: expand_cols = 1 @@ -1321,13 +1329,8 @@ class CreatorAttrsWidget(QtWidgets.QWidget): content_layout.addWidget( widget, row, col_num, 1, expand_cols ) - row += 1 - widget.value_changed.connect(self._input_value_changed) - self._attr_def_id_to_instances[attr_def.id] = attr_instances - self._attr_def_id_to_attr_def[attr_def.id] = attr_def - self._scroll_area.setWidget(content_widget) self._content_widget = content_widget @@ -1421,8 +1424,17 @@ class PublishPluginAttrsWidget(QtWidgets.QWidget): widget = create_widget_for_attr_def( attr_def, content_widget ) - label = attr_def.label or attr_def.key - content_layout.addRow(label, widget) + hidden_widget = attr_def.hidden + # Hide unknown values of publish plugins + # - The keys in most of cases does not represent what would + # label represent + if isinstance(attr_def, UnknownDef): + widget.setVisible(False) + hidden_widget = True + + if not hidden_widget: + label = attr_def.label or attr_def.key + content_layout.addRow(label, widget) widget.value_changed.connect(self._input_value_changed) From 29cc9bdce61ea3ce1dc01d17bb05c3a2db3afffe Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 21 Nov 2022 19:39:10 +0100 Subject: [PATCH 06/27] Fix line length --- openpype/tools/attribute_defs/widgets.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/tools/attribute_defs/widgets.py b/openpype/tools/attribute_defs/widgets.py index 6db6da58e1..1ffb3d3799 100644 --- a/openpype/tools/attribute_defs/widgets.py +++ b/openpype/tools/attribute_defs/widgets.py @@ -489,9 +489,9 @@ class HiddenAttrWidget(_BaseAttrDefWidget): def current_value(self): if self._multivalue: - raise ValueError( - "{} can't output for multivalue.".format(self.__class__.__name__) - ) + raise ValueError("{} can't output for multivalue.".format( + self.__class__.__name__ + )) return self._value def set_value(self, value, multivalue=False): From 996bd4897b80ae72a06a8bbc81c1b69d471485ac Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Tue, 22 Nov 2022 12:04:47 +0100 Subject: [PATCH 07/27] tabs widget can set current tab by index --- openpype/tools/publisher/widgets/tabs_widget.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/openpype/tools/publisher/widgets/tabs_widget.py b/openpype/tools/publisher/widgets/tabs_widget.py index 84638a002c..eb3eda8c19 100644 --- a/openpype/tools/publisher/widgets/tabs_widget.py +++ b/openpype/tools/publisher/widgets/tabs_widget.py @@ -68,7 +68,16 @@ class PublisherTabsWidget(QtWidgets.QFrame): self.set_current_tab(identifier) return button + def get_tab_by_index(self, index): + if index < 0 or index > self._btns_layout.count(): + return None + item = self._btns_layout.itemAt(index) + return item.widget() + def set_current_tab(self, identifier): + if isinstance(identifier, int): + identifier = self.get_tab_by_index(identifier) + if isinstance(identifier, PublisherTabBtn): identifier = identifier.identifier From 430f30c05e3dc53184277ed121efd0fdcd003b3a Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Tue, 22 Nov 2022 12:05:22 +0100 Subject: [PATCH 08/27] added helper methods to know on which tab we are --- openpype/tools/publisher/window.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/openpype/tools/publisher/window.py b/openpype/tools/publisher/window.py index f107c0e505..3879e37ad7 100644 --- a/openpype/tools/publisher/window.py +++ b/openpype/tools/publisher/window.py @@ -539,6 +539,18 @@ class PublisherWindow(QtWidgets.QDialog): def _go_to_report_tab(self): self._set_current_tab("report") + def _is_on_create_tab(self): + self._is_current_tab("create") + + def _is_on_publish_tab(self): + self._is_current_tab("publish") + + def _is_on_details_tab(self): + self._is_current_tab("details") + + def _is_on_report_tab(self): + self._is_current_tab("report") + def _set_publish_overlay_visibility(self, visible): if visible: widget = self._publish_overlay From ac9b9b208e055c856c32313a87d20bf1dbf403c3 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 22 Nov 2022 12:54:28 +0100 Subject: [PATCH 09/27] OP-4196 - safer getter for published_path published_path might be missing in case of thumbnail not getting published. This implementation takes from staging if published_path not present --- .../slack/plugins/publish/integrate_slack_api.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/openpype/modules/slack/plugins/publish/integrate_slack_api.py b/openpype/modules/slack/plugins/publish/integrate_slack_api.py index 643e55915b..f40a13db9f 100644 --- a/openpype/modules/slack/plugins/publish/integrate_slack_api.py +++ b/openpype/modules/slack/plugins/publish/integrate_slack_api.py @@ -142,13 +142,19 @@ class IntegrateSlackAPI(pyblish.api.InstancePlugin): def _get_thumbnail_path(self, instance): """Returns abs url for thumbnail if present in instance repres""" - published_path = None + thumbnail_path = None for repre in instance.data.get("representations", []): if repre.get('thumbnail') or "thumbnail" in repre.get('tags', []): - if os.path.exists(repre["published_path"]): - published_path = repre["published_path"] + self.log.info(repre) + repre_thumbnail_path = ( + repre.get("published_path") or + os.path.join(repre["stagingDir"], repre["files"]) + ) + if os.path.exists(repre_thumbnail_path): + self.log.info("exists") + thumbnail_path = repre_thumbnail_path break - return published_path + return thumbnail_path def _get_review_path(self, instance): """Returns abs url for review if present in instance repres""" From c61098b782492728f7dbbe667b2540b2805b35ba Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 22 Nov 2022 13:00:34 +0100 Subject: [PATCH 10/27] OP-4196 - fix when task_data is not dict In legacy cases task might be only string with its name, not structure with additional metadata (type etc.). This implementation handles that. --- .../modules/slack/plugins/publish/integrate_slack_api.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openpype/modules/slack/plugins/publish/integrate_slack_api.py b/openpype/modules/slack/plugins/publish/integrate_slack_api.py index f40a13db9f..6138671180 100644 --- a/openpype/modules/slack/plugins/publish/integrate_slack_api.py +++ b/openpype/modules/slack/plugins/publish/integrate_slack_api.py @@ -121,10 +121,13 @@ class IntegrateSlackAPI(pyblish.api.InstancePlugin): ): fill_pairs.append(("task", task_data["name"])) - else: + elif isinstance(task_data, dict): for key, value in task_data.items(): fill_key = "task[{}]".format(key) fill_pairs.append((fill_key, value)) + else: + # fallback for legacy - if task_data is only task name + fill_pairs.append(("task", task_data)) self.log.debug("fill_pairs ::{}".format(fill_pairs)) multiple_case_variants = prepare_template_data(fill_pairs) From f993842c4ec7a4e91b5a42cbd61ddba0f9387a35 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 22 Nov 2022 13:01:27 +0100 Subject: [PATCH 11/27] OP-4196 - remove unnecessary logging --- openpype/modules/slack/plugins/publish/integrate_slack_api.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/openpype/modules/slack/plugins/publish/integrate_slack_api.py b/openpype/modules/slack/plugins/publish/integrate_slack_api.py index 6138671180..e43b07b228 100644 --- a/openpype/modules/slack/plugins/publish/integrate_slack_api.py +++ b/openpype/modules/slack/plugins/publish/integrate_slack_api.py @@ -148,13 +148,11 @@ class IntegrateSlackAPI(pyblish.api.InstancePlugin): thumbnail_path = None for repre in instance.data.get("representations", []): if repre.get('thumbnail') or "thumbnail" in repre.get('tags', []): - self.log.info(repre) repre_thumbnail_path = ( repre.get("published_path") or os.path.join(repre["stagingDir"], repre["files"]) ) if os.path.exists(repre_thumbnail_path): - self.log.info("exists") thumbnail_path = repre_thumbnail_path break return thumbnail_path From ab17acddc7c192dab58727e87fe87b51e242a3df Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 22 Nov 2022 13:39:24 +0100 Subject: [PATCH 12/27] OP-4196 - better handling of data It should take task from instance anatomyData, then from context and handle non dict items. --- .../slack/plugins/publish/integrate_slack_api.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/openpype/modules/slack/plugins/publish/integrate_slack_api.py b/openpype/modules/slack/plugins/publish/integrate_slack_api.py index e43b07b228..2c6f3d21bd 100644 --- a/openpype/modules/slack/plugins/publish/integrate_slack_api.py +++ b/openpype/modules/slack/plugins/publish/integrate_slack_api.py @@ -112,7 +112,13 @@ class IntegrateSlackAPI(pyblish.api.InstancePlugin): if review_path: fill_pairs.append(("review_filepath", review_path)) - task_data = fill_data.get("task") + task_data = ( + copy.deepcopy(instance.data.get("anatomyData", [])).get("task") + or fill_data.get("task") + ) + if not isinstance(task_data, dict): + # fallback for legacy - if task_data is only task name + task_data["name"] = task_data if task_data: if ( "{task}" in message_templ @@ -121,13 +127,10 @@ class IntegrateSlackAPI(pyblish.api.InstancePlugin): ): fill_pairs.append(("task", task_data["name"])) - elif isinstance(task_data, dict): + else: for key, value in task_data.items(): fill_key = "task[{}]".format(key) fill_pairs.append((fill_key, value)) - else: - # fallback for legacy - if task_data is only task name - fill_pairs.append(("task", task_data)) self.log.debug("fill_pairs ::{}".format(fill_pairs)) multiple_case_variants = prepare_template_data(fill_pairs) From 3cd241d2dbfa56a43ae2199fb1c38bd236497cd1 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 22 Nov 2022 14:01:10 +0100 Subject: [PATCH 13/27] OP-4196 - fix wrong return type --- openpype/modules/slack/plugins/publish/integrate_slack_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/modules/slack/plugins/publish/integrate_slack_api.py b/openpype/modules/slack/plugins/publish/integrate_slack_api.py index 2c6f3d21bd..9539d03306 100644 --- a/openpype/modules/slack/plugins/publish/integrate_slack_api.py +++ b/openpype/modules/slack/plugins/publish/integrate_slack_api.py @@ -113,7 +113,7 @@ class IntegrateSlackAPI(pyblish.api.InstancePlugin): fill_pairs.append(("review_filepath", review_path)) task_data = ( - copy.deepcopy(instance.data.get("anatomyData", [])).get("task") + copy.deepcopy(instance.data.get("anatomyData", {})).get("task") or fill_data.get("task") ) if not isinstance(task_data, dict): From 788ed6478006c17644460945c9a60cc8207a036c Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Tue, 22 Nov 2022 15:50:46 +0100 Subject: [PATCH 14/27] fix typo --- openpype/tools/publisher/widgets/card_view_widgets.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/tools/publisher/widgets/card_view_widgets.py b/openpype/tools/publisher/widgets/card_view_widgets.py index 9fd2bf0824..72644c09db 100644 --- a/openpype/tools/publisher/widgets/card_view_widgets.py +++ b/openpype/tools/publisher/widgets/card_view_widgets.py @@ -674,9 +674,9 @@ class InstanceCardView(AbstractInstanceView): instances_by_group[group_name] ) - self._update_ordered_group_nameS() + self._update_ordered_group_names() - def _update_ordered_group_nameS(self): + def _update_ordered_group_names(self): ordered_group_names = [CONTEXT_GROUP] for idx in range(self._content_layout.count()): if idx > 0: From 3ba5f8e0e99798c62ec295ea2a3706f3da8aac37 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Tue, 22 Nov 2022 15:51:05 +0100 Subject: [PATCH 15/27] fix tas combobox sizes --- openpype/tools/publisher/widgets/widgets.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openpype/tools/publisher/widgets/widgets.py b/openpype/tools/publisher/widgets/widgets.py index ce3d91ce63..332e231653 100644 --- a/openpype/tools/publisher/widgets/widgets.py +++ b/openpype/tools/publisher/widgets/widgets.py @@ -578,6 +578,11 @@ class TasksCombobox(QtWidgets.QComboBox): self._text = None + # Make sure combobox is extended horizontally + size_policy = self.sizePolicy() + size_policy.setHorizontalPolicy(size_policy.MinimumExpanding) + self.setSizePolicy(size_policy) + def set_invalid_empty_task(self, invalid=True): self._proxy_model.set_filter_empty(invalid) if invalid: From b2065acd7a43724ecd522a9f14531f3a45df38ce Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Tue, 22 Nov 2022 15:51:44 +0100 Subject: [PATCH 16/27] added ability to know if views have any items --- .../publisher/widgets/card_view_widgets.py | 7 +++++++ .../publisher/widgets/list_view_widgets.py | 7 +++++++ .../tools/publisher/widgets/overview_widget.py | 4 ++++ openpype/tools/publisher/widgets/widgets.py | 17 ++++++++++++++++- 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/openpype/tools/publisher/widgets/card_view_widgets.py b/openpype/tools/publisher/widgets/card_view_widgets.py index 72644c09db..09635d1a15 100644 --- a/openpype/tools/publisher/widgets/card_view_widgets.py +++ b/openpype/tools/publisher/widgets/card_view_widgets.py @@ -676,6 +676,13 @@ class InstanceCardView(AbstractInstanceView): self._update_ordered_group_names() + def has_items(self): + if self._convertor_items_group is not None: + return True + if self._widgets_by_group: + return True + return False + def _update_ordered_group_names(self): ordered_group_names = [CONTEXT_GROUP] for idx in range(self._content_layout.count()): diff --git a/openpype/tools/publisher/widgets/list_view_widgets.py b/openpype/tools/publisher/widgets/list_view_widgets.py index 32d84862f0..1cdb4cdcdb 100644 --- a/openpype/tools/publisher/widgets/list_view_widgets.py +++ b/openpype/tools/publisher/widgets/list_view_widgets.py @@ -912,6 +912,13 @@ class InstanceListView(AbstractInstanceView): if not self._instance_view.isExpanded(proxy_index): self._instance_view.expand(proxy_index) + def has_items(self): + if self._convertor_group_widget is not None: + return True + if self._group_items: + return True + return False + def get_selected_items(self): """Get selected instance ids and context selection. diff --git a/openpype/tools/publisher/widgets/overview_widget.py b/openpype/tools/publisher/widgets/overview_widget.py index 1c924d1631..b1aeda9cd4 100644 --- a/openpype/tools/publisher/widgets/overview_widget.py +++ b/openpype/tools/publisher/widgets/overview_widget.py @@ -205,6 +205,10 @@ class OverviewWidget(QtWidgets.QFrame): self._subset_views_widget.height() ) + def has_items(self): + view = self._subset_views_layout.currentWidget() + return view.has_items() + def _on_create_clicked(self): """Pass signal to parent widget which should care about changing state. diff --git a/openpype/tools/publisher/widgets/widgets.py b/openpype/tools/publisher/widgets/widgets.py index 332e231653..d6c6f8673c 100644 --- a/openpype/tools/publisher/widgets/widgets.py +++ b/openpype/tools/publisher/widgets/widgets.py @@ -305,6 +305,20 @@ class AbstractInstanceView(QtWidgets.QWidget): "{} Method 'refresh' is not implemented." ).format(self.__class__.__name__)) + def has_items(self): + """View has at least one item. + + This is more a question for controller but is called from widget + which should probably should not use controller. + + Returns: + bool: There is at least one instance or conversion item. + """ + + raise NotImplementedError(( + "{} Method 'has_items' is not implemented." + ).format(self.__class__.__name__)) + def get_selected_items(self): """Selected instances required for callbacks. @@ -1185,7 +1199,7 @@ class GlobalAttrsWidget(QtWidgets.QWidget): """Set currently selected instances. Args: - instances(list): List of selected instances. + instances(List[CreatedInstance]): List of selected instances. Empty instances tells that nothing or context is selected. """ self._set_btns_visible(False) @@ -1619,6 +1633,7 @@ class SubsetAttributesWidget(QtWidgets.QWidget): instances(List[CreatedInstance]): List of currently selected instances. context_selected(bool): Is context selected. + convertor_identifiers(List[str]): Identifiers of convert items. """ all_valid = True From d87e8fe99c68c23a5fdf1ce19fc0debe654eee97 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Tue, 22 Nov 2022 15:52:06 +0100 Subject: [PATCH 17/27] tabs widget can accept tab indexes --- openpype/tools/publisher/widgets/tabs_widget.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/openpype/tools/publisher/widgets/tabs_widget.py b/openpype/tools/publisher/widgets/tabs_widget.py index eb3eda8c19..d8ad19cfc0 100644 --- a/openpype/tools/publisher/widgets/tabs_widget.py +++ b/openpype/tools/publisher/widgets/tabs_widget.py @@ -54,6 +54,9 @@ class PublisherTabsWidget(QtWidgets.QFrame): self._buttons_by_identifier = {} def is_current_tab(self, identifier): + if isinstance(identifier, int): + identifier = self.get_tab_by_index(identifier) + if isinstance(identifier, PublisherTabBtn): identifier = identifier.identifier return self._current_identifier == identifier @@ -69,10 +72,10 @@ class PublisherTabsWidget(QtWidgets.QFrame): return button def get_tab_by_index(self, index): - if index < 0 or index > self._btns_layout.count(): - return None - item = self._btns_layout.itemAt(index) - return item.widget() + if 0 >= index < self._btns_layout.count(): + item = self._btns_layout.itemAt(index) + return item.widget() + return None def set_current_tab(self, identifier): if isinstance(identifier, int): From dd50c6723e1ec892478205f72de2e0bf57940d35 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Tue, 22 Nov 2022 15:55:39 +0100 Subject: [PATCH 18/27] small teaks and fixes --- openpype/tools/publisher/window.py | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/openpype/tools/publisher/window.py b/openpype/tools/publisher/window.py index 3879e37ad7..59dd2e6ec9 100644 --- a/openpype/tools/publisher/window.py +++ b/openpype/tools/publisher/window.py @@ -432,7 +432,7 @@ class PublisherWindow(QtWidgets.QDialog): self._update_create_overlay_size() self._update_create_overlay_visibility() - if self._is_current_tab("create"): + if self._is_on_create_tab(): self._install_app_event_listener() # Reset if requested @@ -450,7 +450,7 @@ class PublisherWindow(QtWidgets.QDialog): self._context_label.setText(label) def _update_publish_details_widget(self, force=False): - if not force and not self._is_current_tab("details"): + if not force and not self._is_on_details_tab(): return report_data = self.controller.get_publish_report() @@ -540,16 +540,16 @@ class PublisherWindow(QtWidgets.QDialog): self._set_current_tab("report") def _is_on_create_tab(self): - self._is_current_tab("create") + return self._is_current_tab("create") def _is_on_publish_tab(self): - self._is_current_tab("publish") + return self._is_current_tab("publish") def _is_on_details_tab(self): - self._is_current_tab("details") + return self._is_current_tab("details") def _is_on_report_tab(self): - self._is_current_tab("report") + return self._is_current_tab("report") def _set_publish_overlay_visibility(self, visible): if visible: @@ -601,11 +601,8 @@ class PublisherWindow(QtWidgets.QDialog): self._set_publish_visibility(False) self._set_footer_enabled(False) self._update_publish_details_widget() - if ( - not self._is_current_tab("create") - and not self._is_current_tab("publish") ): - self._set_current_tab("publish") + self._go_to_publish_tab() def _on_publish_start(self): self._create_tab.setEnabled(False) @@ -621,8 +618,8 @@ class PublisherWindow(QtWidgets.QDialog): self._publish_details_widget.close_details_popup() - if self._is_current_tab(self._create_tab): - self._set_current_tab("publish") + if self._is_on_create_tab(): + self._go_to_publish_tab() def _on_publish_validated_change(self, event): if event["value"]: @@ -635,7 +632,7 @@ class PublisherWindow(QtWidgets.QDialog): publish_has_crashed = self._controller.publish_has_crashed validate_enabled = not publish_has_crashed publish_enabled = not publish_has_crashed - if self._is_current_tab("publish"): + if self._is_on_publish_tab(): self._go_to_report_tab() if validate_enabled: From caf94fb68f789d528e69cf6b423b29b20fe16369 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Tue, 22 Nov 2022 15:57:17 +0100 Subject: [PATCH 19/27] show publisher can accept tab to switch to --- openpype/tools/publisher/window.py | 62 +++++++++++++++++++++++++++++- openpype/tools/utils/host_tools.py | 16 ++++---- 2 files changed, 67 insertions(+), 11 deletions(-) diff --git a/openpype/tools/publisher/window.py b/openpype/tools/publisher/window.py index 59dd2e6ec9..0f7fd2c7e3 100644 --- a/openpype/tools/publisher/window.py +++ b/openpype/tools/publisher/window.py @@ -156,7 +156,7 @@ class PublisherWindow(QtWidgets.QDialog): footer_layout.addWidget(footer_bottom_widget, 0) # Content - # - wrap stacked widget under one more widget to be able propagate + # - wrap stacked widget under one more widget to be able to propagate # margins (QStackedLayout can't have margins) content_widget = QtWidgets.QWidget(under_publish_widget) @@ -267,6 +267,9 @@ class PublisherWindow(QtWidgets.QDialog): controller.event_system.add_callback( "publish.reset.finished", self._on_publish_reset ) + controller.event_system.add_callback( + "controller.reset.finished", self._on_controller_reset + ) controller.event_system.add_callback( "publish.process.started", self._on_publish_start ) @@ -337,11 +340,13 @@ class PublisherWindow(QtWidgets.QDialog): self._controller = controller self._first_show = True + self._first_reset = True # This is a little bit confusing but 'reset_on_first_show' is too long - # forin init + # for init self._reset_on_first_show = reset_on_show self._reset_on_show = True self._publish_frame_visible = None + self._tab_on_reset = None self._error_messages_to_show = collections.deque() self._errors_dialog_message_timer = errors_dialog_message_timer @@ -353,12 +358,21 @@ class PublisherWindow(QtWidgets.QDialog): self._show_timer = show_timer self._show_counter = 0 + self._window_is_visible = False @property def controller(self): return self._controller + def make_sure_is_visible(self): + if self._window_is_visible: + self.setWindowState(QtCore.Qt.ActiveWindow) + + else: + self.show() + def showEvent(self, event): + self._window_is_visible = True super(PublisherWindow, self).showEvent(event) if self._first_show: self._first_show = False @@ -372,6 +386,7 @@ class PublisherWindow(QtWidgets.QDialog): self._update_create_overlay_size() def closeEvent(self, event): + self._window_is_visible = False self._uninstall_app_event_listener() self.save_changes() self._reset_on_show = True @@ -449,6 +464,19 @@ class PublisherWindow(QtWidgets.QDialog): def set_context_label(self, label): self._context_label.setText(label) + def set_tab_on_reset(self, tab): + """Define tab that will be selected on window show. + + This is single use method, when publisher window is showed the value is + unset and not used on next show. + + Args: + tab (Union[int, Literal[create, publish, details, report]]: Index + or name of tab which will be selected on show (after reset). + """ + + self._tab_on_reset = tab + def _update_publish_details_widget(self, force=False): if not force and not self._is_on_details_tab(): return @@ -524,6 +552,11 @@ class PublisherWindow(QtWidgets.QDialog): def _set_current_tab(self, identifier): self._tabs_widget.set_current_tab(identifier) + def set_current_tab(self, tab): + self._set_current_tab(tab) + if not self._window_is_visible: + self.set_tab_on_reset(tab) + def _is_current_tab(self, identifier): return self._tabs_widget.is_current_tab(identifier) @@ -601,7 +634,32 @@ class PublisherWindow(QtWidgets.QDialog): self._set_publish_visibility(False) self._set_footer_enabled(False) self._update_publish_details_widget() + + def _on_controller_reset(self): + self._first_reset, first_reset = False, self._first_reset + if self._tab_on_reset is not None: + self._tab_on_reset, new_tab = None, self._tab_on_reset + self._set_current_tab(new_tab) + return + + # On first reset change tab based on available items + # - if there is at least one instance the tab is changed to 'publish' + # otherwise 'create' is used + # - this happens only on first show + if first_reset: + if self._overview_widget.has_items(): + self._go_to_publish_tab() + else: + self._go_to_create_tab() + + elif ( + not self._is_on_create_tab() + and not self._is_on_publish_tab() ): + # If current tab is not 'Create' or 'Publish' go to 'Publish' + # - this can happen when publishing started and was reset + # at that moment it doesn't make sense to stay at publish + # specific tabs. self._go_to_publish_tab() def _on_publish_start(self): diff --git a/openpype/tools/utils/host_tools.py b/openpype/tools/utils/host_tools.py index 046dcbdf6a..e8593a8ae2 100644 --- a/openpype/tools/utils/host_tools.py +++ b/openpype/tools/utils/host_tools.py @@ -285,14 +285,12 @@ class HostToolsHelper: return self._publisher_tool - def show_publisher_tool(self, parent=None, controller=None): + def show_publisher_tool(self, parent=None, controller=None, tab=None): with qt_app_context(): - dialog = self.get_publisher_tool(parent, controller) - - dialog.show() - dialog.raise_() - dialog.activateWindow() - dialog.showNormal() + window = self.get_publisher_tool(parent, controller) + if tab: + window.set_current_tab(tab) + window.make_sure_is_visible() def get_tool_by_name(self, tool_name, parent=None, *args, **kwargs): """Show tool by it's name. @@ -446,8 +444,8 @@ def show_publish(parent=None): _SingletonPoint.show_tool_by_name("publish", parent) -def show_publisher(parent=None): - _SingletonPoint.show_tool_by_name("publisher", parent) +def show_publisher(parent=None, **kwargs): + _SingletonPoint.show_tool_by_name("publisher", parent, **kwargs) def show_experimental_tools_dialog(parent=None): From 6af4412591b45f2001a9f01e998a36e871666ec9 Mon Sep 17 00:00:00 2001 From: clement hector Date: Tue, 22 Nov 2022 16:08:03 +0100 Subject: [PATCH 20/27] set creator window as parent of pop up window --- .../hosts/photoshop/plugins/create/create_legacy_image.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/photoshop/plugins/create/create_legacy_image.py b/openpype/hosts/photoshop/plugins/create/create_legacy_image.py index 2792a775e0..7672458165 100644 --- a/openpype/hosts/photoshop/plugins/create/create_legacy_image.py +++ b/openpype/hosts/photoshop/plugins/create/create_legacy_image.py @@ -29,7 +29,8 @@ class CreateImage(create.LegacyCreator): if len(selection) > 1: # Ask user whether to create one image or image per selected # item. - msg_box = QtWidgets.QMessageBox() + active_window = QtWidgets.QApplication.activeWindow() + msg_box = QtWidgets.QMessageBox(parent=active_window) msg_box.setIcon(QtWidgets.QMessageBox.Warning) msg_box.setText( "Multiple layers selected." @@ -102,7 +103,7 @@ class CreateImage(create.LegacyCreator): if group.long_name: for directory in group.long_name[::-1]: name = directory.replace(stub.PUBLISH_ICON, '').\ - replace(stub.LOADED_ICON, '') + replace(stub.LOADED_ICON, '') long_names.append(name) self.data.update({"subset": subset_name}) From 861cdadc9bbcd171da0d8793de6595db8446efce Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Tue, 22 Nov 2022 16:48:02 +0100 Subject: [PATCH 21/27] fix formatting --- openpype/tools/publisher/widgets/widgets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/tools/publisher/widgets/widgets.py b/openpype/tools/publisher/widgets/widgets.py index d6c6f8673c..6bc09c55a3 100644 --- a/openpype/tools/publisher/widgets/widgets.py +++ b/openpype/tools/publisher/widgets/widgets.py @@ -316,7 +316,7 @@ class AbstractInstanceView(QtWidgets.QWidget): """ raise NotImplementedError(( - "{} Method 'has_items' is not implemented." + "{} Method 'has_items' is not implemented." ).format(self.__class__.__name__)) def get_selected_items(self): From 3b81c7f5731dfc5c018bff11e9758fc3e5e26450 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 22 Nov 2022 18:15:27 +0100 Subject: [PATCH 22/27] OP-4196 - better logging of file upload errors --- .../slack/plugins/publish/integrate_slack_api.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/openpype/modules/slack/plugins/publish/integrate_slack_api.py b/openpype/modules/slack/plugins/publish/integrate_slack_api.py index 9539d03306..0cd5ec9de8 100644 --- a/openpype/modules/slack/plugins/publish/integrate_slack_api.py +++ b/openpype/modules/slack/plugins/publish/integrate_slack_api.py @@ -188,10 +188,17 @@ class IntegrateSlackAPI(pyblish.api.InstancePlugin): channel=channel, title=os.path.basename(p_file) ) - attachment_str += "\n<{}|{}>".format( - response["file"]["permalink"], - os.path.basename(p_file)) - file_ids.append(response["file"]["id"]) + if response.get("error"): + error_str = self._enrich_error( + str(response.get("error")), + channel) + self.log.warning( + "Error happened: {}".format(error_str)) + else: + attachment_str += "\n<{}|{}>".format( + response["file"]["permalink"], + os.path.basename(p_file)) + file_ids.append(response["file"]["id"]) if publish_files: message += attachment_str From 855e7d1c61c16093706b276435aed02fbb108e91 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 22 Nov 2022 18:28:01 +0100 Subject: [PATCH 23/27] OP-4196 - fix filtering profiles Task types didn't work. --- .../modules/slack/plugins/publish/collect_slack_family.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/modules/slack/plugins/publish/collect_slack_family.py b/openpype/modules/slack/plugins/publish/collect_slack_family.py index 39b05937dc..27e899d59a 100644 --- a/openpype/modules/slack/plugins/publish/collect_slack_family.py +++ b/openpype/modules/slack/plugins/publish/collect_slack_family.py @@ -18,15 +18,15 @@ class CollectSlackFamilies(pyblish.api.InstancePlugin): profiles = None def process(self, instance): - task_name = legacy_io.Session.get("AVALON_TASK") + task_data = instance.data["anatomyData"].get("task", {}) family = self.main_family_from_instance(instance) key_values = { "families": family, - "tasks": task_name, + "tasks": task_data.get("name"), + "task_types": task_data.get("type"), "hosts": instance.data["anatomyData"]["app"], "subsets": instance.data["subset"] } - profile = filter_profiles(self.profiles, key_values, logger=self.log) From c3e5b7a169c670b35889a5fb0038ba4b50bf7841 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 22 Nov 2022 21:21:42 +0100 Subject: [PATCH 24/27] update history.md --- HISTORY.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index f6cc74e114..7365696f96 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,40 @@ # Changelog +## [3.14.6](https://github.com/pypeclub/OpenPype/tree/3.14.6) + +[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.14.5...3.14.6) + +### 📖 Documentation + +- Documentation: Minor updates to dev\_requirements.md [\#4025](https://github.com/pypeclub/OpenPype/pull/4025) + +**🆕 New features** + +- Nuke: add 13.2 variant [\#4041](https://github.com/pypeclub/OpenPype/pull/4041) + +**🚀 Enhancements** + +- Publish Report Viewer: Store reports locally on machine [\#4040](https://github.com/pypeclub/OpenPype/pull/4040) +- General: More specific error in burnins script [\#4026](https://github.com/pypeclub/OpenPype/pull/4026) +- General: Extract review does not crash with old settings overrides [\#4023](https://github.com/pypeclub/OpenPype/pull/4023) +- Publisher: Convertors for legacy instances [\#4020](https://github.com/pypeclub/OpenPype/pull/4020) +- workflows: adding milestone creator and assigner [\#4018](https://github.com/pypeclub/OpenPype/pull/4018) +- Publisher: Catch creator errors [\#4015](https://github.com/pypeclub/OpenPype/pull/4015) + +**🐛 Bug fixes** + +- Hiero - effect collection fixes [\#4038](https://github.com/pypeclub/OpenPype/pull/4038) +- Nuke - loader clip correct hash conversion in path [\#4037](https://github.com/pypeclub/OpenPype/pull/4037) +- Maya: Soft fail when applying capture preset [\#4034](https://github.com/pypeclub/OpenPype/pull/4034) +- Igniter: handle missing directory [\#4032](https://github.com/pypeclub/OpenPype/pull/4032) +- StandalonePublisher: Fix thumbnail publishing [\#4029](https://github.com/pypeclub/OpenPype/pull/4029) +- Experimental Tools: Fix publisher import [\#4027](https://github.com/pypeclub/OpenPype/pull/4027) +- Houdini: fix wrong path in ASS loader [\#4016](https://github.com/pypeclub/OpenPype/pull/4016) + +**🔀 Refactored code** + +- General: Import lib functions from lib [\#4017](https://github.com/pypeclub/OpenPype/pull/4017) + ## [3.14.5](https://github.com/pypeclub/OpenPype/tree/3.14.5) (2022-10-24) [Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.14.4...3.14.5) From e600cd1b3d2963a2a2e26dce79e07818bb4c5d28 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 22 Nov 2022 21:24:11 +0100 Subject: [PATCH 25/27] updating to 3.14.7 --- CHANGELOG.md | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 707b61676f..c3cccf2d1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,63 @@ # Changelog -## [3.14.6](https://github.com/pypeclub/OpenPype/tree/HEAD) +## [3.14.7](https://github.com/pypeclub/OpenPype/tree/3.14.7) -[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.14.5...HEAD) +[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.14.6...3.14.7) + +**🆕 New features** + +- Hiero: loading effect family to timeline [\#4055](https://github.com/pypeclub/OpenPype/pull/4055) + +**🚀 Enhancements** + +- Ftrack: Event server status give more information about version locations [\#4112](https://github.com/pypeclub/OpenPype/pull/4112) +- General: Allow higher numbers in frames and clips [\#4101](https://github.com/pypeclub/OpenPype/pull/4101) +- Publisher: Settings for validate frame range [\#4097](https://github.com/pypeclub/OpenPype/pull/4097) +- Publisher: Ignore escape button [\#4090](https://github.com/pypeclub/OpenPype/pull/4090) +- Flame: Loading clip with native colorspace resolved from mapping [\#4079](https://github.com/pypeclub/OpenPype/pull/4079) +- General: Extract review single frame output [\#4064](https://github.com/pypeclub/OpenPype/pull/4064) +- Publisher: Prepared common function for instance data cache [\#4063](https://github.com/pypeclub/OpenPype/pull/4063) +- Publisher: Easy access to publish page from create page [\#4058](https://github.com/pypeclub/OpenPype/pull/4058) +- General/TVPaint: Attribute defs dialog [\#4052](https://github.com/pypeclub/OpenPype/pull/4052) +- Publisher: Better reset defer [\#4048](https://github.com/pypeclub/OpenPype/pull/4048) +- Publisher: Add thumbnail sources [\#4042](https://github.com/pypeclub/OpenPype/pull/4042) + +**🐛 Bug fixes** + +- General: Move default settings for template name [\#4119](https://github.com/pypeclub/OpenPype/pull/4119) +- Nuke: loaded nodes set to first tab [\#4114](https://github.com/pypeclub/OpenPype/pull/4114) +- Nuke: load image first frame [\#4113](https://github.com/pypeclub/OpenPype/pull/4113) +- Files Widget: Ignore case sensitivity of extensions [\#4096](https://github.com/pypeclub/OpenPype/pull/4096) +- Webpublisher: extension is lowercased in Setting and in uploaded files [\#4095](https://github.com/pypeclub/OpenPype/pull/4095) +- Publish Report Viewer: Fix small bugs [\#4086](https://github.com/pypeclub/OpenPype/pull/4086) +- Igniter: fix regex to match semver better [\#4085](https://github.com/pypeclub/OpenPype/pull/4085) +- Maya: aov filtering [\#4083](https://github.com/pypeclub/OpenPype/pull/4083) +- Flame/Flare: Loading to multiple batches [\#4080](https://github.com/pypeclub/OpenPype/pull/4080) +- hiero: creator from settings with set maximum [\#4077](https://github.com/pypeclub/OpenPype/pull/4077) +- Nuke: resolve hashes in file name only for frame token [\#4074](https://github.com/pypeclub/OpenPype/pull/4074) +- Publisher: Fix cache of asset docs [\#4070](https://github.com/pypeclub/OpenPype/pull/4070) +- Webpublisher: cleanup wp extract thumbnail [\#4067](https://github.com/pypeclub/OpenPype/pull/4067) +- Settings UI: Locked setting can't bypass lock [\#4066](https://github.com/pypeclub/OpenPype/pull/4066) +- Loader: Fix comparison of repre name [\#4053](https://github.com/pypeclub/OpenPype/pull/4053) +- Deadline: Extract environment subprocess failure [\#4050](https://github.com/pypeclub/OpenPype/pull/4050) + +**🔀 Refactored code** + +- General: Collect entities plugin minor changes [\#4089](https://github.com/pypeclub/OpenPype/pull/4089) +- General: Direct interfaces import [\#4065](https://github.com/pypeclub/OpenPype/pull/4065) + +**Merged pull requests:** + +- Bump loader-utils from 1.4.1 to 1.4.2 in /website [\#4100](https://github.com/pypeclub/OpenPype/pull/4100) +- Online family for Tray Publisher [\#4093](https://github.com/pypeclub/OpenPype/pull/4093) +- Bump loader-utils from 1.4.0 to 1.4.1 in /website [\#4081](https://github.com/pypeclub/OpenPype/pull/4081) +- remove underscore from subset name [\#4059](https://github.com/pypeclub/OpenPype/pull/4059) +- Alembic Loader as Arnold Standin [\#4047](https://github.com/pypeclub/OpenPype/pull/4047) + + +## [3.14.6](https://github.com/pypeclub/OpenPype/tree/3.14.6) + +[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.14.5...3.14.6) ### 📖 Documentation From 0d88af8aec4c6112be2629865da7ffce4a7cce4d Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 23 Nov 2022 11:40:16 +0100 Subject: [PATCH 26/27] update latest 3.14.7 --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c3cccf2d1e..0c5f2cf8b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ **🚀 Enhancements** +- Photoshop: bug with pop-up window on Instance Creator [\#4121](https://github.com/pypeclub/OpenPype/pull/4121) +- Publisher: Open on specific tab [\#4120](https://github.com/pypeclub/OpenPype/pull/4120) +- Publisher: Hide unknown publish values [\#4116](https://github.com/pypeclub/OpenPype/pull/4116) - Ftrack: Event server status give more information about version locations [\#4112](https://github.com/pypeclub/OpenPype/pull/4112) - General: Allow higher numbers in frames and clips [\#4101](https://github.com/pypeclub/OpenPype/pull/4101) - Publisher: Settings for validate frame range [\#4097](https://github.com/pypeclub/OpenPype/pull/4097) @@ -25,6 +28,7 @@ **🐛 Bug fixes** - General: Move default settings for template name [\#4119](https://github.com/pypeclub/OpenPype/pull/4119) +- Slack: notification fail in new tray publisher [\#4118](https://github.com/pypeclub/OpenPype/pull/4118) - Nuke: loaded nodes set to first tab [\#4114](https://github.com/pypeclub/OpenPype/pull/4114) - Nuke: load image first frame [\#4113](https://github.com/pypeclub/OpenPype/pull/4113) - Files Widget: Ignore case sensitivity of extensions [\#4096](https://github.com/pypeclub/OpenPype/pull/4096) @@ -54,7 +58,6 @@ - remove underscore from subset name [\#4059](https://github.com/pypeclub/OpenPype/pull/4059) - Alembic Loader as Arnold Standin [\#4047](https://github.com/pypeclub/OpenPype/pull/4047) - ## [3.14.6](https://github.com/pypeclub/OpenPype/tree/3.14.6) [Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.14.5...3.14.6) From 6725c1f6d8dc025f13bffbbb1c92a242c49b618f Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 23 Nov 2022 11:40:57 +0100 Subject: [PATCH 27/27] udpate history --- HISTORY.md | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index 7365696f96..04a1073c07 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,64 @@ # Changelog + +## [3.14.7](https://github.com/pypeclub/OpenPype/tree/3.14.7) + +[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.14.6...3.14.7) + +**🆕 New features** + +- Hiero: loading effect family to timeline [\#4055](https://github.com/pypeclub/OpenPype/pull/4055) + +**🚀 Enhancements** + +- Photoshop: bug with pop-up window on Instance Creator [\#4121](https://github.com/pypeclub/OpenPype/pull/4121) +- Publisher: Open on specific tab [\#4120](https://github.com/pypeclub/OpenPype/pull/4120) +- Publisher: Hide unknown publish values [\#4116](https://github.com/pypeclub/OpenPype/pull/4116) +- Ftrack: Event server status give more information about version locations [\#4112](https://github.com/pypeclub/OpenPype/pull/4112) +- General: Allow higher numbers in frames and clips [\#4101](https://github.com/pypeclub/OpenPype/pull/4101) +- Publisher: Settings for validate frame range [\#4097](https://github.com/pypeclub/OpenPype/pull/4097) +- Publisher: Ignore escape button [\#4090](https://github.com/pypeclub/OpenPype/pull/4090) +- Flame: Loading clip with native colorspace resolved from mapping [\#4079](https://github.com/pypeclub/OpenPype/pull/4079) +- General: Extract review single frame output [\#4064](https://github.com/pypeclub/OpenPype/pull/4064) +- Publisher: Prepared common function for instance data cache [\#4063](https://github.com/pypeclub/OpenPype/pull/4063) +- Publisher: Easy access to publish page from create page [\#4058](https://github.com/pypeclub/OpenPype/pull/4058) +- General/TVPaint: Attribute defs dialog [\#4052](https://github.com/pypeclub/OpenPype/pull/4052) +- Publisher: Better reset defer [\#4048](https://github.com/pypeclub/OpenPype/pull/4048) +- Publisher: Add thumbnail sources [\#4042](https://github.com/pypeclub/OpenPype/pull/4042) + +**🐛 Bug fixes** + +- General: Move default settings for template name [\#4119](https://github.com/pypeclub/OpenPype/pull/4119) +- Slack: notification fail in new tray publisher [\#4118](https://github.com/pypeclub/OpenPype/pull/4118) +- Nuke: loaded nodes set to first tab [\#4114](https://github.com/pypeclub/OpenPype/pull/4114) +- Nuke: load image first frame [\#4113](https://github.com/pypeclub/OpenPype/pull/4113) +- Files Widget: Ignore case sensitivity of extensions [\#4096](https://github.com/pypeclub/OpenPype/pull/4096) +- Webpublisher: extension is lowercased in Setting and in uploaded files [\#4095](https://github.com/pypeclub/OpenPype/pull/4095) +- Publish Report Viewer: Fix small bugs [\#4086](https://github.com/pypeclub/OpenPype/pull/4086) +- Igniter: fix regex to match semver better [\#4085](https://github.com/pypeclub/OpenPype/pull/4085) +- Maya: aov filtering [\#4083](https://github.com/pypeclub/OpenPype/pull/4083) +- Flame/Flare: Loading to multiple batches [\#4080](https://github.com/pypeclub/OpenPype/pull/4080) +- hiero: creator from settings with set maximum [\#4077](https://github.com/pypeclub/OpenPype/pull/4077) +- Nuke: resolve hashes in file name only for frame token [\#4074](https://github.com/pypeclub/OpenPype/pull/4074) +- Publisher: Fix cache of asset docs [\#4070](https://github.com/pypeclub/OpenPype/pull/4070) +- Webpublisher: cleanup wp extract thumbnail [\#4067](https://github.com/pypeclub/OpenPype/pull/4067) +- Settings UI: Locked setting can't bypass lock [\#4066](https://github.com/pypeclub/OpenPype/pull/4066) +- Loader: Fix comparison of repre name [\#4053](https://github.com/pypeclub/OpenPype/pull/4053) +- Deadline: Extract environment subprocess failure [\#4050](https://github.com/pypeclub/OpenPype/pull/4050) + +**🔀 Refactored code** + +- General: Collect entities plugin minor changes [\#4089](https://github.com/pypeclub/OpenPype/pull/4089) +- General: Direct interfaces import [\#4065](https://github.com/pypeclub/OpenPype/pull/4065) + +**Merged pull requests:** + +- Bump loader-utils from 1.4.1 to 1.4.2 in /website [\#4100](https://github.com/pypeclub/OpenPype/pull/4100) +- Online family for Tray Publisher [\#4093](https://github.com/pypeclub/OpenPype/pull/4093) +- Bump loader-utils from 1.4.0 to 1.4.1 in /website [\#4081](https://github.com/pypeclub/OpenPype/pull/4081) +- remove underscore from subset name [\#4059](https://github.com/pypeclub/OpenPype/pull/4059) +- Alembic Loader as Arnold Standin [\#4047](https://github.com/pypeclub/OpenPype/pull/4047) + ## [3.14.6](https://github.com/pypeclub/OpenPype/tree/3.14.6) [Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.14.5...3.14.6)