From 1089f6e587b600d8ad8cb2ce29cede2346219815 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 23 Feb 2024 12:37:53 +0100 Subject: [PATCH] creator tool is using product name and type --- client/ayon_core/tools/creator/constants.py | 2 +- client/ayon_core/tools/creator/model.py | 14 +- client/ayon_core/tools/creator/widgets.py | 75 +++++----- client/ayon_core/tools/creator/window.py | 149 ++++++++++---------- 4 files changed, 121 insertions(+), 119 deletions(-) diff --git a/client/ayon_core/tools/creator/constants.py b/client/ayon_core/tools/creator/constants.py index 5c4bbdcca3..ec555fbe9c 100644 --- a/client/ayon_core/tools/creator/constants.py +++ b/client/ayon_core/tools/creator/constants.py @@ -1,7 +1,7 @@ from qtpy import QtCore -FAMILY_ROLE = QtCore.Qt.UserRole + 1 +PRODUCT_TYPE_ROLE = QtCore.Qt.UserRole + 1 ITEM_ID_ROLE = QtCore.Qt.UserRole + 2 SEPARATOR = "---" diff --git a/client/ayon_core/tools/creator/model.py b/client/ayon_core/tools/creator/model.py index 3650993b9e..bf6c7380a1 100644 --- a/client/ayon_core/tools/creator/model.py +++ b/client/ayon_core/tools/creator/model.py @@ -4,7 +4,7 @@ from qtpy import QtGui, QtCore from ayon_core.pipeline import discover_legacy_creator_plugins from . constants import ( - FAMILY_ROLE, + PRODUCT_TYPE_ROLE, ITEM_ID_ROLE ) @@ -28,15 +28,15 @@ class CreatorsModel(QtGui.QStandardItemModel): item_id = str(uuid.uuid4()) self._creators_by_id[item_id] = creator - label = creator.label or creator.family + label = creator.label or creator.product_type item = QtGui.QStandardItem(label) item.setEditable(False) item.setData(item_id, ITEM_ID_ROLE) - item.setData(creator.family, FAMILY_ROLE) + item.setData(creator.product_type, PRODUCT_TYPE_ROLE) items.append(item) if not items: - item = QtGui.QStandardItem("No registered families") + item = QtGui.QStandardItem("No registered create plugins") item.setEnabled(False) item.setData(False, QtCore.Qt.ItemIsEnabled) items.append(item) @@ -47,15 +47,15 @@ class CreatorsModel(QtGui.QStandardItemModel): def get_creator_by_id(self, item_id): return self._creators_by_id.get(item_id) - def get_indexes_by_family(self, family): + def get_indexes_by_product_type(self, product_type): indexes = [] for row in range(self.rowCount()): index = self.index(row, 0) item_id = index.data(ITEM_ID_ROLE) creator_plugin = self._creators_by_id.get(item_id) if creator_plugin and ( - creator_plugin.label.lower() == family.lower() - or creator_plugin.family.lower() == family.lower() + creator_plugin.label.lower() == product_type.lower() + or creator_plugin.product_type.lower() == product_type.lower() ): indexes.append(index) return indexes diff --git a/client/ayon_core/tools/creator/widgets.py b/client/ayon_core/tools/creator/widgets.py index 05b5469151..53a2ee1080 100644 --- a/client/ayon_core/tools/creator/widgets.py +++ b/client/ayon_core/tools/creator/widgets.py @@ -5,7 +5,7 @@ from qtpy import QtWidgets, QtCore, QtGui import qtawesome -from ayon_core.pipeline.create import SUBSET_NAME_ALLOWED_SYMBOLS +from ayon_core.pipeline.create import PRODUCT_NAME_ALLOWED_SYMBOLS from ayon_core.tools.utils import ErrorMessageBox if hasattr(QtGui, "QRegularExpressionValidator"): @@ -19,16 +19,16 @@ else: class CreateErrorMessageBox(ErrorMessageBox): def __init__( self, - family, - subset_name, - asset_name, + product_type, + product_name, + folder_path, exc_msg, formatted_traceback, parent ): - self._family = family - self._subset_name = subset_name - self._asset_name = asset_name + self._product_type = product_type + self._product_name = product_name + self._folder_path = folder_path self._exc_msg = exc_msg self._formatted_traceback = formatted_traceback super(CreateErrorMessageBox, self).__init__("Creation failed", parent) @@ -42,14 +42,14 @@ class CreateErrorMessageBox(ErrorMessageBox): def _get_report_data(self): report_message = ( - "Failed to create Product: \"{subset}\"" - " Type: \"{family}\"" - " in Asset: \"{asset}\"" + "Failed to create Product: \"{product_name}\"" + " Type: \"{product_type}\"" + " in Folder: \"{folder_path}\"" "\n\nError: {message}" ).format( - subset=self._subset_name, - family=self._family, - asset=self._asset_name, + product_name=self._product_name, + product_type=self._product_type, + folder_path=self._folder_path, message=self._exc_msg ) if self._formatted_traceback: @@ -74,7 +74,7 @@ class CreateErrorMessageBox(ErrorMessageBox): item_name_widget = QtWidgets.QLabel(self) item_name_widget.setText( item_name_template.format( - self._family, self._subset_name, self._asset_name + self._product_type, self._product_name, self._folder_path ) ) content_layout.addWidget(item_name_widget) @@ -94,16 +94,16 @@ class CreateErrorMessageBox(ErrorMessageBox): content_layout.addWidget(tb_widget) -class SubsetNameValidator(RegularExpressionValidatorClass): +class ProductNameValidator(RegularExpressionValidatorClass): invalid = QtCore.Signal(set) - pattern = "^[{}]*$".format(SUBSET_NAME_ALLOWED_SYMBOLS) + pattern = "^[{}]*$".format(PRODUCT_NAME_ALLOWED_SYMBOLS) def __init__(self): reg = RegularExpressionClass(self.pattern) - super(SubsetNameValidator, self).__init__(reg) + super(ProductNameValidator, self).__init__(reg) def validate(self, text, pos): - results = super(SubsetNameValidator, self).validate(text, pos) + results = super(ProductNameValidator, self).validate(text, pos) if results[0] == self.Invalid: self.invalid.emit(self.invalid_chars(text)) return results @@ -131,7 +131,7 @@ class VariantLineEdit(QtWidgets.QLineEdit): def __init__(self, *args, **kwargs): super(VariantLineEdit, self).__init__(*args, **kwargs) - validator = SubsetNameValidator() + validator = ProductNameValidator() self.setValidator(validator) self.setToolTip("Only alphanumeric characters (A-Z a-z 0-9), " "'_' and '.' are allowed.") @@ -183,24 +183,24 @@ class VariantLineEdit(QtWidgets.QLineEdit): ) -class FamilyDescriptionWidget(QtWidgets.QWidget): - """A family description widget. +class ProductTypeDescriptionWidget(QtWidgets.QWidget): + """A product type description widget. - Shows a family icon, family name and a help description. + Shows a product type icon, name and a help description. Used in creator header. - _________________ - | ____ | - | |icon| FAMILY | - | |____| help | - |_________________| + _______________________ + | ____ | + | |icon| PRODUCT TYPE | + | |____| help | + |_______________________| """ SIZE = 35 def __init__(self, parent=None): - super(FamilyDescriptionWidget, self).__init__(parent=parent) + super(ProductTypeDescriptionWidget, self).__init__(parent=parent) icon_label = QtWidgets.QLabel(self) icon_label.setSizePolicy( @@ -215,14 +215,14 @@ class FamilyDescriptionWidget(QtWidgets.QWidget): label_layout = QtWidgets.QVBoxLayout() label_layout.setSpacing(0) - family_label = QtWidgets.QLabel(self) - family_label.setObjectName("CreatorFamilyLabel") - family_label.setAlignment(QtCore.Qt.AlignBottom | QtCore.Qt.AlignLeft) + product_type_label = QtWidgets.QLabel(self) + product_type_label.setObjectName("CreatorProductTypeLabel") + product_type_label.setAlignment(QtCore.Qt.AlignBottom | QtCore.Qt.AlignLeft) help_label = QtWidgets.QLabel(self) help_label.setAlignment(QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft) - label_layout.addWidget(family_label) + label_layout.addWidget(product_type_label) label_layout.addWidget(help_label) layout = QtWidgets.QHBoxLayout(self) @@ -232,14 +232,15 @@ class FamilyDescriptionWidget(QtWidgets.QWidget): layout.addLayout(label_layout) self._help_label = help_label - self._family_label = family_label + self._product_type_label = product_type_label self._icon_label = icon_label def set_item(self, creator_plugin): - """Update elements to display information of a family item. + """Update elements to display information of a product type item. Args: - item (dict): A family item as registered with name, help and icon + creator_plugin (dict): A product type item as registered with + name, help and icon. Returns: None @@ -247,7 +248,7 @@ class FamilyDescriptionWidget(QtWidgets.QWidget): """ if not creator_plugin: self._icon_label.setPixmap(None) - self._family_label.setText("") + self._product_type_label.setText("") self._help_label.setText("") return @@ -268,5 +269,5 @@ class FamilyDescriptionWidget(QtWidgets.QWidget): creator_help = docstring.splitlines()[0] if docstring else "" self._icon_label.setPixmap(pixmap) - self._family_label.setText(creator_plugin.family) + self._product_type_label.setText(creator_plugin.product_type) self._help_label.setText(creator_help) diff --git a/client/ayon_core/tools/creator/window.py b/client/ayon_core/tools/creator/window.py index 5862725076..6194f019fc 100644 --- a/client/ayon_core/tools/creator/window.py +++ b/client/ayon_core/tools/creator/window.py @@ -14,7 +14,7 @@ from ayon_core.pipeline import ( get_current_task_name, ) from ayon_core.pipeline.create import ( - SUBSET_NAME_ALLOWED_SYMBOLS, + PRODUCT_NAME_ALLOWED_SYMBOLS, legacy_create, CreatorError, ) @@ -23,7 +23,7 @@ from .model import CreatorsModel from .widgets import ( CreateErrorMessageBox, VariantLineEdit, - FamilyDescriptionWidget + ProductTypeDescriptionWidget ) from .constants import ( ITEM_ID_ROLE, @@ -45,7 +45,7 @@ class CreatorWindow(QtWidgets.QDialog): self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint ) - creator_info = FamilyDescriptionWidget(self) + creator_info = ProductTypeDescriptionWidget(self) creators_model = CreatorsModel() @@ -56,19 +56,19 @@ class CreatorWindow(QtWidgets.QDialog): creators_view.setObjectName("CreatorsView") creators_view.setModel(creators_proxy) - asset_name_input = QtWidgets.QLineEdit(self) + folder_path_input = QtWidgets.QLineEdit(self) variant_input = VariantLineEdit(self) - subset_name_input = QtWidgets.QLineEdit(self) - subset_name_input.setEnabled(False) + product_name_input = QtWidgets.QLineEdit(self) + product_name_input.setEnabled(False) - subset_button = QtWidgets.QPushButton() - subset_button.setFixedWidth(18) - subset_menu = QtWidgets.QMenu(subset_button) - subset_button.setMenu(subset_menu) + variants_btn = QtWidgets.QPushButton() + variants_btn.setFixedWidth(18) + variants_menu = QtWidgets.QMenu(variants_btn) + variants_btn.setMenu(variants_menu) name_layout = QtWidgets.QHBoxLayout() name_layout.addWidget(variant_input) - name_layout.addWidget(subset_button) + name_layout.addWidget(variants_btn) name_layout.setSpacing(3) name_layout.setContentsMargins(0, 0, 0, 0) @@ -76,13 +76,13 @@ class CreatorWindow(QtWidgets.QDialog): body_layout.setContentsMargins(0, 0, 0, 0) body_layout.addWidget(creator_info, 0) - body_layout.addWidget(QtWidgets.QLabel("Family", self), 0) + body_layout.addWidget(QtWidgets.QLabel("Product type", self), 0) body_layout.addWidget(creators_view, 1) - body_layout.addWidget(QtWidgets.QLabel("Asset", self), 0) - body_layout.addWidget(asset_name_input, 0) - body_layout.addWidget(QtWidgets.QLabel("Subset", self), 0) + body_layout.addWidget(QtWidgets.QLabel("Folder path", self), 0) + body_layout.addWidget(folder_path_input, 0) + body_layout.addWidget(QtWidgets.QLabel("Product name", self), 0) body_layout.addLayout(name_layout, 0) - body_layout.addWidget(subset_name_input, 0) + body_layout.addWidget(product_name_input, 0) useselection_chk = QtWidgets.QCheckBox("Use selection", self) useselection_chk.setCheckState(QtCore.Qt.Checked) @@ -116,7 +116,7 @@ class CreatorWindow(QtWidgets.QDialog): variant_input.returnPressed.connect(self._on_create) variant_input.textChanged.connect(self._on_data_changed) variant_input.report.connect(self.echo) - asset_name_input.textChanged.connect(self._on_data_changed) + folder_path_input.textChanged.connect(self._on_data_changed) creators_view.selectionModel().currentChanged.connect( self._on_selection_changed ) @@ -134,15 +134,15 @@ class CreatorWindow(QtWidgets.QDialog): self._create_btn = create_btn self._useselection_chk = useselection_chk self._variant_input = variant_input - self._subset_name_input = subset_name_input - self._asset_name_input = asset_name_input + self._product_name_input = product_name_input + self._folder_path_input = folder_path_input self._creators_model = creators_model self._creators_proxy = creators_proxy self._creators_view = creators_view - self._subset_btn = subset_button - self._subset_menu = subset_menu + self._variants_btn = variants_btn + self._variants_menu = variants_menu self._msg_label = msg_label @@ -160,7 +160,7 @@ class CreatorWindow(QtWidgets.QDialog): self._create_btn.setEnabled(valid) def _build_menu(self, default_names=None): - """Create optional predefined subset names + """Create optional predefined variants. Args: default_names(list): all predefined names @@ -171,8 +171,8 @@ class CreatorWindow(QtWidgets.QDialog): if not default_names: default_names = [] - menu = self._subset_menu - button = self._subset_btn + menu = self._variants_menu + button = self._variants_btn # Get and destroy the action group group = button.findChild(QtWidgets.QActionGroup) @@ -211,10 +211,10 @@ class CreatorWindow(QtWidgets.QDialog): item_id = index.data(ITEM_ID_ROLE) creator_plugin = self._creators_model.get_creator_by_id(item_id) user_input_text = self._variant_input.text() - asset_name = self._asset_name_input.text() + folder_path = self._folder_path_input.text() - # Early exit if no asset name - if not asset_name: + # Early exit if no folder path + if not folder_path: self._build_menu() self.echo("Asset name is required ..") self._set_valid_state(False) @@ -225,64 +225,63 @@ class CreatorWindow(QtWidgets.QDialog): if creator_plugin: # Get the asset from the database which match with the name asset_doc = get_asset_by_name( - project_name, asset_name, fields=["_id"] + project_name, folder_path, fields=["_id"] ) # Get plugin if not asset_doc or not creator_plugin: - subset_name = user_input_text self._build_menu() if not creator_plugin: - self.echo("No registered families ..") + self.echo("No registered product types ..") else: - self.echo("Asset '%s' not found .." % asset_name) + self.echo("Folder '{}' not found ..".format(folder_path)) self._set_valid_state(False) return - asset_id = asset_doc["_id"] + folder_id = asset_doc["_id"] task_name = get_current_task_name() - # Calculate subset name with Creator plugin - subset_name = creator_plugin.get_subset_name( - user_input_text, task_name, asset_id, project_name + # Calculate product name with Creator plugin + product_name = creator_plugin.get_product_name( + user_input_text, task_name, folder_id, project_name ) # Force replacement of prohibited symbols # QUESTION should Creator care about this and here should be only # validated with schema regex? - # Allow curly brackets in subset name for dynamic keys + # Allow curly brackets in product name for dynamic keys curly_left = "__cbl__" curly_right = "__cbr__" - tmp_subset_name = ( - subset_name + tmp_product_name = ( + product_name .replace("{", curly_left) .replace("}", curly_right) ) # Replace prohibited symbols - tmp_subset_name = re.sub( - "[^{}]+".format(SUBSET_NAME_ALLOWED_SYMBOLS), + tmp_product_name = re.sub( + "[^{}]+".format(PRODUCT_NAME_ALLOWED_SYMBOLS), "", - tmp_subset_name + tmp_product_name ) - subset_name = ( - tmp_subset_name + product_name = ( + tmp_product_name .replace(curly_left, "{") .replace(curly_right, "}") ) - self._subset_name_input.setText(subset_name) + self._product_name_input.setText(product_name) - # Get all subsets of the current asset + # Get all products of the current folder subset_docs = get_subsets( - project_name, asset_ids=[asset_id], fields=["name"] + project_name, asset_ids=[folder_id], fields=["name"] ) - existing_subset_names = { + existing_product_names = { subset_doc["name"] for subset_doc in subset_docs } - existing_subset_names_low = set( + existing_product_names_low = set( _name.lower() - for _name in existing_subset_names + for _name in existing_product_names ) # Defaults to dropdown @@ -296,26 +295,26 @@ class CreatorWindow(QtWidgets.QDialog): # Replace compare_regex = re.compile(re.sub( - user_input_text, "(.+)", subset_name, flags=re.IGNORECASE + user_input_text, "(.+)", product_name, flags=re.IGNORECASE )) - subset_hints = set() + variant_hints = set() if user_input_text: - for _name in existing_subset_names: + for _name in existing_product_names: _result = compare_regex.search(_name) if _result: - subset_hints |= set(_result.groups()) + variant_hints |= set(_result.groups()) - if subset_hints: + if variant_hints: if defaults: defaults.append(SEPARATOR) - defaults.extend(subset_hints) + defaults.extend(variant_hints) self._build_menu(defaults) - # Indicate subset existence + # Indicate product existence if not user_input_text: self._variant_input.as_empty() - elif subset_name.lower() in existing_subset_names_low: - # validate existence of subset name with lowered text + elif product_name.lower() in existing_product_names_low: + # validate existence of product name with lowered text # - "renderMain" vs. "rensermain" mean same path item for # windows self._variant_input.as_exists() @@ -323,7 +322,7 @@ class CreatorWindow(QtWidgets.QDialog): self._variant_input.as_new() # Update the valid state - valid = subset_name.strip() != "" + valid = product_name.strip() != "" self._set_valid_state(valid) @@ -373,7 +372,7 @@ class CreatorWindow(QtWidgets.QDialog): self.setStyleSheet(style.load_stylesheet()) def refresh(self): - self._asset_name_input.setText(get_current_asset_name()) + self._folder_path_input.setText(get_current_asset_name()) self._creators_model.reset() @@ -385,7 +384,7 @@ class CreatorWindow(QtWidgets.QDialog): ["product_types_smart_select"] ) current_index = None - family = None + product_type = None task_name = get_current_task_name() or None lowered_task_name = task_name.lower() if task_name: @@ -395,13 +394,15 @@ class CreatorWindow(QtWidgets.QDialog): } for _task_name in _low_task_names: if _task_name in lowered_task_name: - family = smart_item["name"] + product_type = smart_item["name"] break - if family: + if product_type: break - if family: - indexes = self._creators_model.get_indexes_by_family(family) + if product_type: + indexes = self._creators_model.get_indexes_by_product_type( + product_type + ) if indexes: index = indexes[0] current_index = self._creators_proxy.mapFromSource(index) @@ -422,8 +423,8 @@ class CreatorWindow(QtWidgets.QDialog): if creator_plugin is None: return - subset_name = self._subset_name_input.text() - asset_name = self._asset_name_input.text() + product_name = self._product_name_input.text() + folder_path = self._folder_path_input.text() use_selection = self._useselection_chk.isChecked() variant = self._variant_input.text() @@ -432,8 +433,8 @@ class CreatorWindow(QtWidgets.QDialog): try: legacy_create( creator_plugin, - subset_name, - asset_name, + product_name, + folder_path, options={"useSelection": use_selection}, data={"variant": variant} ) @@ -453,9 +454,9 @@ class CreatorWindow(QtWidgets.QDialog): if error_info: box = CreateErrorMessageBox( - creator_plugin.family, - subset_name, - asset_name, + creator_plugin.product_type, + product_name, + folder_path, *error_info, parent=self ) @@ -464,7 +465,7 @@ class CreatorWindow(QtWidgets.QDialog): self._message_dialog = box else: - self.echo("Created %s .." % subset_name) + self.echo("Created %s .." % product_name) def _on_msg_timer(self): self._msg_label.setText("") @@ -475,7 +476,7 @@ class CreatorWindow(QtWidgets.QDialog): def show(parent=None): - """Display asset creator GUI + """Display product creator GUI Arguments: debug (bool, optional): Run loader in debug-mode,