Afig menú per ordenar els jocs (per defecte/per nom) amb persistència
This commit is contained in:
@@ -26,6 +26,14 @@ def _valid_console_mode(value) -> str:
|
|||||||
return value if value in _CONSOLE_MODES else "auto"
|
return value if value in _CONSOLE_MODES else "auto"
|
||||||
|
|
||||||
|
|
||||||
|
_SORT_ORDERS = ("default", "name")
|
||||||
|
|
||||||
|
|
||||||
|
def _valid_sort_order(value) -> str:
|
||||||
|
"""Normaliza el orden de la lista; cae a 'default' (orden del TOML) si es desconocido."""
|
||||||
|
return value if value in _SORT_ORDERS else "default"
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Settings:
|
class Settings:
|
||||||
hide_not_downloaded: bool = False
|
hide_not_downloaded: bool = False
|
||||||
@@ -34,6 +42,7 @@ class Settings:
|
|||||||
check_updates_on_start: bool = False # comprobar updates automáticamente al iniciar
|
check_updates_on_start: bool = False # comprobar updates automáticamente al iniciar
|
||||||
theme: str = "system" # tema de la UI: "system" | "light" | "dark"
|
theme: str = "system" # tema de la UI: "system" | "light" | "dark"
|
||||||
console_mode: str = "auto" # consola de log: "show" | "auto" | "hide"
|
console_mode: str = "auto" # consola de log: "show" | "auto" | "hide"
|
||||||
|
sort_order: str = "default" # orden de la lista: "default" (TOML) | "name"
|
||||||
# Tolerancia a repos offline/inalcanzables (segundos, salvo stall_limit en bytes/s).
|
# Tolerancia a repos offline/inalcanzables (segundos, salvo stall_limit en bytes/s).
|
||||||
git_fetch_timeout: int = 60 # techo para fetch / comprobar update
|
git_fetch_timeout: int = 60 # techo para fetch / comprobar update
|
||||||
git_clone_timeout: int = 900 # techo para clone (repo grande)
|
git_clone_timeout: int = 900 # techo para clone (repo grande)
|
||||||
@@ -61,6 +70,7 @@ def load_settings() -> Settings:
|
|||||||
check_updates_on_start=bool(data.get("check_updates_on_start", False)),
|
check_updates_on_start=bool(data.get("check_updates_on_start", False)),
|
||||||
theme=_valid_theme(data.get("theme", "system")),
|
theme=_valid_theme(data.get("theme", "system")),
|
||||||
console_mode=_valid_console_mode(data.get("console_mode", "auto")),
|
console_mode=_valid_console_mode(data.get("console_mode", "auto")),
|
||||||
|
sort_order=_valid_sort_order(data.get("sort_order", "default")),
|
||||||
git_fetch_timeout=int(data.get("git_fetch_timeout", 60)),
|
git_fetch_timeout=int(data.get("git_fetch_timeout", 60)),
|
||||||
git_clone_timeout=int(data.get("git_clone_timeout", 900)),
|
git_clone_timeout=int(data.get("git_clone_timeout", 900)),
|
||||||
http_timeout=int(data.get("http_timeout", 15)),
|
http_timeout=int(data.get("http_timeout", 15)),
|
||||||
|
|||||||
@@ -42,6 +42,9 @@ CONSOLE_SHOW = "show"
|
|||||||
CONSOLE_AUTO = "auto"
|
CONSOLE_AUTO = "auto"
|
||||||
CONSOLE_HIDE = "hide"
|
CONSOLE_HIDE = "hide"
|
||||||
|
|
||||||
|
SORT_DEFAULT = "default" # ordre del games.toml
|
||||||
|
SORT_NAME = "name" # alfabètic pel nom
|
||||||
|
|
||||||
|
|
||||||
class MainWindow(QMainWindow):
|
class MainWindow(QMainWindow):
|
||||||
def __init__(self, config: Config, root: Path, parent=None) -> None:
|
def __init__(self, config: Config, root: Path, parent=None) -> None:
|
||||||
@@ -76,16 +79,15 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
# --- Lista de juegos con scroll ---
|
# --- Lista de juegos con scroll ---
|
||||||
list_container = QWidget()
|
list_container = QWidget()
|
||||||
list_layout = QVBoxLayout(list_container)
|
self.list_layout = QVBoxLayout(list_container)
|
||||||
list_layout.setContentsMargins(6, 6, 6, 6)
|
self.list_layout.setContentsMargins(6, 6, 6, 6)
|
||||||
list_layout.setSpacing(6)
|
self.list_layout.setSpacing(6)
|
||||||
for game in config.games:
|
for game in config.games:
|
||||||
row = GameRow(game, root)
|
row = GameRow(game, root)
|
||||||
row.activated.connect(self._on_activate)
|
row.activated.connect(self._on_activate)
|
||||||
row.delete_requested.connect(self._on_delete)
|
row.delete_requested.connect(self._on_delete)
|
||||||
self.rows[game.id] = row
|
self.rows[game.id] = row
|
||||||
list_layout.addWidget(row)
|
self._populate_list()
|
||||||
list_layout.addStretch(1)
|
|
||||||
|
|
||||||
scroll = QScrollArea()
|
scroll = QScrollArea()
|
||||||
scroll.setWidgetResizable(True)
|
scroll.setWidgetResizable(True)
|
||||||
@@ -238,6 +240,7 @@ class MainWindow(QMainWindow):
|
|||||||
menu.addAction(self.action_check_on_start)
|
menu.addAction(self.action_check_on_start)
|
||||||
|
|
||||||
menu.addSeparator()
|
menu.addSeparator()
|
||||||
|
self._build_sort_menu(menu)
|
||||||
self._build_theme_menu(menu)
|
self._build_theme_menu(menu)
|
||||||
self._build_console_menu(menu)
|
self._build_console_menu(menu)
|
||||||
|
|
||||||
@@ -329,6 +332,27 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
dlg.exec()
|
dlg.exec()
|
||||||
|
|
||||||
|
def _build_sort_menu(self, parent_menu) -> None:
|
||||||
|
"""Submenú Ordena amb dues opcions exclusives: Per defecte / Per nom."""
|
||||||
|
submenu = parent_menu.addMenu("Ordena")
|
||||||
|
group = QActionGroup(self)
|
||||||
|
group.setExclusive(True)
|
||||||
|
options = [
|
||||||
|
("Per defecte", SORT_DEFAULT),
|
||||||
|
("Per nom", SORT_NAME),
|
||||||
|
]
|
||||||
|
for label, mode in options:
|
||||||
|
action = QAction(label, self, checkable=True)
|
||||||
|
action.setChecked(self.settings.sort_order == mode)
|
||||||
|
action.triggered.connect(lambda _checked, m=mode: self._on_sort_selected(m))
|
||||||
|
group.addAction(action)
|
||||||
|
submenu.addAction(action)
|
||||||
|
|
||||||
|
def _on_sort_selected(self, mode: str) -> None:
|
||||||
|
self.settings.sort_order = mode
|
||||||
|
save_settings(self.settings)
|
||||||
|
self._populate_list()
|
||||||
|
|
||||||
def _build_theme_menu(self, parent_menu) -> None:
|
def _build_theme_menu(self, parent_menu) -> None:
|
||||||
"""Submenú Tema amb tres opcions exclusives: Sistema / Clar / Fosc."""
|
"""Submenú Tema amb tres opcions exclusives: Sistema / Clar / Fosc."""
|
||||||
submenu = parent_menu.addMenu("Tema")
|
submenu = parent_menu.addMenu("Tema")
|
||||||
@@ -412,6 +436,23 @@ class MainWindow(QMainWindow):
|
|||||||
self.settings.check_updates_on_start = checked
|
self.settings.check_updates_on_start = checked
|
||||||
save_settings(self.settings)
|
save_settings(self.settings)
|
||||||
|
|
||||||
|
def _ordered_games(self) -> list[Game]:
|
||||||
|
"""Jocs en l'ordre triat: alfabètic pel nom, o l'ordre original del games.toml."""
|
||||||
|
if self.settings.sort_order == SORT_NAME:
|
||||||
|
return sorted(self.config.games, key=lambda g: g.name.casefold())
|
||||||
|
return list(self.config.games)
|
||||||
|
|
||||||
|
def _populate_list(self) -> None:
|
||||||
|
"""(Re)col·loca les files al layout segons l'ordre triat, sense destruir-les."""
|
||||||
|
while self.list_layout.count():
|
||||||
|
item = self.list_layout.takeAt(0)
|
||||||
|
w = item.widget() if item else None
|
||||||
|
if w is not None:
|
||||||
|
w.setParent(None) # treu del layout però conserva la fila (viu a self.rows)
|
||||||
|
for game in self._ordered_games():
|
||||||
|
self.list_layout.addWidget(self.rows[game.id])
|
||||||
|
self.list_layout.addStretch(1)
|
||||||
|
|
||||||
def _apply_filter(self) -> None:
|
def _apply_filter(self) -> None:
|
||||||
hide = self.action_hide.isChecked()
|
hide = self.action_hide.isChecked()
|
||||||
for row in self.rows.values():
|
for row in self.rows.values():
|
||||||
|
|||||||
Reference in New Issue
Block a user