SyncServer - implemented priority in SummaryView

SummaryDetail not implemented
Still some kinks to iron out
This commit is contained in:
Petr Kalis 2021-04-30 18:40:40 +02:00
parent 81baab0372
commit ad87c65b75
3 changed files with 134 additions and 7 deletions

View file

@ -1,9 +1,11 @@
from Qt import QtCore
from Qt import QtCore, QtWidgets, QtGui
from Qt.QtCore import Qt
import attr
import abc
import six
from openpype.lib import PypeLogger
from avalon.vendor import qtawesome
log = PypeLogger().get_logger("SyncServer")
@ -164,3 +166,56 @@ def get_item_by_id(model, object_id):
index = model.get_index(object_id)
item = model.data(index, FullItemRole)
return item
class PriorityDelegate(QtWidgets.QStyledItemDelegate):
def paint(self, painter, option, index):
super(PriorityDelegate, self).paint(painter, option, index)
if option.widget.selectionModel().isSelected(index) or \
option.state & QtWidgets.QStyle.State_MouseOver:
edit_icon = qtawesome.icon("fa.edit", color="white")
state = QtGui.QIcon.On
mode = QtGui.QIcon.Selected
icon_side = 16
icon_rect = QtCore.QRect(
option.rect.left() + option.rect.width() - icon_side - 4,
option.rect.top() + ((option.rect.height() - icon_side) / 2),
icon_side,
icon_side
)
edit_icon.paint(
painter, icon_rect,
QtCore.Qt.AlignRight, mode, state
)
def createEditor(self, parent, option, index):
editor = PriorityLineEdit(
parent,
option.widget.selectionModel().selectedRows())
editor.setValidator(QtGui.QIntValidator(0, 1000, self))
editor.setFocus(True)
return editor
def setModelData(self, editor, model, index):
for index in editor.selected_idxs:
model.set_priority_data(index, editor.text())
class PriorityLineEdit(QtWidgets.QLineEdit):
"""Special LineEdit to consume Enter and store selected indexes"""
def __init__(self, parent=None, selected_idxs=None):
self.selected_idxs = selected_idxs
super(PriorityLineEdit, self).__init__(parent)
def keyPressEvent(self, event):
result = super(PriorityLineEdit, self).keyPressEvent(event)
if (
event.key() in (QtCore.Qt.Key_Return, QtCore.Qt.Key_Enter)
):
return event.accept()
return result

View file

