games: Split out UI into its own module

This commit is contained in:
Jamie Gravendeel
2025-12-19 17:24:34 +01:00
parent 9a9514a1ae
commit e645ade8d6
5 changed files with 60 additions and 45 deletions

View File

@@ -5,7 +5,6 @@
import itertools import itertools
import json import json
import locale
import os import os
import subprocess import subprocess
from collections.abc import Callable, Generator, Iterable from collections.abc import Callable, Generator, Iterable
@@ -14,11 +13,11 @@ from json import JSONDecodeError
from pathlib import Path from pathlib import Path
from shlex import quote from shlex import quote
from types import UnionType 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: if TYPE_CHECKING:
from .application import Application from .application import Application
@@ -51,13 +50,6 @@ _COVERS_DIR = DATA_DIR / "covers"
_SPEC_VERSION = 2.0 _SPEC_VERSION = 2.0
_MANUALLY_ADDED_ID = "imported" _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): class Game(Gio.SimpleActionGroup):
@@ -190,39 +182,6 @@ class Game(Gio.SimpleActionGroup):
window.send_toast(title, undo=undo) 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: def _increment_manually_added_id() -> int:
numbers = { numbers = {
game.game_id.split("_")[1] game.game_id.split("_")[1]

53
cartridges/ui/games.py Normal file
View File

@@ -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))

View File

@@ -4,6 +4,7 @@ python.install_sources(
'cover.py', 'cover.py',
'game_details.py', 'game_details.py',
'game_item.py', 'game_item.py',
'games.py',
'window.py', 'window.py',
), ),
subdir: 'cartridges' / 'ui', subdir: 'cartridges' / 'ui',

View File

@@ -12,10 +12,11 @@ from gi.repository import Adw, Gio, GLib, GObject, Gtk
from cartridges import games, state_settings from cartridges import games, state_settings
from cartridges.config import PREFIX, PROFILE from cartridges.config import PREFIX, PROFILE
from cartridges.games import Game, GameSorter from cartridges.games import Game
from .game_details import GameDetails from .game_details import GameDetails
from .game_item import GameItem # noqa: F401 from .game_item import GameItem # noqa: F401
from .games import GameSorter
if sys.platform.startswith("linux"): if sys.platform.startswith("linux"):
from cartridges import gamepads from cartridges import gamepads

View File

@@ -10,6 +10,7 @@ cartridges/ui/game-details.blp
cartridges/ui/game-item.blp cartridges/ui/game-item.blp
cartridges/ui/game_details.py cartridges/ui/game_details.py
cartridges/ui/game_item.py cartridges/ui/game_item.py
cartridges/ui/games.py
cartridges/ui/shortcuts-dialog.blp cartridges/ui/shortcuts-dialog.blp
cartridges/ui/window.blp cartridges/ui/window.blp
cartridges/ui/window.py cartridges/ui/window.py