190 lines
6.5 KiB
JavaScript
190 lines
6.5 KiB
JavaScript
import { createFilesAndDownload } from "../../../codeEngine/utils"
|
|
import MainWindow from "../widgets/mainWindow"
|
|
|
|
import { message } from "antd"
|
|
import TopLevel from "../widgets/toplevel"
|
|
|
|
|
|
// FIXME: if the toplevel comes first, before the MainWindow in widgetlist the root may become null
|
|
// Recursive function to generate the code list, imports, requirements, and track mainVariable
|
|
function generateTkinterCodeList(widgetList = [], widgetRefs = [], parentVariable = null, mainVariable = "", usedVariableNames = new Set()) {
|
|
let variableMapping = new Map() // Map widget to variable { widgetId: variableName }
|
|
let imports = new Set([])
|
|
let requirements = new Set([])
|
|
let code = []
|
|
|
|
for (let widget of widgetList) {
|
|
const widgetRef = widgetRefs[widget.id].current
|
|
let varName = widgetRef.getVariableName()
|
|
|
|
// Add imports and requirements to sets
|
|
widgetRef.getImports().forEach(importItem => imports.add(importItem))
|
|
widgetRef.getRequirements().forEach(requirementItem => requirements.add(requirementItem))
|
|
|
|
// Set main variable if the widget is MainWindow
|
|
if (widget.widgetType === MainWindow) {
|
|
mainVariable = varName
|
|
}
|
|
|
|
// Ensure unique variable names across recursion
|
|
let originalVarName = varName
|
|
let count = 1;
|
|
|
|
// Check for uniqueness and update varName
|
|
while (usedVariableNames.has(varName)) {
|
|
varName = `${originalVarName}${count}`
|
|
count++
|
|
}
|
|
|
|
usedVariableNames.add(varName)
|
|
variableMapping.set(widget.id, varName) // Store the variable name by widget ID
|
|
|
|
// Determine the current parent variable from variableNames or fallback to parentVariable
|
|
let currentParentVariable = parentVariable || (variableMapping.get(widget.id) || null)
|
|
|
|
if (widget.widgetType === TopLevel){
|
|
// for top level set it to the main variable
|
|
// TODO: the toplevels parent should be determined other ways, suppose the top level has another toplevel
|
|
currentParentVariable = mainVariable
|
|
}
|
|
|
|
let widgetCode = widgetRef.generateCode(varName, currentParentVariable)
|
|
|
|
if (!(widgetCode instanceof Array)) {
|
|
throw new Error("generateCode() function should return array, each new line should be a new item")
|
|
}
|
|
|
|
// Add \n after every line
|
|
widgetCode = widgetCode.flatMap((item, index) => index < widgetCode.length - 1 ? [item, "\n"] : [item])
|
|
|
|
code.push(...widgetCode)
|
|
code.push("\n\n")
|
|
|
|
// Recursively handle child widgets
|
|
if (widget.children && widget.children.length > 0) {
|
|
// Pass down the unique names for children to prevent duplication
|
|
const childResult = generateTkinterCodeList(widget.children, widgetRefs, varName, mainVariable, usedVariableNames)
|
|
|
|
// Merge child imports, requirements, and code
|
|
imports = new Set([...imports, ...childResult.imports])
|
|
requirements = new Set([...requirements, ...childResult.requirements])
|
|
code.push(...childResult.code)
|
|
|
|
mainVariable = childResult.mainVariable || mainVariable // the main variable is the main window variable
|
|
}
|
|
}
|
|
|
|
return {
|
|
imports: Array.from(imports),
|
|
code: code,
|
|
requirements: Array.from(requirements),
|
|
mainVariable
|
|
}
|
|
}
|
|
|
|
|
|
async function generateTkinterCode(projectName, widgetList=[], widgetRefs=[], assetFiles){
|
|
|
|
// console.log("widgetList and refs", projectName, widgetList, widgetRefs, assetFiles)
|
|
|
|
let mainWindowCount = 0
|
|
|
|
// only MainWindow and/or the TopLevel should be on the canvas
|
|
const filteredWidgetList = widgetList.filter(widget => widget.widgetType === MainWindow || widget.widgetType === TopLevel)
|
|
|
|
for (let widget of filteredWidgetList){
|
|
if (widget.widgetType === MainWindow){
|
|
mainWindowCount += 1
|
|
}
|
|
|
|
if (mainWindowCount > 1){
|
|
message.error("Multiple instances of Main window found, delete one and try again.")
|
|
return
|
|
}
|
|
|
|
}
|
|
|
|
if (mainWindowCount === 0){
|
|
message.error("Aborting. No instances of Main window found. Add one and try again")
|
|
return
|
|
}
|
|
|
|
// widget - {id, widgetType: widgetComponentType, children: [], parent: "", initialData: {}}
|
|
|
|
const generatedObject = generateTkinterCodeList(filteredWidgetList, widgetRefs, "", "")
|
|
|
|
const {code: codeLines, imports, requirements, mainVariable} = generatedObject
|
|
|
|
// TODO: avoid adding \n inside the list instead rewrite using code.join("\n")
|
|
const code = [
|
|
"# This code is generated by PyUIbuilder: https://github.com/PaulleDemon/PyUIBuilder",
|
|
"\n\n",
|
|
...imports.flatMap((item, index) => index < imports.length - 1 ? [item, "\n"] : [item]), //add \n to every line
|
|
"\n\n",
|
|
...codeLines,
|
|
"\n",
|
|
`${mainVariable}.mainloop()`,
|
|
]
|
|
|
|
console.log("Code: ", code.join(""), "\n\n requirements:", requirements.join("\n"))
|
|
|
|
message.info("starting zipping files, download will start in a few seconds")
|
|
|
|
const createFileList = [
|
|
{
|
|
fileData: code.join(""),
|
|
fileName: "main.py",
|
|
folder: ""
|
|
}
|
|
]
|
|
|
|
|
|
if (requirements.length > 0){
|
|
createFileList.push({
|
|
fileData: requirements.join("\n"),
|
|
fileName: "requirements.txt",
|
|
folder: ""
|
|
})
|
|
}
|
|
|
|
for (let asset of assetFiles){
|
|
|
|
if (asset.fileType === "image"){
|
|
createFileList.push({
|
|
fileData: asset.originFileObj,
|
|
fileName: asset.name,
|
|
folder: "assets/images"
|
|
})
|
|
}else if (asset.fileType === "video"){
|
|
createFileList.push({
|
|
fileData: asset.originFileObj,
|
|
fileName: asset.name,
|
|
folder: "assets/videos"
|
|
})
|
|
}else if (asset.fileType === "audio"){
|
|
createFileList.push({
|
|
fileData: asset.originFileObj,
|
|
fileName: asset.name,
|
|
folder: "assets/audio"
|
|
})
|
|
}else{
|
|
createFileList.push({
|
|
fileData: asset.originFileObj,
|
|
fileName: asset.name,
|
|
folder: "assets/others"
|
|
})
|
|
}
|
|
|
|
}
|
|
|
|
createFilesAndDownload(createFileList, projectName).then(() => {
|
|
message.success("Download complete")
|
|
}).catch(() => {
|
|
message.error("Error while downloading")
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
export default generateTkinterCode |