use folder naming in widgets

This commit is contained in:
Jakub Trllo 2024-02-28 16:11:38 +01:00
parent de2f48ff54
commit 259983768c
2 changed files with 90 additions and 90 deletions

View file

@ -31,11 +31,11 @@ class FoldersDialogController:
pass
class AssetsDialog(QtWidgets.QDialog):
class FoldersDialog(QtWidgets.QDialog):
"""Dialog to select folder for a context of instance."""
def __init__(self, controller, parent):
super(AssetsDialog, self).__init__(parent)
super(FoldersDialog, self).__init__(parent)
self.setWindowTitle("Select folder")
filter_input = PlaceholderLineEdit(self)
@ -99,7 +99,7 @@ class AssetsDialog(QtWidgets.QDialog):
def showEvent(self, event):
"""Refresh folders widget on show."""
super(AssetsDialog, self).showEvent(event)
super(FoldersDialog, self).showEvent(event)
if self._first_show:
self._first_show = False
self._on_first_show()

View file

@ -26,7 +26,7 @@ from ayon_core.pipeline.create import (
TaskNotSetError,
)
from .thumbnail_widget import ThumbnailWidget
from .assets_dialog import AssetsDialog
from .folders_dialog import FoldersDialog
from .tasks_widget import TasksModel
from .icons import (
get_pixmap,
@ -422,20 +422,20 @@ class ClickableLineEdit(QtWidgets.QLineEdit):
event.accept()
class AssetsField(BaseClickableFrame):
"""Field where asset name of selected instance/s is showed.
class FoldersFields(BaseClickableFrame):
"""Field where folder path of selected instance/s is showed.
Click on the field will trigger `AssetsDialog`.
Click on the field will trigger `FoldersDialog`.
"""
value_changed = QtCore.Signal()
def __init__(self, controller, parent):
super(AssetsField, self).__init__(parent)
super(FoldersFields, self).__init__(parent)
self.setObjectName("AssetNameInputWidget")
# Don't use 'self' for parent!
# - this widget has specific styles
dialog = AssetsDialog(controller, parent)
dialog = FoldersDialog(controller, parent)
name_input = ClickableLineEdit(self)
name_input.setObjectName("AssetNameInput")
@ -481,15 +481,15 @@ class AssetsField(BaseClickableFrame):
if not result:
return
asset_name = self._dialog.get_selected_folder_path()
if asset_name is None:
folder_path = self._dialog.get_selected_folder_path()
if folder_path is None:
return
self._selected_items = [asset_name]
self._selected_items = [folder_path]
self._has_value_changed = (
self._origin_value != self._selected_items
)
self.set_text(asset_name)
self.set_text(folder_path)
self._set_is_valid(True)
self.value_changed.emit()
@ -499,10 +499,10 @@ class AssetsField(BaseClickableFrame):
self._dialog.open()
def set_multiselection_text(self, text):
"""Change text for multiselection of different assets.
"""Change text for multiselection of different folders.
When there are selected multiple instances at once and they don't have
same asset in context.
same folder in context.
"""
self._multiselection_text = text
@ -521,30 +521,30 @@ class AssetsField(BaseClickableFrame):
set_style_property(self._icon_btn, "state", state)
def is_valid(self):
"""Is asset valid."""
"""Is folder valid."""
return self._is_valid
def has_value_changed(self):
"""Value of asset has changed."""
"""Value of folder has changed."""
return self._has_value_changed
def get_selected_items(self):
"""Selected asset names."""
"""Selected folder paths."""
return list(self._selected_items)
def set_text(self, text):
"""Set text in text field.
Does not change selected items (assets).
Does not change selected items (folders).
"""
self._name_input.setText(text)
self._name_input.end(False)
def set_selected_items(self, folder_paths=None):
"""Set asset names for selection of instances.
"""Set folder paths for selection of instances.
Passed asset names are validated and if there are 2 or more different
asset names then multiselection text is shown.
Passed folder paths are validated and if there are 2 or more different
folder paths then multiselection text is shown.
Args:
folder_paths (list, tuple, set, NoneType): List of folder paths.
@ -572,7 +572,7 @@ class AssetsField(BaseClickableFrame):
self._set_is_valid(is_valid)
def reset_to_origin(self):
"""Change to asset names set with last `set_selected_items` call."""
"""Change to folder paths set with last `set_selected_items` call."""
self.set_selected_items(self._origin_value)
def confirm_value(self):
@ -606,9 +606,9 @@ class TasksCombobox(QtWidgets.QComboBox):
"""Combobox to show tasks for selected instances.
Combobox gives ability to select only from intersection of task names for
asset names in selected instances.
folder paths in selected instances.
If asset names in selected instances does not have same tasks then combobox
If folder paths in selected instances does not have same tasks then combobox
will be empty.
"""
value_changed = QtCore.Signal()
@ -742,23 +742,23 @@ class TasksCombobox(QtWidgets.QComboBox):
"""
return list(self._selected_items)
def set_folder_paths(self, asset_names):
"""Set asset names for which should show tasks."""
def set_folder_paths(self, folder_paths):
"""Set folder paths for which should show tasks."""
self._ignore_index_change = True
self._model.set_folder_paths(asset_names)
self._model.set_folder_paths(folder_paths)
self._proxy_model.set_filter_empty(False)
self._proxy_model.sort(0)
self._ignore_index_change = False
# It is a bug if not exactly one asset got here
if len(asset_names) != 1:
# It is a bug if not exactly one folder got here
if len(folder_paths) != 1:
self.set_selected_item("")
self._set_is_valid(False)
return
asset_name = tuple(asset_names)[0]
folder_path = tuple(folder_paths)[0]
is_valid = False
if self._selected_items:
@ -766,7 +766,7 @@ class TasksCombobox(QtWidgets.QComboBox):
valid_task_names = []
for task_name in self._selected_items:
_is_valid = self._model.is_task_name_valid(asset_name, task_name)
_is_valid = self._model.is_task_name_valid(folder_path, task_name)
if _is_valid:
valid_task_names.append(task_name)
else:
@ -787,42 +787,42 @@ class TasksCombobox(QtWidgets.QComboBox):
self._set_is_valid(is_valid)
def confirm_value(self, asset_names):
def confirm_value(self, folder_paths):
new_task_name = self._selected_items[0]
self._origin_value = [
(asset_name, new_task_name)
for asset_name in asset_names
(folder_path, new_task_name)
for folder_path in folder_paths
]
self._origin_selection = copy.deepcopy(self._selected_items)
self._has_value_changed = False
def set_selected_items(self, asset_task_combinations=None):
def set_selected_items(self, folder_task_combinations=None):
"""Set items for selected instances.
Args:
asset_task_combinations (list): List of tuples. Each item in
the list contain asset name and task name.
folder_task_combinations (list): List of tuples. Each item in
the list contain folder path and task name.
"""
self._proxy_model.set_filter_empty(False)
self._proxy_model.sort(0)
if asset_task_combinations is None:
asset_task_combinations = []
if folder_task_combinations is None:
folder_task_combinations = []
task_names = set()
task_names_by_asset_name = collections.defaultdict(set)
for asset_name, task_name in asset_task_combinations:
task_names_by_folder_path = collections.defaultdict(set)
for folder_path, task_name in folder_task_combinations:
task_names.add(task_name)
task_names_by_asset_name[asset_name].add(task_name)
asset_names = set(task_names_by_asset_name.keys())
task_names_by_folder_path[folder_path].add(task_name)
folder_paths = set(task_names_by_folder_path.keys())
self._ignore_index_change = True
self._model.set_folder_paths(asset_names)
self._model.set_folder_paths(folder_paths)
self._has_value_changed = False
self._origin_value = copy.deepcopy(asset_task_combinations)
self._origin_value = copy.deepcopy(folder_task_combinations)
self._origin_selection = list(task_names)
self._selected_items = list(task_names)
@ -836,9 +836,9 @@ class TasksCombobox(QtWidgets.QComboBox):
task_name = tuple(task_names)[0]
idx = self.findText(task_name)
is_valid = not idx < 0
if not is_valid and len(asset_names) > 1:
is_valid = self._validate_task_names_by_asset_names(
task_names_by_asset_name
if not is_valid and len(folder_paths) > 1:
is_valid = self._validate_task_names_by_folder_paths(
task_names_by_folder_path
)
self.set_selected_item(task_name)
@ -849,9 +849,9 @@ class TasksCombobox(QtWidgets.QComboBox):
if not is_valid:
break
if not is_valid and len(asset_names) > 1:
is_valid = self._validate_task_names_by_asset_names(
task_names_by_asset_name
if not is_valid and len(folder_paths) > 1:
is_valid = self._validate_task_names_by_folder_paths(
task_names_by_folder_path
)
multiselection_text = self._multiselection_text
if multiselection_text is None:
@ -864,10 +864,10 @@ class TasksCombobox(QtWidgets.QComboBox):
self.value_changed.emit()
def _validate_task_names_by_asset_names(self, task_names_by_asset_name):
for asset_name, task_names in task_names_by_asset_name.items():
def _validate_task_names_by_folder_paths(self, task_names_by_folder_path):
for folder_path, task_names in task_names_by_folder_path.items():
for task_name in task_names:
if not self._model.is_task_name_valid(asset_name, task_name):
if not self._model.is_task_name_valid(folder_path, task_name):
return False
return True
@ -1102,17 +1102,17 @@ class GlobalAttrsWidget(QtWidgets.QWidget):
self._current_instances = []
variant_input = VariantInputWidget(self)
asset_value_widget = AssetsField(controller, self)
folder_value_widget = FoldersFields(controller, self)
task_value_widget = TasksCombobox(controller, self)
product_type_value_widget = MultipleItemWidget(self)
product_value_widget = MultipleItemWidget(self)
variant_input.set_multiselection_text(self.multiselection_text)
asset_value_widget.set_multiselection_text(self.multiselection_text)
folder_value_widget.set_multiselection_text(self.multiselection_text)
task_value_widget.set_multiselection_text(self.multiselection_text)
variant_input.set_value()
asset_value_widget.set_selected_items()
folder_value_widget.set_selected_items()
task_value_widget.set_selected_items()
product_type_value_widget.set_value()
product_value_widget.set_value()
@ -1133,20 +1133,20 @@ class GlobalAttrsWidget(QtWidgets.QWidget):
main_layout.setHorizontalSpacing(INPUTS_LAYOUT_HSPACING)
main_layout.setVerticalSpacing(INPUTS_LAYOUT_VSPACING)
main_layout.addRow("Variant", variant_input)
main_layout.addRow("Folder", asset_value_widget)
main_layout.addRow("Folder", folder_value_widget)
main_layout.addRow("Task", task_value_widget)
main_layout.addRow("Product type", product_type_value_widget)
main_layout.addRow("Product name", product_value_widget)
main_layout.addRow(btns_layout)
variant_input.value_changed.connect(self._on_variant_change)
asset_value_widget.value_changed.connect(self._on_asset_change)
folder_value_widget.value_changed.connect(self._on_folder_change)
task_value_widget.value_changed.connect(self._on_task_change)
submit_btn.clicked.connect(self._on_submit)
cancel_btn.clicked.connect(self._on_cancel)
self.variant_input = variant_input
self.asset_value_widget = asset_value_widget
self.folder_value_widget = folder_value_widget
self.task_value_widget = task_value_widget
self.product_type_value_widget = product_type_value_widget
self.product_value_widget = product_value_widget
@ -1157,40 +1157,40 @@ class GlobalAttrsWidget(QtWidgets.QWidget):
"""Commit changes for selected instances."""
variant_value = None
asset_name = None
folder_path = None
task_name = None
if self.variant_input.has_value_changed():
variant_value = self.variant_input.get_value()[0]
if self.asset_value_widget.has_value_changed():
asset_name = self.asset_value_widget.get_selected_items()[0]
if self.folder_value_widget.has_value_changed():
folder_path = self.folder_value_widget.get_selected_items()[0]
if self.task_value_widget.has_value_changed():
task_name = self.task_value_widget.get_selected_items()[0]
product_names = set()
invalid_tasks = False
asset_names = []
folder_paths = []
for instance in self._current_instances:
new_variant_value = instance.get("variant")
new_asset_name = instance.get("folderPath")
new_folder_path = instance.get("folderPath")
new_task_name = instance.get("task")
if variant_value is not None:
new_variant_value = variant_value
if asset_name is not None:
new_asset_name = asset_name
if folder_path is not None:
new_folder_path = folder_path
if task_name is not None:
new_task_name = task_name
asset_names.append(new_asset_name)
folder_paths.append(new_folder_path)
try:
new_product_name = self._controller.get_product_name(
instance.creator_identifier,
new_variant_value,
new_task_name,
new_asset_name,
new_folder_path,
instance.id,
)
@ -1204,8 +1204,8 @@ class GlobalAttrsWidget(QtWidgets.QWidget):
if variant_value is not None:
instance["variant"] = variant_value
if asset_name is not None:
instance["folderPath"] = asset_name
if folder_path is not None:
instance["folderPath"] = folder_path
instance.set_asset_invalid(False)
if task_name is not None:
@ -1225,11 +1225,11 @@ class GlobalAttrsWidget(QtWidgets.QWidget):
if variant_value is not None:
self.variant_input.confirm_value()
if asset_name is not None:
self.asset_value_widget.confirm_value()
if folder_path is not None:
self.folder_value_widget.confirm_value()
if task_name is not None:
self.task_value_widget.confirm_value(asset_names)
self.task_value_widget.confirm_value(folder_paths)
self.instance_context_changed.emit()
@ -1237,19 +1237,19 @@ class GlobalAttrsWidget(QtWidgets.QWidget):
"""Cancel changes and set back to their irigin value."""
self.variant_input.reset_to_origin()
self.asset_value_widget.reset_to_origin()
self.folder_value_widget.reset_to_origin()
self.task_value_widget.reset_to_origin()
self._set_btns_enabled(False)
def _on_value_change(self):
any_invalid = (
not self.variant_input.is_valid()
or not self.asset_value_widget.is_valid()
or not self.folder_value_widget.is_valid()
or not self.task_value_widget.is_valid()
)
any_changed = (
self.variant_input.has_value_changed()
or self.asset_value_widget.has_value_changed()
or self.folder_value_widget.has_value_changed()
or self.task_value_widget.has_value_changed()
)
self._set_btns_visible(any_changed or any_invalid)
@ -1259,9 +1259,9 @@ class GlobalAttrsWidget(QtWidgets.QWidget):
def _on_variant_change(self):
self._on_value_change()
def _on_asset_change(self):
asset_names = self.asset_value_widget.get_selected_items()
self.task_value_widget.set_folder_paths(asset_names)
def _on_folder_change(self):
folder_paths = self.folder_value_widget.get_selected_items()
self.task_value_widget.set_folder_paths(folder_paths)
self._on_value_change()
def _on_task_change(self):
@ -1286,7 +1286,7 @@ class GlobalAttrsWidget(QtWidgets.QWidget):
self._current_instances = instances
asset_names = set()
folder_paths = set()
variants = set()
product_types = set()
product_names = set()
@ -1295,7 +1295,7 @@ class GlobalAttrsWidget(QtWidgets.QWidget):
if len(instances) == 0:
editable = False
asset_task_combinations = []
folder_task_combinations = []
for instance in instances:
# NOTE I'm not sure how this can even happen?
if instance.creator_identifier is None:
@ -1303,23 +1303,23 @@ class GlobalAttrsWidget(QtWidgets.QWidget):
variants.add(instance.get("variant") or self.unknown_value)
product_types.add(instance.get("productType") or self.unknown_value)
asset_name = instance.get("folderPath") or self.unknown_value
folder_path = instance.get("folderPath") or self.unknown_value
task_name = instance.get("task") or ""
asset_names.add(asset_name)
asset_task_combinations.append((asset_name, task_name))
folder_paths.add(folder_path)
folder_task_combinations.append((folder_path, task_name))
product_names.add(instance.get("productName") or self.unknown_value)
self.variant_input.set_value(variants)
# Set context of asset widget
self.asset_value_widget.set_selected_items(asset_names)
# Set context of folder widget
self.folder_value_widget.set_selected_items(folder_paths)
# Set context of task widget
self.task_value_widget.set_selected_items(asset_task_combinations)
self.task_value_widget.set_selected_items(folder_task_combinations)
self.product_type_value_widget.set_value(product_types)
self.product_value_widget.set_value(product_names)
self.variant_input.setEnabled(editable)
self.asset_value_widget.setEnabled(editable)
self.folder_value_widget.setEnabled(editable)
self.task_value_widget.setEnabled(editable)