games: Split out UI into its own module
This commit is contained in:
@@ -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
53
cartridges/ui/games.py
Normal 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))
|
||||||
@@ -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',
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user