mirror of
https://github.com/ynput/ayon-core.git
synced 2026-01-02 00:44:52 +01:00
moved modification from avalon PR
This commit is contained in:
parent
912ad165d5
commit
3ee5e3ec40
1 changed files with 371 additions and 26 deletions
|
|
@ -2,10 +2,13 @@ import collections
|
|||
import logging
|
||||
from Qt import QtWidgets, QtCore
|
||||
|
||||
from avalon import io, api
|
||||
from avalon import io, api, pipeline
|
||||
from avalon.vendor import qtawesome
|
||||
|
||||
from .widgets import SearchComboBox
|
||||
from .widgets import (
|
||||
ButtonWithMenu,
|
||||
SearchComboBox
|
||||
)
|
||||
|
||||
log = logging.getLogger("SwitchAssetDialog")
|
||||
|
||||
|
|
@ -55,7 +58,7 @@ class SwitchAssetDialog(QtWidgets.QDialog):
|
|||
current_asset_btn = QtWidgets.QPushButton("Use current asset")
|
||||
|
||||
accept_icon = qtawesome.icon("fa.check", color="white")
|
||||
accept_btn = QtWidgets.QPushButton(self)
|
||||
accept_btn = ButtonWithMenu(self)
|
||||
accept_btn.setIcon(accept_icon)
|
||||
|
||||
main_layout = QtWidgets.QGridLayout(self)
|
||||
|
|
@ -100,6 +103,24 @@ class SwitchAssetDialog(QtWidgets.QDialog):
|
|||
|
||||
self._accept_btn = accept_btn
|
||||
|
||||
self.content_loaders = set()
|
||||
self.content_assets = {}
|
||||
self.content_subsets = {}
|
||||
self.content_versions = {}
|
||||
self.content_repres = {}
|
||||
|
||||
self.hero_version_ids = set()
|
||||
|
||||
self.missing_assets = []
|
||||
self.missing_versions = []
|
||||
self.missing_subsets = []
|
||||
self.missing_repres = []
|
||||
self.missing_docs = False
|
||||
|
||||
self.archived_assets = []
|
||||
self.archived_subsets = []
|
||||
self.archived_repres = []
|
||||
|
||||
self._init_asset_name = None
|
||||
self._init_subset_name = None
|
||||
self._init_repre_name = None
|
||||
|
|
@ -117,13 +138,15 @@ class SwitchAssetDialog(QtWidgets.QDialog):
|
|||
accept_btn.setFocus()
|
||||
|
||||
def _prepare_content_data(self):
|
||||
repre_ids = [
|
||||
io.ObjectId(item["representation"])
|
||||
for item in self._items
|
||||
]
|
||||
repre_ids = set()
|
||||
content_loaders = set()
|
||||
for item in self._items:
|
||||
repre_ids.add(io.ObjectId(item["representation"]))
|
||||
content_loaders.add(item["loader"])
|
||||
|
||||
repres = list(io.find({
|
||||
"type": {"$in": ["representation", "archived_representation"]},
|
||||
"_id": {"$in": repre_ids}
|
||||
"_id": {"$in": list(repre_ids)}
|
||||
}))
|
||||
repres_by_id = {repre["_id"]: repre for repre in repres}
|
||||
|
||||
|
|
@ -207,6 +230,7 @@ class SwitchAssetDialog(QtWidgets.QDialog):
|
|||
else:
|
||||
content_assets[asset_id] = assets_by_id[asset_id]
|
||||
|
||||
self.content_loaders = content_loaders
|
||||
self.content_assets = content_assets
|
||||
self.content_subsets = content_subsets
|
||||
self.content_versions = content_versions
|
||||
|
|
@ -260,8 +284,11 @@ class SwitchAssetDialog(QtWidgets.QDialog):
|
|||
|
||||
# Fill comboboxes with values
|
||||
self.set_labels()
|
||||
|
||||
self.apply_validations(validation_state)
|
||||
|
||||
self._build_loaders_menu()
|
||||
|
||||
if init_refresh: # pre select context if possible
|
||||
self._assets_box.set_valid_value(self._init_asset_name)
|
||||
self._subsets_box.set_valid_value(self._init_subset_name)
|
||||
|
|
@ -269,23 +296,89 @@ class SwitchAssetDialog(QtWidgets.QDialog):
|
|||
|
||||
self._fill_check = True
|
||||
|
||||
def _get_loaders(self, representations):
|
||||
if not representations:
|
||||
def _build_loaders_menu(self):
|
||||
repre_ids = self._get_current_output_repre_ids()
|
||||
loaders = self._get_loaders(repre_ids)
|
||||
# Get and destroy the action group
|
||||
self._accept_btn.clear_actions()
|
||||
|
||||
if not loaders:
|
||||
return
|
||||
|
||||
# Build new action group
|
||||
group = QtWidgets.QActionGroup(self._accept_btn)
|
||||
|
||||
for loader in loaders:
|
||||
# Label
|
||||
label = getattr(loader, "label", None)
|
||||
if label is None:
|
||||
label = loader.__name__
|
||||
|
||||
action = group.addAction(label)
|
||||
# action = QtWidgets.QAction(label)
|
||||
action.setData(loader)
|
||||
|
||||
# Support font-awesome icons using the `.icon` and `.color`
|
||||
# attributes on plug-ins.
|
||||
icon = getattr(loader, "icon", None)
|
||||
if icon is not None:
|
||||
try:
|
||||
key = "fa.{0}".format(icon)
|
||||
color = getattr(loader, "color", "white")
|
||||
action.setIcon(qtawesome.icon(key, color=color))
|
||||
|
||||
except Exception as exc:
|
||||
print("Unable to set icon for loader {}: {}".format(
|
||||
loader, str(exc)
|
||||
))
|
||||
|
||||
self._accept_btn.add_action(action)
|
||||
|
||||
group.triggered.connect(self._on_action_clicked)
|
||||
|
||||
def _on_action_clicked(self, action):
|
||||
loader_plugin = action.data()
|
||||
self._trigger_switch(loader_plugin)
|
||||
|
||||
def _get_loaders(self, repre_ids):
|
||||
repre_contexts = None
|
||||
if repre_ids:
|
||||
repre_contexts = pipeline.get_repres_contexts(repre_ids)
|
||||
|
||||
if not repre_contexts:
|
||||
return list()
|
||||
|
||||
available_loaders = filter(
|
||||
lambda l: not (hasattr(l, "is_utility") and l.is_utility),
|
||||
api.discover(api.Loader)
|
||||
)
|
||||
available_loaders = []
|
||||
for loader_plugin in api.discover(api.Loader):
|
||||
# Skip loaders without switch method
|
||||
if not hasattr(loader_plugin, "switch"):
|
||||
continue
|
||||
|
||||
loaders = set()
|
||||
# Skip utility loaders
|
||||
if (
|
||||
hasattr(loader_plugin, "is_utility")
|
||||
and loader_plugin.is_utility
|
||||
):
|
||||
continue
|
||||
available_loaders.append(loader_plugin)
|
||||
|
||||
for representation in representations:
|
||||
for loader in api.loaders_from_representation(
|
||||
available_loaders,
|
||||
representation
|
||||
):
|
||||
loaders.add(loader)
|
||||
loaders = None
|
||||
for repre_context in repre_contexts.values():
|
||||
_loaders = set(pipeline.loaders_from_repre_context(
|
||||
available_loaders, repre_context
|
||||
))
|
||||
if loaders is None:
|
||||
loaders = _loaders
|
||||
else:
|
||||
loaders = _loaders.intersection(loaders)
|
||||
|
||||
if not loaders:
|
||||
break
|
||||
|
||||
if loaders is None:
|
||||
loaders = []
|
||||
else:
|
||||
loaders = list(loaders)
|
||||
|
||||
return loaders
|
||||
|
||||
|
|
@ -325,12 +418,11 @@ class SwitchAssetDialog(QtWidgets.QDialog):
|
|||
def apply_validations(self, validation_state):
|
||||
error_msg = "*Please select"
|
||||
error_sheet = "border: 1px solid red;"
|
||||
success_sheet = "border: 1px solid green;"
|
||||
|
||||
asset_sheet = None
|
||||
subset_sheet = None
|
||||
repre_sheet = None
|
||||
accept_sheet = None
|
||||
accept_state = ""
|
||||
if validation_state.asset_ok is False:
|
||||
asset_sheet = error_sheet
|
||||
self._asset_label.setText(error_msg)
|
||||
|
|
@ -342,14 +434,264 @@ class SwitchAssetDialog(QtWidgets.QDialog):
|
|||
self._repre_label.setText(error_msg)
|
||||
|
||||
if validation_state.all_ok:
|
||||
accept_sheet = success_sheet
|
||||
accept_state = "1"
|
||||
|
||||
self._assets_box.setStyleSheet(asset_sheet or "")
|
||||
self._subsets_box.setStyleSheet(subset_sheet or "")
|
||||
self._representations_box.setStyleSheet(repre_sheet or "")
|
||||
|
||||
self._accept_btn.setEnabled(validation_state.all_ok)
|
||||
self._accept_btn.setStyleSheet(accept_sheet or "")
|
||||
self._set_style_property(self._accept_btn, "state", accept_state)
|
||||
|
||||
def _set_style_property(self, widget, name, value):
|
||||
cur_value = widget.property(name)
|
||||
if cur_value == value:
|
||||
return
|
||||
widget.setProperty(name, value)
|
||||
widget.style().polish(widget)
|
||||
|
||||
def _get_current_output_repre_ids(self):
|
||||
# NOTE hero versions are not used because it is expected that
|
||||
# hero version has same representations as latests
|
||||
selected_asset = self._assets_box.currentText()
|
||||
selected_subset = self._subsets_box.currentText()
|
||||
selected_repre = self._representations_box.currentText()
|
||||
|
||||
# Nothing is selected
|
||||
# [ ] [ ] [ ]
|
||||
if not selected_asset and not selected_subset and not selected_repre:
|
||||
return list(self.content_repres.keys())
|
||||
|
||||
# Prepare asset document if asset is selcted
|
||||
if selected_asset:
|
||||
asset_doc = io.find_one(
|
||||
{"type": "asset", "name": selected_asset},
|
||||
{"_id": True}
|
||||
)
|
||||
if not asset_doc:
|
||||
return []
|
||||
|
||||
# Everything is selected
|
||||
# [x] [x] [x]
|
||||
if selected_asset and selected_subset and selected_repre:
|
||||
subset_doc = io.find_one(
|
||||
{
|
||||
"type": "subset",
|
||||
"name": selected_subset,
|
||||
"parent": asset_doc["_id"]
|
||||
},
|
||||
{"_id": True}
|
||||
)
|
||||
subset_id = subset_doc["_id"]
|
||||
last_versions_by_subset_id = self.find_last_versions([subset_id])
|
||||
version_doc = last_versions_by_subset_id.get(subset_id)
|
||||
if not version_doc:
|
||||
return []
|
||||
|
||||
repre_docs = io.find(
|
||||
{
|
||||
"type": "representation",
|
||||
"parent": version_doc["_id"],
|
||||
"name": selected_repre
|
||||
},
|
||||
{"_id": True}
|
||||
)
|
||||
return [repre_doc["_id"] for repre_doc in repre_docs]
|
||||
|
||||
# [x] [x] [ ]
|
||||
# If asset and subset is selected
|
||||
if selected_asset and selected_subset:
|
||||
subset_doc = io.find_one(
|
||||
{
|
||||
"type": "subset",
|
||||
"parent": asset_doc["_id"],
|
||||
"name": selected_subset
|
||||
},
|
||||
{"_id": True}
|
||||
)
|
||||
if not subset_doc:
|
||||
return []
|
||||
|
||||
repre_names = set()
|
||||
for repre_doc in self.content_repres.values():
|
||||
repre_names.add(repre_doc["name"])
|
||||
|
||||
repre_docs = io.find(
|
||||
{
|
||||
"type": "rerpesentation",
|
||||
"parent": subset_doc["_id"],
|
||||
"name": {"$in": list(repre_names)}
|
||||
},
|
||||
{"_id": True}
|
||||
)
|
||||
return [repre_doc["_id"] for repre_doc in repre_docs]
|
||||
|
||||
# [x] [ ] [x]
|
||||
# If asset and repre is selected
|
||||
if selected_asset and selected_repre:
|
||||
susbet_names = set()
|
||||
for subset_doc in self.content_subsets.values():
|
||||
susbet_names.add(subset_doc["name"])
|
||||
|
||||
subset_docs = io.find(
|
||||
{
|
||||
"type": "subset",
|
||||
"name": {"$in": list(susbet_names)}
|
||||
},
|
||||
{"_id": True}
|
||||
)
|
||||
subset_ids = [subset_doc["_id"] for subset_doc in subset_docs]
|
||||
repre_docs = io.find(
|
||||
{
|
||||
"type": "representation",
|
||||
"parent": {"$in": subset_ids},
|
||||
"name": selected_repre
|
||||
},
|
||||
{"_id": True}
|
||||
)
|
||||
return [repre_doc["_id"] for repre_doc in repre_docs]
|
||||
|
||||
# [x] [ ] [ ]
|
||||
# If asset and subset is selected
|
||||
if selected_asset:
|
||||
repres_by_subset_name = collections.defaultdict(set)
|
||||
for repre_doc in self.content_repres.values():
|
||||
repre_name = repre_doc["name"]
|
||||
version_doc = self.content_versions[repre_doc["parent"]]
|
||||
subset_doc = self.content_subsets[version_doc["parent"]]
|
||||
subset_name = subset_doc["name"]
|
||||
repres_by_subset_name[subset_name].add(repre_name)
|
||||
|
||||
asset_doc = io.find_one(
|
||||
{"type": "asset", "name": selected_asset},
|
||||
{"_id": True}
|
||||
)
|
||||
subset_docs = list(io.find(
|
||||
{
|
||||
"type": "subset",
|
||||
"parent": asset_doc["_id"],
|
||||
"name": {"$in": list(repres_by_subset_name.keys())}
|
||||
},
|
||||
{"_id": True, "name": True}
|
||||
))
|
||||
subset_name_by_id = {
|
||||
subset_doc["_id"]: subset_doc["name"]
|
||||
for subset_doc in subset_docs
|
||||
}
|
||||
subset_ids = list(subset_name_by_id.keys())
|
||||
last_versions_by_subset_id = self.find_last_versions(subset_ids)
|
||||
last_version_id_by_subset_name = {}
|
||||
for subset_id, last_version in last_versions_by_subset_id.items():
|
||||
subset_name = subset_name_by_id[subset_id]
|
||||
last_version_id_by_subset_name[subset_name] = (
|
||||
last_version["_id"]
|
||||
)
|
||||
|
||||
repre_or_query = []
|
||||
for subset_name, repre_names in repres_by_subset_name.items():
|
||||
version_id = last_version_id_by_subset_name.get(subset_name)
|
||||
# This should not happen but why to crash?
|
||||
if version_id is None:
|
||||
continue
|
||||
repre_or_query.append({
|
||||
"parent": version_id,
|
||||
"name": {"$in": list(repre_names)}
|
||||
})
|
||||
repre_docs = io.find(
|
||||
{"$or": repre_or_query},
|
||||
{"_id": True}
|
||||
)
|
||||
return [repre_doc["_id"] for repre_doc in repre_docs]
|
||||
|
||||
# [ ] [x] [x]
|
||||
if selected_subset and selected_repre:
|
||||
subset_docs = list(io.find({
|
||||
"type": "subset",
|
||||
"parent": {"$in": list(self.content_assets.keys())},
|
||||
"name": selected_subset
|
||||
}))
|
||||
subset_ids = [subset_doc["_id"] for subset_doc in subset_docs]
|
||||
last_versions_by_subset_id = self.find_last_versions(subset_ids)
|
||||
last_version_ids = [
|
||||
last_version["_id"]
|
||||
for last_version in last_versions_by_subset_id.values()
|
||||
]
|
||||
repre_docs = io.find({
|
||||
"type": "representation",
|
||||
"parent": {"$in": last_version_ids},
|
||||
"name": selected_repre
|
||||
})
|
||||
|
||||
return [repre_doc["_id"] for repre_doc in repre_docs]
|
||||
|
||||
# [ ] [x] [ ]
|
||||
if selected_subset:
|
||||
subset_docs = list(io.find(
|
||||
{
|
||||
"type": "subset",
|
||||
"parent": {"$in": list(self.content_assets.keys())},
|
||||
"name": selected_subset
|
||||
},
|
||||
{"_id": True, "parent": True}
|
||||
))
|
||||
if not subset_docs:
|
||||
return list()
|
||||
|
||||
subset_docs_by_id = {
|
||||
subset_doc["_id"]: subset_doc
|
||||
for subset_doc in subset_docs
|
||||
}
|
||||
last_versions_by_subset_id = self.find_last_versions(
|
||||
subset_docs_by_id.keys()
|
||||
)
|
||||
|
||||
subset_id_by_version_id = {}
|
||||
for subset_id, last_version in last_versions_by_subset_id.items():
|
||||
version_id = last_version["_id"]
|
||||
subset_id_by_version_id[version_id] = subset_id
|
||||
|
||||
if not subset_id_by_version_id:
|
||||
return list()
|
||||
|
||||
repre_names_by_asset_id = collections.defaultdict(set)
|
||||
for repre_doc in self.content_repres.values():
|
||||
version_doc = self.content_versions[repre_doc["parent"]]
|
||||
subset_doc = self.content_subsets[version_doc["parent"]]
|
||||
asset_doc = self.content_assets[subset_doc["parent"]]
|
||||
repre_name = repre_doc["name"]
|
||||
asset_id = asset_doc["_id"]
|
||||
repre_names_by_asset_id[asset_id].add(repre_name)
|
||||
|
||||
repre_or_query = []
|
||||
for last_version_id, subset_id in subset_id_by_version_id.items():
|
||||
subset_doc = subset_docs_by_id[subset_id]
|
||||
asset_id = subset_doc["parent"]
|
||||
repre_names = repre_names_by_asset_id.get(asset_id)
|
||||
if not repre_names:
|
||||
continue
|
||||
repre_or_query.append({
|
||||
"parent": last_version_id,
|
||||
"name": {"$in": list(repre_names)}
|
||||
})
|
||||
repre_docs = io.find(
|
||||
{
|
||||
"type": "representation",
|
||||
"$or": repre_or_query
|
||||
},
|
||||
{"_id": True}
|
||||
)
|
||||
|
||||
return [repre_doc["_id"] for repre_doc in repre_docs]
|
||||
|
||||
# [ ] [ ] [x]
|
||||
repre_docs = io.find(
|
||||
{
|
||||
"name": selected_repre,
|
||||
"parent": {"$in": list(self.content_versions.keys())}
|
||||
},
|
||||
{"_id": True}
|
||||
)
|
||||
return [repre_doc["_id"] for repre_doc in repre_docs]
|
||||
|
||||
def _get_asset_box_values(self):
|
||||
asset_docs = io.find(
|
||||
|
|
@ -852,6 +1194,9 @@ class SwitchAssetDialog(QtWidgets.QDialog):
|
|||
self._assets_box.setCurrentIndex(index)
|
||||
|
||||
def _on_accept(self):
|
||||
self._trigger_switch()
|
||||
|
||||
def _trigger_switch(self, loader=None):
|
||||
# Use None when not a valid value or when placeholder value
|
||||
selected_asset = self._assets_box.get_valid_value()
|
||||
selected_subset = self._subsets_box.get_valid_value()
|
||||
|
|
@ -974,7 +1319,7 @@ class SwitchAssetDialog(QtWidgets.QDialog):
|
|||
repre_doc = repres_by_name[container_repre_name]
|
||||
|
||||
try:
|
||||
api.switch(container, repre_doc)
|
||||
api.switch(container, repre_doc, loader)
|
||||
except Exception:
|
||||
msg = (
|
||||
"Couldn't switch asset."
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue