OP-1117 - added context menu to Launcher actions to skip opening last workfile

Choice is persistent in Local Setting (only in DB, not exposed to GUI yet.)
This commit is contained in:
Petr Kalis 2022-01-14 18:09:41 +01:00
parent f511538b49
commit 75d55b9ac5
8 changed files with 145 additions and 6 deletions

View file

@ -43,6 +43,7 @@ class GlobalHostDataHook(PreLaunchHook):
"env": self.launch_context.env,
"start_last_workfile": self.data.get("start_last_workfile"),
"last_workfile_path": self.data.get("last_workfile_path"),
"log": self.log

View file

@ -40,7 +40,7 @@ class NonPythonHostHook(PreLaunchHook):
)
# Add workfile path if exists
workfile_path = self.data["last_workfile_path"]
if os.path.exists(workfile_path):
if workfile_path and os.path.exists(workfile_path):
new_launch_args.append(workfile_path)
# Append as whole list as these areguments should not be separated

View file

@ -1490,6 +1490,11 @@ def _prepare_last_workfile(data, workdir):
import avalon.api
log = data["log"]
if not data.get("start_last_workfile", True):
log.info("Explicitly forbidden to open last workfile, skipping")
return
_workdir_data = data.get("workdir_data")
if not _workdir_data:
log.info(

View file

@ -62,6 +62,7 @@ class ApplicationAction(api.Action):
icon = None
color = None
order = 0
data = {}
_log = None
required_session_keys = (
@ -103,7 +104,8 @@ class ApplicationAction(api.Action):
self.application.launch(
project_name=project_name,
asset_name=asset_name,
task_name=task_name
task_name=task_name,
**self.data
)
except ApplictionExecutableNotFound as exc:

View file

@ -7,6 +7,7 @@ VARIANT_GROUP_ROLE = QtCore.Qt.UserRole + 2
ACTION_ID_ROLE = QtCore.Qt.UserRole + 3
ANIMATION_START_ROLE = QtCore.Qt.UserRole + 4
ANIMATION_STATE_ROLE = QtCore.Qt.UserRole + 5
FORCE_NOT_OPEN_WORKFILE_ROLE = QtCore.Qt.UserRole + 6
# Animation length in seconds
ANIMATION_LEN = 7

View file

@ -2,7 +2,8 @@ import time
from Qt import QtCore, QtWidgets, QtGui
from .constants import (
ANIMATION_START_ROLE,
ANIMATION_STATE_ROLE
ANIMATION_STATE_ROLE,
FORCE_NOT_OPEN_WORKFILE_ROLE
)
@ -69,6 +70,16 @@ class ActionDelegate(QtWidgets.QStyledItemDelegate):
self._draw_animation(painter, option, index)
super(ActionDelegate, self).paint(painter, option, index)
if index.data(FORCE_NOT_OPEN_WORKFILE_ROLE):
rect = QtCore.QRectF(option.rect.x(), option.rect.height(),
5, 5)
painter.setPen(QtCore.Qt.transparent)
painter.setBrush(QtGui.QColor(200, 0, 0))
painter.drawEllipse(rect)
painter.setBrush(self.extender_bg_brush)
is_group = False
for group_role in self.group_roles:
is_group = index.data(group_role)

View file

@ -8,7 +8,8 @@ from .constants import (
ACTION_ROLE,
GROUP_ROLE,
VARIANT_GROUP_ROLE,
ACTION_ID_ROLE
ACTION_ID_ROLE,
FORCE_NOT_OPEN_WORKFILE_ROLE
)
from .actions import ApplicationAction
from Qt import QtCore, QtGui
@ -16,6 +17,8 @@ from avalon.vendor import qtawesome
from avalon import style, api
from openpype.lib import ApplicationManager
from openpype.settings.lib import get_local_settings, save_local_settings
log = logging.getLogger(__name__)
@ -75,7 +78,8 @@ class ActionModel(QtGui.QStandardItemModel):
"group": None,
"icon": app.icon,
"color": getattr(app, "color", None),
"order": getattr(app, "order", None) or 0
"order": getattr(app, "order", None) or 0,
"data": {}
}
)
@ -179,11 +183,20 @@ class ActionModel(QtGui.QStandardItemModel):
self.beginResetModel()
local_settings = get_local_settings()
items = []
for order in sorted(items_by_order.keys()):
for item in items_by_order[order]:
item_id = str(uuid.uuid4())
item.setData(item_id, ACTION_ID_ROLE)
if self.is_force_not_open_workfile(item,
local_settings):
label = item.text()
label += " (Not opening last workfile)"
item.setData(label, QtCore.Qt.ToolTipRole)
item.setData(True, FORCE_NOT_OPEN_WORKFILE_ROLE)
self.items_by_id[item_id] = item
items.append(item)
@ -222,6 +235,75 @@ class ActionModel(QtGui.QStandardItemModel):
key=lambda action: (action.order, action.name)
)
def update_force_not_open_workfile_settings(self, is_checked, action):
"""Store/remove config for forcing to skip opening last workfile.
Args:
is_checked (bool): True to add, False to remove
action (ApplicationAction)
"""
local_settings = get_local_settings()
actual_data = self._prepare_compare_data(action)
force_not_open_workfile = local_settings.get("force_not_open_workfile",
[])
final_local_sett = local_settings
if is_checked:
if not force_not_open_workfile:
final_local_sett["force_not_open_workfile"] = []
final_local_sett["force_not_open_workfile"].append(actual_data)
else:
final_local_sett["force_not_open_workfile"] = []
for config in force_not_open_workfile:
if config != actual_data:
final_local_sett["force_not_open_workfile"].append(config)
if not final_local_sett["force_not_open_workfile"]:
final_local_sett.pop("force_not_open_workfile")
save_local_settings(final_local_sett)
def is_force_not_open_workfile(self, item, local_settings):
"""Checks if application for task is marked to not open workfile
There might be specific tasks where is unwanted to open workfile right
always (broken file, low performance). This allows artist to mark to
skip opening for combination (project, asset, task_name, app)
Args:
item (QStandardItem)
local_settings (dict)
"""
action = item.data(ACTION_ROLE)
actual_data = self._prepare_compare_data(action)
for config in local_settings.get("force_not_open_workfile", []):
if config == actual_data:
return True
return False
def _prepare_compare_data(self, action):
if isinstance(action, list) and action:
action = action[0]
_session = copy.deepcopy(self.dbcon.Session)
session = {
key: value
for key, value in _session.items()
if value
}
actual_data = {
"app_label": action.label.lower(),
"project_name": session["AVALON_PROJECT"],
"asset": session["AVALON_ASSET"],
"task_name": session["AVALON_TASK"]
}
return actual_data
class ProjectModel(QtGui.QStandardItemModel):
"""List of projects"""

