diff --git a/config.json b/config.json index 653e8db..3230492 100644 --- a/config.json +++ b/config.json @@ -27,7 +27,6 @@ "msx", "msx2", "n64", - "nds", "neogeo", "neogeocd", "nes", @@ -35,7 +34,6 @@ "ngpc", "pcengine", "pcenginecd", - "psp", "psx", "satellaview", "saturn", diff --git a/test_tkinter.py b/test_tkinter.py index ae99725..e452a75 100644 --- a/test_tkinter.py +++ b/test_tkinter.py @@ -13,7 +13,7 @@ class DirectorySelectorApp: def __init__(self, root): self.root = root self.root.title("Selector de Directorios ES-DE / ROMs") - self.root.geometry("700x650") + self.root.geometry("700x700") # Variables de rutas self.path_esde_src = tk.StringVar() @@ -34,7 +34,7 @@ class DirectorySelectorApp: # --------------------------- tk.Label(root, text="Directorios encontrados en ROMs:", font=("Arial", 11)).pack(pady=(15, 5)) - self.listbox = tk.Listbox(root, selectmode=tk.MULTIPLE, height=15) + self.listbox = tk.Listbox(root, selectmode=tk.MULTIPLE, height=10) self.listbox.pack(fill="both", expand=True, padx=10) # --------------------------- @@ -52,12 +52,33 @@ class DirectorySelectorApp: command=self.run_robocopy).pack(pady=10) # --------------------------- - # PANEL DE LOG + # LABELS DE ESTADO # --------------------------- - tk.Label(root, text="Progreso:", font=("Arial", 11)).pack(pady=(5, 0)) + status_frame = tk.Frame(root, bg="#2a2a2a", relief="sunken", bd=2) + status_frame.pack(fill="x", padx=10, pady=5) - self.log = tk.Text(root, height=10, state="disabled", bg="#111", fg="#0f0") - self.log.pack(fill="both", expand=False, padx=10, pady=5) + self.label_system = tk.Label(status_frame, text="Sistema: -", + font=("Arial", 10, "bold"), + bg="#2a2a2a", fg="#00ff00", anchor="w") + self.label_system.pack(fill="x", padx=10, pady=3) + + self.label_phase = tk.Label(status_frame, text="Fase: -", + font=("Arial", 10), + bg="#2a2a2a", fg="#00aaff", anchor="w") + self.label_phase.pack(fill="x", padx=10, pady=3) + + self.label_current = tk.Label(status_frame, text="Archivo: -", + font=("Arial", 9), + bg="#2a2a2a", fg="#ffaa00", anchor="w") + self.label_current.pack(fill="x", padx=10, pady=3) + + # --------------------------- + # RESUMEN + # --------------------------- + tk.Label(root, text="Resumen:", font=("Arial", 11)).pack(pady=(10, 5)) + + self.summary_text = tk.Text(root, height=6, state="disabled", bg="#f0f0f0", fg="#000") + self.summary_text.pack(fill="both", expand=False, padx=10, pady=5) # Evento de cierre self.root.protocol("WM_DELETE_WINDOW", self.on_close) @@ -105,13 +126,33 @@ class DirectorySelectorApp: messagebox.showerror("Error", f"No se pudo leer la ruta:\n{e}") # --------------------------------------------------------- - # LOG + # ACTUALIZACIÓN DE LABELS Y RESUMEN # --------------------------------------------------------- - def append_log(self, text): - self.log.configure(state="normal") - self.log.insert(tk.END, text + "\n") - self.log.see(tk.END) - self.log.configure(state="disabled") + def append_summary(self, text): + self.summary_text.configure(state="normal") + self.summary_text.insert(tk.END, text + "\n") + self.summary_text.see(tk.END) + self.summary_text.configure(state="disabled") + + def clear_summary(self): + self.summary_text.configure(state="normal") + self.summary_text.delete(1.0, tk.END) + self.summary_text.configure(state="disabled") + + def update_status_system(self, text): + self.label_system.config(text=text) + self.root.update_idletasks() + + def update_status_phase(self, text): + self.label_phase.config(text=text) + self.root.update_idletasks() + + def update_status_current(self, text): + # Limitar longitud para que no se salga de la ventana + if len(text) > 80: + text = "..." + text[-77:] + self.label_current.config(text=text) + self.root.update_idletasks() # --------------------------------------------------------- # EJECUTAR ROBOCOPY (HILO) @@ -125,7 +166,7 @@ class DirectorySelectorApp: selected = [self.listbox.get(i) for i in self.listbox.curselection()] if not selected: - self.append_log("❌ No hay sistemas seleccionados.") + self.append_summary("❌ No hay sistemas seleccionados.") return esde_src = self.path_esde_src.get() @@ -134,54 +175,68 @@ class DirectorySelectorApp: roms_dst = self.path_roms_dst.get() if not all([esde_src, roms_src, esde_dst, roms_dst]): - self.append_log("❌ ERROR: Debes configurar todas las rutas antes de continuar.") + self.append_summary("❌ ERROR: Debes configurar todas las rutas antes de continuar.") return - self.append_log("=" * 60) - self.append_log("🚀 INICIANDO PROCESO DE COPIA") - self.append_log(f"📦 Total de sistemas a procesar: {len(selected)}") - self.append_log("=" * 60) + self.clear_summary() + self.append_summary("=" * 60) + self.append_summary("🚀 INICIANDO PROCESO DE COPIA") + self.append_summary(f"📦 Total de sistemas a procesar: {len(selected)}") + self.append_summary("=" * 60) + + total_systems = len(selected) for idx, system in enumerate(selected, 1): - self.append_log(f"\n{'=' * 60}") - self.append_log(f"🎮 SISTEMA [{idx}/{len(selected)}]: {system.upper()}") - self.append_log("=" * 60) + # Actualizar label de sistema + self.update_status_system(f"Sistema: {idx}/{total_systems} - {system.upper()}") + + self.append_summary(f"\n🎮 SISTEMA [{idx}/{total_systems}]: {system.upper()}") # ROMs - self.append_log(f"\n📁 [1/3] Copiando ROMs...") + self.update_status_phase("Fase: [1/3] Copiando ROMs...") + self.append_summary(" 📁 [1/3] Copiando ROMs...") self.launch_robocopy_with_log( os.path.join(roms_src, system), os.path.join(roms_dst, system) ) # ES-DE gamelists - self.append_log(f"\n📋 [2/3] Copiando gamelists...") + self.update_status_phase("Fase: [2/3] Copiando gamelists...") + self.append_summary(" 📋 [2/3] Copiando gamelists...") self.launch_robocopy_with_log( os.path.join(esde_src, "gamelists", system), os.path.join(esde_dst, "gamelists", system) ) # ES-DE downloaded_media - self.append_log(f"\n🖼️ [3/3] Copiando media...") + self.update_status_phase("Fase: [3/3] Copiando media...") + self.append_summary(" 🖼️ [3/3] Copiando media...") self.launch_robocopy_with_log( os.path.join(esde_src, "downloaded_media", system), os.path.join(esde_dst, "downloaded_media", system) ) - self.append_log(f"\n✅ Sistema '{system}' completado") + self.append_summary(f" ✅ Sistema '{system}' completado\n") - self.append_log("\n" + "=" * 60) - self.append_log("🎉 PROCESO COMPLETADO EXITOSAMENTE") - self.append_log("=" * 60) + # Limpiar labels al finalizar + self.update_status_system("Sistema: ✅ COMPLETADO") + self.update_status_phase("Fase: -") + self.update_status_current("Archivo: -") + + self.append_summary("=" * 60) + self.append_summary("🎉 PROCESO COMPLETADO EXITOSAMENTE") + self.append_summary("=" * 60) def launch_robocopy_with_log(self, src, dst): if not os.path.isdir(src): - self.append_log(f" ⚠️ Carpeta no existe (omitido): {os.path.basename(src)}") + self.append_summary(f" ⚠️ Carpeta no existe (omitido)") + self.update_status_current("Archivo: (carpeta no existe)") return os.makedirs(dst, exist_ok=True) - cmd = ["robocopy", src, dst, "/MIR", "/NP", "/NDL", "/NFL"] + # Quitar /NFL y /NDL para ver los archivos en tiempo real + cmd = ["robocopy", src, dst, "/MIR", "/NP"] process = subprocess.Popen( cmd, @@ -199,39 +254,48 @@ class DirectorySelectorApp: for line in process.stdout: line = line.strip() + # Actualizar label con el archivo actual + if line and not line.startswith("---") and not line.startswith("Total"): + # Si la línea parece un archivo siendo copiado + if len(line) > 5 and not any(x in line for x in ["Files :", "Dirs :", "Bytes :", "Speed :", "Times :"]): + self.update_status_current(f"Archivo: {line}") + # Extraer información relevante del output de robocopy - if "Files :" in line and "Copied" in line: + if "Files :" in line: parts = line.split() try: - copied_idx = parts.index("Copied") - if copied_idx + 1 < len(parts): - files_copied = int(parts[copied_idx + 1]) + total_idx = parts.index("Files") + if total_idx + 2 < len(parts): + files_copied = int(parts[total_idx + 2]) except (ValueError, IndexError): pass - elif "Dirs :" in line and "Copied" in line: + elif "Dirs :" in line: parts = line.split() try: - copied_idx = parts.index("Copied") - if copied_idx + 1 < len(parts): - dirs_copied = int(parts[copied_idx + 1]) + total_idx = parts.index("Dirs") + if total_idx + 2 < len(parts): + dirs_copied = int(parts[total_idx + 2]) except (ValueError, IndexError): pass - elif "Bytes :" in line and "Copied" in line: + elif "Bytes :" in line: parts = line.split() try: - copied_idx = parts.index("Copied") - if copied_idx + 1 < len(parts): - bytes_str = parts[copied_idx + 1].replace(",", "") - total_bytes = int(bytes_str) + bytes_idx = parts.index("Bytes") + if bytes_idx + 2 < len(parts): + bytes_str = parts[bytes_idx + 2].replace(",", "").replace(".", "") + # Extraer solo números + bytes_str = ''.join(c for c in bytes_str if c.isdigit()) + if bytes_str: + total_bytes = int(bytes_str) except (ValueError, IndexError): pass process.wait() # Convertir bytes a formato legible - if total_bytes > 0: + if files_copied > 0 or dirs_copied > 0: if total_bytes < 1024: size_str = f"{total_bytes} B" elif total_bytes < 1024**2: @@ -241,9 +305,11 @@ class DirectorySelectorApp: else: size_str = f"{total_bytes/(1024**3):.2f} GB" - self.append_log(f" ✓ {files_copied} archivos, {dirs_copied} carpetas ({size_str})") + self.append_summary(f" ✓ {files_copied} archivos, {dirs_copied} carpetas ({size_str})") else: - self.append_log(f" ✓ Sin cambios (ya sincronizado)") + self.append_summary(f" ✓ Sin cambios (ya sincronizado)") + + self.update_status_current("Archivo: -") # --------------------------------------------------------- # PERSISTENCIA @@ -298,4 +364,4 @@ class DirectorySelectorApp: if __name__ == "__main__": root = tk.Tk() app = DirectorySelectorApp(root) - root.mainloop() + root.mainloop() \ No newline at end of file