@ -6,6 +6,7 @@ from Qt import QtCore
from Qt.QtCore import Qt
from avalon.tools.delegates import pretty_timestamp
from avalon.vendor import qtawesome
from openpype.lib import PypeLogger
@ -41,6 +42,8 @@ class _SyncRepresentationModel(QtCore.QAbstractTableModel):
PAGE_SIZE = 20 # default page size to query for
REFRESH_SEC = 5000 # in seconds, requery DB for new status
DEFAULT_PRIORITY = 50
@property
def dbcon(self):
"""
@ -79,6 +82,14 @@ class _SyncRepresentationModel(QtCore.QAbstractTableModel):
return self.COLUMN_LABELS[section][0] # return name
def get_column(self, index):
"""
Returns info about column
Args:
index (QModelIndex)
Returns:
(tuple): (COLUMN_NAME: COLUMN_LABEL)
"""
return self.COLUMN_LABELS[index]
def get_header_index(self, value):
@ -109,7 +120,8 @@ class _SyncRepresentationModel(QtCore.QAbstractTableModel):
than single page of records)
"""
if self.sync_server.is_paused() or \
self.sync_server.is_project_paused(self.project):
self.sync_server.is_project_paused(self.project) or \
self.is_editing:
return
self.refresh_started.emit()
self.beginResetModel()
@ -191,7 +203,7 @@ class _SyncRepresentationModel(QtCore.QAbstractTableModel):
self.sort = {self.SORT_BY_COLUMN[index]: order} # reset
# add last one
for key, val in backup_sort.items():
if key != '_id':
if key != '_id' and key != self.SORT_BY_COLUMN[index]:
self.sort[key] = val
break
# add default one
@ -363,7 +375,7 @@ class SyncRepresentationSummaryModel(_SyncRepresentationModel):
"updated_dt_remote", # remote created_dt
"files_count", # count of files
"files_size", # file size of all files
"context.asset", # priority TODO
"priority", # priority
"status" # status
]
@ -374,6 +386,8 @@ class SyncRepresentationSummaryModel(_SyncRepresentationModel):
'representation': lib.MultiSelectFilter('representation')
}
EDITABLE_COLUMNS = ["priority"]
refresh_started = QtCore.Signal()
refresh_finished = QtCore.Signal()
@ -413,6 +427,9 @@ class SyncRepresentationSummaryModel(_SyncRepresentationModel):
self._word_filter = None
self._column_filtering = {}
self.edit_icon = qtawesome.icon("fa.edit", color="white")
self.is_editing = False
self._word_filter = None
self._initialized = False
@ -472,7 +489,7 @@ class SyncRepresentationSummaryModel(_SyncRepresentationModel):
return item.status == lib.STATUS[2] and \
item.remote_progress < 1
if role == Qt.DisplayRole:
if role in (Qt.DisplayRole, Qt.EditRole):
# because of ImageDelegate
if header_value in ['remote_site', 'local_site']:
return ""
@ -549,7 +566,7 @@ class SyncRepresentationSummaryModel(_SyncRepresentationModel):
avg_progress_remote,
repre.get("files_count", 1),
lib.pretty_size(repre.get("files_size", 0)),
1,
repre.get("priority"),
lib.STATUS[repre.get("status", -1)],
files[0].get('path')
)
@ -668,6 +685,10 @@ class SyncRepresentationSummaryModel(_SyncRepresentationModel):
'$cond': [{'$size': "$order_local.paused"},
1,
0]},
'priority': {
'$cond': [{'$size': '$order_local.priority'},
{'$first': '$order_local.priority'},
self.DEFAULT_PRIORITY]},
}},
{'$group': {
'_id': '$_id',
@ -690,7 +711,8 @@ class SyncRepresentationSummaryModel(_SyncRepresentationModel):
'failed_local_tries': {'$sum': '$failed_local_tries'},
'paused_remote': {'$sum': '$paused_remote'},
'paused_local': {'$sum': '$paused_local'},
'updated_dt_local': {'$max': "$updated_dt_local"}
'updated_dt_local': {'$max': "$updated_dt_local"},
'priority': {'$max': "$priority"},
}},
{"$project": self.projection}
]
@ -772,6 +794,7 @@ class SyncRepresentationSummaryModel(_SyncRepresentationModel):
'updated_dt_local': 1,
'paused_remote': 1,
'paused_local': 1,
'priority': 1,
'status': {
'$switch': {
'branches': [
@ -818,6 +841,27 @@ class SyncRepresentationSummaryModel(_SyncRepresentationModel):
}
}
def set_priority_data(self, index, value):
"""
Sets 'priority' flag and value on active site for selected reprs.
Args:
index (QItemIndex): selected index from View
value (int): priority value
Updates DB
"""
repre_id = self.data(index, Qt.UserRole)
representation = list(self.dbcon.find({"type": "representation",
"_id": repre_id}))
if representation:
self.sync_server.update_db(self.project, None, None,
representation.pop(), self.active_site,
priority=value)
self.is_editing = False
self.refresh(None, self._rec_loaded)
class SyncRepresentationDetailModel(_SyncRepresentationModel):
"""
@ -901,6 +945,8 @@ class SyncRepresentationDetailModel(_SyncRepresentationModel):
self._initialized = False
self._column_filtering = {}
self.is_editing = False
self.sync_server = sync_server
# TODO think about admin mode
# this is for regular user, always only single local and single remote

View file

@ -171,6 +171,13 @@ class _SyncRepresentationWidget(QtWidgets.QWidget):
"""
Opens representation dialog with all files after doubleclick
"""
# priority editing
column_name = self.model.get_column(index.column())
if column_name[0] in self.model.EDITABLE_COLUMNS:
self.model.is_editing = True
self.table_view.openPersistentEditor(index)
return
_id = self.model.data(index, Qt.UserRole)
detail_window = SyncServerDetailWindow(
self.sync_server, _id, self.model.project)
@ -253,6 +260,11 @@ class _SyncRepresentationWidget(QtWidgets.QWidget):
actions_mapping[action] = self._remove_site
menu.addAction(action)
action = QtWidgets.QAction("Change priority")
action_kwarg_map[action] = self._get_action_kwargs(active_site)
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)
@ -397,6 +409,15 @@ class _SyncRepresentationWidget(QtWidgets.QWidget):
except OSError:
raise OSError('unsupported xdg-open call??')
def _change_priority(self, **kwargs):
"""Open editor to change priority on first selected row"""
if self._selected_ids:
index = self.model.get_index(self._selected_ids[0]) # column = 0
column_no = self.model.get_header_index("priority") # real column
real_index = self.model.index(index.row(), column_no)
self.model.is_editing = True
self.table_view.openPersistentEditor(real_index)
def _get_progress(self, item, site_name, opposite=False):
"""Returns progress value according to site (side)"""
progress = {'local': item.local_progress,
@ -470,6 +491,7 @@ class SyncRepresentationSummaryWidget(_SyncRepresentationWidget):
-1, Qt.AscendingOrder)
table_view.setAlternatingRowColors(True)
table_view.verticalHeader().hide()
table_view.viewport().setAttribute(QtCore.Qt.WA_Hover, True)
column = table_view.model().get_header_index("local_site")
delegate = ImageDelegate(self)
@ -479,6 +501,10 @@ class SyncRepresentationSummaryWidget(_SyncRepresentationWidget):
delegate = ImageDelegate(self)
table_view.setItemDelegateForColumn(column, delegate)
column = table_view.model().get_header_index("priority")
priority_delegate = lib.PriorityDelegate(self)
table_view.setItemDelegateForColumn(column, priority_delegate)
layout = QtWidgets.QVBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
layout.addLayout(top_bar_layout)