View file

@ -15,7 +15,8 @@ from .constants import (
ACTION_ID_ROLE,
ANIMATION_START_ROLE,
ANIMATION_STATE_ROLE,
ANIMATION_LEN
ANIMATION_LEN,
FORCE_NOT_OPEN_WORKFILE_ROLE
)
@ -96,6 +97,7 @@ class ActionBar(QtWidgets.QWidget):
view.setViewMode(QtWidgets.QListView.IconMode)
view.setResizeMode(QtWidgets.QListView.Adjust)
view.setSelectionMode(QtWidgets.QListView.NoSelection)
view.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
view.setEditTriggers(QtWidgets.QListView.NoEditTriggers)
view.setWrapping(True)
view.setGridSize(QtCore.QSize(70, 75))
@ -135,6 +137,7 @@ class ActionBar(QtWidgets.QWidget):
project_handler.projects_refreshed.connect(self._on_projects_refresh)
view.clicked.connect(self.on_clicked)
view.customContextMenuRequested.connect(self.on_context_menu)
def discover_actions(self):
if self._animation_timer.isActive():
@ -181,6 +184,38 @@ class ActionBar(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
action_item = index.data(ACTION_ROLE)
menu = QtWidgets.QMenu(self.view)
checkbox = QtWidgets.QCheckBox("Force not open last workfile",
menu)
if index.data(FORCE_NOT_OPEN_WORKFILE_ROLE):
checkbox.setChecked(True)
checkbox.stateChanged.connect(
lambda: self.on_checkbox_changed(checkbox.isChecked(),
action_item))
action = QtWidgets.QWidgetAction(menu)
action.setDefaultWidget(checkbox)
menu.addAction(action)
global_point = self.mapToGlobal(point)
action = menu.exec_(global_point)
if not action or not action.data():
return
return
def on_checkbox_changed(self, is_checked, action):
self.model.update_force_not_open_workfile_settings(is_checked, action)
self.discover_actions() # repaint
def on_clicked(self, index):
if not index or not index.isValid():
return
@ -189,6 +224,8 @@ class ActionBar(QtWidgets.QWidget):
is_variant_group = index.data(VARIANT_GROUP_ROLE)
if not is_group and not is_variant_group:
action = index.data(ACTION_ROLE)
if index.data(FORCE_NOT_OPEN_WORKFILE_ROLE):
action.data["start_last_workfile"] = False
self._start_animation(index)
self.action_clicked.emit(action)
return