diff --git a/openpype/modules/default_modules/sync_server/tray/delegates.py b/openpype/modules/default_modules/sync_server/tray/delegates.py
index 461b9fffb36..5ab809a8166 100644
--- a/openpype/modules/default_modules/sync_server/tray/delegates.py
+++ b/openpype/modules/default_modules/sync_server/tray/delegates.py
@@ -4,6 +4,18 @@
from openpype.lib import PypeLogger
from . import lib
+from openpype.tools.utils.constants import (
+ LOCAL_PROVIDER_ROLE,
+ REMOTE_PROVIDER_ROLE,
+ LOCAL_PROGRESS_ROLE,
+ REMOTE_PROGRESS_ROLE,
+ LOCAL_DATE_ROLE,
+ REMOTE_DATE_ROLE,
+ LOCAL_FAILED_ROLE,
+ REMOTE_FAILED_ROLE,
+ EDIT_ICON_ROLE
+)
+
log = PypeLogger().get_logger("SyncServer")
@@ -14,7 +26,7 @@ def paint(self, painter, option, index):
if option.widget.selectionModel().isSelected(index) or \
option.state & QtWidgets.QStyle.State_MouseOver:
- edit_icon = index.data(lib.EditIconRole)
+ edit_icon = index.data(EDIT_ICON_ROLE)
if not edit_icon:
return
@@ -38,7 +50,7 @@ def createEditor(self, parent, option, index):
editor = PriorityLineEdit(
parent,
option.widget.selectionModel().selectedRows())
- editor.setFocus(True)
+ editor.setFocus()
return editor
def setModelData(self, editor, model, index):
@@ -71,19 +83,30 @@ class ImageDelegate(QtWidgets.QStyledItemDelegate):
Prints icon of site and progress of synchronization
"""
- def __init__(self, parent=None):
+ def __init__(self, parent=None, side=None):
super(ImageDelegate, self).__init__(parent)
self.icons = {}
+ self.side = side
def paint(self, painter, option, index):
super(ImageDelegate, self).paint(painter, option, index)
option = QtWidgets.QStyleOptionViewItem(option)
option.showDecorationSelected = True
- provider = index.data(lib.ProviderRole)
- value = index.data(lib.ProgressRole)
- date_value = index.data(lib.DateRole)
- is_failed = index.data(lib.FailedRole)
+ if not self.side:
+ log.warning("No side provided, delegate won't work")
+ return
+
+ if self.side == 'local':
+ provider = index.data(LOCAL_PROVIDER_ROLE)
+ value = index.data(LOCAL_PROGRESS_ROLE)
+ date_value = index.data(LOCAL_DATE_ROLE)
+ is_failed = index.data(LOCAL_FAILED_ROLE)
+ else:
+ provider = index.data(REMOTE_PROVIDER_ROLE)
+ value = index.data(REMOTE_PROGRESS_ROLE)
+ date_value = index.data(REMOTE_DATE_ROLE)
+ is_failed = index.data(REMOTE_FAILED_ROLE)
if not self.icons.get(provider):
resource_path = os.path.dirname(__file__)
diff --git a/openpype/modules/default_modules/sync_server/tray/lib.py b/openpype/modules/default_modules/sync_server/tray/lib.py
index 25c600abd23..87344be634d 100644
--- a/openpype/modules/default_modules/sync_server/tray/lib.py
+++ b/openpype/modules/default_modules/sync_server/tray/lib.py
@@ -1,4 +1,3 @@
-from Qt import QtCore
import attr
import abc
import six
@@ -19,14 +18,6 @@
DUMMY_PROJECT = "No project configured"
-ProviderRole = QtCore.Qt.UserRole + 2
-ProgressRole = QtCore.Qt.UserRole + 4
-DateRole = QtCore.Qt.UserRole + 6
-FailedRole = QtCore.Qt.UserRole + 8
-HeaderNameRole = QtCore.Qt.UserRole + 10
-FullItemRole = QtCore.Qt.UserRole + 12
-EditIconRole = QtCore.Qt.UserRole + 14
-
@six.add_metaclass(abc.ABCMeta)
class AbstractColumnFilter:
@@ -161,7 +152,7 @@ def translate_provider_for_icon(sync_server, project, site):
return sync_server.get_provider_for_site(site=site)
-def get_item_by_id(model, object_id):
+def get_value_from_id_by_role(model, object_id, role):
+ """Return value from item with 'object_id' with 'role'."""
index = model.get_index(object_id)
- item = model.data(index, FullItemRole)
- return item
+ return model.data(index, role)
diff --git a/openpype/modules/default_modules/sync_server/tray/models.py b/openpype/modules/default_modules/sync_server/tray/models.py
index 713e167a6a2..80f41992cb3 100644
--- a/openpype/modules/default_modules/sync_server/tray/models.py
+++ b/openpype/modules/default_modules/sync_server/tray/models.py
@@ -13,6 +13,23 @@
from . import lib
+from openpype.tools.utils.constants import (
+ LOCAL_PROVIDER_ROLE,
+ REMOTE_PROVIDER_ROLE,
+ LOCAL_PROGRESS_ROLE,
+ REMOTE_PROGRESS_ROLE,
+ HEADER_NAME_ROLE,
+ EDIT_ICON_ROLE,
+ LOCAL_DATE_ROLE,
+ REMOTE_DATE_ROLE,
+ LOCAL_FAILED_ROLE,
+ REMOTE_FAILED_ROLE,
+ STATUS_ROLE,
+ PATH_ROLE,
+ ERROR_ROLE,
+ TRIES_ROLE
+)
+
log = PypeLogger().get_logger("SyncServer")
@@ -68,10 +85,68 @@ def headerData(self, section, orientation, role=Qt.DisplayRole):
if orientation == Qt.Horizontal:
return self.COLUMN_LABELS[section][1]
- if role == lib.HeaderNameRole:
+ if role == HEADER_NAME_ROLE:
if orientation == Qt.Horizontal:
return self.COLUMN_LABELS[section][0] # return name
+ def data(self, index, role):
+ item = self._data[index.row()]
+
+ header_value = self._header[index.column()]
+ if role == LOCAL_PROVIDER_ROLE:
+ return item.local_provider
+
+ if role == REMOTE_PROVIDER_ROLE:
+ return item.remote_provider
+
+ if role == LOCAL_PROGRESS_ROLE:
+ return item.local_progress
+
+ if role == REMOTE_PROGRESS_ROLE:
+ return item.remote_progress
+
+ if role == LOCAL_DATE_ROLE:
+ if item.created_dt:
+ return pretty_timestamp(item.created_dt)
+
+ if role == REMOTE_DATE_ROLE:
+ if item.sync_dt:
+ return pretty_timestamp(item.sync_dt)
+
+ if role == LOCAL_FAILED_ROLE:
+ return item.status == lib.STATUS[2] and \
+ item.local_progress < 1
+
+ if role == REMOTE_FAILED_ROLE:
+ return item.status == lib.STATUS[2] and \
+ item.remote_progress < 1
+
+ if role in (Qt.DisplayRole, Qt.EditRole):
+ # because of ImageDelegate
+ if header_value in ['remote_site', 'local_site']:
+ return ""
+
+ return attr.asdict(item)[self._header[index.column()]]
+
+ if role == EDIT_ICON_ROLE:
+ if self.can_edit and header_value in self.EDITABLE_COLUMNS:
+ return self.edit_icon
+
+ if role == PATH_ROLE:
+ return item.path
+
+ if role == ERROR_ROLE:
+ return item.error
+
+ if role == TRIES_ROLE:
+ return item.tries
+
+ if role == STATUS_ROLE:
+ return item.status
+
+ if role == Qt.UserRole:
+ return item._id
+
@property
def can_edit(self):
"""Returns true if some site is user local site, eg. could edit"""
@@ -456,55 +531,6 @@ def __init__(self, sync_server, header, project=None, parent=None):
self.timer.timeout.connect(self.tick)
self.timer.start(self.REFRESH_SEC)
- def data(self, index, role):
- item = self._data[index.row()]
-
- if role == lib.FullItemRole:
- return item
-
- header_value = self._header[index.column()]
- if role == lib.ProviderRole:
- if header_value == 'local_site':
- return item.local_provider
- if header_value == 'remote_site':
- return item.remote_provider
-
- if role == lib.ProgressRole:
- if header_value == 'local_site':
- return item.local_progress
- if header_value == 'remote_site':
- return item.remote_progress
-
- if role == lib.DateRole:
- if header_value == 'local_site':
- if item.created_dt:
- return pretty_timestamp(item.created_dt)
- if header_value == 'remote_site':
- if item.sync_dt:
- return pretty_timestamp(item.sync_dt)
-
- if role == lib.FailedRole:
- if header_value == 'local_site':
- return item.status == lib.STATUS[2] and \
- item.local_progress < 1
- if header_value == 'remote_site':
- return item.status == lib.STATUS[2] and \
- item.remote_progress < 1
-
- if role in (Qt.DisplayRole, Qt.EditRole):
- # because of ImageDelegate
- if header_value in ['remote_site', 'local_site']:
- return ""
-
- return attr.asdict(item)[self._header[index.column()]]
-
- if role == lib.EditIconRole:
- if self.can_edit and header_value in self.EDITABLE_COLUMNS:
- return self.edit_icon
-
- if role == Qt.UserRole:
- return item._id
-
def add_page_records(self, local_site, remote_site, representations):
"""
Process all records from 'representation' and add them to storage.
@@ -985,55 +1011,6 @@ def __init__(self, sync_server, header, _id,
self.timer.timeout.connect(self.tick)
self.timer.start(SyncRepresentationSummaryModel.REFRESH_SEC)
- def data(self, index, role):
- item = self._data[index.row()]
-
- if role == lib.FullItemRole:
- return item
-
- header_value = self._header[index.column()]
- if role == lib.ProviderRole:
- if header_value == 'local_site':
- return item.local_provider
- if header_value == 'remote_site':
- return item.remote_provider
-
- if role == lib.ProgressRole:
- if header_value == 'local_site':
- return item.local_progress
- if header_value == 'remote_site':
- return item.remote_progress
-
- if role == lib.DateRole:
- if header_value == 'local_site':
- if item.created_dt:
- return pretty_timestamp(item.created_dt)
- if header_value == 'remote_site':
- if item.sync_dt:
- return pretty_timestamp(item.sync_dt)
-
- if role == lib.FailedRole:
- if header_value == 'local_site':
- return item.status == lib.STATUS[2] and \
- item.local_progress < 1
- if header_value == 'remote_site':
- return item.status == lib.STATUS[2] and \
- item.remote_progress < 1
-
- if role in (Qt.DisplayRole, Qt.EditRole):
- # because of ImageDelegate
- if header_value in ['remote_site', 'local_site']:
- return ""
-
- return attr.asdict(item)[self._header[index.column()]]
-
- if role == lib.EditIconRole:
- if self.can_edit and header_value in self.EDITABLE_COLUMNS:
- return self.edit_icon
-
- if role == Qt.UserRole:
- return item._id
-
def add_page_records(self, local_site, remote_site, representations):
"""
Process all records from 'representation' and add them to storage.
diff --git a/openpype/modules/default_modules/sync_server/tray/widgets.py b/openpype/modules/default_modules/sync_server/tray/widgets.py
index 5e368f9e0b6..87044889b70 100644
--- a/openpype/modules/default_modules/sync_server/tray/widgets.py
+++ b/openpype/modules/default_modules/sync_server/tray/widgets.py
@@ -22,6 +22,20 @@
from . import lib
from . import delegates
+from openpype.tools.utils.constants import (
+ LOCAL_PROGRESS_ROLE,
+ REMOTE_PROGRESS_ROLE,
+ HEADER_NAME_ROLE,
+ STATUS_ROLE,
+ PATH_ROLE,
+ LOCAL_SITE_NAME_ROLE,
+ REMOTE_SITE_NAME_ROLE,
+ LOCAL_DATE_ROLE,
+ REMOTE_DATE_ROLE,
+ ERROR_ROLE,
+ TRIES_ROLE
+)
+
log = PypeLogger().get_logger("SyncServer")
@@ -289,14 +303,19 @@ def _on_context_menu(self, point):
if is_multi:
index = self.model.get_index(list(self._selected_ids)[0])
- item = self.model.data(index, lib.FullItemRole)
+ local_progress = self.model.data(index, LOCAL_PROGRESS_ROLE)
+ remote_progress = self.model.data(index, REMOTE_PROGRESS_ROLE)
+ status = self.model.data(index, STATUS_ROLE)
else:
- item = self.model.data(point_index, lib.FullItemRole)
+ local_progress = self.model.data(point_index, LOCAL_PROGRESS_ROLE)
+ remote_progress = self.model.data(point_index,
+ REMOTE_PROGRESS_ROLE)
+ status = self.model.data(point_index, STATUS_ROLE)
+
can_edit = self.model.can_edit
- action_kwarg_map, actions_mapping, menu = self._prepare_menu(item,
- is_multi,
- can_edit)
+ action_kwarg_map, actions_mapping, menu = self._prepare_menu(
+ local_progress, remote_progress, is_multi, can_edit, status)
result = menu.exec_(QtGui.QCursor.pos())
if result:
@@ -307,7 +326,8 @@ def _on_context_menu(self, point):
self.model.refresh()
- def _prepare_menu(self, item, is_multi, can_edit):
+ def _prepare_menu(self, local_progress, remote_progress,
+ is_multi, can_edit, status=None):
menu = QtWidgets.QMenu(self)
actions_mapping = {}
@@ -316,11 +336,6 @@ def _prepare_menu(self, item, is_multi, can_edit):
active_site = self.model.active_site
remote_site = self.model.remote_site
- local_progress = item.local_progress
- remote_progress = item.remote_progress
-
- project = self.model.project
-
for site, progress in {active_site: local_progress,
remote_site: remote_progress}.items():
provider = self.sync_server.get_provider_for_site(site=site)
@@ -360,12 +375,6 @@ def _prepare_menu(self, item, is_multi, can_edit):
actions_mapping[action] = self._change_priority
menu.addAction(action)
- # # temp for testing only !!!
- # action = QtWidgets.QAction("Download")
- # action_kwarg_map[action] = self._get_action_kwargs(active_site)
- # actions_mapping[action] = self._add_site
- # menu.addAction(action)
-
if not actions_mapping:
action = QtWidgets.QAction("< No action >")
actions_mapping[action] = None
@@ -376,11 +385,15 @@ def _prepare_menu(self, item, is_multi, can_edit):
def _pause(self, selected_ids=None):
log.debug("Pause {}".format(selected_ids))
for representation_id in selected_ids:
- item = lib.get_item_by_id(self.model, representation_id)
- if item.status not in [lib.STATUS[0], lib.STATUS[1]]:
+ status = lib.get_value_from_id_by_role(self.model,
+ representation_id,
+ STATUS_ROLE)
+ if status not in [lib.STATUS[0], lib.STATUS[1]]:
continue
for site_name in [self.model.active_site, self.model.remote_site]:
- check_progress = self._get_progress(item, site_name)
+ check_progress = self._get_progress(self.model,
+ representation_id,
+ site_name)
if check_progress < 1:
self.sync_server.pause_representation(self.model.project,
representation_id,
@@ -391,11 +404,15 @@ def _pause(self, selected_ids=None):
def _unpause(self, selected_ids=None):
log.debug("UnPause {}".format(selected_ids))
for representation_id in selected_ids:
- item = lib.get_item_by_id(self.model, representation_id)
- if item.status not in lib.STATUS[3]:
+ status = lib.get_value_from_id_by_role(self.model,
+ representation_id,
+ STATUS_ROLE)
+ if status not in lib.STATUS[3]:
continue
for site_name in [self.model.active_site, self.model.remote_site]:
- check_progress = self._get_progress(item, site_name)
+ check_progress = self._get_progress(self.model,
+ representation_id,
+ site_name)
if check_progress < 1:
self.sync_server.unpause_representation(
self.model.project,
@@ -408,8 +425,11 @@ def _unpause(self, selected_ids=None):
def _add_site(self, selected_ids=None, site_name=None):
log.debug("Add site {}:{}".format(selected_ids, site_name))
for representation_id in selected_ids:
- item = lib.get_item_by_id(self.model, representation_id)
- if item.local_site == site_name or item.remote_site == site_name:
+ item_local_site = lib.get_value_from_id_by_role(
+ self.model, representation_id, LOCAL_SITE_NAME_ROLE)
+ item_remote_site = lib.get_value_from_id_by_role(
+ self.model, representation_id, REMOTE_SITE_NAME_ROLE)
+ if site_name in [item_local_site, item_remote_site]:
# site already exists skip
continue
@@ -460,8 +480,8 @@ def _reset_site(self, selected_ids=None, site_name=None):
"""
log.debug("Reset site {}:{}".format(selected_ids, site_name))
for representation_id in selected_ids:
- item = lib.get_item_by_id(self.model, representation_id)
- check_progress = self._get_progress(item, site_name, True)
+ check_progress = self._get_progress(self.model, representation_id,
+ site_name, True)
# do not reset if opposite side is not fully there
if check_progress != 1:
@@ -482,11 +502,8 @@ def _reset_site(self, selected_ids=None, site_name=None):
def _open_in_explorer(self, selected_ids=None, site_name=None):
log.debug("Open in Explorer {}:{}".format(selected_ids, site_name))
for selected_id in selected_ids:
- item = lib.get_item_by_id(self.model, selected_id)
- if not item:
- return
-
- fpath = item.path
+ fpath = lib.get_value_from_id_by_role(self.model, selected_id,
+ PATH_ROLE)
project = self.model.project
fpath = self.sync_server.get_local_file_path(project,
site_name,
@@ -514,10 +531,17 @@ def _change_priority(self, **kwargs):
self.model.is_editing = True
self.table_view.openPersistentEditor(real_index)
- def _get_progress(self, item, site_name, opposite=False):
+ def _get_progress(self, model, representation_id,
+ site_name, opposite=False):
"""Returns progress value according to site (side)"""
- progress = {'local': item.local_progress,
- 'remote': item.remote_progress}
+ local_progress = lib.get_value_from_id_by_role(model,
+ representation_id,
+ LOCAL_PROGRESS_ROLE)
+ remote_progress = lib.get_value_from_id_by_role(model,
+ representation_id,
+ REMOTE_PROGRESS_ROLE)
+ progress = {'local': local_progress,
+ 'remote': remote_progress}
side = 'remote'
if site_name == self.model.active_site:
side = 'local'
@@ -591,11 +615,11 @@ def __init__(self, sync_server, project=None, parent=None):
table_view.viewport().setAttribute(QtCore.Qt.WA_Hover, True)
column = table_view.model().get_header_index("local_site")
- delegate = delegates.ImageDelegate(self)
+ delegate = delegates.ImageDelegate(self, side="local")
table_view.setItemDelegateForColumn(column, delegate)
column = table_view.model().get_header_index("remote_site")
- delegate = delegates.ImageDelegate(self)
+ delegate = delegates.ImageDelegate(self, side="remote")
table_view.setItemDelegateForColumn(column, delegate)
column = table_view.model().get_header_index("priority")
@@ -631,19 +655,21 @@ def __init__(self, sync_server, project=None, parent=None):
self.selection_model = self.table_view.selectionModel()
self.selection_model.selectionChanged.connect(self._selection_changed)
- def _prepare_menu(self, item, is_multi, can_edit):
+ def _prepare_menu(self, local_progress, remote_progress,
+ is_multi, can_edit, status=None):
action_kwarg_map, actions_mapping, menu = \
- super()._prepare_menu(item, is_multi, can_edit)
+ super()._prepare_menu(local_progress, remote_progress,
+ is_multi, can_edit)
if can_edit and (
- item.status in [lib.STATUS[0], lib.STATUS[1]] or is_multi):
+ status in [lib.STATUS[0], lib.STATUS[1]] or is_multi):
action = QtWidgets.QAction("Pause in queue")
actions_mapping[action] = self._pause
# pause handles which site_name it will pause itself
action_kwarg_map[action] = {"selected_ids": self._selected_ids}
menu.addAction(action)
- if can_edit and (item.status == lib.STATUS[3] or is_multi):
+ if can_edit and (status == lib.STATUS[3] or is_multi):
action = QtWidgets.QAction("Unpause in queue")
actions_mapping[action] = self._unpause
action_kwarg_map[action] = {"selected_ids": self._selected_ids}
@@ -753,11 +779,11 @@ def __init__(self, sync_server, _id=None, project=None, parent=None):
table_view.verticalHeader().hide()
column = model.get_header_index("local_site")
- delegate = delegates.ImageDelegate(self)
+ delegate = delegates.ImageDelegate(self, side="local")
table_view.setItemDelegateForColumn(column, delegate)
column = model.get_header_index("remote_site")
- delegate = delegates.ImageDelegate(self)
+ delegate = delegates.ImageDelegate(self, side="remote")
table_view.setItemDelegateForColumn(column, delegate)
if model.can_edit:
@@ -815,12 +841,14 @@ def _show_detail(self, selected_ids=None):
detail_window.exec()
- def _prepare_menu(self, item, is_multi, can_edit):
+ def _prepare_menu(self, local_progress, remote_progress,
+ is_multi, can_edit, status=None):
"""Adds view (and model) dependent actions to default ones"""
action_kwarg_map, actions_mapping, menu = \
- super()._prepare_menu(item, is_multi, can_edit)
+ super()._prepare_menu(local_progress, remote_progress,
+ is_multi, can_edit, status)
- if item.status == lib.STATUS[2] or is_multi:
+ if status == lib.STATUS[2] or is_multi:
action = QtWidgets.QAction("Open error detail")
actions_mapping[action] = self._show_detail
action_kwarg_map[action] = {"selected_ids": self._selected_ids}
@@ -835,8 +863,8 @@ def _reset_site(self, selected_ids=None, site_name=None):
redo of upload/download
"""
for file_id in selected_ids:
- item = lib.get_item_by_id(self.model, file_id)
- check_progress = self._get_progress(item, site_name, True)
+ check_progress = self._get_progress(self.model, file_id,
+ site_name, True)
# do not reset if opposite side is not fully there
if check_progress != 1:
@@ -895,20 +923,28 @@ def __init__(self, model, selected_ids, parent=None):
no_errors = True
for file_id in selected_ids:
- item = lib.get_item_by_id(model, file_id)
- if not item.created_dt or not item.sync_dt or not item.error:
+ created_dt = lib.get_value_from_id_by_role(model, file_id,
+ LOCAL_DATE_ROLE)
+ sync_dt = lib.get_value_from_id_by_role(model, file_id,
+ REMOTE_DATE_ROLE)
+ errors = lib.get_value_from_id_by_role(model, file_id,
+ ERROR_ROLE)
+ if not created_dt or not sync_dt or not errors:
continue
+ tries = lib.get_value_from_id_by_role(model, file_id,
+ TRIES_ROLE)
+
no_errors = False
- dt = max(item.created_dt, item.sync_dt)
+ dt = max(created_dt, sync_dt)
txts = []
txts.append("{}: {}
".format("Last update date",
pretty_timestamp(dt)))
txts.append("{}: {}
".format("Retries",
- str(item.tries)))
+ str(tries)))
txts.append("{}: {}
".format("Error message",
- item.error))
+ errors))
text_area = QtWidgets.QTextEdit("\n\n".join(txts))
text_area.setReadOnly(True)
@@ -1162,7 +1198,7 @@ def _fix_size(self):
column_name = self.model.headerData(column_idx,
QtCore.Qt.Horizontal,
- lib.HeaderNameRole)
+ HEADER_NAME_ROLE)
button = self.filter_buttons.get(column_name)
if not button:
continue
diff --git a/openpype/tools/libraryloader/app.py b/openpype/tools/libraryloader/app.py
index d7c6c162e64..d9fdf338f03 100644
--- a/openpype/tools/libraryloader/app.py
+++ b/openpype/tools/libraryloader/app.py
@@ -405,7 +405,8 @@ def _assetschanged(self):
self.data["state"]["assetIds"] = asset_ids
# reset repre list
- self._repres_widget.set_version_ids([])
+ if self._repres_widget:
+ self._repres_widget.set_version_ids([])
def _subsetschanged(self):
asset_ids = self.data["state"]["assetIds"]
@@ -495,7 +496,8 @@ def _versionschanged(self):
self._thumbnail_widget.set_thumbnail(thumbnail_docs)
version_ids = [doc["_id"] for doc in version_docs or []]
- self._repres_widget.set_version_ids(version_ids)
+ if self._repres_widget:
+ self._repres_widget.set_version_ids(version_ids)
def _set_context(self, context, refresh=True):
"""Set the selection in the interface using a context.
diff --git a/openpype/tools/loader/model.py b/openpype/tools/loader/model.py
index 6e9c7bf2207..d81fc11cf2d 100644
--- a/openpype/tools/loader/model.py
+++ b/openpype/tools/loader/model.py
@@ -15,6 +15,12 @@
from openpype.tools.utils import lib
from openpype.modules import ModulesManager
+from openpype.tools.utils.constants import (
+ LOCAL_PROVIDER_ROLE,
+ REMOTE_PROVIDER_ROLE,
+ LOCAL_AVAILABILITY_ROLE,
+ REMOTE_AVAILABILITY_ROLE
+)
def is_filtering_recursible():
@@ -333,7 +339,6 @@ def set_version(self, index, version):
repre_info = version_data.get("repre_info")
if repre_info:
item["repre_info"] = repre_info
- item["repre_icon"] = version_data.get("repre_icon")
def _fetch(self):
asset_docs = self.dbcon.find(
@@ -445,14 +450,16 @@ def _fetch(self):
for _subset_id, doc in last_versions_by_subset_id.items():
version_ids.add(doc["_id"])
- site = self.active_site
- query = self._repre_per_version_pipeline(list(version_ids), site)
+ query = self._repre_per_version_pipeline(list(version_ids),
+ self.active_site,
+ self.remote_site)
repre_info = {}
for doc in self.dbcon.aggregate(query):
if self._doc_fetching_stop:
return
- doc["provider"] = self.active_provider
+ doc["active_provider"] = self.active_provider
+ doc["remote_provider"] = self.remote_provider
repre_info[doc["_id"]] = doc
self._doc_payload["repre_info_by_version_id"] = repre_info
@@ -666,8 +673,8 @@ def data(self, index, role):
if not index.isValid():
return
+ item = index.internalPointer()
if role == self.SortDescendingRole:
- item = index.internalPointer()
if item.get("isGroup"):
# Ensure groups be on top when sorting by descending order
prefix = "2"
@@ -683,7 +690,6 @@ def data(self, index, role):
return prefix + order
if role == self.SortAscendingRole:
- item = index.internalPointer()
if item.get("isGroup"):
# Ensure groups be on top when sorting by ascending order
prefix = "0"
@@ -701,14 +707,12 @@ def data(self, index, role):
if role == QtCore.Qt.DisplayRole:
if index.column() == self.columns_index["family"]:
# Show familyLabel instead of family
- item = index.internalPointer()
return item.get("familyLabel", None)
elif role == QtCore.Qt.DecorationRole:
# Add icon to subset column
if index.column() == self.columns_index["subset"]:
- item = index.internalPointer()
if item.get("isGroup") or item.get("isMerged"):
return item["icon"]
else:
@@ -716,20 +720,32 @@ def data(self, index, role):
# Add icon to family column
if index.column() == self.columns_index["family"]:
- item = index.internalPointer()
return item.get("familyIcon", None)
- if index.column() == self.columns_index.get("repre_info"):
- item = index.internalPointer()
- return item.get("repre_icon", None)
-
elif role == QtCore.Qt.ForegroundRole:
- item = index.internalPointer()
version_doc = item.get("version_document")
if version_doc and version_doc.get("type") == "hero_version":
if not version_doc["is_from_latest"]:
return self.not_last_hero_brush
+ elif role == LOCAL_AVAILABILITY_ROLE:
+ if not item.get("isGroup"):
+ return item.get("repre_info_local")
+ else:
+ return None
+
+ elif role == REMOTE_AVAILABILITY_ROLE:
+ if not item.get("isGroup"):
+ return item.get("repre_info_remote")
+ else:
+ return None
+
+ elif role == LOCAL_PROVIDER_ROLE:
+ return self.active_provider
+
+ elif role == REMOTE_PROVIDER_ROLE:
+ return self.remote_provider
+
return super(SubsetsModel, self).data(index, role)
def flags(self, index):
@@ -759,19 +775,25 @@ def _get_last_repre_info(self, repre_info_by_version_id, last_version_id):
return data
def _get_repre_dict(self, repre_info):
- """Returns icon and str representation of availability"""
+ """Returns str representation of availability"""
data = {}
if repre_info:
repres_str = "{}/{}".format(
- int(math.floor(float(repre_info['avail_repre']))),
+ int(math.floor(float(repre_info['avail_repre_local']))),
+ int(math.floor(float(repre_info['repre_count']))))
+
+ data["repre_info_local"] = repres_str
+
+ repres_str = "{}/{}".format(
+ int(math.floor(float(repre_info['avail_repre_remote']))),
int(math.floor(float(repre_info['repre_count']))))
- data["repre_info"] = repres_str
- data["repre_icon"] = self.repre_icons.get(self.active_provider)
+ data["repre_info_remote"] = repres_str
return data
- def _repre_per_version_pipeline(self, version_ids, site):
+ def _repre_per_version_pipeline(self, version_ids,
+ active_site, remote_site):
query = [
{"$match": {"parent": {"$in": version_ids},
"type": "representation",
@@ -780,7 +802,13 @@ def _repre_per_version_pipeline(self, version_ids, site):
{'$addFields': {
'order_local': {
'$filter': {'input': '$files.sites', 'as': 'p',
- 'cond': {'$eq': ['$$p.name', site]}
+ 'cond': {'$eq': ['$$p.name', active_site]}
+ }}
+ }},
+ {'$addFields': {
+ 'order_remote': {
+ '$filter': {'input': '$files.sites', 'as': 'p',
+ 'cond': {'$eq': ['$$p.name', remote_site]}
}}
}},
{'$addFields': {
@@ -795,19 +823,32 @@ def _repre_per_version_pipeline(self, version_ids, site):
]}
]}, 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'},
- 'files_count': {'$sum': 1},
- 'files_avail': {'$sum': "$progress_local"},
- 'avail_ratio': {'$first': {
- '$divide': [{'$sum': "$progress_local"}, {'$sum': 1}]}}
+ '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': {'$sum': "$avail_ratio"}
+ 'avail_repre_local': {'$sum': "$avail_ratio_local"},
+ 'avail_repre_remote': {'$sum': "$avail_ratio_remote"},
}},
]
return query
diff --git a/openpype/tools/loader/widgets.py b/openpype/tools/loader/widgets.py
index 4c075382aca..08b58eebbe7 100644
--- a/openpype/tools/loader/widgets.py
+++ b/openpype/tools/loader/widgets.py
@@ -31,6 +31,13 @@
)
from . import lib
+from openpype.tools.utils.constants import (
+ LOCAL_PROVIDER_ROLE,
+ REMOTE_PROVIDER_ROLE,
+ LOCAL_AVAILABILITY_ROLE,
+ REMOTE_AVAILABILITY_ROLE
+)
+
class OverlayFrame(QtWidgets.QFrame):
def __init__(self, label, parent):
@@ -197,6 +204,10 @@ def __init__(
column = model.Columns.index("time")
view.setItemDelegateForColumn(column, time_delegate)
+ avail_delegate = AvailabilityDelegate(self.dbcon, view)
+ column = model.Columns.index("repre_info")
+ view.setItemDelegateForColumn(column, avail_delegate)
+
layout = QtWidgets.QVBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
layout.addLayout(top_bar_layout)
@@ -1578,3 +1589,54 @@ def _load_subsets_by_loader(loader, subset_contexts, options,
))
return error_info
+
+
+class AvailabilityDelegate(QtWidgets.QStyledItemDelegate):
+ """
+ Prints icons and downloaded representation ration for both sides.
+ """
+
+ def __init__(self, dbcon, parent=None):
+ super(AvailabilityDelegate, self).__init__(parent)
+ self.icons = tools_lib.get_repre_icons()
+
+ def paint(self, painter, option, index):
+ super(AvailabilityDelegate, self).paint(painter, option, index)
+ option = QtWidgets.QStyleOptionViewItem(option)
+ option.showDecorationSelected = True
+
+ provider_active = index.data(LOCAL_PROVIDER_ROLE)
+ provider_remote = index.data(REMOTE_PROVIDER_ROLE)
+
+ availability_active = index.data(LOCAL_AVAILABILITY_ROLE)
+ availability_remote = index.data(REMOTE_AVAILABILITY_ROLE)
+
+ if not availability_active or not availability_remote: # group lines
+ return
+
+ idx = 0
+ height = width = 24
+ for value, provider in [(availability_active, provider_active),
+ (availability_remote, provider_remote)]:
+ icon = self.icons.get(provider)
+ if not icon:
+ continue
+
+ pixmap = icon.pixmap(icon.actualSize(QtCore.QSize(height, width)))
+ padding = 10 + (70 * idx)
+ point = QtCore.QPoint(option.rect.x() + padding,
+ option.rect.y() +
+ (option.rect.height() - pixmap.height()) / 2)
+ painter.drawPixmap(point, pixmap)
+
+ text_rect = option.rect.translated(padding + width + 10, 0)
+ painter.drawText(
+ text_rect,
+ option.displayAlignment,
+ value
+ )
+
+ idx += 1
+
+ def displayText(self, value, locale):
+ pass
diff --git a/openpype/tools/utils/constants.py b/openpype/tools/utils/constants.py
index 0e940a55957..5b6f4126c99 100644
--- a/openpype/tools/utils/constants.py
+++ b/openpype/tools/utils/constants.py
@@ -8,3 +8,22 @@
TASK_NAME_ROLE = QtCore.Qt.UserRole + 301
TASK_TYPE_ROLE = QtCore.Qt.UserRole + 302
TASK_ORDER_ROLE = QtCore.Qt.UserRole + 403
+
+LOCAL_PROVIDER_ROLE = QtCore.Qt.UserRole + 500 # provider of active site
+REMOTE_PROVIDER_ROLE = QtCore.Qt.UserRole + 501 # provider of remote site
+LOCAL_PROGRESS_ROLE = QtCore.Qt.UserRole + 502 # percentage downld on active
+REMOTE_PROGRESS_ROLE = QtCore.Qt.UserRole + 503 # percentage upload on remote
+LOCAL_AVAILABILITY_ROLE = QtCore.Qt.UserRole + 504 # ratio of presence active
+REMOTE_AVAILABILITY_ROLE = QtCore.Qt.UserRole + 505
+LOCAL_DATE_ROLE = QtCore.Qt.UserRole + 506 # created_dt on active site
+REMOTE_DATE_ROLE = QtCore.Qt.UserRole + 507
+LOCAL_FAILED_ROLE = QtCore.Qt.UserRole + 508
+REMOTE_FAILED_ROLE = QtCore.Qt.UserRole + 509
+HEADER_NAME_ROLE = QtCore.Qt.UserRole + 510
+EDIT_ICON_ROLE = QtCore.Qt.UserRole + 511
+STATUS_ROLE = QtCore.Qt.UserRole + 512
+PATH_ROLE = QtCore.Qt.UserRole + 513
+LOCAL_SITE_NAME_ROLE = QtCore.Qt.UserRole + 514
+REMOTE_SITE_NAME_ROLE = QtCore.Qt.UserRole + 515
+ERROR_ROLE = QtCore.Qt.UserRole + 516
+TRIES_ROLE = QtCore.Qt.UserRole + 517