collection-details: Support adding collections

This commit is contained in:
Jamie Gravendeel
2025-12-22 14:24:39 +01:00
parent 26a09c6782
commit 62004753b6
33 changed files with 263 additions and 5 deletions

View File

@@ -21,6 +21,11 @@ class Collection(GObject.Object):
icon_name = GObject.Property(type=str) icon_name = GObject.Property(type=str)
@GObject.Property(type=bool, default=True)
def in_model(self) -> bool:
"""Whether `self` has been added to the model."""
return self in model
def __init__(self, **kwargs: Any): def __init__(self, **kwargs: Any):
super().__init__(**kwargs) super().__init__(**kwargs)
@@ -54,6 +59,9 @@ def load():
model.splice(0, 0, tuple(_get_collections())) model.splice(0, 0, tuple(_get_collections()))
save() save()
for collection in model:
collection.notify("in-model")
def save(): def save():
"""Save collections to GSettings.""" """Save collections to GSettings."""

View File

@@ -0,0 +1,58 @@
using Gtk 4.0;
using Adw 1;
template $CollectionDetails: Adw.Dialog {
title: _("New Collection");
content-width: 360;
default-widget: apply_button;
focus-widget: name_entry;
child: Adw.ToolbarView {
[top]
Adw.HeaderBar {
show-start-title-buttons: false;
show-end-title-buttons: false;
[start]
Button {
action-name: "window.close";
icon-name: "cancel-symbolic";
tooltip-text: _("Cancel");
}
[end]
Button apply_button {
action-name: "details.apply";
icon-name: "apply-symbolic";
tooltip-text: _("Add");
styles [
"suggested-action",
]
}
}
content: Adw.PreferencesPage {
Adw.PreferencesGroup {
Adw.EntryRow name_entry {
title: _("Name");
activates-default: true;
}
}
Adw.PreferencesGroup {
FlowBox icons_box {
min-children-per-line: 7;
styles [
"navigation-sidebar",
]
}
styles [
"card",
]
}
};
};
}

View File

@@ -0,0 +1,90 @@
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: Copyright 2025 Jamie Gravendeel
from typing import Any, cast
from gi.repository import Adw, Gio, GObject, Gtk
from cartridges import collections
from cartridges.collections import Collection
from cartridges.config import PREFIX
ICONS = (
"collection",
"star",
"heart",
"music",
"people",
"skull",
"private",
"globe",
"map",
"city",
"car",
"horse",
"sprout",
"step-over",
"gamepad",
"ball",
"puzzle",
"flashlight",
"knife",
"gun",
"fist",
)
@Gtk.Template.from_resource(f"{PREFIX}/collection-details.ui")
class CollectionDetails(Adw.Dialog):
"""The details of a category."""
__gtype_name__ = __qualname__
name_entry: Adw.EntryRow = Gtk.Template.Child()
icons_box: Gtk.FlowBox = Gtk.Template.Child()
collection = GObject.Property(type=Collection)
def __init__(self, **kwargs: Any):
super().__init__(**kwargs)
self.insert_action_group("details", group := Gio.SimpleActionGroup())
group.add_action(apply := Gio.SimpleAction.new("apply"))
apply.connect("activate", lambda *_: self._apply())
self.name_entry.bind_property(
"text",
apply,
"enabled",
GObject.BindingFlags.SYNC_CREATE,
transform_to=lambda _, text: bool(text),
)
icons = Gtk.StringList.new(tuple(f"{icon}-symbolic" for icon in ICONS))
self.icons_box.bind_model(
icons,
lambda string: Gtk.FlowBoxChild(
name="collection-icon-child",
child=Gtk.Image.new_from_icon_name(string.props.string),
halign=Gtk.Align.CENTER,
),
)
self.icons_box.select_child(
cast(
Gtk.FlowBoxChild,
self.icons_box.get_child_at_index(ICONS.index(self.collection.icon)),
)
)
def _apply(self):
self.collection.name = self.name_entry.props.text
self.collection.icon = ICONS[
self.icons_box.get_selected_children()[0].get_index()
]
if not self.collection.in_model:
collections.model.append(self.collection)
self.collection.notify("in-model")
collections.save()
self.close()

