diff --git a/openpype/tools/sceneinventory/lib.py b/openpype/tools/sceneinventory/lib.py index 0ac7622d65..7653e1da89 100644 --- a/openpype/tools/sceneinventory/lib.py +++ b/openpype/tools/sceneinventory/lib.py @@ -1,3 +1,9 @@ +import os +from openpype_modules import sync_server + +from Qt import QtGui + + def walk_hierarchy(node): """Recursively yield group node.""" for child in node.children(): @@ -6,3 +12,71 @@ def walk_hierarchy(node): for _child in walk_hierarchy(child): yield _child + + +def get_site_icons(): + resource_path = os.path.join( + os.path.dirname(sync_server.sync_server_module.__file__), + "providers", + "resources" + ) + icons = {} + # TODO get from sync module + for provider in ["studio", "local_drive", "gdrive"]: + pix_url = "{}/{}.png".format(resource_path, provider) + icons[provider] = QtGui.QIcon(pix_url) + + return icons + + +def get_progress_for_repre(repre_doc, active_site, remote_site): + """ + Calculates average progress for representation. + + If site has created_dt >> fully available >> progress == 1 + + Could be calculated in aggregate if it would be too slow + Args: + repre_doc(dict): representation dict + Returns: + (dict) with active and remote sites progress + {'studio': 1.0, 'gdrive': -1} - gdrive site is not present + -1 is used to highlight the site should be added + {'studio': 1.0, 'gdrive': 0.0} - gdrive site is present, not + uploaded yet + """ + progress = {active_site: -1, remote_site: -1} + if not repre_doc: + return progress + + files = {active_site: 0, remote_site: 0} + doc_files = repre_doc.get("files") or [] + for doc_file in doc_files: + if not isinstance(doc_file, dict): + continue + + sites = doc_file.get("sites") or [] + for site in sites: + if ( + # Pype 2 compatibility + not isinstance(site, dict) + # Check if site name is one of progress sites + or site["name"] not in progress + ): + continue + + files[site["name"]] += 1 + norm_progress = max(progress[site["name"]], 0) + if site.get("created_dt"): + progress[site["name"]] = norm_progress + 1 + elif site.get("progress"): + progress[site["name"]] = norm_progress + site["progress"] + else: # site exists, might be failed, do not add again + progress[site["name"]] = 0 + + # for example 13 fully avail. files out of 26 >> 13/26 = 0.5 + avg_progress = { + active_site: progress[active_site] / max(files[active_site], 1), + remote_site: progress[remote_site] / max(files[remote_site], 1) + } + return avg_progress diff --git a/openpype/tools/sceneinventory/model.py b/openpype/tools/sceneinventory/model.py index bf7b296703..5962802c30 100644 --- a/openpype/tools/sceneinventory/model.py +++ b/openpype/tools/sceneinventory/model.py @@ -6,11 +6,14 @@ from Qt import QtCore, QtGui from avalon import api, io, style, schema from avalon.vendor import qtawesome -from avalon.tools import lib as tools_lib from avalon.lib import HeroVersionType from avalon.tools.models import TreeModel, Item -from . import lib +from .lib import ( + get_site_icons, + walk_hierarchy, + get_progress_for_repre +) from openpype.modules import ModulesManager @@ -37,7 +40,7 @@ class InventoryModel(TreeModel): manager = ModulesManager() sync_server = manager.modules_by_name["sync_server"] self.sync_enabled = sync_server.enabled - self._icons = {} + self._site_icons = {} self.active_site = self.remote_site = None self.active_provider = self.remote_provider = None @@ -66,11 +69,11 @@ class InventoryModel(TreeModel): self.active_provider = active_provider self.remote_site = remote_site self.remote_provider = remote_provider - self._icons = tools_lib.get_repre_icons() + self._site_icons = get_site_icons() if "active_site" not in self.Columns: self.Columns.append("active_site") if "remote_site" not in self.Columns: - self.Columns.extend("remote_site") + self.Columns.append("remote_site") def outdated(self, item): value = item.get("version") @@ -106,7 +109,7 @@ class InventoryModel(TreeModel): if self._hierarchy_view: # If current group is not outdated, check if any # outdated children. - for _node in lib.walk_hierarchy(item): + for _node in walk_hierarchy(item): if self.outdated(_node): return self.CHILD_OUTDATED_COLOR else: @@ -114,7 +117,7 @@ class InventoryModel(TreeModel): if self._hierarchy_view: # Although this is not a group item, we still need # to distinguish which one contain outdated child. - for _node in lib.walk_hierarchy(item): + for _node in walk_hierarchy(item): if self.outdated(_node): return self.CHILD_OUTDATED_COLOR.darker(150) @@ -142,9 +145,9 @@ class InventoryModel(TreeModel): if item.get("isGroupNode"): column_name = self.Columns[index.column()] if column_name == 'active_site': - return self._icons.get(item.get('active_site_provider')) + return self._site_icons.get(item.get('active_site_provider')) if column_name == 'remote_site': - return self._icons.get(item.get('remote_site_provider')) + return self._site_icons.get(item.get('remote_site_provider')) if role == QtCore.Qt.DisplayRole and item.get("isGroupNode"): column_name = self.Columns[index.column()] @@ -395,7 +398,7 @@ class InventoryModel(TreeModel): group_node["isGroupNode"] = True if self.sync_enabled: - progress = tools_lib.get_progress_for_repre( + progress = get_progress_for_repre( representation, self.active_site, self.remote_site ) group_node["active_site"] = self.active_site