mirror of
https://github.com/ynput/ayon-core.git
synced 2026-01-01 08:24:53 +01:00
Merge branch 'develop' of https://github.com/ynput/ayon-core into enhancement/create_context_typing
# Conflicts: # server_addon/jobqueue/client/ayon_jobqueue/addon.py
This commit is contained in:
commit
ad208251a3
1060 changed files with 3640 additions and 181796 deletions
|
|
@ -87,7 +87,9 @@ class IntegrateHeroVersion(
|
|||
]
|
||||
# QUESTION/TODO this process should happen on server if crashed due to
|
||||
# permissions error on files (files were used or user didn't have perms)
|
||||
# *but all other plugins must be sucessfully completed
|
||||
# *but all other plugins must be successfully completed
|
||||
|
||||
use_hardlinks = False
|
||||
|
||||
def process(self, instance):
|
||||
if not self.is_active(instance.data):
|
||||
|
|
@ -617,24 +619,32 @@ class IntegrateHeroVersion(
|
|||
|
||||
self.log.debug("Folder already exists: \"{}\"".format(dirname))
|
||||
|
||||
if self.use_hardlinks:
|
||||
# First try hardlink and copy if paths are cross drive
|
||||
self.log.debug("Hardlinking file \"{}\" to \"{}\"".format(
|
||||
src_path, dst_path
|
||||
))
|
||||
try:
|
||||
create_hard_link(src_path, dst_path)
|
||||
# Return when successful
|
||||
return
|
||||
|
||||
except OSError as exc:
|
||||
# re-raise exception if different than
|
||||
# EXDEV - cross drive path
|
||||
# EINVAL - wrong format, must be NTFS
|
||||
self.log.debug(
|
||||
"Hardlink failed with errno:'{}'".format(exc.errno))
|
||||
if exc.errno not in [errno.EXDEV, errno.EINVAL]:
|
||||
raise
|
||||
|
||||
self.log.debug(
|
||||
"Hardlinking failed, falling back to regular copy...")
|
||||
|
||||
self.log.debug("Copying file \"{}\" to \"{}\"".format(
|
||||
src_path, dst_path
|
||||
))
|
||||
|
||||
# First try hardlink and copy if paths are cross drive
|
||||
try:
|
||||
create_hard_link(src_path, dst_path)
|
||||
# Return when successful
|
||||
return
|
||||
|
||||
except OSError as exc:
|
||||
# re-raise exception if different than
|
||||
# EXDEV - cross drive path
|
||||
# EINVAL - wrong format, must be NTFS
|
||||
self.log.debug("Hardlink failed with errno:'{}'".format(exc.errno))
|
||||
if exc.errno not in [errno.EXDEV, errno.EINVAL]:
|
||||
raise
|
||||
|
||||
shutil.copy(src_path, dst_path)
|
||||
|
||||
def version_from_representations(self, project_name, repres):
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ from .projects import (
|
|||
ProjectItem,
|
||||
ProjectsModel,
|
||||
PROJECTS_MODEL_SENDER,
|
||||
FolderTypeItem,
|
||||
TaskTypeItem,
|
||||
)
|
||||
from .hierarchy import (
|
||||
FolderItem,
|
||||
|
|
@ -28,6 +30,8 @@ __all__ = (
|
|||
"ProjectItem",
|
||||
"ProjectsModel",
|
||||
"PROJECTS_MODEL_SENDER",
|
||||
"FolderTypeItem",
|
||||
"TaskTypeItem",
|
||||
|
||||
"FolderItem",
|
||||
"TaskItem",
|
||||
|
|
|
|||
587
client/ayon_core/tools/publisher/abstract.py
Normal file
587
client/ayon_core/tools/publisher/abstract.py
Normal file
|
|
@ -0,0 +1,587 @@
|
|||
from abc import ABC, abstractmethod
|
||||
from typing import (
|
||||
Optional,
|
||||
Dict,
|
||||
List,
|
||||
Tuple,
|
||||
Any,
|
||||
Callable,
|
||||
Union,
|
||||
Iterable,
|
||||
TYPE_CHECKING,
|
||||
)
|
||||
|
||||
from ayon_core.lib import AbstractAttrDef
|
||||
from ayon_core.host import HostBase
|
||||
from ayon_core.pipeline.create import CreateContext, CreatedInstance
|
||||
from ayon_core.pipeline.create.context import ConvertorItem
|
||||
from ayon_core.tools.common_models import (
|
||||
FolderItem,
|
||||
TaskItem,
|
||||
FolderTypeItem,
|
||||
TaskTypeItem,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .models import CreatorItem
|
||||
|
||||
|
||||
class CardMessageTypes:
|
||||
standard = None
|
||||
info = "info"
|
||||
error = "error"
|
||||
|
||||
|
||||
class AbstractPublisherCommon(ABC):
|
||||
@abstractmethod
|
||||
def register_event_callback(self, topic, callback):
|
||||
"""Register event callback.
|
||||
|
||||
Listen for events with given topic.
|
||||
|
||||
Args:
|
||||
topic (str): Name of topic.
|
||||
callback (Callable): Callback that will be called when event
|
||||
is triggered.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def emit_event(
|
||||
self, topic: str,
|
||||
data: Optional[Dict[str, Any]] = None,
|
||||
source: Optional[str] = None
|
||||
):
|
||||
"""Emit event.
|
||||
|
||||
Args:
|
||||
topic (str): Event topic used for callbacks filtering.
|
||||
data (Optional[dict[str, Any]]): Event data.
|
||||
source (Optional[str]): Event source.
|
||||
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def emit_card_message(
|
||||
self,
|
||||
message: str,
|
||||
message_type: Optional[str] = CardMessageTypes.standard
|
||||
):
|
||||
"""Emit a card message which can have a lifetime.
|
||||
|
||||
This is for UI purposes. Method can be extended to more arguments
|
||||
in future e.g. different message timeout or type (color).
|
||||
|
||||
Args:
|
||||
message (str): Message that will be showed.
|
||||
message_type (Optional[str]): Message type.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_current_project_name(self) -> Union[str, None]:
|
||||
"""Current context project name.
|
||||
|
||||
Returns:
|
||||
str: Name of project.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_current_folder_path(self) -> Union[str, None]:
|
||||
"""Current context folder path.
|
||||
|
||||
Returns:
|
||||
Union[str, None]: Folder path.
|
||||
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_current_task_name(self) -> Union[str, None]:
|
||||
"""Current context task name.
|
||||
|
||||
Returns:
|
||||
Union[str, None]: Name of task.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def host_context_has_changed(self) -> bool:
|
||||
"""Host context changed after last reset.
|
||||
|
||||
'CreateContext' has this option available using 'context_has_changed'.
|
||||
|
||||
Returns:
|
||||
bool: Context has changed.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def reset(self):
|
||||
"""Reset whole controller.
|
||||
|
||||
This should reset create context, publish context and all variables
|
||||
that are related to it.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class AbstractPublisherBackend(AbstractPublisherCommon):
|
||||
@abstractmethod
|
||||
def is_headless(self) -> bool:
|
||||
"""Controller is in headless mode.
|
||||
|
||||
Notes:
|
||||
Not sure if this method is relevant in UI tool?
|
||||
|
||||
Returns:
|
||||
bool: Headless mode.
|
||||
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_host(self) -> HostBase:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_create_context(self) -> CreateContext:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_task_item_by_name(
|
||||
self,
|
||||
project_name: str,
|
||||
folder_id: str,
|
||||
task_name: str,
|
||||
sender: Optional[str] = None
|
||||
) -> Union[TaskItem, None]:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_folder_entity(
|
||||
self, project_name: str, folder_id: str
|
||||
) -> Union[Dict[str, Any], None]:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_folder_item_by_path(
|
||||
self, project_name: str, folder_path: str
|
||||
) -> Union[FolderItem, None]:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_task_entity(
|
||||
self, project_name: str, task_id: str
|
||||
) -> Union[Dict[str, Any], None]:
|
||||
pass
|
||||
|
||||
|
||||
class AbstractPublisherFrontend(AbstractPublisherCommon):
|
||||
@abstractmethod
|
||||
def register_event_callback(self, topic: str, callback: Callable):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def is_host_valid(self) -> bool:
|
||||
"""Host is valid for creation part.
|
||||
|
||||
Host must have implemented certain functionality to be able create
|
||||
in Publisher tool.
|
||||
|
||||
Returns:
|
||||
bool: Host can handle creation of instances.
|
||||
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_context_title(self) -> Union[str, None]:
|
||||
"""Get context title for artist shown at the top of main window.
|
||||
|
||||
Returns:
|
||||
Union[str, None]: Context title for window or None. In case of None
|
||||
a warning is displayed (not nice for artists).
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_task_items_by_folder_paths(
|
||||
self, folder_paths: Iterable[str]
|
||||
) -> Dict[str, List[TaskItem]]:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_folder_items(
|
||||
self, project_name: str, sender: Optional[str] = None
|
||||
) -> List[FolderItem]:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_task_items(
|
||||
self, project_name: str, folder_id: str, sender: Optional[str] = None
|
||||
) -> List[TaskItem]:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_folder_type_items(
|
||||
self, project_name: str, sender: Optional[str] = None
|
||||
) -> List[FolderTypeItem]:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_task_type_items(
|
||||
self, project_name: str, sender: Optional[str] = None
|
||||
) -> List[TaskTypeItem]:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def are_folder_paths_valid(self, folder_paths: Iterable[str]) -> bool:
|
||||
"""Folder paths do exist in project.
|
||||
|
||||
Args:
|
||||
folder_paths (Iterable[str]): List of folder paths.
|
||||
|
||||
Returns:
|
||||
bool: All folder paths exist in project.
|
||||
|
||||
"""
|
||||
pass
|
||||
|
||||
# --- Create ---
|
||||
@abstractmethod
|
||||
def get_creator_items(self) -> Dict[str, "CreatorItem"]:
|
||||
"""Creator items by identifier.
|
||||
|
||||
Returns:
|
||||
Dict[str, CreatorItem]: Creator items that will be shown to user.
|
||||
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_creator_icon(
|
||||
self, identifier: str
|
||||
) -> Union[str, Dict[str, Any], None]:
|
||||
"""Receive creator's icon by identifier.
|
||||
|
||||
Todos:
|
||||
Icon should be part of 'CreatorItem'.
|
||||
|
||||
Args:
|
||||
identifier (str): Creator's identifier.
|
||||
|
||||
Returns:
|
||||
Union[str, None]: Creator's icon string.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_convertor_items(self) -> Dict[str, ConvertorItem]:
|
||||
"""Convertor items by identifier.
|
||||
|
||||
Returns:
|
||||
Dict[str, ConvertorItem]: Convertor items that can be triggered
|
||||
by user.
|
||||
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_instances(self) -> List[CreatedInstance]:
|
||||
"""Collected/created instances.
|
||||
|
||||
Returns:
|
||||
List[CreatedInstance]: List of created instances.
|
||||
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_instances_by_id(
|
||||
self, instance_ids: Optional[Iterable[str]] = None
|
||||
) -> Dict[str, Union[CreatedInstance, None]]:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_existing_product_names(self, folder_path: str) -> List[str]:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_creator_attribute_definitions(
|
||||
self, instances: List[CreatedInstance]
|
||||
) -> List[Tuple[AbstractAttrDef, List[CreatedInstance], List[Any]]]:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_publish_attribute_definitions(
|
||||
self,
|
||||
instances: List[CreatedInstance],
|
||||
include_context: bool
|
||||
) -> List[Tuple[
|
||||
str,
|
||||
List[AbstractAttrDef],
|
||||
Dict[str, List[Tuple[CreatedInstance, Any]]]
|
||||
]]:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_product_name(
|
||||
self,
|
||||
creator_identifier: str,
|
||||
variant: str,
|
||||
task_name: Union[str, None],
|
||||
folder_path: Union[str, None],
|
||||
instance_id: Optional[str] = None
|
||||
):
|
||||
"""Get product name based on passed data.
|
||||
|
||||
Args:
|
||||
creator_identifier (str): Identifier of creator which should be
|
||||
responsible for product name creation.
|
||||
variant (str): Variant value from user's input.
|
||||
task_name (str): Name of task for which is instance created.
|
||||
folder_path (str): Folder path for which is instance created.
|
||||
instance_id (Union[str, None]): Existing instance id when product
|
||||
name is updated.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def create(
|
||||
self,
|
||||
creator_identifier: str,
|
||||
product_name: str,
|
||||
instance_data: Dict[str, Any],
|
||||
options: Dict[str, Any],
|
||||
):
|
||||
"""Trigger creation by creator identifier.
|
||||
|
||||
Should also trigger refresh of instanes.
|
||||
|
||||
Args:
|
||||
creator_identifier (str): Identifier of Creator plugin.
|
||||
product_name (str): Calculated product name.
|
||||
instance_data (Dict[str, Any]): Base instance data with variant,
|
||||
folder path and task name.
|
||||
options (Dict[str, Any]): Data from pre-create attributes.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def trigger_convertor_items(self, convertor_identifiers: List[str]):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def remove_instances(self, instance_ids: Iterable[str]):
|
||||
"""Remove list of instances from create context."""
|
||||
# TODO expect instance ids
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def save_changes(self) -> bool:
|
||||
"""Save changes in create context.
|
||||
|
||||
Save can crash because of unexpected errors.
|
||||
|
||||
Returns:
|
||||
bool: Save was successful.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
# --- Publish ---
|
||||
@abstractmethod
|
||||
def publish(self):
|
||||
"""Trigger publishing without any order limitations."""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def validate(self):
|
||||
"""Trigger publishing which will stop after validation order."""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def stop_publish(self):
|
||||
"""Stop publishing can be also used to pause publishing.
|
||||
|
||||
Pause of publishing is possible only if all plugins successfully
|
||||
finished.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def run_action(self, plugin_id: str, action_id: str):
|
||||
"""Trigger pyblish action on a plugin.
|
||||
|
||||
Args:
|
||||
plugin_id (str): Id of publish plugin.
|
||||
action_id (str): Id of publish action.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def publish_has_started(self) -> bool:
|
||||
"""Has publishing finished.
|
||||
|
||||
Returns:
|
||||
bool: If publishing finished and all plugins were iterated.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def publish_has_finished(self) -> bool:
|
||||
"""Has publishing finished.
|
||||
|
||||
Returns:
|
||||
bool: If publishing finished and all plugins were iterated.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def publish_is_running(self) -> bool:
|
||||
"""Publishing is running right now.
|
||||
|
||||
Returns:
|
||||
bool: If publishing is in progress.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def publish_has_validated(self) -> bool:
|
||||
"""Publish validation passed.
|
||||
|
||||
Returns:
|
||||
bool: If publishing passed last possible validation order.
|
||||
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def publish_can_continue(self):
|
||||
"""Publish has still plugins to process and did not crash yet.
|
||||
|
||||
Returns:
|
||||
bool: Publishing can continue in processing.
|
||||
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def publish_has_crashed(self) -> bool:
|
||||
"""Publishing crashed for any reason.
|
||||
|
||||
Returns:
|
||||
bool: Publishing crashed.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def publish_has_validation_errors(self) -> bool:
|
||||
"""During validation happened at least one validation error.
|
||||
|
||||
Returns:
|
||||
bool: Validation error was raised during validation.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_publish_progress(self) -> int:
|
||||
"""Current progress number.
|
||||
|
||||
Returns:
|
||||
int: Current progress value from 0 to 'publish_max_progress'.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_publish_max_progress(self) -> int:
|
||||
"""Get maximum possible progress number.
|
||||
|
||||
Returns:
|
||||
int: Number that can be used as 100% of publish progress bar.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_publish_error_msg(self) -> Union[str, None]:
|
||||
"""Current error message which cause fail of publishing.
|
||||
|
||||
Returns:
|
||||
Union[str, None]: Message which will be showed to artist or
|
||||
None.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_publish_report(self) -> Dict[str, Any]:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_validation_errors(self):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def set_comment(self, comment: str):
|
||||
"""Set comment on pyblish context.
|
||||
|
||||
Set "comment" key on current pyblish.api.Context data.
|
||||
|
||||
Args:
|
||||
comment (str): Artist's comment.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_thumbnail_paths_for_instances(
|
||||
self, instance_ids: List[str]
|
||||
) -> Dict[str, Union[str, None]]:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def set_thumbnail_paths_for_instances(
|
||||
self, thumbnail_path_mapping: Dict[str, Optional[str]]
|
||||
):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_thumbnail_temp_dir_path(self) -> str:
|
||||
"""Return path to directory where thumbnails can be temporary stored.
|
||||
|
||||
Returns:
|
||||
str: Path to a directory.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def clear_thumbnail_temp_dir_path(self):
|
||||
"""Remove content of thumbnail temp directory."""
|
||||
|
||||
pass
|
||||
|
|
@ -37,6 +37,9 @@ __all__ = (
|
|||
"CONTEXT_ID",
|
||||
"CONTEXT_LABEL",
|
||||
|
||||
"CONTEXT_GROUP",
|
||||
"CONVERTOR_ITEM_GROUP",
|
||||
|
||||
"VARIANT_TOOLTIP",
|
||||
|
||||
"INPUTS_LAYOUT_HSPACING",
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,16 +1,23 @@
|
|||
import collections
|
||||
from abc import abstractmethod, abstractproperty
|
||||
|
||||
from qtpy import QtCore
|
||||
|
||||
from ayon_core.lib.events import Event
|
||||
from ayon_core.pipeline.create import CreatedInstance
|
||||
from .control import PublisherController
|
||||
|
||||
from .control import (
|
||||
MainThreadItem,
|
||||
PublisherController,
|
||||
BasePublisherController,
|
||||
)
|
||||
|
||||
class MainThreadItem:
|
||||
"""Callback with args and kwargs."""
|
||||
|
||||
def __init__(self, callback, *args, **kwargs):
|
||||
self.callback = callback
|
||||
self.args = args
|
||||
self.kwargs = kwargs
|
||||
|
||||
def __call__(self):
|
||||
self.process()
|
||||
|
||||
def process(self):
|
||||
self.callback(*self.args, **self.kwargs)
|
||||
|
||||
|
||||
class MainThreadProcess(QtCore.QObject):
|
||||
|
|
@ -24,7 +31,7 @@ class MainThreadProcess(QtCore.QObject):
|
|||
count_timeout = 2
|
||||
|
||||
def __init__(self):
|
||||
super(MainThreadProcess, self).__init__()
|
||||
super().__init__()
|
||||
self._items_to_process = collections.deque()
|
||||
|
||||
timer = QtCore.QTimer()
|
||||
|
|
@ -33,11 +40,6 @@ class MainThreadProcess(QtCore.QObject):
|
|||
timer.timeout.connect(self._execute)
|
||||
|
||||
self._timer = timer
|
||||
self._switch_counter = self.count_timeout
|
||||
|
||||
def process(self, func, *args, **kwargs):
|
||||
item = MainThreadItem(func, *args, **kwargs)
|
||||
self.add_item(item)
|
||||
|
||||
def add_item(self, item):
|
||||
self._items_to_process.append(item)
|
||||
|
|
@ -46,12 +48,6 @@ class MainThreadProcess(QtCore.QObject):
|
|||
if not self._items_to_process:
|
||||
return
|
||||
|
||||
if self._switch_counter > 0:
|
||||
self._switch_counter -= 1
|
||||
return
|
||||
|
||||
self._switch_counter = self.count_timeout
|
||||
|
||||
item = self._items_to_process.popleft()
|
||||
item.process()
|
||||
|
||||
|
|
@ -73,18 +69,34 @@ class QtPublisherController(PublisherController):
|
|||
def __init__(self, *args, **kwargs):
|
||||
self._main_thread_processor = MainThreadProcess()
|
||||
|
||||
super(QtPublisherController, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.event_system.add_callback(
|
||||
self.register_event_callback(
|
||||
"publish.process.started", self._qt_on_publish_start
|
||||
)
|
||||
self.event_system.add_callback(
|
||||
self.register_event_callback(
|
||||
"publish.process.stopped", self._qt_on_publish_stop
|
||||
)
|
||||
|
||||
def _reset_publish(self):
|
||||
super(QtPublisherController, self)._reset_publish()
|
||||
def reset(self):
|
||||
self._main_thread_processor.clear()
|
||||
super().reset()
|
||||
|
||||
def _start_publish(self, up_validation):
|
||||
self._publish_model.set_publish_up_validation(up_validation)
|
||||
self._publish_model.start_publish(wait=False)
|
||||
self._process_main_thread_item(
|
||||
MainThreadItem(self._next_publish_item_process)
|
||||
)
|
||||
|
||||
def _next_publish_item_process(self):
|
||||
if not self._publish_model.is_running():
|
||||
return
|
||||
func = self._publish_model.get_next_process_func()
|
||||
self._process_main_thread_item(MainThreadItem(func))
|
||||
self._process_main_thread_item(
|
||||
MainThreadItem(self._next_publish_item_process)
|
||||
)
|
||||
|
||||
def _process_main_thread_item(self, item):
|
||||
self._main_thread_processor.add_item(item)
|
||||
|
|
@ -94,347 +106,3 @@ class QtPublisherController(PublisherController):
|
|||
|
||||
def _qt_on_publish_stop(self):
|
||||
self._main_thread_processor.stop()
|
||||
|
||||
|
||||
class QtRemotePublishController(BasePublisherController):
|
||||
"""Abstract Remote controller for Qt UI.
|
||||
|
||||
This controller should be used in process where UI is running and should
|
||||
listen and ask for data on a client side.
|
||||
|
||||
All objects that are used during UI processing should be able to convert
|
||||
on client side to json serializable data and then recreated here. Keep in
|
||||
mind that all changes made here should be send back to client controller
|
||||
before critical actions.
|
||||
|
||||
ATM Was not tested and will require some changes. All code written here is
|
||||
based on theoretical idea how it could work.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self._created_instances = {}
|
||||
self._thumbnail_paths_by_instance_id = None
|
||||
|
||||
def _reset_attributes(self):
|
||||
super()._reset_attributes()
|
||||
self._thumbnail_paths_by_instance_id = None
|
||||
|
||||
@abstractmethod
|
||||
def _get_serialized_instances(self):
|
||||
"""Receive serialized instances from client process.
|
||||
|
||||
Returns:
|
||||
List[Dict[str, Any]]: Serialized instances.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
def _on_create_instance_change(self):
|
||||
serialized_instances = self._get_serialized_instances()
|
||||
|
||||
created_instances = {}
|
||||
for serialized_data in serialized_instances:
|
||||
item = CreatedInstance.deserialize_on_remote(serialized_data)
|
||||
created_instances[item.id] = item
|
||||
|
||||
self._created_instances = created_instances
|
||||
self._emit_event("instances.refresh.finished")
|
||||
|
||||
def remote_events_handler(self, event_data):
|
||||
event = Event.from_data(event_data)
|
||||
|
||||
# Topics that cause "replication" of controller changes
|
||||
if event.topic == "publish.max_progress.changed":
|
||||
self.publish_max_progress = event["value"]
|
||||
return
|
||||
|
||||
if event.topic == "publish.progress.changed":
|
||||
self.publish_progress = event["value"]
|
||||
return
|
||||
|
||||
if event.topic == "publish.has_validated.changed":
|
||||
self.publish_has_validated = event["value"]
|
||||
return
|
||||
|
||||
if event.topic == "publish.is_running.changed":
|
||||
self.publish_is_running = event["value"]
|
||||
return
|
||||
|
||||
if event.topic == "publish.publish_error.changed":
|
||||
self.publish_error_msg = event["value"]
|
||||
return
|
||||
|
||||
if event.topic == "publish.has_crashed.changed":
|
||||
self.publish_has_crashed = event["value"]
|
||||
return
|
||||
|
||||
if event.topic == "publish.has_validation_errors.changed":
|
||||
self.publish_has_validation_errors = event["value"]
|
||||
return
|
||||
|
||||
if event.topic == "publish.finished.changed":
|
||||
self.publish_has_finished = event["value"]
|
||||
return
|
||||
|
||||
if event.topic == "publish.host_is_valid.changed":
|
||||
self.host_is_valid = event["value"]
|
||||
return
|
||||
|
||||
# Don't skip because UI want know about it too
|
||||
if event.topic == "instance.thumbnail.changed":
|
||||
for instance_id, path in event["mapping"].items():
|
||||
self.thumbnail_paths_by_instance_id[instance_id] = path
|
||||
|
||||
# Topics that can be just passed by because are not affecting
|
||||
# controller itself
|
||||
# - "show.card.message"
|
||||
# - "show.detailed.help"
|
||||
# - "publish.reset.finished"
|
||||
# - "instances.refresh.finished"
|
||||
# - "plugins.refresh.finished"
|
||||
# - "controller.reset.finished"
|
||||
# - "publish.process.started"
|
||||
# - "publish.process.stopped"
|
||||
# - "publish.process.plugin.changed"
|
||||
# - "publish.process.instance.changed"
|
||||
self.event_system.emit_event(event)
|
||||
|
||||
@abstractproperty
|
||||
def project_name(self):
|
||||
"""Current context project name from client.
|
||||
|
||||
Returns:
|
||||
str: Name of project.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractproperty
|
||||
def current_folder_path(self):
|
||||
"""Current context folder path from host.
|
||||
|
||||
Returns:
|
||||
Union[str, None]: Folder path.
|
||||
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractproperty
|
||||
def current_task_name(self):
|
||||
"""Current context task name from client.
|
||||
|
||||
Returns:
|
||||
Union[str, None]: Name of task.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@property
|
||||
def instances(self):
|
||||
"""Collected/created instances.
|
||||
|
||||
Returns:
|
||||
List[CreatedInstance]: List of created instances.
|
||||
"""
|
||||
|
||||
return self._created_instances
|
||||
|
||||
def get_context_title(self):
|
||||
"""Get context title for artist shown at the top of main window.
|
||||
|
||||
Returns:
|
||||
Union[str, None]: Context title for window or None. In case of None
|
||||
a warning is displayed (not nice for artists).
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
def get_existing_product_names(self, folder_path):
|
||||
pass
|
||||
|
||||
@property
|
||||
def thumbnail_paths_by_instance_id(self):
|
||||
if self._thumbnail_paths_by_instance_id is None:
|
||||
self._thumbnail_paths_by_instance_id = (
|
||||
self._collect_thumbnail_paths_by_instance_id()
|
||||
)
|
||||
return self._thumbnail_paths_by_instance_id
|
||||
|
||||
def get_thumbnail_path_for_instance(self, instance_id):
|
||||
return self.thumbnail_paths_by_instance_id.get(instance_id)
|
||||
|
||||
def set_thumbnail_path_for_instance(self, instance_id, thumbnail_path):
|
||||
self._set_thumbnail_path_on_context(self, instance_id, thumbnail_path)
|
||||
|
||||
@abstractmethod
|
||||
def _collect_thumbnail_paths_by_instance_id(self):
|
||||
"""Collect thumbnail paths by instance id in remote controller.
|
||||
|
||||
These should be collected from 'CreatedContext' there.
|
||||
|
||||
Returns:
|
||||
Dict[str, str]: Mapping of thumbnail path by instance id.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def _set_thumbnail_path_on_context(self, instance_id, thumbnail_path):
|
||||
"""Send change of thumbnail path in remote controller.
|
||||
|
||||
That should trigger event 'instance.thumbnail.changed' which is
|
||||
captured and handled in default implementation in this class.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_product_name(
|
||||
self,
|
||||
creator_identifier,
|
||||
variant,
|
||||
task_name,
|
||||
folder_path,
|
||||
instance_id=None
|
||||
):
|
||||
"""Get product name based on passed data.
|
||||
|
||||
Args:
|
||||
creator_identifier (str): Identifier of creator which should be
|
||||
responsible for product name creation.
|
||||
variant (str): Variant value from user's input.
|
||||
task_name (str): Name of task for which is instance created.
|
||||
folder_path (str): Folder path for which is instance created.
|
||||
instance_id (Union[str, None]): Existing instance id when product
|
||||
name is updated.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def create(
|
||||
self, creator_identifier, product_name, instance_data, options
|
||||
):
|
||||
"""Trigger creation by creator identifier.
|
||||
|
||||
Should also trigger refresh of instanes.
|
||||
|
||||
Args:
|
||||
creator_identifier (str): Identifier of Creator plugin.
|
||||
product_name (str): Calculated product name.
|
||||
instance_data (Dict[str, Any]): Base instance data with variant,
|
||||
folder path and task name.
|
||||
options (Dict[str, Any]): Data from pre-create attributes.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
def _get_instance_changes_for_client(self):
|
||||
"""Preimplemented method to receive instance changes for client."""
|
||||
|
||||
created_instance_changes = {}
|
||||
for instance_id, instance in self._created_instances.items():
|
||||
created_instance_changes[instance_id] = (
|
||||
instance.remote_changes()
|
||||
)
|
||||
return created_instance_changes
|
||||
|
||||
@abstractmethod
|
||||
def _send_instance_changes_to_client(self):
|
||||
# TODO Implement to send 'instance_changes' value to client
|
||||
# instance_changes = self._get_instance_changes_for_client()
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def save_changes(self):
|
||||
"""Save changes happened during creation."""
|
||||
|
||||
self._send_instance_changes_to_client()
|
||||
|
||||
@abstractmethod
|
||||
def remove_instances(self, instance_ids):
|
||||
"""Remove list of instances from create context."""
|
||||
# TODO add Args:
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_publish_report(self):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_validation_errors(self):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def reset(self):
|
||||
"""Reset whole controller.
|
||||
|
||||
This should reset create context, publish context and all variables
|
||||
that are related to it.
|
||||
"""
|
||||
|
||||
self._send_instance_changes_to_client()
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def publish(self):
|
||||
"""Trigger publishing without any order limitations."""
|
||||
|
||||
self._send_instance_changes_to_client()
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def validate(self):
|
||||
"""Trigger publishing which will stop after validation order."""
|
||||
|
||||
self._send_instance_changes_to_client()
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def stop_publish(self):
|
||||
"""Stop publishing can be also used to pause publishing.
|
||||
|
||||
Pause of publishing is possible only if all plugins successfully
|
||||
finished.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def run_action(self, plugin_id, action_id):
|
||||
"""Trigger pyblish action on a plugin.
|
||||
|
||||
Args:
|
||||
plugin_id (str): Id of publish plugin.
|
||||
action_id (str): Id of publish action.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def set_comment(self, comment):
|
||||
"""Set comment on pyblish context.
|
||||
|
||||
Set "comment" key on current pyblish.api.Context data.
|
||||
|
||||
Args:
|
||||
comment (str): Artist's comment.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def emit_card_message(self, message):
|
||||
"""Emit a card message which can have a lifetime.
|
||||
|
||||
This is for UI purposes. Method can be extended to more arguments
|
||||
in future e.g. different message timeout or type (color).
|
||||
|
||||
Args:
|
||||
message (str): Message that will be showed.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
|
|
|||
10
client/ayon_core/tools/publisher/models/__init__.py
Normal file
10
client/ayon_core/tools/publisher/models/__init__.py
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
from .create import CreateModel, CreatorItem
|
||||
from .publish import PublishModel
|
||||
|
||||
|
||||
__all__ = (
|
||||
"CreateModel",
|
||||
"CreatorItem",
|
||||
|
||||
"PublishModel",
|
||||
)
|
||||
758
client/ayon_core/tools/publisher/models/create.py
Normal file
758
client/ayon_core/tools/publisher/models/create.py
Normal file
|
|
@ -0,0 +1,758 @@
|
|||
import logging
|
||||
import re
|
||||
from typing import Union, List, Dict, Tuple, Any, Optional, Iterable, Pattern
|
||||
|
||||
from ayon_core.lib.attribute_definitions import (
|
||||
serialize_attr_defs,
|
||||
deserialize_attr_defs,
|
||||
AbstractAttrDef,
|
||||
)
|
||||
from ayon_core.lib.profiles_filtering import filter_profiles
|
||||
from ayon_core.lib.attribute_definitions import UIDef
|
||||
from ayon_core.pipeline.create import (
|
||||
BaseCreator,
|
||||
AutoCreator,
|
||||
HiddenCreator,
|
||||
Creator,
|
||||
CreateContext,
|
||||
CreatedInstance,
|
||||
)
|
||||
from ayon_core.pipeline.create.context import (
|
||||
CreatorsOperationFailed,
|
||||
ConvertorsOperationFailed,
|
||||
ConvertorItem,
|
||||
)
|
||||
from ayon_core.tools.publisher.abstract import (
|
||||
AbstractPublisherBackend,
|
||||
CardMessageTypes,
|
||||
)
|
||||
CREATE_EVENT_SOURCE = "publisher.create.model"
|
||||
|
||||
|
||||
class CreatorType:
|
||||
def __init__(self, name: str):
|
||||
self.name: str = name
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.name == str(other)
|
||||
|
||||
def __ne__(self, other):
|
||||
# This is implemented only because of Python 2
|
||||
return not self == other
|
||||
|
||||
|
||||
class CreatorTypes:
|
||||
base = CreatorType("base")
|
||||
auto = CreatorType("auto")
|
||||
hidden = CreatorType("hidden")
|
||||
artist = CreatorType("artist")
|
||||
|
||||
@classmethod
|
||||
def from_str(cls, value: str) -> CreatorType:
|
||||
for creator_type in (
|
||||
cls.base,
|
||||
cls.auto,
|
||||
cls.hidden,
|
||||
cls.artist
|
||||
):
|
||||
if value == creator_type:
|
||||
return creator_type
|
||||
raise ValueError("Unknown type \"{}\"".format(str(value)))
|
||||
|
||||
|
||||
class CreatorItem:
|
||||
"""Wrapper around Creator plugin.
|
||||
|
||||
Object can be serialized and recreated.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
identifier: str,
|
||||
creator_type: CreatorType,
|
||||
product_type: str,
|
||||
label: str,
|
||||
group_label: str,
|
||||
icon: Union[str, Dict[str, Any], None],
|
||||
description: Union[str, None],
|
||||
detailed_description: Union[str, None],
|
||||
default_variant: Union[str, None],
|
||||
default_variants: Union[List[str], None],
|
||||
create_allow_context_change: Union[bool, None],
|
||||
create_allow_thumbnail: Union[bool, None],
|
||||
show_order: int,
|
||||
pre_create_attributes_defs: List[AbstractAttrDef],
|
||||
):
|
||||
self.identifier: str = identifier
|
||||
self.creator_type: CreatorType = creator_type
|
||||
self.product_type: str = product_type
|
||||
self.label: str = label
|
||||
self.group_label: str = group_label
|
||||
self.icon: Union[str, Dict[str, Any], None] = icon
|
||||
self.description: Union[str, None] = description
|
||||
self.detailed_description: Union[bool, None] = detailed_description
|
||||
self.default_variant: Union[bool, None] = default_variant
|
||||
self.default_variants: Union[List[str], None] = default_variants
|
||||
self.create_allow_context_change: Union[bool, None] = (
|
||||
create_allow_context_change
|
||||
)
|
||||
self.create_allow_thumbnail: Union[bool, None] = create_allow_thumbnail
|
||||
self.show_order: int = show_order
|
||||
self.pre_create_attributes_defs: List[AbstractAttrDef] = (
|
||||
pre_create_attributes_defs
|
||||
)
|
||||
|
||||
def get_group_label(self) -> str:
|
||||
return self.group_label
|
||||
|
||||
@classmethod
|
||||
def from_creator(cls, creator: BaseCreator):
|
||||
creator_type: CreatorType = CreatorTypes.base
|
||||
if isinstance(creator, AutoCreator):
|
||||
creator_type = CreatorTypes.auto
|
||||
elif isinstance(creator, HiddenCreator):
|
||||
creator_type = CreatorTypes.hidden
|
||||
elif isinstance(creator, Creator):
|
||||
creator_type = CreatorTypes.artist
|
||||
|
||||
description = None
|
||||
detail_description = None
|
||||
default_variant = None
|
||||
default_variants = None
|
||||
pre_create_attr_defs = None
|
||||
create_allow_context_change = None
|
||||
create_allow_thumbnail = None
|
||||
show_order = creator.order
|
||||
if creator_type is CreatorTypes.artist:
|
||||
description = creator.get_description()
|
||||
detail_description = creator.get_detail_description()
|
||||
default_variant = creator.get_default_variant()
|
||||
default_variants = creator.get_default_variants()
|
||||
pre_create_attr_defs = creator.get_pre_create_attr_defs()
|
||||
create_allow_context_change = creator.create_allow_context_change
|
||||
create_allow_thumbnail = creator.create_allow_thumbnail
|
||||
show_order = creator.show_order
|
||||
|
||||
identifier = creator.identifier
|
||||
return cls(
|
||||
identifier,
|
||||
creator_type,
|
||||
creator.product_type,
|
||||
creator.label or identifier,
|
||||
creator.get_group_label(),
|
||||
creator.get_icon(),
|
||||
description,
|
||||
detail_description,
|
||||
default_variant,
|
||||
default_variants,
|
||||
create_allow_context_change,
|
||||
create_allow_thumbnail,
|
||||
show_order,
|
||||
pre_create_attr_defs,
|
||||
)
|
||||
|
||||
def to_data(self) -> Dict[str, Any]:
|
||||
pre_create_attributes_defs = None
|
||||
if self.pre_create_attributes_defs is not None:
|
||||
pre_create_attributes_defs = serialize_attr_defs(
|
||||
self.pre_create_attributes_defs
|
||||
)
|
||||
|
||||
return {
|
||||
"identifier": self.identifier,
|
||||
"creator_type": str(self.creator_type),
|
||||
"product_type": self.product_type,
|
||||
"label": self.label,
|
||||
"group_label": self.group_label,
|
||||
"icon": self.icon,
|
||||
"description": self.description,
|
||||
"detailed_description": self.detailed_description,
|
||||
"default_variant": self.default_variant,
|
||||
"default_variants": self.default_variants,
|
||||
"create_allow_context_change": self.create_allow_context_change,
|
||||
"create_allow_thumbnail": self.create_allow_thumbnail,
|
||||
"show_order": self.show_order,
|
||||
"pre_create_attributes_defs": pre_create_attributes_defs,
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def from_data(cls, data: Dict[str, Any]) -> "CreatorItem":
|
||||
pre_create_attributes_defs = data["pre_create_attributes_defs"]
|
||||
if pre_create_attributes_defs is not None:
|
||||
data["pre_create_attributes_defs"] = deserialize_attr_defs(
|
||||
pre_create_attributes_defs
|
||||
)
|
||||
|
||||
data["creator_type"] = CreatorTypes.from_str(data["creator_type"])
|
||||
return cls(**data)
|
||||
|
||||
|
||||
class CreateModel:
|
||||
def __init__(self, controller: AbstractPublisherBackend):
|
||||
self._log = None
|
||||
self._controller: AbstractPublisherBackend = controller
|
||||
|
||||
self._create_context = CreateContext(
|
||||
controller.get_host(),
|
||||
headless=controller.is_headless(),
|
||||
reset=False
|
||||
)
|
||||
# State flags to prevent executing method which is already in progress
|
||||
self._creator_items = None
|
||||
|
||||
@property
|
||||
def log(self) -> logging.Logger:
|
||||
if self._log is None:
|
||||
self._log = logging.getLogger(self.__class__.__name__)
|
||||
return self._log
|
||||
|
||||
def is_host_valid(self) -> bool:
|
||||
return self._create_context.host_is_valid
|
||||
|
||||
def get_create_context(self) -> CreateContext:
|
||||
return self._create_context
|
||||
|
||||
def get_current_project_name(self) -> Union[str, None]:
|
||||
"""Current project context defined by host.
|
||||
|
||||
Returns:
|
||||
str: Project name.
|
||||
|
||||
"""
|
||||
return self._create_context.get_current_project_name()
|
||||
|
||||
def get_current_folder_path(self) -> Union[str, None]:
|
||||
"""Current context folder path defined by host.
|
||||
|
||||
Returns:
|
||||
Union[str, None]: Folder path or None if folder is not set.
|
||||
"""
|
||||
|
||||
return self._create_context.get_current_folder_path()
|
||||
|
||||
def get_current_task_name(self) -> Union[str, None]:
|
||||
"""Current context task name defined by host.
|
||||
|
||||
Returns:
|
||||
Union[str, None]: Task name or None if task is not set.
|
||||
"""
|
||||
|
||||
return self._create_context.get_current_task_name()
|
||||
|
||||
def host_context_has_changed(self) -> bool:
|
||||
return self._create_context.context_has_changed
|
||||
|
||||
def reset(self):
|
||||
self._create_context.reset_preparation()
|
||||
|
||||
# Reset current context
|
||||
self._create_context.reset_current_context()
|
||||
|
||||
self._create_context.reset_plugins()
|
||||
# Reset creator items
|
||||
self._creator_items = None
|
||||
|
||||
self._reset_instances()
|
||||
self._create_context.reset_finalization()
|
||||
|
||||
def get_creator_items(self) -> Dict[str, CreatorItem]:
|
||||
"""Creators that can be shown in create dialog."""
|
||||
if self._creator_items is None:
|
||||
self._creator_items = self._collect_creator_items()
|
||||
return self._creator_items
|
||||
|
||||
def get_creator_item_by_id(
|
||||
self, identifier: str
|
||||
) -> Union[CreatorItem, None]:
|
||||
items = self.get_creator_items()
|
||||
return items.get(identifier)
|
||||
|
||||
def get_creator_icon(
|
||||
self, identifier: str
|
||||
) -> Union[str, Dict[str, Any], None]:
|
||||
"""Function to receive icon for creator identifier.
|
||||
|
||||
Args:
|
||||
identifier (str): Creator's identifier for which should
|
||||
be icon returned.
|
||||
|
||||
"""
|
||||
creator_item = self.get_creator_item_by_id(identifier)
|
||||
if creator_item is not None:
|
||||
return creator_item.icon
|
||||
return None
|
||||
|
||||
def get_instances(self) -> List[CreatedInstance]:
|
||||
"""Current instances in create context."""
|
||||
return list(self._create_context.instances_by_id.values())
|
||||
|
||||
def get_instance_by_id(
|
||||
self, instance_id: str
|
||||
) -> Union[CreatedInstance, None]:
|
||||
return self._create_context.instances_by_id.get(instance_id)
|
||||
|
||||
def get_instances_by_id(
|
||||
self, instance_ids: Optional[Iterable[str]] = None
|
||||
) -> Dict[str, Union[CreatedInstance, None]]:
|
||||
if instance_ids is None:
|
||||
instance_ids = self._create_context.instances_by_id.keys()
|
||||
return {
|
||||
instance_id: self.get_instance_by_id(instance_id)
|
||||
for instance_id in instance_ids
|
||||
}
|
||||
|
||||
def get_convertor_items(self) -> Dict[str, ConvertorItem]:
|
||||
return self._create_context.convertor_items_by_id
|
||||
|
||||
def get_product_name(
|
||||
self,
|
||||
creator_identifier: str,
|
||||
variant: str,
|
||||
task_name: Union[str, None],
|
||||
folder_path: Union[str, None],
|
||||
instance_id: Optional[str] = None
|
||||
) -> str:
|
||||
"""Get product name based on passed data.
|
||||
|
||||
Args:
|
||||
creator_identifier (str): Identifier of creator which should be
|
||||
responsible for product name creation.
|
||||
variant (str): Variant value from user's input.
|
||||
task_name (str): Name of task for which is instance created.
|
||||
folder_path (str): Folder path for which is instance created.
|
||||
instance_id (Union[str, None]): Existing instance id when product
|
||||
name is updated.
|
||||
"""
|
||||
|
||||
creator = self._creators[creator_identifier]
|
||||
|
||||
instance = None
|
||||
if instance_id:
|
||||
instance = self.get_instance_by_id(instance_id)
|
||||
|
||||
project_name = self._controller.get_current_project_name()
|
||||
folder_item = self._controller.get_folder_item_by_path(
|
||||
project_name, folder_path
|
||||
)
|
||||
folder_entity = None
|
||||
task_item = None
|
||||
task_entity = None
|
||||
if folder_item is not None:
|
||||
folder_entity = self._controller.get_folder_entity(
|
||||
project_name, folder_item.entity_id
|
||||
)
|
||||
task_item = self._controller.get_task_item_by_name(
|
||||
project_name,
|
||||
folder_item.entity_id,
|
||||
task_name,
|
||||
CREATE_EVENT_SOURCE
|
||||
)
|
||||
|
||||
if task_item is not None:
|
||||
task_entity = self._controller.get_task_entity(
|
||||
project_name, task_item.task_id
|
||||
)
|
||||
|
||||
return creator.get_product_name(
|
||||
project_name,
|
||||
folder_entity,
|
||||
task_entity,
|
||||
variant,
|
||||
instance=instance
|
||||
)
|
||||
|
||||
def create(
|
||||
self,
|
||||
creator_identifier: str,
|
||||
product_name: str,
|
||||
instance_data: Dict[str, Any],
|
||||
options: Dict[str, Any],
|
||||
):
|
||||
"""Trigger creation and refresh of instances in UI."""
|
||||
|
||||
success = True
|
||||
try:
|
||||
self._create_context.create_with_unified_error(
|
||||
creator_identifier, product_name, instance_data, options
|
||||
)
|
||||
|
||||
except CreatorsOperationFailed as exc:
|
||||
success = False
|
||||
self._emit_event(
|
||||
"instances.create.failed",
|
||||
{
|
||||
"title": "Creation failed",
|
||||
"failed_info": exc.failed_info
|
||||
}
|
||||
)
|
||||
|
||||
self._on_create_instance_change()
|
||||
return success
|
||||
|
||||
def trigger_convertor_items(self, convertor_identifiers: List[str]):
|
||||
"""Trigger legacy item convertors.
|
||||
|
||||
This functionality requires to save and reset CreateContext. The reset
|
||||
is needed so Creators can collect converted items.
|
||||
|
||||
Args:
|
||||
convertor_identifiers (list[str]): Identifiers of convertor
|
||||
plugins.
|
||||
"""
|
||||
|
||||
success = True
|
||||
try:
|
||||
self._create_context.run_convertors(convertor_identifiers)
|
||||
|
||||
except ConvertorsOperationFailed as exc:
|
||||
success = False
|
||||
self._emit_event(
|
||||
"convertors.convert.failed",
|
||||
{
|
||||
"title": "Conversion failed",
|
||||
"failed_info": exc.failed_info
|
||||
}
|
||||
)
|
||||
|
||||
if success:
|
||||
self._controller.emit_card_message(
|
||||
"Conversion finished"
|
||||
)
|
||||
else:
|
||||
self._controller.emit_card_message(
|
||||
"Conversion failed",
|
||||
CardMessageTypes.error
|
||||
)
|
||||
|
||||
def save_changes(self, show_message: Optional[bool] = True) -> bool:
|
||||
"""Save changes happened during creation.
|
||||
|
||||
Trigger save of changes using host api. This functionality does not
|
||||
validate anything. It is required to do checks before this method is
|
||||
called to be able to give user actionable response e.g. check of
|
||||
context using 'host_context_has_changed'.
|
||||
|
||||
Args:
|
||||
show_message (bool): Show message that changes were
|
||||
saved successfully.
|
||||
|
||||
Returns:
|
||||
bool: Save of changes was successful.
|
||||
"""
|
||||
|
||||
if not self._create_context.host_is_valid:
|
||||
# TODO remove
|
||||
# Fake success save when host is not valid for CreateContext
|
||||
# this is for testing as experimental feature
|
||||
return True
|
||||
|
||||
try:
|
||||
self._create_context.save_changes()
|
||||
if show_message:
|
||||
self._controller.emit_card_message("Saved changes..")
|
||||
return True
|
||||
|
||||
except CreatorsOperationFailed as exc:
|
||||
self._emit_event(
|
||||
"instances.save.failed",
|
||||
{
|
||||
"title": "Instances save failed",
|
||||
"failed_info": exc.failed_info
|
||||
}
|
||||
)
|
||||
|
||||
return False
|
||||
|
||||
def remove_instances(self, instance_ids: List[str]):
|
||||
"""Remove instances based on instance ids.
|
||||
|
||||
Args:
|
||||
instance_ids (List[str]): List of instance ids to remove.
|
||||
"""
|
||||
|
||||
# QUESTION Expect that instances are really removed? In that case reset
|
||||
# is not required.
|
||||
self._remove_instances_from_context(instance_ids)
|
||||
|
||||
self._on_create_instance_change()
|
||||
|
||||
def get_creator_attribute_definitions(
|
||||
self, instances: List[CreatedInstance]
|
||||
) -> List[Tuple[AbstractAttrDef, List[CreatedInstance], List[Any]]]:
|
||||
"""Collect creator attribute definitions for multuple instances.
|
||||
|
||||
Args:
|
||||
instances (List[CreatedInstance]): List of created instances for
|
||||
which should be attribute definitions returned.
|
||||
"""
|
||||
|
||||
# NOTE it would be great if attrdefs would have hash method implemented
|
||||
# so they could be used as keys in dictionary
|
||||
output = []
|
||||
_attr_defs = {}
|
||||
for instance in instances:
|
||||
for attr_def in instance.creator_attribute_defs:
|
||||
found_idx = None
|
||||
for idx, _attr_def in _attr_defs.items():
|
||||
if attr_def == _attr_def:
|
||||
found_idx = idx
|
||||
break
|
||||
|
||||
value = None
|
||||
if attr_def.is_value_def:
|
||||
value = instance.creator_attributes[attr_def.key]
|
||||
if found_idx is None:
|
||||
idx = len(output)
|
||||
output.append((attr_def, [instance], [value]))
|
||||
_attr_defs[idx] = attr_def
|
||||
else:
|
||||
item = output[found_idx]
|
||||
item[1].append(instance)
|
||||
item[2].append(value)
|
||||
return output
|
||||
|
||||
def get_publish_attribute_definitions(
|
||||
self,
|
||||
instances: List[CreatedInstance],
|
||||
include_context: bool
|
||||
) -> List[Tuple[
|
||||
str,
|
||||
List[AbstractAttrDef],
|
||||
Dict[str, List[Tuple[CreatedInstance, Any]]]
|
||||
]]:
|
||||
"""Collect publish attribute definitions for passed instances.
|
||||
|
||||
Args:
|
||||
instances (list[CreatedInstance]): List of created instances for
|
||||
which should be attribute definitions returned.
|
||||
include_context (bool): Add context specific attribute definitions.
|
||||
|
||||
"""
|
||||
_tmp_items = []
|
||||
if include_context:
|
||||
_tmp_items.append(self._create_context)
|
||||
|
||||
for instance in instances:
|
||||
_tmp_items.append(instance)
|
||||
|
||||
all_defs_by_plugin_name = {}
|
||||
all_plugin_values = {}
|
||||
for item in _tmp_items:
|
||||
for plugin_name, attr_val in item.publish_attributes.items():
|
||||
attr_defs = attr_val.attr_defs
|
||||
if not attr_defs:
|
||||
continue
|
||||
|
||||
if plugin_name not in all_defs_by_plugin_name:
|
||||
all_defs_by_plugin_name[plugin_name] = attr_val.attr_defs
|
||||
|
||||
plugin_values = all_plugin_values.setdefault(plugin_name, {})
|
||||
|
||||
for attr_def in attr_defs:
|
||||
if isinstance(attr_def, UIDef):
|
||||
continue
|
||||
|
||||
attr_values = plugin_values.setdefault(attr_def.key, [])
|
||||
|
||||
value = attr_val[attr_def.key]
|
||||
attr_values.append((item, value))
|
||||
|
||||
output = []
|
||||
for plugin in self._create_context.plugins_with_defs:
|
||||
plugin_name = plugin.__name__
|
||||
if plugin_name not in all_defs_by_plugin_name:
|
||||
continue
|
||||
output.append((
|
||||
plugin_name,
|
||||
all_defs_by_plugin_name[plugin_name],
|
||||
all_plugin_values
|
||||
))
|
||||
return output
|
||||
|
||||
def get_thumbnail_paths_for_instances(
|
||||
self, instance_ids: List[str]
|
||||
) -> Dict[str, Union[str, None]]:
|
||||
thumbnail_paths_by_instance_id = (
|
||||
self._create_context.thumbnail_paths_by_instance_id
|
||||
)
|
||||
return {
|
||||
instance_id: thumbnail_paths_by_instance_id.get(instance_id)
|
||||
for instance_id in instance_ids
|
||||
}
|
||||
|
||||
def set_thumbnail_paths_for_instances(
|
||||
self, thumbnail_path_mapping: Dict[str, str]
|
||||
):
|
||||
thumbnail_paths_by_instance_id = (
|
||||
self._create_context.thumbnail_paths_by_instance_id
|
||||
)
|
||||
for instance_id, thumbnail_path in thumbnail_path_mapping.items():
|
||||
thumbnail_paths_by_instance_id[instance_id] = thumbnail_path
|
||||
|
||||
self._emit_event(
|
||||
"instance.thumbnail.changed",
|
||||
{
|
||||
"mapping": thumbnail_path_mapping
|
||||
}
|
||||
)
|
||||
|
||||
def _emit_event(self, topic: str, data: Optional[Dict[str, Any]] = None):
|
||||
self._controller.emit_event(topic, data)
|
||||
|
||||
def _get_current_project_settings(self) -> Dict[str, Any]:
|
||||
"""Current project settings.
|
||||
|
||||
Returns:
|
||||
dict
|
||||
"""
|
||||
|
||||
return self._create_context.get_current_project_settings()
|
||||
|
||||
@property
|
||||
def _creators(self) -> Dict[str, BaseCreator]:
|
||||
"""All creators loaded in create context."""
|
||||
|
||||
return self._create_context.creators
|
||||
|
||||
def _reset_instances(self):
|
||||
"""Reset create instances."""
|
||||
|
||||
self._create_context.reset_context_data()
|
||||
with self._create_context.bulk_instances_collection():
|
||||
try:
|
||||
self._create_context.reset_instances()
|
||||
except CreatorsOperationFailed as exc:
|
||||
self._emit_event(
|
||||
"instances.collection.failed",
|
||||
{
|
||||
"title": "Instance collection failed",
|
||||
"failed_info": exc.failed_info
|
||||
}
|
||||
)
|
||||
|
||||
try:
|
||||
self._create_context.find_convertor_items()
|
||||
except ConvertorsOperationFailed as exc:
|
||||
self._emit_event(
|
||||
"convertors.find.failed",
|
||||
{
|
||||
"title": "Collection of unsupported product failed",
|
||||
"failed_info": exc.failed_info
|
||||
}
|
||||
)
|
||||
|
||||
try:
|
||||
self._create_context.execute_autocreators()
|
||||
|
||||
except CreatorsOperationFailed as exc:
|
||||
self._emit_event(
|
||||
"instances.create.failed",
|
||||
{
|
||||
"title": "AutoCreation failed",
|
||||
"failed_info": exc.failed_info
|
||||
}
|
||||
)
|
||||
|
||||
self._on_create_instance_change()
|
||||
|
||||
def _remove_instances_from_context(self, instance_ids: List[str]):
|
||||
instances_by_id = self._create_context.instances_by_id
|
||||
instances = [
|
||||
instances_by_id[instance_id]
|
||||
for instance_id in instance_ids
|
||||
]
|
||||
try:
|
||||
self._create_context.remove_instances(instances)
|
||||
except CreatorsOperationFailed as exc:
|
||||
self._emit_event(
|
||||
"instances.remove.failed",
|
||||
{
|
||||
"title": "Instance removement failed",
|
||||
"failed_info": exc.failed_info
|
||||
}
|
||||
)
|
||||
|
||||
def _on_create_instance_change(self):
|
||||
self._emit_event("instances.refresh.finished")
|
||||
|
||||
def _collect_creator_items(self) -> Dict[str, CreatorItem]:
|
||||
# TODO add crashed initialization of create plugins to report
|
||||
output = {}
|
||||
allowed_creator_pattern = self._get_allowed_creators_pattern()
|
||||
for identifier, creator in self._create_context.creators.items():
|
||||
try:
|
||||
if self._is_label_allowed(
|
||||
creator.label, allowed_creator_pattern
|
||||
):
|
||||
output[identifier] = CreatorItem.from_creator(creator)
|
||||
continue
|
||||
self.log.debug(f"{creator.label} not allowed for context")
|
||||
except Exception:
|
||||
self.log.error(
|
||||
"Failed to create creator item for '%s'",
|
||||
identifier,
|
||||
exc_info=True
|
||||
)
|
||||
|
||||
return output
|
||||
|
||||
def _get_allowed_creators_pattern(self) -> Union[Pattern, None]:
|
||||
"""Provide regex pattern for configured creator labels in this context
|
||||
|
||||
If no profile matches current context, it shows all creators.
|
||||
Support usage of regular expressions for configured values.
|
||||
Returns:
|
||||
(re.Pattern)[optional]: None or regex compiled patterns
|
||||
into single one ('Render|Image.*')
|
||||
"""
|
||||
|
||||
task_type = self._create_context.get_current_task_type()
|
||||
project_settings = self._get_current_project_settings()
|
||||
|
||||
filter_creator_profiles = (
|
||||
project_settings
|
||||
["core"]
|
||||
["tools"]
|
||||
["creator"]
|
||||
["filter_creator_profiles"]
|
||||
)
|
||||
filtering_criteria = {
|
||||
"task_names": self.get_current_task_name(),
|
||||
"task_types": task_type,
|
||||
"host_names": self._create_context.host_name
|
||||
}
|
||||
profile = filter_profiles(
|
||||
filter_creator_profiles,
|
||||
filtering_criteria,
|
||||
logger=self.log
|
||||
)
|
||||
|
||||
allowed_creator_pattern = None
|
||||
if profile:
|
||||
allowed_creator_labels = {
|
||||
label
|
||||
for label in profile["creator_labels"]
|
||||
if label
|
||||
}
|
||||
self.log.debug(f"Only allowed `{allowed_creator_labels}` creators")
|
||||
allowed_creator_pattern = (
|
||||
re.compile("|".join(allowed_creator_labels)))
|
||||
return allowed_creator_pattern
|
||||
|
||||
def _is_label_allowed(
|
||||
self,
|
||||
label: str,
|
||||
allowed_labels_regex: Union[Pattern, None]
|
||||
) -> bool:
|
||||
"""Implement regex support for allowed labels.
|
||||
|
||||
Args:
|
||||
label (str): Label of creator - shown in Publisher
|
||||
allowed_labels_regex (re.Pattern): compiled regular expression
|
||||
"""
|
||||
if not allowed_labels_regex:
|
||||
return True
|
||||
return bool(allowed_labels_regex.match(label))
|
||||
1266
client/ayon_core/tools/publisher/models/publish.py
Normal file
1266
client/ayon_core/tools/publisher/models/publish.py
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -17,7 +17,7 @@ from .constants import (
|
|||
|
||||
class InstancesModel(QtGui.QStandardItemModel):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(InstancesModel, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self._items_by_id = {}
|
||||
self._plugin_items_by_id = {}
|
||||
|
|
@ -83,7 +83,7 @@ class InstancesModel(QtGui.QStandardItemModel):
|
|||
|
||||
class InstanceProxyModel(QtCore.QSortFilterProxyModel):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(InstanceProxyModel, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self._ignore_removed = True
|
||||
|
||||
|
|
@ -116,7 +116,7 @@ class PluginsModel(QtGui.QStandardItemModel):
|
|||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(PluginsModel, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self._items_by_id = {}
|
||||
self._plugin_items_by_id = {}
|
||||
|
|
@ -185,7 +185,7 @@ class PluginsModel(QtGui.QStandardItemModel):
|
|||
|
||||
class PluginProxyModel(QtCore.QSortFilterProxyModel):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(PluginProxyModel, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self._ignore_skipped = True
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ class PluginLoadReportModel(QtGui.QStandardItemModel):
|
|||
|
||||
class DetailWidget(QtWidgets.QTextEdit):
|
||||
def __init__(self, text, *args, **kwargs):
|
||||
super(DetailWidget, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.setReadOnly(True)
|
||||
self.setHtml(text)
|
||||
|
|
@ -73,7 +73,7 @@ class DetailWidget(QtWidgets.QTextEdit):
|
|||
|
||||
class PluginLoadReportWidget(QtWidgets.QWidget):
|
||||
def __init__(self, parent):
|
||||
super(PluginLoadReportWidget, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
|
||||
view = QtWidgets.QTreeView(self)
|
||||
view.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
|
||||
|
|
@ -101,11 +101,11 @@ class PluginLoadReportWidget(QtWidgets.QWidget):
|
|||
self._create_widget(child_index)
|
||||
|
||||
def showEvent(self, event):
|
||||
super(PluginLoadReportWidget, self).showEvent(event)
|
||||
super().showEvent(event)
|
||||
self._update_widgets_size_hints()
|
||||
|
||||
def resizeEvent(self, event):
|
||||
super(PluginLoadReportWidget, self).resizeEvent(event)
|
||||
super().resizeEvent(event)
|
||||
self._update_widgets_size_hints()
|
||||
|
||||
def _update_widgets_size_hints(self):
|
||||
|
|
@ -146,7 +146,7 @@ class ZoomPlainText(QtWidgets.QPlainTextEdit):
|
|||
max_point_size = 200.0
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ZoomPlainText, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
anim_timer = QtCore.QTimer()
|
||||
anim_timer.setInterval(20)
|
||||
|
|
@ -160,7 +160,7 @@ class ZoomPlainText(QtWidgets.QPlainTextEdit):
|
|||
def wheelEvent(self, event):
|
||||
modifiers = QtWidgets.QApplication.keyboardModifiers()
|
||||
if modifiers != QtCore.Qt.ControlModifier:
|
||||
super(ZoomPlainText, self).wheelEvent(event)
|
||||
super().wheelEvent(event)
|
||||
return
|
||||
|
||||
if hasattr(event, "angleDelta"):
|
||||
|
|
@ -219,7 +219,7 @@ class ZoomPlainText(QtWidgets.QPlainTextEdit):
|
|||
|
||||
class DetailsWidget(QtWidgets.QWidget):
|
||||
def __init__(self, parent):
|
||||
super(DetailsWidget, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
|
||||
output_widget = ZoomPlainText(self)
|
||||
output_widget.setObjectName("PublishLogConsole")
|
||||
|
|
@ -327,7 +327,7 @@ class DetailsPopup(QtWidgets.QDialog):
|
|||
closed = QtCore.Signal()
|
||||
|
||||
def __init__(self, parent, center_widget):
|
||||
super(DetailsPopup, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
self.setWindowTitle("Report Details")
|
||||
layout = QtWidgets.QHBoxLayout(self)
|
||||
|
||||
|
|
@ -338,19 +338,19 @@ class DetailsPopup(QtWidgets.QDialog):
|
|||
def showEvent(self, event):
|
||||
layout = self.layout()
|
||||
layout.insertWidget(0, self._center_widget)
|
||||
super(DetailsPopup, self).showEvent(event)
|
||||
super().showEvent(event)
|
||||
if self._first_show:
|
||||
self._first_show = False
|
||||
self.resize(700, 400)
|
||||
|
||||
def closeEvent(self, event):
|
||||
super(DetailsPopup, self).closeEvent(event)
|
||||
super().closeEvent(event)
|
||||
self.closed.emit()
|
||||
|
||||
|
||||
class PublishReportViewerWidget(QtWidgets.QFrame):
|
||||
def __init__(self, parent=None):
|
||||
super(PublishReportViewerWidget, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
|
||||
instances_model = InstancesModel()
|
||||
instances_proxy = InstanceProxyModel()
|
||||
|
|
|
|||
|
|
@ -302,7 +302,7 @@ class LoadedFilesModel(QtGui.QStandardItemModel):
|
|||
header_labels = ("Reports", "Created")
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(LoadedFilesModel, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
# Column count must be set before setting header data
|
||||
self.setColumnCount(len(self.header_labels))
|
||||
|
|
@ -350,7 +350,7 @@ class LoadedFilesModel(QtGui.QStandardItemModel):
|
|||
if col != 0:
|
||||
index = self.index(index.row(), 0, index.parent())
|
||||
|
||||
return super(LoadedFilesModel, self).data(index, role)
|
||||
return super().data(index, role)
|
||||
|
||||
def setData(self, index, value, role=None):
|
||||
if role is None:
|
||||
|
|
@ -364,13 +364,13 @@ class LoadedFilesModel(QtGui.QStandardItemModel):
|
|||
report_item.save()
|
||||
value = report_item.label
|
||||
|
||||
return super(LoadedFilesModel, self).setData(index, value, role)
|
||||
return super().setData(index, value, role)
|
||||
|
||||
def flags(self, index):
|
||||
# Allow editable flag only for first column
|
||||
if index.column() > 0:
|
||||
return QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled
|
||||
return super(LoadedFilesModel, self).flags(index)
|
||||
return super().flags(index)
|
||||
|
||||
def _create_item(self, report_item):
|
||||
if report_item.id in self._items_by_id:
|
||||
|
|
@ -451,7 +451,7 @@ class LoadedFilesView(QtWidgets.QTreeView):
|
|||
selection_changed = QtCore.Signal()
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(LoadedFilesView, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
self.setEditTriggers(
|
||||
QtWidgets.QAbstractItemView.EditKeyPressed
|
||||
| QtWidgets.QAbstractItemView.SelectedClicked
|
||||
|
|
@ -502,11 +502,11 @@ class LoadedFilesView(QtWidgets.QTreeView):
|
|||
self._update_remove_btn()
|
||||
|
||||
def resizeEvent(self, event):
|
||||
super(LoadedFilesView, self).resizeEvent(event)
|
||||
super().resizeEvent(event)
|
||||
self._update_remove_btn()
|
||||
|
||||
def showEvent(self, event):
|
||||
super(LoadedFilesView, self).showEvent(event)
|
||||
super().showEvent(event)
|
||||
self._model.refresh()
|
||||
header = self.header()
|
||||
header.resizeSections(QtWidgets.QHeaderView.ResizeToContents)
|
||||
|
|
@ -548,7 +548,7 @@ class LoadedFilesWidget(QtWidgets.QWidget):
|
|||
report_changed = QtCore.Signal()
|
||||
|
||||
def __init__(self, parent):
|
||||
super(LoadedFilesWidget, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
|
||||
self.setAcceptDrops(True)
|
||||
|
||||
|
|
@ -598,7 +598,7 @@ class PublishReportViewerWindow(QtWidgets.QWidget):
|
|||
default_height = 600
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super(PublishReportViewerWindow, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
self.setWindowTitle("Publish report viewer")
|
||||
icon = QtGui.QIcon(get_ayon_icon_filepath())
|
||||
self.setWindowIcon(icon)
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ class _VLineWidget(QtWidgets.QWidget):
|
|||
It is expected that parent widget will set width.
|
||||
"""
|
||||
def __init__(self, color, line_size, left, parent):
|
||||
super(_VLineWidget, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
self._color = color
|
||||
self._left = left
|
||||
self._line_size = line_size
|
||||
|
|
@ -69,7 +69,7 @@ class _HBottomLineWidget(QtWidgets.QWidget):
|
|||
It is expected that parent widget will set height and radius.
|
||||
"""
|
||||
def __init__(self, color, line_size, parent):
|
||||
super(_HBottomLineWidget, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
self._color = color
|
||||
self._radius = 0
|
||||
self._line_size = line_size
|
||||
|
|
@ -128,7 +128,7 @@ class _HTopCornerLineWidget(QtWidgets.QWidget):
|
|||
"""
|
||||
|
||||
def __init__(self, color, line_size, left_side, parent):
|
||||
super(_HTopCornerLineWidget, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
self._left_side = left_side
|
||||
self._line_size = line_size
|
||||
self._color = color
|
||||
|
|
@ -192,7 +192,7 @@ class BorderedLabelWidget(QtWidgets.QFrame):
|
|||
└──────────────────────┘
|
||||
"""
|
||||
def __init__(self, label, parent):
|
||||
super(BorderedLabelWidget, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
color_value = get_objected_colors("border")
|
||||
color = None
|
||||
if color_value:
|
||||
|
|
@ -269,7 +269,7 @@ class BorderedLabelWidget(QtWidgets.QFrame):
|
|||
self._recalculate_sizes()
|
||||
|
||||
def showEvent(self, event):
|
||||
super(BorderedLabelWidget, self).showEvent(event)
|
||||
super().showEvent(event)
|
||||
self._recalculate_sizes()
|
||||
|
||||
def _recalculate_sizes(self):
|
||||
|
|
|
|||
|
|
@ -29,18 +29,21 @@ from ayon_core.tools.utils import NiceCheckbox
|
|||
|
||||
from ayon_core.tools.utils import BaseClickableFrame
|
||||
from ayon_core.tools.utils.lib import html_escape
|
||||
|
||||
from ayon_core.tools.publisher.abstract import AbstractPublisherFrontend
|
||||
from ayon_core.tools.publisher.constants import (
|
||||
CONTEXT_ID,
|
||||
CONTEXT_LABEL,
|
||||
CONTEXT_GROUP,
|
||||
CONVERTOR_ITEM_GROUP,
|
||||
)
|
||||
|
||||
from .widgets import (
|
||||
AbstractInstanceView,
|
||||
ContextWarningLabel,
|
||||
IconValuePixmapLabel,
|
||||
PublishPixmapLabel
|
||||
)
|
||||
from ..constants import (
|
||||
CONTEXT_ID,
|
||||
CONTEXT_LABEL,
|
||||
CONTEXT_GROUP,
|
||||
CONVERTOR_ITEM_GROUP,
|
||||
)
|
||||
|
||||
|
||||
class SelectionTypes:
|
||||
|
|
@ -55,7 +58,7 @@ class BaseGroupWidget(QtWidgets.QWidget):
|
|||
double_clicked = QtCore.Signal()
|
||||
|
||||
def __init__(self, group_name, parent):
|
||||
super(BaseGroupWidget, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
|
||||
label_widget = QtWidgets.QLabel(group_name, self)
|
||||
|
||||
|
|
@ -207,7 +210,7 @@ class InstanceGroupWidget(BaseGroupWidget):
|
|||
active_changed = QtCore.Signal(str, str, bool)
|
||||
|
||||
def __init__(self, group_icons, *args, **kwargs):
|
||||
super(InstanceGroupWidget, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self._group_icons = group_icons
|
||||
|
||||
|
|
@ -277,14 +280,14 @@ class CardWidget(BaseClickableFrame):
|
|||
double_clicked = QtCore.Signal()
|
||||
|
||||
def __init__(self, parent):
|
||||
super(CardWidget, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
self.setObjectName("CardViewWidget")
|
||||
|
||||
self._selected = False
|
||||
self._id = None
|
||||
|
||||
def mouseDoubleClickEvent(self, event):
|
||||
super(CardWidget, self).mouseDoubleClickEvent(event)
|
||||
super().mouseDoubleClickEvent(event)
|
||||
if self._is_valid_double_click(event):
|
||||
self.double_clicked.emit()
|
||||
|
||||
|
|
@ -332,7 +335,7 @@ class ContextCardWidget(CardWidget):
|
|||
"""
|
||||
|
||||
def __init__(self, parent):
|
||||
super(ContextCardWidget, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
|
||||
self._id = CONTEXT_ID
|
||||
self._group_identifier = CONTEXT_GROUP
|
||||
|
|
@ -362,7 +365,7 @@ class ConvertorItemCardWidget(CardWidget):
|
|||
"""
|
||||
|
||||
def __init__(self, item, parent):
|
||||
super(ConvertorItemCardWidget, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
|
||||
self._id = item.id
|
||||
self.identifier = item.identifier
|
||||
|
|
@ -395,7 +398,7 @@ class InstanceCardWidget(CardWidget):
|
|||
active_changed = QtCore.Signal(str, bool)
|
||||
|
||||
def __init__(self, instance, group_icon, parent):
|
||||
super(InstanceCardWidget, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
|
||||
self._id = instance.id
|
||||
self._group_identifier = instance.group_label
|
||||
|
|
@ -558,9 +561,9 @@ class InstanceCardView(AbstractInstanceView):
|
|||
double_clicked = QtCore.Signal()
|
||||
|
||||
def __init__(self, controller, parent):
|
||||
super(InstanceCardView, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
|
||||
self._controller = controller
|
||||
self._controller: AbstractPublisherFrontend = controller
|
||||
|
||||
scroll_area = QtWidgets.QScrollArea(self)
|
||||
scroll_area.setWidgetResizable(True)
|
||||
|
|
@ -610,7 +613,7 @@ class InstanceCardView(AbstractInstanceView):
|
|||
+ scroll_bar.sizeHint().width()
|
||||
)
|
||||
|
||||
result = super(InstanceCardView, self).sizeHint()
|
||||
result = super().sizeHint()
|
||||
result.setWidth(width)
|
||||
return result
|
||||
|
||||
|
|
@ -651,7 +654,7 @@ class InstanceCardView(AbstractInstanceView):
|
|||
self._toggle_instances(1)
|
||||
return True
|
||||
|
||||
return super(InstanceCardView, self).keyPressEvent(event)
|
||||
return super().keyPressEvent(event)
|
||||
|
||||
def _get_selected_widgets(self):
|
||||
output = []
|
||||
|
|
@ -694,7 +697,7 @@ class InstanceCardView(AbstractInstanceView):
|
|||
# Prepare instances by group and identifiers by group
|
||||
instances_by_group = collections.defaultdict(list)
|
||||
identifiers_by_group = collections.defaultdict(set)
|
||||
for instance in self._controller.instances.values():
|
||||
for instance in self._controller.get_instances():
|
||||
group_name = instance.group_label
|
||||
instances_by_group[group_name].append(instance)
|
||||
identifiers_by_group[group_name].add(
|
||||
|
|
@ -787,7 +790,7 @@ class InstanceCardView(AbstractInstanceView):
|
|||
self._content_layout.insertWidget(0, widget)
|
||||
|
||||
def _update_convertor_items_group(self):
|
||||
convertor_items = self._controller.convertor_items
|
||||
convertor_items = self._controller.get_convertor_items()
|
||||
if not convertor_items and self._convertor_items_group is None:
|
||||
return
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ from ayon_core.tools.utils import PlaceholderLineEdit, GoToCurrentButton
|
|||
|
||||
from ayon_core.tools.common_models import HierarchyExpectedSelection
|
||||
from ayon_core.tools.utils import FoldersWidget, TasksWidget
|
||||
from ayon_core.tools.publisher.abstract import AbstractPublisherFrontend
|
||||
|
||||
|
||||
class CreateSelectionModel(object):
|
||||
|
|
@ -18,8 +19,8 @@ class CreateSelectionModel(object):
|
|||
|
||||
event_source = "publisher.create.selection.model"
|
||||
|
||||
def __init__(self, controller):
|
||||
self._controller = controller
|
||||
def __init__(self, controller: "CreateHierarchyController"):
|
||||
self._controller: CreateHierarchyController = controller
|
||||
|
||||
self._project_name = None
|
||||
self._folder_id = None
|
||||
|
|
@ -94,9 +95,9 @@ class CreateHierarchyController:
|
|||
controller (PublisherController): Publisher controller.
|
||||
|
||||
"""
|
||||
def __init__(self, controller):
|
||||
def __init__(self, controller: AbstractPublisherFrontend):
|
||||
self._event_system = QueuedEventSystem()
|
||||
self._controller = controller
|
||||
self._controller: AbstractPublisherFrontend = controller
|
||||
self._selection_model = CreateSelectionModel(self)
|
||||
self._expected_selection = HierarchyExpectedSelection(
|
||||
self, handle_project=False
|
||||
|
|
@ -118,7 +119,7 @@ class CreateHierarchyController:
|
|||
self.event_system.add_callback(topic, callback)
|
||||
|
||||
def get_project_name(self):
|
||||
return self._controller.project_name
|
||||
return self._controller.get_current_project_name()
|
||||
|
||||
def get_folder_items(self, project_name, sender=None):
|
||||
return self._controller.get_folder_items(project_name, sender)
|
||||
|
|
@ -168,10 +169,10 @@ class CreateContextWidget(QtWidgets.QWidget):
|
|||
folder_changed = QtCore.Signal()
|
||||
task_changed = QtCore.Signal()
|
||||
|
||||
def __init__(self, controller, parent):
|
||||
super(CreateContextWidget, self).__init__(parent)
|
||||
def __init__(self, controller: AbstractPublisherFrontend, parent):
|
||||
super().__init__(parent)
|
||||
|
||||
self._controller = controller
|
||||
self._controller: AbstractPublisherFrontend = controller
|
||||
self._enabled = True
|
||||
self._last_project_name = None
|
||||
self._last_folder_id = None
|
||||
|
|
@ -234,12 +235,12 @@ class CreateContextWidget(QtWidgets.QWidget):
|
|||
|
||||
def update_current_context_btn(self):
|
||||
# Hide set current folder if there is no one
|
||||
folder_path = self._controller.current_folder_path
|
||||
folder_path = self._controller.get_current_folder_path()
|
||||
self._current_context_btn.setVisible(bool(folder_path))
|
||||
|
||||
def set_selected_context(self, folder_id, task_name):
|
||||
self._hierarchy_controller.set_expected_selection(
|
||||
self._controller.project_name,
|
||||
self._controller.get_current_project_name(),
|
||||
folder_id,
|
||||
task_name
|
||||
)
|
||||
|
|
@ -270,13 +271,13 @@ class CreateContextWidget(QtWidgets.QWidget):
|
|||
)
|
||||
|
||||
def refresh(self):
|
||||
self._last_project_name = self._controller.project_name
|
||||
self._last_project_name = self._controller.get_current_project_name()
|
||||
folder_id = self._last_folder_id
|
||||
task_name = self._last_selected_task_name
|
||||
if folder_id is None:
|
||||
folder_path = self._controller.current_folder_path
|
||||
folder_path = self._controller.get_current_folder_path()
|
||||
folder_id = self._controller.get_folder_id_from_path(folder_path)
|
||||
task_name = self._controller.current_task_name
|
||||
task_name = self._controller.get_current_task_name()
|
||||
self._hierarchy_controller.set_selected_project(
|
||||
self._last_project_name
|
||||
)
|
||||
|
|
@ -295,8 +296,8 @@ class CreateContextWidget(QtWidgets.QWidget):
|
|||
self.task_changed.emit()
|
||||
|
||||
def _on_current_context_click(self):
|
||||
folder_path = self._controller.current_folder_path
|
||||
task_name = self._controller.current_task_name
|
||||
folder_path = self._controller.get_current_folder_path()
|
||||
task_name = self._controller.get_current_task_name()
|
||||
folder_id = self._controller.get_folder_id_from_path(folder_path)
|
||||
self._hierarchy_controller.set_expected_selection(
|
||||
self._last_project_name, folder_id, task_name
|
||||
|
|
|
|||
|
|
@ -9,14 +9,8 @@ from ayon_core.pipeline.create import (
|
|||
TaskNotSetError,
|
||||
)
|
||||
|
||||
from .thumbnail_widget import ThumbnailWidget
|
||||
from .widgets import (
|
||||
IconValuePixmapLabel,
|
||||
CreateBtn,
|
||||
)
|
||||
from .create_context_widgets import CreateContextWidget
|
||||
from .precreate_widget import PreCreateWidget
|
||||
from ..constants import (
|
||||
from ayon_core.tools.publisher.abstract import AbstractPublisherFrontend
|
||||
from ayon_core.tools.publisher.constants import (
|
||||
VARIANT_TOOLTIP,
|
||||
PRODUCT_TYPE_ROLE,
|
||||
CREATOR_IDENTIFIER_ROLE,
|
||||
|
|
@ -26,6 +20,14 @@ from ..constants import (
|
|||
INPUTS_LAYOUT_VSPACING,
|
||||
)
|
||||
|
||||
from .thumbnail_widget import ThumbnailWidget
|
||||
from .widgets import (
|
||||
IconValuePixmapLabel,
|
||||
CreateBtn,
|
||||
)
|
||||
from .create_context_widgets import CreateContextWidget
|
||||
from .precreate_widget import PreCreateWidget
|
||||
|
||||
SEPARATORS = ("---separator---", "---")
|
||||
|
||||
|
||||
|
|
@ -33,14 +35,14 @@ class ResizeControlWidget(QtWidgets.QWidget):
|
|||
resized = QtCore.Signal()
|
||||
|
||||
def resizeEvent(self, event):
|
||||
super(ResizeControlWidget, self).resizeEvent(event)
|
||||
super().resizeEvent(event)
|
||||
self.resized.emit()
|
||||
|
||||
|
||||
# TODO add creator identifier/label to details
|
||||
class CreatorShortDescWidget(QtWidgets.QWidget):
|
||||
def __init__(self, parent=None):
|
||||
super(CreatorShortDescWidget, self).__init__(parent=parent)
|
||||
super().__init__(parent=parent)
|
||||
|
||||
# --- Short description widget ---
|
||||
icon_widget = IconValuePixmapLabel(None, self)
|
||||
|
|
@ -98,15 +100,15 @@ class CreatorsProxyModel(QtCore.QSortFilterProxyModel):
|
|||
l_show_order = left.data(CREATOR_SORT_ROLE)
|
||||
r_show_order = right.data(CREATOR_SORT_ROLE)
|
||||
if l_show_order == r_show_order:
|
||||
return super(CreatorsProxyModel, self).lessThan(left, right)
|
||||
return super().lessThan(left, right)
|
||||
return l_show_order < r_show_order
|
||||
|
||||
|
||||
class CreateWidget(QtWidgets.QWidget):
|
||||
def __init__(self, controller, parent=None):
|
||||
super(CreateWidget, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
|
||||
self._controller = controller
|
||||
self._controller: AbstractPublisherFrontend = controller
|
||||
|
||||
self._folder_path = None
|
||||
self._product_names = None
|
||||
|
|
@ -274,11 +276,11 @@ class CreateWidget(QtWidgets.QWidget):
|
|||
thumbnail_widget.thumbnail_created.connect(self._on_thumbnail_create)
|
||||
thumbnail_widget.thumbnail_cleared.connect(self._on_thumbnail_clear)
|
||||
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"main.window.closed", self._on_main_window_close
|
||||
)
|
||||
controller.event_system.add_callback(
|
||||
"plugins.refresh.finished", self._on_plugins_refresh
|
||||
controller.register_event_callback(
|
||||
"controller.reset.finished", self._on_controler_reset
|
||||
)
|
||||
|
||||
self._main_splitter_widget = main_splitter_widget
|
||||
|
|
@ -313,13 +315,11 @@ class CreateWidget(QtWidgets.QWidget):
|
|||
self._last_current_context_task = None
|
||||
self._use_current_context = True
|
||||
|
||||
@property
|
||||
def current_folder_path(self):
|
||||
return self._controller.current_folder_path
|
||||
def get_current_folder_path(self):
|
||||
return self._controller.get_current_folder_path()
|
||||
|
||||
@property
|
||||
def current_task_name(self):
|
||||
return self._controller.current_task_name
|
||||
def get_current_task_name(self):
|
||||
return self._controller.get_current_task_name()
|
||||
|
||||
def _context_change_is_enabled(self):
|
||||
return self._context_widget.is_enabled()
|
||||
|
|
@ -330,7 +330,7 @@ class CreateWidget(QtWidgets.QWidget):
|
|||
folder_path = self._context_widget.get_selected_folder_path()
|
||||
|
||||
if folder_path is None:
|
||||
folder_path = self.current_folder_path
|
||||
folder_path = self.get_current_folder_path()
|
||||
return folder_path or None
|
||||
|
||||
def _get_folder_id(self):
|
||||
|
|
@ -348,7 +348,7 @@ class CreateWidget(QtWidgets.QWidget):
|
|||
task_name = self._context_widget.get_selected_task_name()
|
||||
|
||||
if not task_name:
|
||||
task_name = self.current_task_name
|
||||
task_name = self.get_current_task_name()
|
||||
return task_name
|
||||
|
||||
def _set_context_enabled(self, enabled):
|
||||
|
|
@ -364,8 +364,8 @@ class CreateWidget(QtWidgets.QWidget):
|
|||
self._use_current_context = True
|
||||
|
||||
def refresh(self):
|
||||
current_folder_path = self._controller.current_folder_path
|
||||
current_task_name = self._controller.current_task_name
|
||||
current_folder_path = self._controller.get_current_folder_path()
|
||||
current_task_name = self._controller.get_current_task_name()
|
||||
|
||||
# Get context before refresh to keep selection of folder and
|
||||
# task widgets
|
||||
|
|
@ -481,7 +481,7 @@ class CreateWidget(QtWidgets.QWidget):
|
|||
|
||||
# Add new create plugins
|
||||
new_creators = set()
|
||||
creator_items_by_identifier = self._controller.creator_items
|
||||
creator_items_by_identifier = self._controller.get_creator_items()
|
||||
for identifier, creator_item in creator_items_by_identifier.items():
|
||||
if creator_item.creator_type != "artist":
|
||||
continue
|
||||
|
|
@ -531,7 +531,7 @@ class CreateWidget(QtWidgets.QWidget):
|
|||
|
||||
self._set_creator(create_item)
|
||||
|
||||
def _on_plugins_refresh(self):
|
||||
def _on_controler_reset(self):
|
||||
# Trigger refresh only if is visible
|
||||
self.refresh()
|
||||
|
||||
|
|
@ -562,7 +562,7 @@ class CreateWidget(QtWidgets.QWidget):
|
|||
description = ""
|
||||
if creator_item is not None:
|
||||
description = creator_item.detailed_description or description
|
||||
self._controller.event_system.emit(
|
||||
self._controller.emit_event(
|
||||
"show.detailed.help",
|
||||
{
|
||||
"message": description
|
||||
|
|
@ -571,7 +571,7 @@ class CreateWidget(QtWidgets.QWidget):
|
|||
)
|
||||
|
||||
def _set_creator_by_identifier(self, identifier):
|
||||
creator_item = self._controller.creator_items.get(identifier)
|
||||
creator_item = self._controller.get_creator_item_by_id(identifier)
|
||||
self._set_creator(creator_item)
|
||||
|
||||
def _set_creator(self, creator_item):
|
||||
|
|
@ -755,7 +755,7 @@ class CreateWidget(QtWidgets.QWidget):
|
|||
self._creators_splitter.setSizes([part, rem_width])
|
||||
|
||||
def showEvent(self, event):
|
||||
super(CreateWidget, self).showEvent(event)
|
||||
super().showEvent(event)
|
||||
if self._first_show:
|
||||
self._first_show = False
|
||||
self._on_first_show()
|
||||
|
|
|
|||
|
|
@ -2,12 +2,13 @@ from qtpy import QtWidgets
|
|||
|
||||
from ayon_core.lib.events import QueuedEventSystem
|
||||
from ayon_core.tools.utils import PlaceholderLineEdit, FoldersWidget
|
||||
from ayon_core.tools.publisher.abstract import AbstractPublisherFrontend
|
||||
|
||||
|
||||
class FoldersDialogController:
|
||||
def __init__(self, controller):
|
||||
def __init__(self, controller: AbstractPublisherFrontend):
|
||||
self._event_system = QueuedEventSystem()
|
||||
self._controller = controller
|
||||
self._controller: AbstractPublisherFrontend = controller
|
||||
|
||||
@property
|
||||
def event_system(self):
|
||||
|
|
@ -39,7 +40,7 @@ class FoldersDialog(QtWidgets.QDialog):
|
|||
"""Dialog to select folder for a context of instance."""
|
||||
|
||||
def __init__(self, controller, parent):
|
||||
super(FoldersDialog, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
self.setWindowTitle("Select folder")
|
||||
|
||||
filter_input = PlaceholderLineEdit(self)
|
||||
|
|
@ -62,7 +63,7 @@ class FoldersDialog(QtWidgets.QDialog):
|
|||
layout.addWidget(folders_widget, 1)
|
||||
layout.addLayout(btns_layout, 0)
|
||||
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"controller.reset.finished", self._on_controller_reset
|
||||
)
|
||||
|
||||
|
|
@ -104,7 +105,7 @@ class FoldersDialog(QtWidgets.QDialog):
|
|||
|
||||
def showEvent(self, event):
|
||||
"""Refresh folders widget on show."""
|
||||
super(FoldersDialog, self).showEvent(event)
|
||||
super().showEvent(event)
|
||||
if self._first_show:
|
||||
self._first_show = False
|
||||
self._on_first_show()
|
||||
|
|
@ -119,7 +120,9 @@ class FoldersDialog(QtWidgets.QDialog):
|
|||
if self._soft_reset_enabled:
|
||||
self._soft_reset_enabled = False
|
||||
|
||||
self._folders_widget.set_project_name(self._controller.project_name)
|
||||
self._folders_widget.set_project_name(
|
||||
self._controller.get_current_project_name()
|
||||
)
|
||||
|
||||
def _on_filter_change(self, text):
|
||||
"""Trigger change of filter of folders."""
|
||||
|
|
|
|||
|
|
@ -5,12 +5,14 @@ except Exception:
|
|||
|
||||
from qtpy import QtWidgets, QtCore
|
||||
|
||||
from ayon_core.tools.publisher.abstract import AbstractPublisherFrontend
|
||||
|
||||
|
||||
class HelpButton(QtWidgets.QPushButton):
|
||||
"""Button used to trigger help dialog."""
|
||||
|
||||
def __init__(self, parent):
|
||||
super(HelpButton, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
self.setObjectName("CreateDialogHelpButton")
|
||||
self.setText("?")
|
||||
|
||||
|
|
@ -19,7 +21,7 @@ class HelpWidget(QtWidgets.QWidget):
|
|||
"""Widget showing help for single functionality."""
|
||||
|
||||
def __init__(self, parent):
|
||||
super(HelpWidget, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
|
||||
# TODO add hints what to help with?
|
||||
detail_description_input = QtWidgets.QTextEdit(self)
|
||||
|
|
@ -54,8 +56,10 @@ class HelpDialog(QtWidgets.QDialog):
|
|||
default_width = 530
|
||||
default_height = 340
|
||||
|
||||
def __init__(self, controller, parent):
|
||||
super(HelpDialog, self).__init__(parent)
|
||||
def __init__(
|
||||
self, controller: AbstractPublisherFrontend, parent: QtWidgets.QWidget
|
||||
):
|
||||
super().__init__(parent)
|
||||
|
||||
self.setWindowTitle("Help dialog")
|
||||
|
||||
|
|
@ -64,11 +68,11 @@ class HelpDialog(QtWidgets.QDialog):
|
|||
main_layout = QtWidgets.QHBoxLayout(self)
|
||||
main_layout.addWidget(help_content, 1)
|
||||
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"show.detailed.help", self._on_help_request
|
||||
)
|
||||
|
||||
self._controller = controller
|
||||
self._controller: AbstractPublisherFrontend = controller
|
||||
|
||||
self._help_content = help_content
|
||||
|
||||
|
|
@ -80,5 +84,5 @@ class HelpDialog(QtWidgets.QDialog):
|
|||
self._help_content.set_detailed_text(text)
|
||||
|
||||
def showEvent(self, event):
|
||||
super(HelpDialog, self).showEvent(event)
|
||||
super().showEvent(event)
|
||||
self.resize(self.default_width, self.default_height)
|
||||
|
|
|
|||
|
|
@ -29,8 +29,9 @@ from qtpy import QtWidgets, QtCore, QtGui
|
|||
from ayon_core.style import get_objected_colors
|
||||
from ayon_core.tools.utils import NiceCheckbox
|
||||
from ayon_core.tools.utils.lib import html_escape, checkstate_int_to_enum
|
||||
from .widgets import AbstractInstanceView
|
||||
from ..constants import (
|
||||
|
||||
from ayon_core.tools.publisher.abstract import AbstractPublisherFrontend
|
||||
from ayon_core.tools.publisher.constants import (
|
||||
INSTANCE_ID_ROLE,
|
||||
SORT_VALUE_ROLE,
|
||||
IS_GROUP_ROLE,
|
||||
|
|
@ -41,6 +42,8 @@ from ..constants import (
|
|||
CONVERTOR_ITEM_GROUP,
|
||||
)
|
||||
|
||||
from .widgets import AbstractInstanceView
|
||||
|
||||
|
||||
class ListItemDelegate(QtWidgets.QStyledItemDelegate):
|
||||
"""Generic delegate for instance group.
|
||||
|
|
@ -55,7 +58,7 @@ class ListItemDelegate(QtWidgets.QStyledItemDelegate):
|
|||
radius_ratio = 0.3
|
||||
|
||||
def __init__(self, parent):
|
||||
super(ListItemDelegate, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
|
||||
group_color_info = get_objected_colors("publisher", "list-view-group")
|
||||
|
||||
|
|
@ -68,7 +71,7 @@ class ListItemDelegate(QtWidgets.QStyledItemDelegate):
|
|||
if index.data(IS_GROUP_ROLE):
|
||||
self.group_item_paint(painter, option, index)
|
||||
else:
|
||||
super(ListItemDelegate, self).paint(painter, option, index)
|
||||
super().paint(painter, option, index)
|
||||
|
||||
def group_item_paint(self, painter, option, index):
|
||||
"""Paint group item."""
|
||||
|
|
@ -113,7 +116,7 @@ class InstanceListItemWidget(QtWidgets.QWidget):
|
|||
double_clicked = QtCore.Signal()
|
||||
|
||||
def __init__(self, instance, parent):
|
||||
super(InstanceListItemWidget, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
|
||||
self.instance = instance
|
||||
|
||||
|
|
@ -152,7 +155,7 @@ class InstanceListItemWidget(QtWidgets.QWidget):
|
|||
|
||||
def mouseDoubleClickEvent(self, event):
|
||||
widget = self.childAt(event.pos())
|
||||
super(InstanceListItemWidget, self).mouseDoubleClickEvent(event)
|
||||
super().mouseDoubleClickEvent(event)
|
||||
if widget is not self._active_checkbox:
|
||||
self.double_clicked.emit()
|
||||
|
||||
|
|
@ -219,7 +222,7 @@ class ListContextWidget(QtWidgets.QFrame):
|
|||
double_clicked = QtCore.Signal()
|
||||
|
||||
def __init__(self, parent):
|
||||
super(ListContextWidget, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
|
||||
label_widget = QtWidgets.QLabel(CONTEXT_LABEL, self)
|
||||
|
||||
|
|
@ -235,7 +238,7 @@ class ListContextWidget(QtWidgets.QFrame):
|
|||
self.label_widget = label_widget
|
||||
|
||||
def mouseDoubleClickEvent(self, event):
|
||||
super(ListContextWidget, self).mouseDoubleClickEvent(event)
|
||||
super().mouseDoubleClickEvent(event)
|
||||
self.double_clicked.emit()
|
||||
|
||||
|
||||
|
|
@ -249,7 +252,7 @@ class InstanceListGroupWidget(QtWidgets.QFrame):
|
|||
toggle_requested = QtCore.Signal(str, int)
|
||||
|
||||
def __init__(self, group_name, parent):
|
||||
super(InstanceListGroupWidget, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
self.setObjectName("InstanceListGroupWidget")
|
||||
|
||||
self.group_name = group_name
|
||||
|
|
@ -333,7 +336,7 @@ class InstanceTreeView(QtWidgets.QTreeView):
|
|||
double_clicked = QtCore.Signal()
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(InstanceTreeView, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.setObjectName("InstanceListView")
|
||||
self.setHeaderHidden(True)
|
||||
|
|
@ -384,7 +387,7 @@ class InstanceTreeView(QtWidgets.QTreeView):
|
|||
self.toggle_requested.emit(1)
|
||||
return True
|
||||
|
||||
return super(InstanceTreeView, self).event(event)
|
||||
return super().event(event)
|
||||
|
||||
def _mouse_press(self, event):
|
||||
"""Store index of pressed group.
|
||||
|
|
@ -404,11 +407,11 @@ class InstanceTreeView(QtWidgets.QTreeView):
|
|||
|
||||
def mousePressEvent(self, event):
|
||||
self._mouse_press(event)
|
||||
super(InstanceTreeView, self).mousePressEvent(event)
|
||||
super().mousePressEvent(event)
|
||||
|
||||
def mouseDoubleClickEvent(self, event):
|
||||
self._mouse_press(event)
|
||||
super(InstanceTreeView, self).mouseDoubleClickEvent(event)
|
||||
super().mouseDoubleClickEvent(event)
|
||||
|
||||
def _mouse_release(self, event, pressed_index):
|
||||
if event.button() != QtCore.Qt.LeftButton:
|
||||
|
|
@ -431,7 +434,7 @@ class InstanceTreeView(QtWidgets.QTreeView):
|
|||
self._pressed_group_index = None
|
||||
result = self._mouse_release(event, pressed_index)
|
||||
if not result:
|
||||
super(InstanceTreeView, self).mouseReleaseEvent(event)
|
||||
super().mouseReleaseEvent(event)
|
||||
|
||||
|
||||
class InstanceListView(AbstractInstanceView):
|
||||
|
|
@ -442,10 +445,12 @@ class InstanceListView(AbstractInstanceView):
|
|||
|
||||
double_clicked = QtCore.Signal()
|
||||
|
||||
def __init__(self, controller, parent):
|
||||
super(InstanceListView, self).__init__(parent)
|
||||
def __init__(
|
||||
self, controller: AbstractPublisherFrontend, parent: QtWidgets.QWidget
|
||||
):
|
||||
super().__init__(parent)
|
||||
|
||||
self._controller = controller
|
||||
self._controller: AbstractPublisherFrontend = controller
|
||||
|
||||
instance_view = InstanceTreeView(self)
|
||||
instance_delegate = ListItemDelegate(instance_view)
|
||||
|
|
@ -581,7 +586,7 @@ class InstanceListView(AbstractInstanceView):
|
|||
# Prepare instances by their groups
|
||||
instances_by_group_name = collections.defaultdict(list)
|
||||
group_names = set()
|
||||
for instance in self._controller.instances.values():
|
||||
for instance in self._controller.get_instances():
|
||||
group_label = instance.group_label
|
||||
group_names.add(group_label)
|
||||
instances_by_group_name[group_label].append(instance)
|
||||
|
|
@ -745,7 +750,7 @@ class InstanceListView(AbstractInstanceView):
|
|||
|
||||
def _update_convertor_items_group(self):
|
||||
created_new_items = False
|
||||
convertor_items_by_id = self._controller.convertor_items
|
||||
convertor_items_by_id = self._controller.get_convertor_items()
|
||||
group_item = self._convertor_group_item
|
||||
if not convertor_items_by_id and group_item is None:
|
||||
return created_new_items
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
from qtpy import QtWidgets, QtCore
|
||||
|
||||
from .border_label_widget import BorderedLabelWidget
|
||||
from ayon_core.tools.publisher.abstract import AbstractPublisherFrontend
|
||||
|
||||
from .border_label_widget import BorderedLabelWidget
|
||||
from .card_view_widgets import InstanceCardView
|
||||
from .list_view_widgets import InstanceListView
|
||||
from .widgets import (
|
||||
|
|
@ -23,11 +24,13 @@ class OverviewWidget(QtWidgets.QFrame):
|
|||
anim_end_value = 200
|
||||
anim_duration = 200
|
||||
|
||||
def __init__(self, controller, parent):
|
||||
super(OverviewWidget, self).__init__(parent)
|
||||
def __init__(
|
||||
self, controller: AbstractPublisherFrontend, parent: QtWidgets.QWidget
|
||||
):
|
||||
super().__init__(parent)
|
||||
|
||||
self._refreshing_instances = False
|
||||
self._controller = controller
|
||||
self._controller: AbstractPublisherFrontend = controller
|
||||
|
||||
product_content_widget = QtWidgets.QWidget(self)
|
||||
|
||||
|
|
@ -139,16 +142,16 @@ class OverviewWidget(QtWidgets.QFrame):
|
|||
)
|
||||
|
||||
# --- Controller callbacks ---
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"publish.process.started", self._on_publish_start
|
||||
)
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"controller.reset.started", self._on_controller_reset_start
|
||||
)
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"publish.reset.finished", self._on_publish_reset
|
||||
)
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"instances.refresh.finished", self._on_instances_refresh
|
||||
)
|
||||
|
||||
|
|
@ -291,7 +294,7 @@ class OverviewWidget(QtWidgets.QFrame):
|
|||
# Disable delete button if nothing is selected
|
||||
self._delete_btn.setEnabled(len(instance_ids) > 0)
|
||||
|
||||
instances_by_id = self._controller.instances
|
||||
instances_by_id = self._controller.get_instances_by_id(instance_ids)
|
||||
instances = [
|
||||
instances_by_id[instance_id]
|
||||
for instance_id in instance_ids
|
||||
|
|
@ -454,7 +457,9 @@ class OverviewWidget(QtWidgets.QFrame):
|
|||
|
||||
self._create_btn.setEnabled(True)
|
||||
self._product_attributes_wrap.setEnabled(True)
|
||||
self._product_content_widget.setEnabled(self._controller.host_is_valid)
|
||||
self._product_content_widget.setEnabled(
|
||||
self._controller.is_host_valid()
|
||||
)
|
||||
|
||||
def _on_instances_refresh(self):
|
||||
"""Controller refreshed instances."""
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ from ..constants import INPUTS_LAYOUT_HSPACING, INPUTS_LAYOUT_VSPACING
|
|||
|
||||
class PreCreateWidget(QtWidgets.QWidget):
|
||||
def __init__(self, parent):
|
||||
super(PreCreateWidget, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
|
||||
# Precreate attribute defininitions of Creator
|
||||
scroll_area = QtWidgets.QScrollArea(self)
|
||||
|
|
@ -79,7 +79,7 @@ class PreCreateWidget(QtWidgets.QWidget):
|
|||
|
||||
class AttributesWidget(QtWidgets.QWidget):
|
||||
def __init__(self, parent=None):
|
||||
super(AttributesWidget, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
|
||||
layout = QtWidgets.QGridLayout(self)
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
from qtpy import QtWidgets, QtCore
|
||||
|
||||
from ayon_core.tools.publisher.abstract import AbstractPublisherFrontend
|
||||
|
||||
from .widgets import (
|
||||
StopBtn,
|
||||
ResetBtn,
|
||||
|
|
@ -31,8 +33,13 @@ class PublishFrame(QtWidgets.QWidget):
|
|||
|
||||
details_page_requested = QtCore.Signal()
|
||||
|
||||
def __init__(self, controller, borders, parent):
|
||||
super(PublishFrame, self).__init__(parent)
|
||||
def __init__(
|
||||
self,
|
||||
controller: AbstractPublisherFrontend,
|
||||
borders: int,
|
||||
parent: QtWidgets.QWidget
|
||||
):
|
||||
super().__init__(parent)
|
||||
|
||||
# Bottom part of widget where process and callback buttons are showed
|
||||
# - QFrame used to be able set background using stylesheets easily
|
||||
|
|
@ -157,29 +164,29 @@ class PublishFrame(QtWidgets.QWidget):
|
|||
shrunk_anim.valueChanged.connect(self._on_shrunk_anim)
|
||||
shrunk_anim.finished.connect(self._on_shrunk_anim_finish)
|
||||
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"publish.reset.finished", self._on_publish_reset
|
||||
)
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"publish.process.started", self._on_publish_start
|
||||
)
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"publish.has_validated.changed", self._on_publish_validated_change
|
||||
)
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"publish.process.stopped", self._on_publish_stop
|
||||
)
|
||||
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"publish.process.instance.changed", self._on_instance_change
|
||||
)
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"publish.process.plugin.changed", self._on_plugin_change
|
||||
)
|
||||
|
||||
self._shrunk_anim = shrunk_anim
|
||||
|
||||
self._controller = controller
|
||||
self._controller: AbstractPublisherFrontend = controller
|
||||
|
||||
self._content_frame = content_frame
|
||||
self._content_layout = content_layout
|
||||
|
|
@ -208,7 +215,7 @@ class PublishFrame(QtWidgets.QWidget):
|
|||
self._last_plugin_label = None
|
||||
|
||||
def mouseReleaseEvent(self, event):
|
||||
super(PublishFrame, self).mouseReleaseEvent(event)
|
||||
super().mouseReleaseEvent(event)
|
||||
self._change_shrunk_state()
|
||||
|
||||
def _change_shrunk_state(self):
|
||||
|
|
@ -314,8 +321,12 @@ class PublishFrame(QtWidgets.QWidget):
|
|||
self._validate_btn.setEnabled(True)
|
||||
self._publish_btn.setEnabled(True)
|
||||
|
||||
self._progress_bar.setValue(self._controller.publish_progress)
|
||||
self._progress_bar.setMaximum(self._controller.publish_max_progress)
|
||||
self._progress_bar.setValue(
|
||||
self._controller.get_publish_progress()
|
||||
)
|
||||
self._progress_bar.setMaximum(
|
||||
self._controller.get_publish_max_progress()
|
||||
)
|
||||
|
||||
def _on_publish_start(self):
|
||||
if self._last_plugin_label:
|
||||
|
|
@ -351,12 +362,12 @@ class PublishFrame(QtWidgets.QWidget):
|
|||
"""Change plugin label when instance is going to be processed."""
|
||||
|
||||
self._last_plugin_label = event["plugin_label"]
|
||||
self._progress_bar.setValue(self._controller.publish_progress)
|
||||
self._progress_bar.setValue(self._controller.get_publish_progress())
|
||||
self._plugin_label.setText(event["plugin_label"])
|
||||
QtWidgets.QApplication.processEvents()
|
||||
|
||||
def _on_publish_stop(self):
|
||||
self._progress_bar.setValue(self._controller.publish_progress)
|
||||
self._progress_bar.setValue(self._controller.get_publish_progress())
|
||||
|
||||
self._reset_btn.setEnabled(True)
|
||||
self._stop_btn.setEnabled(False)
|
||||
|
|
@ -364,31 +375,21 @@ class PublishFrame(QtWidgets.QWidget):
|
|||
self._instance_label.setText("")
|
||||
self._plugin_label.setText("")
|
||||
|
||||
validate_enabled = not self._controller.publish_has_crashed
|
||||
publish_enabled = not self._controller.publish_has_crashed
|
||||
if validate_enabled:
|
||||
validate_enabled = not self._controller.publish_has_validated
|
||||
if publish_enabled:
|
||||
if (
|
||||
self._controller.publish_has_validated
|
||||
and self._controller.publish_has_validation_errors
|
||||
):
|
||||
publish_enabled = False
|
||||
|
||||
else:
|
||||
publish_enabled = not self._controller.publish_has_finished
|
||||
|
||||
publish_enabled = self._controller.publish_can_continue()
|
||||
validate_enabled = (
|
||||
publish_enabled and not self._controller.publish_has_validated()
|
||||
)
|
||||
self._validate_btn.setEnabled(validate_enabled)
|
||||
self._publish_btn.setEnabled(publish_enabled)
|
||||
|
||||
if self._controller.publish_has_crashed:
|
||||
if self._controller.publish_has_crashed():
|
||||
self._set_error_msg()
|
||||
|
||||
elif self._controller.publish_has_validation_errors:
|
||||
elif self._controller.publish_has_validation_errors():
|
||||
self._set_progress_visibility(False)
|
||||
self._set_validation_errors()
|
||||
|
||||
elif self._controller.publish_has_finished:
|
||||
elif self._controller.publish_has_finished():
|
||||
self._set_finished()
|
||||
|
||||
else:
|
||||
|
|
@ -411,7 +412,9 @@ class PublishFrame(QtWidgets.QWidget):
|
|||
|
||||
self._set_main_label("Error happened")
|
||||
|
||||
self._message_label_top.setText(self._controller.publish_error_msg)
|
||||
self._message_label_top.setText(
|
||||
self._controller.get_publish_error_msg()
|
||||
)
|
||||
|
||||
self._set_success_property(1)
|
||||
|
||||
|
|
@ -467,11 +470,11 @@ class PublishFrame(QtWidgets.QWidget):
|
|||
|
||||
def _on_report_triggered(self, identifier):
|
||||
if identifier == "export_report":
|
||||
self._controller.event_system.emit(
|
||||
self._controller.emit_event(
|
||||
"export_report.request", {}, "publish_frame")
|
||||
|
||||
elif identifier == "copy_report":
|
||||
self._controller.event_system.emit(
|
||||
self._controller.emit_event(
|
||||
"copy_report.request", {}, "publish_frame")
|
||||
|
||||
elif identifier == "go_to_report":
|
||||
|
|
|
|||
|
|
@ -19,16 +19,18 @@ from ayon_core.tools.utils import (
|
|||
paint_image_with_color,
|
||||
SeparatorWidget,
|
||||
)
|
||||
from ayon_core.tools.publisher.abstract import AbstractPublisherFrontend
|
||||
from ayon_core.tools.publisher.constants import (
|
||||
INSTANCE_ID_ROLE,
|
||||
CONTEXT_ID,
|
||||
CONTEXT_LABEL,
|
||||
)
|
||||
|
||||
from .widgets import IconValuePixmapLabel
|
||||
from .icons import (
|
||||
get_pixmap,
|
||||
get_image,
|
||||
)
|
||||
from ..constants import (
|
||||
INSTANCE_ID_ROLE,
|
||||
CONTEXT_ID,
|
||||
CONTEXT_LABEL,
|
||||
)
|
||||
|
||||
LOG_DEBUG_VISIBLE = 1 << 0
|
||||
LOG_INFO_VISIBLE = 1 << 1
|
||||
|
|
@ -50,7 +52,7 @@ class VerticalScrollArea(QtWidgets.QScrollArea):
|
|||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(VerticalScrollArea, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
||||
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
|
||||
|
|
@ -80,7 +82,7 @@ class VerticalScrollArea(QtWidgets.QScrollArea):
|
|||
if old_widget:
|
||||
old_widget.removeEventFilter(self)
|
||||
|
||||
super(VerticalScrollArea, self).setVerticalScrollBar(widget)
|
||||
super().setVerticalScrollBar(widget)
|
||||
if widget:
|
||||
widget.installEventFilter(self)
|
||||
|
||||
|
|
@ -89,7 +91,7 @@ class VerticalScrollArea(QtWidgets.QScrollArea):
|
|||
if old_widget:
|
||||
old_widget.removeEventFilter(self)
|
||||
|
||||
super(VerticalScrollArea, self).setWidget(widget)
|
||||
super().setWidget(widget)
|
||||
if widget:
|
||||
widget.installEventFilter(self)
|
||||
|
||||
|
|
@ -105,7 +107,7 @@ class VerticalScrollArea(QtWidgets.QScrollArea):
|
|||
and (obj is self.widget() or obj is self.verticalScrollBar())
|
||||
):
|
||||
self._size_changed_timer.start()
|
||||
return super(VerticalScrollArea, self).eventFilter(obj, event)
|
||||
return super().eventFilter(obj, event)
|
||||
|
||||
|
||||
# --- Publish actions widget ---
|
||||
|
|
@ -122,7 +124,7 @@ class ActionButton(BaseClickableFrame):
|
|||
action_clicked = QtCore.Signal(str, str)
|
||||
|
||||
def __init__(self, plugin_action_item, parent):
|
||||
super(ActionButton, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
|
||||
self.setObjectName("ValidationActionButton")
|
||||
|
||||
|
|
@ -159,8 +161,10 @@ class ValidateActionsWidget(QtWidgets.QFrame):
|
|||
Change actions based on selected validation error.
|
||||
"""
|
||||
|
||||
def __init__(self, controller, parent):
|
||||
super(ValidateActionsWidget, self).__init__(parent)
|
||||
def __init__(
|
||||
self, controller: AbstractPublisherFrontend, parent: QtWidgets.QWidget
|
||||
):
|
||||
super().__init__(parent)
|
||||
|
||||
self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
|
||||
|
||||
|
|
@ -172,7 +176,7 @@ class ValidateActionsWidget(QtWidgets.QFrame):
|
|||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
layout.addWidget(content_widget)
|
||||
|
||||
self._controller = controller
|
||||
self._controller: AbstractPublisherFrontend = controller
|
||||
self._content_widget = content_widget
|
||||
self._content_layout = content_layout
|
||||
|
||||
|
|
@ -246,7 +250,7 @@ class ValidationErrorInstanceList(QtWidgets.QListView):
|
|||
Instances are collected per plugin's validation error title.
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ValidationErrorInstanceList, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.setObjectName("ValidationErrorInstanceList")
|
||||
|
||||
|
|
@ -257,7 +261,7 @@ class ValidationErrorInstanceList(QtWidgets.QListView):
|
|||
return self.sizeHint()
|
||||
|
||||
def sizeHint(self):
|
||||
result = super(ValidationErrorInstanceList, self).sizeHint()
|
||||
result = super().sizeHint()
|
||||
row_count = self.model().rowCount()
|
||||
height = 0
|
||||
if row_count > 0:
|
||||
|
|
@ -280,7 +284,7 @@ class ValidationErrorTitleWidget(QtWidgets.QWidget):
|
|||
instance_changed = QtCore.Signal(str)
|
||||
|
||||
def __init__(self, title_id, error_info, parent):
|
||||
super(ValidationErrorTitleWidget, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
|
||||
self._title_id = title_id
|
||||
self._error_info = error_info
|
||||
|
|
@ -371,7 +375,7 @@ class ValidationErrorTitleWidget(QtWidgets.QWidget):
|
|||
self._expanded = False
|
||||
|
||||
def sizeHint(self):
|
||||
result = super(ValidationErrorTitleWidget, self).sizeHint()
|
||||
result = super().sizeHint()
|
||||
expected_width = max(
|
||||
self._view_widget.minimumSizeHint().width(),
|
||||
self._view_widget.sizeHint().width()
|
||||
|
|
@ -475,7 +479,7 @@ class ValidationErrorTitleWidget(QtWidgets.QWidget):
|
|||
|
||||
class ValidationArtistMessage(QtWidgets.QWidget):
|
||||
def __init__(self, message, parent):
|
||||
super(ValidationArtistMessage, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
|
||||
artist_msg_label = QtWidgets.QLabel(message, self)
|
||||
artist_msg_label.setAlignment(QtCore.Qt.AlignCenter)
|
||||
|
|
@ -491,7 +495,7 @@ class ValidationErrorsView(QtWidgets.QWidget):
|
|||
selection_changed = QtCore.Signal()
|
||||
|
||||
def __init__(self, parent):
|
||||
super(ValidationErrorsView, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
|
||||
errors_scroll = VerticalScrollArea(self)
|
||||
errors_scroll.setWidgetResizable(True)
|
||||
|
|
@ -715,7 +719,7 @@ class _InstanceItem:
|
|||
|
||||
class FamilyGroupLabel(QtWidgets.QWidget):
|
||||
def __init__(self, family, parent):
|
||||
super(FamilyGroupLabel, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
|
||||
self.setLayoutDirection(QtCore.Qt.LeftToRight)
|
||||
|
||||
|
|
@ -742,8 +746,8 @@ class PublishInstanceCardWidget(BaseClickableFrame):
|
|||
_success_pix = None
|
||||
_in_progress_pix = None
|
||||
|
||||
def __init__(self, instance, icon, publish_finished, parent):
|
||||
super(PublishInstanceCardWidget, self).__init__(parent)
|
||||
def __init__(self, instance, icon, publish_can_continue, parent):
|
||||
super().__init__(parent)
|
||||
|
||||
self.setObjectName("CardViewWidget")
|
||||
|
||||
|
|
@ -756,10 +760,10 @@ class PublishInstanceCardWidget(BaseClickableFrame):
|
|||
state_pix = self.get_error_pix()
|
||||
elif instance.warned:
|
||||
state_pix = self.get_warning_pix()
|
||||
elif publish_finished:
|
||||
state_pix = self.get_success_pix()
|
||||
else:
|
||||
elif publish_can_continue:
|
||||
state_pix = self.get_in_progress_pix()
|
||||
else:
|
||||
state_pix = self.get_success_pix()
|
||||
|
||||
state_label = IconValuePixmapLabel(state_pix, self)
|
||||
|
||||
|
|
@ -874,8 +878,10 @@ class PublishInstancesViewWidget(QtWidgets.QWidget):
|
|||
_min_width_measure_string = 24 * "O"
|
||||
selection_changed = QtCore.Signal()
|
||||
|
||||
def __init__(self, controller, parent):
|
||||
super(PublishInstancesViewWidget, self).__init__(parent)
|
||||
def __init__(
|
||||
self, controller: AbstractPublisherFrontend, parent: QtWidgets.QWidget
|
||||
):
|
||||
super().__init__(parent)
|
||||
|
||||
scroll_area = VerticalScrollArea(self)
|
||||
scroll_area.setWidgetResizable(True)
|
||||
|
|
@ -898,7 +904,7 @@ class PublishInstancesViewWidget(QtWidgets.QWidget):
|
|||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
layout.addWidget(scroll_area, 1)
|
||||
|
||||
self._controller = controller
|
||||
self._controller: AbstractPublisherFrontend = controller
|
||||
self._scroll_area = scroll_area
|
||||
self._instance_view = instance_view
|
||||
self._instance_layout = instance_layout
|
||||
|
|
@ -927,7 +933,7 @@ class PublishInstancesViewWidget(QtWidgets.QWidget):
|
|||
+ scroll_bar.sizeHint().width()
|
||||
)
|
||||
|
||||
result = super(PublishInstancesViewWidget, self).sizeHint()
|
||||
result = super().sizeHint()
|
||||
result.setWidth(width)
|
||||
return result
|
||||
|
||||
|
|
@ -970,11 +976,7 @@ class PublishInstancesViewWidget(QtWidgets.QWidget):
|
|||
widgets = []
|
||||
group_widgets = []
|
||||
|
||||
publish_finished = (
|
||||
self._controller.publish_has_crashed
|
||||
or self._controller.publish_has_validation_errors
|
||||
or self._controller.publish_has_finished
|
||||
)
|
||||
publish_can_continue = self._controller.publish_can_continue()
|
||||
instances_by_family = collections.defaultdict(list)
|
||||
for instance_item in instance_items:
|
||||
if not instance_item.exists:
|
||||
|
|
@ -996,7 +998,10 @@ class PublishInstancesViewWidget(QtWidgets.QWidget):
|
|||
icon = identifier_icons[instance_item.creator_identifier]
|
||||
|
||||
widget = PublishInstanceCardWidget(
|
||||
instance_item, icon, publish_finished, self._instance_view
|
||||
instance_item,
|
||||
icon,
|
||||
publish_can_continue,
|
||||
self._instance_view
|
||||
)
|
||||
widget.selection_requested.connect(self._on_selection_request)
|
||||
self._instance_layout.addWidget(widget, 0)
|
||||
|
|
@ -1040,7 +1045,7 @@ class LogIconFrame(QtWidgets.QFrame):
|
|||
_validation_error_pix = None
|
||||
|
||||
def __init__(self, parent, log_type, log_level, is_validation_error):
|
||||
super(LogIconFrame, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
|
||||
self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
|
||||
|
||||
|
|
@ -1108,7 +1113,7 @@ class LogItemWidget(QtWidgets.QWidget):
|
|||
}
|
||||
|
||||
def __init__(self, log, parent):
|
||||
super(LogItemWidget, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
|
||||
type_flag, level_n = self._get_log_info(log)
|
||||
icon_label = LogIconFrame(
|
||||
|
|
@ -1185,7 +1190,7 @@ class LogsWithIconsView(QtWidgets.QWidget):
|
|||
"""
|
||||
|
||||
def __init__(self, logs, parent):
|
||||
super(LogsWithIconsView, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
|
||||
|
||||
logs_layout = QtWidgets.QVBoxLayout(self)
|
||||
|
|
@ -1265,7 +1270,7 @@ class InstanceLogsWidget(QtWidgets.QWidget):
|
|||
"""
|
||||
|
||||
def __init__(self, instance, parent):
|
||||
super(InstanceLogsWidget, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
|
||||
self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
|
||||
|
||||
|
|
@ -1296,7 +1301,7 @@ class InstancesLogsView(QtWidgets.QFrame):
|
|||
"""Publish instances logs view widget."""
|
||||
|
||||
def __init__(self, parent):
|
||||
super(InstancesLogsView, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
self.setObjectName("InstancesLogsView")
|
||||
|
||||
scroll_area = QtWidgets.QScrollArea(self)
|
||||
|
|
@ -1349,16 +1354,16 @@ class InstancesLogsView(QtWidgets.QFrame):
|
|||
self._plugin_ids_filter = None
|
||||
|
||||
def showEvent(self, event):
|
||||
super(InstancesLogsView, self).showEvent(event)
|
||||
super().showEvent(event)
|
||||
self._is_showed = True
|
||||
self._update_instances()
|
||||
|
||||
def hideEvent(self, event):
|
||||
super(InstancesLogsView, self).hideEvent(event)
|
||||
super().hideEvent(event)
|
||||
self._is_showed = False
|
||||
|
||||
def closeEvent(self, event):
|
||||
super(InstancesLogsView, self).closeEvent(event)
|
||||
super().closeEvent(event)
|
||||
self._is_showed = False
|
||||
|
||||
def _update_instances(self):
|
||||
|
|
@ -1456,8 +1461,10 @@ class CrashWidget(QtWidgets.QWidget):
|
|||
actions.
|
||||
"""
|
||||
|
||||
def __init__(self, controller, parent):
|
||||
super(CrashWidget, self).__init__(parent)
|
||||
def __init__(
|
||||
self, controller: AbstractPublisherFrontend, parent: QtWidgets.QWidget
|
||||
):
|
||||
super().__init__(parent)
|
||||
|
||||
main_label = QtWidgets.QLabel("This is not your fault", self)
|
||||
main_label.setAlignment(QtCore.Qt.AlignCenter)
|
||||
|
|
@ -1499,20 +1506,20 @@ class CrashWidget(QtWidgets.QWidget):
|
|||
copy_clipboard_btn.clicked.connect(self._on_copy_to_clipboard)
|
||||
save_to_disk_btn.clicked.connect(self._on_save_to_disk_click)
|
||||
|
||||
self._controller = controller
|
||||
self._controller: AbstractPublisherFrontend = controller
|
||||
|
||||
def _on_copy_to_clipboard(self):
|
||||
self._controller.event_system.emit(
|
||||
self._controller.emit_event(
|
||||
"copy_report.request", {}, "report_page")
|
||||
|
||||
def _on_save_to_disk_click(self):
|
||||
self._controller.event_system.emit(
|
||||
self._controller.emit_event(
|
||||
"export_report.request", {}, "report_page")
|
||||
|
||||
|
||||
class ErrorDetailsWidget(QtWidgets.QWidget):
|
||||
def __init__(self, parent):
|
||||
super(ErrorDetailsWidget, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
|
||||
inputs_widget = QtWidgets.QWidget(self)
|
||||
# Error 'Description' input
|
||||
|
|
@ -1624,8 +1631,10 @@ class ReportsWidget(QtWidgets.QWidget):
|
|||
└──────┴─────────┴─────────┘
|
||||
"""
|
||||
|
||||
def __init__(self, controller, parent):
|
||||
super(ReportsWidget, self).__init__(parent)
|
||||
def __init__(
|
||||
self, controller: AbstractPublisherFrontend, parent: QtWidgets.QWidget
|
||||
):
|
||||
super().__init__(parent)
|
||||
|
||||
# Instances view
|
||||
views_widget = QtWidgets.QWidget(self)
|
||||
|
|
@ -1709,7 +1718,7 @@ class ReportsWidget(QtWidgets.QWidget):
|
|||
self._detail_input_scroll = detail_input_scroll
|
||||
self._crash_widget = crash_widget
|
||||
|
||||
self._controller = controller
|
||||
self._controller: AbstractPublisherFrontend = controller
|
||||
|
||||
self._validation_errors_by_id = {}
|
||||
|
||||
|
|
@ -1744,8 +1753,8 @@ class ReportsWidget(QtWidgets.QWidget):
|
|||
view = self._instances_view
|
||||
validation_error_mode = False
|
||||
if (
|
||||
not self._controller.publish_has_crashed
|
||||
and self._controller.publish_has_validation_errors
|
||||
not self._controller.publish_has_crashed()
|
||||
and self._controller.publish_has_validation_errors()
|
||||
):
|
||||
view = self._validation_error_view
|
||||
validation_error_mode = True
|
||||
|
|
@ -1755,8 +1764,9 @@ class ReportsWidget(QtWidgets.QWidget):
|
|||
self._detail_input_scroll.setVisible(validation_error_mode)
|
||||
self._views_layout.setCurrentWidget(view)
|
||||
|
||||
self._crash_widget.setVisible(self._controller.publish_has_crashed)
|
||||
self._logs_view.setVisible(not self._controller.publish_has_crashed)
|
||||
is_crashed = self._controller.publish_has_crashed()
|
||||
self._crash_widget.setVisible(is_crashed)
|
||||
self._logs_view.setVisible(not is_crashed)
|
||||
|
||||
# Instance view & logs update
|
||||
instance_items = self._get_instance_items()
|
||||
|
|
@ -1818,8 +1828,10 @@ class ReportPageWidget(QtWidgets.QFrame):
|
|||
and validation error detail with possible actions (repair).
|
||||
"""
|
||||
|
||||
def __init__(self, controller, parent):
|
||||
super(ReportPageWidget, self).__init__(parent)
|
||||
def __init__(
|
||||
self, controller: AbstractPublisherFrontend, parent: QtWidgets.QWidget
|
||||
):
|
||||
super().__init__(parent)
|
||||
|
||||
header_label = QtWidgets.QLabel(self)
|
||||
header_label.setAlignment(QtCore.Qt.AlignCenter)
|
||||
|
|
@ -1832,30 +1844,30 @@ class ReportPageWidget(QtWidgets.QFrame):
|
|||
layout.addWidget(header_label, 0)
|
||||
layout.addWidget(publish_instances_widget, 0)
|
||||
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"publish.process.started", self._on_publish_start
|
||||
)
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"publish.reset.finished", self._on_publish_reset
|
||||
)
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"publish.process.stopped", self._on_publish_stop
|
||||
)
|
||||
|
||||
self._header_label = header_label
|
||||
self._publish_instances_widget = publish_instances_widget
|
||||
|
||||
self._controller = controller
|
||||
self._controller: AbstractPublisherFrontend = controller
|
||||
|
||||
def _update_label(self):
|
||||
if not self._controller.publish_has_started:
|
||||
if not self._controller.publish_has_started():
|
||||
# This probably never happen when this widget is visible
|
||||
header_label = "Nothing to report until you run publish"
|
||||
elif self._controller.publish_has_crashed:
|
||||
elif self._controller.publish_has_crashed():
|
||||
header_label = "Publish error report"
|
||||
elif self._controller.publish_has_validation_errors:
|
||||
elif self._controller.publish_has_validation_errors():
|
||||
header_label = "Publish validation report"
|
||||
elif self._controller.publish_has_finished:
|
||||
elif self._controller.publish_has_finished():
|
||||
header_label = "Publish success report"
|
||||
else:
|
||||
header_label = "Publish report"
|
||||
|
|
@ -1863,7 +1875,7 @@ class ReportPageWidget(QtWidgets.QFrame):
|
|||
|
||||
def _update_state(self):
|
||||
self._update_label()
|
||||
publish_started = self._controller.publish_has_started
|
||||
publish_started = self._controller.publish_has_started()
|
||||
self._publish_instances_widget.setVisible(publish_started)
|
||||
if publish_started:
|
||||
self._publish_instances_widget.update_data()
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ class ScreenMarquee(QtWidgets.QDialog):
|
|||
"""
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super(ScreenMarquee, self).__init__(parent=parent)
|
||||
super().__init__(parent=parent)
|
||||
|
||||
self.setWindowFlags(
|
||||
QtCore.Qt.Window
|
||||
|
|
@ -138,7 +138,7 @@ class ScreenMarquee(QtWidgets.QDialog):
|
|||
event.accept()
|
||||
self.close()
|
||||
return
|
||||
return super(ScreenMarquee, self).keyPressEvent(event)
|
||||
return super().keyPressEvent(event)
|
||||
|
||||
def showEvent(self, event):
|
||||
self._fit_screen_geometry()
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ class PublisherTabBtn(QtWidgets.QPushButton):
|
|||
tab_clicked = QtCore.Signal(str)
|
||||
|
||||
def __init__(self, identifier, label, parent):
|
||||
super(PublisherTabBtn, self).__init__(label, parent)
|
||||
super().__init__(label, parent)
|
||||
self._identifier = identifier
|
||||
self._active = False
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ class PublisherTabsWidget(QtWidgets.QFrame):
|
|||
tab_changed = QtCore.Signal(str, str)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super(PublisherTabsWidget, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
|
||||
btns_widget = QtWidgets.QWidget(self)
|
||||
btns_layout = QtWidgets.QHBoxLayout(btns_widget)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
from typing import Optional
|
||||
|
||||
from qtpy import QtCore, QtGui
|
||||
|
||||
from ayon_core.style import get_default_entity_icon_color
|
||||
from ayon_core.tools.utils import get_qt_icon
|
||||
from ayon_core.tools.publisher.abstract import AbstractPublisherFrontend
|
||||
|
||||
TASK_NAME_ROLE = QtCore.Qt.UserRole + 1
|
||||
TASK_TYPE_ROLE = QtCore.Qt.UserRole + 2
|
||||
|
|
@ -19,14 +22,19 @@ class TasksModel(QtGui.QStandardItemModel):
|
|||
tasks with same names then model is empty too.
|
||||
|
||||
Args:
|
||||
controller (PublisherController): Controller which handles creation and
|
||||
controller (AbstractPublisherFrontend): Controller which handles creation and
|
||||
publishing.
|
||||
|
||||
"""
|
||||
def __init__(self, controller, allow_empty_task=False):
|
||||
super(TasksModel, self).__init__()
|
||||
def __init__(
|
||||
self,
|
||||
controller: AbstractPublisherFrontend,
|
||||
allow_empty_task: Optional[bool] = False
|
||||
):
|
||||
super().__init__()
|
||||
|
||||
self._allow_empty_task = allow_empty_task
|
||||
self._controller = controller
|
||||
self._controller: AbstractPublisherFrontend = controller
|
||||
self._items_by_name = {}
|
||||
self._folder_paths = []
|
||||
self._task_names_by_folder_path = {}
|
||||
|
|
@ -135,7 +143,7 @@ class TasksModel(QtGui.QStandardItemModel):
|
|||
task_type_items = {
|
||||
task_type_item.name: task_type_item
|
||||
for task_type_item in self._controller.get_task_type_items(
|
||||
self._controller.project_name
|
||||
self._controller.get_current_project_name()
|
||||
)
|
||||
}
|
||||
icon_name_by_task_name = {}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,10 @@ from ayon_core.tools.utils import (
|
|||
paint_image_with_color,
|
||||
PixmapButton,
|
||||
)
|
||||
from ayon_core.tools.publisher.control import CardMessageTypes
|
||||
from ayon_core.tools.publisher.abstract import (
|
||||
CardMessageTypes,
|
||||
AbstractPublisherFrontend,
|
||||
)
|
||||
|
||||
from .icons import get_image
|
||||
from .screenshot_widget import capture_to_file
|
||||
|
|
@ -34,7 +37,7 @@ class ThumbnailPainterWidget(QtWidgets.QWidget):
|
|||
checker_boxes_count = 20
|
||||
|
||||
def __init__(self, parent):
|
||||
super(ThumbnailPainterWidget, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
|
||||
border_color = get_objected_colors("bg-buttons").get_qcolor()
|
||||
thumbnail_bg_color = get_objected_colors("bg-view").get_qcolor()
|
||||
|
|
@ -299,10 +302,12 @@ class ThumbnailWidget(QtWidgets.QWidget):
|
|||
thumbnail_created = QtCore.Signal(str)
|
||||
thumbnail_cleared = QtCore.Signal()
|
||||
|
||||
def __init__(self, controller, parent):
|
||||
def __init__(
|
||||
self, controller: AbstractPublisherFrontend, parent: QtWidgets.QWidget
|
||||
):
|
||||
# Missing implementation for thumbnail
|
||||
# - widget kept to make a visial offset of global attr widget offset
|
||||
super(ThumbnailWidget, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
self.setAcceptDrops(True)
|
||||
|
||||
thumbnail_painter = ThumbnailPainterWidget(self)
|
||||
|
|
@ -355,7 +360,7 @@ class ThumbnailWidget(QtWidgets.QWidget):
|
|||
paste_btn.clicked.connect(self._on_paste_from_clipboard)
|
||||
browse_btn.clicked.connect(self._on_browse_clicked)
|
||||
|
||||
self._controller = controller
|
||||
self._controller: AbstractPublisherFrontend = controller
|
||||
self._output_dir = controller.get_thumbnail_temp_dir_path()
|
||||
|
||||
self._review_extensions = set(IMAGE_EXTENSIONS) | set(VIDEO_EXTENSIONS)
|
||||
|
|
@ -570,12 +575,12 @@ class ThumbnailWidget(QtWidgets.QWidget):
|
|||
)
|
||||
|
||||
def resizeEvent(self, event):
|
||||
super(ThumbnailWidget, self).resizeEvent(event)
|
||||
super().resizeEvent(event)
|
||||
self._adapt_to_size()
|
||||
self._update_buttons_position()
|
||||
|
||||
def showEvent(self, event):
|
||||
super(ThumbnailWidget, self).showEvent(event)
|
||||
super().showEvent(event)
|
||||
self._adapt_to_size()
|
||||
self._update_buttons_position()
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,11 @@ from qtpy import QtWidgets, QtCore, QtGui
|
|||
import qtawesome
|
||||
|
||||
from ayon_core.lib.attribute_definitions import UnknownDef
|
||||
from ayon_core.style import get_objected_colors
|
||||
from ayon_core.pipeline.create import (
|
||||
PRODUCT_NAME_ALLOWED_SYMBOLS,
|
||||
TaskNotSetError,
|
||||
)
|
||||
from ayon_core.tools.attribute_defs import create_widget_for_attr_def
|
||||
from ayon_core.tools import resources
|
||||
from ayon_core.tools.flickcharm import FlickCharm
|
||||
|
|
@ -20,11 +25,14 @@ from ayon_core.tools.utils import (
|
|||
BaseClickableFrame,
|
||||
set_style_property,
|
||||
)
|
||||
from ayon_core.style import get_objected_colors
|
||||
from ayon_core.pipeline.create import (
|
||||
PRODUCT_NAME_ALLOWED_SYMBOLS,
|
||||
TaskNotSetError,
|
||||
from ayon_core.tools.publisher.abstract import AbstractPublisherFrontend
|
||||
from ayon_core.tools.publisher.constants import (
|
||||
VARIANT_TOOLTIP,
|
||||
ResetKeySequence,
|
||||
INPUTS_LAYOUT_HSPACING,
|
||||
INPUTS_LAYOUT_VSPACING,
|
||||
)
|
||||
|
||||
from .thumbnail_widget import ThumbnailWidget
|
||||
from .folders_dialog import FoldersDialog
|
||||
from .tasks_model import TasksModel
|
||||
|
|
@ -33,13 +41,6 @@ from .icons import (
|
|||
get_icon_path
|
||||
)
|
||||
|
||||
from ..constants import (
|
||||
VARIANT_TOOLTIP,
|
||||
ResetKeySequence,
|
||||
INPUTS_LAYOUT_HSPACING,
|
||||
INPUTS_LAYOUT_VSPACING,
|
||||
)
|
||||
|
||||
FA_PREFIXES = ["", "fa.", "fa5.", "fa5b.", "fa5s.", "ei.", "mdi."]
|
||||
|
||||
|
||||
|
|
@ -94,7 +95,7 @@ class IconValuePixmapLabel(PublishPixmapLabel):
|
|||
def __init__(self, icon_def, parent):
|
||||
source_pixmap = self._parse_icon_def(icon_def)
|
||||
|
||||
super(IconValuePixmapLabel, self).__init__(source_pixmap, parent)
|
||||
super().__init__(source_pixmap, parent)
|
||||
|
||||
def set_icon_def(self, icon_def):
|
||||
"""Set icon by it's definition name.
|
||||
|
|
@ -122,7 +123,7 @@ class ContextWarningLabel(PublishPixmapLabel):
|
|||
def __init__(self, parent):
|
||||
pix = get_pixmap("warning")
|
||||
|
||||
super(ContextWarningLabel, self).__init__(pix, parent)
|
||||
super().__init__(pix, parent)
|
||||
|
||||
self.setToolTip(
|
||||
"Contain invalid context. Please check details."
|
||||
|
|
@ -145,7 +146,7 @@ class PublishIconBtn(IconButton):
|
|||
"""
|
||||
|
||||
def __init__(self, pixmap_path, *args, **kwargs):
|
||||
super(PublishIconBtn, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
colors = get_objected_colors()
|
||||
icon = self.generate_icon(
|
||||
|
|
@ -208,7 +209,7 @@ class CreateBtn(PublishIconBtn):
|
|||
|
||||
def __init__(self, parent=None):
|
||||
icon_path = get_icon_path("create")
|
||||
super(CreateBtn, self).__init__(icon_path, "Create", parent)
|
||||
super().__init__(icon_path, "Create", parent)
|
||||
self.setToolTip("Create new product/s")
|
||||
self.setLayoutDirection(QtCore.Qt.RightToLeft)
|
||||
|
||||
|
|
@ -217,7 +218,7 @@ class SaveBtn(PublishIconBtn):
|
|||
"""Save context and instances information."""
|
||||
def __init__(self, parent=None):
|
||||
icon_path = get_icon_path("save")
|
||||
super(SaveBtn, self).__init__(icon_path, parent)
|
||||
super().__init__(icon_path, parent)
|
||||
self.setToolTip(
|
||||
"Save changes ({})".format(
|
||||
QtGui.QKeySequence(QtGui.QKeySequence.Save).toString()
|
||||
|
|
@ -229,7 +230,7 @@ class ResetBtn(PublishIconBtn):
|
|||
"""Publish reset button."""
|
||||
def __init__(self, parent=None):
|
||||
icon_path = get_icon_path("refresh")
|
||||
super(ResetBtn, self).__init__(icon_path, parent)
|
||||
super().__init__(icon_path, parent)
|
||||
self.setToolTip(
|
||||
"Reset & discard changes ({})".format(ResetKeySequence.toString())
|
||||
)
|
||||
|
|
@ -239,7 +240,7 @@ class StopBtn(PublishIconBtn):
|
|||
"""Publish stop button."""
|
||||
def __init__(self, parent):
|
||||
icon_path = get_icon_path("stop")
|
||||
super(StopBtn, self).__init__(icon_path, parent)
|
||||
super().__init__(icon_path, parent)
|
||||
self.setToolTip("Stop/Pause publishing")
|
||||
|
||||
|
||||
|
|
@ -247,7 +248,7 @@ class ValidateBtn(PublishIconBtn):
|
|||
"""Publish validate button."""
|
||||
def __init__(self, parent=None):
|
||||
icon_path = get_icon_path("validate")
|
||||
super(ValidateBtn, self).__init__(icon_path, parent)
|
||||
super().__init__(icon_path, parent)
|
||||
self.setToolTip("Validate")
|
||||
|
||||
|
||||
|
|
@ -255,7 +256,7 @@ class PublishBtn(PublishIconBtn):
|
|||
"""Publish start publish button."""
|
||||
def __init__(self, parent=None):
|
||||
icon_path = get_icon_path("play")
|
||||
super(PublishBtn, self).__init__(icon_path, "Publish", parent)
|
||||
super().__init__(icon_path, "Publish", parent)
|
||||
self.setToolTip("Publish")
|
||||
|
||||
|
||||
|
|
@ -263,7 +264,7 @@ class CreateInstanceBtn(PublishIconBtn):
|
|||
"""Create add button."""
|
||||
def __init__(self, parent=None):
|
||||
icon_path = get_icon_path("add")
|
||||
super(CreateInstanceBtn, self).__init__(icon_path, parent)
|
||||
super().__init__(icon_path, parent)
|
||||
self.setToolTip("Create new instance")
|
||||
|
||||
|
||||
|
|
@ -274,7 +275,7 @@ class PublishReportBtn(PublishIconBtn):
|
|||
|
||||
def __init__(self, parent=None):
|
||||
icon_path = get_icon_path("view_report")
|
||||
super(PublishReportBtn, self).__init__(icon_path, parent)
|
||||
super().__init__(icon_path, parent)
|
||||
self.setToolTip("Copy report")
|
||||
self._actions = []
|
||||
|
||||
|
|
@ -287,7 +288,7 @@ class PublishReportBtn(PublishIconBtn):
|
|||
self.triggered.emit(identifier)
|
||||
|
||||
def mouseReleaseEvent(self, event):
|
||||
super(PublishReportBtn, self).mouseReleaseEvent(event)
|
||||
super().mouseReleaseEvent(event)
|
||||
menu = QtWidgets.QMenu(self)
|
||||
actions = []
|
||||
for item in self._actions:
|
||||
|
|
@ -305,7 +306,7 @@ class RemoveInstanceBtn(PublishIconBtn):
|
|||
"""Create remove button."""
|
||||
def __init__(self, parent=None):
|
||||
icon_path = resources.get_icon_path("delete")
|
||||
super(RemoveInstanceBtn, self).__init__(icon_path, parent)
|
||||
super().__init__(icon_path, parent)
|
||||
self.setToolTip("Remove selected instances")
|
||||
|
||||
|
||||
|
|
@ -313,7 +314,7 @@ class ChangeViewBtn(PublishIconBtn):
|
|||
"""Create toggle view button."""
|
||||
def __init__(self, parent=None):
|
||||
icon_path = get_icon_path("change_view")
|
||||
super(ChangeViewBtn, self).__init__(icon_path, parent)
|
||||
super().__init__(icon_path, parent)
|
||||
self.setToolTip("Swap between views")
|
||||
|
||||
|
||||
|
|
@ -363,7 +364,9 @@ class AbstractInstanceView(QtWidgets.QWidget):
|
|||
"{} Method 'get_selected_items' is not implemented."
|
||||
).format(self.__class__.__name__))
|
||||
|
||||
def set_selected_items(self, instance_ids, context_selected):
|
||||
def set_selected_items(
|
||||
self, instance_ids, context_selected, convertor_identifiers
|
||||
):
|
||||
"""Change selection for instances and context.
|
||||
|
||||
Used to applying selection from one view to other.
|
||||
|
|
@ -371,8 +374,9 @@ class AbstractInstanceView(QtWidgets.QWidget):
|
|||
Args:
|
||||
instance_ids (List[str]): Selected instance ids.
|
||||
context_selected (bool): Context is selected.
|
||||
"""
|
||||
convertor_identifiers (List[str]): Selected convertor identifiers.
|
||||
|
||||
"""
|
||||
raise NotImplementedError((
|
||||
"{} Method 'set_selected_items' is not implemented."
|
||||
).format(self.__class__.__name__))
|
||||
|
|
@ -399,7 +403,7 @@ class ClickableLineEdit(QtWidgets.QLineEdit):
|
|||
clicked = QtCore.Signal()
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ClickableLineEdit, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
self.setReadOnly(True)
|
||||
self._mouse_pressed = False
|
||||
|
||||
|
|
@ -429,8 +433,10 @@ class FoldersFields(BaseClickableFrame):
|
|||
"""
|
||||
value_changed = QtCore.Signal()
|
||||
|
||||
def __init__(self, controller, parent):
|
||||
super(FoldersFields, self).__init__(parent)
|
||||
def __init__(
|
||||
self, controller: AbstractPublisherFrontend, parent: QtWidgets.QWidget
|
||||
):
|
||||
super().__init__(parent)
|
||||
self.setObjectName("FolderPathInputWidget")
|
||||
|
||||
# Don't use 'self' for parent!
|
||||
|
|
@ -465,7 +471,7 @@ class FoldersFields(BaseClickableFrame):
|
|||
icon_btn.clicked.connect(self._mouse_release_callback)
|
||||
dialog.finished.connect(self._on_dialog_finish)
|
||||
|
||||
self._controller = controller
|
||||
self._controller: AbstractPublisherFrontend = controller
|
||||
self._dialog = dialog
|
||||
self._name_input = name_input
|
||||
self._icon_btn = icon_btn
|
||||
|
|
@ -582,7 +588,7 @@ class FoldersFields(BaseClickableFrame):
|
|||
|
||||
class TasksComboboxProxy(QtCore.QSortFilterProxyModel):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(TasksComboboxProxy, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
self._filter_empty = False
|
||||
|
||||
def set_filter_empty(self, filter_empty):
|
||||
|
|
@ -613,8 +619,10 @@ class TasksCombobox(QtWidgets.QComboBox):
|
|||
"""
|
||||
value_changed = QtCore.Signal()
|
||||
|
||||
def __init__(self, controller, parent):
|
||||
super(TasksCombobox, self).__init__(parent)
|
||||
def __init__(
|
||||
self, controller: AbstractPublisherFrontend, parent: QtWidgets.QWidget
|
||||
):
|
||||
super().__init__(parent)
|
||||
self.setObjectName("TasksCombobox")
|
||||
|
||||
# Set empty delegate to propagate stylesheet to a combobox
|
||||
|
|
@ -892,7 +900,7 @@ class VariantInputWidget(PlaceholderLineEdit):
|
|||
value_changed = QtCore.Signal()
|
||||
|
||||
def __init__(self, parent):
|
||||
super(VariantInputWidget, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
|
||||
self.setObjectName("VariantInput")
|
||||
self.setToolTip(VARIANT_TOOLTIP)
|
||||
|
|
@ -1003,7 +1011,7 @@ class MultipleItemWidget(QtWidgets.QWidget):
|
|||
"""
|
||||
|
||||
def __init__(self, parent):
|
||||
super(MultipleItemWidget, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
|
||||
model = QtGui.QStandardItemModel()
|
||||
|
||||
|
|
@ -1043,7 +1051,7 @@ class MultipleItemWidget(QtWidgets.QWidget):
|
|||
self.setMaximumHeight(height + (2 * self._view.spacing()))
|
||||
|
||||
def showEvent(self, event):
|
||||
super(MultipleItemWidget, self).showEvent(event)
|
||||
super().showEvent(event)
|
||||
tmp_item = None
|
||||
if not self._value:
|
||||
# Add temp item to be able calculate maximum height of widget
|
||||
|
|
@ -1055,7 +1063,7 @@ class MultipleItemWidget(QtWidgets.QWidget):
|
|||
self._model.clear()
|
||||
|
||||
def resizeEvent(self, event):
|
||||
super(MultipleItemWidget, self).resizeEvent(event)
|
||||
super().resizeEvent(event)
|
||||
self._update_size()
|
||||
|
||||
def set_value(self, value=None):
|
||||
|
|
@ -1095,10 +1103,12 @@ class GlobalAttrsWidget(QtWidgets.QWidget):
|
|||
multiselection_text = "< Multiselection >"
|
||||
unknown_value = "N/A"
|
||||
|
||||
def __init__(self, controller, parent):
|
||||
super(GlobalAttrsWidget, self).__init__(parent)
|
||||
def __init__(
|
||||
self, controller: AbstractPublisherFrontend, parent: QtWidgets.QWidget
|
||||
):
|
||||
super().__init__(parent)
|
||||
|
||||
self._controller = controller
|
||||
self._controller: AbstractPublisherFrontend = controller
|
||||
self._current_instances = []
|
||||
|
||||
variant_input = VariantInputWidget(self)
|
||||
|
|
@ -1338,8 +1348,10 @@ class CreatorAttrsWidget(QtWidgets.QWidget):
|
|||
widgets are merged into one (different label does not count).
|
||||
"""
|
||||
|
||||
def __init__(self, controller, parent):
|
||||
super(CreatorAttrsWidget, self).__init__(parent)
|
||||
def __init__(
|
||||
self, controller: AbstractPublisherFrontend, parent: QtWidgets.QWidget
|
||||
):
|
||||
super().__init__(parent)
|
||||
|
||||
scroll_area = QtWidgets.QScrollArea(self)
|
||||
scroll_area.setWidgetResizable(True)
|
||||
|
|
@ -1351,7 +1363,7 @@ class CreatorAttrsWidget(QtWidgets.QWidget):
|
|||
|
||||
self._main_layout = main_layout
|
||||
|
||||
self._controller = controller
|
||||
self._controller: AbstractPublisherFrontend = controller
|
||||
self._scroll_area = scroll_area
|
||||
|
||||
self._attr_def_id_to_instances = {}
|
||||
|
|
@ -1476,8 +1488,10 @@ class PublishPluginAttrsWidget(QtWidgets.QWidget):
|
|||
does not count).
|
||||
"""
|
||||
|
||||
def __init__(self, controller, parent):
|
||||
super(PublishPluginAttrsWidget, self).__init__(parent)
|
||||
def __init__(
|
||||
self, controller: AbstractPublisherFrontend, parent: QtWidgets.QWidget
|
||||
):
|
||||
super().__init__(parent)
|
||||
|
||||
scroll_area = QtWidgets.QScrollArea(self)
|
||||
scroll_area.setWidgetResizable(True)
|
||||
|
|
@ -1489,7 +1503,7 @@ class PublishPluginAttrsWidget(QtWidgets.QWidget):
|
|||
|
||||
self._main_layout = main_layout
|
||||
|
||||
self._controller = controller
|
||||
self._controller: AbstractPublisherFrontend = controller
|
||||
self._scroll_area = scroll_area
|
||||
|
||||
self._attr_def_id_to_instances = {}
|
||||
|
|
@ -1635,8 +1649,10 @@ class ProductAttributesWidget(QtWidgets.QWidget):
|
|||
instance_context_changed = QtCore.Signal()
|
||||
convert_requested = QtCore.Signal()
|
||||
|
||||
def __init__(self, controller, parent):
|
||||
super(ProductAttributesWidget, self).__init__(parent)
|
||||
def __init__(
|
||||
self, controller: AbstractPublisherFrontend, parent: QtWidgets.QWidget
|
||||
):
|
||||
super().__init__(parent)
|
||||
|
||||
# TOP PART
|
||||
top_widget = QtWidgets.QWidget(self)
|
||||
|
|
@ -1734,11 +1750,11 @@ class ProductAttributesWidget(QtWidgets.QWidget):
|
|||
thumbnail_widget.thumbnail_created.connect(self._on_thumbnail_create)
|
||||
thumbnail_widget.thumbnail_cleared.connect(self._on_thumbnail_clear)
|
||||
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"instance.thumbnail.changed", self._on_thumbnail_changed
|
||||
)
|
||||
|
||||
self._controller = controller
|
||||
self._controller: AbstractPublisherFrontend = controller
|
||||
|
||||
self._convert_widget = convert_widget
|
||||
|
||||
|
|
@ -1877,7 +1893,7 @@ class CreateNextPageOverlay(QtWidgets.QWidget):
|
|||
clicked = QtCore.Signal()
|
||||
|
||||
def __init__(self, parent):
|
||||
super(CreateNextPageOverlay, self).__init__(parent)
|
||||
super().__init__(parent)
|
||||
self.setCursor(QtCore.Qt.PointingHandCursor)
|
||||
self._arrow_color = (
|
||||
get_objected_colors("font").get_qcolor()
|
||||
|
|
@ -1967,7 +1983,7 @@ class CreateNextPageOverlay(QtWidgets.QWidget):
|
|||
def mousePressEvent(self, event):
|
||||
if event.button() == QtCore.Qt.LeftButton:
|
||||
self._mouse_pressed = True
|
||||
super(CreateNextPageOverlay, self).mousePressEvent(event)
|
||||
super().mousePressEvent(event)
|
||||
|
||||
def mouseReleaseEvent(self, event):
|
||||
if self._mouse_pressed:
|
||||
|
|
@ -1975,7 +1991,7 @@ class CreateNextPageOverlay(QtWidgets.QWidget):
|
|||
if self.rect().contains(event.pos()):
|
||||
self.clicked.emit()
|
||||
|
||||
super(CreateNextPageOverlay, self).mouseReleaseEvent(event)
|
||||
super().mouseReleaseEvent(event)
|
||||
|
||||
def paintEvent(self, event):
|
||||
painter = QtGui.QPainter()
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ import json
|
|||
import time
|
||||
import collections
|
||||
import copy
|
||||
from typing import Optional
|
||||
|
||||
from qtpy import QtWidgets, QtCore, QtGui
|
||||
|
||||
from ayon_core import (
|
||||
|
|
@ -19,7 +21,7 @@ from ayon_core.tools.utils.lib import center_window
|
|||
|
||||
from .constants import ResetKeySequence
|
||||
from .publish_report_viewer import PublishReportViewerWidget
|
||||
from .control import CardMessageTypes
|
||||
from .abstract import CardMessageTypes, AbstractPublisherFrontend
|
||||
from .control_qt import QtPublisherController
|
||||
from .widgets import (
|
||||
OverviewWidget,
|
||||
|
|
@ -48,8 +50,13 @@ class PublisherWindow(QtWidgets.QDialog):
|
|||
footer_border = 8
|
||||
publish_footer_spacer = 2
|
||||
|
||||
def __init__(self, parent=None, controller=None, reset_on_show=None):
|
||||
super(PublisherWindow, self).__init__(parent)
|
||||
def __init__(
|
||||
self,
|
||||
parent: Optional[QtWidgets.QWidget] = None,
|
||||
controller: Optional[AbstractPublisherFrontend] = None,
|
||||
reset_on_show: Optional[bool] = None
|
||||
):
|
||||
super().__init__(parent)
|
||||
|
||||
self.setObjectName("PublishWindow")
|
||||
|
||||
|
|
@ -273,55 +280,55 @@ class PublisherWindow(QtWidgets.QDialog):
|
|||
self._on_create_overlay_button_click
|
||||
)
|
||||
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"instances.refresh.finished", self._on_instances_refresh
|
||||
)
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"publish.reset.finished", self._on_publish_reset
|
||||
)
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"controller.reset.finished", self._on_controller_reset
|
||||
)
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"publish.process.started", self._on_publish_start
|
||||
)
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"publish.has_validated.changed", self._on_publish_validated_change
|
||||
)
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"publish.finished.changed", self._on_publish_finished_change
|
||||
)
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"publish.process.stopped", self._on_publish_stop
|
||||
)
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"show.card.message", self._on_overlay_message
|
||||
)
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"instances.collection.failed", self._on_creator_error
|
||||
)
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"instances.save.failed", self._on_creator_error
|
||||
)
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"instances.remove.failed", self._on_creator_error
|
||||
)
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"instances.create.failed", self._on_creator_error
|
||||
)
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"convertors.convert.failed", self._on_convertor_error
|
||||
)
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"convertors.find.failed", self._on_convertor_error
|
||||
)
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"publish.action.failed", self._on_action_error
|
||||
)
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"export_report.request", self._export_report
|
||||
)
|
||||
controller.event_system.add_callback(
|
||||
controller.register_event_callback(
|
||||
"copy_report.request", self._copy_report
|
||||
)
|
||||
|
||||
|
|
@ -362,7 +369,7 @@ class PublisherWindow(QtWidgets.QDialog):
|
|||
|
||||
self._overlay_object = overlay_object
|
||||
|
||||
self._controller = controller
|
||||
self._controller: AbstractPublisherFrontend = controller
|
||||
|
||||
self._first_show = True
|
||||
self._first_reset = True
|
||||
|
|
@ -386,7 +393,8 @@ class PublisherWindow(QtWidgets.QDialog):
|
|||
self._window_is_visible = False
|
||||
|
||||
@property
|
||||
def controller(self):
|
||||
def controller(self) -> AbstractPublisherFrontend:
|
||||
"""Kept for compatibility with traypublisher."""
|
||||
return self._controller
|
||||
|
||||
def show_and_publish(self, comment=None):
|
||||
|
|
@ -437,7 +445,7 @@ class PublisherWindow(QtWidgets.QDialog):
|
|||
|
||||
def showEvent(self, event):
|
||||
self._window_is_visible = True
|
||||
super(PublisherWindow, self).showEvent(event)
|
||||
super().showEvent(event)
|
||||
if self._first_show:
|
||||
self._first_show = False
|
||||
self._on_first_show()
|
||||
|
|
@ -445,7 +453,7 @@ class PublisherWindow(QtWidgets.QDialog):
|
|||
self._show_timer.start()
|
||||
|
||||
def resizeEvent(self, event):
|
||||
super(PublisherWindow, self).resizeEvent(event)
|
||||
super().resizeEvent(event)
|
||||
self._update_publish_frame_rect()
|
||||
self._update_create_overlay_size()
|
||||
|
||||
|
|
@ -453,24 +461,24 @@ class PublisherWindow(QtWidgets.QDialog):
|
|||
self._window_is_visible = False
|
||||
self._uninstall_app_event_listener()
|
||||
# TODO capture changes and ask user if wants to save changes on close
|
||||
if not self._controller.host_context_has_changed:
|
||||
if not self._controller.host_context_has_changed():
|
||||
self._save_changes(False)
|
||||
self._comment_input.setText("") # clear comment
|
||||
self._reset_on_show = True
|
||||
self._controller.clear_thumbnail_temp_dir_path()
|
||||
# Trigger custom event that should be captured only in UI
|
||||
# - backend (controller) must not be dependent on this event topic!!!
|
||||
self._controller.event_system.emit("main.window.closed", {}, "window")
|
||||
super(PublisherWindow, self).closeEvent(event)
|
||||
self._controller.emit_event("main.window.closed", {}, "window")
|
||||
super().closeEvent(event)
|
||||
|
||||
def leaveEvent(self, event):
|
||||
super(PublisherWindow, self).leaveEvent(event)
|
||||
super().leaveEvent(event)
|
||||
self._update_create_overlay_visibility()
|
||||
|
||||
def eventFilter(self, obj, event):
|
||||
if event.type() == QtCore.QEvent.MouseMove:
|
||||
self._update_create_overlay_visibility(event.globalPos())
|
||||
return super(PublisherWindow, self).eventFilter(obj, event)
|
||||
return super().eventFilter(obj, event)
|
||||
|
||||
def _install_app_event_listener(self):
|
||||
if self._app_event_listener_installed:
|
||||
|
|
@ -520,12 +528,12 @@ class PublisherWindow(QtWidgets.QDialog):
|
|||
)
|
||||
|
||||
if reset_match_result == QtGui.QKeySequence.ExactMatch:
|
||||
if not self.controller.publish_is_running:
|
||||
if not self._controller.publish_is_running:
|
||||
self.reset()
|
||||
event.accept()
|
||||
return
|
||||
|
||||
super(PublisherWindow, self).keyPressEvent(event)
|
||||
super().keyPressEvent(event)
|
||||
|
||||
def _on_overlay_message(self, event):
|
||||
self._overlay_object.add_message(
|
||||
|
|
@ -574,7 +582,7 @@ class PublisherWindow(QtWidgets.QDialog):
|
|||
bool: Save can happen.
|
||||
"""
|
||||
|
||||
if not self._controller.host_context_has_changed:
|
||||
if not self._controller.host_context_has_changed():
|
||||
return True
|
||||
|
||||
title = "Host context changed"
|
||||
|
|
@ -643,7 +651,7 @@ class PublisherWindow(QtWidgets.QDialog):
|
|||
if not force and not self._is_on_details_tab():
|
||||
return
|
||||
|
||||
report_data = self.controller.get_publish_report()
|
||||
report_data = self._controller.get_publish_report()
|
||||
self._publish_details_widget.set_report_data(report_data)
|
||||
|
||||
def _on_help_click(self):
|
||||
|
|
@ -831,7 +839,6 @@ class PublisherWindow(QtWidgets.QDialog):
|
|||
self._set_comment_input_visiblity(True)
|
||||
self._set_publish_overlay_visibility(False)
|
||||
self._set_publish_visibility(False)
|
||||
self._set_footer_enabled(False)
|
||||
self._update_publish_details_widget()
|
||||
|
||||
def _on_controller_reset(self):
|
||||
|
|
@ -885,24 +892,13 @@ class PublisherWindow(QtWidgets.QDialog):
|
|||
self._set_publish_overlay_visibility(False)
|
||||
self._reset_btn.setEnabled(True)
|
||||
self._stop_btn.setEnabled(False)
|
||||
publish_has_crashed = self._controller.publish_has_crashed
|
||||
validate_enabled = not publish_has_crashed
|
||||
publish_enabled = not publish_has_crashed
|
||||
if self._is_on_publish_tab():
|
||||
self._go_to_report_tab()
|
||||
|
||||
if validate_enabled:
|
||||
validate_enabled = not self._controller.publish_has_validated
|
||||
if publish_enabled:
|
||||
if (
|
||||
self._controller.publish_has_validated
|
||||
and self._controller.publish_has_validation_errors
|
||||
):
|
||||
publish_enabled = False
|
||||
|
||||
else:
|
||||
publish_enabled = not self._controller.publish_has_finished
|
||||
|
||||
publish_enabled = self._controller.publish_can_continue()
|
||||
validate_enabled = (
|
||||
publish_enabled and not self._controller.publish_has_validated()
|
||||
)
|
||||
self._validate_btn.setEnabled(validate_enabled)
|
||||
self._publish_btn.setEnabled(publish_enabled)
|
||||
|
||||
|
|
@ -912,12 +908,12 @@ class PublisherWindow(QtWidgets.QDialog):
|
|||
self._update_publish_details_widget()
|
||||
|
||||
def _validate_create_instances(self):
|
||||
if not self._controller.host_is_valid:
|
||||
if not self._controller.is_host_valid():
|
||||
self._set_footer_enabled(True)
|
||||
return
|
||||
|
||||
all_valid = None
|
||||
for instance in self._controller.instances.values():
|
||||
for instance in self._controller.get_instances():
|
||||
if not instance["active"]:
|
||||
continue
|
||||
|
||||
|
|
@ -933,7 +929,7 @@ class PublisherWindow(QtWidgets.QDialog):
|
|||
def _on_instances_refresh(self):
|
||||
self._validate_create_instances()
|
||||
|
||||
context_title = self.controller.get_context_title()
|
||||
context_title = self._controller.get_context_title()
|
||||
self.set_context_label(context_title)
|
||||
self._update_publish_details_widget()
|
||||
|
||||
|
|
@ -1091,7 +1087,7 @@ class ErrorsMessageBox(ErrorMessageBox):
|
|||
self._tabs_widget = None
|
||||
self._stack_layout = None
|
||||
|
||||
super(ErrorsMessageBox, self).__init__(error_title, parent)
|
||||
super().__init__(error_title, parent)
|
||||
|
||||
layout = self.layout()
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ class FoldersQtModel(QtGui.QStandardItemModel):
|
|||
Union[str, None]: Folder id or None if folder is not available.
|
||||
|
||||
"""
|
||||
for folder_id, item in self._items_by_id.values():
|
||||
for folder_id, item in self._items_by_id.items():
|
||||
if item.data(FOLDER_PATH_ROLE) == folder_path:
|
||||
return folder_id
|
||||
return None
|
||||
|
|
@ -165,7 +165,7 @@ class FoldersQtModel(QtGui.QStandardItemModel):
|
|||
folder_items = self._controller.get_folder_items(
|
||||
project_name, FOLDERS_MODEL_SENDER_NAME
|
||||
)
|
||||
folder_type_items = {}
|
||||
folder_type_items = []
|
||||
if hasattr(self._controller, "get_folder_type_items"):
|
||||
folder_type_items = self._controller.get_folder_type_items(
|
||||
project_name, FOLDERS_MODEL_SENDER_NAME
|
||||
|
|
@ -194,7 +194,7 @@ class FoldersQtModel(QtGui.QStandardItemModel):
|
|||
return
|
||||
if thread.failed:
|
||||
# TODO visualize that refresh failed
|
||||
folder_items, folder_type_items = {}, {}
|
||||
folder_items, folder_type_items = {}, []
|
||||
else:
|
||||
folder_items, folder_type_items = thread.get_result()
|
||||
self._fill_items(folder_items, folder_type_items)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue