[Automated] Merged develop into main

This commit is contained in:
pypebot 2022-11-23 11:44:03 +01:00 committed by GitHub
commit ea9e3a849a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 429 additions and 54 deletions

View file

@ -1,8 +1,66 @@
# 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**
- 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)
### 📖 Documentation

View file

@ -1,5 +1,99 @@
# 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)
### 📖 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)

View file

@ -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})

View file

@ -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)
@ -235,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.

View file

@ -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)

View file

@ -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
@ -142,13 +148,17 @@ 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"]
repre_thumbnail_path = (
repre.get("published_path") or
os.path.join(repre["stagingDir"], repre["files"])
)
if os.path.exists(repre_thumbnail_path):
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"""
@ -178,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

View file

@ -6,6 +6,7 @@ from Qt import QtWidgets, QtCore
from openpype.lib.attribute_definitions import (
AbtractAttrDef,
UnknownDef,
HiddenDef,
NumberDef,
TextDef,
EnumDef,
@ -22,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
@ -42,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)
@ -115,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:
@ -133,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):
@ -459,6 +476,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(

View file

@ -674,9 +674,16 @@ 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 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()):
if idx > 0:

View file

@ -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.

View file

@ -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.

View file

@ -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
@ -68,7 +71,16 @@ class PublisherTabsWidget(QtWidgets.QFrame):
self.set_current_tab(identifier)
return button
def get_tab_by_index(self, index):
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):
identifier = self.get_tab_by_index(identifier)
if isinstance(identifier, PublisherTabBtn):
identifier = identifier.identifier

View file

@ -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
@ -305,6 +306,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.
@ -578,6 +593,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:
@ -1180,7 +1200,7 @@ class GlobalAttrsWidget(QtWidgets.QWidget):
"""Set currently selected instances.
Args:
instances(list<CreatedInstance>): 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)
@ -1303,6 +1323,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 +1348,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 +1443,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)
@ -1614,6 +1645,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

View file

@ -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
@ -432,7 +447,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
@ -449,8 +464,21 @@ 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_current_tab("details"):
if not force and not self._is_on_details_tab():
return
report_data = self.controller.get_publish_report()
@ -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)
@ -539,6 +572,18 @@ class PublisherWindow(QtWidgets.QDialog):
def _go_to_report_tab(self):
self._set_current_tab("report")
def _is_on_create_tab(self):
return self._is_current_tab("create")
def _is_on_publish_tab(self):
return self._is_current_tab("publish")
def _is_on_details_tab(self):
return self._is_current_tab("details")
def _is_on_report_tab(self):
return self._is_current_tab("report")
def _set_publish_overlay_visibility(self, visible):
if visible:
widget = self._publish_overlay
@ -589,11 +634,33 @@ 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")
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()
):
self._set_current_tab("publish")
# 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):
self._create_tab.setEnabled(False)
@ -609,8 +676,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"]:
@ -623,7 +690,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:

View file

@ -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):