Merge branch 'develop' into release/3.14.x

This commit is contained in:
Milan Kolar 2022-08-18 10:48:46 +02:00
commit 4334adda1a
140 changed files with 5094 additions and 2286 deletions

View file

@ -10,6 +10,7 @@ from Qt import QtCore, QtGui
import qtawesome
from openpype.client import (
get_projects,
get_project,
get_assets,
)
@ -527,7 +528,7 @@ class LauncherModel(QtCore.QObject):
current_project = self.project_name
project_names = set()
project_docs_by_name = {}
for project_doc in self._dbcon.projects(only_active=True):
for project_doc in get_projects():
project_name = project_doc["name"]
project_names.add(project_name)
project_docs_by_name[project_name] = project_doc

View file

@ -3,7 +3,7 @@ import sys
from Qt import QtWidgets, QtCore, QtGui
from openpype import style
from openpype.client import get_project
from openpype.client import get_projects, get_project
from openpype.pipeline import AvalonMongoDB
from openpype.tools.utils import lib as tools_lib
from openpype.tools.loader.widgets import (
@ -239,7 +239,7 @@ class LibraryLoaderWindow(QtWidgets.QDialog):
def get_filtered_projects(self):
projects = list()
for project in self.dbcon.projects():
for project in get_projects(fields=["name", "data.library_project"]):
is_library = project.get("data", {}).get("library_project", False)
if (
(is_library and self.show_libraries) or

View file

@ -272,15 +272,15 @@ class SubsetsModel(TreeModel, BaseRepresentationModel):
# update availability on active site when version changes
if self.sync_server.enabled and version_doc:
query = self._repre_per_version_pipeline(
repre_info = self.sync_server.get_repre_info_for_versions(
project_name,
[version_doc["_id"]],
self.active_site,
self.remote_site
)
docs = list(self.dbcon.aggregate(query))
if docs:
repre = docs.pop()
version_doc["data"].update(self._get_repre_dict(repre))
if repre_info:
version_doc["data"].update(
self._get_repre_dict(repre_info[0]))
self.set_version(index, version_doc)
@ -478,16 +478,16 @@ class SubsetsModel(TreeModel, BaseRepresentationModel):
for _subset_id, doc in last_versions_by_subset_id.items():
version_ids.add(doc["_id"])
query = self._repre_per_version_pipeline(
repres = self.sync_server.get_repre_info_for_versions(
project_name,
list(version_ids), self.active_site, self.remote_site
)
for doc in self.dbcon.aggregate(query):
for repre in repres:
if self._doc_fetching_stop:
return
doc["active_provider"] = self.active_provider
doc["remote_provider"] = self.remote_provider
repre_info[doc["_id"]] = doc
repre_info[repre["_id"]] = repre
self._doc_payload = {
"asset_docs_by_id": asset_docs_by_id,
@ -827,83 +827,6 @@ class SubsetsModel(TreeModel, BaseRepresentationModel):
return data
def _repre_per_version_pipeline(self, version_ids,
active_site, remote_site):
query = [
{"$match": {"parent": {"$in": version_ids},
"type": "representation",
"files.sites.name": {"$exists": 1}}},
{"$unwind": "$files"},
{'$addFields': {
'order_local': {
'$filter': {
'input': '$files.sites', 'as': 'p',
'cond': {'$eq': ['$$p.name', active_site]}
}
}
}},
{'$addFields': {
'order_remote': {
'$filter': {
'input': '$files.sites', 'as': 'p',
'cond': {'$eq': ['$$p.name', remote_site]}
}
}
}},
{'$addFields': {
'progress_local': {"$arrayElemAt": [{
'$cond': [
{'$size': "$order_local.progress"},
"$order_local.progress",
# if exists created_dt count is as available
{'$cond': [
{'$size': "$order_local.created_dt"},
[1],
[0]
]}
]},
0
]}
}},
{'$addFields': {
'progress_remote': {"$arrayElemAt": [{
'$cond': [
{'$size': "$order_remote.progress"},
"$order_remote.progress",
# if exists created_dt count is as available
{'$cond': [
{'$size': "$order_remote.created_dt"},
[1],
[0]
]}
]},
0
]}
}},
{'$group': { # first group by repre
'_id': '$_id',
'parent': {'$first': '$parent'},
'avail_ratio_local': {
'$first': {
'$divide': [{'$sum': "$progress_local"}, {'$sum': 1}]
}
},
'avail_ratio_remote': {
'$first': {
'$divide': [{'$sum': "$progress_remote"}, {'$sum': 1}]
}
}
}},
{'$group': { # second group by parent, eg version_id
'_id': '$parent',
'repre_count': {'$sum': 1}, # total representations
# fully available representation for site
'avail_repre_local': {'$sum': "$avail_ratio_local"},
'avail_repre_remote': {'$sum': "$avail_ratio_remote"},
}},
]
return query
class GroupMemberFilterProxyModel(QtCore.QSortFilterProxyModel):
"""Provide the feature of filtering group by the acceptance of members

View file

@ -567,12 +567,12 @@ class SubsetWidget(QtWidgets.QWidget):
# Trigger
project_name = self.dbcon.active_project()
subset_names_by_version_id = collections.defaultdict(set)
subset_name_by_version_id = dict()
for item in items:
version_id = item["version_document"]["_id"]
subset_names_by_version_id[version_id].add(item["subset"])
subset_name_by_version_id[version_id] = item["subset"]
version_ids = set(subset_names_by_version_id.keys())
version_ids = set(subset_name_by_version_id.keys())
repre_docs = get_representations(
project_name,
representation_names=[representation_name],
@ -584,14 +584,15 @@ class SubsetWidget(QtWidgets.QWidget):
for repre_doc in repre_docs:
repre_ids.append(repre_doc["_id"])
# keep only version ids without representation with that name
version_id = repre_doc["parent"]
if version_id not in version_ids:
version_ids.remove(version_id)
version_ids.discard(version_id)
for version_id in version_ids:
if version_ids:
# report versions that didn't have valid representation
joined_subset_names = ", ".join([
'"{}"'.format(subset)
for subset in subset_names_by_version_id[version_id]
'"{}"'.format(subset_name_by_version_id[version_id])
for version_id in version_ids
])
self.echo("Subsets {} don't have representation '{}'".format(
joined_subset_names, representation_name

View file

@ -8,6 +8,7 @@ from pymongo import UpdateOne, DeleteOne
from Qt import QtCore, QtGui
from openpype.client import (
get_projects,
get_project,
get_assets,
get_asset_ids_with_subsets,
@ -54,12 +55,8 @@ class ProjectModel(QtGui.QStandardItemModel):
self._items_by_name[None] = none_project
new_project_items.append(none_project)
project_docs = self.dbcon.projects(
projection={"name": 1},
only_active=True
)
project_names = set()
for project_doc in project_docs:
for project_doc in get_projects(fields=["name"]):
project_name = project_doc.get("name")
if not project_name:
continue

View file

@ -551,16 +551,16 @@ class SceneInventoryView(QtWidgets.QTreeView):
"toggle": selection_model.Toggle,
}[options.get("mode", "select")]
for item in iter_model_rows(model, 0):
item = item.data(InventoryModel.ItemRole)
for index in iter_model_rows(model, 0):
item = index.data(InventoryModel.ItemRole)
if item.get("isGroupNode"):
continue
name = item.get("objectName")
if name in object_names:
self.scrollTo(item) # Ensure item is visible
self.scrollTo(index) # Ensure item is visible
flags = select_mode | selection_model.Rows
selection_model.select(item, flags)
selection_model.select(index, flags)
object_names.remove(name)

View file

@ -4,8 +4,9 @@ import sys
from Qt import QtWidgets, QtCore
import qtawesome
from openpype.pipeline import legacy_io
from openpype import style
from openpype.client import get_projects
from openpype.pipeline import legacy_io
from openpype.tools.utils.delegates import VersionDelegate
from openpype.tools.utils.lib import (
qt_app_context,
@ -195,8 +196,7 @@ def show(root=None, debug=False, parent=None, items=None):
if not os.environ.get("AVALON_PROJECT"):
any_project = next(
project for project in legacy_io.projects()
if project.get("active", True) is not False
project for project in get_projects()
)
project_name = any_project["name"]

View file

@ -3,6 +3,7 @@ import uuid
from Qt import QtWidgets, QtCore, QtGui
import qtawesome
from openpype.client import get_projects
from openpype.pipeline import AvalonMongoDB
from openpype.style import get_objected_colors
from openpype.tools.utils.widgets import ImageButton
@ -783,8 +784,6 @@ class ProjectModel(QtGui.QStandardItemModel):
self.setColumnCount(2)
self.dbcon = None
self._only_active = only_active
self._default_item = None
self._items_by_name = {}
@ -828,9 +827,6 @@ class ProjectModel(QtGui.QStandardItemModel):
index = self.index(index.row(), 0, index.parent())
return super(ProjectModel, self).flags(index)
def set_dbcon(self, dbcon):
self.dbcon = dbcon
def refresh(self):
# Change id of versions refresh
self._version_refresh_id = uuid.uuid4()
@ -846,31 +842,30 @@ class ProjectModel(QtGui.QStandardItemModel):
self._default_item.setData("", PROJECT_VERSION_ROLE)
project_names = set()
if self.dbcon is not None:
for project_doc in self.dbcon.projects(
projection={"name": 1, "data.active": 1},
only_active=self._only_active
):
project_name = project_doc["name"]
project_names.add(project_name)
if project_name in self._items_by_name:
item = self._items_by_name[project_name]
else:
item = QtGui.QStandardItem(project_name)
for project_doc in get_projects(
inactive=not self._only_active,
fields=["name", "data.active"]
):
project_name = project_doc["name"]
project_names.add(project_name)
if project_name in self._items_by_name:
item = self._items_by_name[project_name]
else:
item = QtGui.QStandardItem(project_name)
self._items_by_name[project_name] = item
new_items.append(item)
self._items_by_name[project_name] = item
new_items.append(item)
is_active = project_doc.get("data", {}).get("active", True)
item.setData(project_name, PROJECT_NAME_ROLE)
item.setData(is_active, PROJECT_IS_ACTIVE_ROLE)
item.setData("", PROJECT_VERSION_ROLE)
item.setData(False, PROJECT_IS_SELECTED_ROLE)
is_active = project_doc.get("data", {}).get("active", True)
item.setData(project_name, PROJECT_NAME_ROLE)
item.setData(is_active, PROJECT_IS_ACTIVE_ROLE)
item.setData("", PROJECT_VERSION_ROLE)
item.setData(False, PROJECT_IS_SELECTED_ROLE)
if not is_active:
font = item.font()
font.setItalic(True)
item.setFont(font)
if not is_active:
font = item.font()
font.setItalic(True)
item.setFont(font)
root_item = self.invisibleRootItem()
for project_name in tuple(self._items_by_name.keys()):
@ -1067,8 +1062,6 @@ class ProjectListWidget(QtWidgets.QWidget):
self.project_model = project_model
self.inactive_chk = inactive_chk
self.dbcon = None
def set_entity(self, entity):
self._entity = entity
@ -1211,15 +1204,6 @@ class ProjectListWidget(QtWidgets.QWidget):
selected_project = index.data(PROJECT_NAME_ROLE)
break
if not self.dbcon:
try:
self.dbcon = AvalonMongoDB()
self.dbcon.install()
except Exception:
self.dbcon = None
self.current_project = None
self.project_model.set_dbcon(self.dbcon)
self.project_model.refresh()
self.project_proxy.sort(0)

View file

@ -3,6 +3,7 @@ from Qt import QtWidgets, QtCore
import qtawesome
from openpype.client import (
get_projects,
get_project,
get_asset_by_id,
)
@ -291,9 +292,7 @@ class AssetWidget(QtWidgets.QWidget):
def _set_projects(self):
project_names = list()
for doc in self.dbcon.projects(projection={"name": 1},
only_active=True):
for doc in get_projects(fields=["name"]):
project_name = doc.get("name")
if project_name:
project_names.append(project_name)
@ -320,8 +319,7 @@ class AssetWidget(QtWidgets.QWidget):
def on_project_change(self):
projects = list()
for project in self.dbcon.projects(projection={"name": 1},
only_active=True):
for project in get_projects(fields=["name"]):
projects.append(project['name'])
project_name = self.combo_projects.currentText()
if project_name in projects:

View file

@ -443,10 +443,6 @@ class FamilyConfigCache:
if profiles:
# Make sure connection is installed
# - accessing attribute which does not have auto-install
self.dbcon.install()
database = getattr(self.dbcon, "database", None)
if database is None:
database = self.dbcon._database
asset_doc = get_asset_by_name(
project_name, asset_name, fields=["data.tasks"]
) or {}

View file

@ -3,6 +3,7 @@ import logging
import Qt
from Qt import QtCore, QtGui
from openpype.client import get_projects
from .constants import (
PROJECT_IS_ACTIVE_ROLE,
PROJECT_NAME_ROLE,
@ -296,29 +297,29 @@ class ProjectModel(QtGui.QStandardItemModel):
self._default_item = item
project_names = set()
if self.dbcon is not None:
for project_doc in self.dbcon.projects(
projection={"name": 1, "data.active": 1},
only_active=self._only_active
):
project_name = project_doc["name"]
project_names.add(project_name)
if project_name in self._items_by_name:
item = self._items_by_name[project_name]
else:
item = QtGui.QStandardItem(project_name)
project_docs = get_projects(
inactive=not self._only_active,
fields=["name", "data.active"]
)
for project_doc in project_docs:
project_name = project_doc["name"]
project_names.add(project_name)
if project_name in self._items_by_name:
item = self._items_by_name[project_name]
else:
item = QtGui.QStandardItem(project_name)
self._items_by_name[project_name] = item
new_items.append(item)
self._items_by_name[project_name] = item
new_items.append(item)
is_active = project_doc.get("data", {}).get("active", True)
item.setData(project_name, PROJECT_NAME_ROLE)
item.setData(is_active, PROJECT_IS_ACTIVE_ROLE)
is_active = project_doc.get("data", {}).get("active", True)
item.setData(project_name, PROJECT_NAME_ROLE)
item.setData(is_active, PROJECT_IS_ACTIVE_ROLE)
if not is_active:
font = item.font()
font.setItalic(True)
item.setFont(font)
if not is_active:
font = item.font()
font.setItalic(True)
item.setFont(font)
root_item = self.invisibleRootItem()
for project_name in tuple(self._items_by_name.keys()):

View file

@ -12,7 +12,6 @@ from openpype.tools.utils import PlaceholderLineEdit
from openpype.tools.utils.delegates import PrettyTimeDelegate
from openpype.lib import (
emit_event,
get_workfile_template_key,
create_workdir_extra_folders,
)
from openpype.lib.avalon_context import (
@ -24,6 +23,8 @@ from openpype.pipeline import (
legacy_io,
Anatomy,
)
from openpype.pipeline.workfile import get_workfile_template_key
from .model import (
WorkAreaFilesModel,
PublishFilesModel,

View file

@ -5,11 +5,11 @@ import logging
from Qt import QtWidgets, QtCore
from openpype.lib import get_last_workfile_with_version
from openpype.pipeline import (
registered_host,
legacy_io,
)
from openpype.pipeline.workfile import get_last_workfile_with_version
from openpype.pipeline.template_data import get_template_data_with_names
from openpype.tools.utils import PlaceholderLineEdit

View file

@ -1,18 +1,20 @@
import os
import datetime
import copy
from Qt import QtCore, QtWidgets, QtGui
from openpype.client import (
get_asset_by_id,
get_asset_by_name,
get_workfile_info,
)
from openpype.client.operations import (
OperationsSession,
new_workfile_info_doc,
prepare_workfile_info_update_data,
)
from openpype import style
from openpype import resources
from openpype.lib import (
create_workfile_doc,
save_workfile_data_to_doc,
)
from openpype.pipeline import Anatomy
from openpype.pipeline import legacy_io
from openpype.tools.utils.assets_widget import SingleSelectAssetsWidget
from openpype.tools.utils.tasks_widget import TasksWidget
@ -324,10 +326,23 @@ class Window(QtWidgets.QWidget):
workfile_doc, data = self.side_panel.get_workfile_data()
if not workfile_doc:
filepath = self.files_widget._get_selected_filepath()
self._create_workfile_doc(filepath, force=True)
workfile_doc = self._get_current_workfile_doc()
workfile_doc = self._create_workfile_doc(filepath)
save_workfile_data_to_doc(workfile_doc, data, legacy_io)
new_workfile_doc = copy.deepcopy(workfile_doc)
new_workfile_doc["data"] = data
update_data = prepare_workfile_info_update_data(
workfile_doc, new_workfile_doc
)
if not update_data:
return
project_name = legacy_io.active_project()
session = OperationsSession()
session.update_entity(
project_name, "workfile", workfile_doc["_id"], update_data
)
session.commit()
def _get_current_workfile_doc(self, filepath=None):
if filepath is None:
@ -343,20 +358,32 @@ class Window(QtWidgets.QWidget):
project_name, asset_id, task_name, filename
)
def _create_workfile_doc(self, filepath, force=False):
workfile_doc = None
if not force:
workfile_doc = self._get_current_workfile_doc(filepath)
def _create_workfile_doc(self, filepath):
workfile_doc = self._get_current_workfile_doc(filepath)
if workfile_doc:
return workfile_doc
if not workfile_doc:
workdir, filename = os.path.split(filepath)
asset_id = self.assets_widget.get_selected_asset_id()
project_name = legacy_io.active_project()
asset_doc = get_asset_by_id(project_name, asset_id)
task_name = self.tasks_widget.get_selected_task_name()
create_workfile_doc(
asset_doc, task_name, filename, workdir, legacy_io
)
workdir, filename = os.path.split(filepath)
project_name = legacy_io.active_project()
asset_id = self.assets_widget.get_selected_asset_id()
task_name = self.tasks_widget.get_selected_task_name()
anatomy = Anatomy(project_name)
success, rootless_dir = anatomy.find_root_template_from_path(workdir)
filepath = "/".join([
os.path.normpath(rootless_dir).replace("\\", "/"),
filename
])
workfile_doc = new_workfile_info_doc(
filename, asset_id, task_name, [filepath]
)
session = OperationsSession()
session.create_entity(project_name, "workfile", workfile_doc)
session.commit()
return workfile_doc
def refresh(self):
# Refresh asset widget