Merge branch 'develop' of github.com:pypeclub/OpenPype into bugfix/sftp_provider_sync_import

This commit is contained in:
Petr Kalis 2021-10-05 14:58:21 +02:00
commit bd020bb606
7 changed files with 150 additions and 56 deletions

View file

@ -3,4 +3,17 @@ from avalon.tvpaint import pipeline
class Creator(PypeCreatorMixin, pipeline.Creator):
pass
@classmethod
def get_dynamic_data(cls, *args, **kwargs):
dynamic_data = super(Creator, cls).get_dynamic_data(*args, **kwargs)
# Change asset and name by current workfile context
workfile_context = pipeline.get_current_workfile_context()
asset_name = workfile_context.get("asset")
task_name = workfile_context.get("task")
if "asset" not in dynamic_data and asset_name:
dynamic_data["asset"] = asset_name
if "task" not in dynamic_data and task_name:
dynamic_data["task"] = task_name
return dynamic_data

View file

@ -10,6 +10,7 @@ from openpype_modules.ftrack.lib import (
CUST_ATTR_GROUP,
CUST_ATTR_TOOLS,
CUST_ATTR_APPLICATIONS,
CUST_ATTR_INTENT,
default_custom_attributes_definition,
app_definitions_from_app_manager,
@ -431,7 +432,7 @@ class CustomAttributes(BaseAction):
intent_custom_attr_data = {
"label": "Intent",
"key": "intent",
"key": CUST_ATTR_INTENT,
"type": "enumerator",
"entity_type": "assetversion",
"group": CUST_ATTR_GROUP,

View file

@ -230,7 +230,13 @@ class FtrackModule(
return
import ftrack_api
from openpype_modules.ftrack.lib import get_openpype_attr
from openpype_modules.ftrack.lib import (
get_openpype_attr,
default_custom_attributes_definition,
CUST_ATTR_TOOLS,
CUST_ATTR_APPLICATIONS,
CUST_ATTR_INTENT
)
try:
session = self.create_ftrack_session()
@ -255,6 +261,15 @@ class FtrackModule(
project_id = project_entity["id"]
ca_defs = default_custom_attributes_definition()
hierarchical_attrs = ca_defs.get("is_hierarchical") or {}
project_attrs = ca_defs.get("show") or {}
ca_keys = (
set(hierarchical_attrs.keys())
| set(project_attrs.keys())
| {CUST_ATTR_TOOLS, CUST_ATTR_APPLICATIONS, CUST_ATTR_INTENT}
)
cust_attr, hier_attr = get_openpype_attr(session)
cust_attr_by_key = {attr["key"]: attr for attr in cust_attr}
hier_attrs_by_key = {attr["key"]: attr for attr in hier_attr}
@ -262,6 +277,9 @@ class FtrackModule(
failed = {}
missing = {}
for key, value in attributes_changes.items():
if key not in ca_keys:
continue
configuration = hier_attrs_by_key.get(key)
if not configuration:
configuration = cust_attr_by_key.get(key)

View file

@ -3,7 +3,8 @@ from .constants import (
CUST_ATTR_AUTO_SYNC,
CUST_ATTR_GROUP,
CUST_ATTR_TOOLS,
CUST_ATTR_APPLICATIONS
CUST_ATTR_APPLICATIONS,
CUST_ATTR_INTENT
)
from .settings import (
get_ftrack_event_mongo_info

View file

@ -10,3 +10,5 @@ CUST_ATTR_AUTO_SYNC = "avalon_auto_sync"
CUST_ATTR_APPLICATIONS = "applications"
# Environment tools custom attribute
CUST_ATTR_TOOLS = "tools_env"
# Intent custom attribute name
CUST_ATTR_INTENT = "intent"

View file

@ -0,0 +1,16 @@
from Qt import QtCore
DEFAULT_PROJECT_LABEL = "< Default >"
PROJECT_NAME_ROLE = QtCore.Qt.UserRole + 1
PROJECT_IS_ACTIVE_ROLE = QtCore.Qt.UserRole + 2
PROJECT_IS_SELECTED_ROLE = QtCore.Qt.UserRole + 3
__all__ = (
"DEFAULT_PROJECT_LABEL",
"PROJECT_NAME_ROLE",
"PROJECT_IS_ACTIVE_ROLE",
"PROJECT_IS_SELECTED_ROLE"
)

View file

@ -7,6 +7,12 @@ from avalon.mongodb import (
)
from openpype.settings.lib import get_system_settings
from .constants import (
DEFAULT_PROJECT_LABEL,
PROJECT_NAME_ROLE,
PROJECT_IS_ACTIVE_ROLE,
PROJECT_IS_SELECTED_ROLE
)
class SettingsLineEdit(QtWidgets.QLineEdit):
@ -602,10 +608,63 @@ class NiceCheckbox(QtWidgets.QFrame):
return super(NiceCheckbox, self).mouseReleaseEvent(event)
class ProjectListModel(QtGui.QStandardItemModel):
sort_role = QtCore.Qt.UserRole + 10
filter_role = QtCore.Qt.UserRole + 11
selected_role = QtCore.Qt.UserRole + 12
class ProjectModel(QtGui.QStandardItemModel):
def __init__(self, only_active, *args, **kwargs):
super(ProjectModel, self).__init__(*args, **kwargs)
self.dbcon = None
self._only_active = only_active
self._default_item = None
self._items_by_name = {}
def set_dbcon(self, dbcon):
self.dbcon = dbcon
def refresh(self):
new_items = []
if self._default_item is None:
item = QtGui.QStandardItem(DEFAULT_PROJECT_LABEL)
item.setData(None, PROJECT_NAME_ROLE)
item.setData(True, PROJECT_IS_ACTIVE_ROLE)
item.setData(False, PROJECT_IS_SELECTED_ROLE)
new_items.append(item)
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)
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(False, PROJECT_IS_SELECTED_ROLE)
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()):
if project_name not in project_names:
item = self._items_by_name.pop(project_name)
root_item.removeRow(item.row())
if new_items:
root_item.appendRows(new_items)
class ProjectListView(QtWidgets.QListView):
@ -618,19 +677,36 @@ class ProjectListView(QtWidgets.QListView):
super(ProjectListView, self).mouseReleaseEvent(event)
class ProjectListSortFilterProxy(QtCore.QSortFilterProxyModel):
class ProjectSortFilterProxy(QtCore.QSortFilterProxyModel):
def __init__(self, *args, **kwargs):
super(ProjectListSortFilterProxy, self).__init__(*args, **kwargs)
super(ProjectSortFilterProxy, self).__init__(*args, **kwargs)
self._enable_filter = True
def lessThan(self, left_index, right_index):
if left_index.data(PROJECT_NAME_ROLE) is None:
return True
if right_index.data(PROJECT_NAME_ROLE) is None:
return False
left_is_active = left_index.data(PROJECT_IS_ACTIVE_ROLE)
right_is_active = right_index.data(PROJECT_IS_ACTIVE_ROLE)
if right_is_active == left_is_active:
return super(ProjectSortFilterProxy, self).lessThan(
left_index, right_index
)
if left_is_active:
return True
return False
def filterAcceptsRow(self, source_row, source_parent):
if not self._enable_filter:
return True
index = self.sourceModel().index(source_row, 0, source_parent)
is_active = bool(index.data(self.filterRole()))
is_selected = bool(index.data(ProjectListModel.selected_role))
is_selected = bool(index.data(PROJECT_IS_SELECTED_ROLE))
return is_active or is_selected
@ -643,7 +719,6 @@ class ProjectListSortFilterProxy(QtCore.QSortFilterProxyModel):
class ProjectListWidget(QtWidgets.QWidget):
default = "< Default >"
project_changed = QtCore.Signal()
def __init__(self, parent, only_active=False):
@ -657,13 +732,10 @@ class ProjectListWidget(QtWidgets.QWidget):
label_widget = QtWidgets.QLabel("Projects")
project_list = ProjectListView(self)
project_model = ProjectListModel()
project_proxy = ProjectListSortFilterProxy()
project_proxy.setFilterRole(ProjectListModel.filter_role)
project_proxy.setSortRole(ProjectListModel.sort_role)
project_proxy.setSortCaseSensitivity(QtCore.Qt.CaseInsensitive)
project_model = ProjectModel(only_active)
project_proxy = ProjectSortFilterProxy()
project_proxy.setFilterRole(PROJECT_IS_ACTIVE_ROLE)
project_proxy.setSourceModel(project_model)
project_list.setModel(project_proxy)
@ -693,13 +765,14 @@ class ProjectListWidget(QtWidgets.QWidget):
project_list.left_mouse_released_at.connect(self.on_item_clicked)
self._default_project_item = None
self.project_list = project_list
self.project_proxy = project_proxy
self.project_model = project_model
self.inactive_chk = inactive_chk
self.dbcon = None
self._only_active = only_active
def on_item_clicked(self, new_index):
new_project_name = new_index.data(QtCore.Qt.DisplayRole)
@ -746,12 +819,12 @@ class ProjectListWidget(QtWidgets.QWidget):
return not self._parent.entity.has_unsaved_changes
def project_name(self):
if self.current_project == self.default:
if self.current_project == DEFAULT_PROJECT_LABEL:
return None
return self.current_project
def select_default_project(self):
self.select_project(self.default)
self.select_project(DEFAULT_PROJECT_LABEL)
def select_project(self, project_name):
model = self.project_model
@ -759,10 +832,10 @@ class ProjectListWidget(QtWidgets.QWidget):
found_items = model.findItems(project_name)
if not found_items:
found_items = model.findItems(self.default)
found_items = model.findItems(DEFAULT_PROJECT_LABEL)
index = model.indexFromItem(found_items[0])
model.setData(index, True, ProjectListModel.selected_role)
model.setData(index, True, PROJECT_IS_SELECTED_ROLE)
index = proxy.mapFromSource(index)
@ -777,9 +850,6 @@ class ProjectListWidget(QtWidgets.QWidget):
selected_project = index.data(QtCore.Qt.DisplayRole)
break
model = self.project_model
model.clear()
mongo_url = os.environ["OPENPYPE_MONGO"]
# Force uninstall of whole avalon connection if url does not match
@ -797,35 +867,8 @@ class ProjectListWidget(QtWidgets.QWidget):
self.dbcon = None
self.current_project = None
items = [(self.default, True)]
if self.dbcon:
for doc in self.dbcon.projects(
projection={"name": 1, "data.active": 1},
only_active=self._only_active
):
items.append(
(doc["name"], doc.get("data", {}).get("active", True))
)
for project_name, is_active in items:
row = QtGui.QStandardItem(project_name)
row.setData(is_active, ProjectListModel.filter_role)
row.setData(False, ProjectListModel.selected_role)
if is_active:
row.setData(project_name, ProjectListModel.sort_role)
else:
row.setData("~" + project_name, ProjectListModel.sort_role)
font = row.font()
font.setItalic(True)
row.setFont(font)
model.appendRow(row)
self.project_model.set_dbcon(self.dbcon)
self.project_model.refresh()
self.project_proxy.sort(0)