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 = "") { let variableNames = [] // {widgetId: "", name: "", count: 1} let imports = new Set([]) let requirements = new Set([]) let code = [] for (let widget of widgetList) { // console.log("Key: ", widget) const widgetRef = widgetRefs[widget.id].current let varName = widgetRef.getVariableName() imports.add(widgetRef.getImports()) requirements.add(widgetRef.getRequirements()) // Set main variable if the widget is MainWindow if (widget.widgetType === MainWindow) { mainVariable = varName } if (!variableNames.find((val) => val.variable === varName)) { variableNames.push({ widgetId: widgetRef.id, name: varName, count: 1 }) } else { // Avoid duplicate names const existingVariable = variableNames.find((val) => val.variable === varName) const existingCount = existingVariable.count existingVariable.count += 1 varName = `${existingVariable.name}${existingCount}` variableNames.push({ widgetId: widgetRef.id, name: varName, count: 1 }) } const currentParentVariable = variableNames.find(val => val.widgetId === widget.id)?.name || parentVariable let widgetCode = widgetRef.generateCode(varName, currentParentVariable) if (!(widgetCode instanceof Array)) { throw new Error("Generate code 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, which are full widget objects if (widget.children && widget.children.length > 0) { const childResult = generateTkinterCodeList(widget.children, widgetRefs, varName, mainVariable) // Merge child imports, requirements, and code imports = new Set([...imports, ...childResult.imports]) requirements = new Set([...requirements, ...childResult.requirements]) code.push(...childResult.code) // Track the main variable returned by the child mainVariable = childResult.mainVariable || mainVariable } } return { imports: Array.from(imports), // Convert Set to Array code: code, requirements: Array.from(requirements), // Convert Set to Array mainVariable } } async function generateTkinterCode(projectName, widgetList=[], widgetRefs=[]){ console.log("widgetList and refs", projectName, widgetList, widgetRefs) 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 } // let code = [`# This code is generated by PyUIbuilder: https://github.com/paulledemon \n`] // code.push("\n", "import tkinter as tk", "\n\n") // widget - {id, widgetType: widgetComponentType, children: [], parent: "", initialData: {}} const generatedObject = generateTkinterCodeList(filteredWidgetList, widgetRefs, "", "") const {code: codeLines, imports, requirements, mainVariable} = generatedObject const code = [ "# This code is generated by PyUIbuilder: https://github.com/paulledemon", "\n\n", ...imports, "\n\n", ...codeLines, "\n", `${mainVariable}.mainloop()`, ] // TODO: create requirements.txt file console.log("Code: ", code.join("")) 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: "" }) } // createFilesAndDownload(createFileList, projectName).then(() => { // message.success("Download complete") // }).catch(() => { // message.error("Error while downloading") // }) } export default generateTkinterCode