mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
Merge pull request #2731 from pypeclub/bugfix/OP-2643_Loader-multiple-asset-selection-error
Loader UI: Multiple asset selection and underline colors fixed
This commit is contained in:
commit
8deb622ae6
6 changed files with 109 additions and 148 deletions
|
|
@ -396,9 +396,7 @@ class LibraryLoaderWindow(QtWidgets.QDialog):
|
|||
self._versionschanged()
|
||||
return
|
||||
|
||||
selected_subsets = self._subsets_widget.selected_subsets(
|
||||
_merged=True, _other=False
|
||||
)
|
||||
selected_subsets = self._subsets_widget.get_selected_merge_items()
|
||||
|
||||
asset_colors = {}
|
||||
asset_ids = []
|
||||
|
|
@ -423,35 +421,14 @@ class LibraryLoaderWindow(QtWidgets.QDialog):
|
|||
self._versionschanged()
|
||||
|
||||
def _versionschanged(self):
|
||||
selection = self._subsets_widget.view.selectionModel()
|
||||
|
||||
# Active must be in the selected rows otherwise we
|
||||
# assume it's not actually an "active" current index.
|
||||
version_docs = None
|
||||
items = self._subsets_widget.get_selected_subsets()
|
||||
version_doc = None
|
||||
active = selection.currentIndex()
|
||||
rows = selection.selectedRows(column=active.column())
|
||||
if active and active in rows:
|
||||
item = active.data(self._subsets_widget.model.ItemRole)
|
||||
if (
|
||||
item is not None
|
||||
and not (item.get("isGroup") or item.get("isMerged"))
|
||||
):
|
||||
version_doc = item["version_document"]
|
||||
|
||||
if rows:
|
||||
version_docs = []
|
||||
for index in rows:
|
||||
if not index or not index.isValid():
|
||||
continue
|
||||
item = index.data(self._subsets_widget.model.ItemRole)
|
||||
if (
|
||||
item is None
|
||||
or item.get("isGroup")
|
||||
or item.get("isMerged")
|
||||
):
|
||||
continue
|
||||
version_docs.append(item["version_document"])
|
||||
version_docs = []
|
||||
for item in items:
|
||||
doc = item["version_document"]
|
||||
version_docs.append(doc)
|
||||
if version_doc is None:
|
||||
version_doc = doc
|
||||
|
||||
self._version_info_widget.set_version(version_doc)
|
||||
|
||||
|
|
|
|||
|
|
@ -287,9 +287,7 @@ class LoaderWindow(QtWidgets.QDialog):
|
|||
on selection change so they match current selection.
|
||||
"""
|
||||
# TODO do not touch inner attributes of asset widget
|
||||
last_asset_ids = self.data["state"]["assetIds"]
|
||||
if last_asset_ids:
|
||||
self._assets_widget.clear_underlines()
|
||||
self._assets_widget.clear_underlines()
|
||||
|
||||
def _assetschanged(self):
|
||||
"""Selected assets have changed"""
|
||||
|
|
@ -328,12 +326,11 @@ class LoaderWindow(QtWidgets.QDialog):
|
|||
asset_ids = self.data["state"]["assetIds"]
|
||||
# Skip setting colors if not asset multiselection
|
||||
if not asset_ids or len(asset_ids) < 2:
|
||||
self.clear_assets_underlines()
|
||||
self._versionschanged()
|
||||
return
|
||||
|
||||
selected_subsets = self._subsets_widget.selected_subsets(
|
||||
_merged=True, _other=False
|
||||
)
|
||||
selected_subsets = self._subsets_widget.get_selected_merge_items()
|
||||
|
||||
asset_colors = {}
|
||||
asset_ids = []
|
||||
|
|
@ -358,37 +355,16 @@ class LoaderWindow(QtWidgets.QDialog):
|
|||
self._versionschanged()
|
||||
|
||||
def _versionschanged(self):
|
||||
subsets = self._subsets_widget
|
||||
selection = subsets.view.selectionModel()
|
||||
|
||||
# Active must be in the selected rows otherwise we
|
||||
# assume it's not actually an "active" current index.
|
||||
items = self._subsets_widget.get_selected_subsets()
|
||||
version_doc = None
|
||||
active = selection.currentIndex()
|
||||
rows = selection.selectedRows(column=active.column())
|
||||
if active:
|
||||
if active in rows:
|
||||
item = active.data(subsets.model.ItemRole)
|
||||
if (
|
||||
item is not None and
|
||||
not (item.get("isGroup") or item.get("isMerged"))
|
||||
):
|
||||
version_doc = item["version_document"]
|
||||
self._version_info_widget.set_version(version_doc)
|
||||
|
||||
version_docs = []
|
||||
if rows:
|
||||
for index in rows:
|
||||
if not index or not index.isValid():
|
||||
continue
|
||||
item = index.data(subsets.model.ItemRole)
|
||||
if item is None:
|
||||
continue
|
||||
if item.get("isGroup") or item.get("isMerged"):
|
||||
for child in item.children():
|
||||
version_docs.append(child["version_document"])
|
||||
else:
|
||||
version_docs.append(item["version_document"])
|
||||
for item in items:
|
||||
doc = item["version_document"]
|
||||
version_docs.append(doc)
|
||||
if version_doc is None:
|
||||
version_doc = doc
|
||||
|
||||
self._version_info_widget.set_version(version_doc)
|
||||
|
||||
thumbnail_src_ids = [
|
||||
version_doc["_id"]
|
||||
|
|
@ -480,18 +456,7 @@ class LoaderWindow(QtWidgets.QDialog):
|
|||
self.echo("Grouping not enabled.")
|
||||
return
|
||||
|
||||
selected = []
|
||||
merged_items = []
|
||||
for item in subsets.selected_subsets(_merged=True):
|
||||
if item.get("isMerged"):
|
||||
merged_items.append(item)
|
||||
else:
|
||||
selected.append(item)
|
||||
|
||||
for merged_item in merged_items:
|
||||
for child_item in merged_item.children():
|
||||
selected.append(child_item)
|
||||
|
||||
selected = self._subsets_widget.get_selected_subsets()
|
||||
if not selected:
|
||||
self.echo("No selected subset.")
|
||||
return
|
||||
|
|
|
|||
|
|
@ -18,26 +18,6 @@ def change_visibility(model, view, column_name, visible):
|
|||
view.setColumnHidden(index, not visible)
|
||||
|
||||
|
||||
def get_selected_items(rows, item_role):
|
||||
items = []
|
||||
for row_index in rows:
|
||||
item = row_index.data(item_role)
|
||||
if item.get("isGroup"):
|
||||
continue
|
||||
|
||||
elif item.get("isMerged"):
|
||||
for idx in range(row_index.model().rowCount(row_index)):
|
||||
child_index = row_index.child(idx, 0)
|
||||
item = child_index.data(item_role)
|
||||
if item not in items:
|
||||
items.append(item)
|
||||
|
||||
else:
|
||||
if item not in items:
|
||||
items.append(item)
|
||||
return items
|
||||
|
||||
|
||||
def get_options(action, loader, parent, repre_contexts):
|
||||
"""Provides dialog to select value from loader provided options.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import copy
|
||||
import re
|
||||
import math
|
||||
from uuid import uuid4
|
||||
|
||||
from avalon import (
|
||||
style,
|
||||
|
|
@ -22,6 +23,8 @@ from openpype.tools.utils.constants import (
|
|||
REMOTE_AVAILABILITY_ROLE
|
||||
)
|
||||
|
||||
ITEM_ID_ROLE = QtCore.Qt.UserRole + 90
|
||||
|
||||
|
||||
def is_filtering_recursible():
|
||||
"""Does Qt binding support recursive filtering for QSortFilterProxyModel?
|
||||
|
|
@ -179,6 +182,7 @@ class SubsetsModel(TreeModel, BaseRepresentationModel):
|
|||
self._icons = {
|
||||
"subset": qtawesome.icon("fa.file-o", color=style.colors.default)
|
||||
}
|
||||
self._items_by_id = {}
|
||||
|
||||
self._doc_fetching_thread = None
|
||||
self._doc_fetching_stop = False
|
||||
|
|
@ -188,6 +192,15 @@ class SubsetsModel(TreeModel, BaseRepresentationModel):
|
|||
|
||||
self.refresh()
|
||||
|
||||
def get_item_by_id(self, item_id):
|
||||
return self._items_by_id.get(item_id)
|
||||
|
||||
def add_child(self, new_item, *args, **kwargs):
|
||||
item_id = str(uuid4())
|
||||
new_item["id"] = item_id
|
||||
self._items_by_id[item_id] = new_item
|
||||
super(SubsetsModel, self).add_child(new_item, *args, **kwargs)
|
||||
|
||||
def set_assets(self, asset_ids):
|
||||
self._asset_ids = asset_ids
|
||||
self.refresh()
|
||||
|
|
@ -486,7 +499,7 @@ class SubsetsModel(TreeModel, BaseRepresentationModel):
|
|||
def refresh(self):
|
||||
self.stop_fetch_thread()
|
||||
self.clear()
|
||||
|
||||
self._items_by_id = {}
|
||||
self.reset_sync_server()
|
||||
|
||||
if not self._asset_ids:
|
||||
|
|
@ -497,6 +510,7 @@ class SubsetsModel(TreeModel, BaseRepresentationModel):
|
|||
|
||||
def on_doc_fetched(self):
|
||||
self.clear()
|
||||
self._items_by_id = {}
|
||||
self.beginResetModel()
|
||||
|
||||
asset_docs_by_id = self._doc_payload.get(
|
||||
|
|
@ -524,9 +538,13 @@ class SubsetsModel(TreeModel, BaseRepresentationModel):
|
|||
return
|
||||
|
||||
self._fill_subset_items(
|
||||
asset_docs_by_id, subset_docs_by_id, last_versions_by_subset_id,
|
||||
asset_docs_by_id,
|
||||
subset_docs_by_id,
|
||||
last_versions_by_subset_id,
|
||||
repre_info_by_version_id
|
||||
)
|
||||
self.endResetModel()
|
||||
self.refreshed.emit(True)
|
||||
|
||||
def create_multiasset_group(
|
||||
self, subset_name, asset_ids, subset_counter, parent_item=None
|
||||
|
|
@ -538,7 +556,6 @@ class SubsetsModel(TreeModel, BaseRepresentationModel):
|
|||
merge_group.update({
|
||||
"subset": "{} ({})".format(subset_name, len(asset_ids)),
|
||||
"isMerged": True,
|
||||
"childRow": 0,
|
||||
"subsetColor": subset_color,
|
||||
"assetIds": list(asset_ids),
|
||||
"icon": qtawesome.icon(
|
||||
|
|
@ -547,7 +564,6 @@ class SubsetsModel(TreeModel, BaseRepresentationModel):
|
|||
)
|
||||
})
|
||||
|
||||
subset_counter += 1
|
||||
self.add_child(merge_group, parent_item)
|
||||
|
||||
return merge_group
|
||||
|
|
@ -567,8 +583,7 @@ class SubsetsModel(TreeModel, BaseRepresentationModel):
|
|||
group_item = Item()
|
||||
group_item.update({
|
||||
"subset": group_name,
|
||||
"isGroup": True,
|
||||
"childRow": 0
|
||||
"isGroup": True
|
||||
})
|
||||
group_item.update(group_data)
|
||||
|
||||
|
|
@ -666,14 +681,14 @@ class SubsetsModel(TreeModel, BaseRepresentationModel):
|
|||
index = self.index(item.row(), 0, parent_index)
|
||||
self.set_version(index, last_version)
|
||||
|
||||
self.endResetModel()
|
||||
self.refreshed.emit(True)
|
||||
|
||||
def data(self, index, role):
|
||||
if not index.isValid():
|
||||
return
|
||||
|
||||
item = index.internalPointer()
|
||||
if role == ITEM_ID_ROLE:
|
||||
return item["id"]
|
||||
|
||||
if role == self.SortDescendingRole:
|
||||
if item.get("isGroup"):
|
||||
# Ensure groups be on top when sorting by descending order
|
||||
|
|
@ -1139,7 +1154,6 @@ class RepresentationModel(TreeModel, BaseRepresentationModel):
|
|||
"_id": doc["_id"],
|
||||
"name": doc["name"],
|
||||
"isMerged": True,
|
||||
"childRow": 0,
|
||||
"active_site_name": self.active_site,
|
||||
"remote_site_name": self.remote_site,
|
||||
"icon": qtawesome.icon(
|
||||
|
|
|
|||
|
|
@ -34,7 +34,8 @@ from .model import (
|
|||
SubsetFilterProxyModel,
|
||||
FamiliesFilterProxyModel,
|
||||
RepresentationModel,
|
||||
RepresentationSortProxyModel
|
||||
RepresentationSortProxyModel,
|
||||
ITEM_ID_ROLE
|
||||
)
|
||||
from . import lib
|
||||
|
||||
|
|
@ -351,6 +352,59 @@ class SubsetWidget(QtWidgets.QWidget):
|
|||
|
||||
lib.change_visibility(self.model, self.view, "repre_info", enabled)
|
||||
|
||||
def get_selected_items(self):
|
||||
selection_model = self.view.selectionModel()
|
||||
indexes = selection_model.selectedIndexes()
|
||||
|
||||
item_ids = set()
|
||||
for index in indexes:
|
||||
item_id = index.data(ITEM_ID_ROLE)
|
||||
if item_id is not None:
|
||||
item_ids.add(item_id)
|
||||
|
||||
output = []
|
||||
for item_id in item_ids:
|
||||
item = self.model.get_item_by_id(item_id)
|
||||
if item is not None:
|
||||
output.append(item)
|
||||
return output
|
||||
|
||||
def get_selected_merge_items(self):
|
||||
output = []
|
||||
items = collections.deque(self.get_selected_items())
|
||||
|
||||
item_ids = set()
|
||||
while items:
|
||||
item = items.popleft()
|
||||
if item.get("isGroup"):
|
||||
for child in item.children():
|
||||
items.appendleft(child)
|
||||
|
||||
elif item.get("isMerged"):
|
||||
item_id = item["id"]
|
||||
if item_id not in item_ids:
|
||||
item_ids.add(item_id)
|
||||
output.append(item)
|
||||
|
||||
return output
|
||||
|
||||
def get_selected_subsets(self):
|
||||
output = []
|
||||
items = collections.deque(self.get_selected_items())
|
||||
|
||||
item_ids = set()
|
||||
while items:
|
||||
item = items.popleft()
|
||||
if item.get("isGroup") or item.get("isMerged"):
|
||||
for child in item.children():
|
||||
items.appendleft(child)
|
||||
else:
|
||||
item_id = item["id"]
|
||||
if item_id not in item_ids:
|
||||
item_ids.add(item_id)
|
||||
output.append(item)
|
||||
return output
|
||||
|
||||
def on_context_menu(self, point):
|
||||
"""Shows menu with loader actions on Right-click.
|
||||
|
||||
|
|
@ -367,10 +421,7 @@ class SubsetWidget(QtWidgets.QWidget):
|
|||
return
|
||||
|
||||
# Get selected subsets without groups
|
||||
selection = self.view.selectionModel()
|
||||
rows = selection.selectedRows(column=0)
|
||||
|
||||
items = lib.get_selected_items(rows, self.model.ItemRole)
|
||||
items = self.get_selected_subsets()
|
||||
|
||||
# Get all representation->loader combinations available for the
|
||||
# index under the cursor, so we can list the user the options.
|
||||
|
|
@ -539,35 +590,6 @@ class SubsetWidget(QtWidgets.QWidget):
|
|||
box = LoadErrorMessageBox(error_info, self)
|
||||
box.show()
|
||||
|
||||
def selected_subsets(self, _groups=False, _merged=False, _other=True):
|
||||
selection = self.view.selectionModel()
|
||||
rows = selection.selectedRows(column=0)
|
||||
|
||||
subsets = list()
|
||||
if not any([_groups, _merged, _other]):
|
||||
self.echo((
|
||||
"This is a BUG: Selected_subsets args must contain"
|
||||
" at least one value set to True"
|
||||
))
|
||||
return subsets
|
||||
|
||||
for row in rows:
|
||||
item = row.data(self.model.ItemRole)
|
||||
if item.get("isGroup"):
|
||||
if not _groups:
|
||||
continue
|
||||
|
||||
elif item.get("isMerged"):
|
||||
if not _merged:
|
||||
continue
|
||||
else:
|
||||
if not _other:
|
||||
continue
|
||||
|
||||
subsets.append(item)
|
||||
|
||||
return subsets
|
||||
|
||||
def group_subsets(self, name, asset_ids, items):
|
||||
field = "data.subsetGroup"
|
||||
|
||||
|
|
@ -1279,7 +1301,7 @@ class RepresentationWidget(QtWidgets.QWidget):
|
|||
selection = self.tree_view.selectionModel()
|
||||
rows = selection.selectedRows(column=0)
|
||||
|
||||
items = lib.get_selected_items(rows, self.model.ItemRole)
|
||||
items = self.get_selected_subsets()
|
||||
|
||||
selected_side = self._get_selected_side(point_index, rows)
|
||||
|
||||
|
|
|
|||
|
|
@ -303,7 +303,7 @@ class AssetModel(QtGui.QStandardItemModel):
|
|||
|
||||
self._doc_fetched.connect(self._on_docs_fetched)
|
||||
|
||||
self._items_with_color_by_id = {}
|
||||
self._item_ids_with_color = set()
|
||||
self._items_by_asset_id = {}
|
||||
|
||||
self._last_project_name = None
|
||||
|
|
@ -382,9 +382,11 @@ class AssetModel(QtGui.QStandardItemModel):
|
|||
self._stop_fetch_thread()
|
||||
|
||||
def clear_underlines(self):
|
||||
for asset_id in tuple(self._items_with_color_by_id.keys()):
|
||||
item = self._items_with_color_by_id.pop(asset_id)
|
||||
item.setData(None, ASSET_UNDERLINE_COLORS_ROLE)
|
||||
for asset_id in set(self._item_ids_with_color):
|
||||
self._item_ids_with_color.remove(asset_id)
|
||||
item = self._items_by_asset_id.get(asset_id)
|
||||
if item is not None:
|
||||
item.setData(None, ASSET_UNDERLINE_COLORS_ROLE)
|
||||
|
||||
def set_underline_colors(self, colors_by_asset_id):
|
||||
self.clear_underlines()
|
||||
|
|
@ -394,12 +396,13 @@ class AssetModel(QtGui.QStandardItemModel):
|
|||
if item is None:
|
||||
continue
|
||||
item.setData(colors, ASSET_UNDERLINE_COLORS_ROLE)
|
||||
self._item_ids_with_color.add(asset_id)
|
||||
|
||||
def _clear_items(self):
|
||||
root_item = self.invisibleRootItem()
|
||||
root_item.removeRows(0, root_item.rowCount())
|
||||
self._items_by_asset_id = {}
|
||||
self._items_with_color_by_id = {}
|
||||
self._item_ids_with_color = set()
|
||||
|
||||
def _on_docs_fetched(self):
|
||||
# Make sure refreshing did not change
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue