Source code for cgl.plugins.otio.tools.summary
import sys
import os
import json
import traceback
from PySide6 import QtCore, QtWidgets
from cgl.plugins.otio.tools import extract_shots
[docs]
class StoryBoardSummary(QtWidgets.QDialog):
def __init__(self, timeline, shot_dict, parent=None):
super(StoryBoardSummary, self).__init__(parent)
self.setWindowFlag(QtCore.Qt.WindowStaysOnTopHint, True)
self.result = False
self.tree = QtWidgets.QTreeWidget()
self.tree.setHeaderLabels(["Shot", "Path", "Relative Frame", "Absolute Frame"])
self.tree.setAlternatingRowColors(True)
for name, psd_list in shot_dict.items():
w = QtWidgets.QTreeWidgetItem(self.tree)
w.setText(0, name)
for p, start_frame, global_start_frame, duration in psd_list:
child = QtWidgets.QTreeWidgetItem(w)
child.setText(0, os.path.basename(p))
child.setText(1, p)
child.setText(2, str(start_frame))
child.setText(3, str(global_start_frame))
# otioview component
self.timeline_view = timeline_widget.Timeline()
self.timeline_view.set_timeline(timeline)
self.button_box = QtWidgets.QDialogButtonBox(
QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel
)
self.button_box.accepted.connect(self.accept)
self.button_box.rejected.connect(self.close)
button_layout = QtWidgets.QHBoxLayout()
button_layout.addStretch()
button_layout.addWidget(self.button_box)
self.splitter = QtWidgets.QSplitter(QtCore.Qt.Vertical)
self.splitter.addWidget(self.tree)
self.splitter.addWidget(self.timeline_view)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.splitter)
layout.addLayout(button_layout)
self.setLayout(layout)
# Initialize
self.resize(900, 500)
self.tree.expandAll()
col_count = self.tree.columnCount()
for i in range(col_count):
self.tree.resizeColumnToContents(i)
[docs]
def accept(self):
self.result = True
self.close()
[docs]
def confirm_summary(path_to_edit_file):
app = QtWidgets.QApplication.instance()
w = None
if not app:
app = QtWidgets.QApplication(sys.argv)
try:
timeline, shot_dict = extract_shots.simplify_timeline(path_to_edit_file)
w = StoryBoardSummary(timeline, shot_dict)
w.setWindowTitle("Shot Summary")
w.exec()
except Exception as e:
tb = traceback.format_exc()
print(path_to_edit_file)
print(tb, e)
QtWidgets.QMessageBox.critical(
None,
"Error!",
f"Error reading file\n\n{path_to_edit_file}\n\n{tb}",
QtWidgets.QMessageBox.Ok,
)
return False
return w.result if w else None
[docs]
def show_summary_from_msd(path_to_msd, project_root_path):
data = {}
with open(path_to_msd) as f:
data = json.load(f)
assert data
edit_file_path = None
for ext in (".xml", ".aaf"):
path = data.get("render_files", {}).get(ext, None)
if not path:
continue
if isinstance(path, list):
path = path[0]
edit_file_path = os.path.join(project_root_path, path).replace("\\", "/")
break
assert edit_file_path
confirm_summary(edit_file_path)
if __name__ == "__main__":
xml_path = r"Z:/Alchemy/jhcs/ttas/VERSIONS/0/000/render/shots/103/s01/SEQ/edt/default/tmakota/000.000/high/MDC_103_MonsterOpposites_RC_251021.xml"
# xml_path = sys.argv[1]
confirm_summary(xml_path)