From 6d678c242b3e27075b10e0057b50c83498bc841b Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 7 Jul 2021 19:53:36 +0200 Subject: [PATCH 01/39] trigger reset on show with small delay so setting ui is visible --- openpype/tools/settings/settings/window.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openpype/tools/settings/settings/window.py b/openpype/tools/settings/settings/window.py index a60a2a1d88..f4428af6ed 100644 --- a/openpype/tools/settings/settings/window.py +++ b/openpype/tools/settings/settings/window.py @@ -94,7 +94,8 @@ class MainWidget(QtWidgets.QWidget): super(MainWidget, self).showEvent(event) if self._reset_on_show: self._reset_on_show = False - self.reset() + # Trigger reset with 100ms delay + QtCore.QTimer.singleShot(100, self.reset) def _show_password_dialog(self): if self._password_dialog: From 4648e145816bf6c517c4063e0aa3eccb90a25911 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 7 Jul 2021 19:54:01 +0200 Subject: [PATCH 02/39] make sure on passed password that window is visible --- openpype/tools/settings/settings/window.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openpype/tools/settings/settings/window.py b/openpype/tools/settings/settings/window.py index f4428af6ed..a3591f292a 100644 --- a/openpype/tools/settings/settings/window.py +++ b/openpype/tools/settings/settings/window.py @@ -108,6 +108,8 @@ class MainWidget(QtWidgets.QWidget): self._password_dialog = None if password_passed: self.reset() + if not self.isVisible(): + self.show() else: self.close() From 179328fbe799668e718e3b0f7b4d6a8c41f31c4c Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 7 Jul 2021 19:58:45 +0200 Subject: [PATCH 03/39] added few titles to dialogs --- openpype/tools/settings/settings/categories.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openpype/tools/settings/settings/categories.py b/openpype/tools/settings/settings/categories.py index 392c749211..cf57785c25 100644 --- a/openpype/tools/settings/settings/categories.py +++ b/openpype/tools/settings/settings/categories.py @@ -289,6 +289,7 @@ class SettingsCategoryWidget(QtWidgets.QWidget): msg = "

