games: Add loading of games from disk

This commit is contained in:
Zoey Ahmed
2025-11-28 21:10:06 +00:00
parent a5721e41e7
commit 958558d1b6
9 changed files with 81 additions and 7 deletions

View File

@@ -1,3 +1,6 @@
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: Copyright 2025 Zoey Ahmed
import gettext import gettext
import locale import locale
import signal import signal
@@ -9,6 +12,7 @@ import gi
gi.require_versions({ gi.require_versions({
"Gtk": "4.0", "Gtk": "4.0",
"Adw": "1", "Adw": "1",
"Json": "1.0",
}) })
from gi.repository import Gio from gi.repository import Gio

View File

@@ -1,3 +1,6 @@
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: Copyright 2025 Zoey Ahmed
import sys import sys
from gi.events import GLibEventLoopPolicy from gi.events import GLibEventLoopPolicy

View File

@@ -1,3 +1,6 @@
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: Copyright 2025 Zoey Ahmed
from gettext import gettext as _ from gettext import gettext as _
from typing import override from typing import override

47
cartridges/games.py Normal file
View File

@@ -0,0 +1,47 @@
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: Copyright 2025 Zoey Ahmed
from collections.abc import Generator
from pathlib import Path
from gi.repository import (
Gio,
GLib,
GObject,
Json, # pyright: ignore[reportAttributeAccessIssue, reportUnknownVariableType]
)
GAMES_DIR = Path(GLib.get_user_data_dir(), "cartridges", "games")
class Game(GObject.Object):
"""Game data class."""
__gtype_name__ = __qualname__
added = GObject.Property(type=int)
executable = GObject.Property(type=str)
game_id = GObject.Property(type=str)
source = GObject.Property(type=str)
hidden = GObject.Property(type=bool, default=False)
last_played = GObject.Property(type=int, default=0)
name = GObject.Property(type=str)
developer = GObject.Property(type=str)
removed = GObject.Property(type=bool, default=False)
blacklisted = GObject.Property(type=bool, default=False)
version = GObject.Property(type=float, default=2.0)
def load() -> Generator[Game]:
"""Load the user's games from disk."""
for game in GAMES_DIR.iterdir():
data = game.read_text("utf-8")
try:
yield Json.gobject_from_data(Game, data, len(data))
except GLib.Error:
continue
model = Gio.ListStore.new(Game)
model.splice(0, 0, tuple(load()))

View File

@@ -1,5 +1,5 @@
python.install_sources( python.install_sources(
files('__init__.py', '__main__.py', 'application.py'), files('__init__.py', '__main__.py', 'application.py', 'games.py'),
subdir: 'cartridges', subdir: 'cartridges',
) )

View File

@@ -28,12 +28,18 @@ template $Window: Adw.ApplicationWindow {
} }
} }
content: Label { content: GridView {
label: _("Hello, World!"); model: NoSelection {
model: bind template.games;
};
styles [ factory: BuilderListItemFactory {
"title-1", template ListItem {
] child: Label {
label: bind template.item as <$Game>.name;
};
}
};
}; };
}; };
} }

View File

@@ -1,7 +1,11 @@
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: Copyright 2025 Zoey Ahmed
from typing import Any from typing import Any
from gi.repository import Adw, Gtk from gi.repository import Adw, Gio, GObject, Gtk
from cartridges import games
from cartridges.config import PREFIX, PROFILE from cartridges.config import PREFIX, PROFILE
@@ -11,6 +15,11 @@ class Window(Adw.ApplicationWindow):
__gtype_name__ = __qualname__ __gtype_name__ = __qualname__
@GObject.Property(type=Gio.ListStore)
def games(self) -> Gio.ListStore:
"""Model of the user's games."""
return games.model
def __init__(self, **kwargs: Any) -> None: def __init__(self, **kwargs: Any) -> None:
super().__init__(**kwargs) super().__init__(**kwargs)

View File

@@ -1,4 +1,5 @@
cartridges/application.py cartridges/application.py
cartridges/games.py
cartridges/ui/window.blp cartridges/ui/window.blp
cartridges/ui/window.py cartridges/ui/window.py
data/page.kramo.Cartridges.desktop.in data/page.kramo.Cartridges.desktop.in

View File

@@ -26,6 +26,7 @@ ignore = [
"COM812", "COM812",
"COM819", "COM819",
"D100", "D100",
"D104",
"D105", "D105",
"D107", "D107",
"D203", "D203",