moved modification from avalon PR

This commit is contained in:
iLLiCiTiT 2021-11-16 19:15:51 +01:00
parent 912ad165d5
commit 3ee5e3ec40

View file

@ -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."