diff --git a/cartridges/games.py b/cartridges/games.py index 537d527..c7beb87 100644 --- a/cartridges/games.py +++ b/cartridges/games.py @@ -5,7 +5,6 @@ import itertools import json -import locale import os import subprocess from collections.abc import Callable, Generator, Iterable @@ -14,11 +13,11 @@ from json import JSONDecodeError from pathlib import Path from shlex import quote from types import UnionType -from typing import TYPE_CHECKING, Any, NamedTuple, Self, cast, override +from typing import TYPE_CHECKING, Any, NamedTuple, Self, cast -from gi.repository import Gdk, Gio, GLib, GObject, Gtk +from gi.repository import Gdk, Gio, GLib, GObject -from cartridges import DATA_DIR, state_settings +from cartridges import DATA_DIR if TYPE_CHECKING: from .application import Application @@ -51,13 +50,6 @@ _COVERS_DIR = DATA_DIR / "covers" _SPEC_VERSION = 2.0 _MANUALLY_ADDED_ID = "imported" -_SORT_MODES = { - "last_played": ("last-played", True), - "a-z": ("name", False), - "z-a": ("name", True), - "newest": ("added", True), - "oldest": ("added", False), -} class Game(Gio.SimpleActionGroup): @@ -190,39 +182,6 @@ class Game(Gio.SimpleActionGroup): window.send_toast(title, undo=undo) -class GameSorter(Gtk.Sorter): - """A sorter for game objects. - - Automatically updates if the "sort-mode" GSetting changes. - """ - - __gtype_name__ = __qualname__ - - def __init__(self, **kwargs: Any): - super().__init__(**kwargs) - - state_settings.connect( - "changed::sort-mode", lambda *_: self.changed(Gtk.SorterChange.DIFFERENT) - ) - - @override - def do_compare(self, game1: Game, game2: Game) -> Gtk.Ordering: # pyright: ignore[reportIncompatibleMethodOverride] - prop, invert = _SORT_MODES[state_settings.get_string("sort-mode")] - a = (game2 if invert else game1).get_property(prop) - b = (game1 if invert else game2).get_property(prop) - - return Gtk.Ordering( - self._name_cmp(a, b) - if isinstance(a, str) - else ((a > b) - (a < b)) or self._name_cmp(game1.name, game2.name) - ) - - @staticmethod - def _name_cmp(a: str, b: str) -> int: - a, b = (name.lower().removeprefix("the ") for name in (a, b)) - return max(-1, min(locale.strcoll(a, b), 1)) - - def _increment_manually_added_id() -> int: numbers = { game.game_id.split("_")[1] diff --git a/cartridges/ui/games.py b/cartridges/ui/games.py new file mode 100644 index 0000000..9644010 --- /dev/null +++ b/cartridges/ui/games.py @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: GPL-3.0-or-later +# SPDX-FileCopyrightText: Copyright 2025 Zoey Ahmed +# SPDX-FileCopyrightText: Copyright 2025 kramo +# SPDX-FileCopyrightText: Copyright 2025 Jamie Gravendeel + +import locale +from typing import Any, override + +from gi.repository import Gtk + +from cartridges import state_settings +from cartridges.games import Game + +_SORT_MODES = { + "last_played": ("last-played", True), + "a-z": ("name", False), + "z-a": ("name", True), + "newest": ("added", True), + "oldest": ("added", False), +} + + +class GameSorter(Gtk.Sorter): + """A sorter for game objects. + + Automatically updates if the "sort-mode" GSetting changes. + """ + + __gtype_name__ = __qualname__ + + def __init__(self, **kwargs: Any): + super().__init__(**kwargs) + + state_settings.connect( + "changed::sort-mode", lambda *_: self.changed(Gtk.SorterChange.DIFFERENT) + ) + + @override + def do_compare(self, game1: Game, game2: Game) -> Gtk.Ordering: # pyright: ignore[reportIncompatibleMethodOverride] + prop, invert = _SORT_MODES[state_settings.get_string("sort-mode")] + a = (game2 if invert else game1).get_property(prop) + b = (game1 if invert else game2).get_property(prop) + + return Gtk.Ordering( + self._name_cmp(a, b) + if isinstance(a, str) + else ((a > b) - (a < b)) or self._name_cmp(game1.name, game2.name) + ) + + @staticmethod + def _name_cmp(a: str, b: str) -> int: + a, b = (name.lower().removeprefix("the ") for name in (a, b)) + return max(-1, min(locale.strcoll(a, b), 1)) diff --git a/cartridges/ui/meson.build b/cartridges/ui/meson.build index c3e291f..cc2be3d 100644 --- a/cartridges/ui/meson.build +++ b/cartridges/ui/meson.build @@ -4,6 +4,7 @@ python.install_sources( 'cover.py', 'game_details.py', 'game_item.py', + 'games.py', 'window.py', ), subdir: 'cartridges' / 'ui', diff --git a/cartridges/ui/window.py b/cartridges/ui/window.py index 34a6f4a..7f953c4 100644 --- a/cartridges/ui/window.py +++ b/cartridges/ui/window.py @@ -12,10 +12,11 @@ from gi.repository import Adw, Gio, GLib, GObject, Gtk from cartridges import games, state_settings from cartridges.config import PREFIX, PROFILE -from cartridges.games import Game, GameSorter +from cartridges.games import Game from .game_details import GameDetails from .game_item import GameItem # noqa: F401 +from .games import GameSorter if sys.platform.startswith("linux"): from cartridges import gamepads diff --git a/po/POTFILES.in b/po/POTFILES.in index c5dd04f..3417e4d 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -10,6 +10,7 @@ cartridges/ui/game-details.blp cartridges/ui/game-item.blp cartridges/ui/game_details.py cartridges/ui/game_item.py +cartridges/ui/games.py cartridges/ui/shortcuts-dialog.blp cartridges/ui/window.blp cartridges/ui/window.py