View File

@@ -5,6 +5,7 @@ from typing import Any, override
from gi.repository import Adw, GObject, Gtk from gi.repository import Adw, GObject, Gtk
from cartridges import collections
from cartridges.collections import Collection from cartridges.collections import Collection
from cartridges.games import Game from cartridges.games import Game
@@ -51,3 +52,17 @@ class CollectionSidebarItem(Adw.SidebarItem): # pyright: ignore[reportAttribute
super().__init__(**kwargs) super().__init__(**kwargs)
self.bind_property("title", self, "tooltip", GObject.BindingFlags.SYNC_CREATE) self.bind_property("title", self, "tooltip", GObject.BindingFlags.SYNC_CREATE)
sorter = Gtk.StringSorter.new(Gtk.PropertyExpression.new(Collection, None, "name"))
model = Gtk.SortListModel.new(
Gtk.FilterListModel(
model=collections.model,
filter=Gtk.BoolFilter(
expression=Gtk.PropertyExpression.new(Collection, None, "removed"),
invert=True,
),
watch_items=True, # pyright: ignore[reportCallIssue]
),
sorter,
)

View File

@@ -1,6 +1,7 @@
python.install_sources( python.install_sources(
files( files(
'__init__.py', '__init__.py',
'collection_details.py',
'collections.py', 'collections.py',
'cover.py', 'cover.py',
'game_details.py', 'game_details.py',
@@ -13,6 +14,7 @@ python.install_sources(
blueprints = custom_target( blueprints = custom_target(
input: files( input: files(
'collection-details.blp',
'cover.blp', 'cover.blp',
'game-details.blp', 'game-details.blp',
'game-item.blp', 'game-item.blp',

View File

@@ -63,6 +63,10 @@
filter: saturate(300%) opacity(50%); filter: saturate(300%) opacity(50%);
} }
#collection-icon-child {
border-radius: 9999px;
}
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
#details list { #details list {
background: rgb(from white r g b / 10%); background: rgb(from white r g b / 10%);

View File

@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<gresources> <gresources>
<gresource prefix="@PREFIX@"> <gresource prefix="@PREFIX@">
<file>collection-details.ui</file>
<file>cover.ui</file> <file>cover.ui</file>
<file>game-details.ui</file> <file>game-details.ui</file>
<file>game-item.ui</file> <file>game-item.ui</file>

View File

@@ -78,6 +78,8 @@ template $Window: Adw.ApplicationWindow {
content: Adw.Sidebar sidebar { content: Adw.Sidebar sidebar {
activated => $_navigate(); activated => $_navigate();
setup-menu => $_setup_sidebar_menu();
notify::selected => $_update_selection();
Adw.SidebarSection { Adw.SidebarSection {
Adw.SidebarItem { Adw.SidebarItem {
@@ -89,6 +91,13 @@ template $Window: Adw.ApplicationWindow {
Adw.SidebarSection collections { Adw.SidebarSection collections {
title: _("Collections"); title: _("Collections");
} }
Adw.SidebarSection {
Adw.SidebarItem new_collection_item {
icon-name: "list-add-symbolic";
title: _("New Collection");
}
}
}; };
}; };
}; };

View File

@@ -10,11 +10,13 @@ from typing import Any, TypeVar, cast
from gi.repository import Adw, Gio, GLib, GObject, Gtk from gi.repository import Adw, Gio, GLib, GObject, Gtk
from cartridges import STATE_SETTINGS, collections, games from cartridges import STATE_SETTINGS, games
from cartridges.collections import Collection from cartridges.collections import Collection
from cartridges.config import PREFIX, PROFILE from cartridges.config import PREFIX, PROFILE
from cartridges.games import Game from cartridges.games import Game
from cartridges.ui import collections
from .collection_details import CollectionDetails
from .collections import ( from .collections import (
CollectionFilter, # noqa: F401 CollectionFilter, # noqa: F401
CollectionSidebarItem, CollectionSidebarItem,
@@ -47,6 +49,7 @@ class Window(Adw.ApplicationWindow):
split_view: Adw.OverlaySplitView = Gtk.Template.Child() split_view: Adw.OverlaySplitView = Gtk.Template.Child()
collections: Adw.SidebarSection = Gtk.Template.Child() # pyright: ignore[reportAttributeAccessIssue] collections: Adw.SidebarSection = Gtk.Template.Child() # pyright: ignore[reportAttributeAccessIssue]
new_collection_item: Adw.SidebarItem = Gtk.Template.Child() # pyright: ignore[reportAttributeAccessIssue]
navigation_view: Adw.NavigationView = Gtk.Template.Child() navigation_view: Adw.NavigationView = Gtk.Template.Child()
header_bar: Adw.HeaderBar = Gtk.Template.Child() header_bar: Adw.HeaderBar = Gtk.Template.Child()
title_box: Gtk.CenterBox = Gtk.Template.Child() title_box: Gtk.CenterBox = Gtk.Template.Child()
@@ -64,6 +67,8 @@ class Window(Adw.ApplicationWindow):
settings = GObject.Property(type=Gtk.Settings) settings = GObject.Property(type=Gtk.Settings)
_selected_sidebar_item = 0
@GObject.Property(type=Gio.ListStore) @GObject.Property(type=Gio.ListStore)
def games(self) -> Gio.ListStore: def games(self) -> Gio.ListStore:
"""Model of the user's games.""" """Model of the user's games."""
@@ -128,9 +133,24 @@ class Window(Adw.ApplicationWindow):
@Gtk.Template.Callback() @Gtk.Template.Callback()
def _navigate(self, sidebar: Adw.Sidebar, index: int): # pyright: ignore[reportAttributeAccessIssue] def _navigate(self, sidebar: Adw.Sidebar, index: int): # pyright: ignore[reportAttributeAccessIssue]
item = sidebar.get_item(index) item = sidebar.get_item(index)
self.collection = (
item.collection if isinstance(item, CollectionSidebarItem) else None match item:
) case self.new_collection_item:
self._add_collection()
sidebar.props.selected = self._selected_sidebar_item
case CollectionSidebarItem():
self.collection = item.collection
case _:
self.collection = None
if item is not self.new_collection_item:
self._selected_sidebar_item = index
@Gtk.Template.Callback()
def _update_selection(self, sidebar: Adw.Sidebar, *_args): # pyright: ignore[reportAttributeAccessIssue]
if sidebar.props.selected_item is self.new_collection_item:
sidebar.props.selected = self._selected_sidebar_item
self._selected_sidebar_item = sidebar.props.selected
@Gtk.Template.Callback() @Gtk.Template.Callback()
def _setup_gamepad_monitor(self, *_args): def _setup_gamepad_monitor(self, *_args):
@@ -186,6 +206,10 @@ class Window(Adw.ApplicationWindow):
self.details.edit() self.details.edit()
def _add_collection(self):
details = CollectionDetails(collection=Collection())
details.present(self)
def _undo(self, toast: Adw.Toast | None = None): def _undo(self, toast: Adw.Toast | None = None):
if toast: if toast:
self._history.pop(toast)() self._history.pop(toast)()

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill="#222" d="M13.754 4.668c.176-.2.262-.461.246-.723a1 1 0 0 0-.34-.687 1 1 0 0 0-.726-.246 1 1 0 0 0-.688.34L5.95 10.547 3.707 8.3A1 1 0 0 0 2 9.01a1 1 0 0 0 .293.708l3 3c.195.195.465.3.742.293.278-.012.535-.133.719-.344zm0 0"/></svg>

After

Width:  |  Height:  |  Size: 326 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill="#222" d="M8 0C3.594 0 0 3.594 0 8s3.594 8 8 8 8-3.594 8-8-3.594-8-8-8m.469 2.02a5.98 5.98 0 0 1 5.511 5.52q-3.109.234-4.718 1.94c-1.055 1.114-1.586 2.649-1.723 4.5A5.98 5.98 0 0 1 2.02 8.47c2.06-.125 3.626-.656 4.708-1.739 1.085-1.085 1.617-2.652 1.742-4.71m-1.004.007c-.121 1.864-.598 3.149-1.445 3.996-.844.844-2.13 1.32-3.997 1.446a5.98 5.98 0 0 1 5.442-5.442m6.508 6.516a5.98 5.98 0 0 1-5.434 5.434c.137-1.653.61-2.922 1.45-3.809.855-.91 2.136-1.477 3.984-1.625m0 0"/></svg>

After

Width:  |  Height:  |  Size: 573 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill="#222" d="M3.02 2a1 1 0 0 0-.707 1.707L6.605 8l-4.292 4.293a1 1 0 1 0 1.414 1.414L8.02 9.414l4.293 4.293a1 1 0 1 0 1.414-1.414L9.434 8l4.293-4.293a1 1 0 1 0-1.415-1.414L8.02 6.586 3.727 2.293A1 1 0 0 0 3.02 2m0 0"/></svg>

After

Width:  |  Height:  |  Size: 315 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:gpa="https://www.gtk.org/grappa" gpa:keywords="car vehicle ice combustion engine internal" gpa:state="0" gpa:version="1" width="16" height="16"><path gpa:fill="none" gpa:stroke="foreground" gpa:stroke-width="0.25 1 1.5" fill="none" stroke="url(&quot;#gpa:foreground&quot;) rgb(0,0,0)" stroke-dashoffset="3.2" stroke-linecap="round" stroke-linejoin="round" d="M6 13.496h4" class="transparent-fill foreground-stroke"/><path gpa:fill="none" gpa:stroke="foreground" gpa:stroke-width="0.5 2 3" fill="none" stroke="url(&quot;#gpa:foreground&quot;) rgb(0,0,0)" stroke-dashoffset="3.2" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 13.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0m7 0a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0M1 9h11.486A2.514 2.514 0 0 1 15 11.514 2.256 2.256 0 0 1 13 14M3 14a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2h5c1.226 0 2.346.693 2.894 1.789L12 9" class="transparent-fill foreground-stroke"/></svg>

After

Width:  |  Height:  |  Size: 961 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill="#222" d="M6 0v4H5v2H4v9H3V6H0v10h16v-1h-1v-4h-1V3l-3 3v5h-1v4H9V6H8V4H7V0zm6.5 6a.499.499 0 1 1 0 1 .499.499 0 1 1 0-1M1 7h1v1H1zm4 0h3v1H5zm7.5 1a.499.499 0 1 1 0 1 .499.499 0 1 1 0-1M1 9h1v1H1zm4 0h3v1H5zm7.5 1.008a.499.499 0 1 1-.5.5c0-.278.223-.5.5-.5M1 11h1v1H1zm4 0h3v1H5zm6 1h3v1h-3zM1 13h1v1H1zm4 0h3v1H5zm0 0"/></svg>

After

Width:  |  Height:  |  Size: 421 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill="#222" d="M1.977 7c-.551 0-1 .45-1 1v1.617c0 1.098.32 2.168.921 3.086l.114.172A4.72 4.72 0 0 0 5.949 15H12c1.645 0 3-1.355 3-3V9.914c-.004-.008 0-.008 0-.016 0-.023-.012-.043-.012-.066v-.016c0-.023-.011-.043-.015-.066-.012-.027-.016-.055-.024-.082l-.031-.074s0-.012-.008-.016q-.019-.029-.031-.062s0-.008-.012-.012q-.016-.03-.039-.059-.023-.036-.047-.066-.02-.026-.043-.05c0-.009-.011-.009-.015-.017l-.008-.007q-.026-.029-.05-.051l-.013-.008a.3.3 0 0 0-.054-.043s-.008-.012-.012-.012l-.059-.039-.011-.011-.063-.032-.074-.035c-.012 0-.012-.008-.016-.008q-.03-.017-.066-.027h-.012a.4.4 0 0 0-.066-.016c-.024-.011-.047-.011-.067-.015h-.047c-.023 0-.046-.008-.066-.008H8.703a2 2 0 0 1-1.73.996h-2v1c-.551 0-1-.45-1-1v-1h3a1 1 0 0 0 .304-.047c.028-.008.051-.02.078-.027.29-.121.508-.371.586-.676.012-.027.012-.055.02-.082q.012-.082.012-.168a1 1 0 0 0-1-.996zM8 2c-.555 0-1 .445-1 1v3h2V3a1 1 0 0 0-1-1m2.973-.004a1 1 0 0 0-1 1V7a1 1 0 1 0 2 0V2.996c0-.55-.45-1-1-1m3 1.5a1 1 0 0 0-1 1V7a1 1 0 1 0 2 0V4.496c0-.55-.45-1-1-1m-9-.496c-.551 0-1 .45-1 1v2h2V4a1 1 0 0 0-1-1m0 0"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill="#222" d="M4.945 0C4 0 4 1 4 1h8s0-1-1-1zM4 2a4 4 0 0 0 2 3.465V15s-.023 1 2 1c1.922 0 2-1 2-1l.004-9.54A4 4 0 0 0 12 2zm4 4.5c.555 0 1 .445 1 1v1c0 .555-.445 1-1 1s-1-.445-1-1v-1c0-.555.445-1 1-1m0 0"/></svg>

After

Width:  |  Height:  |  Size: 303 B

View File

@@ -0,0 +1 @@
<svg xmlns:gpa="https://www.gtk.org/grappa" gpa:keywords="input-gaming applications-games controller gamepad" gpa:state="0" gpa:version="1" width="16" height="16"><path fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M1 5.51V11a3 3 0 0 0 3 3c.552 0 1-.336 1-1a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2c0 .717.53 1 1 1a3 3 0 0 0 3-3V5.51A4.51 4.51 0 0 0 10.49 1H5.51A4.51 4.51 0 0 0 1 5.51M12.025 6h.024M10 4h.025M4 6h4M6 4v4" class="foreground-stroke transparent-fill"/></svg>

After

Width:  |  Height:  |  Size: 509 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill="#222" d="M7.52-.004c-4.13 0-7.5 3.371-7.5 7.5s3.37 7.5 7.5 7.5c4.128 0 7.5-3.371 7.5-7.5s-3.372-7.5-7.5-7.5m0 2c.253 0 .503.024.75.055.19.261.382.594.55 1.027.106.277.203.586.29.918H5.93q.13-.5.289-.918c.168-.433.36-.765.547-1.027.25-.031.496-.055.754-.055m-2.09.406c-.047.11-.102.203-.145.317-.148.386-.27.82-.379 1.277h-1.62A5.5 5.5 0 0 1 5.43 2.402m4.175 0a5.5 5.5 0 0 1 2.145 1.594h-1.617a10 10 0 0 0-.38-1.277c-.042-.114-.097-.207-.148-.317M2.621 4.996h2.086c-.098.629-.148 1.3-.168 2H2.055a5.6 5.6 0 0 1 .566-2m3.098 0h3.597c.106.617.16 1.293.184 2H5.54c.022-.707.077-1.383.179-2m4.613 0h2.082c.313.61.504 1.285.566 2H10.5c-.02-.7-.07-1.371-.168-2m-8.277 3h2.484c.02.7.07 1.375.168 2H2.621a5.6 5.6 0 0 1-.566-2m3.484 0H9.5a15 15 0 0 1-.184 2H5.72a16 16 0 0 1-.18-2m4.961 0h2.48a5.4 5.4 0 0 1-.566 2h-2.082c.098-.625.148-1.3.168-2m-7.215 3h1.621c.11.457.23.89.38 1.274.042.117.097.21.144.32a5.5 5.5 0 0 1-2.145-1.594m2.645 0h3.18q-.13.5-.29.918a4.4 4.4 0 0 1-.55 1.027 6 6 0 0 1-.75.055c-.254 0-.504-.023-.75-.055a4.4 4.4 0 0 1-.551-1.027 9 9 0 0 1-.29-.918m4.203 0h1.617a5.5 5.5 0 0 1-2.145 1.594c.051-.11.106-.203.149-.32.148-.383.27-.817.379-1.274m0 0"/></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill="#222" d="M5 2.988V4.98a1 1 0 0 0-1-.992H1v1h2c.55 0 1 .45 1 1v.395a5.27 5.27 0 0 0-2.543 2.18l-.75 1.25A4.9 4.9 0 0 0 0 12.359v.63c0 .55.45 1 1 1h3c.55 0 1-.45 1-1v-3c0-.552.45-1 1-1 .195.98.96 1.792 2 2v-2h3v-3h5v-3h-1l-1 1h-3v-1zm2 1h3v1H7zm0 2h3v1H7zm0 0"/></svg>

After

Width:  |  Height:  |  Size: 361 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:gpa="https://www.gtk.org/grappa" gpa:keywords="heart emote-love" gpa:state="0" gpa:version="1" width="16" height="16"><path gpa:fill="none" gpa:states="0" gpa:stroke="foreground" gpa:stroke-width="0.5 2 3" fill="none" stroke="url(&quot;#gpa:foreground&quot;) rgb(0,0,0)" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 5.757A3.763 3.763 0 0 0 11.23 2C9.86 2 8.66 2.73 8 3.822A3.77 3.77 0 0 0 4.77 2 3.763 3.763 0 0 0 1 5.757c0 1.038.43 2.03 1.19 2.738h-.001l5.725 5.496 5.898-5.496h-.002c.76-.708 1.19-1.7 1.19-2.738" class="transparent-fill foreground-stroke"/></svg>

After

Width:  |  Height:  |  Size: 637 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><g fill="#222"><path d="M4.523 5.79C3.95 8.43 5.32 11 9 11l-.45-.105 4 2c.434.214.962.093 1.25-.293l1.5-2c.235-.317.266-.743.075-1.086l-5-9a1 1 0 0 0-1.43-.348l-1.5 1L8.008 1 7.156.992a5.724 5.724 0 0 0-5.726 4.93L.164 14.859A1.006 1.006 0 0 0 1.156 16H8c.55 0 1-.45 1-1v-2c0-.55-.45-1-1-1s-1 .45-1 1v2l1-1H1.156l.989 1.14L3.41 6.204a3.72 3.72 0 0 1 3.73-3.21L7.993 3c.2 0 .395-.059.563-.168l1.5-1-1.43-.348 5 9 .074-1.086-1.5 2 1.246-.293-4-2A1 1 0 0 0 9 9c-1.285 0-1.898-.371-2.242-.828-.34-.457-.457-1.14-.281-1.961a.996.996 0 0 0-.766-1.188.996.996 0 0 0-1.188.766m0 0"/><path d="M10 6c0 .55-.45 1-1 1s-1-.45-1-1 .45-1 1-1 1 .45 1 1m0 0"/></g></svg>

After

Width:  |  Height:  |  Size: 736 B

View File

@@ -1,7 +1,30 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<gresources> <gresources>
<gresource prefix="@PREFIX@/icons/scalable/actions"> <gresource prefix="@PREFIX@/icons/scalable/actions">
<file>collection-symbolic.svg</file> <file>apply-symbolic.svg</file>
<file>cancel-symbolic.svg</file>
<file>filter-symbolic.svg</file> <file>filter-symbolic.svg</file>
<!-- Categories -->
<file>collection-symbolic.svg</file>
<file>ball-symbolic.svg</file>
<file>car-symbolic.svg</file>
<file>city-symbolic.svg</file>
<file>fist-symbolic.svg</file>
<file>flashlight-symbolic.svg</file>
<file>gamepad-symbolic.svg</file>
<file>globe-symbolic.svg</file>
<file>gun-symbolic.svg</file>
<file>heart-symbolic.svg</file>
<file>horse-symbolic.svg</file>
<file>knife-symbolic.svg</file>
<file>map-symbolic.svg</file>
<file>music-symbolic.svg</file>
<file>people-symbolic.svg</file>
<file>private-symbolic.svg</file>
<file>puzzle-symbolic.svg</file>
<file>skull-symbolic.svg</file>
<file>sprout-symbolic.svg</file>
<file>star-symbolic.svg</file>
<file>step-over-symbolic.svg</file>
</gresource> </gresource>
</gresources> </gresources>

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill="#222" d="M14.285.582a1.5 1.5 0 0 0-1.015.441L9.734 4.56l1.414 1.414 2.536-2.535a1.5 1.5 0 1 0 .601-2.856M9.027 5.266.543 13.754c.707.703 5.656 1.41 12.02-4.953zm0 0"/></svg>

After

Width:  |  Height:  |  Size: 268 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill="#222" d="M15 2v10l-5 3-5-3-5 3V5l5-3 5 3zM5 3v8l5 3V6zm0 0"/></svg>

After

Width:  |  Height:  |  Size: 162 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:gpa="https://www.gtk.org/grappa" gpa:keywords="folder-music note folder sound tune audio-x-generic" gpa:state="0" gpa:version="1" width="16" height="16"><path fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 11.485V4a2 2 0 0 0-2-2H8a2 2 0 0 0-2 2l.001 7.539M14 11.485a2.485 2.485 0 1 1-4.97 0 2.485 2.485 0 0 1 4.97 0m-7.999.054C6.001 12.91 4.86 14 3.487 14a2.485 2.485 0 0 1 0-4.97C4.859 9.03 6 10.166 6 11.539" class="foreground-stroke transparent-fill"/></svg>

After

Width:  |  Height:  |  Size: 557 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:gpa="https://www.gtk.org/grappa" gpa:keywords="people human person user account system-users" gpa:state="0" gpa:version="1" width="16" height="16"><path fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.282 8A3.04 3.04 0 0 0 1 10.499V12h2m2-5.557a2.722 2.722 0 1 1 2.175-4.358M6.203 11a3.04 3.04 0 0 0-1.282 2.499V15H15v-1.501c0-1.12-.588-2.096-1.459-2.613m-.82-3.164a2.722 2.722 0 1 1-5.443 0 2.722 2.722 0 0 1 5.444 0" class="foreground-stroke transparent-fill"/></svg>

After

Width:  |  Height:  |  Size: 563 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:gpa="https://www.gtk.org/grappa" gpa:keywords="privacy private window session browser hat glasses tracking" gpa:state="1" gpa:version="1" width="16" height="16"><path gpa:fill="none" gpa:stroke="foreground" gpa:stroke-width="0.5 2 3" fill="none" stroke="url(&quot;#gpa:foreground&quot;) rgb(0,0,0)" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m4 7 .66-3.297a2.123 2.123 0 0 1 4.033-.42L9 4a1.503 1.503 0 0 1 2.89.041L13 7M2 7h12" class="transparent-fill foreground-stroke"/><path gpa:fill="none" gpa:stroke="foreground" gpa:stroke-width="0.25 0.999998 1.5" fill="none" stroke="url(&quot;#gpa:foreground&quot;) rgb(0,0,0)" stroke-linejoin="round" d="M6.475 11.643c.18-.775.887-1.123 1.584-1.123.696 0 1.312.48 1.468 1.152m3.973-.162a1.99 1.99 0 1 1-3.98 0 1.99 1.99 0 0 1 3.98 0Zm-7.02 0a1.99 1.99 0 1 1-3.98 0 1.99 1.99 0 0 1 3.98 0Z" class="transparent-fill foreground-stroke"/></svg>

After

Width:  |  Height:  |  Size: 954 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill="#222" d="M6.5 1C5.668 1 5 1.668 5 2.5V4H2c-.555 0-1 .445-1 1v3h1.5C3.332 8 4 8.668 4 9.5S3.332 11 2.5 11H1v3c0 .555.445 1 1 1h3v-1.5c0-.832.668-1.5 1.5-1.5s1.5.668 1.5 1.5V15h3c.555 0 1-.445 1-1v-3h1.5c.832 0 1.5-.668 1.5-1.5S14.332 8 13.5 8H12V5c0-.555-.445-1-1-1H8V2.5C8 1.668 7.332 1 6.5 1m0 0"/></svg>

After

Width:  |  Height:  |  Size: 400 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><g fill="#222"><path d="M0 7c0 2.414 1.059 3.66 2.5 4.492l-.5-.867V13.5C2 14.883 3.117 16 4.5 16S7 14.883 7 13.5V13H5v.5C5 14.883 6.117 16 7.5 16s2.5-1.117 2.5-2.5V13H8v.5c0 1.383 1.117 2.5 2.5 2.5s2.5-1.117 2.5-2.496l.008-1.938-.559.895C15.391 11.016 16 9.328 16 7c0-3.957-3.656-7-8-7-4.348 0-8 3.043-8 7m14 0c0 .934-.105 1.547-.41 2.063-.3.515-.86 1.03-2.024 1.605q-.274.133-.554.254L11 13.5c0 .293-.207.5-.5.5s-.5-.207-.5-.5V13H8v.5c0 .293-.207.5-.5.5s-.5-.207-.5-.5V13H5v.5c0 .293-.207.5-.5.5s-.5-.207-.5-.5v-3.48a8 8 0 0 1-.5-.262c-.508-.293-.852-.586-1.094-.977S2 7.863 2 7c0-2.7 2.582-5 6-5s6 2.3 6 5m0 0"/><path fill-rule="evenodd" d="M6 7c0 .55-.45 1-1 1s-1-.45-1-1 .45-1 1-1 1 .45 1 1m6 0c0 .55-.45 1-1 1s-1-.45-1-1 .45-1 1-1 1 .45 1 1m0 0"/></g></svg>

After

Width:  |  Height:  |  Size: 845 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill="#222" d="M15 0c-3.512 0-6.312 1.434-6.89 4.668C6.925 2.84 4.671 2 2 2c-.55 0-1 .45-1 1 0 4.328 2.613 6.95 6 6.71V14H3c-.55 0-1 .45-1 1s.45 1 1 1h10c.55 0 1-.45 1-1s-.45-1-1-1H9V8c4.91 0 7-2.21 7-7 0-.55-.45-1-1-1m-1.043 2.055c-.113 1.375-.477 2.261-1.043 2.832-.57.582-1.476.96-2.914 1.078 0-.754.133-1.352.352-1.828.222-.485.53-.856.937-1.168.637-.477 1.547-.793 2.668-.914M3.067 4.059c1.109.12 2.007.441 2.64.921.406.317.715.692.938 1.176.19.422.316.93.347 1.551-1.039.11-1.89-.176-2.566-.77-.668-.59-1.184-1.542-1.36-2.878m0 0"/></svg>

After

Width:  |  Height:  |  Size: 633 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:gpa="https://www.gtk.org/grappa" gpa:keywords="starred" gpa:state="1" gpa:version="1" width="16" height="16"><path gpa:fill="foreground" gpa:states="1" d="M4.556 9.172 1.39 6.92a.864.864 0 0 1 .503-1.567l4.01.013 1.246-3.74a.896.896 0 0 1 1.702.005l1.201 3.688 4.056.015a.873.873 0 0 1 .501 1.585l-3.17 2.253 1.302 3.612a.912.912 0 0 1-1.355 1.072L8.04 11.672l-3.349 2.185a.929.929 0 0 1-1.385-1.084Z" class="foreground-fill"/></svg>

After

Width:  |  Height:  |  Size: 479 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill="#222" d="M7 2.926c-4.043 0-5.895 3.613-5.895 3.613l1.786.902S4.14 4.926 7 4.926c2.055 0 3.098 1.394 3.484 2.074h-.91C8.242 7 8 8.254 8 9.035l6-.047.043-6c-1.043 0-2.031.524-2.031 1.668v.93l-.063.062C11.191 4.558 9.633 2.926 7 2.926M2.383 8.988c-.688 0-1.266.582-1.266 1.266v3.469c0 .683.578 1.265 1.266 1.265h3.469c.683 0 1.265-.582 1.265-1.265v-3.47c0-.683-.582-1.265-1.265-1.265zm.734 2h2v2h-2zm0 0"/></svg>

After

Width:  |  Height:  |  Size: 504 B

View File

@@ -6,6 +6,8 @@ cartridges/sources/__init__.py
cartridges/sources/heroic.py cartridges/sources/heroic.py
cartridges/sources/imported.py cartridges/sources/imported.py
cartridges/sources/steam.py cartridges/sources/steam.py
cartridges/ui/collection-details.blp
cartridges/ui/collection_details.py
cartridges/ui/collections.py cartridges/ui/collections.py
cartridges/ui/cover.blp cartridges/ui/cover.blp
cartridges/ui/cover.py cartridges/ui/cover.py