diff --git a/MAIN.py b/MAIN.py index 7e51f1f..a4d9f0a 100644 --- a/MAIN.py +++ b/MAIN.py @@ -10,9 +10,9 @@ import tkinter as tk from tkinter import ttk import yaml -folder_parsets = "_cfg_parsets" +folder_parsets = r"\\HOST-BL7\Mabi-Robotic-Produktion\40_PROJEKTE\30_Interne_Projekte\DMU50_Automation\40_SOFTWARE\CONFIGURATOR\DMU50_GUI_PY-main\dmu50_gui_py\_cfg_parsets" folder_pictures = "cfg_picture" -folder_output = "_out" +folder_output = r"\\HOST-BL7\Mabi-Robotic-Produktion\40_PROJEKTE\30_Interne_Projekte\DMU50_Automation\40_SOFTWARE\CONFIGURATOR\DMU50_GUI_PY-main\dmu50_gui_py\_out" file_def = "def.yml" file_jobs = "jobs.yml" name_newparset = "" @@ -20,6 +20,26 @@ name_newjob = "" pic_sizelimit = 250 + +def _verify_job(job_name): + if job_name in ("", name_newjob): + messagebox.showwarning("No job selected", + "Please select (or save) a job first.") + return 0 + else: + return 1 + +def _deep_copy(save_dir, gen_dir): + if os.path.isdir(save_dir): + for name in os.listdir(save_dir): + src = os.path.join(save_dir, name) + dst = os.path.join(gen_dir, name) + if os.path.isdir(src): + shutil.copytree(src, dst, dirs_exist_ok=True) + else: + shutil.copy2(src, dst) + + def setup_group(frame, group_name, data, input_vars, selected_params, group_widgets): group_data = data['groups'][group_name] picture_name = group_data['cfg']['picture_name'] # Picture name defined in def.yml @@ -243,12 +263,69 @@ def setup_jobs(frame, data, selected_job, selected_params, input_vars, group_wid job_dropdown['values'] = job_values load_selected_job() + def upload_job_files(): + job_name = selected_job.get() + if not _verify_job(job_name): + return + + job_safe = make_windows_safe(job_name) + save_dir = os.path.join(folder_parsets, "files", job_safe) + os.makedirs(save_dir, exist_ok=True) + + paths = filedialog.askopenfilenames( + parent=frame, title=f"Attach file(s) to job: {job_name}" + ) + if not paths: + return + + copied = 0 + for src in paths: + try: + shutil.copy2(src, save_dir) + copied += 1 + except Exception as exc: + messagebox.showerror("Copy failed", + f"Could not copy:\n{src}\n\n{exc}") + return + + messagebox.showinfo("Upload complete", + f"{copied} file(s) copied to:\n{save_dir}") + + def show_job_files(): + job_name = selected_job.get() + if not _verify_job(job_name): + return + + job_safe = make_windows_safe(job_name) + target = os.path.join(folder_parsets, "files", job_safe) + + if not os.path.isdir(target) or not os.listdir(target): + messagebox.showinfo("No files", + f"No files found for job “{job_name}”.") + return + + os.startfile(target) + + # Job dropdown and buttons for save/load/delete ttk.Label(frame, text="Job:").grid(row=0, column=0, padx=5, pady=5, sticky="w") job_dropdown = ttk.Combobox(frame, textvariable=selected_job, values=job_values) job_dropdown.grid(row=0, column=1, padx=5, pady=5) - ttk.Button(frame, text="Save", command=save_current_job).grid(row=0, column=2, padx=5, pady=5, sticky="w") - ttk.Button(frame, text="Delete", command=delete_current_job).grid(row=0, column=3, padx=5, pady=5, sticky="w") + + ttk.Button(frame, text="Save", command=save_current_job) \ + .grid(row=0, column=2, padx=5, pady=5, sticky="w") + ttk.Button(frame, text="Delete", command=delete_current_job) \ + .grid(row=0, column=3, padx=5, pady=5, sticky="w") + + sep = ttk.Separator(frame, orient="vertical") + sep.grid(row=0, column=4, sticky="ns", padx=8) # full height of the cell + frame.grid_columnconfigure(4, minsize=15) # width of the line + + ttk.Button(frame, text="Upload Job-Files", command=upload_job_files) \ + .grid(row=0, column=5, padx=5, pady=5, sticky="w") + ttk.Button(frame, text="Show Job-Files", command=show_job_files) \ + .grid(row=0, column=6, padx=5, pady=5, sticky="w") + # Bind job selection to loading the selected job and updating the groups job_dropdown.bind("<>", lambda event: load_selected_job()) @@ -263,7 +340,7 @@ def setup_jobs(frame, data, selected_job, selected_params, input_vars, group_wid -def setup_evaluation(root, folder_pictures, data, folder_output, input_vars, selected_params): +def setup_evaluation(root, folder_pictures, data, folder_output, input_vars, selected_params, selected_job): # Create a frame for the EVALUATION section frame = ttk.LabelFrame(root, text="EVALUATION", padding=(10, 10)) frame.grid(row=2, column=0, columnspan=5, padx=10, pady=10, sticky="nsew") @@ -278,7 +355,16 @@ def setup_evaluation(root, folder_pictures, data, folder_output, input_vars, sel # Function to generate configuration file based on current parameters def btn_gen_cfg_dmuaut1(): - gen_cfg_dmuaut(folder_output, input_vars, selected_params) + job_name = selected_job.get() + if not _verify_job(job_name): + return + job_safe = make_windows_safe(job_name) + save_dir = os.path.join(folder_parsets, "files", job_safe) + + gen_dir = gen_cfg_dmuaut(folder_output, input_vars, selected_params) + print(save_dir) + print(gen_dir) + _deep_copy(save_dir, gen_dir) # def btn_gen_cfg_dmuaut2(): # gen_cfg_dmuaut(folder_output, input_vars, selected_params, filetransfer=True) @@ -335,7 +421,7 @@ def main(): root.grid_rowconfigure(0, weight=1) # ---- Setup the EVALUATION section - setup_evaluation(root, folder_pictures, data, folder_output, input_vars, selected_params) + setup_evaluation(root, folder_pictures, data, folder_output, input_vars, selected_params, selected_job) # After the UI is fully set up, load the selected job to update parameter lists load_selected_job() # Ensure this is called to load the job parameters diff --git a/funct_gen.py b/funct_gen.py index 00354de..742e994 100644 --- a/funct_gen.py +++ b/funct_gen.py @@ -54,6 +54,8 @@ def gen_cfg_dmuaut(folder_output, input_vars, selected_params, filetransfer=Fals else: os.startfile(folder_path) + return folder_path + def gen_cfg_inlay(folder_output, input_vars, selected_params, filetransfer=False): diff --git a/functions.py b/functions.py index 31baf19..4fa4de0 100644 --- a/functions.py +++ b/functions.py @@ -8,8 +8,10 @@ import os import trimesh from mpl_toolkits.mplot3d.art3d import Poly3DCollection import numpy as np +import re +import hashlib + -# Function to load object definitions from YAML # Load a specific parameter set from a YAML file for a group def load_yaml(group_name, param_name, folder_parsets): @@ -93,6 +95,14 @@ def create_new_param_popup(root, group_name, input_vars, param_values, param_dro tk.Button(new_window, text="Create", command=create_param_set).pack(pady=10) +def make_windows_safe(name: str) -> str: + suffix = hashlib.sha1(name.encode("utf-8")).hexdigest()[:4] + safe = re.sub(r'[<>:"/\\\\|?*]', "_", name).strip() + safe = safe.rstrip(". ") + return f"{safe}_{suffix}" + + + # ------------------------------------------------------------------------------------------------------- def plot_clamping(ax, x, y, z, dx, dy1, dy2, dz1, dz2, color='blue', alpha=0.5, linewidth=1, inverty=False): """Efficiently plots an L-shaped merged cube structure and draws only axis-aligned edges."""