From 3daa0749d1a40eb0c22214fb69cc5ef76965b65d Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 5 Oct 2023 15:08:31 +0200 Subject: [PATCH] AYON Launcher tool: Fix skip last workfile boolean (#5700) * reverse the boolean to skip last workfile * remove 'start_last_workfile' key to keep logic based on settings * change 'skip_last_workfile' for all variants of DCC * fix context menu on ungrouped items * better sort of action items --- openpype/tools/ayon_launcher/abstract.py | 4 +- openpype/tools/ayon_launcher/control.py | 4 +- .../tools/ayon_launcher/models/actions.py | 10 +++-- .../tools/ayon_launcher/ui/actions_widget.py | 37 +++++++++++++++++-- 4 files changed, 45 insertions(+), 10 deletions(-) diff --git a/openpype/tools/ayon_launcher/abstract.py b/openpype/tools/ayon_launcher/abstract.py index 00502fe930..f2ef681c62 100644 --- a/openpype/tools/ayon_launcher/abstract.py +++ b/openpype/tools/ayon_launcher/abstract.py @@ -272,7 +272,7 @@ class AbstractLauncherFrontEnd(AbstractLauncherCommon): @abstractmethod def set_application_force_not_open_workfile( - self, project_name, folder_id, task_id, action_id, enabled + self, project_name, folder_id, task_id, action_ids, enabled ): """This is application action related to force not open last workfile. @@ -280,7 +280,7 @@ class AbstractLauncherFrontEnd(AbstractLauncherCommon): project_name (Union[str, None]): Project name. folder_id (Union[str, None]): Folder id. task_id (Union[str, None]): Task id. - action_id (str): Action identifier. + action_id (Iterable[str]): Action identifiers. enabled (bool): New value of force not open workfile. """ diff --git a/openpype/tools/ayon_launcher/control.py b/openpype/tools/ayon_launcher/control.py index 09e07893c3..a6e528b104 100644 --- a/openpype/tools/ayon_launcher/control.py +++ b/openpype/tools/ayon_launcher/control.py @@ -121,10 +121,10 @@ class BaseLauncherController( project_name, folder_id, task_id) def set_application_force_not_open_workfile( - self, project_name, folder_id, task_id, action_id, enabled + 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_id, enabled + project_name, folder_id, task_id, action_ids, enabled ) def trigger_action(self, project_name, folder_id, task_id, identifier): diff --git a/openpype/tools/ayon_launcher/models/actions.py b/openpype/tools/ayon_launcher/models/actions.py index 24fea44db2..93ec115734 100644 --- a/openpype/tools/ayon_launcher/models/actions.py +++ b/openpype/tools/ayon_launcher/models/actions.py @@ -326,13 +326,14 @@ class ActionsModel: return output def set_application_force_not_open_workfile( - self, project_name, folder_id, task_id, action_id, enabled + 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, {}) - task_data[action_id] = enabled + 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 ) @@ -359,7 +360,10 @@ class ActionsModel: project_name, folder_id, task_id ) force_not_open_workfile = per_action.get(identifier, False) - action.data["start_last_workfile"] = force_not_open_workfile + if force_not_open_workfile: + action.data["start_last_workfile"] = False + else: + action.data.pop("start_last_workfile", None) action.process(session) except Exception as exc: self.log.warning("Action trigger failed.", exc_info=True) diff --git a/openpype/tools/ayon_launcher/ui/actions_widget.py b/openpype/tools/ayon_launcher/ui/actions_widget.py index d04f8f8d24..0630d1d5b5 100644 --- a/openpype/tools/ayon_launcher/ui/actions_widget.py +++ b/openpype/tools/ayon_launcher/ui/actions_widget.py @@ -19,6 +19,21 @@ ANIMATION_STATE_ROLE = QtCore.Qt.UserRole + 6 FORCE_NOT_OPEN_WORKFILE_ROLE = QtCore.Qt.UserRole + 7 +def _variant_label_sort_getter(action_item): + """Get variant label value for sorting. + + Make sure the output value is a string. + + Args: + action_item (ActionItem): Action item. + + Returns: + str: Variant label or empty string. + """ + + return action_item.variant_label or "" + + class ActionsQtModel(QtGui.QStandardItemModel): """Qt model for actions. @@ -51,6 +66,7 @@ class ActionsQtModel(QtGui.QStandardItemModel): self._controller = controller self._items_by_id = {} + self._action_items_by_id = {} self._groups_by_id = {} self._selected_project_name = None @@ -72,8 +88,12 @@ class ActionsQtModel(QtGui.QStandardItemModel): def get_item_by_id(self, action_id): return self._items_by_id.get(action_id) + def get_action_item_by_id(self, action_id): + return self._action_items_by_id.get(action_id) + def _clear_items(self): self._items_by_id = {} + self._action_items_by_id = {} self._groups_by_id = {} root = self.invisibleRootItem() root.removeRows(0, root.rowCount()) @@ -101,12 +121,14 @@ class ActionsQtModel(QtGui.QStandardItemModel): groups_by_id = {} for action_items in items_by_label.values(): + action_items.sort(key=_variant_label_sort_getter, reverse=True) first_item = next(iter(action_items)) all_action_items_info.append((first_item, len(action_items) > 1)) groups_by_id[first_item.identifier] = action_items new_items = [] items_by_id = {} + action_items_by_id = {} for action_item_info in all_action_items_info: action_item, is_group = action_item_info icon = get_qt_icon(action_item.icon) @@ -132,6 +154,7 @@ class ActionsQtModel(QtGui.QStandardItemModel): 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 if new_items: root_item.appendRows(new_items) @@ -139,10 +162,12 @@ class ActionsQtModel(QtGui.QStandardItemModel): to_remove = set(self._items_by_id.keys()) - set(items_by_id.keys()) for identifier in to_remove: item = self._items_by_id.pop(identifier) + self._action_items_by_id.pop(identifier) root_item.removeRow(item.row()) self._groups_by_id = groups_by_id self._items_by_id = items_by_id + self._action_items_by_id = action_items_by_id self.refreshed.emit() def _on_controller_refresh_finished(self): @@ -387,9 +412,15 @@ class ActionsWidget(QtWidgets.QWidget): 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_id, checkbox.isChecked() + action_ids, checkbox.isChecked() ) ) action = QtWidgets.QWidgetAction(menu) @@ -402,7 +433,7 @@ class ActionsWidget(QtWidgets.QWidget): menu.exec_(global_point) self._context_menu = None - def _on_checkbox_changed(self, action_id, is_checked): + def _on_checkbox_changed(self, action_ids, is_checked): if self._context_menu is not None: self._context_menu.close() @@ -410,7 +441,7 @@ class ActionsWidget(QtWidgets.QWidget): 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_id, is_checked) + project_name, folder_id, task_id, action_ids, is_checked) self._model.refresh() def _on_clicked(self, index):