mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 12:54:40 +01:00
Merge pull request #982 from ynput/enhancement/139-enhancement-display-overriden-vs-default-values-of-attributes-in-publisher-ui
Publisher: Display overridden vs default values of attributes
This commit is contained in:
commit
9fbc08dd5e
5 changed files with 158 additions and 49 deletions
|
|
@ -60,7 +60,11 @@
|
|||
"icon-alert-tools": "#AA5050",
|
||||
"icon-entity-default": "#bfccd6",
|
||||
"icon-entity-disabled": "#808080",
|
||||
|
||||
"font-entity-deprecated": "#666666",
|
||||
|
||||
"font-overridden": "#91CDFC",
|
||||
|
||||
"overlay-messages": {
|
||||
"close-btn": "#D3D8DE",
|
||||
"bg-success": "#458056",
|
||||
|
|
|
|||
|
|
@ -44,6 +44,10 @@ QLabel {
|
|||
background: transparent;
|
||||
}
|
||||
|
||||
QLabel[overriden="1"] {
|
||||
color: {color:font-overridden};
|
||||
}
|
||||
|
||||
/* Inputs */
|
||||
QAbstractSpinBox, QLineEdit, QPlainTextEdit, QTextEdit {
|
||||
border: 1px solid {color:border};
|
||||
|
|
|
|||
|
|
@ -366,7 +366,7 @@ class AbstractPublisherFrontend(AbstractPublisherCommon):
|
|||
@abstractmethod
|
||||
def get_creator_attribute_definitions(
|
||||
self, instance_ids: Iterable[str]
|
||||
) -> List[Tuple[AbstractAttrDef, List[str], List[Any]]]:
|
||||
) -> List[Tuple[AbstractAttrDef, Dict[str, Dict[str, Any]]]]:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
|
|
@ -383,7 +383,7 @@ class AbstractPublisherFrontend(AbstractPublisherCommon):
|
|||
) -> List[Tuple[
|
||||
str,
|
||||
List[AbstractAttrDef],
|
||||
Dict[str, List[Tuple[str, Any]]]
|
||||
Dict[str, List[Tuple[str, Any, Any]]]
|
||||
]]:
|
||||
pass
|
||||
|
||||
|
|
|
|||
|
|
@ -769,7 +769,7 @@ class CreateModel:
|
|||
|
||||
def get_creator_attribute_definitions(
|
||||
self, instance_ids: List[str]
|
||||
) -> List[Tuple[AbstractAttrDef, List[str], List[Any]]]:
|
||||
) -> List[Tuple[AbstractAttrDef, Dict[str, Dict[str, Any]]]]:
|
||||
"""Collect creator attribute definitions for multuple instances.
|
||||
|
||||
Args:
|
||||
|
|
@ -796,12 +796,23 @@ class CreateModel:
|
|||
|
||||
if found_idx is None:
|
||||
idx = len(output)
|
||||
output.append((attr_def, [instance_id], [value]))
|
||||
output.append((
|
||||
attr_def,
|
||||
{
|
||||
instance_id: {
|
||||
"value": value,
|
||||
"default": attr_def.default
|
||||
}
|
||||
}
|
||||
))
|
||||
_attr_defs[idx] = attr_def
|
||||
else:
|
||||
_, ids, values = output[found_idx]
|
||||
ids.append(instance_id)
|
||||
values.append(value)
|
||||
_, info_by_id = output[found_idx]
|
||||
info_by_id[instance_id] = {
|
||||
"value": value,
|
||||
"default": attr_def.default
|
||||
}
|
||||
|
||||
return output
|
||||
|
||||
def set_instances_publish_attr_values(
|
||||
|
|
@ -835,7 +846,7 @@ class CreateModel:
|
|||
) -> List[Tuple[
|
||||
str,
|
||||
List[AbstractAttrDef],
|
||||
Dict[str, List[Tuple[str, Any]]]
|
||||
Dict[str, List[Tuple[str, Any, Any]]]
|
||||
]]:
|
||||
"""Collect publish attribute definitions for passed instances.
|
||||
|
||||
|
|
@ -865,21 +876,21 @@ class CreateModel:
|
|||
attr_defs = attr_val.attr_defs
|
||||
if not attr_defs:
|
||||
continue
|
||||
|
||||
plugin_attr_defs = all_defs_by_plugin_name.setdefault(
|
||||
plugin_name, []
|
||||
)
|
||||
plugin_attr_defs.append(attr_defs)
|
||||
|
||||
plugin_values = all_plugin_values.setdefault(plugin_name, {})
|
||||
|
||||
plugin_attr_defs.append(attr_defs)
|
||||
|
||||
for attr_def in attr_defs:
|
||||
if isinstance(attr_def, UIDef):
|
||||
continue
|
||||
|
||||
attr_values = plugin_values.setdefault(attr_def.key, [])
|
||||
|
||||
value = attr_val[attr_def.key]
|
||||
attr_values.append((item_id, value))
|
||||
attr_values.append(
|
||||
(item_id, attr_val[attr_def.key], attr_def.default)
|
||||
)
|
||||
|
||||
attr_defs_by_plugin_name = {}
|
||||
for plugin_name, attr_defs in all_defs_by_plugin_name.items():
|
||||
|
|
@ -893,7 +904,7 @@ class CreateModel:
|
|||
output.append((
|
||||
plugin_name,
|
||||
attr_defs_by_plugin_name[plugin_name],
|
||||
all_plugin_values
|
||||
all_plugin_values[plugin_name],
|
||||
))
|
||||
return output
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
import typing
|
||||
from typing import Dict, List, Any
|
||||
|
||||
from qtpy import QtWidgets, QtCore
|
||||
|
||||
from ayon_core.lib.attribute_definitions import UnknownDef
|
||||
from ayon_core.lib.attribute_definitions import AbstractAttrDef, UnknownDef
|
||||
from ayon_core.tools.utils import set_style_property
|
||||
from ayon_core.tools.attribute_defs import create_widget_for_attr_def
|
||||
from ayon_core.tools.publisher.abstract import AbstractPublisherFrontend
|
||||
from ayon_core.tools.publisher.constants import (
|
||||
|
|
@ -8,6 +12,49 @@ from ayon_core.tools.publisher.constants import (
|
|||
INPUTS_LAYOUT_VSPACING,
|
||||
)
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from typing import Union
|
||||
|
||||
|
||||
def _set_label_overriden(label: QtWidgets.QLabel, overriden: bool):
|
||||
set_style_property(
|
||||
label,
|
||||
"overriden",
|
||||
"1" if overriden else ""
|
||||
)
|
||||
|
||||
|
||||
class _CreateAttrDefInfo:
|
||||
"""Helper class to store information about create attribute definition."""
|
||||
def __init__(
|
||||
self,
|
||||
attr_def: AbstractAttrDef,
|
||||
instance_ids: List["Union[str, None]"],
|
||||
defaults: List[Any],
|
||||
label_widget: "Union[None, QtWidgets.QLabel]",
|
||||
):
|
||||
self.attr_def: AbstractAttrDef = attr_def
|
||||
self.instance_ids: List["Union[str, None]"] = instance_ids
|
||||
self.defaults: List[Any] = defaults
|
||||
self.label_widget: "Union[None, QtWidgets.QLabel]" = label_widget
|
||||
|
||||
|
||||
class _PublishAttrDefInfo:
|
||||
"""Helper class to store information about publish attribute definition."""
|
||||
def __init__(
|
||||
self,
|
||||
attr_def: AbstractAttrDef,
|
||||
plugin_name: str,
|
||||
instance_ids: List["Union[str, None]"],
|
||||
defaults: List[Any],
|
||||
label_widget: "Union[None, QtWidgets.QLabel]",
|
||||
):
|
||||
self.attr_def: AbstractAttrDef = attr_def
|
||||
self.plugin_name: str = plugin_name
|
||||
self.instance_ids: List["Union[str, None]"] = instance_ids
|
||||
self.defaults: List[Any] = defaults
|
||||
self.label_widget: "Union[None, QtWidgets.QLabel]" = label_widget
|
||||
|
||||
|
||||
class CreatorAttrsWidget(QtWidgets.QWidget):
|
||||
"""Widget showing creator specific attributes for selected instances.
|
||||
|
|
@ -51,8 +98,7 @@ class CreatorAttrsWidget(QtWidgets.QWidget):
|
|||
self._controller: AbstractPublisherFrontend = controller
|
||||
self._scroll_area = scroll_area
|
||||
|
||||
self._attr_def_id_to_instances = {}
|
||||
self._attr_def_id_to_attr_def = {}
|
||||
self._attr_def_info_by_id: Dict[str, _CreateAttrDefInfo] = {}
|
||||
self._current_instance_ids = set()
|
||||
|
||||
# To store content of scroll area to prevent garbage collection
|
||||
|
|
@ -81,8 +127,7 @@ class CreatorAttrsWidget(QtWidgets.QWidget):
|
|||
prev_content_widget.deleteLater()
|
||||
|
||||
self._content_widget = None
|
||||
self._attr_def_id_to_instances = {}
|
||||
self._attr_def_id_to_attr_def = {}
|
||||
self._attr_def_info_by_id = {}
|
||||
|
||||
result = self._controller.get_creator_attribute_definitions(
|
||||
self._current_instance_ids
|
||||
|
|
@ -97,9 +142,19 @@ class CreatorAttrsWidget(QtWidgets.QWidget):
|
|||
content_layout.setVerticalSpacing(INPUTS_LAYOUT_VSPACING)
|
||||
|
||||
row = 0
|
||||
for attr_def, instance_ids, values in result:
|
||||
for attr_def, info_by_id in result:
|
||||
widget = create_widget_for_attr_def(attr_def, content_widget)
|
||||
default_values = []
|
||||
if attr_def.is_value_def:
|
||||
values = []
|
||||
for item in info_by_id.values():
|
||||
values.append(item["value"])
|
||||
# 'set' cannot be used for default values because they can
|
||||
# be unhashable types, e.g. 'list'.
|
||||
default = item["default"]
|
||||
if default not in default_values:
|
||||
default_values.append(default)
|
||||
|
||||
if len(values) == 1:
|
||||
value = values[0]
|
||||
if value is not None:
|
||||
|
|
@ -108,8 +163,10 @@ class CreatorAttrsWidget(QtWidgets.QWidget):
|
|||
widget.set_value(values, True)
|
||||
|
||||
widget.value_changed.connect(self._input_value_changed)
|
||||
self._attr_def_id_to_instances[attr_def.id] = instance_ids
|
||||
self._attr_def_id_to_attr_def[attr_def.id] = attr_def
|
||||
attr_def_info = _CreateAttrDefInfo(
|
||||
attr_def, list(info_by_id), default_values, None
|
||||
)
|
||||
self._attr_def_info_by_id[attr_def.id] = attr_def_info
|
||||
|
||||
if not attr_def.visible:
|
||||
continue
|
||||
|
|
@ -121,8 +178,14 @@ class CreatorAttrsWidget(QtWidgets.QWidget):
|
|||
col_num = 2 - expand_cols
|
||||
|
||||
label = None
|
||||
is_overriden = False
|
||||
if attr_def.is_value_def:
|
||||
is_overriden = any(
|
||||
item["value"] != item["default"]
|
||||
for item in info_by_id.values()
|
||||
)
|
||||
label = attr_def.label or attr_def.key
|
||||
|
||||
if label:
|
||||
label_widget = QtWidgets.QLabel(label, self)
|
||||
tooltip = attr_def.tooltip
|
||||
|
|
@ -138,6 +201,8 @@ class CreatorAttrsWidget(QtWidgets.QWidget):
|
|||
)
|
||||
if not attr_def.is_label_horizontal:
|
||||
row += 1
|
||||
attr_def_info.label_widget = label_widget
|
||||
_set_label_overriden(label_widget, is_overriden)
|
||||
|
||||
content_layout.addWidget(
|
||||
widget, row, col_num, 1, expand_cols
|
||||
|
|
@ -165,12 +230,19 @@ class CreatorAttrsWidget(QtWidgets.QWidget):
|
|||
break
|
||||
|
||||
def _input_value_changed(self, value, attr_id):
|
||||
instance_ids = self._attr_def_id_to_instances.get(attr_id)
|
||||
attr_def = self._attr_def_id_to_attr_def.get(attr_id)
|
||||
if not instance_ids or not attr_def:
|
||||
attr_def_info = self._attr_def_info_by_id.get(attr_id)
|
||||
if attr_def_info is None:
|
||||
return
|
||||
|
||||
if attr_def_info.label_widget is not None:
|
||||
defaults = attr_def_info.defaults
|
||||
is_overriden = len(defaults) != 1 or value not in defaults
|
||||
_set_label_overriden(attr_def_info.label_widget, is_overriden)
|
||||
|
||||
self._controller.set_instances_create_attr_values(
|
||||
instance_ids, attr_def.key, value
|
||||
attr_def_info.instance_ids,
|
||||
attr_def_info.attr_def.key,
|
||||
value
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -223,9 +295,7 @@ class PublishPluginAttrsWidget(QtWidgets.QWidget):
|
|||
self._controller: AbstractPublisherFrontend = controller
|
||||
self._scroll_area = scroll_area
|
||||
|
||||
self._attr_def_id_to_instances = {}
|
||||
self._attr_def_id_to_attr_def = {}
|
||||
self._attr_def_id_to_plugin_name = {}
|
||||
self._attr_def_info_by_id: Dict[str, _PublishAttrDefInfo] = {}
|
||||
|
||||
# Store content of scroll area to prevent garbage collection
|
||||
self._content_widget = None
|
||||
|
|
@ -254,9 +324,7 @@ class PublishPluginAttrsWidget(QtWidgets.QWidget):
|
|||
|
||||
self._content_widget = None
|
||||
|
||||
self._attr_def_id_to_instances = {}
|
||||
self._attr_def_id_to_attr_def = {}
|
||||
self._attr_def_id_to_plugin_name = {}
|
||||
self._attr_def_info_by_id = {}
|
||||
|
||||
result = self._controller.get_publish_attribute_definitions(
|
||||
self._current_instance_ids, self._context_selected
|
||||
|
|
@ -275,9 +343,7 @@ class PublishPluginAttrsWidget(QtWidgets.QWidget):
|
|||
content_layout.addStretch(1)
|
||||
|
||||
row = 0
|
||||
for plugin_name, attr_defs, all_plugin_values in result:
|
||||
plugin_values = all_plugin_values[plugin_name]
|
||||
|
||||
for plugin_name, attr_defs, plugin_values in result:
|
||||
for attr_def in attr_defs:
|
||||
widget = create_widget_for_attr_def(
|
||||
attr_def, content_widget
|
||||
|
|
@ -290,6 +356,7 @@ class PublishPluginAttrsWidget(QtWidgets.QWidget):
|
|||
widget.setVisible(False)
|
||||
visible_widget = False
|
||||
|
||||
label_widget = None
|
||||
if visible_widget:
|
||||
expand_cols = 2
|
||||
if attr_def.is_value_def and attr_def.is_label_horizontal:
|
||||
|
|
@ -324,35 +391,58 @@ class PublishPluginAttrsWidget(QtWidgets.QWidget):
|
|||
|
||||
widget.value_changed.connect(self._input_value_changed)
|
||||
|
||||
attr_values = plugin_values[attr_def.key]
|
||||
multivalue = len(attr_values) > 1
|
||||
instance_ids = []
|
||||
values = []
|
||||
instances = []
|
||||
for instance, value in attr_values:
|
||||
default_values = []
|
||||
is_overriden = False
|
||||
for (instance_id, value, default_value) in (
|
||||
plugin_values.get(attr_def.key, [])
|
||||
):
|
||||
instance_ids.append(instance_id)
|
||||
values.append(value)
|
||||
instances.append(instance)
|
||||
if not is_overriden and value != default_value:
|
||||
is_overriden = True
|
||||
# 'set' cannot be used for default values because they can
|
||||
# be unhashable types, e.g. 'list'.
|
||||
if default_value not in default_values:
|
||||
default_values.append(default_value)
|
||||
|
||||
self._attr_def_id_to_attr_def[attr_def.id] = attr_def
|
||||
self._attr_def_id_to_instances[attr_def.id] = instances
|
||||
self._attr_def_id_to_plugin_name[attr_def.id] = plugin_name
|
||||
multivalue = len(values) > 1
|
||||
|
||||
self._attr_def_info_by_id[attr_def.id] = _PublishAttrDefInfo(
|
||||
attr_def,
|
||||
plugin_name,
|
||||
instance_ids,
|
||||
default_values,
|
||||
label_widget,
|
||||
)
|
||||
|
||||
if multivalue:
|
||||
widget.set_value(values, multivalue)
|
||||
else:
|
||||
widget.set_value(values[0])
|
||||
|
||||
if label_widget is not None:
|
||||
_set_label_overriden(label_widget, is_overriden)
|
||||
|
||||
self._scroll_area.setWidget(content_widget)
|
||||
self._content_widget = content_widget
|
||||
|
||||
def _input_value_changed(self, value, attr_id):
|
||||
instance_ids = self._attr_def_id_to_instances.get(attr_id)
|
||||
attr_def = self._attr_def_id_to_attr_def.get(attr_id)
|
||||
plugin_name = self._attr_def_id_to_plugin_name.get(attr_id)
|
||||
if not instance_ids or not attr_def or not plugin_name:
|
||||
attr_def_info = self._attr_def_info_by_id.get(attr_id)
|
||||
if attr_def_info is None:
|
||||
return
|
||||
|
||||
if attr_def_info.label_widget is not None:
|
||||
defaults = attr_def_info.defaults
|
||||
is_overriden = len(defaults) != 1 or value not in defaults
|
||||
_set_label_overriden(attr_def_info.label_widget, is_overriden)
|
||||
|
||||
self._controller.set_instances_publish_attr_values(
|
||||
instance_ids, plugin_name, attr_def.key, value
|
||||
attr_def_info.instance_ids,
|
||||
attr_def_info.plugin_name,
|
||||
attr_def_info.attr_def.key,
|
||||
value
|
||||
)
|
||||
|
||||
def _on_instance_attr_defs_change(self, event):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue