From fc0232b7449f888f54568cae4955e0238ff737dc Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 25 Aug 2025 17:57:39 +0200 Subject: [PATCH] convert open file action --- client/ayon_core/plugins/load/open_file.py | 36 ----- client/ayon_core/plugins/loader/open_file.py | 133 +++++++++++++++++++ 2 files changed, 133 insertions(+), 36 deletions(-) delete mode 100644 client/ayon_core/plugins/load/open_file.py create mode 100644 client/ayon_core/plugins/loader/open_file.py diff --git a/client/ayon_core/plugins/load/open_file.py b/client/ayon_core/plugins/load/open_file.py deleted file mode 100644 index 3b5fbbc0c9..0000000000 --- a/client/ayon_core/plugins/load/open_file.py +++ /dev/null @@ -1,36 +0,0 @@ -import sys -import os -import subprocess - -from ayon_core.pipeline import load - - -def open(filepath): - """Open file with system default executable""" - if sys.platform.startswith('darwin'): - subprocess.call(('open', filepath)) - elif os.name == 'nt': - os.startfile(filepath) - elif os.name == 'posix': - subprocess.call(('xdg-open', filepath)) - - -class OpenFile(load.LoaderPlugin): - """Open Image Sequence or Video with system default""" - - product_types = {"render2d"} - representations = {"*"} - - label = "Open" - order = -10 - icon = "play-circle" - color = "orange" - - def load(self, context, name, namespace, data): - - path = self.filepath_from_context(context) - if not os.path.exists(path): - raise RuntimeError("File not found: {}".format(path)) - - self.log.info("Opening : {}".format(path)) - open(path) diff --git a/client/ayon_core/plugins/loader/open_file.py b/client/ayon_core/plugins/loader/open_file.py new file mode 100644 index 0000000000..a46bb31472 --- /dev/null +++ b/client/ayon_core/plugins/loader/open_file.py @@ -0,0 +1,133 @@ +import os +import sys +import subprocess +import collections +from typing import Optional, Any + +from ayon_core.pipeline.load import get_representation_path_with_anatomy +from ayon_core.pipeline.actions import ( + LoaderActionPlugin, + LoaderActionItem, + LoaderActionSelection, + LoaderActionResult, +) + + +def open_file(filepath: str) -> None: + """Open file with system default executable""" + if sys.platform.startswith("darwin"): + subprocess.call(("open", filepath)) + elif os.name == "nt": + os.startfile(filepath) + elif os.name == "posix": + subprocess.call(("xdg-open", filepath)) + + +class OpenFileAction(LoaderActionPlugin): + """Open Image Sequence or Video with system default""" + identifier = "core.open-file" + + product_types = {"render2d"} + + def get_action_items( + self, selection: LoaderActionSelection + ) -> list[LoaderActionItem]: + repres = [] + if selection.selected_type == "representations": + repres = selection.entities.get_representations( + selection.selected_ids + ) + + if selection.selected_type == "version": + repres = selection.entities.get_versions_representations( + selection.selected_ids + ) + + if not repres: + return [] + + repre_ids = {repre["id"] for repre in repres} + versions = selection.entities.get_representations_versions( + repre_ids + ) + product_ids = {version["productId"] for version in versions} + products = selection.entities.get_products(product_ids) + fitlered_product_ids = { + product["id"] + for product in products + if product["productType"] in self.product_types + } + if not fitlered_product_ids: + return [] + + versions_by_product_id = collections.defaultdict(list) + for version in versions: + versions_by_product_id[version["productId"]].append(version) + + repres_by_version_ids = collections.defaultdict(list) + for repre in repres: + repres_by_version_ids[repre["versionId"]].append(repre) + + filtered_repres = [] + for product_id in fitlered_product_ids: + for version in versions_by_product_id[product_id]: + for repre in repres_by_version_ids[version["id"]]: + filtered_repres.append(repre) + + repre_ids_by_name = collections.defaultdict(set) + for repre in filtered_repres: + repre_ids_by_name[repre["name"]].add(repre["id"]) + + return [ + LoaderActionItem( + identifier="open-file", + label=repre_name, + group_label="Open file", + order=-10, + entity_ids=repre_ids, + entity_type="representation", + icon={ + "type": "material-symbols", + "name": "play_circle", + "color": "#FFA500", + } + ) + for repre_name, repre_ids in repre_ids_by_name.items() + ] + + def execute_action( + self, + identifier: str, + entity_ids: set[str], + entity_type: str, + selection: LoaderActionSelection, + form_values: dict[str, Any], + ) -> Optional[LoaderActionResult]: + path = None + repre_path = None + for repre in selection.entities.get_representations(entity_ids): + repre_path = get_representation_path_with_anatomy( + repre, selection.get_project_anatomy() + ) + if os.path.exists(repre_path): + path = repre_path + break + + if path is None: + if repre_path is None: + return LoaderActionResult( + "Failed to fill representation path...", + success=False, + ) + return LoaderActionResult( + "File to open was not found...", + success=False, + ) + + self.log.info(f"Opening: {path}") + open_file(path) + + return LoaderActionResult( + "File was opened...", + success=True, + )