From bfa01f31e38ff51e8b8d6e622d443718c2b9ca7e Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Fri, 29 May 2026 22:13:58 +0200 Subject: [PATCH] =?UTF-8?q?Mode=20esborrar=20des=20del=20men=C3=BA:=20tria?= =?UTF-8?q?=20un=20joc=20descarregat=20i=20s'elimina?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jlauncher/ui/game_row.py | 23 ++++++++++++++++++++--- jlauncher/ui/main_window.py | 30 +++++++++++++++++++++++++++--- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/jlauncher/ui/game_row.py b/jlauncher/ui/game_row.py index 8a1c7bf..a410cd0 100644 --- a/jlauncher/ui/game_row.py +++ b/jlauncher/ui/game_row.py @@ -40,6 +40,7 @@ class GameRow(QFrame): self.root = root self._update_available = False self._busy = False + self._delete_mode = False self.setObjectName("gameRow") self.setFrameShape(QFrame.StyledPanel) # La fila és un botó: cursor de mà i ressaltat en passar el ratolí. @@ -118,6 +119,11 @@ class GameRow(QFrame): self._update_available = available self.refresh() + def set_delete_mode(self, on: bool) -> None: + """Activa/desactiva el mode esborrar (canvia el text d'acció a 'Esborra').""" + self._delete_mode = on + self.refresh() + def refresh(self) -> None: """Recarrega icona, descripció i estat des de la cache local.""" meta = load_meta(self.root, self.game.id) @@ -143,20 +149,31 @@ class GameRow(QFrame): ) def _set_status(self, meta: GameMeta) -> None: - if not self.is_installed(): + installed = self.is_installed() + + # Text d'estat (independent del mode esborrar). + if not installed: self.status_label.setText("No descarregat") self.status_label.setStyleSheet("color: #cc8855; font-size: 11px;") - self._set_action("Descarrega", "#4a90d9") elif self._update_available: self.status_label.setText("⬆ Actualització disponible") self.status_label.setStyleSheet( "color: #e0a030; font-weight: bold; font-size: 11px;" ) - self._set_action("Actualitza", "#e0a030") else: ver = f" {meta.version}" if meta.version else "" self.status_label.setText(f"Descarregat{ver}") self.status_label.setStyleSheet("color: #6fae6f; font-size: 11px;") + + # Text d'acció (què fa el clic). + if self._delete_mode: + # Només es pot esborrar el que està descarregat. + self._set_action("Esborra", "#d9534f") if installed else self.action_label.clear() + elif not installed: + self._set_action("Descarrega", "#4a90d9") + elif self._update_available: + self._set_action("Actualitza", "#e0a030") + else: self._set_action("Juga", "#6fae6f") def _set_action(self, text: str, color: str) -> None: diff --git a/jlauncher/ui/main_window.py b/jlauncher/ui/main_window.py index c1497c4..9ffd37a 100644 --- a/jlauncher/ui/main_window.py +++ b/jlauncher/ui/main_window.py @@ -34,6 +34,7 @@ class MainWindow(QMainWindow): self.settings = load_settings() self.pool = QThreadPool.globalInstance() self.rows: dict[str, GameRow] = {} + self._delete_mode = False # Mantener referencias a los workers en vuelo: si no, Python los recolecta # (junto a su objeto de señales) antes de que la señal en cola `finished` # llegue al hilo principal, y la UI nunca se refresca. @@ -95,6 +96,11 @@ class MainWindow(QMainWindow): self.action_check.triggered.connect(self._check_updates) menu.addAction(self.action_check) + menu.addSeparator() + self.action_delete = QAction("Esborra un joc", self, checkable=True) + self.action_delete.toggled.connect(self._set_delete_mode) + menu.addAction(self.action_delete) + def _on_toggle_hide(self, checked: bool) -> None: self.settings.hide_not_downloaded = checked save_settings(self.settings) @@ -150,9 +156,25 @@ class MainWindow(QMainWindow): # --------------------------------------------------------------- accions + def _set_delete_mode(self, on: bool) -> None: + self._delete_mode = on + for row in self.rows.values(): + row.set_delete_mode(on) + if on: + self._log( + "Mode esborrar: tria un joc descarregat per eliminar-lo " + "(o desmarca «Esborra un joc» per cancel·lar)." + ) + def _on_activate(self, game: Game) -> None: - """Clic sobre la fila: descarrega/actualitza si cal, si no juga.""" + """Clic sobre la fila. En mode esborrar elimina; si no, descarrega/actualitza o juga.""" row = self.rows[game.id] + if self._delete_mode: + if not row.is_installed(): + return # res a esborrar; segueix en mode esborrar + if self._on_delete(game): + self.action_delete.setChecked(False) # surt del mode esborrar + return if row.primary_action_is_download(): self._on_download(game) else: @@ -206,7 +228,8 @@ class MainWindow(QMainWindow): row.set_busy(False) row.refresh() - def _on_delete(self, game: Game) -> None: + def _on_delete(self, game: Game) -> bool: + """Esborra la descàrrega local (amb confirmació). Retorna True si s'ha esborrat.""" resp = QMessageBox.question( self, "Esborrar descàrrega", @@ -216,7 +239,7 @@ class MainWindow(QMainWindow): QMessageBox.No, ) if resp != QMessageBox.Yes: - return + return False self._log(f"=== Esborra: {game.name} ===") gitops.delete_local(self.root, game, log=self._log) if game.id in self.settings.updates_pending: @@ -228,3 +251,4 @@ class MainWindow(QMainWindow): row.set_update_available(False) row.refresh() self._apply_filter() # si està actiu "amaga no descarregats", ara s'amaga + return True