mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-27 14:22:37 +01:00
Merge branch 'develop' into enhancement/OP-8218_Loader-OTIO-export-action
This commit is contained in:
commit
be3c55dd43
46 changed files with 309 additions and 310 deletions
|
|
@ -103,19 +103,18 @@ def extractenvironments(output_json_path, project, asset, task, app, envgroup):
|
|||
|
||||
|
||||
@main_cli.command()
|
||||
@click.argument("paths", nargs=-1)
|
||||
@click.option("-t", "--targets", help="Targets module", default=None,
|
||||
@click.argument("path", required=True)
|
||||
@click.option("-t", "--targets", help="Targets", default=None,
|
||||
multiple=True)
|
||||
@click.option("-g", "--gui", is_flag=True,
|
||||
help="Show Publish UI", default=False)
|
||||
def publish(paths, targets, gui):
|
||||
def publish(path, targets, gui):
|
||||
"""Start CLI publishing.
|
||||
|
||||
Publish collects json from paths provided as an argument.
|
||||
More than one path is allowed.
|
||||
Publish collects json from path provided as an argument.
|
||||
S
|
||||
"""
|
||||
|
||||
Commands.publish(list(paths), targets, gui)
|
||||
Commands.publish(path, targets, gui)
|
||||
|
||||
|
||||
@main_cli.command(context_settings={"ignore_unknown_options": True})
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
import os
|
||||
import sys
|
||||
import json
|
||||
import warnings
|
||||
|
||||
|
||||
class Commands:
|
||||
|
|
@ -41,21 +42,21 @@ class Commands:
|
|||
return click_func
|
||||
|
||||
@staticmethod
|
||||
def publish(paths, targets=None, gui=False):
|
||||
def publish(path: str, targets: list=None, gui:bool=False) -> None:
|
||||
"""Start headless publishing.
|
||||
|
||||
Publish use json from passed paths argument.
|
||||
Publish use json from passed path argument.
|
||||
|
||||
Args:
|
||||
paths (list): Paths to jsons.
|
||||
targets (string): What module should be targeted
|
||||
(to choose validator for example)
|
||||
path (str): Path to JSON.
|
||||
targets (list of str): List of pyblish targets.
|
||||
gui (bool): Show publish UI.
|
||||
|
||||
Raises:
|
||||
RuntimeError: When there is no path to process.
|
||||
"""
|
||||
RuntimeError: When executed with list of JSON paths.
|
||||
|
||||
"""
|
||||
from ayon_core.lib import Logger
|
||||
from ayon_core.lib.applications import (
|
||||
get_app_environments_for_context,
|
||||
|
|
@ -73,6 +74,9 @@ class Commands:
|
|||
import pyblish.api
|
||||
import pyblish.util
|
||||
|
||||
if not isinstance(path, str):
|
||||
raise RuntimeError("Path to JSON must be a string.")
|
||||
|
||||
# Fix older jobs
|
||||
for src_key, dst_key in (
|
||||
("AVALON_PROJECT", "AYON_PROJECT_NAME"),
|
||||
|
|
@ -95,11 +99,8 @@ class Commands:
|
|||
|
||||
publish_paths = manager.collect_plugin_paths()["publish"]
|
||||
|
||||
for path in publish_paths:
|
||||
pyblish.api.register_plugin_path(path)
|
||||
|
||||
if not any(paths):
|
||||
raise RuntimeError("No publish paths specified")
|
||||
for plugin_path in publish_paths:
|
||||
pyblish.api.register_plugin_path(plugin_path)
|
||||
|
||||
app_full_name = os.getenv("AYON_APP_NAME")
|
||||
if app_full_name:
|
||||
|
|
@ -122,7 +123,7 @@ class Commands:
|
|||
else:
|
||||
pyblish.api.register_target("farm")
|
||||
|
||||
os.environ["AYON_PUBLISH_DATA"] = os.pathsep.join(paths)
|
||||
os.environ["AYON_PUBLISH_DATA"] = path
|
||||
os.environ["HEADLESS_PUBLISH"] = 'true' # to use in app lib
|
||||
|
||||
log.info("Running publish ...")
|
||||
|
|
|
|||
|
|
@ -8,8 +8,11 @@ from qtpy import QtWidgets, QtCore, QtGui
|
|||
|
||||
from ayon_core import style
|
||||
from ayon_core.pipeline import get_current_project_name
|
||||
from ayon_core.tools.utils import PlaceholderLineEdit, RefreshButton
|
||||
from ayon_core.tools.ayon_utils.widgets import SimpleFoldersWidget
|
||||
from ayon_core.tools.utils import (
|
||||
PlaceholderLineEdit,
|
||||
RefreshButton,
|
||||
SimpleFoldersWidget,
|
||||
)
|
||||
|
||||
from pxr import Sdf
|
||||
|
||||
|
|
|
|||
|
|
@ -608,7 +608,7 @@ class RenderlayerCreator(NewCreator, MayaCreatorBase):
|
|||
return get_product_name(
|
||||
project_name,
|
||||
task_name,
|
||||
task_type
|
||||
task_type,
|
||||
host_name,
|
||||
self.layer_instance_prefix or self.product_type,
|
||||
variant,
|
||||
|
|
|
|||
|
|
@ -330,19 +330,25 @@ def get_timeline_item(media_pool_item: object,
|
|||
Returns:
|
||||
object: resolve.TimelineItem
|
||||
"""
|
||||
_clip_property = media_pool_item.GetClipProperty
|
||||
clip_name = _clip_property("File Name")
|
||||
clip_name = media_pool_item.GetClipProperty("File Name")
|
||||
output_timeline_item = None
|
||||
timeline = timeline or get_current_timeline()
|
||||
|
||||
with maintain_current_timeline(timeline):
|
||||
# search the timeline for the added clip
|
||||
|
||||
for _ti_data in get_current_timeline_items():
|
||||
_ti_clip = _ti_data["clip"]["item"]
|
||||
_ti_clip_property = _ti_clip.GetMediaPoolItem().GetClipProperty
|
||||
if clip_name in _ti_clip_property("File Name"):
|
||||
output_timeline_item = _ti_clip
|
||||
for ti_data in get_current_timeline_items():
|
||||
ti_clip_item = ti_data["clip"]["item"]
|
||||
ti_media_pool_item = ti_clip_item.GetMediaPoolItem()
|
||||
|
||||
# Skip items that do not have a media pool item, like for example
|
||||
# an "Adjustment Clip" or a "Fusion Composition" from the effects
|
||||
# toolbox
|
||||
if not ti_media_pool_item:
|
||||
continue
|
||||
|
||||
if clip_name in ti_media_pool_item.GetClipProperty("File Name"):
|
||||
output_timeline_item = ti_clip_item
|
||||
|
||||
return output_timeline_item
|
||||
|
||||
|
|
|
|||
|
|
@ -36,18 +36,18 @@ class CollectRenderedFiles(pyblish.api.ContextPlugin):
|
|||
|
||||
def _load_json(self, path):
|
||||
path = path.strip('\"')
|
||||
assert os.path.isfile(path), (
|
||||
"Path to json file doesn't exist. \"{}\"".format(path)
|
||||
)
|
||||
|
||||
if not os.path.isfile(path):
|
||||
raise FileNotFoundError(
|
||||
f"Path to json file doesn't exist. \"{path}\"")
|
||||
|
||||
data = None
|
||||
with open(path, "r") as json_file:
|
||||
try:
|
||||
data = json.load(json_file)
|
||||
except Exception as exc:
|
||||
self.log.error(
|
||||
"Error loading json: "
|
||||
"{} - Exception: {}".format(path, exc)
|
||||
)
|
||||
"Error loading json: %s - Exception: %s", path, exc)
|
||||
return data
|
||||
|
||||
def _fill_staging_dir(self, data_object, anatomy):
|
||||
|
|
@ -73,30 +73,23 @@ class CollectRenderedFiles(pyblish.api.ContextPlugin):
|
|||
data_err = "invalid json file - missing data"
|
||||
required = ["user", "comment",
|
||||
"job", "instances", "version"]
|
||||
assert all(elem in data.keys() for elem in required), data_err
|
||||
|
||||
if any(elem not in data for elem in required):
|
||||
raise ValueError(data_err)
|
||||
|
||||
if "folderPath" not in data and "asset" not in data:
|
||||
raise AssertionError(data_err)
|
||||
raise ValueError(data_err)
|
||||
|
||||
if "folderPath" not in data:
|
||||
data["folderPath"] = data.pop("asset")
|
||||
|
||||
# set context by first json file
|
||||
ctx = self._context.data
|
||||
|
||||
ctx["folderPath"] = ctx.get("folderPath") or data.get("folderPath")
|
||||
ctx["intent"] = ctx.get("intent") or data.get("intent")
|
||||
ctx["comment"] = ctx.get("comment") or data.get("comment")
|
||||
ctx["user"] = ctx.get("user") or data.get("user")
|
||||
ctx["version"] = ctx.get("version") or data.get("version")
|
||||
|
||||
# basic sanity check to see if we are working in same context
|
||||
# if some other json file has different context, bail out.
|
||||
ctx_err = "inconsistent contexts in json files - %s"
|
||||
assert ctx.get("folderPath") == data.get("folderPath"), ctx_err % "folderPath"
|
||||
assert ctx.get("intent") == data.get("intent"), ctx_err % "intent"
|
||||
assert ctx.get("comment") == data.get("comment"), ctx_err % "comment"
|
||||
assert ctx.get("user") == data.get("user"), ctx_err % "user"
|
||||
assert ctx.get("version") == data.get("version"), ctx_err % "version"
|
||||
# ftrack credentials are passed as environment variables by Deadline
|
||||
# to publish job, but Muster doesn't pass them.
|
||||
if data.get("ftrack") and not os.environ.get("FTRACK_API_USER"):
|
||||
ftrack = data.get("ftrack")
|
||||
os.environ["FTRACK_API_USER"] = ftrack["FTRACK_API_USER"]
|
||||
os.environ["FTRACK_API_KEY"] = ftrack["FTRACK_API_KEY"]
|
||||
os.environ["FTRACK_SERVER"] = ftrack["FTRACK_SERVER"]
|
||||
|
||||
# now we can just add instances from json file and we are done
|
||||
any_staging_dir_persistent = False
|
||||
|
|
|
|||
|
|
@ -1,51 +0,0 @@
|
|||
from .projects_widget import (
|
||||
# ProjectsWidget,
|
||||
ProjectsCombobox,
|
||||
ProjectsQtModel,
|
||||
ProjectSortFilterProxy,
|
||||
PROJECT_NAME_ROLE,
|
||||
PROJECT_IS_CURRENT_ROLE,
|
||||
PROJECT_IS_ACTIVE_ROLE,
|
||||
PROJECT_IS_LIBRARY_ROLE,
|
||||
)
|
||||
|
||||
from .folders_widget import (
|
||||
FoldersWidget,
|
||||
FoldersQtModel,
|
||||
FOLDERS_MODEL_SENDER_NAME,
|
||||
SimpleFoldersWidget,
|
||||
)
|
||||
|
||||
from .tasks_widget import (
|
||||
TasksWidget,
|
||||
TasksQtModel,
|
||||
TASKS_MODEL_SENDER_NAME,
|
||||
)
|
||||
from .utils import (
|
||||
get_qt_icon,
|
||||
RefreshThread,
|
||||
)
|
||||
|
||||
|
||||
__all__ = (
|
||||
# "ProjectsWidget",
|
||||
"ProjectsCombobox",
|
||||
"ProjectsQtModel",
|
||||
"ProjectSortFilterProxy",
|
||||
"PROJECT_NAME_ROLE",
|
||||
"PROJECT_IS_CURRENT_ROLE",
|
||||
"PROJECT_IS_ACTIVE_ROLE",
|
||||
"PROJECT_IS_LIBRARY_ROLE",
|
||||
|
||||
"FoldersWidget",
|
||||
"FoldersQtModel",
|
||||
"FOLDERS_MODEL_SENDER_NAME",
|
||||
"SimpleFoldersWidget",
|
||||
|
||||
"TasksWidget",
|
||||
"TasksQtModel",
|
||||
"TASKS_MODEL_SENDER_NAME",
|
||||
|
||||
"get_qt_icon",
|
||||
"RefreshThread",
|
||||
)
|
||||
|
|
@ -1,109 +0,0 @@
|
|||
import os
|
||||
from functools import partial
|
||||
|
||||
from qtpy import QtCore, QtGui
|
||||
|
||||
from ayon_core.tools.utils.lib import get_qta_icon_by_name_and_color
|
||||
|
||||
|
||||
class RefreshThread(QtCore.QThread):
|
||||
refresh_finished = QtCore.Signal(str)
|
||||
|
||||
def __init__(self, thread_id, func, *args, **kwargs):
|
||||
super(RefreshThread, self).__init__()
|
||||
self._id = thread_id
|
||||
self._callback = partial(func, *args, **kwargs)
|
||||
self._exception = None
|
||||
self._result = None
|
||||
self.finished.connect(self._on_finish_callback)
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return self._id
|
||||
|
||||
@property
|
||||
def failed(self):
|
||||
return self._exception is not None
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
self._result = self._callback()
|
||||
except Exception as exc:
|
||||
self._exception = exc
|
||||
|
||||
def get_result(self):
|
||||
return self._result
|
||||
|
||||
def _on_finish_callback(self):
|
||||
"""Trigger custom signal with thread id.
|
||||
|
||||
Listening for 'finished' signal we make sure that execution of thread
|
||||
finished and QThread object can be safely deleted.
|
||||
"""
|
||||
|
||||
self.refresh_finished.emit(self.id)
|
||||
|
||||
|
||||
class _IconsCache:
|
||||
"""Cache for icons."""
|
||||
|
||||
_cache = {}
|
||||
_default = None
|
||||
|
||||
@classmethod
|
||||
def _get_cache_key(cls, icon_def):
|
||||
parts = []
|
||||
icon_type = icon_def["type"]
|
||||
if icon_type == "path":
|
||||
parts = [icon_type, icon_def["path"]]
|
||||
|
||||
elif icon_type == "awesome-font":
|
||||
parts = [icon_type, icon_def["name"], icon_def["color"]]
|
||||
return "|".join(parts)
|
||||
|
||||
@classmethod
|
||||
def get_icon(cls, icon_def):
|
||||
if not icon_def:
|
||||
return None
|
||||
icon_type = icon_def["type"]
|
||||
cache_key = cls._get_cache_key(icon_def)
|
||||
cache = cls._cache.get(cache_key)
|
||||
if cache is not None:
|
||||
return cache
|
||||
|
||||
icon = None
|
||||
if icon_type == "path":
|
||||
path = icon_def["path"]
|
||||
if os.path.exists(path):
|
||||
icon = QtGui.QIcon(path)
|
||||
|
||||
elif icon_type == "awesome-font":
|
||||
icon_name = icon_def["name"]
|
||||
icon_color = icon_def["color"]
|
||||
icon = get_qta_icon_by_name_and_color(icon_name, icon_color)
|
||||
if icon is None:
|
||||
icon = get_qta_icon_by_name_and_color(
|
||||
"fa.{}".format(icon_name), icon_color)
|
||||
if icon is None:
|
||||
icon = cls.get_default()
|
||||
cls._cache[cache_key] = icon
|
||||
return icon
|
||||
|
||||
@classmethod
|
||||
def get_default(cls):
|
||||
pix = QtGui.QPixmap(1, 1)
|
||||
pix.fill(QtCore.Qt.transparent)
|
||||
return QtGui.QIcon(pix)
|
||||
|
||||
|
||||
def get_qt_icon(icon_def):
|
||||
"""Returns icon from cache or creates new one.
|
||||
|
||||
Args:
|
||||
icon_def (dict[str, Any]): Icon definition.
|
||||
|
||||
Returns:
|
||||
QtGui.QIcon: Icon.
|
||||
"""
|
||||
|
||||
return _IconsCache.get_icon(icon_def)
|
||||
|
|
@ -6,19 +6,17 @@ from qtpy import QtWidgets, QtCore, QtGui
|
|||
|
||||
from ayon_core import style
|
||||
from ayon_core.lib.events import QueuedEventSystem
|
||||
from ayon_core.tools.ayon_utils.models import (
|
||||
from ayon_core.tools.common_models import (
|
||||
ProjectsModel,
|
||||
HierarchyModel,
|
||||
)
|
||||
from ayon_core.tools.ayon_utils.widgets import (
|
||||
from ayon_core.tools.utils import (
|
||||
ProjectsCombobox,
|
||||
FoldersWidget,
|
||||
TasksWidget,
|
||||
)
|
||||
from ayon_core.tools.utils.lib import (
|
||||
center_window,
|
||||
get_ayon_qt_app,
|
||||
)
|
||||
from ayon_core.tools.utils.lib import center_window
|
||||
|
||||
|
||||
class SelectionModel(object):
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
from ayon_core.lib import Logger
|
||||
from ayon_core.lib.events import QueuedEventSystem
|
||||
from ayon_core.settings import get_project_settings
|
||||
from ayon_core.tools.ayon_utils.models import ProjectsModel, HierarchyModel
|
||||
from ayon_core.tools.common_models import ProjectsModel, HierarchyModel
|
||||
|
||||
from .abstract import AbstractLauncherFrontEnd, AbstractLauncherBackend
|
||||
from .models import LauncherSelectionModel, ActionsModel
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import collections
|
|||
from qtpy import QtWidgets, QtCore, QtGui
|
||||
|
||||
from ayon_core.tools.flickcharm import FlickCharm
|
||||
from ayon_core.tools.ayon_utils.widgets import get_qt_icon
|
||||
from ayon_core.tools.utils import get_qt_icon
|
||||
|
||||
from .resources import get_options_image_path
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ from ayon_core.tools.utils import (
|
|||
SquareButton,
|
||||
RefreshButton,
|
||||
)
|
||||
from ayon_core.tools.ayon_utils.widgets import (
|
||||
from ayon_core.tools.utils import (
|
||||
ProjectsCombobox,
|
||||
FoldersWidget,
|
||||
TasksWidget,
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
from qtpy import QtWidgets, QtCore
|
||||
|
||||
from ayon_core.tools.flickcharm import FlickCharm
|
||||
from ayon_core.tools.utils import PlaceholderLineEdit, RefreshButton
|
||||
from ayon_core.tools.ayon_utils.widgets import (
|
||||
from ayon_core.tools.utils import (
|
||||
PlaceholderLineEdit,
|
||||
RefreshButton,
|
||||
ProjectsQtModel,
|
||||
ProjectSortFilterProxy,
|
||||
)
|
||||
from ayon_core.tools.ayon_utils.models import PROJECTS_MODEL_SENDER
|
||||
from ayon_core.tools.common_models import PROJECTS_MODEL_SENDER
|
||||
|
||||
|
||||
class ProjectIconView(QtWidgets.QListView):
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import ayon_api
|
|||
from ayon_core.lib.events import QueuedEventSystem
|
||||
from ayon_core.pipeline import Anatomy, get_current_context
|
||||
from ayon_core.host import ILoadHost
|
||||
from ayon_core.tools.ayon_utils.models import (
|
||||
from ayon_core.tools.common_models import (
|
||||
ProjectsModel,
|
||||
HierarchyModel,
|
||||
NestedCacheItem,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ from ayon_core.pipeline.load import (
|
|||
LoadError,
|
||||
IncompatibleLoaderError,
|
||||
)
|
||||
from ayon_core.tools.ayon_utils.models import NestedCacheItem
|
||||
from ayon_core.tools.common_models import NestedCacheItem
|
||||
from ayon_core.tools.loader.abstract import ActionItem
|
||||
|
||||
ACTIONS_MODEL_SENDER = "actions.model"
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import ayon_api
|
|||
from ayon_api.operations import OperationsSession
|
||||
|
||||
from ayon_core.style import get_default_entity_icon_color
|
||||
from ayon_core.tools.ayon_utils.models import NestedCacheItem
|
||||
from ayon_core.tools.common_models import NestedCacheItem
|
||||
from ayon_core.tools.loader.abstract import (
|
||||
ProductTypeItem,
|
||||
ProductItem,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from ayon_api import get_representations, get_versions_links
|
|||
|
||||
from ayon_core.lib import Logger
|
||||
from ayon_core.addon import AddonsManager
|
||||
from ayon_core.tools.ayon_utils.models import NestedCacheItem
|
||||
from ayon_core.tools.common_models import NestedCacheItem
|
||||
from ayon_core.tools.loader.abstract import ActionItem
|
||||
|
||||
DOWNLOAD_IDENTIFIER = "sitesync.download"
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ from ayon_core.tools.utils.widgets import (
|
|||
OptionalAction,
|
||||
OptionDialog,
|
||||
)
|
||||
from ayon_core.tools.ayon_utils.widgets import get_qt_icon
|
||||
from ayon_core.tools.utils import get_qt_icon
|
||||
|
||||
|
||||
def show_actions_menu(action_items, global_point, one_item_selected, parent):
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@ from ayon_core.tools.utils import (
|
|||
)
|
||||
from ayon_core.style import get_objected_colors
|
||||
|
||||
from ayon_core.tools.ayon_utils.widgets import (
|
||||
from ayon_core.tools.utils import (
|
||||
FoldersQtModel,
|
||||
FOLDERS_MODEL_SENDER_NAME,
|
||||
)
|
||||
from ayon_core.tools.ayon_utils.widgets.folders_widget import FOLDER_ID_ROLE
|
||||
from ayon_core.tools.utils.folders_widget import FOLDER_ID_ROLE
|
||||
|
||||
if qtpy.API == "pyside":
|
||||
from PySide.QtGui import QStyleOptionViewItemV4
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from qtpy import QtWidgets, QtGui, QtCore
|
||||
|
||||
from ayon_core.tools.ayon_utils.widgets import get_qt_icon
|
||||
from ayon_core.tools.utils import get_qt_icon
|
||||
|
||||
PRODUCT_TYPE_ROLE = QtCore.Qt.UserRole + 1
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import qtawesome
|
|||
from qtpy import QtGui, QtCore
|
||||
|
||||
from ayon_core.style import get_default_entity_icon_color
|
||||
from ayon_core.tools.ayon_utils.widgets import get_qt_icon
|
||||
from ayon_core.tools.utils import get_qt_icon
|
||||
|
||||
PRODUCTS_MODEL_SENDER_NAME = "qt_products_model"
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from qtpy import QtWidgets, QtGui, QtCore
|
|||
import qtawesome
|
||||
|
||||
from ayon_core.style import get_default_entity_icon_color
|
||||
from ayon_core.tools.ayon_utils.widgets import get_qt_icon
|
||||
from ayon_core.tools.utils import get_qt_icon
|
||||
from ayon_core.tools.utils import DeselectableTreeView
|
||||
|
||||
from .actions_utils import show_actions_menu
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ from ayon_core.tools.utils import (
|
|||
GoToCurrentButton,
|
||||
)
|
||||
from ayon_core.tools.utils.lib import center_window
|
||||
from ayon_core.tools.ayon_utils.widgets import ProjectsCombobox
|
||||
from ayon_core.tools.utils import ProjectsCombobox
|
||||
from ayon_core.tools.loader.control import LoaderController
|
||||
|
||||
from .folders_widget import LoaderFoldersWidget
|
||||
|
|
|
|||
|
|
@ -38,7 +38,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
|
||||
from ayon_core.tools.common_models import HierarchyModel
|
||||
|
||||
# Define constant for plugin orders offset
|
||||
PLUGIN_ORDER_OFFSET = 0.5
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ from qtpy import QtWidgets, QtCore, QtGui
|
|||
from ayon_core.lib.events import QueuedEventSystem
|
||||
from ayon_core.tools.utils import PlaceholderLineEdit, GoToCurrentButton
|
||||
|
||||
from ayon_core.tools.ayon_utils.models import HierarchyExpectedSelection
|
||||
from ayon_core.tools.ayon_utils.widgets import FoldersWidget, TasksWidget
|
||||
from ayon_core.tools.common_models import HierarchyExpectedSelection
|
||||
from ayon_core.tools.utils import FoldersWidget, TasksWidget
|
||||
|
||||
|
||||
class CreateSelectionModel(object):
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
from qtpy import QtWidgets, QtCore, QtGui
|
||||
|
||||
from ayon_core.lib.events import QueuedEventSystem
|
||||
from ayon_core.tools.ayon_utils.widgets import FoldersWidget
|
||||
from ayon_core.tools.utils import PlaceholderLineEdit
|
||||
from ayon_core.tools.utils import PlaceholderLineEdit, FoldersWidget
|
||||
|
||||
|
||||
class FoldersDialogController:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
from qtpy import QtWidgets, QtCore, QtGui
|
||||
|
||||
from ayon_core.tools.utils.lib import get_default_task_icon
|
||||
from ayon_core.style import get_default_entity_icon_color
|
||||
from ayon_core.tools.utils import get_qt_icon
|
||||
|
||||
TASK_NAME_ROLE = QtCore.Qt.UserRole + 1
|
||||
TASK_TYPE_ROLE = QtCore.Qt.UserRole + 2
|
||||
|
|
@ -121,6 +122,11 @@ class TasksModel(QtGui.QStandardItemModel):
|
|||
item = self._items_by_name.pop(task_name)
|
||||
root_item.removeRow(item.row())
|
||||
|
||||
icon = get_qt_icon({
|
||||
"type": "awesome-font",
|
||||
"name": "fa.male",
|
||||
"color": get_default_entity_icon_color(),
|
||||
})
|
||||
new_items = []
|
||||
for task_name in new_task_names:
|
||||
if task_name in self._items_by_name:
|
||||
|
|
@ -129,7 +135,7 @@ class TasksModel(QtGui.QStandardItemModel):
|
|||
item = QtGui.QStandardItem(task_name)
|
||||
item.setData(task_name, TASK_NAME_ROLE)
|
||||
if task_name:
|
||||
item.setData(get_default_task_icon(), QtCore.Qt.DecorationRole)
|
||||
item.setData(icon, QtCore.Qt.DecorationRole)
|
||||
self._items_by_name[task_name] = item
|
||||
new_items.append(item)
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ from ayon_core.settings import get_project_settings
|
|||
from ayon_core.lib import prepare_template_data
|
||||
from ayon_core.lib.events import QueuedEventSystem
|
||||
from ayon_core.pipeline.create import get_product_name_template
|
||||
from ayon_core.tools.ayon_utils.models import ProjectsModel, HierarchyModel
|
||||
from ayon_core.tools.common_models import ProjectsModel, HierarchyModel
|
||||
|
||||
from .models import (
|
||||
PushToProjectSelectionModel,
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@ from ayon_core.tools.utils import (
|
|||
PlaceholderLineEdit,
|
||||
SeparatorWidget,
|
||||
set_style_property,
|
||||
)
|
||||
from ayon_core.tools.ayon_utils.widgets import (
|
||||
ProjectsCombobox,
|
||||
FoldersWidget,
|
||||
TasksWidget,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ from ayon_core.pipeline import (
|
|||
registered_host,
|
||||
get_current_context,
|
||||
)
|
||||
from ayon_core.tools.ayon_utils.models import HierarchyModel
|
||||
from ayon_core.tools.common_models import HierarchyModel
|
||||
|
||||
from .models import SiteSyncModel
|
||||
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ from ayon_core.pipeline import (
|
|||
HeroVersionType,
|
||||
)
|
||||
from ayon_core.style import get_default_entity_icon_color
|
||||
from ayon_core.tools.utils import get_qt_icon
|
||||
from ayon_core.tools.utils.models import TreeModel, Item
|
||||
from ayon_core.tools.ayon_utils.widgets import get_qt_icon
|
||||
|
||||
|
||||
def walk_hierarchy(node):
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ from ayon_core.tools.utils import (
|
|||
PlaceholderLineEdit,
|
||||
BaseClickableFrame,
|
||||
set_style_property,
|
||||
FoldersWidget,
|
||||
)
|
||||
from ayon_core.tools.ayon_utils.widgets import FoldersWidget
|
||||
|
||||
NOT_SET = object()
|
||||
|
||||
|
|
|
|||
|
|
@ -16,9 +16,10 @@ from ayon_core.pipeline import install_host
|
|||
from ayon_core.hosts.traypublisher.api import TrayPublisherHost
|
||||
from ayon_core.tools.publisher.control_qt import QtPublisherController
|
||||
from ayon_core.tools.publisher.window import PublisherWindow
|
||||
from ayon_core.tools.utils import PlaceholderLineEdit, get_ayon_qt_app
|
||||
from ayon_core.tools.ayon_utils.models import ProjectsModel
|
||||
from ayon_core.tools.ayon_utils.widgets import (
|
||||
from ayon_core.tools.common_models import ProjectsModel
|
||||
from ayon_core.tools.utils import (
|
||||
PlaceholderLineEdit,
|
||||
get_ayon_qt_app,
|
||||
ProjectsQtModel,
|
||||
ProjectSortFilterProxy,
|
||||
PROJECT_NAME_ROLE,
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ from .lib import (
|
|||
get_qt_app,
|
||||
get_ayon_qt_app,
|
||||
get_openpype_qt_app,
|
||||
get_qt_icon,
|
||||
)
|
||||
|
||||
from .models import (
|
||||
|
|
@ -55,6 +56,28 @@ from .dialogs import (
|
|||
SimplePopup,
|
||||
PopupUpdateKeys,
|
||||
)
|
||||
from .projects_widget import (
|
||||
ProjectsCombobox,
|
||||
ProjectsQtModel,
|
||||
ProjectSortFilterProxy,
|
||||
PROJECT_NAME_ROLE,
|
||||
PROJECT_IS_CURRENT_ROLE,
|
||||
PROJECT_IS_ACTIVE_ROLE,
|
||||
PROJECT_IS_LIBRARY_ROLE,
|
||||
)
|
||||
|
||||
from .folders_widget import (
|
||||
FoldersWidget,
|
||||
FoldersQtModel,
|
||||
FOLDERS_MODEL_SENDER_NAME,
|
||||
SimpleFoldersWidget,
|
||||
)
|
||||
|
||||
from .tasks_widget import (
|
||||
TasksWidget,
|
||||
TasksQtModel,
|
||||
TASKS_MODEL_SENDER_NAME,
|
||||
)
|
||||
|
||||
|
||||
__all__ = (
|
||||
|
|
@ -96,6 +119,7 @@ __all__ = (
|
|||
"get_qt_app",
|
||||
"get_ayon_qt_app",
|
||||
"get_openpype_qt_app",
|
||||
"get_qt_icon",
|
||||
|
||||
"RecursiveSortFilterProxyModel",
|
||||
|
||||
|
|
@ -113,4 +137,21 @@ __all__ = (
|
|||
"ScrollMessageBox",
|
||||
"SimplePopup",
|
||||
"PopupUpdateKeys",
|
||||
|
||||
"ProjectsCombobox",
|
||||
"ProjectsQtModel",
|
||||
"ProjectSortFilterProxy",
|
||||
"PROJECT_NAME_ROLE",
|
||||
"PROJECT_IS_CURRENT_ROLE",
|
||||
"PROJECT_IS_ACTIVE_ROLE",
|
||||
"PROJECT_IS_LIBRARY_ROLE",
|
||||
|
||||
"FoldersWidget",
|
||||
"FoldersQtModel",
|
||||
"FOLDERS_MODEL_SENDER_NAME",
|
||||
"SimpleFoldersWidget",
|
||||
|
||||
"TasksWidget",
|
||||
"TasksQtModel",
|
||||
"TASKS_MODEL_SENDER_NAME",
|
||||
)
|
||||
|
|
|
|||
|
|
@ -3,16 +3,15 @@ import collections
|
|||
from qtpy import QtWidgets, QtGui, QtCore
|
||||
|
||||
from ayon_core.lib.events import QueuedEventSystem
|
||||
from ayon_core.tools.ayon_utils.models import (
|
||||
from ayon_core.tools.common_models import (
|
||||
HierarchyModel,
|
||||
HierarchyExpectedSelection,
|
||||
)
|
||||
from ayon_core.tools.utils import (
|
||||
RecursiveSortFilterProxyModel,
|
||||
TreeView,
|
||||
)
|
||||
|
||||
from .utils import RefreshThread, get_qt_icon
|
||||
from .models import RecursiveSortFilterProxyModel
|
||||
from .views import TreeView
|
||||
from .lib import RefreshThread, get_qt_icon
|
||||
|
||||
|
||||
FOLDERS_MODEL_SENDER_NAME = "qt_folders_model"
|
||||
FOLDER_ID_ROLE = QtCore.Qt.UserRole + 1
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import os
|
||||
import sys
|
||||
import contextlib
|
||||
from functools import partial
|
||||
|
||||
from qtpy import QtWidgets, QtCore, QtGui
|
||||
import qtawesome
|
||||
|
|
@ -195,51 +196,6 @@ def get_openpype_qt_app():
|
|||
return get_ayon_qt_app()
|
||||
|
||||
|
||||
class _Cache:
|
||||
icons = {}
|
||||
|
||||
|
||||
def get_qta_icon_by_name_and_color(icon_name, icon_color):
|
||||
if not icon_name or not icon_color:
|
||||
return None
|
||||
|
||||
full_icon_name = "{0}-{1}".format(icon_name, icon_color)
|
||||
if full_icon_name in _Cache.icons:
|
||||
return _Cache.icons[full_icon_name]
|
||||
|
||||
variants = [icon_name]
|
||||
qta_instance = qtawesome._instance()
|
||||
for key in qta_instance.charmap.keys():
|
||||
variants.append("{0}.{1}".format(key, icon_name))
|
||||
|
||||
icon = None
|
||||
used_variant = None
|
||||
for variant in variants:
|
||||
try:
|
||||
icon = qtawesome.icon(variant, color=icon_color)
|
||||
used_variant = variant
|
||||
break
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if used_variant is None:
|
||||
log.info("Didn't find icon \"{}\"".format(icon_name))
|
||||
|
||||
elif used_variant != icon_name:
|
||||
log.debug("Icon \"{}\" was not found \"{}\" is used instead".format(
|
||||
icon_name, used_variant
|
||||
))
|
||||
|
||||
_Cache.icons[full_icon_name] = icon
|
||||
return icon
|
||||
|
||||
|
||||
def get_default_task_icon(color=None):
|
||||
if color is None:
|
||||
color = get_default_entity_icon_color()
|
||||
return get_qta_icon_by_name_and_color("fa.male", color)
|
||||
|
||||
|
||||
def iter_model_rows(model, column, include_root=False):
|
||||
"""Iterate over all row indices in a model"""
|
||||
indices = [QtCore.QModelIndex()] # start iteration at root
|
||||
|
|
@ -457,3 +413,156 @@ def get_warning_pixmap(color=None):
|
|||
color = get_objected_colors("delete-btn-bg").get_qcolor()
|
||||
|
||||
return paint_image_with_color(src_image, color)
|
||||
|
||||
|
||||
class RefreshThread(QtCore.QThread):
|
||||
refresh_finished = QtCore.Signal(str)
|
||||
|
||||
def __init__(self, thread_id, func, *args, **kwargs):
|
||||
super(RefreshThread, self).__init__()
|
||||
self._id = thread_id
|
||||
self._callback = partial(func, *args, **kwargs)
|
||||
self._exception = None
|
||||
self._result = None
|
||||
self.finished.connect(self._on_finish_callback)
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return self._id
|
||||
|
||||
@property
|
||||
def failed(self):
|
||||
return self._exception is not None
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
self._result = self._callback()
|
||||
except Exception as exc:
|
||||
self._exception = exc
|
||||
|
||||
def get_result(self):
|
||||
return self._result
|
||||
|
||||
def _on_finish_callback(self):
|
||||
"""Trigger custom signal with thread id.
|
||||
|
||||
Listening for 'finished' signal we make sure that execution of thread
|
||||
finished and QThread object can be safely deleted.
|
||||
"""
|
||||
|
||||
self.refresh_finished.emit(self.id)
|
||||
|
||||
|
||||
class _IconsCache:
|
||||
"""Cache for icons."""
|
||||
|
||||
_cache = {}
|
||||
_default = None
|
||||
_qtawesome_cache = {}
|
||||
|
||||
@classmethod
|
||||
def _get_cache_key(cls, icon_def):
|
||||
parts = []
|
||||
icon_type = icon_def["type"]
|
||||
if icon_type == "path":
|
||||
parts = [icon_type, icon_def["path"]]
|
||||
|
||||
elif icon_type == "awesome-font":
|
||||
parts = [icon_type, icon_def["name"], icon_def["color"]]
|
||||
return "|".join(parts)
|
||||
|
||||
@classmethod
|
||||
def get_icon(cls, icon_def):
|
||||
if not icon_def:
|
||||
return None
|
||||
icon_type = icon_def["type"]
|
||||
cache_key = cls._get_cache_key(icon_def)
|
||||
cache = cls._cache.get(cache_key)
|
||||
if cache is not None:
|
||||
return cache
|
||||
|
||||
icon = None
|
||||
if icon_type == "path":
|
||||
path = icon_def["path"]
|
||||
if os.path.exists(path):
|
||||
icon = QtGui.QIcon(path)
|
||||
|
||||
elif icon_type == "awesome-font":
|
||||
icon_name = icon_def["name"]
|
||||
icon_color = icon_def["color"]
|
||||
icon = cls.get_qta_icon_by_name_and_color(icon_name, icon_color)
|
||||
if icon is None:
|
||||
icon = cls.get_qta_icon_by_name_and_color(
|
||||
"fa.{}".format(icon_name), icon_color)
|
||||
if icon is None:
|
||||
icon = cls.get_default()
|
||||
cls._cache[cache_key] = icon
|
||||
return icon
|
||||
|
||||
@classmethod
|
||||
def get_default(cls):
|
||||
pix = QtGui.QPixmap(1, 1)
|
||||
pix.fill(QtCore.Qt.transparent)
|
||||
return QtGui.QIcon(pix)
|
||||
|
||||
@classmethod
|
||||
def get_qta_icon_by_name_and_color(cls, icon_name, icon_color):
|
||||
if not icon_name or not icon_color:
|
||||
return None
|
||||
|
||||
full_icon_name = "{0}-{1}".format(icon_name, icon_color)
|
||||
if full_icon_name in cls._qtawesome_cache:
|
||||
return cls._qtawesome_cache[full_icon_name]
|
||||
|
||||
variants = [icon_name]
|
||||
qta_instance = qtawesome._instance()
|
||||
for key in qta_instance.charmap.keys():
|
||||
variants.append("{0}.{1}".format(key, icon_name))
|
||||
|
||||
icon = None
|
||||
used_variant = None
|
||||
for variant in variants:
|
||||
try:
|
||||
icon = qtawesome.icon(variant, color=icon_color)
|
||||
used_variant = variant
|
||||
break
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if used_variant is None:
|
||||
log.info("Didn't find icon \"{}\"".format(icon_name))
|
||||
|
||||
elif used_variant != icon_name:
|
||||
log.debug("Icon \"{}\" was not found \"{}\" is used instead".format(
|
||||
icon_name, used_variant
|
||||
))
|
||||
|
||||
cls._qtawesome_cache[full_icon_name] = icon
|
||||
return icon
|
||||
|
||||
|
||||
def get_qt_icon(icon_def):
|
||||
"""Returns icon from cache or creates new one.
|
||||
|
||||
Args:
|
||||
icon_def (dict[str, Any]): Icon definition.
|
||||
|
||||
Returns:
|
||||
QtGui.QIcon: Icon.
|
||||
|
||||
"""
|
||||
return _IconsCache.get_icon(icon_def)
|
||||
|
||||
|
||||
def get_qta_icon_by_name_and_color(icon_name, icon_color):
|
||||
"""Returns icon from cache or creates new one.
|
||||
|
||||
Args:
|
||||
icon_name (str): Icon name.
|
||||
icon_color (str): Icon color.
|
||||
|
||||
Returns:
|
||||
QtGui.QIcon: Icon.
|
||||
|
||||
"""
|
||||
return _IconsCache.get_qta_icon_by_name_and_color(icon_name, icon_color)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
from qtpy import QtWidgets, QtCore, QtGui
|
||||
|
||||
from ayon_core.tools.ayon_utils.models import PROJECTS_MODEL_SENDER
|
||||
from .utils import RefreshThread, get_qt_icon
|
||||
from ayon_core.tools.common_models import PROJECTS_MODEL_SENDER
|
||||
|
||||
from .lib import RefreshThread, get_qt_icon
|
||||
|
||||
PROJECT_NAME_ROLE = QtCore.Qt.UserRole + 1
|
||||
PROJECT_IS_ACTIVE_ROLE = QtCore.Qt.UserRole + 2
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
from qtpy import QtWidgets, QtGui, QtCore
|
||||
|
||||
from ayon_core.style import get_disabled_entity_icon_color
|
||||
from ayon_core.tools.utils import DeselectableTreeView
|
||||
|
||||
from .utils import RefreshThread, get_qt_icon
|
||||
from .views import DeselectableTreeView
|
||||
from .lib import RefreshThread, get_qt_icon
|
||||
|
||||
TASKS_MODEL_SENDER_NAME = "qt_tasks_model"
|
||||
ITEM_ID_ROLE = QtCore.Qt.UserRole + 1
|
||||
|
|
@ -15,7 +15,7 @@ from ayon_core.pipeline.context_tools import (
|
|||
)
|
||||
from ayon_core.pipeline.workfile import create_workdir_extra_folders
|
||||
|
||||
from ayon_core.tools.ayon_utils.models import (
|
||||
from ayon_core.tools.common_models import (
|
||||
HierarchyModel,
|
||||
HierarchyExpectedSelection,
|
||||
ProjectsModel,
|
||||
|
|
|
|||
|
|
@ -6,9 +6,13 @@ from ayon_core.tools.utils import (
|
|||
MessageOverlayObject,
|
||||
)
|
||||
|
||||
from ayon_core.tools.ayon_utils.widgets import FoldersWidget, TasksWidget
|
||||
from ayon_core.tools.workfiles.control import BaseWorkfileController
|
||||
from ayon_core.tools.utils import GoToCurrentButton, RefreshButton
|
||||
from ayon_core.tools.utils import (
|
||||
GoToCurrentButton,
|
||||
RefreshButton,
|
||||
FoldersWidget,
|
||||
TasksWidget,
|
||||
)
|
||||
|
||||
from .side_panel import SidePanelWidget
|
||||
from .files_widget import FilesWidget
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue