Working GUI with comboboxes and create function loading info from presets

This commit is contained in:
Jakub Trllo 2019-02-21 16:38:45 +01:00
parent 89b1595985
commit 26fd516700

View file

@ -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()