games: Load cover art
This commit is contained in:
@@ -1,18 +1,22 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# SPDX-FileCopyrightText: Copyright 2025 Zoey Ahmed
|
||||
# SPDX-FileCopyrightText: Copyright 2025 kramo
|
||||
|
||||
from collections.abc import Generator
|
||||
from pathlib import Path
|
||||
from typing import cast
|
||||
|
||||
from gi.repository import (
|
||||
Gdk,
|
||||
Gio,
|
||||
GLib,
|
||||
GObject,
|
||||
Json, # pyright: ignore[reportAttributeAccessIssue, reportUnknownVariableType]
|
||||
)
|
||||
|
||||
|
||||
GAMES_DIR = Path(GLib.get_user_data_dir(), "cartridges", "games")
|
||||
DATA_DIR = Path(GLib.get_user_data_dir(), "cartridges")
|
||||
GAMES_DIR = DATA_DIR / "games"
|
||||
COVERS_DIR = DATA_DIR / "covers"
|
||||
|
||||
|
||||
class Game(GObject.Object):
|
||||
@@ -32,16 +36,32 @@ class Game(GObject.Object):
|
||||
blacklisted = GObject.Property(type=bool, default=False)
|
||||
version = GObject.Property(type=float, default=2.0)
|
||||
|
||||
cover = GObject.Property(type=Gdk.Texture)
|
||||
|
||||
|
||||
def load() -> Generator[Game]:
|
||||
"""Load the user's games from disk."""
|
||||
for game in GAMES_DIR.iterdir():
|
||||
data = game.read_text("utf-8")
|
||||
for path in GAMES_DIR.glob("*.json"):
|
||||
try:
|
||||
yield Json.gobject_from_data(Game, data, len(data))
|
||||
data = path.read_text("utf-8")
|
||||
except UnicodeError:
|
||||
continue
|
||||
|
||||
try:
|
||||
game = cast(Game, Json.gobject_from_data(Game, data, len(data)))
|
||||
except GLib.Error:
|
||||
continue
|
||||
|
||||
cover_path = COVERS_DIR / game.game_id
|
||||
for ext in ".gif", ".tiff":
|
||||
filename = str(cover_path.with_suffix(ext))
|
||||
try:
|
||||
game.cover = Gdk.Texture.new_from_filename(filename)
|
||||
except GLib.Error:
|
||||
continue
|
||||
|
||||
yield game
|
||||
|
||||
|
||||
model = Gio.ListStore.new(Game)
|
||||
model.splice(0, 0, tuple(load()))
|
||||
|
||||
8
cartridges/ui/style.css
Normal file
8
cartridges/ui/style.css
Normal file
@@ -0,0 +1,8 @@
|
||||
#grid {
|
||||
padding: 6px 12px 12px;
|
||||
}
|
||||
|
||||
#grid > child {
|
||||
padding: 12px;
|
||||
border-radius: 24px;
|
||||
}
|
||||
@@ -2,5 +2,6 @@
|
||||
<gresources>
|
||||
<gresource prefix="@PREFIX@">
|
||||
<file>window.ui</file>
|
||||
<file>style.css</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
|
||||
@@ -3,8 +3,8 @@ using Adw 1;
|
||||
|
||||
template $Window: Adw.ApplicationWindow {
|
||||
title: _("Cartridges");
|
||||
default-width: 800;
|
||||
default-height: 600;
|
||||
default-width: 920;
|
||||
default-height: 700;
|
||||
|
||||
ShortcutController {
|
||||
Shortcut {
|
||||
@@ -28,18 +28,43 @@ template $Window: Adw.ApplicationWindow {
|
||||
}
|
||||
}
|
||||
|
||||
content: GridView {
|
||||
model: NoSelection {
|
||||
model: bind template.games;
|
||||
};
|
||||
content: ScrolledWindow {
|
||||
child: GridView {
|
||||
name: "grid";
|
||||
|
||||
factory: BuilderListItemFactory {
|
||||
template ListItem {
|
||||
child: Label {
|
||||
label: bind template.item as <$Game>.name;
|
||||
};
|
||||
}
|
||||
model: NoSelection {
|
||||
model: bind template.games;
|
||||
};
|
||||
|
||||
factory: BuilderListItemFactory {
|
||||
template ListItem {
|
||||
child: Box {
|
||||
orientation: vertical;
|
||||
spacing: 12;
|
||||
|
||||
Picture {
|
||||
paintable: bind template.item as <$Game>.cover;
|
||||
width-request: 200;
|
||||
height-request: 300;
|
||||
halign: center;
|
||||
|
||||
styles [
|
||||
"card",
|
||||
]
|
||||
}
|
||||
|
||||
Label {
|
||||
label: bind template.item as <$Game>.name;
|
||||
ellipsize: middle;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
styles [
|
||||
"view",
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ ignore = [
|
||||
"Q002",
|
||||
"Q003",
|
||||
"S310",
|
||||
"TC006",
|
||||
"TD",
|
||||
"TRY301",
|
||||
"W191",
|
||||
|
||||
Reference in New Issue
Block a user