mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-26 13:52:15 +01:00
remove applications action logic
This commit is contained in:
parent
ddad178dd6
commit
172fc27fa0
4 changed files with 8 additions and 341 deletions
|
|
@ -307,22 +307,6 @@ class AbstractLauncherFrontEnd(AbstractLauncherCommon):
|
|||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def set_application_force_not_open_workfile(
|
||||
self, project_name, folder_id, task_id, action_ids, enabled
|
||||
):
|
||||
"""This is application action related to force not open last workfile.
|
||||
|
||||
Args:
|
||||
project_name (Union[str, None]): Project name.
|
||||
folder_id (Union[str, None]): Folder id.
|
||||
task_id (Union[str, None]): Task id.
|
||||
action_ids (Iterable[str]): Action identifiers.
|
||||
enabled (bool): New value of force not open workfile.
|
||||
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def refresh(self):
|
||||
"""Refresh everything, models, ui etc.
|
||||
|
|
|
|||
|
|
@ -135,12 +135,7 @@ class BaseLauncherController(
|
|||
return self._actions_model.get_action_items(
|
||||
project_name, folder_id, task_id)
|
||||
|
||||
def set_application_force_not_open_workfile(
|
||||
self, project_name, folder_id, task_id, action_ids, enabled
|
||||
):
|
||||
self._actions_model.set_application_force_not_open_workfile(
|
||||
project_name, folder_id, task_id, action_ids, enabled
|
||||
)
|
||||
|
||||
def trigger_action(self, project_name, folder_id, task_id, identifier):
|
||||
self._actions_model.trigger_action(
|
||||
|
|
|
|||
|
|
@ -1,117 +1,12 @@
|
|||
import os
|
||||
|
||||
from ayon_core import resources
|
||||
from ayon_core.lib import Logger, AYONSettingsRegistry
|
||||
from ayon_core.addon import AddonsManager
|
||||
from ayon_core.pipeline.actions import (
|
||||
discover_launcher_actions,
|
||||
LauncherAction,
|
||||
LauncherActionSelection,
|
||||
register_launcher_action_path,
|
||||
)
|
||||
from ayon_core.pipeline.workfile import should_use_last_workfile_on_launch
|
||||
|
||||
try:
|
||||
# Available since applications addon 0.2.4
|
||||
from ayon_applications.action import ApplicationAction
|
||||
except ImportError:
|
||||
# Backwards compatibility from 0.3.3 (24/06/10)
|
||||
# TODO: Remove in future releases
|
||||
class ApplicationAction(LauncherAction):
|
||||
"""Action to launch an application.
|
||||
|
||||
Application action based on 'ApplicationManager' system.
|
||||
|
||||
Handling of applications in launcher is not ideal and should be
|
||||
completely redone from scratch. This is just a temporary solution
|
||||
to keep backwards compatibility with AYON launcher.
|
||||
|
||||
Todos:
|
||||
Move handling of errors to frontend.
|
||||
"""
|
||||
|
||||
# Application object
|
||||
application = None
|
||||
# Action attributes
|
||||
name = None
|
||||
label = None
|
||||
label_variant = None
|
||||
group = None
|
||||
icon = None
|
||||
color = None
|
||||
order = 0
|
||||
data = {}
|
||||
project_settings = {}
|
||||
project_entities = {}
|
||||
|
||||
_log = None
|
||||
|
||||
@property
|
||||
def log(self):
|
||||
if self._log is None:
|
||||
self._log = Logger.get_logger(self.__class__.__name__)
|
||||
return self._log
|
||||
|
||||
def is_compatible(self, selection):
|
||||
if not selection.is_task_selected:
|
||||
return False
|
||||
|
||||
project_entity = self.project_entities[selection.project_name]
|
||||
apps = project_entity["attrib"].get("applications")
|
||||
if not apps or self.application.full_name not in apps:
|
||||
return False
|
||||
|
||||
project_settings = self.project_settings[selection.project_name]
|
||||
only_available = project_settings["applications"]["only_available"]
|
||||
if only_available and not self.application.find_executable():
|
||||
return False
|
||||
return True
|
||||
|
||||
def _show_message_box(self, title, message, details=None):
|
||||
from qtpy import QtWidgets, QtGui
|
||||
from ayon_core import style
|
||||
|
||||
dialog = QtWidgets.QMessageBox()
|
||||
icon = QtGui.QIcon(resources.get_ayon_icon_filepath())
|
||||
dialog.setWindowIcon(icon)
|
||||
dialog.setStyleSheet(style.load_stylesheet())
|
||||
dialog.setWindowTitle(title)
|
||||
dialog.setText(message)
|
||||
if details:
|
||||
dialog.setDetailedText(details)
|
||||
dialog.exec_()
|
||||
|
||||
def process(self, selection, **kwargs):
|
||||
"""Process the full Application action"""
|
||||
|
||||
from ayon_applications import (
|
||||
ApplicationExecutableNotFound,
|
||||
ApplicationLaunchFailed,
|
||||
)
|
||||
|
||||
try:
|
||||
self.application.launch(
|
||||
project_name=selection.project_name,
|
||||
folder_path=selection.folder_path,
|
||||
task_name=selection.task_name,
|
||||
**self.data
|
||||
)
|
||||
|
||||
except ApplicationExecutableNotFound as exc:
|
||||
details = exc.details
|
||||
msg = exc.msg
|
||||
log_msg = str(msg)
|
||||
if details:
|
||||
log_msg += "\n" + details
|
||||
self.log.warning(log_msg)
|
||||
self._show_message_box(
|
||||
"Application executable not found", msg, details
|
||||
)
|
||||
|
||||
except ApplicationLaunchFailed as exc:
|
||||
msg = str(exc)
|
||||
self.log.warning(msg, exc_info=True)
|
||||
self._show_message_box("Application launch failed", msg)
|
||||
|
||||
|
||||
# class Action:
|
||||
|
|
@ -160,9 +55,6 @@ class ActionItem:
|
|||
action if it has same 'label' and have set 'variant_label'.
|
||||
icon (dict[str, str]): Icon definition.
|
||||
order (int): Action ordering.
|
||||
is_application (bool): Is action application action.
|
||||
force_not_open_workfile (bool): Force not open workfile. Application
|
||||
related.
|
||||
full_label (Optional[str]): Full label, if not set it is generated
|
||||
from 'label' and 'variant_label'.
|
||||
"""
|
||||
|
|
@ -174,8 +66,6 @@ class ActionItem:
|
|||
variant_label,
|
||||
icon,
|
||||
order,
|
||||
is_application,
|
||||
force_not_open_workfile,
|
||||
full_label=None
|
||||
):
|
||||
self.identifier = identifier
|
||||
|
|
@ -183,8 +73,6 @@ class ActionItem:
|
|||
self.variant_label = variant_label
|
||||
self.icon = icon
|
||||
self.order = order
|
||||
self.is_application = is_application
|
||||
self.force_not_open_workfile = force_not_open_workfile
|
||||
self._full_label = full_label
|
||||
|
||||
def copy(self):
|
||||
|
|
@ -206,8 +94,6 @@ class ActionItem:
|
|||
"variant_label": self.variant_label,
|
||||
"icon": self.icon,
|
||||
"order": self.order,
|
||||
"is_application": self.is_application,
|
||||
"force_not_open_workfile": self.force_not_open_workfile,
|
||||
"full_label": self._full_label,
|
||||
}
|
||||
|
||||
|
|
@ -264,8 +150,6 @@ class ActionsModel:
|
|||
controller (AbstractLauncherBackend): Controller instance.
|
||||
"""
|
||||
|
||||
_not_open_workfile_reg_key = "force_not_open_workfile"
|
||||
|
||||
def __init__(self, controller):
|
||||
self._controller = controller
|
||||
|
||||
|
|
@ -275,8 +159,6 @@ class ActionsModel:
|
|||
self._actions = None
|
||||
self._action_items = {}
|
||||
|
||||
self._launcher_tool_reg = AYONSettingsRegistry("launcher_tool")
|
||||
|
||||
self._addons_manager = None
|
||||
|
||||
@property
|
||||
|
|
@ -294,34 +176,6 @@ class ActionsModel:
|
|||
self._get_action_objects()
|
||||
self._controller.emit_event("actions.refresh.finished")
|
||||
|
||||
def _should_start_last_workfile(
|
||||
self,
|
||||
project_name,
|
||||
task_id,
|
||||
identifier,
|
||||
host_name,
|
||||
not_open_workfile_actions
|
||||
):
|
||||
if identifier in not_open_workfile_actions:
|
||||
return not not_open_workfile_actions[identifier]
|
||||
|
||||
task_name = None
|
||||
task_type = None
|
||||
if task_id is not None:
|
||||
task_entity = self._controller.get_task_entity(
|
||||
project_name, task_id
|
||||
)
|
||||
task_name = task_entity["name"]
|
||||
task_type = task_entity["taskType"]
|
||||
|
||||
output = should_use_last_workfile_on_launch(
|
||||
project_name,
|
||||
host_name,
|
||||
task_name,
|
||||
task_type
|
||||
)
|
||||
return output
|
||||
|
||||
def get_action_items(self, project_name, folder_id, task_id):
|
||||
"""Get actions for project.
|
||||
|
||||
|
|
@ -332,46 +186,18 @@ class ActionsModel:
|
|||
|
||||
Returns:
|
||||
list[ActionItem]: List of actions.
|
||||
|
||||
"""
|
||||
not_open_workfile_actions = self._get_no_last_workfile_for_context(
|
||||
project_name, folder_id, task_id)
|
||||
selection = self._prepare_selection(project_name, folder_id, task_id)
|
||||
output = []
|
||||
action_items = self._get_action_items(project_name)
|
||||
for identifier, action in self._get_action_objects().items():
|
||||
if not action.is_compatible(selection):
|
||||
continue
|
||||
if action.is_compatible(selection):
|
||||
output.append(action_items[identifier])
|
||||
|
||||
action_item = action_items[identifier]
|
||||
# Handling of 'force_not_open_workfile' for applications
|
||||
if action_item.is_application:
|
||||
action_item = action_item.copy()
|
||||
start_last_workfile = self._should_start_last_workfile(
|
||||
project_name,
|
||||
task_id,
|
||||
identifier,
|
||||
action.application.host_name,
|
||||
not_open_workfile_actions
|
||||
)
|
||||
action_item.force_not_open_workfile = (
|
||||
not start_last_workfile
|
||||
)
|
||||
|
||||
output.append(action_item)
|
||||
return output
|
||||
|
||||
def set_application_force_not_open_workfile(
|
||||
self, project_name, folder_id, task_id, action_ids, enabled
|
||||
):
|
||||
no_workfile_reg_data = self._get_no_last_workfile_reg_data()
|
||||
project_data = no_workfile_reg_data.setdefault(project_name, {})
|
||||
folder_data = project_data.setdefault(folder_id, {})
|
||||
task_data = folder_data.setdefault(task_id, {})
|
||||
for action_id in action_ids:
|
||||
task_data[action_id] = enabled
|
||||
self._launcher_tool_reg.set_item(
|
||||
self._not_open_workfile_reg_key, no_workfile_reg_data
|
||||
)
|
||||
|
||||
def trigger_action(self, project_name, folder_id, task_id, identifier):
|
||||
selection = self._prepare_selection(project_name, folder_id, task_id)
|
||||
|
|
@ -390,18 +216,6 @@ class ActionsModel:
|
|||
"full_label": action_label,
|
||||
}
|
||||
)
|
||||
if isinstance(action, ApplicationAction):
|
||||
per_action = self._get_no_last_workfile_for_context(
|
||||
project_name, folder_id, task_id
|
||||
)
|
||||
start_last_workfile = self._should_start_last_workfile(
|
||||
project_name,
|
||||
task_id,
|
||||
identifier,
|
||||
action.application.host_name,
|
||||
per_action
|
||||
)
|
||||
action.data["start_last_workfile"] = start_last_workfile
|
||||
|
||||
action.process(selection)
|
||||
except Exception as exc:
|
||||
|
|
@ -424,27 +238,6 @@ class ActionsModel:
|
|||
self._addons_manager = AddonsManager()
|
||||
return self._addons_manager
|
||||
|
||||
def _get_no_last_workfile_reg_data(self):
|
||||
try:
|
||||
no_workfile_reg_data = self._launcher_tool_reg.get_item(
|
||||
self._not_open_workfile_reg_key)
|
||||
except ValueError:
|
||||
no_workfile_reg_data = {}
|
||||
self._launcher_tool_reg.set_item(
|
||||
self._not_open_workfile_reg_key, no_workfile_reg_data)
|
||||
return no_workfile_reg_data
|
||||
|
||||
def _get_no_last_workfile_for_context(
|
||||
self, project_name, folder_id, task_id
|
||||
):
|
||||
not_open_workfile_reg_data = self._get_no_last_workfile_reg_data()
|
||||
return (
|
||||
not_open_workfile_reg_data
|
||||
.get(project_name, {})
|
||||
.get(folder_id, {})
|
||||
.get(task_id, {})
|
||||
)
|
||||
|
||||
def _prepare_selection(self, project_name, folder_id, task_id):
|
||||
project_entity = None
|
||||
if project_name:
|
||||
|
|
@ -470,7 +263,6 @@ class ActionsModel:
|
|||
register_launcher_action_path(path)
|
||||
self._discovered_actions = (
|
||||
discover_launcher_actions()
|
||||
+ self._get_applications_action_classes()
|
||||
)
|
||||
return self._discovered_actions
|
||||
|
||||
|
|
@ -498,10 +290,9 @@ class ActionsModel:
|
|||
|
||||
action_items = {}
|
||||
for identifier, action in self._get_action_objects().items():
|
||||
is_application = isinstance(action, ApplicationAction)
|
||||
# Backwards compatibility from 0.3.3 (24/06/10)
|
||||
# TODO: Remove in future releases
|
||||
if is_application and hasattr(action, "project_settings"):
|
||||
if hasattr(action, "project_settings"):
|
||||
action.project_entities[project_name] = project_entity
|
||||
action.project_settings[project_name] = project_settings
|
||||
|
||||
|
|
@ -515,45 +306,7 @@ class ActionsModel:
|
|||
variant_label,
|
||||
icon,
|
||||
action.order,
|
||||
is_application,
|
||||
False
|
||||
)
|
||||
action_items[identifier] = item
|
||||
self._action_items[project_name] = action_items
|
||||
return action_items
|
||||
|
||||
def _get_applications_action_classes(self):
|
||||
addons_manager = self._get_addons_manager()
|
||||
applications_addon = addons_manager.get_enabled_addon("applications")
|
||||
if hasattr(applications_addon, "get_applications_action_classes"):
|
||||
return applications_addon.get_applications_action_classes()
|
||||
|
||||
# Backwards compatibility from 0.3.3 (24/06/10)
|
||||
# TODO: Remove in future releases
|
||||
actions = []
|
||||
if applications_addon is None:
|
||||
return actions
|
||||
|
||||
manager = applications_addon.get_applications_manager()
|
||||
for full_name, application in manager.applications.items():
|
||||
if not application.enabled:
|
||||
continue
|
||||
|
||||
action = type(
|
||||
"app_{}".format(full_name),
|
||||
(ApplicationAction,),
|
||||
{
|
||||
"identifier": "application.{}".format(full_name),
|
||||
"application": application,
|
||||
"name": application.name,
|
||||
"label": application.group.label,
|
||||
"label_variant": application.label,
|
||||
"group": None,
|
||||
"icon": application.icon,
|
||||
"color": getattr(application, "color", None),
|
||||
"order": getattr(application, "order", None) or 0,
|
||||
"data": {}
|
||||
}
|
||||
)
|
||||
actions.append(action)
|
||||
return actions
|
||||
|
|
|
|||
|
|
@ -11,12 +11,10 @@ from .resources import get_options_image_path
|
|||
ANIMATION_LEN = 7
|
||||
|
||||
ACTION_ID_ROLE = QtCore.Qt.UserRole + 1
|
||||
ACTION_IS_APPLICATION_ROLE = QtCore.Qt.UserRole + 2
|
||||
ACTION_IS_GROUP_ROLE = QtCore.Qt.UserRole + 3
|
||||
ACTION_SORT_ROLE = QtCore.Qt.UserRole + 4
|
||||
ANIMATION_START_ROLE = QtCore.Qt.UserRole + 5
|
||||
ANIMATION_STATE_ROLE = QtCore.Qt.UserRole + 6
|
||||
FORCE_NOT_OPEN_WORKFILE_ROLE = QtCore.Qt.UserRole + 7
|
||||
ACTION_IS_GROUP_ROLE = QtCore.Qt.UserRole + 2
|
||||
ACTION_SORT_ROLE = QtCore.Qt.UserRole + 3
|
||||
ANIMATION_START_ROLE = QtCore.Qt.UserRole + 4
|
||||
ANIMATION_STATE_ROLE = QtCore.Qt.UserRole + 5
|
||||
|
||||
|
||||
def _variant_label_sort_getter(action_item):
|
||||
|
|
@ -144,11 +142,6 @@ class ActionsQtModel(QtGui.QStandardItemModel):
|
|||
item.setData(icon, QtCore.Qt.DecorationRole)
|
||||
item.setData(is_group, ACTION_IS_GROUP_ROLE)
|
||||
item.setData(action_item.order, ACTION_SORT_ROLE)
|
||||
item.setData(
|
||||
action_item.is_application, ACTION_IS_APPLICATION_ROLE)
|
||||
item.setData(
|
||||
action_item.force_not_open_workfile,
|
||||
FORCE_NOT_OPEN_WORKFILE_ROLE)
|
||||
items_by_id[action_item.identifier] = item
|
||||
action_items_by_id[action_item.identifier] = action_item
|
||||
|
||||
|
|
@ -263,13 +256,6 @@ class ActionDelegate(QtWidgets.QStyledItemDelegate):
|
|||
|
||||
super(ActionDelegate, self).paint(painter, option, index)
|
||||
|
||||
if index.data(FORCE_NOT_OPEN_WORKFILE_ROLE):
|
||||
rect = QtCore.QRectF(
|
||||
option.rect.x(), option.rect.y() + option.rect.height(), 5, 5)
|
||||
painter.setPen(QtCore.Qt.NoPen)
|
||||
painter.setBrush(QtGui.QColor(200, 0, 0))
|
||||
painter.drawEllipse(rect)
|
||||
|
||||
if not index.data(ACTION_IS_GROUP_ROLE):
|
||||
return
|
||||
|
||||
|
|
@ -360,14 +346,11 @@ class ActionsWidget(QtWidgets.QWidget):
|
|||
animation_timer.timeout.connect(self._on_animation)
|
||||
|
||||
view.clicked.connect(self._on_clicked)
|
||||
view.customContextMenuRequested.connect(self._on_context_menu)
|
||||
model.refreshed.connect(self._on_model_refresh)
|
||||
|
||||
self._animated_items = set()
|
||||
self._animation_timer = animation_timer
|
||||
|
||||
self._context_menu = None
|
||||
|
||||
self._flick = flick
|
||||
self._view = view
|
||||
self._model = model
|
||||
|
|
@ -416,54 +399,6 @@ class ActionsWidget(QtWidgets.QWidget):
|
|||
self._animated_items.add(action_id)
|
||||
self._animation_timer.start()
|
||||
|
||||
def _on_context_menu(self, point):
|
||||
"""Creates menu to force skip opening last workfile."""
|
||||
index = self._view.indexAt(point)
|
||||
if not index.isValid():
|
||||
return
|
||||
|
||||
if not index.data(ACTION_IS_APPLICATION_ROLE):
|
||||
return
|
||||
|
||||
menu = QtWidgets.QMenu(self._view)
|
||||
checkbox = QtWidgets.QCheckBox(
|
||||
"Skip opening last workfile.", menu)
|
||||
if index.data(FORCE_NOT_OPEN_WORKFILE_ROLE):
|
||||
checkbox.setChecked(True)
|
||||
|
||||
action_id = index.data(ACTION_ID_ROLE)
|
||||
is_group = index.data(ACTION_IS_GROUP_ROLE)
|
||||
if is_group:
|
||||
action_items = self._model.get_group_items(action_id)
|
||||
else:
|
||||
action_items = [self._model.get_action_item_by_id(action_id)]
|
||||
action_ids = {action_item.identifier for action_item in action_items}
|
||||
checkbox.stateChanged.connect(
|
||||
lambda: self._on_checkbox_changed(
|
||||
action_ids, checkbox.isChecked()
|
||||
)
|
||||
)
|
||||
action = QtWidgets.QWidgetAction(menu)
|
||||
action.setDefaultWidget(checkbox)
|
||||
|
||||
menu.addAction(action)
|
||||
|
||||
self._context_menu = menu
|
||||
global_point = self.mapToGlobal(point)
|
||||
menu.exec_(global_point)
|
||||
self._context_menu = None
|
||||
|
||||
def _on_checkbox_changed(self, action_ids, is_checked):
|
||||
if self._context_menu is not None:
|
||||
self._context_menu.close()
|
||||
|
||||
project_name = self._model.get_selected_project_name()
|
||||
folder_id = self._model.get_selected_folder_id()
|
||||
task_id = self._model.get_selected_task_id()
|
||||
self._controller.set_application_force_not_open_workfile(
|
||||
project_name, folder_id, task_id, action_ids, is_checked)
|
||||
self._model.refresh()
|
||||
|
||||
def _on_clicked(self, index):
|
||||
if not index or not index.isValid():
|
||||
return
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue