mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
Working GUI with comboboxes and create function loading info from presets
This commit is contained in:
parent
89b1595985
commit
26fd516700
1 changed files with 356 additions and 33 deletions
|
|
@ -1,9 +1,13 @@
|
|||
import os
|
||||
import sys
|
||||
import json
|
||||
|
||||
import ftrack_api_old as ftrack_api
|
||||
from pype import lib as pypelib
|
||||
from avalon.vendor.Qt import QtWidgets, QtCore
|
||||
from avalon import io, api, style
|
||||
from avalon.tools import lib as parentlib
|
||||
from . import widget
|
||||
from . import widget, model
|
||||
|
||||
module = sys.modules[__name__]
|
||||
module.window = None
|
||||
|
|
@ -24,50 +28,87 @@ class Window(QtWidgets.QDialog):
|
|||
# Validators
|
||||
self.valid_parent = False
|
||||
|
||||
# assets
|
||||
assets_widgets = QtWidgets.QWidget()
|
||||
assets_widgets.setContentsMargins(0, 0, 0, 0)
|
||||
assets_layout = QtWidgets.QVBoxLayout(assets_widgets)
|
||||
self.session = None
|
||||
|
||||
# assets widget
|
||||
assets_widget = QtWidgets.QWidget()
|
||||
assets_widget.setContentsMargins(0, 0, 0, 0)
|
||||
assets_layout = QtWidgets.QVBoxLayout(assets_widget)
|
||||
assets = widget.AssetWidget()
|
||||
assets.view.setSelectionMode(assets.view.ExtendedSelection)
|
||||
assets_layout.addWidget(assets)
|
||||
|
||||
# info
|
||||
widget_name = QtWidgets.QWidget()
|
||||
widget_name.setContentsMargins(0, 0, 0, 0)
|
||||
layout_name = QtWidgets.QHBoxLayout(widget_name)
|
||||
label_name = QtWidgets.QLabel("Name:")
|
||||
input_name = QtWidgets.QLineEdit()
|
||||
input_name.setPlaceholderText("<asset name>")
|
||||
layout_name.addWidget(label_name)
|
||||
layout_name.addWidget(input_name)
|
||||
|
||||
# Outlink
|
||||
label_outlink = QtWidgets.QLabel("Outlink:")
|
||||
input_outlink = QtWidgets.QLineEdit()
|
||||
input_outlink.setReadOnly(True)
|
||||
input_outlink.setStyleSheet("background-color: #333333;") # greyed out
|
||||
checkbox_outlink = QtWidgets.QCheckBox("Use outlink")
|
||||
# Parent
|
||||
widget_parent = QtWidgets.QWidget()
|
||||
widget_parent.setContentsMargins(0, 0, 0, 0)
|
||||
layout_parent = QtWidgets.QHBoxLayout(widget_parent)
|
||||
label_parent = QtWidgets.QLabel("Parent:")
|
||||
input_parent = QtWidgets.QLineEdit()
|
||||
input_parent.setReadOnly(True)
|
||||
input_parent.setStyleSheet("background-color: #333333;") # greyed out
|
||||
layout_parent.addWidget(label_parent)
|
||||
layout_parent.addWidget(input_parent)
|
||||
|
||||
# Name
|
||||
label_name = QtWidgets.QLabel("Name:")
|
||||
input_name = QtWidgets.QLineEdit()
|
||||
input_name.setPlaceholderText("<asset name>")
|
||||
|
||||
# Asset Build
|
||||
label_assetbuild = QtWidgets.QLabel("Asset Build:")
|
||||
combo_assetbuilt = QtWidgets.QComboBox()
|
||||
|
||||
# Task template
|
||||
label_task_template = QtWidgets.QLabel("Task template:")
|
||||
combo_task_template = QtWidgets.QComboBox()
|
||||
|
||||
# Info widget
|
||||
info_widget = QtWidgets.QWidget()
|
||||
info_widget.setContentsMargins(0, 0, 0, 0)
|
||||
info_widget.setContentsMargins(10, 10, 10, 10)
|
||||
info_layout = QtWidgets.QVBoxLayout(info_widget)
|
||||
info_layout.addWidget(widget_parent)
|
||||
info_layout.addWidget(widget_name)
|
||||
|
||||
# Inputs widget
|
||||
inputs_widget = QtWidgets.QWidget()
|
||||
inputs_widget.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
inputs_layout = QtWidgets.QFormLayout(inputs_widget)
|
||||
inputs_layout.addRow(label_outlink, input_outlink)
|
||||
inputs_layout.addRow(None, checkbox_outlink)
|
||||
inputs_layout.addRow(label_parent, input_parent)
|
||||
inputs_layout.addRow(label_name, input_name)
|
||||
inputs_layout.addRow(label_assetbuild, combo_assetbuilt)
|
||||
inputs_layout.addRow(label_task_template, combo_task_template)
|
||||
|
||||
# Add button
|
||||
btns_widget = QtWidgets.QWidget()
|
||||
btns_widget.setContentsMargins(0, 0, 0, 0)
|
||||
btn_layout = QtWidgets.QVBoxLayout(btns_widget)
|
||||
btn_create_asset = QtWidgets.QPushButton("Create asset")
|
||||
btn_create_asset.setToolTip(
|
||||
"Creates all neccessary components for asset"
|
||||
)
|
||||
btn_layout.addWidget(btn_create_asset)
|
||||
|
||||
task_view = QtWidgets.QTreeView()
|
||||
task_view.setIndentation(0)
|
||||
task_model = model.TasksTemplateModel()
|
||||
task_view.setModel(task_model)
|
||||
|
||||
info_layout.addWidget(inputs_widget)
|
||||
info_layout.addWidget(task_view)
|
||||
info_layout.addWidget(btns_widget)
|
||||
|
||||
# Body
|
||||
body = QtWidgets.QSplitter()
|
||||
body.setContentsMargins(0, 0, 0, 0)
|
||||
body.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
|
||||
QtWidgets.QSizePolicy.Expanding)
|
||||
body.setOrientation(QtCore.Qt.Horizontal)
|
||||
body.addWidget(assets_widgets)
|
||||
body.addWidget(assets_widget)
|
||||
body.addWidget(info_widget)
|
||||
body.setStretchFactor(0, 100)
|
||||
body.setStretchFactor(1, 200)
|
||||
body.setStretchFactor(1, 150)
|
||||
|
||||
# statusbar
|
||||
message = QtWidgets.QLabel()
|
||||
|
|
@ -87,27 +128,273 @@ class Window(QtWidgets.QDialog):
|
|||
"message": message,
|
||||
},
|
||||
"model": {
|
||||
"assets": assets
|
||||
"assets": assets,
|
||||
"tasks": task_model
|
||||
},
|
||||
"inputs": {
|
||||
"outlink": input_outlink,
|
||||
"outlink_cb": checkbox_outlink,
|
||||
"parent": input_parent,
|
||||
"name": input_name
|
||||
"name": input_name,
|
||||
"assetbuild": combo_assetbuilt,
|
||||
"tasktemplate": combo_task_template
|
||||
},
|
||||
"buttons": {
|
||||
|
||||
"create_asset": btn_create_asset
|
||||
}
|
||||
}
|
||||
|
||||
# signals
|
||||
btn_create_asset.clicked.connect(self.create_asset)
|
||||
assets.selection_changed.connect(self.on_asset_changed)
|
||||
checkbox_outlink.toggled.connect(self.on_outlink_checkbox_change)
|
||||
combo_task_template.currentTextChanged.connect(
|
||||
self.on_task_template_changed
|
||||
)
|
||||
# on start
|
||||
self.on_asset_changed()
|
||||
self.resize(800, 500)
|
||||
self.on_start()
|
||||
|
||||
self.resize(600, 500)
|
||||
|
||||
self.echo("Connected to project: {0}".format(project_name))
|
||||
|
||||
def refresh(self):
|
||||
def on_start(self):
|
||||
# Load config
|
||||
preset_path = pypelib.get_presets_path()
|
||||
config_file_items = [
|
||||
preset_path, 'tools', 'asset_creator', 'config.json'
|
||||
]
|
||||
config_file = os.path.sep.join(config_file_items)
|
||||
with open(config_file) as data_file:
|
||||
self.config_data = json.load(data_file)
|
||||
|
||||
# set outlink
|
||||
input_outlink = self.data['inputs']['outlink']
|
||||
checkbox_outlink = self.data['inputs']['outlink_cb']
|
||||
outlink_text = io.Session.get('AVALON_ASSET', '')
|
||||
checkbox_outlink.setChecked(True)
|
||||
if outlink_text == '':
|
||||
outlink_text = '< No context >'
|
||||
checkbox_outlink.setChecked(False)
|
||||
checkbox_outlink.hide()
|
||||
input_outlink.setText(outlink_text)
|
||||
|
||||
# load asset build types
|
||||
self.load_assetbuild_types()
|
||||
|
||||
# Load task templates
|
||||
self.load_task_templates()
|
||||
self.data["model"]["assets"].refresh()
|
||||
self.on_asset_changed()
|
||||
|
||||
def create_asset(self):
|
||||
# Init validation
|
||||
name_input = self.data['inputs']['name']
|
||||
name = name_input.text()
|
||||
test_name = name.replace(' ', '')
|
||||
error_message = None
|
||||
message = QtWidgets.QMessageBox(self)
|
||||
message.setWindowTitle("Some errors has occured")
|
||||
message.setIcon(QtWidgets.QMessageBox.Critical)
|
||||
# TODO: show error messages on any error
|
||||
if self.valid_parent is not True and test_name == '':
|
||||
error_message = "Name is not set and Parent is not selected"
|
||||
elif self.valid_parent is not True:
|
||||
error_message = "Parent is not selected"
|
||||
elif test_name == '':
|
||||
error_message = "Name is not set"
|
||||
if error_message is not None:
|
||||
message.setText(error_message)
|
||||
message.show()
|
||||
return
|
||||
|
||||
test_name_exists = io.find({
|
||||
'type': 'asset',
|
||||
'name': name
|
||||
})
|
||||
existing_assets = [x for x in test_name_exists]
|
||||
if len(existing_assets) > 0:
|
||||
message.setText("Entered Asset name is occupied")
|
||||
message.show()
|
||||
return
|
||||
|
||||
# Get ftrack session
|
||||
if self.session is None:
|
||||
session = ftrack_api.Session()
|
||||
self.session = session
|
||||
else:
|
||||
session = self.session
|
||||
|
||||
# Get Ftrack project entity
|
||||
project_name = io.Session['AVALON_PROJECT']
|
||||
project_query = 'Project where full_name is "{}"'.format(project_name)
|
||||
try:
|
||||
ft_project = session.query(project_query).one()
|
||||
except Exception:
|
||||
message.setText("Ftrack project was not found")
|
||||
message.show()
|
||||
return
|
||||
|
||||
# Get Ftrack entity of parent
|
||||
ft_asset = None
|
||||
assets_model = self.data["model"]["assets"]
|
||||
selected = assets_model.get_selected_assets()
|
||||
asset = io.find_one({"_id": selected[0], "type": "asset"})
|
||||
asset_id = asset.get('data', {}).get('ftrackId', None)
|
||||
asset_entity_type = asset.get('data', {}).get('entityType', None)
|
||||
asset_query = '{} where id is "{}"'
|
||||
if asset_id is not None and asset_entity_type is not None:
|
||||
try:
|
||||
ft_asset = session.query(asset_query.format(
|
||||
asset_entity_type, asset_id)
|
||||
).one()
|
||||
except Exception:
|
||||
ft_asset = None
|
||||
|
||||
if ft_asset is None:
|
||||
ft_asset = self.get_ftrack_asset(asset, ft_project)
|
||||
|
||||
if ft_asset is None:
|
||||
message.setText("Parent's Ftrack entity was not found")
|
||||
message.show()
|
||||
return
|
||||
|
||||
asset_build_combo = self.data['inputs']['assetbuild']
|
||||
asset_type_name = asset_build_combo.currentText()
|
||||
asset_type_query = 'Type where name is "{}"'.format(asset_type_name)
|
||||
try:
|
||||
asset_type = session.query(asset_type_query).one()
|
||||
except Exception:
|
||||
message.setText("Selected Asset Build type does not exists")
|
||||
message.show()
|
||||
return
|
||||
|
||||
for children in ft_asset['children']:
|
||||
if children['name'] == name:
|
||||
message.setText("Entered Asset name is occupied")
|
||||
message.show()
|
||||
return
|
||||
|
||||
task_template_combo = self.data['inputs']['tasktemplate']
|
||||
task_template = task_template_combo.currentText()
|
||||
tasks = self.config_data['task_templates'].get(task_template, [])
|
||||
|
||||
available_task_types = []
|
||||
task_types = ft_project['project_schema']['_task_type_schema']
|
||||
for task_type in task_types['types']:
|
||||
available_task_types.append(task_type['name'])
|
||||
|
||||
not_possible_tasks = []
|
||||
for task in tasks:
|
||||
if task not in available_task_types:
|
||||
not_possible_tasks.append(task)
|
||||
|
||||
if len(not_possible_tasks) != 0:
|
||||
message.setText((
|
||||
"These Task types weren't found"
|
||||
" in Ftrack project schema:\n{}").format(
|
||||
', '.join(not_possible_tasks))
|
||||
)
|
||||
message.show()
|
||||
return
|
||||
|
||||
# Create asset build
|
||||
asset_build_data = {
|
||||
'name': name,
|
||||
'project_id': ft_project['id'],
|
||||
'parent_id': ft_asset['id'],
|
||||
'type': asset_type
|
||||
}
|
||||
|
||||
new_entity = session.create('AssetBuild', asset_build_data)
|
||||
session.commit()
|
||||
|
||||
task_data = {
|
||||
'project_id': ft_project['id'],
|
||||
'parent_id': new_entity['id']
|
||||
}
|
||||
|
||||
for task in tasks:
|
||||
type = session.query('Type where name is "{}"'.format(task)).one()
|
||||
|
||||
task_data['type_id'] = type['id']
|
||||
task_data['name'] = task
|
||||
session.create('Task', task_data)
|
||||
session.commit()
|
||||
|
||||
outlink_cb = self.data['inputs']['outlink_cb']
|
||||
if outlink_cb.isChecked() is True:
|
||||
outlink_input = self.data['inputs']['outlink']
|
||||
outlink_name = outlink_input.text()
|
||||
outlink_asset = io.find_one({
|
||||
'type': 'asset',
|
||||
'name': outlink_name
|
||||
})
|
||||
outlink_ft_id = outlink_asset.get('data', {}).get('ftrackId', None)
|
||||
outlink_entity_type = outlink_asset.get(
|
||||
'data', {}
|
||||
).get('entityType', None)
|
||||
if outlink_ft_id is not None and outlink_entity_type is not None:
|
||||
try:
|
||||
outlink_entity = session.query(asset_query.format()).one()
|
||||
except Exception:
|
||||
outlink_entity = None
|
||||
|
||||
if outlink_entity is None:
|
||||
outlink_entity = self.get_ftrack_asset(
|
||||
outlink_asset, ft_project
|
||||
)
|
||||
|
||||
if outlink_entity is None:
|
||||
message.setText("Outlink's Ftrack entity was not found")
|
||||
message.show()
|
||||
return
|
||||
|
||||
link_data = {
|
||||
'from_id': new_entity['id'],
|
||||
'to_id': outlink_entity['id']
|
||||
}
|
||||
session.create('TypedContextLink', link_data)
|
||||
session.commit()
|
||||
|
||||
message.setWindowTitle("Asset Created")
|
||||
message.setText("Asset Created successfully")
|
||||
message.setIcon(QtWidgets.QMessageBox.Information)
|
||||
message.show()
|
||||
|
||||
def get_ftrack_asset(self, asset, ft_project):
|
||||
parenthood = []
|
||||
parenthood.append(asset['name'])
|
||||
parenthood.extend(self.get_avalon_parent(asset))
|
||||
|
||||
output_entity = None
|
||||
ft_entity = ft_project
|
||||
index = len(parenthood) - 1
|
||||
while True:
|
||||
name = parenthood[index]
|
||||
found = False
|
||||
for children in ft_entity['children']:
|
||||
if children['name'] == name:
|
||||
ft_entity = children
|
||||
found = True
|
||||
break
|
||||
if found is False:
|
||||
return None
|
||||
if index == 0:
|
||||
output_entity = ft_entity
|
||||
break
|
||||
index -= 1
|
||||
|
||||
return output_entity
|
||||
|
||||
def get_avalon_parent(self, entity):
|
||||
parent_id = entity['data']['visualParent']
|
||||
parents = []
|
||||
if parent_id is not None:
|
||||
parent = io.find_one({'_id': parent_id})
|
||||
parents.append(parent['name'])
|
||||
parents.extend(self.get_avalon_parent(parent))
|
||||
return parents
|
||||
|
||||
def echo(self, message):
|
||||
widget = self.data["label"]["message"]
|
||||
|
|
@ -117,6 +404,40 @@ class Window(QtWidgets.QDialog):
|
|||
|
||||
print(message)
|
||||
|
||||
def load_task_templates(self):
|
||||
templates = self.config_data.get('task_templates', {})
|
||||
all_names = []
|
||||
for name, statuses in templates.items():
|
||||
all_names.append(name)
|
||||
|
||||
tt_combobox = self.data['inputs']['tasktemplate']
|
||||
tt_combobox.clear()
|
||||
tt_combobox.addItems(all_names)
|
||||
|
||||
def load_assetbuild_types(self):
|
||||
types = self.config_data.get('assetbuild_types', [])
|
||||
|
||||
ab_combobox = self.data['inputs']['assetbuild']
|
||||
ab_combobox.clear()
|
||||
ab_combobox.addItems(types)
|
||||
|
||||
def on_outlink_checkbox_change(self):
|
||||
checkbox_outlink = self.data['inputs']['outlink_cb']
|
||||
outlink_input = self.data['inputs']['outlink']
|
||||
if checkbox_outlink.isChecked() is True:
|
||||
outlink_text = io.Session['AVALON_ASSET']
|
||||
else:
|
||||
outlink_text = '< Outlinks won\'t be set >'
|
||||
|
||||
outlink_input.setText(outlink_text)
|
||||
|
||||
def on_task_template_changed(self):
|
||||
combobox = self.data['inputs']['tasktemplate']
|
||||
task_model = self.data['model']['tasks']
|
||||
name = combobox.currentText()
|
||||
tasks = self.config_data['task_templates'].get(name, [])
|
||||
task_model.set_tasks(tasks)
|
||||
|
||||
def on_asset_changed(self):
|
||||
"""Callback on asset selection changed
|
||||
|
||||
|
|
@ -160,7 +481,6 @@ def show(root=None, debug=False, parent=None):
|
|||
window = Window(parent)
|
||||
window.setStyleSheet(style.load_stylesheet())
|
||||
window.show()
|
||||
window.refresh()
|
||||
|
||||
module.window = window
|
||||
|
||||
|
|
@ -169,12 +489,15 @@ def cli(args):
|
|||
import argparse
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("project")
|
||||
parser.add_argument("asset")
|
||||
|
||||
args = parser.parse_args(args)
|
||||
project = args.project
|
||||
|
||||
asset = args.asset
|
||||
io.install()
|
||||
|
||||
api.Session["AVALON_PROJECT"] = project
|
||||
if asset is not None:
|
||||
api.Session["AVALON_ASSET"] = asset
|
||||
|
||||
show()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue