diff --git a/.gitignore b/.gitignore index 69aa934..f238897 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +PocketSync.exe + # ---> Python # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/PocketSync.exe b/PocketSync.exe index 4407927..83576f0 100644 Binary files a/PocketSync.exe and b/PocketSync.exe differ diff --git a/config.json b/config.json index 8c79707..0519d56 100644 --- a/config.json +++ b/config.json @@ -1,9 +1,9 @@ { "version": 2, - "active_profile": "Default", + "active_profile": "Retroid Pocket 5", "profiles": [ { - "name": "Default", + "name": "Retroid Pocket 5", "esde_src": "C:/Users/jaild/Retroid/ES-DE", "roms_src": "C:/Users/jaild/Retroid/ROMs", "esde_dst": "F:/ES-DE", diff --git a/core/robocopy_engine.py b/core/robocopy_engine.py index b2546fe..ab173b3 100644 --- a/core/robocopy_engine.py +++ b/core/robocopy_engine.py @@ -42,6 +42,7 @@ class RobocopySyncEngine(SyncEngine): stderr=subprocess.STDOUT, text=True, universal_newlines=True, + creationflags=subprocess.CREATE_NO_WINDOW, ) files_copied = 0 diff --git a/pocketsync.py b/pocketsync.py index ff39770..addcfc4 100644 --- a/pocketsync.py +++ b/pocketsync.py @@ -23,6 +23,9 @@ def main() -> None: cm.load() root = tk.Tk() + ico = os.path.join(BASE_DIR, "assets", "pocketsync.ico") + if os.path.isfile(ico): + root.iconbitmap(ico) PocketSyncApp(root, cm) root.mainloop() diff --git a/ui/app.py b/ui/app.py index 27db7d2..b418135 100644 --- a/ui/app.py +++ b/ui/app.py @@ -27,8 +27,9 @@ class PocketSyncApp: # ------------------------------------------------------------------ def _build_ui(self) -> None: - self.root.title("PocketSync") + self.root.title("PocketSync (© 2026 JailDesigner)") self.root.geometry(f"{styles.WINDOW_WIDTH}x{styles.WINDOW_HEIGHT}") + self.root.configure(bg=styles.APP_BG) # --- Barra de perfiles --- self.profile_bar = ProfileBar(self.root, on_change=self._on_profile_change) @@ -56,7 +57,7 @@ class PocketSyncApp: # --- Botón Sync --- tk.Button( self.root, - text="Sync Now", + text="Sincronizar", font=styles.FONT_BUTTON, command=self._run_sync, ).pack(pady=6) @@ -67,7 +68,7 @@ class PocketSyncApp: # --- Panel de resumen --- self.summary = SummaryPanel(self.root) - self.summary.pack(fill="x", padx=styles.PAD_X, pady=styles.PAD_Y) + self.summary.pack(fill="both", expand=True, padx=styles.PAD_X, pady=styles.PAD_Y) self.root.protocol("WM_DELETE_WINDOW", self._on_close) diff --git a/ui/path_panel.py b/ui/path_panel.py index ca16c67..158b619 100644 --- a/ui/path_panel.py +++ b/ui/path_panel.py @@ -13,29 +13,40 @@ class PathPanel(tk.LabelFrame): parent, text=title, font=styles.FONT_HEADING, - padx=styles.PAD_X, - pady=styles.PAD_Y, + padx=8, + pady=4, **kwargs, ) + self.columnconfigure(1, weight=1) + self.path_esde = tk.StringVar() self.path_roms = tk.StringVar() - self._add_selector("ES-DE:", self.path_esde) - self._add_selector("ROMs:", self.path_roms) + self._add_selector(0, "ES-DE:", self.path_esde) + self._add_selector(1, "ROMs:", self.path_roms) - def _add_selector(self, label: str, var: tk.StringVar, callback: Optional[Callable] = None): - frame = tk.Frame(self) - frame.pack(fill="x", pady=2) + def _add_selector(self, row: int, label: str, var: tk.StringVar, callback: Optional[Callable] = None): + tk.Label( + self, + text=label, + width=8, + anchor="w", + font=styles.FONT_LABEL, + ).grid(row=row, column=0, sticky="w", pady=2) + + tk.Entry( + self, + textvariable=var, + font=styles.FONT_SMALL, + ).grid(row=row, column=1, sticky="ew", padx=4, pady=2) - tk.Label(frame, text=label, width=10, anchor="w", font=styles.FONT_LABEL).pack(side="left") - tk.Entry(frame, textvariable=var, width=55, font=styles.FONT_SMALL).pack(side="left", padx=4) tk.Button( - frame, + self, text="Buscar", font=styles.FONT_SMALL, command=lambda: self._choose(var, callback), - ).pack(side="left") + ).grid(row=row, column=2, sticky="e", pady=2) def _choose(self, var: tk.StringVar, callback: Optional[Callable]): path = filedialog.askdirectory() @@ -47,11 +58,10 @@ class PathPanel(tk.LabelFrame): def set_roms_callback(self, callback: Callable[[str], None]) -> None: """Registra callback que se invoca al cambiar la ruta de ROMs.""" - # Reemplaza el selector de ROMs con uno que tenga el callback for widget in self.winfo_children(): widget.destroy() - self._add_selector("ES-DE:", self.path_esde) - self._add_selector("ROMs:", self.path_roms, callback=callback) + self._add_selector(0, "ES-DE:", self.path_esde) + self._add_selector(1, "ROMs:", self.path_roms, callback=callback) def get_esde(self) -> str: return self.path_esde.get() diff --git a/ui/status_bar.py b/ui/status_bar.py index 334ef41..4f9f926 100644 --- a/ui/status_bar.py +++ b/ui/status_bar.py @@ -6,56 +6,58 @@ _MAX_FILE_LEN = 80 class StatusBar(tk.Frame): - """Barra de estado con tres labels: sistema, fase y archivo actual.""" + """Barra de estado con tres filas: sistema, fase y archivo actual.""" def __init__(self, parent, **kwargs): - super().__init__(parent, bg=styles.STATUS_BG, relief="sunken", bd=2, **kwargs) + super().__init__(parent, bg=styles.STATUS_BG, relief="groove", bd=1, **kwargs) - self._label_system = tk.Label( - self, - text="Sistema: -", - font=styles.FONT_LABEL + ("bold",) if isinstance(styles.FONT_LABEL, tuple) else styles.FONT_LABEL, - bg=styles.STATUS_BG, - fg=styles.STATUS_SYSTEM_FG, - anchor="w", - ) - self._label_system.pack(fill="x", padx=10, pady=3) + self.columnconfigure(1, weight=1) - self._label_phase = tk.Label( - self, - text="Fase: -", - font=styles.FONT_LABEL, - bg=styles.STATUS_BG, - fg=styles.STATUS_PHASE_FG, - anchor="w", - ) - self._label_phase.pack(fill="x", padx=10, pady=3) + labels = ["Sistema:", "Fase:", "Archivo:"] + self._values = [] - self._label_file = tk.Label( - self, - text="Archivo: -", - font=styles.FONT_SMALL, - bg=styles.STATUS_BG, - fg=styles.STATUS_FILE_FG, - anchor="w", - ) - self._label_file.pack(fill="x", padx=10, pady=3) + for row, name in enumerate(labels): + tk.Label( + self, + text=name, + font=styles.FONT_LABEL + ("bold",), + bg=styles.STATUS_BG, + fg=styles.STATUS_LABEL_FG, + anchor="w", + width=9, + ).grid(row=row, column=0, sticky="w", padx=(10, 4), pady=3) + + val = tk.Label( + self, + text="-", + font=styles.FONT_SMALL, + bg=styles.STATUS_BG, + fg=styles.STATUS_VALUE_FG, + anchor="w", + ) + val.grid(row=row, column=1, sticky="ew", padx=(0, 10), pady=3) + self._values.append(val) def set_system(self, text: str) -> None: - self._label_system.config(text=text) - self._label_system.update_idletasks() + # Eliminar el prefijo "Sistema: " si viene incluido (compatibilidad con app.py) + if text.startswith("Sistema: "): + text = text[len("Sistema: "):] + self._values[0].config(text=text) + self._values[0].update_idletasks() def set_phase(self, text: str) -> None: - self._label_phase.config(text=text) - self._label_phase.update_idletasks() + if text.startswith("Fase: "): + text = text[len("Fase: "):] + self._values[1].config(text=text) + self._values[1].update_idletasks() def set_file(self, text: str) -> None: if len(text) > _MAX_FILE_LEN: text = "..." + text[-(_MAX_FILE_LEN - 3):] - self._label_file.config(text=f"Archivo: {text}") - self._label_file.update_idletasks() + self._values[2].config(text=text) + self._values[2].update_idletasks() def reset(self) -> None: - self.set_system("Sistema: ✅ COMPLETADO") - self.set_phase("Fase: -") - self.set_file("-") + self._values[0].config(text="✅ COMPLETADO") + self._values[1].config(text="-") + self._values[2].config(text="-") diff --git a/ui/styles.py b/ui/styles.py index 2c42629..c9bcf2b 100644 --- a/ui/styles.py +++ b/ui/styles.py @@ -3,24 +3,29 @@ FONT_FAMILY = "Segoe UI" FONT_HEADING = (FONT_FAMILY, 11, "bold") -FONT_LABEL = (FONT_FAMILY, 10) -FONT_SMALL = (FONT_FAMILY, 9) -FONT_BUTTON = (FONT_FAMILY, 11, "bold") -FONT_MONO = ("Consolas", 9) +FONT_LABEL = (FONT_FAMILY, 10) +FONT_SMALL = (FONT_FAMILY, 9) +FONT_BUTTON = (FONT_FAMILY, 10, "bold") +FONT_MONO = ("Consolas", 9) -# Colores de la barra de estado -STATUS_BG = "#2a2a2a" -STATUS_SYSTEM_FG = "#00ff00" -STATUS_PHASE_FG = "#00aaff" -STATUS_FILE_FG = "#ffaa00" +# Colores base +APP_BG = "#f5f5f5" # fondo ventana principal +FRAME_BG = "#ffffff" # fondo de frames internos +TEXT_PRIMARY = "#1a1a1a" # texto principal +TEXT_SECONDARY = "#555555" # texto secundario + +# StatusBar — Light +STATUS_BG = "#f0f0f0" +STATUS_LABEL_FG = TEXT_PRIMARY +STATUS_VALUE_FG = "#333333" # Colores del panel de resumen -SUMMARY_BG = "#f0f0f0" -SUMMARY_FG = "#000000" +SUMMARY_BG = "#ffffff" +SUMMARY_FG = TEXT_PRIMARY # Dimensiones de ventana -WINDOW_WIDTH = 800 -WINDOW_HEIGHT = 720 +WINDOW_WIDTH = 800 +WINDOW_HEIGHT = 860 # Padding genérico PAD_X = 10 diff --git a/ui/summary_panel.py b/ui/summary_panel.py index 6a6aa1c..f9f6129 100644 --- a/ui/summary_panel.py +++ b/ui/summary_panel.py @@ -13,13 +13,13 @@ class SummaryPanel(tk.Frame): self._text = tk.Text( self, - height=6, + height=10, state="disabled", bg=styles.SUMMARY_BG, fg=styles.SUMMARY_FG, font=styles.FONT_MONO, ) - self._text.pack(fill="both", expand=False, padx=styles.PAD_X, pady=styles.PAD_Y) + self._text.pack(fill="both", expand=True, padx=styles.PAD_X, pady=styles.PAD_Y) def append(self, line: str) -> None: self._text.configure(state="normal") diff --git a/ui/system_list.py b/ui/system_list.py index 2c5de17..853017a 100644 --- a/ui/system_list.py +++ b/ui/system_list.py @@ -26,14 +26,14 @@ class SystemList(tk.Frame): tk.Button( btn_frame, - text="Select All", + text="Seleccionar todo", font=styles.FONT_SMALL, command=self._select_all, ).pack(side="left", padx=2) tk.Button( btn_frame, - text="Select None", + text="Quitar selección", font=styles.FONT_SMALL, command=self._select_none, ).pack(side="left", padx=2)