498 lines
19 KiB
Python
498 lines
19 KiB
Python
import tkinter as tk
|
|
from tkinter import ttk, filedialog, messagebox
|
|
import PyLibrary.funciones_comunes as fc
|
|
import x1_importar_to_master
|
|
import x2_master_export2translate
|
|
import x3_llm_auto_translate
|
|
import x4_integrate_translates_to_master
|
|
import x4B_integrate_manual_translates_to_master
|
|
import x5_complete_empty_cells_master
|
|
import x6_update_from_master
|
|
from translation_config import TranslationConfig
|
|
import sys
|
|
import threading
|
|
import os
|
|
import queue
|
|
|
|
|
|
class RedirectText:
|
|
def __init__(self, queue):
|
|
self.queue = queue
|
|
|
|
def write(self, string):
|
|
self.queue.put(string)
|
|
|
|
def flush(self):
|
|
pass
|
|
|
|
|
|
class TranslationApp:
|
|
def __init__(self, master):
|
|
self.master = master
|
|
self.master.title("Ayuda para traducir textos de TIA Portal y Allen Bradley")
|
|
self.master.geometry("1200x800")
|
|
|
|
self.config = TranslationConfig.load()
|
|
|
|
self.create_variables()
|
|
self.create_widgets()
|
|
self.place_widgets()
|
|
|
|
self.queue = queue.Queue()
|
|
self.update_output()
|
|
|
|
# Cargar el log existente al iniciar
|
|
self.load_existing_log()
|
|
|
|
def create_variables(self):
|
|
self.codigo_tipo_PLC_var = tk.StringVar(value=self.config.codigo_tipo_PLC)
|
|
self.codigo_columna_maestra_var = tk.StringVar(
|
|
value=self.config.codigo_columna_maestra
|
|
)
|
|
self.codigo_idioma_var = tk.StringVar(
|
|
value=self.config.codigo_idioma_seleccionado
|
|
)
|
|
self.codigo_idioma_var2 = tk.StringVar(
|
|
value=self.config.codigo_idioma_secundario
|
|
)
|
|
self.work_dir_var = tk.StringVar(value=self.config.work_dir)
|
|
|
|
self.master_name_var = tk.StringVar(value=self.config.master_name)
|
|
self.translate_name_var = tk.StringVar(value=self.config.translate_name)
|
|
self.auto_translate_name_var = tk.StringVar(
|
|
value=self.config.auto_translate_name
|
|
)
|
|
|
|
def create_widgets(self):
|
|
self.main_frame = ttk.Frame(self.master)
|
|
self.main_frame.grid(row=0, column=0, sticky="nsew")
|
|
self.master.grid_rowconfigure(0, weight=1)
|
|
self.master.grid_columnconfigure(0, weight=1)
|
|
|
|
self.frame_combos = ttk.Frame(self.main_frame)
|
|
|
|
self.label_tipo_PLC = ttk.Label(
|
|
self.frame_combos, text="Selecciona el tipo de PLC:"
|
|
)
|
|
self.combo_tipo_PLC = ttk.Combobox(self.frame_combos, state="readonly")
|
|
self.combo_tipo_PLC["values"] = [nombre for nombre, _ in fc.PLCs.values()]
|
|
self.combo_tipo_PLC.bind("<<ComboboxSelected>>", self.update_tipo_PLC)
|
|
self.set_combo_value(self.combo_tipo_PLC, self.codigo_tipo_PLC_var.get())
|
|
|
|
self.label_codigo_maestra = ttk.Label(
|
|
self.frame_combos, text="Idioma Columna Maestra:"
|
|
)
|
|
self.combo_codigo_maestra = ttk.Combobox(self.frame_combos, state="readonly")
|
|
self.combo_codigo_maestra["values"] = [
|
|
nombre for nombre, _ in fc.IDIOMAS.values()
|
|
]
|
|
self.combo_codigo_maestra.bind(
|
|
"<<ComboboxSelected>>", self.update_codigo_maestra
|
|
)
|
|
self.set_combo_value(
|
|
self.combo_codigo_maestra, self.codigo_columna_maestra_var.get()
|
|
)
|
|
|
|
self.label1 = ttk.Label(self.frame_combos, text="Idioma de Traducción:")
|
|
self.combo = ttk.Combobox(self.frame_combos, state="readonly")
|
|
self.combo["values"] = [nombre for nombre, _ in fc.IDIOMAS.values()]
|
|
self.combo.bind("<<ComboboxSelected>>", self.update_idioma)
|
|
self.set_combo_value(self.combo, self.codigo_idioma_var.get())
|
|
|
|
self.label2 = ttk.Label(self.frame_combos, text="Selecciona segundo idioma:")
|
|
self.combo2 = ttk.Combobox(self.frame_combos, state="readonly")
|
|
self.combo2["values"] = [nombre for nombre, _ in fc.IDIOMAS.values()]
|
|
self.combo2.bind("<<ComboboxSelected>>", self.update_idioma2)
|
|
self.set_combo_value(self.combo2, self.codigo_idioma_var2.get())
|
|
|
|
self.work_dir_frame = ttk.Frame(self.main_frame)
|
|
self.work_dir_label = ttk.Label(
|
|
self.work_dir_frame, text="Directorio de trabajo:"
|
|
)
|
|
self.work_dir_entry = ttk.Entry(
|
|
self.work_dir_frame, textvariable=self.work_dir_var, width=50
|
|
)
|
|
self.work_dir_button = ttk.Button(
|
|
self.work_dir_frame, text="Seleccionar", command=self.select_work_dir
|
|
)
|
|
self.open_explorer_button = ttk.Button(
|
|
self.work_dir_frame, text="Abrir Explorador", command=self.open_explorer
|
|
)
|
|
|
|
style = ttk.Style()
|
|
style.configure("TButton", padding=(10, 10), font=("Helvetica", 10, "bold"))
|
|
style.configure(
|
|
"Excel.TButton",
|
|
padding=(10, 10),
|
|
font=("Helvetica", 10),
|
|
background="#69cf81",
|
|
)
|
|
|
|
self.button_width = 60
|
|
self.entry_width = 50
|
|
|
|
self.paso1 = ttk.Button(
|
|
self.main_frame,
|
|
text="1 - Importar al Master",
|
|
command=lambda: self.ejecutar_run(x1_importar_to_master.run),
|
|
width=self.button_width,
|
|
)
|
|
self.master_name_button = ttk.Button(
|
|
self.main_frame,
|
|
textvariable=self.master_name_var,
|
|
command=lambda: self.open_file(self.config.get_master_path()),
|
|
width=self.entry_width,
|
|
style="Excel.TButton",
|
|
)
|
|
|
|
self.paso2 = ttk.Button(
|
|
self.main_frame,
|
|
text="2 - Exportar Idioma a 2_master_export2translate.xlsx",
|
|
command=lambda: self.ejecutar_run(x2_master_export2translate.run),
|
|
width=self.button_width,
|
|
)
|
|
self.translate_name_button = ttk.Button(
|
|
self.main_frame,
|
|
textvariable=self.translate_name_var,
|
|
command=lambda: self.open_file(self.config.get_translate_path()),
|
|
width=self.entry_width,
|
|
style="Excel.TButton",
|
|
)
|
|
|
|
self.paso3 = ttk.Button(
|
|
self.main_frame,
|
|
text="3 - Traducir y generar 3_master_export2translate_translated.xlsx",
|
|
command=lambda: self.ejecutar_run(x3_llm_auto_translate.run),
|
|
width=self.button_width,
|
|
)
|
|
self.auto_translate_name_button = ttk.Button(
|
|
self.main_frame,
|
|
textvariable=self.auto_translate_name_var,
|
|
command=lambda: self.open_file(self.config.get_auto_translate_path()),
|
|
width=self.entry_width,
|
|
style="Excel.TButton",
|
|
)
|
|
|
|
self.paso4 = ttk.Button(
|
|
self.main_frame,
|
|
text="4 - Integrar las traducciones al 1_hmi_master_translates",
|
|
command=lambda: self.ejecutar_run(x4_integrate_translates_to_master.run),
|
|
width=self.button_width,
|
|
)
|
|
|
|
self.paso4B = ttk.Button(
|
|
self.main_frame,
|
|
text="4B - Integrar traducciones manuales al 1_hmi_master_translates",
|
|
command=lambda: self.ejecutar_run(
|
|
x4B_integrate_manual_translates_to_master.run
|
|
),
|
|
width=self.button_width,
|
|
)
|
|
|
|
self.paso5 = ttk.Button(
|
|
self.main_frame,
|
|
text="5 - Completar en 1_hmi_master_translates el idioma seleccionado usando el segundo idioma",
|
|
command=lambda: self.ejecutar_run(x5_complete_empty_cells_master.run),
|
|
width=self.button_width,
|
|
)
|
|
|
|
self.paso6 = ttk.Button(
|
|
self.main_frame,
|
|
text="6 - Exportar usando un archivo exportado desde Rockwell o TIA Portal usando 1_hmi_master_translates",
|
|
command=lambda: self.ejecutar_run(x6_update_from_master.run),
|
|
width=self.button_width,
|
|
)
|
|
|
|
self.output_text = tk.Text(self.main_frame, wrap="none", height=20)
|
|
self.scrollbar_y = ttk.Scrollbar(
|
|
self.main_frame, orient="vertical", command=self.output_text.yview
|
|
)
|
|
self.scrollbar_x = ttk.Scrollbar(
|
|
self.main_frame, orient="horizontal", command=self.output_text.xview
|
|
)
|
|
self.output_text.configure(
|
|
yscrollcommand=self.scrollbar_y.set, xscrollcommand=self.scrollbar_x.set
|
|
)
|
|
|
|
self.clear_button = ttk.Button(
|
|
self.main_frame, text="Limpiar salida", command=self.clear_output
|
|
)
|
|
self.open_log_button = ttk.Button(
|
|
self.main_frame, text="Abrir Log", command=self.open_log_file
|
|
)
|
|
|
|
def place_widgets(self):
|
|
self.main_frame.grid_columnconfigure(0, weight=1)
|
|
self.main_frame.grid_columnconfigure(1, weight=1)
|
|
|
|
self.frame_combos.grid(row=0, column=0, columnspan=2, pady=10, sticky="ew")
|
|
self.label_tipo_PLC.grid(row=0, column=0, padx=5, pady=5, sticky="e")
|
|
self.combo_tipo_PLC.grid(row=0, column=1, padx=5, pady=5, sticky="w")
|
|
self.label_codigo_maestra.grid(row=1, column=0, padx=5, pady=5, sticky="e")
|
|
self.combo_codigo_maestra.grid(row=1, column=1, padx=5, pady=5, sticky="w")
|
|
self.label1.grid(row=0, column=2, padx=5, pady=5, sticky="e")
|
|
self.combo.grid(row=0, column=3, padx=5, pady=5, sticky="w")
|
|
self.label2.grid(row=1, column=2, padx=5, pady=5, sticky="e")
|
|
self.combo2.grid(row=1, column=3, padx=5, pady=5, sticky="w")
|
|
|
|
self.work_dir_frame.grid(row=1, column=0, columnspan=2, pady=10, sticky="ew")
|
|
self.work_dir_label.grid(row=0, column=0, padx=5, sticky="w")
|
|
self.work_dir_entry.grid(row=0, column=1, padx=5, sticky="ew")
|
|
self.work_dir_button.grid(row=0, column=2, padx=5, sticky="e")
|
|
self.open_explorer_button.grid(row=0, column=3, padx=5, sticky="e")
|
|
self.work_dir_frame.grid_columnconfigure(1, weight=1)
|
|
|
|
current_row = 2
|
|
self.paso1.grid(row=current_row, column=0, pady=5, padx=5, sticky="ew")
|
|
self.master_name_button.grid(
|
|
row=current_row, column=1, pady=5, padx=5, sticky="ew"
|
|
)
|
|
|
|
current_row += 1
|
|
self.paso2.grid(row=current_row, column=0, pady=5, padx=5, sticky="ew")
|
|
self.translate_name_button.grid(
|
|
row=current_row, column=1, pady=5, padx=5, sticky="ew"
|
|
)
|
|
|
|
current_row += 1
|
|
self.paso3.grid(row=current_row, column=0, pady=5, padx=5, sticky="ew")
|
|
self.auto_translate_name_button.grid(
|
|
row=current_row, column=1, pady=5, padx=5, sticky="ew"
|
|
)
|
|
|
|
current_row += 1
|
|
self.paso4.grid(row=current_row, column=0, pady=5, padx=5, sticky="ew")
|
|
|
|
current_row += 1
|
|
self.paso4B.grid(row=current_row, column=0, pady=5, padx=5, sticky="ew")
|
|
|
|
current_row += 1
|
|
self.paso5.grid(
|
|
row=current_row, column=0, columnspan=2, pady=5, padx=5, sticky="ew"
|
|
)
|
|
|
|
current_row += 1
|
|
self.paso6.grid(
|
|
row=current_row, column=0, columnspan=2, pady=5, padx=5, sticky="ew"
|
|
)
|
|
|
|
current_row += 1
|
|
self.output_text.grid(
|
|
row=current_row,
|
|
column=0,
|
|
columnspan=2,
|
|
padx=(10, 0),
|
|
pady=10,
|
|
sticky="nsew",
|
|
)
|
|
self.scrollbar_y.grid(row=current_row, column=2, pady=10, sticky="ns")
|
|
self.scrollbar_x.grid(
|
|
row=current_row + 1, column=0, columnspan=2, padx=10, sticky="ew"
|
|
)
|
|
|
|
current_row += 2
|
|
self.clear_button.grid(row=current_row, column=0, pady=10, padx=5, sticky="e")
|
|
self.open_log_button.grid(
|
|
row=current_row, column=1, pady=10, padx=5, sticky="w"
|
|
)
|
|
|
|
self.main_frame.grid_rowconfigure(current_row - 2, weight=1)
|
|
|
|
def set_combo_value(self, combo, codigo):
|
|
for nombre, code in fc.IDIOMAS.values():
|
|
if code == codigo:
|
|
combo.set(nombre)
|
|
return
|
|
for nombre, code in fc.PLCs.values():
|
|
if code == codigo:
|
|
combo.set(nombre)
|
|
return
|
|
|
|
def update_tipo_PLC(self, event):
|
|
nombre_seleccionado = self.combo_tipo_PLC.get()
|
|
for nombre, codigo in fc.PLCs.values():
|
|
if nombre == nombre_seleccionado:
|
|
self.codigo_tipo_PLC_var.set(codigo)
|
|
break
|
|
self.update_file_names()
|
|
|
|
def update_codigo_maestra(self, event):
|
|
nombre_seleccionado = self.combo_codigo_maestra.get()
|
|
for nombre, codigo in fc.IDIOMAS.values():
|
|
if nombre == nombre_seleccionado:
|
|
self.codigo_columna_maestra_var.set(codigo)
|
|
break
|
|
self.update_file_names()
|
|
|
|
def update_idioma(self, event):
|
|
nombre_seleccionado = self.combo.get()
|
|
for nombre, codigo in fc.IDIOMAS.values():
|
|
if nombre == nombre_seleccionado:
|
|
self.codigo_idioma_var.set(codigo)
|
|
break
|
|
self.update_file_names()
|
|
|
|
def update_idioma2(self, event):
|
|
nombre_seleccionado = self.combo2.get()
|
|
for nombre, codigo in fc.IDIOMAS.values():
|
|
if nombre == nombre_seleccionado:
|
|
self.codigo_idioma_var2.set(codigo)
|
|
break
|
|
self.update_file_names()
|
|
|
|
def save_config(self):
|
|
self.config.update(
|
|
codigo_tipo_PLC=self.codigo_tipo_PLC_var.get(),
|
|
codigo_columna_maestra=self.codigo_columna_maestra_var.get(),
|
|
codigo_idioma_seleccionado=self.codigo_idioma_var.get(),
|
|
codigo_idioma_secundario=self.codigo_idioma_var2.get(),
|
|
work_dir=self.work_dir_var.get(),
|
|
master_name=self.master_name_var.get(),
|
|
translate_name=self.translate_name_var.get(),
|
|
auto_translate_name=self.auto_translate_name_var.get(),
|
|
)
|
|
self.config.save()
|
|
|
|
def select_work_dir(self):
|
|
dir_path = filedialog.askdirectory()
|
|
if dir_path:
|
|
self.work_dir_var.set(dir_path)
|
|
self.config.work_dir = dir_path
|
|
self.save_config()
|
|
self.load_existing_log() # Cargar el log del nuevo directorio
|
|
|
|
def load_existing_log(self):
|
|
log_file = os.path.join(self.config.work_dir, "logs", "app_log.txt")
|
|
if os.path.exists(log_file):
|
|
with open(log_file, "r", encoding="utf-8") as f:
|
|
log_content = f.read()
|
|
self.output_text.delete("1.0", tk.END)
|
|
self.output_text.insert(tk.END, log_content)
|
|
self.output_text.see(tk.END)
|
|
else:
|
|
self.output_text.delete("1.0", tk.END)
|
|
self.output_text.insert(tk.END, "No se encontró un log existente.\n")
|
|
|
|
def open_file(self, file_path):
|
|
if os.path.exists(file_path):
|
|
os.startfile(file_path)
|
|
else:
|
|
messagebox.showerror("Error", f"El archivo {file_path} no existe.")
|
|
|
|
def open_explorer(self):
|
|
if os.path.exists(self.config.work_dir):
|
|
os.startfile(self.config.work_dir)
|
|
else:
|
|
messagebox.showerror(
|
|
"Error", f"El directorio {self.config.work_dir} no existe."
|
|
)
|
|
|
|
def open_log_file(self):
|
|
log_file_path = os.path.join(self.config.work_dir, "logs", "translate_log.log")
|
|
if os.path.exists(log_file_path):
|
|
if sys.platform == "win32":
|
|
os.startfile(log_file_path)
|
|
else:
|
|
opener = "open" if sys.platform == "darwin" else "xdg-open"
|
|
subprocess.call([opener, log_file_path])
|
|
else:
|
|
messagebox.showerror("Error", f"El archivo de log {log_file_path} no existe.")
|
|
|
|
def update_file_names(self, event=None):
|
|
codigo_tipo_PLC = self.codigo_tipo_PLC_var.get()
|
|
codigo_idioma_seleccionado = self.codigo_idioma_var.get()
|
|
|
|
self.master_name_var.set(f"1_hmi_master_translates_{codigo_tipo_PLC}.xlsx")
|
|
self.translate_name_var.set(
|
|
f"2_master_export2translate_{codigo_tipo_PLC}_{codigo_idioma_seleccionado}.xlsx"
|
|
)
|
|
self.auto_translate_name_var.set(
|
|
f"3_master_export2translate_translated_{codigo_tipo_PLC}_{codigo_idioma_seleccionado}.xlsx"
|
|
)
|
|
|
|
self.save_config()
|
|
|
|
def ejecutar_run(self, funcion_run):
|
|
self.save_config()
|
|
|
|
# No limpiar el texto anterior
|
|
# self.output_text.delete('1.0', tk.END)
|
|
|
|
sys.stdout = RedirectText(self.queue)
|
|
|
|
def run_script():
|
|
try:
|
|
if funcion_run == x1_importar_to_master.run:
|
|
archivo_importacion = filedialog.askopenfilename(
|
|
title="Seleccione el archivo para Importar",
|
|
filetypes=[("Excel files", "*.xls*")],
|
|
)
|
|
if archivo_importacion:
|
|
funcion_run(self.config,archivo_importacion)
|
|
elif funcion_run == x2_master_export2translate.run:
|
|
funcion_run(self.config)
|
|
elif funcion_run == x3_llm_auto_translate.run:
|
|
traducir_todo = messagebox.askyesno(
|
|
"Traducir todo", "¿Desea traducir todas las celdas?"
|
|
)
|
|
self.config.traducir_todo = traducir_todo
|
|
funcion_run(self.config)
|
|
elif funcion_run == x4_integrate_translates_to_master.run:
|
|
funcion_run(self.config)
|
|
elif funcion_run == x4B_integrate_manual_translates_to_master.run:
|
|
funcion_run(self.config)
|
|
elif funcion_run == x5_complete_empty_cells_master.run:
|
|
funcion_run(self.config)
|
|
elif funcion_run == x6_update_from_master.run:
|
|
archivo_to_update = filedialog.askopenfilename(
|
|
title="Seleccione el archivo a actualizar",
|
|
filetypes=[("Excel files", "*.xlsx")],
|
|
)
|
|
if archivo_to_update:
|
|
funcion_run(self.config, archivo_to_update)
|
|
except Exception as e:
|
|
self.queue.put(f"Error: {str(e)}\n")
|
|
finally:
|
|
sys.stdout = sys.__stdout__
|
|
self.save_config()
|
|
self.save_log()
|
|
self.queue.put("DONE")
|
|
|
|
threading.Thread(target=run_script, daemon=True).start()
|
|
|
|
def update_output(self):
|
|
while True:
|
|
try:
|
|
message = self.queue.get_nowait()
|
|
if message == "DONE":
|
|
break
|
|
self.output_text.insert(tk.END, message)
|
|
self.output_text.see(tk.END)
|
|
self.output_text.update_idletasks()
|
|
except queue.Empty:
|
|
break
|
|
self.master.after(100, self.update_output)
|
|
|
|
def clear_output(self):
|
|
self.output_text.delete("1.0", tk.END)
|
|
self.save_log()
|
|
|
|
def save_log(self):
|
|
log_content = self.output_text.get("1.0", tk.END)
|
|
log_dir = os.path.join(self.config.work_dir, "logs")
|
|
os.makedirs(log_dir, exist_ok=True)
|
|
log_file = os.path.join(log_dir, "app_log.txt")
|
|
|
|
with open(log_file, "w", encoding="utf-8") as f:
|
|
f.write(log_content)
|
|
|
|
|
|
def main():
|
|
root = tk.Tk()
|
|
app = TranslationApp(root)
|
|
root.mainloop()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|