".join(warnings) dialog = QtWidgets.QMessageBox(self) + dialog.setWindowTitle("Save warnings") dialog.setText(msg) dialog.setIcon(QtWidgets.QMessageBox.Warning) dialog.exec_() @@ -298,6 +299,7 @@ class SettingsCategoryWidget(QtWidgets.QWidget): except Exception as exc: formatted_traceback = traceback.format_exception(*sys.exc_info()) dialog = QtWidgets.QMessageBox(self) + dialog.setWindowTitle("Unexpected error") msg = "Unexpected error happened!\n\nError: {}".format(str(exc)) dialog.setText(msg) dialog.setDetailedText("\n".join(formatted_traceback)) @@ -387,6 +389,7 @@ class SettingsCategoryWidget(QtWidgets.QWidget): except Exception as exc: formatted_traceback = traceback.format_exception(*sys.exc_info()) dialog = QtWidgets.QMessageBox(self) + dialog.setWindowTitle("Unexpected error") msg = "Unexpected error happened!\n\nError: {}".format(str(exc)) dialog.setText(msg) dialog.setDetailedText("\n".join(formatted_traceback)) From 295e400c81fca122e9dbda7b1b337697e4482b67 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 26 Jul 2021 11:38:50 +0200 Subject: [PATCH 04/39] BaseAction has identifier id added to end of class identifier --- .../modules/ftrack/lib/ftrack_action_handler.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/openpype/modules/ftrack/lib/ftrack_action_handler.py b/openpype/modules/ftrack/lib/ftrack_action_handler.py index 2bff9d8cb3..6994ecc4dd 100644 --- a/openpype/modules/ftrack/lib/ftrack_action_handler.py +++ b/openpype/modules/ftrack/lib/ftrack_action_handler.py @@ -1,4 +1,5 @@ import os +from uuid import uuid4 from .ftrack_base_handler import BaseHandler @@ -29,6 +30,10 @@ class BaseAction(BaseHandler): icon = None type = 'Action' + # Modified identifier used for local actions + _identifier = None + _identifier_id = str(uuid4()) + settings_frack_subkey = "user_handlers" settings_enabled_key = "enabled" @@ -42,6 +47,14 @@ class BaseAction(BaseHandler): super().__init__(session) + def get_identifier(self): + """Modify identifier to trigger the action only on once machine.""" + if self._identifier is None: + self._identifier = "{}.{}".format( + self.identifier, self._identifier_id + ) + return self._identifier + def register(self): ''' Registers the action, subscribing the the discover and launch topics. @@ -60,7 +73,7 @@ class BaseAction(BaseHandler): ' and data.actionIdentifier={0}' ' and source.user.username={1}' ).format( - self.identifier, + self.get_identifier(), self.session.api_user ) self.session.event_hub.subscribe( @@ -86,7 +99,7 @@ class BaseAction(BaseHandler): 'label': self.label, 'variant': self.variant, 'description': self.description, - 'actionIdentifier': self.identifier, + 'actionIdentifier': self.get_identifier(), 'icon': self.icon, }] } From 607cc6e2ea75fb3a711afc5f3d3665bcb9fb8483 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 26 Jul 2021 11:39:05 +0200 Subject: [PATCH 05/39] override `get_identifier` for server action --- openpype/modules/ftrack/lib/ftrack_action_handler.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/openpype/modules/ftrack/lib/ftrack_action_handler.py b/openpype/modules/ftrack/lib/ftrack_action_handler.py index 6994ecc4dd..9d005eb876 100644 --- a/openpype/modules/ftrack/lib/ftrack_action_handler.py +++ b/openpype/modules/ftrack/lib/ftrack_action_handler.py @@ -331,6 +331,12 @@ class ServerAction(BaseAction): settings_frack_subkey = "events" + def get_identifier(self): + """Override default implementation to not add identifier id.""" + if self._identifier is None: + self._identifier = self.identifier + return self._identifier + def register(self): """Register subcription to Ftrack event hub.""" self.session.event_hub.subscribe( @@ -341,5 +347,5 @@ class ServerAction(BaseAction): launch_subscription = ( "topic=ftrack.action.launch and data.actionIdentifier={0}" - ).format(self.identifier) + ).format(self.get_identifier()) self.session.event_hub.subscribe(launch_subscription, self._launch) From e1b10317da98691abc8737e62db9c1baf5d82b84 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 26 Jul 2021 12:00:47 +0200 Subject: [PATCH 06/39] removed all added stuff --- .../ftrack/lib/ftrack_action_handler.py | 24 +++---------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/openpype/modules/ftrack/lib/ftrack_action_handler.py b/openpype/modules/ftrack/lib/ftrack_action_handler.py index 9d005eb876..06152c19f7 100644 --- a/openpype/modules/ftrack/lib/ftrack_action_handler.py +++ b/openpype/modules/ftrack/lib/ftrack_action_handler.py @@ -30,10 +30,6 @@ class BaseAction(BaseHandler): icon = None type = 'Action' - # Modified identifier used for local actions - _identifier = None - _identifier_id = str(uuid4()) - settings_frack_subkey = "user_handlers" settings_enabled_key = "enabled" @@ -47,14 +43,6 @@ class BaseAction(BaseHandler): super().__init__(session) - def get_identifier(self): - """Modify identifier to trigger the action only on once machine.""" - if self._identifier is None: - self._identifier = "{}.{}".format( - self.identifier, self._identifier_id - ) - return self._identifier - def register(self): ''' Registers the action, subscribing the the discover and launch topics. @@ -73,7 +61,7 @@ class BaseAction(BaseHandler): ' and data.actionIdentifier={0}' ' and source.user.username={1}' ).format( - self.get_identifier(), + self.identifier, self.session.api_user ) self.session.event_hub.subscribe( @@ -99,7 +87,7 @@ class BaseAction(BaseHandler): 'label': self.label, 'variant': self.variant, 'description': self.description, - 'actionIdentifier': self.get_identifier(), + 'actionIdentifier': self.identifier, 'icon': self.icon, }] } @@ -331,12 +319,6 @@ class ServerAction(BaseAction): settings_frack_subkey = "events" - def get_identifier(self): - """Override default implementation to not add identifier id.""" - if self._identifier is None: - self._identifier = self.identifier - return self._identifier - def register(self): """Register subcription to Ftrack event hub.""" self.session.event_hub.subscribe( @@ -347,5 +329,5 @@ class ServerAction(BaseAction): launch_subscription = ( "topic=ftrack.action.launch and data.actionIdentifier={0}" - ).format(self.get_identifier()) + ).format(self.identifier) self.session.event_hub.subscribe(launch_subscription, self._launch) From 5c9a7d10486ae543688c4dcee06797dc8323e130 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 26 Jul 2021 12:21:14 +0200 Subject: [PATCH 07/39] added discover and launch identifier properties for actions --- .../action_applications.py | 2 +- .../ftrack/lib/ftrack_action_handler.py | 34 +++++++++++++++++-- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/openpype/modules/ftrack/event_handlers_user/action_applications.py b/openpype/modules/ftrack/event_handlers_user/action_applications.py index 23c96e1b9f..58ea3c5671 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_applications.py +++ b/openpype/modules/ftrack/event_handlers_user/action_applications.py @@ -29,7 +29,7 @@ class AppplicationsAction(BaseAction): icon_url = os.environ.get("OPENPYPE_STATICS_SERVER") def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) + super(AppplicationsAction, self).__init__(*args, **kwargs) self.application_manager = ApplicationManager() self.dbcon = AvalonMongoDB() diff --git a/openpype/modules/ftrack/lib/ftrack_action_handler.py b/openpype/modules/ftrack/lib/ftrack_action_handler.py index 06152c19f7..878eac6627 100644 --- a/openpype/modules/ftrack/lib/ftrack_action_handler.py +++ b/openpype/modules/ftrack/lib/ftrack_action_handler.py @@ -30,6 +30,10 @@ class BaseAction(BaseHandler): icon = None type = 'Action' + _identifier_id = str(uuid4()) + _discover_identifier = None + _launch_identifier = None + settings_frack_subkey = "user_handlers" settings_enabled_key = "enabled" @@ -43,6 +47,22 @@ class BaseAction(BaseHandler): super().__init__(session) + @property + def discover_identifier(self): + if self._discover_identifier is None: + self._discover_identifier = "{}.{}".format( + self.identifier, self._identifier_id + ) + return self._discover_identifier + + @property + def launch_identifier(self): + if self._launch_identifier is None: + self._launch_identifier = "{}.{}".format( + self.identifier, self._identifier_id + ) + return self._launch_identifier + def register(self): ''' Registers the action, subscribing the the discover and launch topics. @@ -61,7 +81,7 @@ class BaseAction(BaseHandler): ' and data.actionIdentifier={0}' ' and source.user.username={1}' ).format( - self.identifier, + self.launch_identifier, self.session.api_user ) self.session.event_hub.subscribe( @@ -87,7 +107,7 @@ class BaseAction(BaseHandler): 'label': self.label, 'variant': self.variant, 'description': self.description, - 'actionIdentifier': self.identifier, + 'actionIdentifier': self.discover_identifier, 'icon': self.icon, }] } @@ -319,6 +339,14 @@ class ServerAction(BaseAction): settings_frack_subkey = "events" + @property + def discover_identifier(self): + return self.identifier + + @property + def launch_identifier(self): + return self.identifier + def register(self): """Register subcription to Ftrack event hub.""" self.session.event_hub.subscribe( @@ -329,5 +357,5 @@ class ServerAction(BaseAction): launch_subscription = ( "topic=ftrack.action.launch and data.actionIdentifier={0}" - ).format(self.identifier) + ).format(self.launch_identifier) self.session.event_hub.subscribe(launch_subscription, self._launch) From 281e6645ffcc7af8dc39f57e5f8d49fc6b34ae87 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 27 Jul 2021 12:26:37 +0200 Subject: [PATCH 08/39] emit workfile arguments as list instead of path --- openpype/tools/workfiles/app.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/tools/workfiles/app.py b/openpype/tools/workfiles/app.py index d567e26d74..f98085e579 100644 --- a/openpype/tools/workfiles/app.py +++ b/openpype/tools/workfiles/app.py @@ -695,14 +695,14 @@ class FilesWidget(QtWidgets.QWidget): file_path = os.path.join(self.root, work_file) - pipeline.emit("before.workfile.save", file_path) + pipeline.emit("before.workfile.save", [file_path]) self._enter_session() # Make sure we are in the right session self.host.save_file(file_path) self.set_asset_task(self._asset, self._task) - pipeline.emit("after.workfile.save", file_path) + pipeline.emit("after.workfile.save", [file_path]) self.workfile_created.emit(file_path) From 74c74dc97d53d52536a82c2591102534aafb1d57 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 27 Jul 2021 15:13:31 +0200 Subject: [PATCH 09/39] Settings: adding workfile tool start attribute --- .../defaults/project_settings/global.json | 7 ++++ .../schemas/schema_global_tools.json | 32 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/openpype/settings/defaults/project_settings/global.json b/openpype/settings/defaults/project_settings/global.json index 43053c38c0..636acc0d17 100644 --- a/openpype/settings/defaults/project_settings/global.json +++ b/openpype/settings/defaults/project_settings/global.json @@ -260,6 +260,13 @@ "enabled": true } ], + "open_workfile_tool_on_startup": [ + { + "hosts": [], + "tasks": [], + "enabled": false + } + ], "sw_folders": { "compositing": [ "nuke", diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json index 8c92a45a56..a9fe27c24b 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json @@ -97,6 +97,38 @@ ] } }, + { + "type": "list", + "key": "open_workfile_tool_on_startup", + "label": "Open workfile tool on launch", + "is_group": true, + "use_label_wrap": true, + "object_type": { + "type": "dict", + "children": [ + { + "type": "hosts-enum", + "key": "hosts", + "label": "Hosts", + "multiselection": true + }, + { + "key": "tasks", + "label": "Tasks", + "type": "list", + "object_type": "text" + }, + { + "type": "splitter" + }, + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + } + ] + } + }, { "type": "dict-modifiable", "collapsible": true, From 08b0b3035a02d1a41274a8b0e9b4f64f419b5434 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 27 Jul 2021 15:14:03 +0200 Subject: [PATCH 10/39] global: adding workfile start at launch attribute search func --- openpype/lib/applications.py | 119 +++++++++++++++++++++++++---------- 1 file changed, 86 insertions(+), 33 deletions(-) diff --git a/openpype/lib/applications.py b/openpype/lib/applications.py index e1b304a351..01bc0cddf8 100644 --- a/openpype/lib/applications.py +++ b/openpype/lib/applications.py @@ -1302,10 +1302,18 @@ def _prepare_last_workfile(data, workdir): ) data["start_last_workfile"] = start_last_workfile + workfile_startup = should_workfile_tool_start( + project_name, app.host_name, task_name + ) + data["workfile_startup"] = workfile_startup + # Store boolean as "0"(False) or "1"(True) data["env"]["AVALON_OPEN_LAST_WORKFILE"] = ( str(int(bool(start_last_workfile))) ) + data["env"]["WORKFILE_STARTUP"] = ( + str(int(bool(workfile_startup))) + ) _sub_msg = "" if start_last_workfile else " not" log.debug( @@ -1344,40 +1352,9 @@ def _prepare_last_workfile(data, workdir): data["last_workfile_path"] = last_workfile_path -def should_start_last_workfile( - project_name, host_name, task_name, default_output=False +def get_option_from_preset( + startup_presets, host_name, task_name, default_output ): - """Define if host should start last version workfile if possible. - - Default output is `False`. Can be overriden with environment variable - `AVALON_OPEN_LAST_WORKFILE`, valid values without case sensitivity are - `"0", "1", "true", "false", "yes", "no"`. - - Args: - project_name (str): Name of project. - host_name (str): Name of host which is launched. In avalon's - application context it's value stored in app definition under - key `"application_dir"`. Is not case sensitive. - task_name (str): Name of task which is used for launching the host. - Task name is not case sensitive. - - Returns: - bool: True if host should start workfile. - - """ - - project_settings = get_project_settings(project_name) - startup_presets = ( - project_settings - ["global"] - ["tools"] - ["Workfiles"] - ["last_workfile_on_startup"] - ) - - if not startup_presets: - return default_output - host_name_lowered = host_name.lower() task_name_lowered = task_name.lower() @@ -1421,6 +1398,82 @@ def should_start_last_workfile( return default_output +def should_start_last_workfile( + project_name, host_name, task_name, default_output=False +): + """Define if host should start last version workfile if possible. + + Default output is `False`. Can be overriden with environment variable + `AVALON_OPEN_LAST_WORKFILE`, valid values without case sensitivity are + `"0", "1", "true", "false", "yes", "no"`. + + Args: + project_name (str): Name of project. + host_name (str): Name of host which is launched. In avalon's + application context it's value stored in app definition under + key `"application_dir"`. Is not case sensitive. + task_name (str): Name of task which is used for launching the host. + Task name is not case sensitive. + + Returns: + bool: True if host should start workfile. + + """ + + project_settings = get_project_settings(project_name) + startup_presets = ( + project_settings + ["global"] + ["tools"] + ["Workfiles"] + ["last_workfile_on_startup"] + ) + + if not startup_presets: + return default_output + + return get_option_from_preset( + startup_presets, host_name, task_name, default_output) + + +def should_workfile_tool_start( + project_name, host_name, task_name, default_output=False +): + """Define if host should start workfile tool at host launch. + + Default output is `False`. Can be overriden with environment variable + `WORKFILE_STARTUP`, valid values without case sensitivity are + `"0", "1", "true", "false", "yes", "no"`. + + Args: + project_name (str): Name of project. + host_name (str): Name of host which is launched. In avalon's + application context it's value stored in app definition under + key `"application_dir"`. Is not case sensitive. + task_name (str): Name of task which is used for launching the host. + Task name is not case sensitive. + + Returns: + bool: True if host should start workfile. + + """ + + project_settings = get_project_settings(project_name) + startup_presets = ( + project_settings + ["global"] + ["tools"] + ["Workfiles"] + ["open_workfile_tool_on_startup"] + ) + + if not startup_presets: + return default_output + + return get_option_from_preset( + startup_presets, host_name, task_name, default_output) + + def compile_list_of_regexes(in_list): """Convert strings in entered list to compiled regex objects.""" regexes = list() From d23f31da7edf5723d571a774e200f0056bbb0032 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 27 Jul 2021 15:14:22 +0200 Subject: [PATCH 11/39] Nuke: refactory workfile launch callback --- openpype/hosts/nuke/api/lib.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index eefbcc5d20..fce92f08d5 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -1660,9 +1660,13 @@ def find_free_space_to_paste_nodes( def launch_workfiles_app(): '''Function letting start workfiles after start of host ''' - # get state from settings - open_at_start = get_current_project_settings()["nuke"].get( - "general", {}).get("open_workfile_at_start") + from openpype.lib import ( + env_value_to_bool + ) + # get all imortant settings + open_at_start = env_value_to_bool( + env_key="WORKFILE_STARTUP", + default=None) # return if none is defined if not open_at_start: From bee136e29a3fbcdd0d24438e3cfda47d3eebf3fd Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 27 Jul 2021 15:22:11 +0200 Subject: [PATCH 12/39] added process identifier to base handler --- openpype/modules/ftrack/lib/ftrack_base_handler.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/openpype/modules/ftrack/lib/ftrack_base_handler.py b/openpype/modules/ftrack/lib/ftrack_base_handler.py index 011ce8db9d..b8be287a03 100644 --- a/openpype/modules/ftrack/lib/ftrack_base_handler.py +++ b/openpype/modules/ftrack/lib/ftrack_base_handler.py @@ -2,6 +2,7 @@ import os import tempfile import json import functools +import uuid import datetime import traceback import time @@ -36,6 +37,7 @@ class BaseHandler(object): - a verbose descriptive text for you action - icon in ftrack ''' + _process_id = None # Default priority is 100 priority = 100 # Type is just for logging purpose (e.g.: Action, Event, Application,...) @@ -70,6 +72,13 @@ class BaseHandler(object): self.register = self.register_decorator(self.register) self.launch = self.launch_log(self.launch) + @staticmethod + def process_identifier(): + """Helper property to have """ + if not BaseHandler._process_id: + BaseHandler._process_id = str(uuid.uuid4()) + return BaseHandler._process_id + # Decorator def register_decorator(self, func): @functools.wraps(func) From 7737dbb326d26ae2e25f3b037f7b814d0f2cf6d5 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 27 Jul 2021 15:22:58 +0200 Subject: [PATCH 13/39] use process_identifier instead of uuid for each action --- openpype/modules/ftrack/lib/ftrack_action_handler.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/openpype/modules/ftrack/lib/ftrack_action_handler.py b/openpype/modules/ftrack/lib/ftrack_action_handler.py index 878eac6627..1c9faec6bf 100644 --- a/openpype/modules/ftrack/lib/ftrack_action_handler.py +++ b/openpype/modules/ftrack/lib/ftrack_action_handler.py @@ -1,5 +1,4 @@ import os -from uuid import uuid4 from .ftrack_base_handler import BaseHandler @@ -30,7 +29,6 @@ class BaseAction(BaseHandler): icon = None type = 'Action' - _identifier_id = str(uuid4()) _discover_identifier = None _launch_identifier = None @@ -51,7 +49,7 @@ class BaseAction(BaseHandler): def discover_identifier(self): if self._discover_identifier is None: self._discover_identifier = "{}.{}".format( - self.identifier, self._identifier_id + self.identifier, self.process_identifier() ) return self._discover_identifier @@ -59,7 +57,7 @@ class BaseAction(BaseHandler): def launch_identifier(self): if self._launch_identifier is None: self._launch_identifier = "{}.{}".format( - self.identifier, self._identifier_id + self.identifier, self.process_identifier() ) return self._launch_identifier From 72a2bdfd04e5d060057ddbb28f5c4458db612b13 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 27 Jul 2021 15:23:43 +0200 Subject: [PATCH 14/39] AppplicationsAction is using process identifier --- .../action_applications.py | 63 ++++++++++++++----- 1 file changed, 48 insertions(+), 15 deletions(-) diff --git a/openpype/modules/ftrack/event_handlers_user/action_applications.py b/openpype/modules/ftrack/event_handlers_user/action_applications.py index 58ea3c5671..74d14c2fc4 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_applications.py +++ b/openpype/modules/ftrack/event_handlers_user/action_applications.py @@ -11,21 +11,14 @@ from avalon.api import AvalonMongoDB class AppplicationsAction(BaseAction): - """Application Action class. - - Args: - session (ftrack_api.Session): Session where action will be registered. - label (str): A descriptive string identifing your action. - varaint (str, optional): To group actions together, give them the same - label and specify a unique variant per action. - identifier (str): An unique identifier for app. - description (str): A verbose descriptive text for you action. - icon (str): Url path to icon which will be shown in Ftrack web. - """ + """Applications Action class.""" type = "Application" label = "Application action" - identifier = "pype_app.{}.".format(str(uuid4())) + + identifier = "openpype_app" + _launch_identifier_with_id = None + icon_url = os.environ.get("OPENPYPE_STATICS_SERVER") def __init__(self, *args, **kwargs): @@ -34,6 +27,28 @@ class AppplicationsAction(BaseAction): self.application_manager = ApplicationManager() self.dbcon = AvalonMongoDB() + @property + def discover_identifier(self): + if self._discover_identifier is None: + self._discover_identifier = "{}.{}".format( + self.identifier, self.process_identifier() + ) + return self._discover_identifier + + @property + def launch_identifier(self): + if self._launch_identifier is None: + self._launch_identifier = "{}.*".format(self.identifier) + return self._launch_identifier + + @property + def launch_identifier_with_id(self): + if self._launch_identifier_with_id is None: + self._launch_identifier_with_id = "{}.{}".format( + self.identifier, self.process_identifier() + ) + return self._launch_identifier_with_id + def construct_requirements_validations(self): # Override validation as this action does not need them return @@ -56,7 +71,7 @@ class AppplicationsAction(BaseAction): " and data.actionIdentifier={0}" " and source.user.username={1}" ).format( - self.identifier + "*", + self.launch_identifier, self.session.api_user ) self.session.event_hub.subscribe( @@ -136,12 +151,29 @@ class AppplicationsAction(BaseAction): "label": app.group.label, "variant": app.label, "description": None, - "actionIdentifier": self.identifier + app_name, + "actionIdentifier": "{}.{}".format( + self.launch_identifier_with_id, app_name + ), "icon": app_icon }) return items + def _launch(self, event): + event_identifier = event["data"]["actionIdentifier"] + # Check if identifier is same + # - show message that acion may not be triggered on this machine + if event_identifier.startswith(self.launch_identifier_with_id): + return BaseAction._launch(self, event) + + return { + "success": False, + "message": ( + "There are running more OpenPype processes" + " where Application can be launched." + ) + } + def launch(self, session, entities, event): """Callback method for the custom action. @@ -162,7 +194,8 @@ class AppplicationsAction(BaseAction): *event* the unmodified original event """ identifier = event["data"]["actionIdentifier"] - app_name = identifier[len(self.identifier):] + id_identifier_len = len(self.launch_identifier_with_id) + 1 + app_name = identifier[id_identifier_len:] entity = entities[0] From 8ebdbd4f932ad1171257f40a754c9b04d3dc2a7b Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 27 Jul 2021 15:25:50 +0200 Subject: [PATCH 15/39] added helper LocalAction as base which tells user that is not launched because was launched in other process --- .../ftrack/lib/ftrack_action_handler.py | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/openpype/modules/ftrack/lib/ftrack_action_handler.py b/openpype/modules/ftrack/lib/ftrack_action_handler.py index 1c9faec6bf..b24fe5f12a 100644 --- a/openpype/modules/ftrack/lib/ftrack_action_handler.py +++ b/openpype/modules/ftrack/lib/ftrack_action_handler.py @@ -328,6 +328,78 @@ class BaseAction(BaseHandler): return True +class LocalAction(BaseAction): + """Action that warn user when more Processes with same action are running. + + Action is launched all the time but if id does not match id of current + instanace then message is shown to user. + + Handy for actions where matters if is executed on specific machine. + """ + _full_launch_identifier = None + + @property + def discover_identifier(self): + if self._discover_identifier is None: + self._discover_identifier = "{}.{}".format( + self.identifier, self.process_identifier() + ) + return self._discover_identifier + + @property + def launch_identifier(self): + """Catch all topics with same identifier.""" + if self._launch_identifier is None: + self._launch_identifier = "{}.*".format(self.identifier) + return self._launch_identifier + + @property + def full_launch_identifier(self): + """Catch all topics with same identifier.""" + if self._full_launch_identifier is None: + self._full_launch_identifier = "{}.{}".format( + self.identifier, self.process_identifier() + ) + return self._full_launch_identifier + + def _discover(self, event): + entities = self._translate_event(event) + if not entities: + return + + accepts = self.discover(self.session, entities, event) + if not accepts: + return + + self.log.debug("Discovering action with selection: {0}".format( + event["data"].get("selection", []) + )) + + return { + "items": [{ + "label": self.label, + "variant": self.variant, + "description": self.description, + "actionIdentifier": self.discover_identifier, + "icon": self.icon, + }] + } + + def _launch(self, event): + event_identifier = event["data"]["actionIdentifier"] + # Check if identifier is same + # - show message that acion may not be triggered on this machine + if event_identifier != self.full_launch_identifier: + return { + "success": False, + "message": ( + "There are running more OpenPype processes" + " where this action could be launched." + ) + } + return super(LocalAction, self)._launch(event) + + class ServerAction(BaseAction): """Action class meant to be used on event server. From b911f3f0655551a829f5f15ec4efc199f4720e44 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 27 Jul 2021 15:32:04 +0200 Subject: [PATCH 16/39] fix prepare project which triggers different action --- .../ftrack/event_handlers_user/action_prepare_project.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openpype/modules/ftrack/event_handlers_user/action_prepare_project.py b/openpype/modules/ftrack/event_handlers_user/action_prepare_project.py index ea0bfa2971..4b42500e8f 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_prepare_project.py +++ b/openpype/modules/ftrack/event_handlers_user/action_prepare_project.py @@ -428,9 +428,11 @@ class PrepareProjectLocal(BaseAction): # Trigger create project structure action if create_project_structure_checked: - self.trigger_action( - self.create_project_structure_identifier, event + trigger_identifier = "{}.{}".format( + self.create_project_structure_identifier, + self.process_identifier() ) + self.trigger_action(trigger_identifier, event) return True From a4089715b456c0700aa04dee9d4bd51ff6efedf6 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 27 Jul 2021 15:42:12 +0200 Subject: [PATCH 17/39] fix where I run action --- .../ftrack/event_handlers_user/action_where_run_show.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openpype/modules/ftrack/event_handlers_user/action_where_run_show.py b/openpype/modules/ftrack/event_handlers_user/action_where_run_show.py index 4ce1a439a3..b8b49e86cb 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_where_run_show.py +++ b/openpype/modules/ftrack/event_handlers_user/action_where_run_show.py @@ -24,6 +24,10 @@ class ActionShowWhereIRun(BaseAction): return False + @property + def launch_identifier(self): + return self.identifier + def launch(self, session, entities, event): # Don't show info when was launch from this session if session.event_hub.id == event.get("data", {}).get("event_hub_id"): From 7a9fb009e3f6e857a7d35e1f60c7000a668e644a Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 27 Jul 2021 16:37:24 +0200 Subject: [PATCH 18/39] define host names in class definition --- openpype/settings/entities/enum_entity.py | 34 ++++++++++++----------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/openpype/settings/entities/enum_entity.py b/openpype/settings/entities/enum_entity.py index d306eca7ef..8055b0167f 100644 --- a/openpype/settings/entities/enum_entity.py +++ b/openpype/settings/entities/enum_entity.py @@ -1,3 +1,4 @@ +import copy from .input_entities import InputEntity from .exceptions import EntitySchemaError from .lib import ( @@ -118,6 +119,22 @@ class HostsEnumEntity(BaseEnumEntity): implementation instead of application name. """ schema_types = ["hosts-enum"] + all_host_names = [ + "aftereffects", + "blender", + "celaction", + "fusion", + "harmony", + "hiero", + "houdini", + "maya", + "nuke", + "photoshop", + "resolve", + "tvpaint", + "unreal", + "standalonepublisher" + ] def _item_initalization(self): self.multiselection = self.schema_data.get("multiselection", True) @@ -126,22 +143,7 @@ class HostsEnumEntity(BaseEnumEntity): ) custom_labels = self.schema_data.get("custom_labels") or {} - host_names = [ - "aftereffects", - "blender", - "celaction", - "fusion", - "harmony", - "hiero", - "houdini", - "maya", - "nuke", - "photoshop", - "resolve", - "tvpaint", - "unreal", - "standalonepublisher" - ] + host_names = copy.deepcopy(self.all_host_names) if self.use_empty_value: host_names.insert(0, "") # Add default label for empty value if not available From e450dc1254c4da191c258480d6a71f3fa5a2d555 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 27 Jul 2021 16:37:30 +0200 Subject: [PATCH 19/39] use_empty_value can't be set if multiselection is used --- openpype/settings/entities/enum_entity.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/openpype/settings/entities/enum_entity.py b/openpype/settings/entities/enum_entity.py index 8055b0167f..f223898f83 100644 --- a/openpype/settings/entities/enum_entity.py +++ b/openpype/settings/entities/enum_entity.py @@ -138,9 +138,12 @@ class HostsEnumEntity(BaseEnumEntity): def _item_initalization(self): self.multiselection = self.schema_data.get("multiselection", True) - self.use_empty_value = self.schema_data.get( - "use_empty_value", not self.multiselection - ) + use_empty_value = False + if not self.multiselection: + use_empty_value = self.schema_data.get( + "use_empty_value", use_empty_value + ) + self.use_empty_value = use_empty_value custom_labels = self.schema_data.get("custom_labels") or {} host_names = copy.deepcopy(self.all_host_names) From caa7ff4993d5f0c446472b11d7005e26f394c9bc Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 27 Jul 2021 16:37:56 +0200 Subject: [PATCH 20/39] added hosts_filter attribute to explicitly filter available host names --- openpype/settings/entities/enum_entity.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/openpype/settings/entities/enum_entity.py b/openpype/settings/entities/enum_entity.py index f223898f83..a712d71806 100644 --- a/openpype/settings/entities/enum_entity.py +++ b/openpype/settings/entities/enum_entity.py @@ -144,9 +144,18 @@ class HostsEnumEntity(BaseEnumEntity): "use_empty_value", use_empty_value ) self.use_empty_value = use_empty_value + + hosts_filter = self.schema_data.get("hosts_filter") or [] + self.hosts_filter = hosts_filter + custom_labels = self.schema_data.get("custom_labels") or {} host_names = copy.deepcopy(self.all_host_names) + if hosts_filter: + for host_name in tuple(host_names): + if host_name not in hosts_filter: + host_names.remove(host_name) + if self.use_empty_value: host_names.insert(0, "") # Add default label for empty value if not available From 916262da41242ec1dfbf8e8a99857dcccfe48bcd Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 27 Jul 2021 16:38:23 +0200 Subject: [PATCH 21/39] added schema validations for hosts filter --- openpype/settings/entities/enum_entity.py | 38 +++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/openpype/settings/entities/enum_entity.py b/openpype/settings/entities/enum_entity.py index a712d71806..4f6a2886bc 100644 --- a/openpype/settings/entities/enum_entity.py +++ b/openpype/settings/entities/enum_entity.py @@ -187,6 +187,44 @@ class HostsEnumEntity(BaseEnumEntity): # GUI attribute self.placeholder = self.schema_data.get("placeholder") + def schema_validations(self): + if self.hosts_filter: + enum_len = len(self.enum_items) + if ( + enum_len == 0 + or (enum_len == 1 and self.use_empty_value) + ): + joined_filters = ", ".join([ + '"{}"'.format(item) + for item in self.hosts_filter + ]) + reason = ( + "All host names were removed after applying" + " host filters. {}" + ).format(joined_filters) + raise EntitySchemaError(self, reason) + + invalid_filters = set() + for item in self.hosts_filter: + if item not in self.all_host_names: + invalid_filters.add(item) + + if invalid_filters: + joined_filters = ", ".join([ + '"{}"'.format(item) + for item in self.hosts_filter + ]) + expected_hosts = ", ".join([ + '"{}"'.format(item) + for item in self.all_host_names + ]) + self.log.warning(( + "Host filters containt invalid host names:" + " \"{}\" Expected values are {}" + ).format(joined_filters, expected_hosts)) + + super(HostsEnumEntity, self).schema_validations() + class AppsEnumEntity(BaseEnumEntity): schema_types = ["apps-enum"] From 6d6f355e000f117be98407eead47192340a18661 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 27 Jul 2021 16:38:42 +0200 Subject: [PATCH 22/39] added hosts_filter for workfiles on startup --- .../schemas/schema_global_tools.json | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json index 8c92a45a56..02ce8d6e88 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json @@ -78,7 +78,21 @@ "type": "hosts-enum", "key": "hosts", "label": "Hosts", - "multiselection": true + "multiselection": true, + "hosts_filter": [ + "aftereffects", + "blender", + "celaction", + "fusion", + "harmony", + "hiero", + "houdini", + "maya", + "nuke", + "photoshop", + "resolve", + "tvpaint" + ] }, { "key": "tasks", From dbfd8bff2f7e786a1691a108b11409773232d1e7 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 27 Jul 2021 16:41:21 +0200 Subject: [PATCH 23/39] added docs to readme --- openpype/settings/entities/schemas/README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/openpype/settings/entities/schemas/README.md b/openpype/settings/entities/schemas/README.md index d457e44e74..fae9b390fd 100644 --- a/openpype/settings/entities/schemas/README.md +++ b/openpype/settings/entities/schemas/README.md @@ -379,6 +379,9 @@ How output of the schema could look like on save: - multiselection can be allowed with setting key `"multiselection"` to `True` (Default: `False`) - it is possible to add empty value (represented with empty string) with setting `"use_empty_value"` to `True` (Default: `False`) - it is possible to set `"custom_labels"` for host names where key `""` is empty value (Default: `{}`) +- to filter host names it is required to define `"hosts_filter"` which is list of host names that will be available + - do not pass empty string if `use_empty_value` is enabled + - ignoring host names would be more dangerous in some cases ``` { "key": "host", @@ -389,7 +392,10 @@ How output of the schema could look like on save: "custom_labels": { "": "N/A", "nuke": "Nuke" - } + }, + "hosts_filter": [ + "nuke" + ] } ``` From ac55f02fb6ed8198bb516398b3386dab451682c2 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 27 Jul 2021 16:46:35 +0200 Subject: [PATCH 24/39] added nreal back to hosts filter --- .../schemas/projects_schema/schemas/schema_global_tools.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json index 02ce8d6e88..fa0e705cbf 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json @@ -91,7 +91,8 @@ "nuke", "photoshop", "resolve", - "tvpaint" + "tvpaint", + "unreal" ] }, { From f1ef07c7d1e128a01660227e12475999afc7abdb Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 23 Jun 2021 11:26:05 +0200 Subject: [PATCH 25/39] fix receivers discovery --- openpype/tools/settings/settings/window.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openpype/tools/settings/settings/window.py b/openpype/tools/settings/settings/window.py index a60a2a1d88..54f8ec0a11 100644 --- a/openpype/tools/settings/settings/window.py +++ b/openpype/tools/settings/settings/window.py @@ -141,7 +141,10 @@ class MainWidget(QtWidgets.QWidget): # Don't show dialog if there are not registered slots for # `trigger_restart` signal. # - For example when settings are runnin as standalone tool - if self.receivers(self.trigger_restart) < 1: + # - PySide2 and PyQt5 compatible way how to find out + method_index = self.metaObject().indexOfMethod("trigger_restart()") + method = self.metaObject().method(method_index) + if not self.isSignalConnected(method): return dialog = RestartDialog(self) From e7a3b0633aad0b0e8185a0aca78334cdfa86281f Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 23 Jun 2021 11:56:56 +0200 Subject: [PATCH 26/39] fix log viewer stylesheet of qtoolbutton --- openpype/modules/log_viewer/tray/app.py | 8 ++++---- openpype/modules/log_viewer/tray/widgets.py | 5 ++--- openpype/style/style.css | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/openpype/modules/log_viewer/tray/app.py b/openpype/modules/log_viewer/tray/app.py index 9aab37cd20..1e8d6483cd 100644 --- a/openpype/modules/log_viewer/tray/app.py +++ b/openpype/modules/log_viewer/tray/app.py @@ -7,12 +7,13 @@ class LogsWindow(QtWidgets.QWidget): def __init__(self, parent=None): super(LogsWindow, self).__init__(parent) - self.setStyleSheet(style.load_stylesheet()) + self.setWindowTitle("Logs viewer") + self.resize(1400, 800) log_detail = OutputWidget(parent=self) logs_widget = LogsWidget(log_detail, parent=self) - main_layout = QtWidgets.QHBoxLayout() + main_layout = QtWidgets.QHBoxLayout(self) log_splitter = QtWidgets.QSplitter(self) log_splitter.setOrientation(QtCore.Qt.Horizontal) @@ -24,5 +25,4 @@ class LogsWindow(QtWidgets.QWidget): self.logs_widget = logs_widget self.log_detail = log_detail - self.setLayout(main_layout) - self.setWindowTitle("Logs") + self.setStyleSheet(style.load_stylesheet()) diff --git a/openpype/modules/log_viewer/tray/widgets.py b/openpype/modules/log_viewer/tray/widgets.py index b9a8499a4c..d906a1b6ad 100644 --- a/openpype/modules/log_viewer/tray/widgets.py +++ b/openpype/modules/log_viewer/tray/widgets.py @@ -76,13 +76,12 @@ class CustomCombo(QtWidgets.QWidget): toolbutton.setMenu(toolmenu) toolbutton.setPopupMode(QtWidgets.QToolButton.MenuButtonPopup) + toolbutton.setProperty("popup_mode", "1") - layout = QtWidgets.QHBoxLayout() + layout = QtWidgets.QHBoxLayout(self) layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(toolbutton) - self.setLayout(layout) - toolmenu.selection_changed.connect(self.selection_changed) self.toolbutton = toolbutton diff --git a/openpype/style/style.css b/openpype/style/style.css index c57b9a8da6..8391fcd0ae 100644 --- a/openpype/style/style.css +++ b/openpype/style/style.css @@ -97,7 +97,7 @@ QToolButton:disabled { background: {color:bg-buttons-disabled}; } -QToolButton[popupMode="1"] { +QToolButton[popupMode="1"], QToolButton[popup_mode="1"] { /* make way for the popup button */ padding-right: 20px; border: 1px solid {color:bg-buttons}; From ae20e682f839a5595b879333a4430676c0f8a203 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 23 Jun 2021 12:11:17 +0200 Subject: [PATCH 27/39] added comment --- openpype/modules/log_viewer/tray/widgets.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openpype/modules/log_viewer/tray/widgets.py b/openpype/modules/log_viewer/tray/widgets.py index d906a1b6ad..669acf4b67 100644 --- a/openpype/modules/log_viewer/tray/widgets.py +++ b/openpype/modules/log_viewer/tray/widgets.py @@ -76,6 +76,9 @@ class CustomCombo(QtWidgets.QWidget): toolbutton.setMenu(toolmenu) toolbutton.setPopupMode(QtWidgets.QToolButton.MenuButtonPopup) + + # Fake popupMenu property as PySide2 does not store it's value as + # integer but as enum object toolbutton.setProperty("popup_mode", "1") layout = QtWidgets.QHBoxLayout(self) From 16a258bc2764956dd3bfdc2eedc2d90416ca3761 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 23 Jun 2021 12:38:50 +0200 Subject: [PATCH 28/39] fixed popupMode property --- openpype/modules/log_viewer/tray/widgets.py | 4 ---- openpype/style/style.css | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/openpype/modules/log_viewer/tray/widgets.py b/openpype/modules/log_viewer/tray/widgets.py index 669acf4b67..0f77a7f111 100644 --- a/openpype/modules/log_viewer/tray/widgets.py +++ b/openpype/modules/log_viewer/tray/widgets.py @@ -77,10 +77,6 @@ class CustomCombo(QtWidgets.QWidget): toolbutton.setMenu(toolmenu) toolbutton.setPopupMode(QtWidgets.QToolButton.MenuButtonPopup) - # Fake popupMenu property as PySide2 does not store it's value as - # integer but as enum object - toolbutton.setProperty("popup_mode", "1") - layout = QtWidgets.QHBoxLayout(self) layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(toolbutton) diff --git a/openpype/style/style.css b/openpype/style/style.css index 8391fcd0ae..8dffd98e43 100644 --- a/openpype/style/style.css +++ b/openpype/style/style.css @@ -97,7 +97,7 @@ QToolButton:disabled { background: {color:bg-buttons-disabled}; } -QToolButton[popupMode="1"], QToolButton[popup_mode="1"] { +QToolButton[popupMode="1"], QToolButton[popupMode="MenuButtonPopup"] { /* make way for the popup button */ padding-right: 20px; border: 1px solid {color:bg-buttons}; From 65be35d86c6126d5a4b38ade3317fb9bb19fe613 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Fri, 25 Jun 2021 10:15:49 +0200 Subject: [PATCH 29/39] use parenting to skip style set --- .../tools/standalonepublish/widgets/widget_component_item.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/openpype/tools/standalonepublish/widgets/widget_component_item.py b/openpype/tools/standalonepublish/widgets/widget_component_item.py index 186c8024db..de3cde50cd 100644 --- a/openpype/tools/standalonepublish/widgets/widget_component_item.py +++ b/openpype/tools/standalonepublish/widgets/widget_component_item.py @@ -1,7 +1,6 @@ import os from Qt import QtCore, QtGui, QtWidgets from .resources import get_resource -from avalon import style class ComponentItem(QtWidgets.QFrame): @@ -61,7 +60,7 @@ class ComponentItem(QtWidgets.QFrame): name="menu", size=QtCore.QSize(22, 22) ) - self.action_menu = QtWidgets.QMenu() + self.action_menu = QtWidgets.QMenu(self.btn_action_menu) expanding_sizePolicy = QtWidgets.QSizePolicy( QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding @@ -229,7 +228,6 @@ class ComponentItem(QtWidgets.QFrame): if not self.btn_action_menu.isVisible(): self.btn_action_menu.setVisible(True) self.btn_action_menu.clicked.connect(self.show_actions) - self.action_menu.setStyleSheet(style.load_stylesheet()) def set_repre_name_valid(self, valid): self.has_valid_repre = valid From 324560a6e93c2a7a2c3de2f2f51e3452eb7e3a20 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 27 Jul 2021 17:41:21 +0200 Subject: [PATCH 30/39] hide outlines of selected item --- openpype/modules/log_viewer/tray/widgets.py | 5 ++--- openpype/style/style.css | 5 +++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/openpype/modules/log_viewer/tray/widgets.py b/openpype/modules/log_viewer/tray/widgets.py index 0f77a7f111..5a67780413 100644 --- a/openpype/modules/log_viewer/tray/widgets.py +++ b/openpype/modules/log_viewer/tray/widgets.py @@ -139,7 +139,6 @@ class LogsWidget(QtWidgets.QWidget): filter_layout.addWidget(refresh_btn) view = QtWidgets.QTreeView(self) - view.setAllColumnsShowFocus(True) view.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers) layout = QtWidgets.QVBoxLayout(self) @@ -227,9 +226,9 @@ class OutputWidget(QtWidgets.QWidget): super(OutputWidget, self).__init__(parent=parent) layout = QtWidgets.QVBoxLayout(self) - show_timecode_checkbox = QtWidgets.QCheckBox("Show timestamp") + show_timecode_checkbox = QtWidgets.QCheckBox("Show timestamp", self) - output_text = QtWidgets.QTextEdit() + output_text = QtWidgets.QTextEdit(self) output_text.setReadOnly(True) # output_text.setLineWrapMode(QtWidgets.QTextEdit.FixedPixelWidth) diff --git a/openpype/style/style.css b/openpype/style/style.css index 8dffd98e43..12ea960859 100644 --- a/openpype/style/style.css +++ b/openpype/style/style.css @@ -340,6 +340,11 @@ QAbstractItemView { selection-background-color: transparent; } +QAbstractItemView::item { + /* `border: none` hide outline of selected item. */ + border: none; +} + QAbstractItemView:disabled{ background: {color:bg-view-disabled}; alternate-background-color: {color:bg-view-alternate-disabled}; From 23ee92ecb974c1f8c51ad9a170f38b4f9792af61 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 28 Jul 2021 10:52:15 +0200 Subject: [PATCH 31/39] labels are transparent by default --- openpype/style/style.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openpype/style/style.css b/openpype/style/style.css index 12ea960859..b955bdc2a6 100644 --- a/openpype/style/style.css +++ b/openpype/style/style.css @@ -35,6 +35,10 @@ QWidget:disabled { color: {color:font-disabled}; } +QLabel { + background: transparent; +} + /* Inputs */ QAbstractSpinBox, QLineEdit, QPlainTextEdit, QTextEdit { border: 1px solid {color:border}; From b4c27aa5d28488b37ad5a9578aa8caed6e17ff24 Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Wed, 28 Jul 2021 11:11:46 +0100 Subject: [PATCH 32/39] Update pre_copy_template_workfile.py Spelling correction --- openpype/hooks/pre_copy_template_workfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hooks/pre_copy_template_workfile.py b/openpype/hooks/pre_copy_template_workfile.py index 29a522f933..5c56d721e8 100644 --- a/openpype/hooks/pre_copy_template_workfile.py +++ b/openpype/hooks/pre_copy_template_workfile.py @@ -49,7 +49,7 @@ class CopyTemplateWorkfile(PreLaunchHook): )) return - self.log.info("Last workfile does not exits.") + self.log.info("Last workfile does not exist.") project_name = self.data["project_name"] asset_name = self.data["asset_name"] From 6a2bd167b5fdadf6283dbfdbc783cb44c1efbab4 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 28 Jul 2021 14:08:41 +0200 Subject: [PATCH 33/39] global: better env var name --- openpype/lib/applications.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openpype/lib/applications.py b/openpype/lib/applications.py index 01bc0cddf8..ada194f15f 100644 --- a/openpype/lib/applications.py +++ b/openpype/lib/applications.py @@ -1311,7 +1311,7 @@ def _prepare_last_workfile(data, workdir): data["env"]["AVALON_OPEN_LAST_WORKFILE"] = ( str(int(bool(start_last_workfile))) ) - data["env"]["WORKFILE_STARTUP"] = ( + data["env"]["OPENPYPE_WORKFILE_TOOL_ON_START"] = ( str(int(bool(workfile_startup))) ) @@ -1352,7 +1352,7 @@ def _prepare_last_workfile(data, workdir): data["last_workfile_path"] = last_workfile_path -def get_option_from_preset( +def get_option_from_settings( startup_presets, host_name, task_name, default_output ): host_name_lowered = host_name.lower() @@ -1432,7 +1432,7 @@ def should_start_last_workfile( if not startup_presets: return default_output - return get_option_from_preset( + return get_option_from_settings( startup_presets, host_name, task_name, default_output) @@ -1442,7 +1442,7 @@ def should_workfile_tool_start( """Define if host should start workfile tool at host launch. Default output is `False`. Can be overriden with environment variable - `WORKFILE_STARTUP`, valid values without case sensitivity are + `OPENPYPE_WORKFILE_TOOL_ON_START`, valid values without case sensitivity are `"0", "1", "true", "false", "yes", "no"`. Args: @@ -1470,7 +1470,7 @@ def should_workfile_tool_start( if not startup_presets: return default_output - return get_option_from_preset( + return get_option_from_settings( startup_presets, host_name, task_name, default_output) From 95b7ee57ec0952c6bcaa829ec63ab0d36bb6032a Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 28 Jul 2021 14:09:11 +0200 Subject: [PATCH 34/39] settings: add filter to host which are supported now --- .../schemas/projects_schema/schemas/schema_global_tools.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json index 211a8d0057..9e39eeb39e 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json @@ -125,7 +125,10 @@ "type": "hosts-enum", "key": "hosts", "label": "Hosts", - "multiselection": true + "multiselection": true, + "hosts_filter": [ + "nuke" + ] }, { "key": "tasks", From 9f018cb6fb840551fbb084eb263b3cf96dc00a94 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 28 Jul 2021 14:09:29 +0200 Subject: [PATCH 35/39] nuke: improving env var name --- openpype/hosts/nuke/api/lib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index 442c0122be..7e7cd27f90 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -1665,7 +1665,7 @@ def launch_workfiles_app(): ) # get all imortant settings open_at_start = env_value_to_bool( - env_key="WORKFILE_STARTUP", + env_key="OPENPYPE_WORKFILE_TOOL_ON_START", default=None) # return if none is defined From 490ec264b3c147562ba10ea39b46d70ca47c0029 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 29 Jul 2021 08:43:08 +0100 Subject: [PATCH 36/39] Normalize path returned from Workfiles. --- openpype/tools/workfiles/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/tools/workfiles/app.py b/openpype/tools/workfiles/app.py index d567e26d74..6b56322140 100644 --- a/openpype/tools/workfiles/app.py +++ b/openpype/tools/workfiles/app.py @@ -693,7 +693,7 @@ class FilesWidget(QtWidgets.QWidget): ) return - file_path = os.path.join(self.root, work_file) + file_path = os.path.join(os.path.normpath(self.root), work_file) pipeline.emit("before.workfile.save", file_path) From 03a894ac9503c254eb7fb0c0c082a53c54a10b3f Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 29 Jul 2021 09:24:35 +0100 Subject: [PATCH 37/39] Allow Multiple Notes to run on tasks. --- .../ftrack/event_handlers_user/action_multiple_notes.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/openpype/modules/ftrack/event_handlers_user/action_multiple_notes.py b/openpype/modules/ftrack/event_handlers_user/action_multiple_notes.py index 8db65fe39b..666e7efaef 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_multiple_notes.py +++ b/openpype/modules/ftrack/event_handlers_user/action_multiple_notes.py @@ -9,14 +9,15 @@ class MultipleNotes(BaseAction): #: Action label. label = 'Multiple Notes' #: Action description. - description = 'Add same note to multiple Asset Versions' + description = 'Add same note to multiple entities' icon = statics_icon("ftrack", "action_icons", "MultipleNotes.svg") def discover(self, session, entities, event): ''' Validation ''' + valid_entity_types = ['assetversion', 'task'] valid = True for entity in entities: - if entity.entity_type.lower() != 'assetversion': + if entity.entity_type.lower() not in valid_entity_types: valid = False break return valid @@ -58,7 +59,7 @@ class MultipleNotes(BaseAction): splitter = { 'type': 'label', - 'value': '{}'.format(200*"-") + 'value': '{}'.format(200 * "-") } items = [] From 02780730d62fe5d05037bd20ecc1cebb05a9b9e1 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 29 Jul 2021 09:34:30 +0100 Subject: [PATCH 38/39] Check for multiple selection. --- .../ftrack/event_handlers_user/action_multiple_notes.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/openpype/modules/ftrack/event_handlers_user/action_multiple_notes.py b/openpype/modules/ftrack/event_handlers_user/action_multiple_notes.py index 666e7efaef..f5af044de0 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_multiple_notes.py +++ b/openpype/modules/ftrack/event_handlers_user/action_multiple_notes.py @@ -14,12 +14,19 @@ class MultipleNotes(BaseAction): def discover(self, session, entities, event): ''' Validation ''' - valid_entity_types = ['assetversion', 'task'] valid = True + + # Check for multiple selection. + if len(entities) < 2: + valid = False + + # Check for valid entities. + valid_entity_types = ['assetversion', 'task'] for entity in entities: if entity.entity_type.lower() not in valid_entity_types: valid = False break + return valid def interface(self, session, entities, event): From 7ec2cf735252c01b912049eec8a58c737651d04d Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 30 Jul 2021 12:12:56 +0100 Subject: [PATCH 39/39] Expose stop timer through rest api. --- openpype/modules/timers_manager/rest_api.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/openpype/modules/timers_manager/rest_api.py b/openpype/modules/timers_manager/rest_api.py index 975c1a91f9..ac8d8b7b74 100644 --- a/openpype/modules/timers_manager/rest_api.py +++ b/openpype/modules/timers_manager/rest_api.py @@ -3,6 +3,7 @@ from openpype.api import Logger log = Logger().get_logger("Event processor") + class TimersManagerModuleRestApi: """ REST API endpoint used for calling from hosts when context change @@ -22,6 +23,11 @@ class TimersManagerModuleRestApi: self.prefix + "/start_timer", self.start_timer ) + self.server_manager.add_route( + "POST", + self.prefix + "/stop_timer", + self.stop_timer + ) async def start_timer(self, request): data = await request.json() @@ -38,3 +44,7 @@ class TimersManagerModuleRestApi: self.module.stop_timers() self.module.start_timer(project_name, asset_name, task_name, hierarchy) return Response(status=200) + + async def stop_timer(self, request): + self.module.stop_timers() + return Response(status=200)