mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 12:54:40 +01:00
base implementation in loader tool
This commit is contained in:
parent
234ac09f42
commit
12d4905b39
6 changed files with 162 additions and 58 deletions
|
|
@ -317,6 +317,7 @@ class ActionItem:
|
|||
use 'identifier' and context, it necessary also use 'options'.
|
||||
|
||||
Args:
|
||||
plugin_identifier (str): Action identifier.
|
||||
identifier (str): Action identifier.
|
||||
entity_ids (set[str]): Entity ids.
|
||||
entity_type (str): Entity type.
|
||||
|
|
@ -330,6 +331,7 @@ class ActionItem:
|
|||
"""
|
||||
def __init__(
|
||||
self,
|
||||
plugin_identifier,
|
||||
identifier,
|
||||
entity_ids,
|
||||
entity_type,
|
||||
|
|
@ -339,6 +341,7 @@ class ActionItem:
|
|||
options,
|
||||
order,
|
||||
):
|
||||
self.plugin_identifier = plugin_identifier
|
||||
self.identifier = identifier
|
||||
self.entity_ids = entity_ids
|
||||
self.entity_type = entity_type
|
||||
|
|
@ -367,6 +370,7 @@ class ActionItem:
|
|||
def to_data(self):
|
||||
options = self._options_to_data()
|
||||
return {
|
||||
"plugin_identifier": self.plugin_identifier,
|
||||
"identifier": self.identifier,
|
||||
"entity_ids": list(self.entity_ids),
|
||||
"entity_type": self.entity_type,
|
||||
|
|
@ -992,11 +996,14 @@ class FrontendLoaderController(_BaseLoaderController):
|
|||
@abstractmethod
|
||||
def trigger_action_item(
|
||||
self,
|
||||
plugin_identifier: str,
|
||||
identifier: str,
|
||||
options: dict[str, Any],
|
||||
project_name: str,
|
||||
entity_ids: set[str],
|
||||
entity_type: str,
|
||||
selected_ids: set[str],
|
||||
selected_entity_type: str,
|
||||
):
|
||||
"""Trigger action item.
|
||||
|
||||
|
|
@ -1014,11 +1021,14 @@ class FrontendLoaderController(_BaseLoaderController):
|
|||
}
|
||||
|
||||
Args:
|
||||
identifier (str): Action identifier.
|
||||
plugin_identifier (sttr): Plugin identifier.
|
||||
identifier (sttr): Action identifier.
|
||||
options (dict[str, Any]): Action option values from UI.
|
||||
project_name (str): Project name.
|
||||
entity_ids (set[str]): Selected entity ids.
|
||||
entity_type (str): Selected entity type.
|
||||
entity_ids (set[str]): Entity ids stored on action item.
|
||||
entity_type (str): Entity type stored on action item.
|
||||
selected_ids (set[str]): Selected entity ids.
|
||||
selected_entity_type (str): Selected entity type.
|
||||
|
||||
"""
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ from __future__ import annotations
|
|||
|
||||
import logging
|
||||
import uuid
|
||||
from typing import Any
|
||||
|
||||
import ayon_api
|
||||
|
||||
|
|
@ -297,22 +298,25 @@ class LoaderController(BackendLoaderController, FrontendLoaderController):
|
|||
action_items = self._loader_actions_model.get_action_items(
|
||||
project_name, entity_ids, entity_type
|
||||
)
|
||||
if entity_type == "representation":
|
||||
site_sync_items = self._sitesync_model.get_sitesync_action_items(
|
||||
project_name, entity_ids
|
||||
)
|
||||
action_items.extend(site_sync_items)
|
||||
|
||||
site_sync_items = self._sitesync_model.get_sitesync_action_items(
|
||||
project_name, entity_ids, entity_type
|
||||
)
|
||||
action_items.extend(site_sync_items)
|
||||
return action_items
|
||||
|
||||
def trigger_action_item(
|
||||
self,
|
||||
identifier,
|
||||
options,
|
||||
project_name,
|
||||
entity_ids,
|
||||
entity_type,
|
||||
plugin_identifier: str,
|
||||
identifier: str,
|
||||
options: dict[str, Any],
|
||||
project_name: str,
|
||||
entity_ids: set[str],
|
||||
entity_type: str,
|
||||
selected_ids: set[str],
|
||||
selected_entity_type: str,
|
||||
):
|
||||
if self._sitesync_model.is_sitesync_action(identifier):
|
||||
if self._sitesync_model.is_sitesync_action(plugin_identifier):
|
||||
self._sitesync_model.trigger_action_item(
|
||||
identifier,
|
||||
project_name,
|
||||
|
|
@ -321,11 +325,14 @@ class LoaderController(BackendLoaderController, FrontendLoaderController):
|
|||
return
|
||||
|
||||
self._loader_actions_model.trigger_action_item(
|
||||
plugin_identifier,
|
||||
identifier,
|
||||
options,
|
||||
project_name,
|
||||
entity_ids,
|
||||
entity_type,
|
||||
selected_ids,
|
||||
selected_entity_type,
|
||||
)
|
||||
|
||||
# Selection model wrappers
|
||||
|
|
|
|||
|
|
@ -9,7 +9,12 @@ from typing import Callable, Any
|
|||
|
||||
import ayon_api
|
||||
|
||||
from ayon_core.lib import NestedCacheItem
|
||||
from ayon_core.lib import NestedCacheItem, Logger
|
||||
from ayon_core.pipeline.actions import (
|
||||
LoaderActionsContext,
|
||||
LoaderActionSelection,
|
||||
SelectionEntitiesCache,
|
||||
)
|
||||
from ayon_core.pipeline.load import (
|
||||
discover_loader_plugins,
|
||||
ProductLoaderPlugin,
|
||||
|
|
@ -24,6 +29,7 @@ from ayon_core.pipeline.load import (
|
|||
from ayon_core.tools.loader.abstract import ActionItem
|
||||
|
||||
ACTIONS_MODEL_SENDER = "actions.model"
|
||||
LOADER_PLUGIN_ID = "__loader_plugin__"
|
||||
NOT_SET = object()
|
||||
|
||||
|
||||
|
|
@ -45,6 +51,7 @@ class LoaderActionsModel:
|
|||
loaders_cache_lifetime = 30
|
||||
|
||||
def __init__(self, controller):
|
||||
self._log = Logger.get_logger(self.__class__.__name__)
|
||||
self._controller = controller
|
||||
self._current_context_project = NOT_SET
|
||||
self._loaders_by_identifier = NestedCacheItem(
|
||||
|
|
@ -53,6 +60,7 @@ class LoaderActionsModel:
|
|||
levels=1, lifetime=self.loaders_cache_lifetime)
|
||||
self._repre_loaders = NestedCacheItem(
|
||||
levels=1, lifetime=self.loaders_cache_lifetime)
|
||||
self._loader_actions = LoaderActionsContext()
|
||||
|
||||
self._projects_cache = NestedCacheItem(levels=1, lifetime=60)
|
||||
self._folders_cache = NestedCacheItem(levels=2, lifetime=300)
|
||||
|
|
@ -69,6 +77,7 @@ class LoaderActionsModel:
|
|||
self._loaders_by_identifier.reset()
|
||||
self._product_loaders.reset()
|
||||
self._repre_loaders.reset()
|
||||
self._loader_actions.reset()
|
||||
|
||||
self._folders_cache.reset()
|
||||
self._tasks_cache.reset()
|
||||
|
|
@ -102,16 +111,25 @@ class LoaderActionsModel:
|
|||
version_context_by_id,
|
||||
repre_context_by_id
|
||||
)
|
||||
action_items.extend(self._get_loader_action_items(
|
||||
project_name,
|
||||
entity_ids,
|
||||
entity_type,
|
||||
))
|
||||
|
||||
action_items.sort(key=self._actions_sorter)
|
||||
return action_items
|
||||
|
||||
def trigger_action_item(
|
||||
self,
|
||||
plugin_identifier: str,
|
||||
identifier: str,
|
||||
options: dict[str, Any],
|
||||
project_name: str,
|
||||
entity_ids: set[str],
|
||||
entity_type: str,
|
||||
selected_ids: set[str],
|
||||
selected_entity_type: str,
|
||||
):
|
||||
"""Trigger action by identifier.
|
||||
|
||||
|
|
@ -122,14 +140,18 @@ class LoaderActionsModel:
|
|||
happened.
|
||||
|
||||
Args:
|
||||
identifier (str): Loader identifier.
|
||||
plugin_identifier (str): Plugin identifier.
|
||||
identifier (str): Action identifier.
|
||||
options (dict[str, Any]): Loader option values.
|
||||
project_name (str): Project name.
|
||||
entity_ids (set[str]): Entity ids.
|
||||
entity_type (str): Entity type.
|
||||
entity_ids (set[str]): Entity ids on action item.
|
||||
entity_type (str): Entity type on action item.
|
||||
selected_ids (set[str]): Selected entity ids.
|
||||
selected_entity_type (str): Selected entity type.
|
||||
|
||||
"""
|
||||
event_data = {
|
||||
"plugin_identifier": plugin_identifier,
|
||||
"identifier": identifier,
|
||||
"id": uuid.uuid4().hex,
|
||||
}
|
||||
|
|
@ -138,27 +160,52 @@ class LoaderActionsModel:
|
|||
event_data,
|
||||
ACTIONS_MODEL_SENDER,
|
||||
)
|
||||
loader = self._get_loader_by_identifier(project_name, identifier)
|
||||
if plugin_identifier != LOADER_PLUGIN_ID:
|
||||
# TODO fill error infor if any happens
|
||||
error_info = []
|
||||
try:
|
||||
self._loader_actions.execute_action(
|
||||
plugin_identifier,
|
||||
identifier,
|
||||
entity_ids,
|
||||
entity_type,
|
||||
LoaderActionSelection(
|
||||
project_name,
|
||||
selected_ids,
|
||||
selected_entity_type,
|
||||
),
|
||||
{},
|
||||
)
|
||||
|
||||
if entity_type == "version":
|
||||
error_info = self._trigger_version_loader(
|
||||
loader,
|
||||
options,
|
||||
project_name,
|
||||
entity_ids,
|
||||
)
|
||||
elif entity_type == "representation":
|
||||
error_info = self._trigger_representation_loader(
|
||||
loader,
|
||||
options,
|
||||
project_name,
|
||||
entity_ids,
|
||||
)
|
||||
except Exception:
|
||||
self._log.warning(
|
||||
f"Failed to execute action '{identifier}'",
|
||||
exc_info=True,
|
||||
)
|
||||
else:
|
||||
raise NotImplementedError(
|
||||
f"Invalid entity type '{entity_type}' to trigger action item"
|
||||
loader = self._get_loader_by_identifier(
|
||||
project_name, identifier
|
||||
)
|
||||
|
||||
if entity_type == "version":
|
||||
error_info = self._trigger_version_loader(
|
||||
loader,
|
||||
options,
|
||||
project_name,
|
||||
entity_ids,
|
||||
)
|
||||
elif entity_type == "representation":
|
||||
error_info = self._trigger_representation_loader(
|
||||
loader,
|
||||
options,
|
||||
project_name,
|
||||
entity_ids,
|
||||
)
|
||||
else:
|
||||
raise NotImplementedError(
|
||||
f"Invalid entity type '{entity_type}' to trigger action item"
|
||||
)
|
||||
|
||||
event_data["error_info"] = error_info
|
||||
self._controller.emit_event(
|
||||
"load.finished",
|
||||
|
|
@ -278,8 +325,9 @@ class LoaderActionsModel:
|
|||
):
|
||||
label = self._get_action_label(loader)
|
||||
if repre_name:
|
||||
label = "{} ({})".format(label, repre_name)
|
||||
label = f"{label} ({repre_name})"
|
||||
return ActionItem(
|
||||
LOADER_PLUGIN_ID,
|
||||
get_loader_identifier(loader),
|
||||
entity_ids=entity_ids,
|
||||
entity_type=entity_type,
|
||||
|
|
@ -456,8 +504,8 @@ class LoaderActionsModel:
|
|||
Returns:
|
||||
tuple[list[dict[str, Any]], list[dict[str, Any]]]: Version and
|
||||
representation contexts.
|
||||
"""
|
||||
|
||||
"""
|
||||
version_context_by_id = {}
|
||||
repre_context_by_id = {}
|
||||
if not project_name and not repre_ids:
|
||||
|
|
@ -710,6 +758,39 @@ class LoaderActionsModel:
|
|||
action_items.append(item)
|
||||
return action_items
|
||||
|
||||
|
||||
def _get_loader_action_items(
|
||||
self,
|
||||
project_name: str,
|
||||
entity_ids: set[str],
|
||||
entity_type: str,
|
||||
) -> list[ActionItem]:
|
||||
# TODO prepare cached entities
|
||||
# entities_cache = SelectionEntitiesCache(project_name)
|
||||
selection = LoaderActionSelection(
|
||||
project_name,
|
||||
entity_ids,
|
||||
entity_type,
|
||||
# entities_cache=entities_cache
|
||||
)
|
||||
items = []
|
||||
for action in self._loader_actions.get_action_items(selection):
|
||||
label = action.label
|
||||
if action.group_label:
|
||||
label = f"{action.group_label} ({label})"
|
||||
items.append(ActionItem(
|
||||
action.plugin_identifier,
|
||||
action.identifier,
|
||||
action.entity_ids,
|
||||
action.entity_type,
|
||||
label,
|
||||
action.icon,
|
||||
None, # action.tooltip,
|
||||
None, # action.options,
|
||||
action.order,
|
||||
))
|
||||
return items
|
||||
|
||||
def _trigger_version_loader(
|
||||
self,
|
||||
loader,
|
||||
|
|
|
|||
|
|
@ -246,26 +246,32 @@ class SiteSyncModel:
|
|||
output[repre_id] = repre_cache.get_data()
|
||||
return output
|
||||
|
||||
def get_sitesync_action_items(self, project_name, representation_ids):
|
||||
def get_sitesync_action_items(
|
||||
self, project_name, entity_ids, entity_type
|
||||
):
|
||||
"""
|
||||
|
||||
Args:
|
||||
project_name (str): Project name.
|
||||
representation_ids (Iterable[str]): Representation ids.
|
||||
entity_ids (set[str]): Selected entity ids.
|
||||
entity_type (str): Selected entity type.
|
||||
|
||||
Returns:
|
||||
list[ActionItem]: Actions that can be shown in loader.
|
||||
|
||||
"""
|
||||
if entity_type != "representation":
|
||||
return []
|
||||
|
||||
if not self.is_sitesync_enabled(project_name):
|
||||
return []
|
||||
|
||||
repres_status = self.get_representations_sync_status(
|
||||
project_name, representation_ids
|
||||
project_name, entity_ids
|
||||
)
|
||||
|
||||
repre_ids_per_identifier = collections.defaultdict(set)
|
||||
for repre_id in representation_ids:
|
||||
for repre_id in entity_ids:
|
||||
repre_status = repres_status[repre_id]
|
||||
local_status, remote_status = repre_status
|
||||
|
||||
|
|
@ -293,27 +299,23 @@ class SiteSyncModel:
|
|||
|
||||
return action_items
|
||||
|
||||
def is_sitesync_action(self, identifier):
|
||||
def is_sitesync_action(self, plugin_identifier: str) -> bool:
|
||||
"""Should be `identifier` handled by SiteSync.
|
||||
|
||||
Args:
|
||||
identifier (str): Action identifier.
|
||||
plugin_identifier (str): Plugin identifier.
|
||||
|
||||
Returns:
|
||||
bool: Should action be handled by SiteSync.
|
||||
"""
|
||||
|
||||
return identifier in {
|
||||
UPLOAD_IDENTIFIER,
|
||||
DOWNLOAD_IDENTIFIER,
|
||||
REMOVE_IDENTIFIER,
|
||||
}
|
||||
"""
|
||||
return plugin_identifier == "sitesync.loader.action"
|
||||
|
||||
def trigger_action_item(
|
||||
self,
|
||||
identifier,
|
||||
project_name,
|
||||
representation_ids
|
||||
identifier: str,
|
||||
project_name: str,
|
||||
representation_ids: set[str],
|
||||
):
|
||||
"""Resets status for site_name or remove local files.
|
||||
|
||||
|
|
@ -321,8 +323,8 @@ class SiteSyncModel:
|
|||
identifier (str): Action identifier.
|
||||
project_name (str): Project name.
|
||||
representation_ids (Iterable[str]): Representation ids.
|
||||
"""
|
||||
|
||||
"""
|
||||
active_site = self.get_active_site(project_name)
|
||||
remote_site = self.get_remote_site(project_name)
|
||||
|
||||
|
|
@ -482,6 +484,7 @@ class SiteSyncModel:
|
|||
icon_name
|
||||
):
|
||||
return ActionItem(
|
||||
"sitesync.loader.action",
|
||||
identifier,
|
||||
label,
|
||||
icon={
|
||||
|
|
@ -492,11 +495,8 @@ class SiteSyncModel:
|
|||
tooltip=tooltip,
|
||||
options={},
|
||||
order=1,
|
||||
project_name=project_name,
|
||||
folder_ids=[],
|
||||
product_ids=[],
|
||||
version_ids=[],
|
||||
representation_ids=representation_ids,
|
||||
entity_ids=representation_ids,
|
||||
entity_type="representation",
|
||||
)
|
||||
|
||||
def _add_site(self, project_name, repre_entity, site_name, product_type):
|
||||
|
|
|
|||
|
|
@ -438,11 +438,14 @@ class ProductsWidget(QtWidgets.QWidget):
|
|||
return
|
||||
|
||||
self._controller.trigger_action_item(
|
||||
action_item.plugin_identifier,
|
||||
action_item.identifier,
|
||||
options,
|
||||
project_name,
|
||||
action_item.entity_ids,
|
||||
action_item.entity_type,
|
||||
version_ids,
|
||||
"version",
|
||||
)
|
||||
|
||||
def _on_selection_change(self):
|
||||
|
|
|
|||
|
|
@ -399,9 +399,12 @@ class RepresentationsWidget(QtWidgets.QWidget):
|
|||
return
|
||||
|
||||
self._controller.trigger_action_item(
|
||||
action_item.plugin_identifier,
|
||||
action_item.identifier,
|
||||
options,
|
||||
self._selected_project_name,
|
||||
action_item.entity_ids,
|
||||
action_item.entity_type,
|
||||
repre_ids,
|
||||
"representation",
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue