initial commit

This commit is contained in:
Jakub Trllo 2024-02-28 14:30:59 +01:00
parent 65865c2e8f
commit 175185d177
8 changed files with 324 additions and 469 deletions

View file

@ -14,12 +14,10 @@ import arrow
import pyblish.api
from ayon_core.client import (
get_assets,
get_asset_by_id,
get_asset_by_name,
get_subsets,
get_asset_name_identifier,
)
from ayon_core.lib.events import EventSystem
from ayon_core.lib.events import QueuedEventSystem
from ayon_core.lib.attribute_definitions import (
UIDef,
serialize_attr_defs,
@ -43,6 +41,7 @@ from ayon_core.pipeline.create.context import (
ConvertorsOperationFailed,
)
from ayon_core.pipeline.publish import get_publish_instance_label
from ayon_core.tools.ayon_utils.models import HierarchyModel
# Define constant for plugin orders offset
PLUGIN_ORDER_OFFSET = 0.5
@ -69,101 +68,17 @@ class MainThreadItem:
class AssetDocsCache:
"""Cache asset documents for creation part."""
projection = {
"_id": True,
"name": True,
"data.visualParent": True,
"data.tasks": True,
"data.parents": True,
}
def __init__(self, controller):
self._controller = controller
self._asset_docs = None
self._asset_docs_hierarchy = None
self._task_names_by_asset_name = {}
self._asset_docs_by_name = {}
self._full_asset_docs_by_name = {}
def reset(self):
self._asset_docs = None
self._asset_docs_hierarchy = None
self._task_names_by_asset_name = {}
self._asset_docs_by_name = {}
self._full_asset_docs_by_name = {}
def _query(self):
if self._asset_docs is not None:
return
project_name = self._controller.project_name
asset_docs = list(get_assets(
project_name, fields=self.projection.keys()
))
asset_docs_by_name = {}
task_names_by_asset_name = {}
for asset_doc in asset_docs:
if "data" not in asset_doc:
asset_doc["data"] = {"tasks": {}, "visualParent": None}
elif "tasks" not in asset_doc["data"]:
asset_doc["data"]["tasks"] = {}
asset_name = get_asset_name_identifier(asset_doc)
asset_tasks = asset_doc["data"]["tasks"]
task_names_by_asset_name[asset_name] = list(asset_tasks.keys())
asset_docs_by_name[asset_name] = asset_doc
self._asset_docs = asset_docs
self._asset_docs_by_name = asset_docs_by_name
self._task_names_by_asset_name = task_names_by_asset_name
def get_asset_docs(self):
self._query()
return copy.deepcopy(self._asset_docs)
def get_asset_hierarchy(self):
"""Prepare asset documents into hierarchy.
Convert ObjectId to string. Asset id is not used during whole
process of publisher but asset name is used rather.
Returns:
Dict[Union[str, None]: Any]: Mapping of parent id to it's children.
Top level assets have parent id 'None'.
"""
if self._asset_docs_hierarchy is None:
_queue = collections.deque(self.get_asset_docs())
output = collections.defaultdict(list)
while _queue:
asset_doc = _queue.popleft()
asset_doc["_id"] = str(asset_doc["_id"])
parent_id = asset_doc["data"]["visualParent"]
if parent_id is not None:
parent_id = str(parent_id)
asset_doc["data"]["visualParent"] = parent_id
output[parent_id].append(asset_doc)
self._asset_docs_hierarchy = output
return copy.deepcopy(self._asset_docs_hierarchy)
def get_task_names_by_asset_name(self):
self._query()
return copy.deepcopy(self._task_names_by_asset_name)
def get_asset_by_name(self, asset_name):
self._query()
asset_doc = self._asset_docs_by_name.get(asset_name)
if asset_doc is None:
return None
return copy.deepcopy(asset_doc)
def get_full_asset_by_name(self, asset_name):
self._query()
if asset_name not in self._full_asset_docs_by_name:
asset_doc = self._asset_docs_by_name.get(asset_name)
project_name = self._controller.project_name
full_asset_doc = get_asset_by_id(project_name, asset_doc["_id"])
full_asset_doc = get_asset_by_name(project_name, asset_name)
self._full_asset_docs_by_name[asset_name] = full_asset_doc
return copy.deepcopy(self._full_asset_docs_by_name[asset_name])
@ -1104,18 +1019,6 @@ class AbstractPublisherController(object):
pass
@abstractmethod
def get_asset_docs(self):
pass
@abstractmethod
def get_asset_hierarchy(self):
pass
@abstractmethod
def get_task_names_by_asset_names(self, asset_names):
pass
@abstractmethod
def get_existing_subset_names(self, asset_name):
pass
@ -1499,13 +1402,22 @@ class BasePublisherController(AbstractPublisherController):
"""
if self._event_system is None:
self._event_system = EventSystem()
self._event_system = QueuedEventSystem()
return self._event_system
def _emit_event(self, topic, data=None):
# Events system
def emit_event(self, topic, data=None, source=None):
"""Use implemented event system to trigger event."""
if data is None:
data = {}
self.event_system.emit(topic, data, "controller")
self.event_system.emit(topic, data, source)
def register_event_callback(self, topic, callback):
self.event_system.add_callback(topic, callback)
def _emit_event(self, topic, data=None):
self.emit_event(topic, data, "controller")
def _get_host_is_valid(self):
return self._host_is_valid
@ -1738,6 +1650,7 @@ class PublisherController(BasePublisherController):
self._resetting_instances = False
# Cacher of avalon documents
self._hierarchy_model = HierarchyModel(self)
self._asset_docs_cache = AssetDocsCache(self)
@property
@ -1794,11 +1707,24 @@ class PublisherController(BasePublisherController):
"""Publish plugins."""
return self._create_context.publish_plugins
# --- Publish specific callbacks ---
def get_asset_docs(self):
"""Get asset documents from cache for whole project."""
return self._asset_docs_cache.get_asset_docs()
# Hierarchy model
def get_folder_items(self, project_name, sender=None):
return self._hierarchy_model.get_folder_items(project_name, sender)
def get_task_items(self, project_name, folder_id, sender=None):
return self._hierarchy_model.get_task_items(
project_name, folder_id, sender
)
def get_folder_entity(self, project_name, folder_id):
return self._hierarchy_model.get_folder_entity(
project_name, folder_id
)
def get_task_entity(self, project_name, task_id):
return self._hierarchy_model.get_task_entity(project_name, task_id)
# --- Publish specific callbacks ---
def get_context_title(self):
"""Get context title for artist shown at the top of main window."""
@ -1813,32 +1739,18 @@ class PublisherController(BasePublisherController):
return context_title
def get_asset_hierarchy(self):
"""Prepare asset documents into hierarchy."""
return self._asset_docs_cache.get_asset_hierarchy()
def get_task_names_by_asset_names(self, asset_names):
"""Prepare task names by asset name."""
task_names_by_asset_name = (
self._asset_docs_cache.get_task_names_by_asset_name()
)
result = {}
for asset_name in asset_names:
result[asset_name] = set(
task_names_by_asset_name.get(asset_name) or []
)
return result
def get_existing_subset_names(self, asset_name):
project_name = self.project_name
asset_doc = self._asset_docs_cache.get_asset_by_name(asset_name)
if not asset_doc:
folder_item = self._hierarchy_model.get_folder_item_by_path(
project_name, asset_name
)
if not folder_item:
return None
asset_id = asset_doc["_id"]
subset_docs = get_subsets(
project_name, asset_ids=[asset_id], fields=["name"]
project_name,
asset_ids=[folder_item.entity_id],
fields=["name"]
)
return {
subset_doc["name"]
@ -1858,8 +1770,6 @@ class PublisherController(BasePublisherController):
# Reset avalon context
self._create_context.reset_current_context()
self._asset_docs_cache.reset()
self._reset_plugins()
# Publish part must be reset after plugins
self._reset_publish()

View file

@ -251,15 +251,9 @@ class QtRemotePublishController(BasePublisherController):
pass
def get_asset_docs(self):
pass
def get_asset_hierarchy(self):
pass
def get_task_names_by_asset_names(self, asset_names):
pass
def get_existing_subset_names(self, asset_name):
pass

View file

@ -2,99 +2,13 @@ import collections
from qtpy import QtWidgets, QtCore, QtGui
from ayon_core.tools.utils.assets_widget import (
get_asset_icon,
)
from ayon_core.tools.utils import (
PlaceholderLineEdit,
RecursiveSortFilterProxyModel,
)
from ayon_core.tools.utils.assets_widget import (
SingleSelectAssetsWidget,
ASSET_ID_ROLE,
ASSET_NAME_ROLE,
ASSET_PATH_ROLE,
get_asset_icon,
)
class CreateWidgetAssetsWidget(SingleSelectAssetsWidget):
current_context_required = QtCore.Signal()
header_height_changed = QtCore.Signal(int)
def __init__(self, controller, parent):
self._controller = controller
super(CreateWidgetAssetsWidget, self).__init__(parent)
self.set_refresh_btn_visibility(False)
self.set_current_asset_btn_visibility(False)
self._last_selection = None
self._enabled = None
self._last_filter_height = None
def get_project_name(self):
return self._controller.project_name
def get_selected_asset_name(self):
selection_model = self._view.selectionModel()
indexes = selection_model.selectedRows()
for index in indexes:
return index.data(ASSET_PATH_ROLE)
return None
def _check_header_height(self):
"""Catch header height changes.
Label on top of creaters should have same height so Creators view has
same offset.
"""
height = self.header_widget.height()
if height != self._last_filter_height:
self._last_filter_height = height
self.header_height_changed.emit(height)
def resizeEvent(self, event):
super(CreateWidgetAssetsWidget, self).resizeEvent(event)
self._check_header_height()
def showEvent(self, event):
super(CreateWidgetAssetsWidget, self).showEvent(event)
self._check_header_height()
def _on_current_asset_click(self):
self.current_context_required.emit()
def set_enabled(self, enabled):
if self._enabled == enabled:
return
self._enabled = enabled
if not enabled:
self._last_selection = self.get_selected_asset_id()
self._clear_selection()
elif self._last_selection is not None:
self.select_asset(self._last_selection)
def _select_indexes(self, *args, **kwargs):
super(CreateWidgetAssetsWidget, self)._select_indexes(*args, **kwargs)
if self._enabled:
return
self._last_selection = self.get_selected_asset_id()
self._clear_selection()
def update_current_asset(self):
# Hide set current asset if there is no one
asset_name = self._get_current_asset_name()
self.set_current_asset_btn_visibility(bool(asset_name))
def _get_current_asset_name(self):
return self._controller.current_asset_name
def _create_source_model(self):
return AssetsHierarchyModel(self._controller)
def _refresh_model(self):
self._model.reset()
self._on_model_refresh(self._model.rowCount() > 0)
class AssetsHierarchyModel(QtGui.QStandardItemModel):
"""Assets hierarchy model.
@ -119,7 +33,8 @@ class AssetsHierarchyModel(QtGui.QStandardItemModel):
self._items_by_name = {}
self._items_by_path = {}
self._items_by_asset_id = {}
assets_by_parent_id = self._controller.get_asset_hierarchy()
# assets_by_parent_id = self._controller.get_asset_hierarchy()
assets_by_parent_id = {}
items_by_name = {}
items_by_path = {}

View file

@ -0,0 +1,239 @@
from qtpy import QtWidgets, QtCore, QtGui
from ayon_core.lib.events import QueuedEventSystem
from ayon_core.tools.utils import PlaceholderLineEdit
from ayon_core.tools.ayon_utils.widgets import FoldersWidget, TasksWidget
class CreateSelectionModel(object):
"""Model handling selection changes.
Triggering events:
- "selection.project.changed"
- "selection.folder.changed"
- "selection.task.changed"
"""
event_source = "publisher.create.selection.model"
def __init__(self, controller):
self._controller = controller
self._project_name = None
self._folder_id = None
self._task_name = None
self._task_id = None
def get_selected_project_name(self):
return self._project_name
def set_selected_project(self, project_name):
if project_name == self._project_name:
return
self._project_name = project_name
self._controller.emit_event(
"selection.project.changed",
{"project_name": project_name},
self.event_source
)
def get_selected_folder_id(self):
return self._folder_id
def set_selected_folder(self, folder_id):
print(folder_id, self._folder_id)
if folder_id == self._folder_id:
return
self._folder_id = folder_id
self._controller.emit_event(
"selection.folder.changed",
{
"project_name": self._project_name,
"folder_id": folder_id,
},
self.event_source
)
def get_selected_task_name(self):
return self._task_name
def get_selected_task_id(self):
return self._task_id
def set_selected_task(self, task_id, task_name):
if task_id == self._task_id:
return
self._task_name = task_name
self._task_id = task_id
self._controller.emit_event(
"selection.task.changed",
{
"project_name": self._project_name,
"folder_id": self._folder_id,
"task_name": task_name,
"task_id": task_id,
},
self.event_source
)
class CreateHierarchyController:
def __init__(self, controller):
self._event_system = QueuedEventSystem()
self._controller = controller
self._selection_model = CreateSelectionModel(controller)
# Events system
@property
def event_system(self):
return self._event_system
def emit_event(self, topic, data=None, source=None):
"""Use implemented event system to trigger event."""
if data is None:
data = {}
print("emit_event", topic, data, source)
self.event_system.emit(topic, data, source)
def register_event_callback(self, topic, callback):
self.event_system.add_callback(topic, callback)
def get_project_name(self):
return self._controller.project_name
def get_folder_items(self, project_name, sender=None):
return self._controller.get_folder_items(project_name, sender)
def get_task_items(self, project_name, folder_id, sender=None):
return self._controller.get_task_items(
project_name, folder_id, sender
)
# Selection model
def set_selected_project(self, project_name):
self._selection_model.set_selected_project(project_name)
def set_selected_folder(self, folder_id):
self._selection_model.set_selected_folder(folder_id)
def set_selected_task(self, task_id, task_name):
self._selection_model.set_selected_task(task_id, task_name)
class CreateContextWidget(QtWidgets.QWidget):
folder_changed = QtCore.Signal()
task_changed = QtCore.Signal()
def __init__(self, controller, parent):
super(CreateContextWidget, self).__init__(parent)
self._controller = controller
self._enabled = True
self._last_folder_id = None
self._last_selected_task_name = None
headers_widget = QtWidgets.QWidget(self)
folder_filter_input = PlaceholderLineEdit(headers_widget)
folder_filter_input.setPlaceholderText("Filter folders..")
current_context_btn = QtWidgets.QPushButton(
"Go to current context", headers_widget
)
current_context_btn.setToolTip("Go to current context")
current_context_btn.setVisible(False)
headers_layout = QtWidgets.QHBoxLayout(headers_widget)
headers_layout.setContentsMargins(0, 0, 0, 0)
headers_layout.addWidget(folder_filter_input, 1)
headers_layout.addWidget(current_context_btn, 0)
hierarchy_controller = CreateHierarchyController(controller)
folders_widget = FoldersWidget(hierarchy_controller, self)
tasks_widget = TasksWidget(hierarchy_controller, self)
main_layout = QtWidgets.QVBoxLayout(self)
main_layout.setContentsMargins(0, 0, 0, 0)
main_layout.setSpacing(0)
main_layout.addWidget(headers_widget, 0)
main_layout.addWidget(folders_widget, 2)
main_layout.addWidget(tasks_widget, 1)
folders_widget.selection_changed.connect(self._on_folder_change)
tasks_widget.selection_changed.connect(self._on_task_change)
current_context_btn.clicked.connect(self._on_current_context_click)
self._folder_filter_input = folder_filter_input
self._current_context_btn = current_context_btn
self._folders_widget = folders_widget
self._tasks_widget = tasks_widget
self._hierarchy_controller = hierarchy_controller
def get_selected_folder_id(self):
return self._folders_widget.get_selected_folder_id()
def get_selected_folder_path(self):
return self._folders_widget.get_selected_folder_path()
def get_selected_task_name(self):
return self._tasks_widget.get_selected_task_name()
def get_selected_task_type(self):
return self._tasks_widget.get_selected_task_type()
def update_current_context_btn(self):
# Hide set current asset if there is no one
folder_path = self._controller.current_asset_name
self._current_context_btn.setVisible(bool(folder_path))
def set_selected_context(self, folder_path, task_name):
self._folders_widget.set_selected_folder_path(folder_path)
self._tasks_widget.set_selected_task(task_name)
def is_enabled(self):
return self._enabled
def set_enabled(self, enabled):
if enabled is self._enabled:
return
self.setEnabled(enabled)
self._enabled = enabled
if not enabled:
self._last_folder_id = self.get_selected_folder_id()
self._folders_widget.set_selected_folder(None)
last_selected_task_name = self.get_selected_task_name()
if last_selected_task_name:
self._last_selected_task_name = last_selected_task_name
self._clear_selection()
elif self._last_selected_task_name is not None:
self.set_selected_folder(self._last_folder_id)
self.select_task_name(self._last_selected_task_name)
def refresh(self):
self._hierarchy_controller.set_selected_project(
self._controller.project_name
)
self._folders_widget.set_project_name(self._controller.project_name)
def _clear_selection(self):
self._folders_widget.set_selected_folder(None)
def _on_folder_change(self):
self.folder_changed.emit()
def _on_task_change(self):
self.task_changed.emit()
def _on_current_context_click(self):
# TODO implement
folder_path = self._controller.current_asset_name
task_name = self._controller.current_task_name

View file

@ -14,8 +14,7 @@ from .widgets import (
IconValuePixmapLabel,
CreateBtn,
)
from .assets_widget import CreateWidgetAssetsWidget
from .tasks_widget import CreateWidgetTasksWidget
from .create_context_widgets import CreateContextWidget
from .precreate_widget import PreCreateWidget
from ..constants import (
VARIANT_TOOLTIP,
@ -121,16 +120,7 @@ class CreateWidget(QtWidgets.QWidget):
main_splitter_widget = QtWidgets.QSplitter(self)
context_widget = QtWidgets.QWidget(main_splitter_widget)
assets_widget = CreateWidgetAssetsWidget(controller, context_widget)
tasks_widget = CreateWidgetTasksWidget(controller, context_widget)
context_layout = QtWidgets.QVBoxLayout(context_widget)
context_layout.setContentsMargins(0, 0, 0, 0)
context_layout.setSpacing(0)
context_layout.addWidget(assets_widget, 2)
context_layout.addWidget(tasks_widget, 1)
context_widget = CreateContextWidget(controller, main_splitter_widget)
# --- Creators view ---
creators_widget = QtWidgets.QWidget(main_splitter_widget)
@ -279,11 +269,8 @@ class CreateWidget(QtWidgets.QWidget):
)
variant_hints_btn.clicked.connect(self._on_variant_btn_click)
variant_hints_menu.triggered.connect(self._on_variant_action)
assets_widget.selection_changed.connect(self._on_asset_change)
assets_widget.current_context_required.connect(
self._on_current_session_context_request
)
tasks_widget.task_changed.connect(self._on_task_change)
context_widget.folder_changed.connect(self._on_folder_change)
context_widget.task_changed.connect(self._on_task_change)
thumbnail_widget.thumbnail_created.connect(self._on_thumbnail_create)
thumbnail_widget.thumbnail_cleared.connect(self._on_thumbnail_clear)
@ -299,8 +286,6 @@ class CreateWidget(QtWidgets.QWidget):
self._creators_splitter = creators_splitter
self._context_widget = context_widget
self._assets_widget = assets_widget
self._tasks_widget = tasks_widget
self.subset_name_input = subset_name_input
@ -324,7 +309,7 @@ class CreateWidget(QtWidgets.QWidget):
self._first_show = True
self._last_thumbnail_path = None
self._last_current_context_asset = None
self._last_current_context_folder_path = None
self._last_current_context_task = None
self._use_current_context = True
@ -340,31 +325,35 @@ class CreateWidget(QtWidgets.QWidget):
return self._context_widget.isEnabled()
def _get_asset_name(self):
asset_name = None
folder_path = None
if self._context_change_is_enabled():
asset_name = self._assets_widget.get_selected_asset_name()
folder_path = self._context_widget.get_selected_folder_path()
if asset_name is None:
asset_name = self.current_asset_name
return asset_name or None
if folder_path is None:
folder_path = self.current_asset_name
return folder_path or None
def _get_folder_id(self):
folder_id = None
if self._context_widget.isEnabled():
folder_id = self._context_widget.get_selected_folder_id()
return folder_id
def _get_task_name(self):
task_name = None
if self._context_change_is_enabled():
# Don't use selection of task if asset is not set
asset_name = self._assets_widget.get_selected_asset_name()
if asset_name:
task_name = self._tasks_widget.get_selected_task_name()
folder_path = self._context_widget.get_selected_folder_path()
if folder_path:
task_name = self._context_widget.get_selected_task_name()
if not task_name:
task_name = self.current_task_name
return task_name
def _set_context_enabled(self, enabled):
self._assets_widget.set_enabled(enabled)
self._tasks_widget.set_enabled(enabled)
check_prereq = self._context_widget.isEnabled() != enabled
self._context_widget.setEnabled(enabled)
self._context_widget.set_enabled(enabled)
if check_prereq:
self._invalidate_prereq()
@ -375,12 +364,12 @@ class CreateWidget(QtWidgets.QWidget):
self._use_current_context = True
def refresh(self):
current_asset_name = self._controller.current_asset_name
current_folder_path = self._controller.current_asset_name
current_task_name = self._controller.current_task_name
# Get context before refresh to keep selection of asset and
# task widgets
asset_name = self._get_asset_name()
folder_path = self._get_asset_name()
task_name = self._get_task_name()
# Replace by current context if last loaded context was
@ -388,16 +377,16 @@ class CreateWidget(QtWidgets.QWidget):
if (
self._use_current_context
or (
self._last_current_context_asset
and asset_name == self._last_current_context_asset
self._last_current_context_folder_path
and folder_path == self._last_current_context_folder_path
and task_name == self._last_current_context_task
)
):
asset_name = current_asset_name
folder_path = current_folder_path
task_name = current_task_name
# Store values for future refresh
self._last_current_context_asset = current_asset_name
self._last_current_context_folder_path = current_folder_path
self._last_current_context_task = current_task_name
self._use_current_context = False
@ -407,18 +396,16 @@ class CreateWidget(QtWidgets.QWidget):
# name
self._set_context_enabled(False)
self._assets_widget.refresh()
# Refresh data before update of creators
self._refresh_asset()
self._context_widget.refresh()
self._refresh_product_name()
# Then refresh creators which may trigger callbacks using refreshed
# data
self._refresh_creators()
self._assets_widget.update_current_asset()
self._assets_widget.select_asset_by_name(asset_name)
self._tasks_widget.set_asset_name(asset_name)
self._tasks_widget.select_task_name(task_name)
self._context_widget.update_current_context_btn()
self._context_widget.set_selected_context(folder_path, task_name)
self._invalidate_prereq_deffered()
@ -460,7 +447,7 @@ class CreateWidget(QtWidgets.QWidget):
self._on_variant_change()
def _refresh_asset(self):
def _refresh_product_name(self):
asset_name = self._get_asset_name()
# Skip if asset did not change
@ -545,11 +532,8 @@ class CreateWidget(QtWidgets.QWidget):
# Trigger refresh only if is visible
self.refresh()
def _on_asset_change(self):
self._refresh_asset()
asset_name = self._assets_widget.get_selected_asset_name()
self._tasks_widget.set_asset_name(asset_name)
def _on_folder_change(self):
self._refresh_product_name()
if self._context_change_is_enabled():
self._invalidate_prereq_deffered()
@ -564,12 +548,6 @@ class CreateWidget(QtWidgets.QWidget):
def _on_thumbnail_clear(self):
self._last_thumbnail_path = None
def _on_current_session_context_request(self):
self._assets_widget.select_current_asset()
task_name = self.current_task_name
if task_name:
self._tasks_widget.select_task_name(task_name)
def _on_creator_item_change(self, new_index, _old_index):
identifier = None
if new_index.isValid():
@ -616,7 +594,7 @@ class CreateWidget(QtWidgets.QWidget):
!= self._context_change_is_enabled()
):
self._set_context_enabled(creator_item.create_allow_context_change)
self._refresh_asset()
self._refresh_product_name()
self._thumbnail_widget.setVisible(
creator_item.create_allow_thumbnail

View file

@ -1,6 +1,5 @@
from qtpy import QtWidgets, QtCore, QtGui
from ayon_core.tools.utils.views import DeselectableTreeView
from ayon_core.tools.utils.lib import get_default_task_icon
TASK_NAME_ROLE = QtCore.Qt.UserRole + 1
@ -144,183 +143,3 @@ class TasksModel(QtGui.QStandardItemModel):
return super(TasksModel, self).headerData(section, orientation, role)
class TasksProxyModel(QtCore.QSortFilterProxyModel):
def lessThan(self, x_index, y_index):
x_order = x_index.data(TASK_ORDER_ROLE)
y_order = y_index.data(TASK_ORDER_ROLE)
if x_order is not None and y_order is not None:
if x_order < y_order:
return True
if x_order > y_order:
return False
elif x_order is None and y_order is not None:
return True
elif y_order is None and x_order is not None:
return False
x_name = x_index.data(QtCore.Qt.DisplayRole)
y_name = y_index.data(QtCore.Qt.DisplayRole)
if x_name == y_name:
return True
if x_name == tuple(sorted((x_name, y_name)))[0]:
return True
return False
class CreateWidgetTasksWidget(QtWidgets.QWidget):
"""Widget showing active Tasks
Deprecated:
This widget will be removed soon. Please do not use it in new code.
"""
task_changed = QtCore.Signal()
def __init__(self, controller, parent):
self._controller = controller
self._enabled = None
super(CreateWidgetTasksWidget, self).__init__(parent)
tasks_view = DeselectableTreeView(self)
tasks_view.setIndentation(0)
tasks_view.setSortingEnabled(True)
tasks_view.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
header_view = tasks_view.header()
header_view.setSortIndicator(0, QtCore.Qt.AscendingOrder)
tasks_model = TasksModel(self._controller)
tasks_proxy = TasksProxyModel()
tasks_proxy.setSourceModel(tasks_model)
tasks_view.setModel(tasks_proxy)
layout = QtWidgets.QVBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(tasks_view)
selection_model = tasks_view.selectionModel()
selection_model.selectionChanged.connect(self._on_task_change)
self._tasks_model = tasks_model
self._tasks_proxy = tasks_proxy
self._tasks_view = tasks_view
self._last_selected_task_name = None
def refresh(self):
self._tasks_model.refresh()
def set_asset_id(self, asset_id):
# Try and preserve the last selected task and reselect it
# after switching assets. If there's no currently selected
# asset keep whatever the "last selected" was prior to it.
current = self.get_selected_task_name()
if current:
self._last_selected_task_name = current
self._tasks_model.set_asset_id(asset_id)
if self._last_selected_task_name:
self.select_task_name(self._last_selected_task_name)
# Force a task changed emit.
self.task_changed.emit()
def _clear_selection(self):
selection_model = self._tasks_view.selectionModel()
selection_model.clearSelection()
def select_task_name(self, task_name):
"""Select a task by name.
If the task does not exist in the current model then selection is only
cleared.
Args:
task_name (str): Name of the task to select.
"""
task_view_model = self._tasks_view.model()
if not task_view_model:
return
# Clear selection
selection_model = self._tasks_view.selectionModel()
selection_model.clearSelection()
# Select the task
mode = (
QtCore.QItemSelectionModel.Select
| QtCore.QItemSelectionModel.Rows
)
for row in range(task_view_model.rowCount()):
index = task_view_model.index(row, 0)
name = index.data(TASK_NAME_ROLE)
if name == task_name:
selection_model.select(index, mode)
# Set the currently active index
self._tasks_view.setCurrentIndex(index)
break
last_selected_task_name = self.get_selected_task_name()
if last_selected_task_name:
self._last_selected_task_name = last_selected_task_name
if not self._enabled:
current = self.get_selected_task_name()
if current:
self._last_selected_task_name = current
self._clear_selection()
def get_selected_task_name(self):
"""Return name of task at current index (selected)
Returns:
str: Name of the current task.
"""
index = self._tasks_view.currentIndex()
selection_model = self._tasks_view.selectionModel()
if index.isValid() and selection_model.isSelected(index):
return index.data(TASK_NAME_ROLE)
return None
def get_selected_task_type(self):
index = self._tasks_view.currentIndex()
selection_model = self._tasks_view.selectionModel()
if index.isValid() and selection_model.isSelected(index):
return index.data(TASK_TYPE_ROLE)
return None
def set_asset_name(self, asset_name):
current = self.get_selected_task_name()
if current:
self._last_selected_task_name = current
self._tasks_model.set_asset_names([asset_name])
if self._last_selected_task_name and self._enabled:
self.select_task_name(self._last_selected_task_name)
# Force a task changed emit.
self.task_changed.emit()
def set_enabled(self, enabled):
self._enabled = enabled
if not enabled:
last_selected_task_name = self.get_selected_task_name()
if last_selected_task_name:
self._last_selected_task_name = last_selected_task_name
self._clear_selection()
elif self._last_selected_task_name is not None:
self.select_task_name(self._last_selected_task_name)
def _on_task_change(self):
self.task_changed.emit()

View file

@ -26,7 +26,7 @@ from ayon_core.pipeline.create import (
TaskNotSetError,
)
from .thumbnail_widget import ThumbnailWidget
from .assets_widget import AssetsDialog
from .assets_dialog import AssetsDialog
from .tasks_widget import TasksModel
from .icons import (
get_pixmap,

View file

@ -30,8 +30,8 @@ class TrayPublisherController(QtPublisherController):
def host(self):
return self._host
def reset_project_data_cache(self):
self._asset_docs_cache.reset()
def reset_hierarchy_cache(self):
self._hierarchy_model.reset()
class TrayPublisherRegistry(JSONSettingRegistry):
@ -248,7 +248,7 @@ class TrayPublishWindow(PublisherWindow):
def _on_project_select(self, project_name):
# TODO register project specific plugin paths
self._controller.save_changes(False)
self._controller.reset_project_data_cache()
self._controller.reset_hierarchy_cache()
self.reset()
if not self._controller.instances: