Commit 9d7deaa3 authored by Jaden's avatar Jaden
Browse files

Added PoC for regen UI from data, impl interactives

Finally found a way to regenerate a large UI tree based on
the contents of a BEAT object. Also implemented the various
methods for transforming data in the library editor.
parent 09a599ad
Pipeline #27906 passed with stage
in 15 minutes and 40 seconds
......@@ -26,6 +26,8 @@
import re
import json
import glob
from copy import copy
from collections import OrderedDict
from PyQt5.QtWidgets import (
QGroupBox,
......@@ -37,13 +39,34 @@ from PyQt5.QtWidgets import (
QGridLayout,
QSizePolicy,
)
from PyQt5.QtCore import Qt
from PyQt5.QtCore import Qt, pyqtSlot
from .editor import AbstractAssetEditor
# use standard 12-column spacing
GRID_COLUMN_COUNT = 12
def new_obj_key(keys, prefix):
key = prefix
i = 0
while key in keys:
key = f"{prefix}{i}"
i = i + 1
return key
def deleteItemsOfLayout(layout):
if layout is not None:
while layout.count():
item = layout.takeAt(0)
widget = item.widget()
if widget is not None:
widget.setParent(None)
else:
deleteItemsOfLayout(item.layout())
class LibraryEditorWidget(AbstractAssetEditor):
"""
This widget will show the library editor.
......@@ -54,7 +77,12 @@ class LibraryEditorWidget(AbstractAssetEditor):
super(LibraryEditorWidget, self).__init__(parent)
with open(file_path) as json_file:
self.contents = json.loads(json_file.read())
self.contents = json.loads(json_file.read(), object_pairs_hook=OrderedDict)
# make contents['uses'] a list of 2-tuples
# this lets us manipulate it by indexes instead of just keys/values
self.contents["uses"] = list(self.contents["uses"].items())
re_name = re.compile(r".*/libraries/(\w+)/(\w+)/(\w+)\.json")
self.name = re.search(re_name, file_path).groups()
......@@ -72,48 +100,71 @@ class LibraryEditorWidget(AbstractAssetEditor):
if path != file_path
]
self.init_ui()
self.layout = QVBoxLayout(self)
self.refresh_ui()
def dump_json(self):
"""Returns the json representation of the asset"""
return json.dumps(self.contents)
# contents['uses'] is a list of 2-tuples
contents = copy(self.contents)
usesDict = OrderedDict()
for (key, val) in contents["uses"]:
usesDict[key] = val
contents["uses"] = usesDict
return json.dumps(contents)
def refresh_ui(self):
"""Re-creates the UI using the data from `self.contents`"""
deleteItemsOfLayout(self.layout)
self.init_ui()
def init_ui(self):
layout = QVBoxLayout(self)
layout = self.layout
# Title
label = QLabel("/".join(map(str, self.name)), self)
label.setAlignment(Qt.AlignCenter)
# Save Button
saveButton = QPushButton("Save Changes")
saveButton.clicked.connect(self.save_changes)
# saveButton.setAlignment(Qt.AlignCenter)
# Description
descBox = QGroupBox("Description")
descLayout = QVBoxLayout(descBox)
descInput = QLineEdit()
descInput.setText(self.contents["description"])
descInput.textChanged.connect(self.update_description)
descLayout.addWidget(descInput)
# List of aliases/libraries used
usesBox = QGroupBox("Libraries used")
usesLayout = QGridLayout(usesBox)
usesDict = self.contents["uses"]
for idx, (key, val) in enumerate(usesDict.items()):
# print(f"key: {key} val: {json.dumps(val)}")
# Each alias/library used
usesList = self.contents["uses"]
library_options = [""] + self.libraries_names
for idx, (key, val) in enumerate(usesList):
# remove button
removeButton = QPushButton("Remove")
removeButton.clicked.connect(lambda args, idx=idx: self.remove_library(idx))
# the alias lineinput
aliasInput = QLineEdit()
aliasInput.setText(key)
aliasInput.textChanged.connect(
lambda alias, idx=idx: self.update_library(idx, alias, None)
)
# the library select box
libraryInput = QComboBox()
libraryInput.addItems(self.libraries_names)
libraryInput.addItems(library_options)
libraryInput.setEditable(False)
libraryInput.setCurrentText(val)
libraryInput.currentTextChanged.connect(
lambda library, idx=idx: self.update_library(idx, None, library)
)
usesLayout.addWidget(aliasInput, idx, 0, 1, 5)
usesLayout.addWidget(libraryInput, idx, 5, 1, 5)
......@@ -121,50 +172,74 @@ class LibraryEditorWidget(AbstractAssetEditor):
# asserts that the gridlayout logic is correct
# assert usesLayout.columnCount() == GRID_COLUMN_COUNT
# assert usesLayout.rowCount() == len(usesDict)
# assert usesLayout.rowCount() == len(usesList)
# button to add a new library
addButton = QPushButton(
f'Add {"A" if len(usesDict) == 0 else "Another"} Library'
f'Add {"A" if len(usesList) == 0 else "Another"} Library'
)
usesLayout.addWidget(addButton, len(usesDict), 0, 1, -1)
addButton.clicked.connect(self.add_library)
usesLayout.addWidget(addButton, len(usesList), 0, 1, -1)
# put all top-level parts together in order
layout.addWidget(label)
layout.addWidget(descBox)
layout.addWidget(usesBox)
layout.addStretch(QSizePolicy.Maximum)
layout.addWidget(saveButton)
def write_updated_library(new_json):
@pyqtSlot()
def save_changes(self):
"""
Writes the given JSON to the current library's metadata file,
using the default json library to convert.
"""
pass
new_json = self.dump_json()
print(new_json)
def update_description(text):
@pyqtSlot(str)
def update_description(self, text):
"""
Updates the library's description text to the given text string.
"""
pass
# print(f'update_description {text}')
self.contents["description"] = text
def add_library():
@pyqtSlot()
def add_library(self):
"""
Adds a new alias/library entry to the library.
"""
pass
keys = [key for (key, val) in self.contents["uses"]]
key = new_obj_key(keys, "alias")
# print(f'add_library {key}')
self.contents["uses"].append((key, ""))
self.refresh_ui()
def update_library(idx, new_alias, new_library):
def update_library(self, idx, alias, library):
"""
Updates the alias/library entry at the given index
to use the new alias and the new library.
To only update one of those, just pass the old values.
"""
pass
To only update one of those, just pass None to the other.
def remove_library(idx):
this *doesnt* refresh the UI on purpose because the
QLineEdit & QComboBox manage their internal state
"""
# print(f'idx: {idx} alias: {alias} lib: {library}')
(old_alias, old_library) = self.contents["uses"][idx]
# avoid key collisions
if alias == old_alias:
return
alias = alias if alias is not None else old_alias
library = library if library is not None else old_library
# print(f'idx: {idx} alias: {alias} lib: {library}')
self.contents["uses"][idx] = (alias, library)
def remove_library(self, idx):
"""
Removes the alias/library entry at the given index.
Removes the alias/library entry with the given alias.
"""
pass
# print(f'remove_library {idx}')
del self.contents["uses"][idx]
self.refresh_ui()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment