Merge pull request #133 from kra-mo/libadwaita-1.4
Port to Libadwaita 1.4
@@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gresources>
|
||||
<gresource prefix="@PREFIX@">
|
||||
<file preprocess="xml-stripblanks">@APP_ID@.metainfo.xml</file>
|
||||
<file preprocess="xml-stripblanks">gtk/window.ui</file>
|
||||
<file preprocess="xml-stripblanks">gtk/help-overlay.ui</file>
|
||||
<file preprocess="xml-stripblanks">gtk/game.ui</file>
|
||||
@@ -11,4 +12,14 @@
|
||||
<file>library_placeholder.svg</file>
|
||||
<file>library_placeholder_small.svg</file>
|
||||
</gresource>
|
||||
<gresource prefix="@PREFIX@/icons/scalable/categories/">
|
||||
<file alias="bottles-source-symbolic.svg">icons/sources/bottles-source-symbolic.svg</file>
|
||||
<file alias="flatpak-source-symbolic.svg">icons/sources/flatpak-source-symbolic.svg</file>
|
||||
<file alias="heroic-source-symbolic.svg">icons/sources/heroic-source-symbolic.svg</file>
|
||||
<file alias="itch-source-symbolic.svg">icons/sources/itch-source-symbolic.svg</file>
|
||||
<file alias="legendary-source-symbolic.svg">icons/sources/legendary-source-symbolic.svg</file>
|
||||
<file alias="lutris-source-symbolic.svg">icons/sources/lutris-source-symbolic.svg</file>
|
||||
<file alias="retroarch-source-symbolic.svg">icons/sources/retroarch-source-symbolic.svg</file>
|
||||
<file alias="steam-source-symbolic.svg">icons/sources/steam-source-symbolic.svg</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
|
||||
@@ -2,159 +2,151 @@ using Gtk 4.0;
|
||||
using Adw 1;
|
||||
|
||||
template $DetailsWindow : Adw.Window {
|
||||
default-width: 480; // Same as Nautilus' properties window
|
||||
default-height: -1;
|
||||
modal: true;
|
||||
default-width: 480; // Same as Nautilus' properties window
|
||||
default-height: -1;
|
||||
modal: true;
|
||||
|
||||
ShortcutController {
|
||||
Shortcut {
|
||||
trigger: "Escape";
|
||||
action: "action(window.close)";
|
||||
}
|
||||
}
|
||||
|
||||
Box {
|
||||
orientation: vertical;
|
||||
|
||||
Adw.HeaderBar HeaderBar {
|
||||
show-start-title-buttons: false;
|
||||
show-end-title-buttons: false;
|
||||
|
||||
[start]
|
||||
Button cancel_button {
|
||||
label: _("Cancel");
|
||||
action-name: "window.close";
|
||||
}
|
||||
|
||||
[end]
|
||||
Button apply_button {
|
||||
styles [
|
||||
"suggested-action",
|
||||
]
|
||||
}
|
||||
ShortcutController {
|
||||
Shortcut {
|
||||
trigger: "Escape";
|
||||
action: "action(window.close)";
|
||||
}
|
||||
}
|
||||
|
||||
Adw.PreferencesPage {
|
||||
vexpand: true;
|
||||
Adw.ToolbarView {
|
||||
|
||||
Adw.PreferencesGroup cover_group {
|
||||
Adw.Clamp cover_clamp {
|
||||
maximum-size: 200;
|
||||
[top]
|
||||
Adw.HeaderBar HeaderBar {
|
||||
show-start-title-buttons: false;
|
||||
show-end-title-buttons: false;
|
||||
|
||||
Overlay {
|
||||
[overlay]
|
||||
Spinner spinner {
|
||||
margin-start: 72;
|
||||
margin-end: 72;
|
||||
[start]
|
||||
Button cancel_button {
|
||||
label: _("Cancel");
|
||||
action-name: "window.close";
|
||||
}
|
||||
|
||||
Overlay cover_overlay {
|
||||
halign: center;
|
||||
valign: center;
|
||||
|
||||
[overlay]
|
||||
Button cover_button_edit {
|
||||
icon-name: "document-edit-symbolic";
|
||||
tooltip-text: _("New Cover");
|
||||
halign: end;
|
||||
valign: end;
|
||||
margin-bottom: 6;
|
||||
margin-end: 6;
|
||||
|
||||
[end]
|
||||
Button apply_button {
|
||||
styles [
|
||||
"circular",
|
||||
"osd",
|
||||
"suggested-action"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[overlay]
|
||||
Revealer cover_button_delete_revealer {
|
||||
transition-type: crossfade;
|
||||
margin-end: 40;
|
||||
Adw.PreferencesPage {
|
||||
Adw.PreferencesGroup cover_group {
|
||||
Adw.Clamp cover_clamp {
|
||||
maximum-size: 200;
|
||||
Overlay {
|
||||
[overlay]
|
||||
Spinner spinner {
|
||||
margin-start: 72;
|
||||
margin-end: 72;
|
||||
}
|
||||
|
||||
Button cover_button_delete {
|
||||
icon-name: "user-trash-symbolic";
|
||||
tooltip-text: _("Delete Cover");
|
||||
halign: end;
|
||||
valign: end;
|
||||
margin-bottom: 6;
|
||||
margin-end: 6;
|
||||
Overlay cover_overlay {
|
||||
halign: center;
|
||||
valign: center;
|
||||
|
||||
styles [
|
||||
"circular",
|
||||
"osd",
|
||||
]
|
||||
[overlay]
|
||||
Button cover_button_edit {
|
||||
icon-name: "document-edit-symbolic";
|
||||
tooltip-text: _("New Cover");
|
||||
halign: end;
|
||||
valign: end;
|
||||
margin-bottom: 6;
|
||||
margin-end: 6;
|
||||
|
||||
styles [
|
||||
"circular", "osd"
|
||||
]
|
||||
}
|
||||
|
||||
[overlay]
|
||||
Revealer cover_button_delete_revealer {
|
||||
transition-type: crossfade;
|
||||
margin-end: 40;
|
||||
|
||||
Button cover_button_delete {
|
||||
icon-name: "user-trash-symbolic";
|
||||
tooltip-text: _("Delete Cover");
|
||||
halign: end;
|
||||
valign: end;
|
||||
margin-bottom: 6;
|
||||
margin-end: 6;
|
||||
|
||||
styles [
|
||||
"circular", "osd"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Picture cover {
|
||||
width-request: 200;
|
||||
height-request: 300;
|
||||
|
||||
styles [
|
||||
"card"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Picture cover {
|
||||
width-request: 200;
|
||||
height-request: 300;
|
||||
|
||||
styles [
|
||||
"card",
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Adw.PreferencesGroup {
|
||||
Adw.EntryRow name {
|
||||
title: _("Title");
|
||||
}
|
||||
|
||||
Adw.EntryRow developer {
|
||||
title: _("Developer (optional)");
|
||||
}
|
||||
}
|
||||
|
||||
Adw.PreferencesGroup {
|
||||
Adw.EntryRow executable {
|
||||
title: _("Executable");
|
||||
|
||||
[suffix]
|
||||
Button file_chooser_button {
|
||||
valign: center;
|
||||
icon-name: "document-open-symbolic";
|
||||
tooltip-text: _("Select File");
|
||||
|
||||
styles [
|
||||
"flat",
|
||||
]
|
||||
}
|
||||
|
||||
[suffix]
|
||||
MenuButton exec_info_button {
|
||||
valign: center;
|
||||
icon-name: "help-about-symbolic";
|
||||
tooltip-text: _("More Info");
|
||||
popover:
|
||||
Popover exec_info_popover {
|
||||
focusable: true;
|
||||
|
||||
Label exec_info_label {
|
||||
use-markup: true;
|
||||
wrap: true;
|
||||
max-width-chars: 50;
|
||||
halign: center;
|
||||
valign: center;
|
||||
margin-top: 6;
|
||||
margin-bottom: 6;
|
||||
margin-start: 6;
|
||||
margin-end: 6;
|
||||
}
|
||||
}
|
||||
|
||||
;
|
||||
Adw.PreferencesGroup {
|
||||
Adw.EntryRow name {
|
||||
title: _("Title");
|
||||
}
|
||||
Adw.EntryRow developer {
|
||||
title: _("Developer (optional)");
|
||||
}
|
||||
}
|
||||
Adw.PreferencesGroup {
|
||||
Adw.EntryRow executable {
|
||||
title: _("Executable");
|
||||
|
||||
styles [
|
||||
"flat",
|
||||
]
|
||||
}
|
||||
[suffix]
|
||||
Button file_chooser_button {
|
||||
valign: center;
|
||||
icon-name: "document-open-symbolic";
|
||||
tooltip-text: _("Select File");
|
||||
|
||||
styles [
|
||||
"flat",
|
||||
]
|
||||
}
|
||||
|
||||
[suffix]
|
||||
MenuButton exec_info_button {
|
||||
valign: center;
|
||||
icon-name: "help-about-symbolic";
|
||||
tooltip-text: _("More Info");
|
||||
|
||||
popover: Popover exec_info_popover {
|
||||
focusable: true;
|
||||
|
||||
Label exec_info_label {
|
||||
use-markup: true;
|
||||
wrap: true;
|
||||
max-width-chars: 50;
|
||||
halign: center;
|
||||
valign: center;
|
||||
margin-top: 6;
|
||||
margin-bottom: 6;
|
||||
margin-start: 6;
|
||||
margin-end: 6;
|
||||
}
|
||||
};
|
||||
|
||||
styles [
|
||||
"flat"
|
||||
]
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@ using Gtk 4.0;
|
||||
using Adw 1;
|
||||
|
||||
template $PreferencesWindow : Adw.PreferencesWindow {
|
||||
default-height: 500;
|
||||
|
||||
Adw.PreferencesPage general_page {
|
||||
name: "general";
|
||||
@@ -12,37 +11,22 @@ template $PreferencesWindow : Adw.PreferencesWindow {
|
||||
Adw.PreferencesGroup behavior_group {
|
||||
title: _("Behavior");
|
||||
|
||||
Adw.ActionRow {
|
||||
Adw.SwitchRow exit_after_launch_switch {
|
||||
title: _("Exit After Launching Games");
|
||||
activatable-widget: exit_after_launch_switch;
|
||||
|
||||
Switch exit_after_launch_switch {
|
||||
valign: center;
|
||||
}
|
||||
}
|
||||
|
||||
Adw.ActionRow {
|
||||
Adw.SwitchRow cover_launches_game_switch {
|
||||
title: _("Cover Image Launches Game");
|
||||
subtitle: _("Swaps the behavior of the cover image and the play button");
|
||||
activatable-widget: cover_launches_game_switch;
|
||||
|
||||
Switch cover_launches_game_switch {
|
||||
valign: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Adw.PreferencesGroup images_group {
|
||||
title: _("Images");
|
||||
|
||||
Adw.ActionRow {
|
||||
Adw.SwitchRow high_quality_images_switch {
|
||||
title: _("High Quality Images");
|
||||
subtitle: _("Save game covers losslessly at the cost of storage");
|
||||
activatable-widget: high_quality_images_switch;
|
||||
|
||||
Switch high_quality_images_switch {
|
||||
valign: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,13 +71,8 @@ template $PreferencesWindow : Adw.PreferencesWindow {
|
||||
Adw.PreferencesGroup import_behavior_group {
|
||||
title: _("Behavior");
|
||||
|
||||
Adw.ActionRow {
|
||||
Adw.SwitchRow remove_missing_switch {
|
||||
title: _("Remove Uninstalled Games");
|
||||
activatable-widget: remove_missing_switch;
|
||||
|
||||
Switch remove_missing_switch {
|
||||
valign: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,22 +124,12 @@ template $PreferencesWindow : Adw.PreferencesWindow {
|
||||
}
|
||||
}
|
||||
|
||||
Adw.ActionRow {
|
||||
Adw.SwitchRow lutris_import_steam_switch {
|
||||
title: _("Import Steam Games");
|
||||
activatable-widget: lutris_import_steam_switch;
|
||||
|
||||
Switch lutris_import_steam_switch {
|
||||
valign: center;
|
||||
}
|
||||
}
|
||||
|
||||
Adw.ActionRow {
|
||||
Adw.SwitchRow lutris_import_flatpak_switch {
|
||||
title: _("Import Flatpak Games");
|
||||
activatable-widget: lutris_import_flatpak_switch;
|
||||
|
||||
Switch lutris_import_flatpak_switch {
|
||||
valign: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,40 +149,20 @@ template $PreferencesWindow : Adw.PreferencesWindow {
|
||||
}
|
||||
}
|
||||
|
||||
Adw.ActionRow {
|
||||
Adw.SwitchRow heroic_import_epic_switch {
|
||||
title: _("Import Epic Games");
|
||||
activatable-widget: heroic_import_epic_switch;
|
||||
|
||||
Switch heroic_import_epic_switch {
|
||||
valign: center;
|
||||
}
|
||||
}
|
||||
|
||||
Adw.ActionRow {
|
||||
Adw.SwitchRow heroic_import_gog_switch {
|
||||
title: _("Import GOG Games");
|
||||
activatable-widget: heroic_import_gog_switch;
|
||||
|
||||
Switch heroic_import_gog_switch {
|
||||
valign: center;
|
||||
}
|
||||
}
|
||||
|
||||
Adw.ActionRow {
|
||||
Adw.SwitchRow heroic_import_amazon_switch {
|
||||
title: _("Import Amazon Games");
|
||||
activatable-widget: heroic_import_amazon_switch;
|
||||
|
||||
Switch heroic_import_amazon_switch {
|
||||
valign: center;
|
||||
}
|
||||
}
|
||||
|
||||
Adw.ActionRow {
|
||||
Adw.SwitchRow heroic_import_sideload_switch {
|
||||
title: _("Import Sideloaded Games");
|
||||
activatable-widget: heroic_import_sideload_switch;
|
||||
|
||||
Switch heroic_import_sideload_switch {
|
||||
valign: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -301,23 +250,13 @@ template $PreferencesWindow : Adw.PreferencesWindow {
|
||||
}
|
||||
}
|
||||
|
||||
Adw.ActionRow flatpak_import_launchers_row {
|
||||
Adw.SwitchRow flatpak_import_launchers_switch {
|
||||
title: _("Import Game Launchers");
|
||||
activatable-widget: flatpak_import_launchers_switch;
|
||||
|
||||
Switch flatpak_import_launchers_switch {
|
||||
valign: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Adw.ActionRow {
|
||||
Adw.SwitchRow desktop_switch {
|
||||
title: _("Desktop Entries");
|
||||
activatable-widget: desktop_switch;
|
||||
|
||||
Switch desktop_switch {
|
||||
valign: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -338,32 +277,17 @@ template $PreferencesWindow : Adw.PreferencesWindow {
|
||||
Adw.PreferencesGroup sgdb_behavior_group {
|
||||
title: _("Behavior");
|
||||
|
||||
Adw.ActionRow sgdb_switch_row {
|
||||
Adw.SwitchRow sgdb_switch {
|
||||
title: _("Use SteamGridDB");
|
||||
subtitle: _("Download images when adding or importing games");
|
||||
activatable-widget: sgdb_switch;
|
||||
|
||||
Switch sgdb_switch {
|
||||
valign: center;
|
||||
}
|
||||
}
|
||||
|
||||
Adw.ActionRow {
|
||||
Adw.SwitchRow sgdb_prefer_switch {
|
||||
title: _("Prefer Over Official Images");
|
||||
activatable-widget: sgdb_prefer_switch;
|
||||
|
||||
Switch sgdb_prefer_switch {
|
||||
valign: center;
|
||||
}
|
||||
}
|
||||
|
||||
Adw.ActionRow {
|
||||
Adw.SwitchRow sgdb_animated_switch {
|
||||
title: _("Prefer Animated Images");
|
||||
activatable-widget: sgdb_animated_switch;
|
||||
|
||||
Switch sgdb_animated_switch {
|
||||
valign: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,339 +45,422 @@ Adw.StatusPage hidden_notice_empty {
|
||||
|
||||
template $CartridgesWindow : Adw.ApplicationWindow {
|
||||
title: _("Cartridges");
|
||||
width-request: 281;
|
||||
height-request: 100;
|
||||
|
||||
Adw.Breakpoint {
|
||||
condition ("max-width: 564px")
|
||||
setters {
|
||||
overlay_split_view.collapsed: true;
|
||||
details_view_box.orientation: vertical;
|
||||
details_view_box.margin-top: 12;
|
||||
details_view_box.margin-start: 12;
|
||||
details_view_box.margin-end: 12;
|
||||
details_view_details_box.margin-start: 0;
|
||||
details_view_details_box.margin-end: 0;
|
||||
details_view_title.margin-top: 30;
|
||||
details_view_title.halign: center;
|
||||
details_view_developer.halign: center;
|
||||
details_view_date_box.halign: center;
|
||||
details_view_toolbar.halign: center;
|
||||
details_view_toolbar.orientation: vertical;
|
||||
details_view_play_button.halign: center;
|
||||
details_view_toolbar_buttons.margin-start: 0;
|
||||
}
|
||||
}
|
||||
|
||||
Adw.ToastOverlay toast_overlay {
|
||||
Stack stack {
|
||||
visible-child: library_view;
|
||||
transition-type: over_left;
|
||||
Adw.NavigationView navigation_view {
|
||||
Adw.NavigationPage library_page {
|
||||
title: _("All Games");
|
||||
|
||||
Overlay details_view {
|
||||
name: "details_view";
|
||||
|
||||
[overlay]
|
||||
Box details_view_box {
|
||||
orientation: vertical;
|
||||
|
||||
Adw.HeaderBar {
|
||||
[start]
|
||||
Button back_button {
|
||||
tooltip-text: _("Back");
|
||||
action-name: "win.go_back";
|
||||
icon-name: "go-previous-symbolic";
|
||||
}
|
||||
|
||||
[title]
|
||||
Adw.WindowTitle details_view_header_bar_title {
|
||||
title: _("Game Details");
|
||||
}
|
||||
|
||||
styles [
|
||||
"flat",
|
||||
]
|
||||
}
|
||||
|
||||
Adw.Bin {
|
||||
hexpand: true;
|
||||
vexpand: true;
|
||||
|
||||
Box {
|
||||
halign: center;
|
||||
valign: center;
|
||||
margin-start: 24;
|
||||
margin-end: 24;
|
||||
margin-top: 24;
|
||||
margin-bottom: 24;
|
||||
|
||||
Adw.Clamp {
|
||||
maximum-size: 200;
|
||||
|
||||
Overlay {
|
||||
[overlay]
|
||||
Spinner details_view_spinner {
|
||||
margin-start: 72;
|
||||
margin-end: 72;
|
||||
Adw.OverlaySplitView overlay_split_view {
|
||||
[sidebar]
|
||||
Adw.NavigationPage {
|
||||
title: _("Cartridges");
|
||||
Adw.ToolbarView {
|
||||
[top]
|
||||
Adw.HeaderBar {
|
||||
[start]
|
||||
Button {
|
||||
icon-name: "sidebar-show-symbolic";
|
||||
action-name: "win.show_sidebar";
|
||||
tooltip-text: _("Toggle Sidebar");
|
||||
}
|
||||
}
|
||||
|
||||
Picture details_view_cover {
|
||||
halign: end;
|
||||
ListBox sidebar {
|
||||
Box all_games_row_box {
|
||||
margin-top: 12;
|
||||
margin-bottom: 12;
|
||||
margin-start: 6;
|
||||
margin-end: 6;
|
||||
spacing: 12;
|
||||
|
||||
Image {
|
||||
icon-name: "view-grid-symbolic";
|
||||
}
|
||||
Label {
|
||||
halign: start;
|
||||
label: _("All Games");
|
||||
}
|
||||
Label all_games_no_label {
|
||||
hexpand: true;
|
||||
halign: end;
|
||||
|
||||
styles ["dim-label"]
|
||||
}
|
||||
}
|
||||
Box added_row_box {
|
||||
margin-top: 12;
|
||||
margin-bottom: 12;
|
||||
margin-start: 6;
|
||||
spacing: 12;
|
||||
|
||||
Image {
|
||||
icon-name: "list-add-symbolic";
|
||||
}
|
||||
Label {
|
||||
halign: start;
|
||||
label: _("Added");
|
||||
margin-end: 6;
|
||||
}
|
||||
Label added_games_no_label {
|
||||
hexpand: true;
|
||||
halign: end;
|
||||
margin-end: 6;
|
||||
|
||||
styles ["dim-label"]
|
||||
}
|
||||
}
|
||||
ListBoxRow {
|
||||
selectable: false;
|
||||
activatable: false;
|
||||
Label {
|
||||
label: _("Imported");
|
||||
styles ["heading"]
|
||||
halign: start;
|
||||
}
|
||||
}
|
||||
styles ["navigation-sidebar"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Adw.ToolbarView library_view {
|
||||
|
||||
[top]
|
||||
Adw.HeaderBar header_bar {
|
||||
|
||||
[start]
|
||||
Revealer {
|
||||
transition-type: slide_right;
|
||||
reveal-child: bind overlay_split_view.show-sidebar inverted;
|
||||
Button show_sidebar_button {
|
||||
icon-name: "sidebar-show-symbolic";
|
||||
action-name: "win.show_sidebar";
|
||||
tooltip-text: _("Toggle Sidebar");
|
||||
}
|
||||
}
|
||||
|
||||
[start]
|
||||
MenuButton {
|
||||
tooltip-text: _("Add Game");
|
||||
icon-name: "list-add-symbolic";
|
||||
menu-model: add_games;
|
||||
}
|
||||
|
||||
[end]
|
||||
MenuButton primary_menu_button {
|
||||
tooltip-text: _("Main Menu");
|
||||
icon-name: "open-menu-symbolic";
|
||||
menu-model: primary_menu;
|
||||
}
|
||||
|
||||
[end]
|
||||
ToggleButton search_button {
|
||||
tooltip-text: _("Search");
|
||||
icon-name: "system-search-symbolic";
|
||||
action-name: "win.toggle_search";
|
||||
}
|
||||
}
|
||||
|
||||
[top]
|
||||
SearchBar search_bar {
|
||||
search-mode-enabled: bind search_button.active bidirectional;
|
||||
key-capture-widget: navigation_view;
|
||||
|
||||
Adw.Clamp {
|
||||
maximum-size: 500;
|
||||
tightening-threshold: 500;
|
||||
|
||||
SearchEntry search_entry {
|
||||
hexpand: true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Overlay library_overlay {
|
||||
ScrolledWindow scrolledwindow {
|
||||
FlowBox library {
|
||||
homogeneous: true;
|
||||
halign: center;
|
||||
valign: start;
|
||||
width-request: 200;
|
||||
height-request: 300;
|
||||
|
||||
styles [
|
||||
"card",
|
||||
]
|
||||
column-spacing: 12;
|
||||
row-spacing: 12;
|
||||
margin-top: 15;
|
||||
margin-bottom: 15;
|
||||
margin-start: 15;
|
||||
margin-end: 15;
|
||||
selection-mode: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Box {
|
||||
orientation: vertical;
|
||||
margin-start: 48;
|
||||
vexpand: true;
|
||||
Adw.NavigationPage hidden_library_page {
|
||||
title: _("Hidden Games");
|
||||
|
||||
Adw.ToolbarView hidden_library_view {
|
||||
[top]
|
||||
Adw.HeaderBar hidden_header_bar {
|
||||
[end]
|
||||
MenuButton hidden_primary_menu_button {
|
||||
tooltip-text: _("Main Menu");
|
||||
icon-name: "open-menu-symbolic";
|
||||
menu-model: primary_menu;
|
||||
}
|
||||
|
||||
[end]
|
||||
ToggleButton hidden_search_button {
|
||||
tooltip-text: _("Search");
|
||||
icon-name: "system-search-symbolic";
|
||||
action-name: "win.toggle_search";
|
||||
}
|
||||
}
|
||||
|
||||
[top]
|
||||
SearchBar hidden_search_bar {
|
||||
search-mode-enabled: bind hidden_search_button.active bidirectional;
|
||||
key-capture-widget: hidden_library_view;
|
||||
|
||||
Adw.Clamp {
|
||||
maximum-size: 500;
|
||||
tightening-threshold: 500;
|
||||
|
||||
SearchEntry hidden_search_entry {
|
||||
hexpand: true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Overlay hidden_library_overlay {
|
||||
ScrolledWindow hidden_scrolledwindow {
|
||||
FlowBox hidden_library {
|
||||
homogeneous: true;
|
||||
halign: center;
|
||||
valign: start;
|
||||
column-spacing: 12;
|
||||
row-spacing: 12;
|
||||
margin-top: 15;
|
||||
margin-bottom: 15;
|
||||
margin-start: 15;
|
||||
margin-end: 15;
|
||||
selection-mode: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
styles [
|
||||
"background",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Adw.NavigationPage details_page {
|
||||
title: _("Game Details");
|
||||
|
||||
Overlay details_view {
|
||||
name: "details_view";
|
||||
|
||||
[overlay]
|
||||
Adw.ToolbarView details_view_toolbar_view {
|
||||
|
||||
[top]
|
||||
Adw.HeaderBar {
|
||||
}
|
||||
|
||||
ScrolledWindow {
|
||||
Box details_view_box {
|
||||
halign: center;
|
||||
valign: center;
|
||||
margin-start: 24;
|
||||
margin-end: 24;
|
||||
margin-top: 24;
|
||||
margin-bottom: 24;
|
||||
|
||||
Adw.Clamp {
|
||||
maximum-size: 200;
|
||||
|
||||
Overlay {
|
||||
[overlay]
|
||||
Spinner details_view_spinner {
|
||||
margin-start: 72;
|
||||
margin-end: 72;
|
||||
}
|
||||
|
||||
Picture details_view_cover {
|
||||
halign: end;
|
||||
valign: start;
|
||||
width-request: 200;
|
||||
height-request: 300;
|
||||
|
||||
styles [
|
||||
"card",
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Box details_view_details_box {
|
||||
orientation: vertical;
|
||||
margin-start: 48;
|
||||
vexpand: true;
|
||||
valign: center;
|
||||
|
||||
Label details_view_title {
|
||||
label: _("Game Title");
|
||||
hexpand: true;
|
||||
halign: start;
|
||||
max-width-chars: 24;
|
||||
wrap: true;
|
||||
wrap-mode: word_char;
|
||||
natural-wrap-mode: word;
|
||||
|
||||
styles [
|
||||
"title-1",
|
||||
]
|
||||
}
|
||||
|
||||
Label details_view_developer {
|
||||
margin-top: 6;
|
||||
hexpand: true;
|
||||
halign: start;
|
||||
max-width-chars: 36;
|
||||
wrap: true;
|
||||
wrap-mode: word_char;
|
||||
natural-wrap-mode: word;
|
||||
|
||||
styles [
|
||||
"heading",
|
||||
]
|
||||
}
|
||||
|
||||
Box details_view_date_box {
|
||||
orientation: horizontal;
|
||||
margin-top: 15;
|
||||
hexpand: true;
|
||||
halign: start;
|
||||
|
||||
Label details_view_added {
|
||||
wrap: true;
|
||||
wrap-mode: word_char;
|
||||
natural-wrap-mode: word;
|
||||
justify: center;
|
||||
}
|
||||
|
||||
Label details_view_last_played {
|
||||
margin-start: 12;
|
||||
wrap: true;
|
||||
wrap-mode: word_char;
|
||||
natural-wrap-mode: word;
|
||||
justify: center;
|
||||
}
|
||||
}
|
||||
|
||||
Box details_view_toolbar {
|
||||
hexpand: true;
|
||||
vexpand: true;
|
||||
valign: center;
|
||||
|
||||
Button details_view_play_button {
|
||||
name: "details_view_play_button";
|
||||
action-name: "app.launch_game";
|
||||
label: _("Play");
|
||||
halign: start;
|
||||
margin-top: 24;
|
||||
|
||||
styles [
|
||||
"opaque",
|
||||
"pill",
|
||||
]
|
||||
}
|
||||
|
||||
Box details_view_toolbar_buttons {
|
||||
halign: start;
|
||||
valign: center;
|
||||
margin-top: 24;
|
||||
margin-start: 9;
|
||||
|
||||
Label details_view_title {
|
||||
label: _("Game Title");
|
||||
hexpand: true;
|
||||
halign: start;
|
||||
max-width-chars: 24;
|
||||
wrap: true;
|
||||
wrap-mode: word_char;
|
||||
natural-wrap-mode: word;
|
||||
Button {
|
||||
icon-name: "document-edit-symbolic";
|
||||
action-name: "app.edit_game";
|
||||
tooltip-text: _("Edit");
|
||||
|
||||
styles [
|
||||
"title-1",
|
||||
"raised",
|
||||
"circular",
|
||||
]
|
||||
}
|
||||
|
||||
Label details_view_developer {
|
||||
margin-top: 6;
|
||||
hexpand: true;
|
||||
halign: start;
|
||||
max-width-chars: 36;
|
||||
wrap: true;
|
||||
wrap-mode: word_char;
|
||||
natural-wrap-mode: word;
|
||||
Button details_view_hide_button {
|
||||
action-name: "app.hide_game";
|
||||
|
||||
styles [
|
||||
"heading",
|
||||
"raised",
|
||||
"circular",
|
||||
]
|
||||
}
|
||||
|
||||
Box {
|
||||
orientation: horizontal;
|
||||
margin-top: 15;
|
||||
hexpand: true;
|
||||
halign: start;
|
||||
Button {
|
||||
icon-name: "user-trash-symbolic";
|
||||
action-name: "app.remove_game";
|
||||
tooltip-text: _("Remove");
|
||||
|
||||
Label details_view_added {
|
||||
wrap: true;
|
||||
wrap-mode: word_char;
|
||||
natural-wrap-mode: word;
|
||||
}
|
||||
|
||||
Label details_view_last_played {
|
||||
margin-start: 12;
|
||||
wrap: true;
|
||||
wrap-mode: word_char;
|
||||
natural-wrap-mode: word;
|
||||
}
|
||||
styles [
|
||||
"raised",
|
||||
"circular",
|
||||
]
|
||||
}
|
||||
|
||||
Box {
|
||||
hexpand: true;
|
||||
vexpand: true;
|
||||
valign: center;
|
||||
MenuButton {
|
||||
icon-name: "system-search-symbolic";
|
||||
menu-model: search;
|
||||
tooltip-text: _("Search");
|
||||
|
||||
Button details_view_play_button {
|
||||
name: "details_view_play_button";
|
||||
action-name: "app.launch_game";
|
||||
label: _("Play");
|
||||
halign: start;
|
||||
margin-top: 24;
|
||||
|
||||
styles [
|
||||
"opaque",
|
||||
"pill",
|
||||
]
|
||||
}
|
||||
|
||||
Box {
|
||||
halign: start;
|
||||
valign: center;
|
||||
margin-top: 24;
|
||||
margin-start: 9;
|
||||
|
||||
Button {
|
||||
icon-name: "document-edit-symbolic";
|
||||
action-name: "app.edit_game";
|
||||
tooltip-text: _("Edit");
|
||||
|
||||
styles [
|
||||
"raised",
|
||||
"circular",
|
||||
]
|
||||
}
|
||||
|
||||
Button details_view_hide_button {
|
||||
action-name: "app.hide_game";
|
||||
|
||||
styles [
|
||||
"raised",
|
||||
"circular",
|
||||
]
|
||||
}
|
||||
|
||||
Button {
|
||||
icon-name: "user-trash-symbolic";
|
||||
action-name: "app.remove_game";
|
||||
tooltip-text: _("Remove");
|
||||
|
||||
styles [
|
||||
"raised",
|
||||
"circular",
|
||||
]
|
||||
}
|
||||
|
||||
MenuButton {
|
||||
icon-name: "system-search-symbolic";
|
||||
menu-model: search;
|
||||
tooltip-text: _("Search");
|
||||
|
||||
styles [
|
||||
"raised",
|
||||
"circular",
|
||||
]
|
||||
}
|
||||
|
||||
styles [
|
||||
"toolbar",
|
||||
]
|
||||
}
|
||||
styles [
|
||||
"raised",
|
||||
"circular",
|
||||
]
|
||||
}
|
||||
|
||||
styles [
|
||||
"toolbar",
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Picture details_view_blurred_cover {
|
||||
keep-aspect-ratio: false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Box library_view {
|
||||
orientation: vertical;
|
||||
|
||||
Adw.HeaderBar header_bar {
|
||||
[start]
|
||||
MenuButton {
|
||||
tooltip-text: _("Add Game");
|
||||
icon-name: "list-add-symbolic";
|
||||
menu-model: add_games;
|
||||
}
|
||||
|
||||
[end]
|
||||
MenuButton primary_menu_button {
|
||||
tooltip-text: _("Main Menu");
|
||||
icon-name: "open-menu-symbolic";
|
||||
menu-model: primary_menu;
|
||||
}
|
||||
|
||||
[end]
|
||||
ToggleButton search_button {
|
||||
tooltip-text: _("Search");
|
||||
icon-name: "system-search-symbolic";
|
||||
action-name: "win.toggle_search";
|
||||
}
|
||||
}
|
||||
|
||||
SearchBar search_bar {
|
||||
search-mode-enabled: bind-property search_button.active bidirectional;
|
||||
key-capture-widget: library_view;
|
||||
|
||||
Adw.Clamp {
|
||||
maximum-size: 500;
|
||||
tightening-threshold: 500;
|
||||
|
||||
SearchEntry search_entry {
|
||||
placeholder-text: _("Search games");
|
||||
hexpand: true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Adw.Bin library_bin {
|
||||
ScrolledWindow scrolledwindow {
|
||||
hexpand: true;
|
||||
vexpand: true;
|
||||
|
||||
FlowBox library {
|
||||
homogeneous: true;
|
||||
halign: center;
|
||||
valign: start;
|
||||
column-spacing: 12;
|
||||
row-spacing: 12;
|
||||
margin-top: 15;
|
||||
margin-bottom: 15;
|
||||
margin-start: 15;
|
||||
margin-end: 15;
|
||||
selection-mode: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Box hidden_library_view {
|
||||
orientation: vertical;
|
||||
|
||||
Adw.HeaderBar hidden_header_bar {
|
||||
[start]
|
||||
Button hidden_back_button {
|
||||
tooltip-text: _("Back");
|
||||
action-name: "win.go_back";
|
||||
icon-name: "go-previous-symbolic";
|
||||
}
|
||||
|
||||
[title]
|
||||
Adw.WindowTitle {
|
||||
title: _("Hidden Games");
|
||||
}
|
||||
|
||||
[end]
|
||||
MenuButton hidden_primary_menu_button {
|
||||
tooltip-text: _("Main Menu");
|
||||
icon-name: "open-menu-symbolic";
|
||||
menu-model: primary_menu;
|
||||
}
|
||||
|
||||
[end]
|
||||
ToggleButton hidden_search_button {
|
||||
tooltip-text: _("Search");
|
||||
icon-name: "system-search-symbolic";
|
||||
action-name: "win.toggle_search";
|
||||
}
|
||||
}
|
||||
|
||||
SearchBar hidden_search_bar {
|
||||
search-mode-enabled: bind-property hidden_search_button.active bidirectional;
|
||||
key-capture-widget: hidden_library_view;
|
||||
|
||||
Adw.Clamp {
|
||||
maximum-size: 500;
|
||||
tightening-threshold: 500;
|
||||
|
||||
SearchEntry hidden_search_entry {
|
||||
placeholder-text: _("Search hidden games");
|
||||
hexpand: true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Adw.Bin hidden_library_bin {
|
||||
ScrolledWindow hidden_scrolledwindow {
|
||||
hexpand: true;
|
||||
vexpand: true;
|
||||
|
||||
FlowBox hidden_library {
|
||||
homogeneous: true;
|
||||
halign: center;
|
||||
valign: start;
|
||||
column-spacing: 12;
|
||||
row-spacing: 12;
|
||||
margin-top: 15;
|
||||
margin-bottom: 15;
|
||||
margin-start: 15;
|
||||
margin-end: 15;
|
||||
selection-mode: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
styles [
|
||||
"background",
|
||||
]
|
||||
}
|
||||
Picture details_view_blurred_cover {
|
||||
keep-aspect-ratio: false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,10 +108,10 @@
|
||||
|
||||
<schema id="@APP_ID@.State" path="@PREFIX@/State/">
|
||||
<key name="width" type="i">
|
||||
<default>1110</default>
|
||||
<default>1170</default>
|
||||
</key>
|
||||
<key name="height" type="i">
|
||||
<default>820</default>
|
||||
<default>795</default>
|
||||
</key>
|
||||
<key name="is-maximized" type="b">
|
||||
<default>false</default>
|
||||
@@ -126,6 +126,9 @@
|
||||
</choices>
|
||||
<default>"a-z"</default>
|
||||
</key>
|
||||
<key name="show-sidebar" type="b">
|
||||
<default>false</default>
|
||||
</key>
|
||||
<key name="steam-limiter-tokens-history" type="s">
|
||||
<default>"[]"</default>
|
||||
</key>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
<control>touch</control>
|
||||
</supports>
|
||||
<recommends>
|
||||
<display_length compare="gt">545</display_length>
|
||||
<display_length compare="gt">280</display_length>
|
||||
</recommends>
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
|
||||
1
data/icons/sources/bottles-source-symbolic.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="16" height="16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M2.847 0v.616c0 .371-.17.786-.405 1.239C1.812 2.95 1.163 4.02 1.01 5.288L1 16h2l.01-10.712c.153-1.267.802-2.337 1.432-3.433.235-.453.405-.868.405-1.24V0h-2Zm4 0v.616c0 .371-.17.786-.404 1.239C5.812 2.95 5.163 4.02 5.01 5.288L5 16h2.001l.01-10.712c.153-1.267.801-2.337 1.432-3.433.235-.453.405-.868.405-1.24V0h-2Zm4.001 0v.616c-.315 1.678-1.632 3.165-1.837 4.672L9.001 16h5.693l-.008-10.7c-.32-1.815-1.385-3.08-1.838-4.684V0h-2Z" fill="#000"/></svg>
|
||||
|
After Width: | Height: | Size: 532 B |
1
data/icons/sources/flatpak-source-symbolic.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="16" height="16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M7.805.02a.971.971 0 0 0-.36.148l-6 4A.998.998 0 0 0 1 5v6a1 1 0 0 0 .445.833l6 4c.337.223.774.223 1.11 0l6-4a.998.998 0 0 0 .446-.832V5a.998.998 0 0 0-.445-.832l-6-4a.994.994 0 0 0-.75-.149Zm.196 2.179V9l5-3.332v4.797l-5 3.337V9L3 5.668v-.133L8 2.2Z" fill="#000"/></svg>
|
||||
|
After Width: | Height: | Size: 355 B |
1
data/icons/sources/heroic-source-symbolic.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="16" height="16" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="m7.872 16-3.817-3.083L2 2.79 7.872 0l5.871 2.789-2.055 10.128L7.872 16Zm0-4.257-.294-.293-.88-7.927 1.1-1.908 1.174 1.908-.807 7.927-.293.293Zm-.294.367-.147.367-1.761.294-.294-.66.294-.662 1.761.294.147.367Zm-.073.734-.22 1.541.587.294.587-.294-.22-1.541-.367-.22-.367.22Zm.807-.367-.147-.367.147-.367 1.761-.293.294.66-.294.66-1.761-.293Z" fill="#000"/></svg>
|
||||
|
After Width: | Height: | Size: 485 B |
1
data/icons/sources/itch-source-symbolic.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="16" height="16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1.965 1.992C1.43 2.08 1 2.58 1 3.115V15.18c0 .534.43.894.965.806l12.066-1.979c.534-.088.964-.588.964-1.122V.82c0-.535-.43-.894-.964-.807L1.964 1.992Zm3.41 3.33c.555-.091.95.204 1.09.722l3.068-.503c.14-.564.532-.988 1.087-1.08.882-.144 1.851.602 2.154 1.659l.723 2.523c.302 1.056-.172 2.04-1.054 2.184-.774.127-1.615-.432-2.014-1.286l-4.863.798c-.399.984-1.24 1.82-2.014 1.946-.882.145-1.356-.683-1.054-1.838l.723-2.76c.303-1.157 1.272-2.22 2.154-2.365ZM7.282 6.58v.986l-.791.13L7.997 9.36 9.505 7.2l-.743.122v-.985l-1.48.243Z" fill="#000"/></svg>
|
||||
|
After Width: | Height: | Size: 631 B |
1
data/icons/sources/legendary-source-symbolic.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="16" height="16" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M0 6.355V1a1 1 0 0 1 1-1h2.893a1 1 0 0 1 .708.293l.645.645a1 1 0 0 0 .707.293h4.094a1 1 0 0 0 .707-.293L11.4.293A1 1 0 0 1 12.107 0H15a1 1 0 0 1 1 1v5.355a1 1 0 0 1-.293.707l-.23.23a1 1 0 0 0 0 1.415l.23.23a1 1 0 0 1 .293.708V15a1 1 0 0 1-1 1h-2.893a1 1 0 0 1-.708-.293l-.645-.645a1 1 0 0 0-.707-.293H5.953a1 1 0 0 0-.707.293l-.645.645a1 1 0 0 1-.708.293H1a1 1 0 0 1-1-1V9.645a1 1 0 0 1 .293-.707l.23-.23a1 1 0 0 0 0-1.415l-.23-.23A1 1 0 0 1 0 6.354ZM8 5a1 1 0 0 0-2 0v5.5a1 1 0 0 0 1 1h3a1 1 0 1 0 0-2H8V5Z" fill="#000"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>
|
||||
|
After Width: | Height: | Size: 757 B |
1
data/icons/sources/lutris-source-symbolic.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="16" height="16" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M0 7.937C0 3.554 3.518 0 7.857 0c1.196 0 2.33.27 3.344.753.055-.118.181-.363.301-.371.158-.012.248.09.35.203l.001.002c.102.115.306.287.306.287s.929-.32 1.97.251c1.043.572 1.19.744 1.394 1.144.144.284.14.87.126 1.19a.248.248 0 0 0-.039-.004c-.17 0-.308.174-.308.387 0 .214.138.387.308.387a.256.256 0 0 0 .133-.039c.153.292.233.562.255.806-.05-.348-.544-.586-.544-.586s-.077.135-.243.215c-.025.012-.056.01-.091.006-.063-.007-.138-.014-.21.06-.239.484.345.888.617.877.265-.011.476-.276.475-.512.047.92-.74 1.461-1.495 1.374-.493-.058-.907-.249-1.383-.469a10.262 10.262 0 0 0-1.187-.483c-.951-.307-1.569-.47-2.322-.585-1.486-.227-2.557.12-3.061.424a5.84 5.84 0 0 0-.427.284c.772.15 1.236 1.329 1.25 1.65l.002.013v.007l.001.033c-.021.484-.247.845-.725.83a.823.823 0 0 1-.713-.426c-.014-.024-.028-.049-.044-.072a1.92 1.92 0 0 0-.965-.795c-.46.705-.715 1.548-.715 2.53 0 2.897 2.345 5.052 5.213 5.052.907 0 2.817-.309 4-1.28.226-.207.485-.438.725-.55-.862 2.161-3.479 3.488-6.299 3.403C3.534 15.996 0 12.321 0 7.937ZM13.415 4.02a.596.596 0 0 0 .593-.6.596.596 0 0 0-.593-.599.597.597 0 0 0-.594.6c0 .33.266.6.594.6Z" fill="#000"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
1
data/icons/sources/retroarch-source-symbolic.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="16" height="16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M4.56 4 5.6 5.28H3.52L3.04 7.2H1.76l.48-1.92H.96L0 9.12h2.56l-.32 1.28h2.24L2.8 12.32h1.88l1.56-1.92h3.52l1.56 1.92h1.88l-1.68-1.92h2.24l-.32-1.28H16l-.96-3.84h-1.28l.48 1.92h-1.28l-.48-1.92H10.4L11.44 4h-1.36L8.96 5.28H7.04L5.92 4H4.56Zm.16 2.56H6v1.28H4.72V6.56Zm5.283 0h1.28v1.28h-1.28V6.56Z" fill="#000"/></svg>
|
||||
|
After Width: | Height: | Size: 399 B |
1
data/icons/sources/steam-source-symbolic.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="16" height="16" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M9.352 5.1a1.509 1.509 0 1 0 2.51 1.675A1.509 1.509 0 0 0 9.352 5.1Zm2.923-.277a2.009 2.009 0 1 1-3.34 2.231 2.009 2.009 0 0 1 3.34-2.23ZM5.01 12.131l-.983-.407a1.7 1.7 0 0 0 3.108-.103 1.696 1.696 0 0 0-1.213-2.29 1.699 1.699 0 0 0-.966.07l1.015.421a1.249 1.249 0 0 1-.96 2.307v.002ZM2.546 2.121A7.996 7.996 0 0 1 7.966 0l.003.013a7.988 7.988 0 0 1 7.159 4.432 7.996 7.996 0 0 1-4.277 11.018 7.99 7.99 0 0 1-8.274-1.558A7.989 7.989 0 0 1 .279 10.18l3.064 1.267A2.264 2.264 0 0 0 7.823 11v-.107l2.718-1.938h.063A3.016 3.016 0 1 0 7.589 5.94v.031l-1.906 2.76h-.126c-.454 0-.898.138-1.273.395L0 7.354A7.995 7.995 0 0 1 2.546 2.12Z" fill="#000"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>
|
||||
|
After Width: | Height: | Size: 878 B |
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id" : "hu.kramo.Cartridges.Devel",
|
||||
"runtime" : "org.gnome.Platform",
|
||||
"runtime-version" : "44",
|
||||
"runtime-version" : "45",
|
||||
"sdk" : "org.gnome.Sdk",
|
||||
"command" : "cartridges",
|
||||
"finish-args" : [
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR kramo
|
||||
# This file is distributed under the same license as the Cartridges~ package.
|
||||
# This file is distributed under the same license as the Cartridges package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Cartridges~\n"
|
||||
"Project-Id-Version: Cartridges\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-08-30 10:28+0200\n"
|
||||
"POT-Creation-Date: 2023-08-30 10:43+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -19,7 +19,7 @@ msgstr ""
|
||||
|
||||
#: data/hu.kramo.Cartridges.desktop.in:3
|
||||
#: data/hu.kramo.Cartridges.metainfo.xml.in:6 data/gtk/window.blp:47
|
||||
#: src/main.py:176
|
||||
#: data/gtk/window.blp:80
|
||||
msgid "Cartridges"
|
||||
msgstr ""
|
||||
|
||||
@@ -53,14 +53,14 @@ msgstr ""
|
||||
msgid "Edit Game Details"
|
||||
msgstr ""
|
||||
|
||||
#: data/hu.kramo.Cartridges.metainfo.xml.in:38 data/gtk/window.blp:71
|
||||
#: data/hu.kramo.Cartridges.metainfo.xml.in:38 data/gtk/window.blp:286
|
||||
#: src/details_window.py:71
|
||||
msgid "Game Details"
|
||||
msgstr ""
|
||||
|
||||
#: data/hu.kramo.Cartridges.metainfo.xml.in:42 data/gtk/window.blp:430
|
||||
#: src/details_window.py:265 src/importer/importer.py:304
|
||||
#: src/importer/importer.py:355
|
||||
#: data/hu.kramo.Cartridges.metainfo.xml.in:42 data/gtk/window.blp:513
|
||||
#: src/details_window.py:271 src/importer/importer.py:308
|
||||
#: src/importer/importer.py:359
|
||||
msgid "Preferences"
|
||||
msgstr ""
|
||||
|
||||
@@ -68,52 +68,52 @@ msgstr ""
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/details-window.blp:58
|
||||
#: data/gtk/details-window.blp:55
|
||||
msgid "New Cover"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/details-window.blp:77
|
||||
#: data/gtk/details-window.blp:73
|
||||
msgid "Delete Cover"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/details-window.blp:105 data/gtk/game.blp:80
|
||||
#: data/gtk/details-window.blp:100 data/gtk/game.blp:80
|
||||
msgid "Title"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/details-window.blp:109
|
||||
#: data/gtk/details-window.blp:103
|
||||
msgid "Developer (optional)"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/details-window.blp:115
|
||||
#: data/gtk/details-window.blp:108
|
||||
msgid "Executable"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/details-window.blp:121
|
||||
#: data/gtk/details-window.blp:114
|
||||
msgid "Select File"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/details-window.blp:132
|
||||
#: data/gtk/details-window.blp:125
|
||||
msgid "More Info"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/game.blp:102 data/gtk/game.blp:121 data/gtk/window.blp:195
|
||||
#: data/gtk/game.blp:102 data/gtk/game.blp:121 data/gtk/window.blp:413
|
||||
msgid "Edit"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/game.blp:107 src/window.py:190
|
||||
#: data/gtk/game.blp:107 src/window.py:348
|
||||
msgid "Hide"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/game.blp:112 data/gtk/game.blp:131 data/gtk/preferences.blp:56
|
||||
#: data/gtk/window.blp:215
|
||||
#: data/gtk/game.blp:112 data/gtk/game.blp:131 data/gtk/preferences.blp:40
|
||||
#: data/gtk/window.blp:433
|
||||
msgid "Remove"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/game.blp:126 src/window.py:192
|
||||
#: data/gtk/game.blp:126 src/window.py:350
|
||||
msgid "Unhide"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/help-overlay.blp:11 data/gtk/preferences.blp:9
|
||||
#: data/gtk/help-overlay.blp:11 data/gtk/preferences.blp:8
|
||||
msgid "General"
|
||||
msgstr ""
|
||||
|
||||
@@ -121,8 +121,8 @@ msgstr ""
|
||||
msgid "Quit"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/help-overlay.blp:19 data/gtk/window.blp:226 data/gtk/window.blp:269
|
||||
#: data/gtk/window.blp:336
|
||||
#: data/gtk/help-overlay.blp:19 data/gtk/window.blp:182 data/gtk/window.blp:241
|
||||
#: data/gtk/window.blp:444
|
||||
msgid "Search"
|
||||
msgstr ""
|
||||
|
||||
@@ -134,8 +134,8 @@ msgstr ""
|
||||
msgid "Shortcuts"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/help-overlay.blp:34 src/game.py:105 src/preferences.py:124
|
||||
#: src/importer/importer.py:379
|
||||
#: data/gtk/help-overlay.blp:34 src/game.py:105 src/preferences.py:122
|
||||
#: src/importer/importer.py:383
|
||||
msgid "Undo"
|
||||
msgstr ""
|
||||
|
||||
@@ -163,155 +163,155 @@ msgstr ""
|
||||
msgid "Remove game"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:13 data/gtk/preferences.blp:88
|
||||
#: data/gtk/preferences.blp:339
|
||||
#: data/gtk/preferences.blp:12 data/gtk/preferences.blp:72
|
||||
#: data/gtk/preferences.blp:288
|
||||
msgid "Behavior"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:16
|
||||
#: data/gtk/preferences.blp:15
|
||||
msgid "Exit After Launching Games"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:25
|
||||
#: data/gtk/preferences.blp:19
|
||||
msgid "Cover Image Launches Game"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:26
|
||||
#: data/gtk/preferences.blp:20
|
||||
msgid "Swaps the behavior of the cover image and the play button"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:36 src/details_window.py:85
|
||||
#: data/gtk/preferences.blp:25 src/details_window.py:85
|
||||
msgid "Images"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:39
|
||||
#: data/gtk/preferences.blp:28
|
||||
msgid "High Quality Images"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:40
|
||||
#: data/gtk/preferences.blp:29
|
||||
msgid "Save game covers losslessly at the cost of storage"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:50
|
||||
#: data/gtk/preferences.blp:34
|
||||
msgid "Danger Zone"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:53
|
||||
#: data/gtk/preferences.blp:37
|
||||
msgid "Remove All Games"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:84 data/gtk/window.blp:27 data/gtk/window.blp:456
|
||||
#: data/gtk/preferences.blp:68 data/gtk/window.blp:27 data/gtk/window.blp:539
|
||||
msgid "Import"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:91
|
||||
#: data/gtk/preferences.blp:75
|
||||
msgid "Remove Uninstalled Games"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:101
|
||||
#: data/gtk/preferences.blp:80
|
||||
msgid "Sources"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:104 src/importer/sources/steam_source.py:114
|
||||
#: data/gtk/preferences.blp:83 src/importer/sources/steam_source.py:114
|
||||
msgid "Steam"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:108 data/gtk/preferences.blp:125
|
||||
#: data/gtk/preferences.blp:172 data/gtk/preferences.blp:225
|
||||
#: data/gtk/preferences.blp:242 data/gtk/preferences.blp:259
|
||||
#: data/gtk/preferences.blp:276 data/gtk/preferences.blp:293
|
||||
#: data/gtk/preferences.blp:87 data/gtk/preferences.blp:104
|
||||
#: data/gtk/preferences.blp:141 data/gtk/preferences.blp:174
|
||||
#: data/gtk/preferences.blp:191 data/gtk/preferences.blp:208
|
||||
#: data/gtk/preferences.blp:225 data/gtk/preferences.blp:242
|
||||
msgid "Install Location"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:121 src/importer/sources/lutris_source.py:92
|
||||
#: data/gtk/preferences.blp:100 src/importer/sources/lutris_source.py:92
|
||||
msgid "Lutris"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:137
|
||||
#: data/gtk/preferences.blp:116
|
||||
msgid "Cache Location"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:149
|
||||
#: data/gtk/preferences.blp:128
|
||||
msgid "Import Steam Games"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:158
|
||||
#: data/gtk/preferences.blp:132
|
||||
msgid "Import Flatpak Games"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:168 src/importer/sources/heroic_source.py:355
|
||||
#: data/gtk/preferences.blp:137 src/importer/sources/heroic_source.py:355
|
||||
msgid "Heroic"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:184
|
||||
#: data/gtk/preferences.blp:153
|
||||
msgid "Import Epic Games"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:193
|
||||
#: data/gtk/preferences.blp:157
|
||||
msgid "Import GOG Games"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:202
|
||||
#: data/gtk/preferences.blp:161
|
||||
msgid "Import Amazon Games"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:211
|
||||
#: data/gtk/preferences.blp:165
|
||||
msgid "Import Sideloaded Games"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:221 src/importer/sources/bottles_source.py:86
|
||||
#: data/gtk/preferences.blp:170 src/importer/sources/bottles_source.py:86
|
||||
msgid "Bottles"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:238 src/importer/sources/itch_source.py:81
|
||||
#: data/gtk/preferences.blp:187 src/importer/sources/itch_source.py:81
|
||||
msgid "itch"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:255 src/importer/sources/legendary_source.py:97
|
||||
#: data/gtk/preferences.blp:204 src/importer/sources/legendary_source.py:97
|
||||
msgid "Legendary"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:272 src/importer/sources/retroarch_source.py:142
|
||||
#: data/gtk/preferences.blp:221 src/importer/sources/retroarch_source.py:142
|
||||
msgid "RetroArch"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:289 src/importer/sources/flatpak_source.py:118
|
||||
#: data/gtk/preferences.blp:238 src/importer/sources/flatpak_source.py:118
|
||||
msgid "Flatpak"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:305
|
||||
#: data/gtk/preferences.blp:254
|
||||
msgid "Import Game Launchers"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:315 src/importer/sources/desktop_source.py:196
|
||||
#: data/gtk/preferences.blp:264 src/importer/sources/desktop_source.py:196
|
||||
msgid "Desktop Entries"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:327
|
||||
#: data/gtk/preferences.blp:276
|
||||
msgid "SteamGridDB"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:331
|
||||
#: data/gtk/preferences.blp:280
|
||||
msgid "Authentication"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:334
|
||||
#: data/gtk/preferences.blp:283
|
||||
msgid "API Key"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:342
|
||||
#: data/gtk/preferences.blp:291
|
||||
msgid "Use SteamGridDB"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:343
|
||||
#: data/gtk/preferences.blp:292
|
||||
msgid "Download images when adding or importing games"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:352
|
||||
#: data/gtk/preferences.blp:296
|
||||
msgid "Prefer Over Official Images"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/preferences.blp:361
|
||||
#: data/gtk/preferences.blp:300
|
||||
msgid "Prefer Animated Images"
|
||||
msgstr ""
|
||||
|
||||
@@ -339,90 +339,94 @@ msgstr ""
|
||||
msgid "Games you hide will appear here."
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/window.blp:64 data/gtk/window.blp:317
|
||||
msgid "Back"
|
||||
#: data/gtk/window.blp:75 data/gtk/window.blp:105 src/main.py:166
|
||||
msgid "All Games"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/window.blp:121
|
||||
msgid "Game Title"
|
||||
#: data/gtk/window.blp:88 data/gtk/window.blp:162
|
||||
msgid "Toggle Sidebar"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/window.blp:176
|
||||
msgid "Play"
|
||||
#: data/gtk/window.blp:125 src/main.py:168
|
||||
msgid "Added"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/window.blp:255 data/gtk/window.blp:449
|
||||
#: data/gtk/window.blp:140
|
||||
msgid "Imported"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/window.blp:168 data/gtk/window.blp:532
|
||||
msgid "Add Game"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/window.blp:262 data/gtk/window.blp:329
|
||||
#: data/gtk/window.blp:175 data/gtk/window.blp:234
|
||||
msgid "Main Menu"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/window.blp:284
|
||||
msgid "Search games"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/window.blp:324
|
||||
#: data/gtk/window.blp:227
|
||||
msgid "Hidden Games"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/window.blp:351
|
||||
msgid "Search hidden games"
|
||||
#: data/gtk/window.blp:337
|
||||
msgid "Game Title"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/window.blp:388
|
||||
#: data/gtk/window.blp:394
|
||||
msgid "Play"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/window.blp:471
|
||||
msgid "Sort"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/window.blp:391
|
||||
#: data/gtk/window.blp:474
|
||||
msgid "A-Z"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/window.blp:397
|
||||
#: data/gtk/window.blp:480
|
||||
msgid "Z-A"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/window.blp:403
|
||||
#: data/gtk/window.blp:486
|
||||
msgid "Newest"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/window.blp:409
|
||||
#: data/gtk/window.blp:492
|
||||
msgid "Oldest"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/window.blp:415
|
||||
#: data/gtk/window.blp:498
|
||||
msgid "Last Played"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/window.blp:422
|
||||
#: data/gtk/window.blp:505
|
||||
msgid "Show Hidden"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/window.blp:435
|
||||
#: data/gtk/window.blp:518
|
||||
msgid "Keyboard Shortcuts"
|
||||
msgstr ""
|
||||
|
||||
#: data/gtk/window.blp:440
|
||||
#: data/gtk/window.blp:523
|
||||
msgid "About Cartridges"
|
||||
msgstr ""
|
||||
|
||||
#. Translators: Replace this with your name for it to show up in the about window
|
||||
#: src/main.py:195
|
||||
#: src/main.py:207
|
||||
msgid "translator_credits"
|
||||
msgstr ""
|
||||
|
||||
#. The variable is the date when the game was added
|
||||
#: src/window.py:213
|
||||
#: src/window.py:371
|
||||
msgid "Added: {}"
|
||||
msgstr ""
|
||||
|
||||
#: src/window.py:216
|
||||
#: src/window.py:374
|
||||
msgid "Never"
|
||||
msgstr ""
|
||||
|
||||
#. The variable is the date when the game was last played
|
||||
#: src/window.py:220
|
||||
#: src/window.py:378
|
||||
msgid "Last played: {}"
|
||||
msgstr ""
|
||||
|
||||
@@ -479,15 +483,15 @@ msgstr ""
|
||||
msgid "Couldn't Add Game"
|
||||
msgstr ""
|
||||
|
||||
#: src/details_window.py:171 src/details_window.py:207
|
||||
#: src/details_window.py:171 src/details_window.py:213
|
||||
msgid "Game title cannot be empty."
|
||||
msgstr ""
|
||||
|
||||
#: src/details_window.py:177 src/details_window.py:215
|
||||
#: src/details_window.py:177 src/details_window.py:221
|
||||
msgid "Executable cannot be empty."
|
||||
msgstr ""
|
||||
|
||||
#: src/details_window.py:206 src/details_window.py:214
|
||||
#: src/details_window.py:212 src/details_window.py:220
|
||||
msgid "Couldn't Apply Preferences"
|
||||
msgstr ""
|
||||
|
||||
@@ -507,66 +511,66 @@ msgstr ""
|
||||
|
||||
#. The variable is the title of the game
|
||||
#. The variable is the number of games removed
|
||||
#: src/game.py:172 src/importer/importer.py:376
|
||||
#: src/game.py:169 src/importer/importer.py:380
|
||||
msgid "{} removed"
|
||||
msgstr ""
|
||||
|
||||
#: src/preferences.py:123
|
||||
#: src/preferences.py:121
|
||||
msgid "All games removed"
|
||||
msgstr ""
|
||||
|
||||
#: src/preferences.py:172
|
||||
#: src/preferences.py:169
|
||||
msgid ""
|
||||
"An API key is required to use SteamGridDB. You can generate one {}here{}."
|
||||
msgstr ""
|
||||
|
||||
#: src/preferences.py:293
|
||||
#: src/preferences.py:296
|
||||
msgid "Installation Not Found"
|
||||
msgstr ""
|
||||
|
||||
#: src/preferences.py:294
|
||||
#: src/preferences.py:297
|
||||
msgid "Select a valid directory."
|
||||
msgstr ""
|
||||
|
||||
#: src/preferences.py:330 src/importer/importer.py:302
|
||||
#: src/preferences.py:333 src/importer/importer.py:306
|
||||
msgid "Warning"
|
||||
msgstr ""
|
||||
|
||||
#: src/preferences.py:364
|
||||
#: src/preferences.py:367
|
||||
msgid "Invalid Directory"
|
||||
msgstr ""
|
||||
|
||||
#: src/preferences.py:370
|
||||
#: src/preferences.py:373
|
||||
msgid "Set Location"
|
||||
msgstr ""
|
||||
|
||||
#: src/utils/create_dialog.py:33 src/importer/importer.py:303
|
||||
#: src/utils/create_dialog.py:33 src/importer/importer.py:307
|
||||
msgid "Dismiss"
|
||||
msgstr ""
|
||||
|
||||
#: src/importer/importer.py:140
|
||||
#: src/importer/importer.py:142
|
||||
msgid "Importing Games…"
|
||||
msgstr ""
|
||||
|
||||
#: src/importer/importer.py:323
|
||||
#: src/importer/importer.py:327
|
||||
msgid "The following errors occured during import:"
|
||||
msgstr ""
|
||||
|
||||
#: src/importer/importer.py:352
|
||||
#: src/importer/importer.py:356
|
||||
msgid "No new games found"
|
||||
msgstr ""
|
||||
|
||||
#: src/importer/importer.py:364
|
||||
#: src/importer/importer.py:368
|
||||
msgid "1 game imported"
|
||||
msgstr ""
|
||||
|
||||
#. The variable is the number of games
|
||||
#: src/importer/importer.py:368
|
||||
#: src/importer/importer.py:372
|
||||
msgid "{} games imported"
|
||||
msgstr ""
|
||||
|
||||
#. A single game removed
|
||||
#: src/importer/importer.py:372
|
||||
#: src/importer/importer.py:376
|
||||
msgid "1 removed"
|
||||
msgstr ""
|
||||
|
||||
|
||||
@@ -199,6 +199,12 @@ class DetailsWindow(Adw.Window):
|
||||
}
|
||||
)
|
||||
|
||||
if shared.win.sidebar.get_selected_row().get_child() not in (
|
||||
shared.win.all_games_row_box,
|
||||
shared.win.added_row_box,
|
||||
):
|
||||
shared.win.sidebar.select_row(shared.win.added_row_box.get_parent())
|
||||
|
||||
else:
|
||||
if final_name == "":
|
||||
create_dialog(
|
||||
@@ -246,7 +252,7 @@ class DetailsWindow(Adw.Window):
|
||||
self.game_cover.pictures.remove(self.cover)
|
||||
|
||||
self.close()
|
||||
shared.win.show_details_view(self.game)
|
||||
shared.win.show_details_page(self.game)
|
||||
|
||||
def update_cover_callback(self, manager: SGDBManager) -> None:
|
||||
# Set the game as not loading
|
||||
|
||||
37
src/game.py
@@ -25,7 +25,7 @@ from pathlib import Path
|
||||
from time import time
|
||||
from typing import Any, Optional
|
||||
|
||||
from gi.repository import Adw, GLib, GObject, Gtk
|
||||
from gi.repository import Adw, GObject, Gtk
|
||||
|
||||
from src import shared
|
||||
from src.game_cover import GameCover
|
||||
@@ -66,8 +66,7 @@ class Game(Gtk.Box):
|
||||
def __init__(self, data: dict[str, Any], **kwargs: Any) -> None:
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.win = shared.win
|
||||
self.app = self.win.get_application()
|
||||
self.app = shared.win.get_application()
|
||||
self.version = shared.SPEC_VERSION
|
||||
|
||||
self.update_values(data)
|
||||
@@ -100,18 +99,19 @@ class Game(Gtk.Box):
|
||||
def create_toast(self, title: str, action: Optional[str] = None) -> None:
|
||||
toast = Adw.Toast.new(title.format(self.name))
|
||||
toast.set_priority(Adw.ToastPriority.HIGH)
|
||||
toast.set_use_markup(False)
|
||||
|
||||
if action:
|
||||
toast.set_button_label(_("Undo"))
|
||||
toast.connect("button-clicked", self.win.on_undo_action, self, action)
|
||||
toast.connect("button-clicked", shared.win.on_undo_action, self, action)
|
||||
|
||||
if (self, action) in self.win.toasts.keys():
|
||||
if (self, action) in shared.win.toasts.keys():
|
||||
# Dismiss the toast if there already is one
|
||||
self.win.toasts[(self, action)].dismiss()
|
||||
shared.win.toasts[(self, action)].dismiss()
|
||||
|
||||
self.win.toasts[(self, action)] = toast
|
||||
shared.win.toasts[(self, action)] = toast
|
||||
|
||||
self.win.toast_overlay.add_toast(toast)
|
||||
shared.win.toast_overlay.add_toast(toast)
|
||||
|
||||
def launch(self) -> None:
|
||||
self.last_played = int(time())
|
||||
@@ -144,17 +144,15 @@ class Game(Gtk.Box):
|
||||
self.hidden = not self.hidden
|
||||
self.save()
|
||||
|
||||
if self.win.stack.get_visible_child() == self.win.details_view:
|
||||
self.win.on_go_back_action()
|
||||
if shared.win.navigation_view.get_visible_page() == shared.win.details_page:
|
||||
shared.win.navigation_view.pop()
|
||||
|
||||
self.update()
|
||||
|
||||
if toast:
|
||||
self.create_toast(
|
||||
# The variable is the title of the game
|
||||
(_("{} hidden") if self.hidden else _("{} unhidden")).format(
|
||||
GLib.markup_escape_text(self.name)
|
||||
),
|
||||
(_("{} hidden") if self.hidden else _("{} unhidden")).format(self.name),
|
||||
"hide",
|
||||
)
|
||||
|
||||
@@ -164,14 +162,11 @@ class Game(Gtk.Box):
|
||||
self.save()
|
||||
self.update()
|
||||
|
||||
if self.win.stack.get_visible_child() == self.win.details_view:
|
||||
self.win.on_go_back_action()
|
||||
if shared.win.navigation_view.get_visible_page() == shared.win.details_page:
|
||||
shared.win.navigation_view.pop()
|
||||
|
||||
self.create_toast(
|
||||
# The variable is the title of the game
|
||||
_("{} removed").format(GLib.markup_escape_text(self.name)),
|
||||
"remove",
|
||||
)
|
||||
# The variable is the title of the game
|
||||
self.create_toast(_("{} removed").format(self.name), "remove")
|
||||
|
||||
def set_loading(self, state: int) -> None:
|
||||
self.loading += state
|
||||
@@ -202,7 +197,7 @@ class Game(Gtk.Box):
|
||||
if shared.schema.get_boolean("cover-launches-game") ^ button:
|
||||
self.launch()
|
||||
else:
|
||||
self.win.show_details_view(self)
|
||||
shared.win.show_details_page(self)
|
||||
|
||||
def set_play_icon(self) -> None:
|
||||
self.play_button.set_icon_name(
|
||||
|
||||
@@ -53,6 +53,8 @@ class Importer(ErrorProducer):
|
||||
removed_game_ids: set[str]
|
||||
imported_game_ids: set[str]
|
||||
|
||||
close_req_id: int
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
@@ -105,10 +107,13 @@ class Importer(ErrorProducer):
|
||||
def run(self) -> None:
|
||||
"""Use several Gio.Task to import games from added sources"""
|
||||
|
||||
shared.win.get_application().state = shared.AppState.IMPORT
|
||||
|
||||
if self.__class__.summary_toast:
|
||||
self.__class__.summary_toast.dismiss()
|
||||
|
||||
shared.win.get_application().lookup_action("import").set_enabled(False)
|
||||
shared.win.get_application().lookup_action("add_game").set_enabled(False)
|
||||
|
||||
self.create_dialog()
|
||||
|
||||
@@ -148,6 +153,11 @@ class Importer(ErrorProducer):
|
||||
transient_for=shared.win,
|
||||
deletable=False,
|
||||
)
|
||||
|
||||
self.close_req_id = self.import_dialog.connect(
|
||||
"close-request", lambda *_: shared.win.close()
|
||||
)
|
||||
|
||||
self.import_dialog.present()
|
||||
|
||||
def source_task_thread_func(self, data: tuple) -> None:
|
||||
@@ -268,10 +278,15 @@ class Importer(ErrorProducer):
|
||||
self.imported_game_ids = shared.store.new_game_ids
|
||||
shared.store.new_game_ids = set()
|
||||
shared.store.duplicate_game_ids = set()
|
||||
# Disconnect the close-request signal that closes the main window
|
||||
self.import_dialog.disconnect(self.close_req_id)
|
||||
self.import_dialog.close()
|
||||
self.__class__.summary_toast = self.create_summary_toast()
|
||||
self.create_error_dialog()
|
||||
shared.win.get_application().lookup_action("import").set_enabled(True)
|
||||
shared.win.get_application().lookup_action("add_game").set_enabled(True)
|
||||
shared.win.get_application().state = shared.AppState.DEFAULT
|
||||
shared.win.create_source_rows()
|
||||
|
||||
def create_error_dialog(self) -> None:
|
||||
"""Dialog containing all errors raised by importers"""
|
||||
|
||||
101
src/main.py
@@ -59,6 +59,7 @@ from src.window import CartridgesWindow
|
||||
|
||||
|
||||
class CartridgesApplication(Adw.Application):
|
||||
state = shared.AppState.DEFAULT
|
||||
win: CartridgesWindow
|
||||
|
||||
def __init__(self) -> None:
|
||||
@@ -80,25 +81,28 @@ class CartridgesApplication(Adw.Application):
|
||||
Gtk.Window.set_default_icon_name(shared.APP_ID)
|
||||
|
||||
# Create the main window
|
||||
self.win = self.props.active_window # pylint: disable=no-member
|
||||
if not self.win:
|
||||
shared.win = self.win = CartridgesWindow(application=self)
|
||||
win = self.props.active_window # pylint: disable=no-member
|
||||
if not win:
|
||||
shared.win = win = CartridgesWindow(application=self)
|
||||
|
||||
# Save window geometry
|
||||
shared.state_schema.bind(
|
||||
"width", self.win, "default-width", Gio.SettingsBindFlags.DEFAULT
|
||||
"width", shared.win, "default-width", Gio.SettingsBindFlags.DEFAULT
|
||||
)
|
||||
shared.state_schema.bind(
|
||||
"height", self.win, "default-height", Gio.SettingsBindFlags.DEFAULT
|
||||
"height", shared.win, "default-height", Gio.SettingsBindFlags.DEFAULT
|
||||
)
|
||||
shared.state_schema.bind(
|
||||
"is-maximized", self.win, "maximized", Gio.SettingsBindFlags.DEFAULT
|
||||
"is-maximized", shared.win, "maximized", Gio.SettingsBindFlags.DEFAULT
|
||||
)
|
||||
|
||||
# Load games from disk
|
||||
shared.store.add_manager(FileManager(), False)
|
||||
shared.store.add_manager(DisplayManager())
|
||||
self.state = shared.AppState.LOAD_FROM_DISK
|
||||
self.load_games_from_disk()
|
||||
self.state = shared.AppState.DEFAULT
|
||||
shared.win.create_source_rows()
|
||||
|
||||
# Add rest of the managers for game imports
|
||||
shared.store.add_manager(CoverManager())
|
||||
@@ -124,26 +128,28 @@ class CartridgesApplication(Adw.Application):
|
||||
("protondb_search",),
|
||||
("lutris_search",),
|
||||
("hltb_search",),
|
||||
("show_hidden", ("<primary>h",), self.win),
|
||||
("go_back", ("<alt>Left",), self.win),
|
||||
("go_to_parent", ("<alt>Up",), self.win),
|
||||
("go_home", ("<alt>Home",), self.win),
|
||||
("toggle_search", ("<primary>f",), self.win),
|
||||
("escape", ("Escape",), self.win),
|
||||
("undo", ("<primary>z",), self.win),
|
||||
("open_menu", ("F10",), self.win),
|
||||
("close", ("<primary>w",), self.win),
|
||||
("show_sidebar", ("F9",), shared.win),
|
||||
("show_hidden", ("<primary>h",), shared.win),
|
||||
("go_to_parent", ("<alt>Up",), shared.win),
|
||||
("go_home", ("<alt>Home",), shared.win),
|
||||
("toggle_search", ("<primary>f",), shared.win),
|
||||
("escape", ("Escape",), shared.win),
|
||||
("undo", ("<primary>z",), shared.win),
|
||||
("open_menu", ("F10",), shared.win),
|
||||
("close", ("<primary>w",), shared.win),
|
||||
}
|
||||
)
|
||||
|
||||
sort_action = Gio.SimpleAction.new_stateful(
|
||||
"sort_by", GLib.VariantType.new("s"), GLib.Variant("s", "a-z")
|
||||
)
|
||||
sort_action.connect("activate", self.win.on_sort_action)
|
||||
self.win.add_action(sort_action)
|
||||
self.win.on_sort_action(sort_action, shared.state_schema.get_value("sort-mode"))
|
||||
sort_action.connect("activate", shared.win.on_sort_action)
|
||||
shared.win.add_action(sort_action)
|
||||
shared.win.on_sort_action(
|
||||
sort_action, shared.state_schema.get_value("sort-mode")
|
||||
)
|
||||
|
||||
self.win.present()
|
||||
shared.win.present()
|
||||
|
||||
def load_games_from_disk(self) -> None:
|
||||
if shared.games_dir.is_dir():
|
||||
@@ -155,6 +161,15 @@ class CartridgesApplication(Adw.Application):
|
||||
game = Game(data)
|
||||
shared.store.add_game(game, {"skip_save": True})
|
||||
|
||||
def get_source_name(self, source_id: str) -> Any:
|
||||
if source_id == "all":
|
||||
name = _("All Games")
|
||||
elif source_id == "imported":
|
||||
name = _("Added")
|
||||
else:
|
||||
name = globals()[f'{source_id.split("_")[0].title()}Source'].name
|
||||
return name
|
||||
|
||||
def on_about_action(self, *_args: Any) -> None:
|
||||
# Get the debug info from the log files
|
||||
debug_str = ""
|
||||
@@ -171,13 +186,12 @@ class CartridgesApplication(Adw.Application):
|
||||
debug_str += log_file.read()
|
||||
log_file.close()
|
||||
|
||||
about = Adw.AboutWindow(
|
||||
transient_for=self.win,
|
||||
application_name=_("Cartridges"),
|
||||
application_icon=shared.APP_ID,
|
||||
developer_name="kramo",
|
||||
version=shared.VERSION,
|
||||
developers=[
|
||||
about = Adw.AboutWindow.new_from_appdata(
|
||||
shared.PREFIX + "/" + shared.APP_ID + ".metainfo.xml", shared.VERSION
|
||||
)
|
||||
about.set_transient_for(shared.win)
|
||||
about.set_developers(
|
||||
(
|
||||
"kramo https://kramo.hu",
|
||||
"Geoffrey Coulaud https://geoffrey-coulaud.fr",
|
||||
"Rilic https://rilic.red",
|
||||
@@ -185,16 +199,19 @@ class CartridgesApplication(Adw.Application):
|
||||
"Paweł Lidwin https://github.com/imLinguin",
|
||||
"Domenico https://github.com/Domefemia",
|
||||
"Rafael Mardojai CM https://mardojai.com",
|
||||
],
|
||||
designers=("kramo https://kramo.hu",),
|
||||
copyright="© 2022-2023 kramo",
|
||||
license_type=Gtk.License.GPL_3_0,
|
||||
issue_url="https://github.com/kra-mo/cartridges/issues/new",
|
||||
website="https://github.com/kra-mo/cartridges",
|
||||
# Translators: Replace this with your name for it to show up in the about window
|
||||
translator_credits=_("translator_credits"),
|
||||
debug_info=debug_str,
|
||||
debug_info_filename="cartridges.log",
|
||||
)
|
||||
)
|
||||
about.set_designers(("kramo https://kramo.hu",))
|
||||
about.set_copyright("© 2022-2023 kramo")
|
||||
# Translators: Replace this with your name for it to show up in the about window
|
||||
about.set_translator_credits = (_("translator_credits"),)
|
||||
about.set_debug_info(debug_str)
|
||||
about.set_debug_info_filename("cartridges.log")
|
||||
about.add_legal_section(
|
||||
"Steam Branding",
|
||||
"© 2023 Valve Corporation",
|
||||
Gtk.License.CUSTOM,
|
||||
"Steam and the Steam logo are trademarks and/or registered trademarks of Valve Corporation in the U.S. and/or other countries.", # pylint: disable=line-too-long
|
||||
)
|
||||
about.present()
|
||||
|
||||
@@ -215,13 +232,13 @@ class CartridgesApplication(Adw.Application):
|
||||
return win
|
||||
|
||||
def on_launch_game_action(self, *_args: Any) -> None:
|
||||
self.win.active_game.launch()
|
||||
shared.win.active_game.launch()
|
||||
|
||||
def on_hide_game_action(self, *_args: Any) -> None:
|
||||
self.win.active_game.toggle_hidden()
|
||||
shared.win.active_game.toggle_hidden()
|
||||
|
||||
def on_edit_game_action(self, *_args: Any) -> None:
|
||||
DetailsWindow(self.win.active_game)
|
||||
DetailsWindow(shared.win.active_game)
|
||||
|
||||
def on_add_game_action(self, *_args: Any) -> None:
|
||||
DetailsWindow()
|
||||
@@ -259,14 +276,14 @@ class CartridgesApplication(Adw.Application):
|
||||
shared.importer.run()
|
||||
|
||||
def on_remove_game_action(self, *_args: Any) -> None:
|
||||
self.win.active_game.remove_game()
|
||||
shared.win.active_game.remove_game()
|
||||
|
||||
def on_remove_game_details_view_action(self, *_args: Any) -> None:
|
||||
if self.win.stack.get_visible_child() == self.win.details_view:
|
||||
if shared.win.navigation_view.get_visible_page() == shared.win.details_page:
|
||||
self.on_remove_game_action()
|
||||
|
||||
def search(self, uri: str) -> None:
|
||||
Gio.AppInfo.launch_default_for_uri(f"{uri}{self.win.active_game.name}")
|
||||
Gio.AppInfo.launch_default_for_uri(f"{uri}{shared.win.active_game.name}")
|
||||
|
||||
def on_igdb_search_action(self, *_args: Any) -> None:
|
||||
self.search("https://www.igdb.com/search?type=1&q=")
|
||||
|
||||
@@ -102,7 +102,6 @@ class PreferencesWindow(Adw.PreferencesWindow):
|
||||
sgdb_key_group = Gtk.Template.Child()
|
||||
sgdb_key_entry_row = Gtk.Template.Child()
|
||||
sgdb_switch = Gtk.Template.Child()
|
||||
sgdb_switch_row = Gtk.Template.Child()
|
||||
sgdb_prefer_switch = Gtk.Template.Child()
|
||||
sgdb_animated_switch = Gtk.Template.Child()
|
||||
|
||||
@@ -116,9 +115,8 @@ class PreferencesWindow(Adw.PreferencesWindow):
|
||||
|
||||
def __init__(self, **kwargs: Any) -> None:
|
||||
super().__init__(**kwargs)
|
||||
self.win = shared.win
|
||||
self.file_chooser = Gtk.FileDialog()
|
||||
self.set_transient_for(self.win)
|
||||
self.set_transient_for(shared.win)
|
||||
|
||||
self.toast = Adw.Toast.new(_("All games removed"))
|
||||
self.toast.set_button_label(_("Undo"))
|
||||
@@ -140,7 +138,6 @@ class PreferencesWindow(Adw.PreferencesWindow):
|
||||
if shared.PROFILE == "development":
|
||||
self.reset_action_row.set_visible(True)
|
||||
self.reset_button.connect("clicked", self.reset_app)
|
||||
self.set_default_size(-1, 560)
|
||||
|
||||
# Sources settings
|
||||
for source_class in (
|
||||
@@ -175,15 +172,6 @@ class PreferencesWindow(Adw.PreferencesWindow):
|
||||
)
|
||||
)
|
||||
|
||||
def set_sgdb_sensitive(widget: Adw.EntryRow) -> None:
|
||||
if not widget.get_text():
|
||||
shared.schema.set_boolean("sgdb", False)
|
||||
|
||||
self.sgdb_switch_row.set_sensitive(widget.get_text())
|
||||
|
||||
self.sgdb_key_entry_row.connect("changed", set_sgdb_sensitive)
|
||||
set_sgdb_sensitive(self.sgdb_key_entry_row)
|
||||
|
||||
# Switches
|
||||
self.bind_switches(
|
||||
{
|
||||
@@ -205,6 +193,15 @@ class PreferencesWindow(Adw.PreferencesWindow):
|
||||
}
|
||||
)
|
||||
|
||||
def set_sgdb_sensitive(widget: Adw.EntryRow) -> None:
|
||||
if not widget.get_text():
|
||||
shared.schema.set_boolean("sgdb", False)
|
||||
|
||||
self.sgdb_switch.set_sensitive(widget.get_text())
|
||||
|
||||
self.sgdb_key_entry_row.connect("changed", set_sgdb_sensitive)
|
||||
set_sgdb_sensitive(self.sgdb_key_entry_row)
|
||||
|
||||
def get_switch(self, setting: str) -> Any:
|
||||
return getattr(self, f'{setting.replace("-", "_")}_switch')
|
||||
|
||||
@@ -220,9 +217,10 @@ class PreferencesWindow(Adw.PreferencesWindow):
|
||||
def choose_folder(
|
||||
self, _widget: Any, callback: Callable, callback_data: Optional[str] = None
|
||||
) -> None:
|
||||
self.file_chooser.select_folder(self.win, None, callback, callback_data)
|
||||
self.file_chooser.select_folder(shared.win, None, callback, callback_data)
|
||||
|
||||
def undo_remove_all(self, *_args: Any) -> None:
|
||||
shared.win.get_application().state = shared.AppState.UNDO_REMOVE_ALL_GAMES
|
||||
for game in self.removed_games:
|
||||
game.removed = False
|
||||
game.save()
|
||||
@@ -230,8 +228,12 @@ class PreferencesWindow(Adw.PreferencesWindow):
|
||||
|
||||
self.removed_games = set()
|
||||
self.toast.dismiss()
|
||||
shared.win.get_application().state = shared.AppState.DEFAULT
|
||||
shared.win.create_source_rows()
|
||||
|
||||
def remove_all_games(self, *_args: Any) -> None:
|
||||
shared.win.get_application().state = shared.AppState.REMOVE_ALL_GAMES
|
||||
shared.win.row_selected(None, shared.win.all_games_row_box.get_parent())
|
||||
for game in shared.store:
|
||||
if not game.removed:
|
||||
self.removed_games.add(game)
|
||||
@@ -239,10 +241,12 @@ class PreferencesWindow(Adw.PreferencesWindow):
|
||||
game.save()
|
||||
game.update()
|
||||
|
||||
if self.win.stack.get_visible_child() == self.win.details_view:
|
||||
self.win.on_go_back_action()
|
||||
if shared.win.navigation_view.get_visible_page() == shared.win.details_page:
|
||||
shared.win.navigation_view.pop()
|
||||
|
||||
self.add_toast(self.toast)
|
||||
shared.win.get_application().state = shared.AppState.DEFAULT
|
||||
shared.win.create_source_rows()
|
||||
|
||||
def reset_app(self, *_args: Any) -> None:
|
||||
rmtree(shared.data_dir / "cartridges", True)
|
||||
|
||||
@@ -18,10 +18,20 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import os
|
||||
from enum import IntEnum, auto
|
||||
from pathlib import Path
|
||||
|
||||
from gi.repository import Gdk, Gio, GLib
|
||||
|
||||
|
||||
class AppState(IntEnum):
|
||||
DEFAULT = auto()
|
||||
LOAD_FROM_DISK = auto()
|
||||
IMPORT = auto()
|
||||
REMOVE_ALL_GAMES = auto()
|
||||
UNDO_REMOVE_ALL_GAMES = auto()
|
||||
|
||||
|
||||
APP_ID = "@APP_ID@"
|
||||
VERSION = "@VERSION@"
|
||||
PREFIX = "@PREFIX@"
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from src import shared
|
||||
from src.game import Game
|
||||
from src.game_cover import GameCover
|
||||
from src.store.managers.manager import Manager
|
||||
@@ -46,27 +47,30 @@ class DisplayManager(Manager):
|
||||
"notify::visible", game.toggle_play, None
|
||||
)
|
||||
game.menu_button.get_popover().connect(
|
||||
"notify::visible", game.win.set_active_game, game
|
||||
"notify::visible", shared.win.set_active_game, game
|
||||
)
|
||||
|
||||
if game.game_id in game.win.game_covers:
|
||||
game.game_cover = game.win.game_covers[game.game_id]
|
||||
if game.game_id in shared.win.game_covers:
|
||||
game.game_cover = shared.win.game_covers[game.game_id]
|
||||
game.game_cover.add_picture(game.cover)
|
||||
else:
|
||||
game.game_cover = GameCover({game.cover}, game.get_cover_path())
|
||||
game.win.game_covers[game.game_id] = game.game_cover
|
||||
shared.win.game_covers[game.game_id] = game.game_cover
|
||||
|
||||
if (
|
||||
game.win.stack.get_visible_child() == game.win.details_view
|
||||
and game.win.active_game == game
|
||||
shared.win.navigation_view.get_visible_page() == shared.win.details_page
|
||||
and shared.win.active_game == game
|
||||
):
|
||||
game.win.show_details_view(game)
|
||||
shared.win.show_details_page(game)
|
||||
|
||||
if not game.removed and not game.blacklisted:
|
||||
if game.hidden:
|
||||
game.win.hidden_library.append(game)
|
||||
shared.win.hidden_library.append(game)
|
||||
else:
|
||||
game.win.library.append(game)
|
||||
shared.win.library.append(game)
|
||||
game.get_parent().set_focusable(False)
|
||||
|
||||
game.win.set_library_child()
|
||||
shared.win.set_library_child()
|
||||
|
||||
if shared.win.get_application().state == shared.AppState.DEFAULT:
|
||||
shared.win.create_source_rows()
|
||||
|
||||
@@ -48,7 +48,7 @@ class Store:
|
||||
"""Check if the game is present in the store with the `in` keyword"""
|
||||
if not isinstance(obj, Game):
|
||||
return False
|
||||
if not (source_mapping := self.source_games.get(obj.source)):
|
||||
if not (source_mapping := self.source_games.get(obj.base_source)):
|
||||
return False
|
||||
return obj.game_id in source_mapping
|
||||
|
||||
@@ -150,9 +150,9 @@ class Store:
|
||||
game.connect(signal, manager.run)
|
||||
|
||||
# Add the game to the store
|
||||
if not game.source in self.source_games:
|
||||
self.source_games[game.source] = {}
|
||||
self.source_games[game.source][game.game_id] = game
|
||||
if not game.base_source in self.source_games:
|
||||
self.source_games[game.base_source] = {}
|
||||
self.source_games[game.base_source][game.game_id] = game
|
||||
|
||||
# Run the pipeline for the game
|
||||
if not run_pipeline:
|
||||
|
||||
@@ -61,7 +61,6 @@ def convert_cover(
|
||||
tmp_path,
|
||||
save_all=True,
|
||||
append_images=frames[1:],
|
||||
disposal=2,
|
||||
)
|
||||
|
||||
else:
|
||||
|
||||
266
src/window.py
@@ -31,25 +31,33 @@ from src.utils.relative_date import relative_date
|
||||
class CartridgesWindow(Adw.ApplicationWindow):
|
||||
__gtype_name__ = "CartridgesWindow"
|
||||
|
||||
overlay_split_view = Gtk.Template.Child()
|
||||
navigation_view = Gtk.Template.Child()
|
||||
sidebar = Gtk.Template.Child()
|
||||
all_games_row_box = Gtk.Template.Child()
|
||||
all_games_no_label = Gtk.Template.Child()
|
||||
added_row_box = Gtk.Template.Child()
|
||||
added_games_no_label = Gtk.Template.Child()
|
||||
toast_overlay = Gtk.Template.Child()
|
||||
primary_menu_button = Gtk.Template.Child()
|
||||
stack = Gtk.Template.Child()
|
||||
show_sidebar_button = Gtk.Template.Child()
|
||||
details_view = Gtk.Template.Child()
|
||||
library_page = Gtk.Template.Child()
|
||||
library_view = Gtk.Template.Child()
|
||||
library = Gtk.Template.Child()
|
||||
scrolledwindow = Gtk.Template.Child()
|
||||
library_bin = Gtk.Template.Child()
|
||||
library_overlay = Gtk.Template.Child()
|
||||
notice_empty = Gtk.Template.Child()
|
||||
notice_no_results = Gtk.Template.Child()
|
||||
search_bar = Gtk.Template.Child()
|
||||
search_entry = Gtk.Template.Child()
|
||||
search_button = Gtk.Template.Child()
|
||||
|
||||
details_view_box = Gtk.Template.Child()
|
||||
details_page = Gtk.Template.Child()
|
||||
details_view_toolbar_view = Gtk.Template.Child()
|
||||
details_view_cover = Gtk.Template.Child()
|
||||
details_view_spinner = Gtk.Template.Child()
|
||||
details_view_title = Gtk.Template.Child()
|
||||
details_view_header_bar_title = Gtk.Template.Child()
|
||||
details_view_blurred_cover = Gtk.Template.Child()
|
||||
details_view_play_button = Gtk.Template.Child()
|
||||
details_view_developer = Gtk.Template.Child()
|
||||
@@ -57,11 +65,12 @@ class CartridgesWindow(Adw.ApplicationWindow):
|
||||
details_view_last_played = Gtk.Template.Child()
|
||||
details_view_hide_button = Gtk.Template.Child()
|
||||
|
||||
hidden_library_page = Gtk.Template.Child()
|
||||
hidden_primary_menu_button = Gtk.Template.Child()
|
||||
hidden_library = Gtk.Template.Child()
|
||||
hidden_library_view = Gtk.Template.Child()
|
||||
hidden_scrolledwindow = Gtk.Template.Child()
|
||||
hidden_library_bin = Gtk.Template.Child()
|
||||
hidden_library_overlay = Gtk.Template.Child()
|
||||
hidden_notice_empty = Gtk.Template.Child()
|
||||
hidden_notice_no_results = Gtk.Template.Child()
|
||||
hidden_search_bar = Gtk.Template.Child()
|
||||
@@ -73,14 +82,139 @@ class CartridgesWindow(Adw.ApplicationWindow):
|
||||
active_game: Game
|
||||
details_view_game_cover: Optional[GameCover] = None
|
||||
sort_state: str = "a-z"
|
||||
filter_state: str = "all"
|
||||
source_rows: dict = {}
|
||||
|
||||
def create_source_rows(self) -> None:
|
||||
def get_removed(source_id: str) -> Any:
|
||||
removed = tuple(
|
||||
game.removed or game.hidden or game.blacklisted
|
||||
for game in shared.store.source_games[source_id].values()
|
||||
)
|
||||
return (
|
||||
(count,) if (count := sum(removed)) != len(removed) else False
|
||||
) # Return a tuple because 0 == False and 1 == True
|
||||
|
||||
total_games_no = 0
|
||||
restored = False
|
||||
|
||||
selected_id = (
|
||||
self.source_rows[selected_row][0]
|
||||
if (selected_row := self.sidebar.get_selected_row()) in self.source_rows
|
||||
else None
|
||||
)
|
||||
|
||||
if selected_row == self.added_row_box.get_parent():
|
||||
self.sidebar.select_row(self.added_row_box.get_parent())
|
||||
restored = True
|
||||
|
||||
if added_missing := (
|
||||
not shared.store.source_games.get("imported")
|
||||
or not (removed := get_removed("imported"))
|
||||
):
|
||||
self.sidebar.select_row(self.all_games_row_box.get_parent())
|
||||
else:
|
||||
games_no = len(shared.store.source_games["imported"]) - removed[0]
|
||||
self.added_games_no_label.set_label(str(games_no))
|
||||
total_games_no += games_no
|
||||
self.added_row_box.get_parent().set_visible(not added_missing)
|
||||
|
||||
self.sidebar.get_row_at_index(2).set_visible(False)
|
||||
|
||||
while row := self.sidebar.get_row_at_index(3):
|
||||
self.sidebar.remove(row)
|
||||
|
||||
for source_id in shared.store.source_games:
|
||||
if source_id == "imported":
|
||||
continue
|
||||
if not (removed := get_removed(source_id)):
|
||||
continue
|
||||
|
||||
row = Gtk.Box(
|
||||
margin_top=12,
|
||||
margin_bottom=12,
|
||||
margin_start=6,
|
||||
margin_end=6,
|
||||
spacing=12,
|
||||
)
|
||||
games_no = len(shared.store.source_games[source_id]) - removed[0]
|
||||
total_games_no += games_no
|
||||
|
||||
row.append(
|
||||
Gtk.Image.new_from_icon_name(
|
||||
"user-desktop-symbolic"
|
||||
if (split_id := source_id.split("_")[0]) == "desktop"
|
||||
else f"{split_id}-source-symbolic"
|
||||
)
|
||||
)
|
||||
|
||||
row.append(
|
||||
Gtk.Label(
|
||||
label=self.get_application().get_source_name(source_id),
|
||||
halign=Gtk.Align.START,
|
||||
)
|
||||
)
|
||||
|
||||
row.append(
|
||||
games_no_label := Gtk.Label(
|
||||
label=games_no,
|
||||
hexpand=True,
|
||||
halign=Gtk.Align.END,
|
||||
)
|
||||
)
|
||||
|
||||
games_no_label.add_css_class("dim-label")
|
||||
|
||||
# Order rows based on the number of games in them
|
||||
index = 3
|
||||
while source_row := self.sidebar.get_row_at_index(index):
|
||||
if self.source_rows[source_row][1] < games_no:
|
||||
self.sidebar.insert(row, index)
|
||||
break
|
||||
index += 1
|
||||
if not row.get_parent():
|
||||
self.sidebar.append(row)
|
||||
|
||||
self.source_rows[row.get_parent()] = (
|
||||
source_id,
|
||||
games_no,
|
||||
)
|
||||
|
||||
if source_id == selected_id:
|
||||
self.sidebar.select_row(row.get_parent())
|
||||
restored = True
|
||||
|
||||
self.sidebar.get_row_at_index(2).set_visible(True)
|
||||
|
||||
self.all_games_no_label.set_label(str(total_games_no))
|
||||
|
||||
if not restored:
|
||||
self.sidebar.select_row(self.all_games_row_box.get_parent())
|
||||
|
||||
def row_selected(self, _widget: Any, row: Gtk.ListBoxRow | None) -> None:
|
||||
if not row:
|
||||
return
|
||||
match row.get_child():
|
||||
case self.all_games_row_box:
|
||||
value = "all"
|
||||
case self.added_row_box:
|
||||
value = "imported"
|
||||
case _:
|
||||
value = self.source_rows[row][0]
|
||||
|
||||
self.library_page.set_title(self.get_application().get_source_name(value))
|
||||
|
||||
self.filter_state = value
|
||||
self.library.invalidate_filter()
|
||||
|
||||
if self.overlay_split_view.get_collapsed():
|
||||
self.overlay_split_view.set_show_sidebar(False)
|
||||
|
||||
def __init__(self, **kwargs: Any) -> None:
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.previous_page = self.library_view
|
||||
|
||||
self.details_view.set_measure_overlay(self.details_view_box, True)
|
||||
self.details_view.set_clip_overlay(self.details_view_box, False)
|
||||
self.details_view.set_measure_overlay(self.details_view_toolbar_view, True)
|
||||
self.details_view.set_clip_overlay(self.details_view_toolbar_view, False)
|
||||
|
||||
self.library.set_filter_func(self.filter_func)
|
||||
self.hidden_library.set_filter_func(self.filter_func)
|
||||
@@ -92,6 +226,12 @@ class CartridgesWindow(Adw.ApplicationWindow):
|
||||
|
||||
self.notice_empty.set_icon_name(shared.APP_ID + "-symbolic")
|
||||
|
||||
self.overlay_split_view.set_show_sidebar(
|
||||
shared.state_schema.get_boolean("show-sidebar")
|
||||
)
|
||||
|
||||
self.sidebar.select_row(self.all_games_row_box.get_parent())
|
||||
|
||||
if shared.PROFILE == "development":
|
||||
self.add_css_class("devel")
|
||||
|
||||
@@ -103,12 +243,13 @@ class CartridgesWindow(Adw.ApplicationWindow):
|
||||
self.search_entry.connect("search-changed", self.search_changed, False)
|
||||
self.hidden_search_entry.connect("search-changed", self.search_changed, True)
|
||||
|
||||
self.search_entry.connect("activate", self.show_details_view_search)
|
||||
self.hidden_search_entry.connect("activate", self.show_details_view_search)
|
||||
self.search_entry.connect("activate", self.show_details_page_search)
|
||||
self.hidden_search_entry.connect("activate", self.show_details_page_search)
|
||||
|
||||
back_mouse_button = Gtk.GestureClick(button=8)
|
||||
(back_mouse_button).connect("pressed", self.on_go_back_action)
|
||||
self.add_controller(back_mouse_button)
|
||||
self.navigation_view.connect("popped", self.set_show_hidden)
|
||||
self.navigation_view.connect("pushed", self.set_show_hidden)
|
||||
|
||||
self.sidebar.connect("row-selected", self.row_selected)
|
||||
|
||||
style_manager = Adw.StyleManager.get_default()
|
||||
style_manager.connect("notify::dark", self.set_details_view_opacity)
|
||||
@@ -140,25 +281,38 @@ class CartridgesWindow(Adw.ApplicationWindow):
|
||||
if game.removed or game.blacklisted:
|
||||
continue
|
||||
if game.hidden:
|
||||
if game.filtered and hidden_child != self.hidden_scrolledwindow:
|
||||
if game.filtered and hidden_child:
|
||||
hidden_child = self.hidden_notice_no_results
|
||||
continue
|
||||
hidden_child = self.hidden_scrolledwindow
|
||||
hidden_child = None
|
||||
else:
|
||||
if game.filtered and child != self.scrolledwindow:
|
||||
if game.filtered and child:
|
||||
child = self.notice_no_results
|
||||
continue
|
||||
child = self.scrolledwindow
|
||||
child = None
|
||||
|
||||
self.library_bin.set_child(child)
|
||||
self.hidden_library_bin.set_child(hidden_child)
|
||||
def remove_from_overlay(widget: Gtk.Widget) -> None:
|
||||
if isinstance(widget.get_parent(), Gtk.Overlay):
|
||||
widget.get_parent().remove_overlay(widget)
|
||||
|
||||
if child:
|
||||
self.library_overlay.add_overlay(child)
|
||||
else:
|
||||
remove_from_overlay(self.notice_empty)
|
||||
remove_from_overlay(self.notice_no_results)
|
||||
|
||||
if hidden_child:
|
||||
self.hidden_library_overlay.add_overlay(hidden_child)
|
||||
else:
|
||||
remove_from_overlay(self.hidden_notice_empty)
|
||||
remove_from_overlay(self.hidden_notice_no_results)
|
||||
|
||||
def filter_func(self, child: Gtk.Widget) -> bool:
|
||||
game = child.get_child()
|
||||
text = (
|
||||
(
|
||||
self.hidden_search_entry
|
||||
if self.stack.get_visible_child() == self.hidden_library_view
|
||||
if self.navigation_view.get_visible_page() == self.hidden_library_page
|
||||
else self.search_entry
|
||||
)
|
||||
.get_text()
|
||||
@@ -170,6 +324,12 @@ class CartridgesWindow(Adw.ApplicationWindow):
|
||||
or (text in game.developer.lower() if game.developer else False)
|
||||
)
|
||||
|
||||
if not filtered:
|
||||
if self.filter_state == "all":
|
||||
pass
|
||||
elif game.base_source != self.filter_state:
|
||||
filtered = True
|
||||
|
||||
game.filtered = filtered
|
||||
self.set_library_child()
|
||||
|
||||
@@ -178,7 +338,7 @@ class CartridgesWindow(Adw.ApplicationWindow):
|
||||
def set_active_game(self, _widget: Any, _pspec: Any, game: Game) -> None:
|
||||
self.active_game = game
|
||||
|
||||
def show_details_view(self, game: Game) -> None:
|
||||
def show_details_page(self, game: Game) -> None:
|
||||
self.active_game = game
|
||||
|
||||
self.details_view_cover.set_opacity(int(not game.loading))
|
||||
@@ -205,7 +365,7 @@ class CartridgesWindow(Adw.ApplicationWindow):
|
||||
)
|
||||
|
||||
self.details_view_title.set_label(game.name)
|
||||
self.details_view_header_bar_title.set_title(game.name)
|
||||
self.details_page.set_title(game.name)
|
||||
|
||||
date = relative_date(game.added)
|
||||
self.details_view_added.set_label(
|
||||
@@ -220,14 +380,14 @@ class CartridgesWindow(Adw.ApplicationWindow):
|
||||
_("Last played: {}").format(last_played_date)
|
||||
)
|
||||
|
||||
if self.stack.get_visible_child() != self.details_view:
|
||||
self.navigate(self.details_view)
|
||||
if self.navigation_view.get_visible_page() != self.details_page:
|
||||
self.navigation_view.push(self.details_page)
|
||||
self.set_focus(self.details_view_play_button)
|
||||
|
||||
self.set_details_view_opacity()
|
||||
|
||||
def set_details_view_opacity(self, *_args: Any) -> None:
|
||||
if self.stack.get_visible_child() != self.details_view:
|
||||
if self.navigation_view.get_visible_page() != self.details_page:
|
||||
return
|
||||
|
||||
if (
|
||||
@@ -262,42 +422,26 @@ class CartridgesWindow(Adw.ApplicationWindow):
|
||||
|
||||
return ((get_value(0) > get_value(1)) ^ order) * 2 - 1
|
||||
|
||||
def navigate(self, next_page: Gtk.Widget) -> None:
|
||||
levels = (self.library_view, self.hidden_library_view, self.details_view)
|
||||
self.stack.set_transition_type(
|
||||
Gtk.StackTransitionType.UNDER_RIGHT
|
||||
if levels.index(self.stack.get_visible_child()) - levels.index(next_page)
|
||||
> 0
|
||||
else Gtk.StackTransitionType.OVER_LEFT
|
||||
def set_show_hidden(self, navigation_view: Adw.NavigationView, *_args: Any) -> None:
|
||||
self.lookup_action("show_hidden").set_enabled(
|
||||
navigation_view.get_visible_page() == self.library_page
|
||||
)
|
||||
|
||||
if next_page in (self.library_view, self.hidden_library_view):
|
||||
self.previous_page = next_page
|
||||
self.lookup_action("show_hidden").set_enabled(
|
||||
next_page == self.library_view
|
||||
)
|
||||
|
||||
self.stack.set_visible_child(next_page)
|
||||
|
||||
def on_go_back_action(self, *_args: Any) -> None:
|
||||
if self.stack.get_visible_child() == self.hidden_library_view:
|
||||
self.navigate(self.library_view)
|
||||
elif self.stack.get_visible_child() == self.details_view:
|
||||
self.on_go_to_parent_action()
|
||||
def on_show_sidebar_action(self, *_args: Any) -> None:
|
||||
shared.state_schema.set_boolean(
|
||||
"show-sidebar", (value := not self.overlay_split_view.get_show_sidebar())
|
||||
)
|
||||
self.overlay_split_view.set_show_sidebar(value)
|
||||
|
||||
def on_go_to_parent_action(self, *_args: Any) -> None:
|
||||
if self.stack.get_visible_child() == self.details_view:
|
||||
self.navigate(
|
||||
self.hidden_library_view
|
||||
if self.previous_page == self.hidden_library_view
|
||||
else self.library_view
|
||||
)
|
||||
if self.navigation_view.get_visible_page() == self.details_page:
|
||||
self.navigation_view.pop()
|
||||
|
||||
def on_go_home_action(self, *_args: Any) -> None:
|
||||
self.navigate(self.library_view)
|
||||
self.navigation_view.pop_to_page(self.library_page)
|
||||
|
||||
def on_show_hidden_action(self, *_args: Any) -> None:
|
||||
self.navigate(self.hidden_library_view)
|
||||
self.navigation_view.push(self.hidden_library_page)
|
||||
|
||||
def on_sort_action(self, action: Gio.SimpleAction, state: GLib.Variant) -> None:
|
||||
action.set_state(state)
|
||||
@@ -307,10 +451,10 @@ class CartridgesWindow(Adw.ApplicationWindow):
|
||||
shared.state_schema.set_string("sort-mode", self.sort_state)
|
||||
|
||||
def on_toggle_search_action(self, *_args: Any) -> None:
|
||||
if self.stack.get_visible_child() == self.library_view:
|
||||
if self.navigation_view.get_visible_page() == self.library_page:
|
||||
search_bar = self.search_bar
|
||||
search_entry = self.search_entry
|
||||
elif self.stack.get_visible_child() == self.hidden_library_view:
|
||||
elif self.navigation_view.get_visible_page() == self.hidden_library_page:
|
||||
search_bar = self.hidden_search_bar
|
||||
search_entry = self.hidden_search_entry
|
||||
else:
|
||||
@@ -330,9 +474,9 @@ class CartridgesWindow(Adw.ApplicationWindow):
|
||||
):
|
||||
self.on_toggle_search_action()
|
||||
else:
|
||||
self.on_go_back_action()
|
||||
self.navigation_view.pop()
|
||||
|
||||
def show_details_view_search(self, widget: Gtk.Widget) -> None:
|
||||
def show_details_page_search(self, widget: Gtk.Widget) -> None:
|
||||
library = (
|
||||
self.hidden_library if widget == self.hidden_search_entry else self.library
|
||||
)
|
||||
@@ -343,7 +487,7 @@ class CartridgesWindow(Adw.ApplicationWindow):
|
||||
break
|
||||
|
||||
if self.filter_func(child):
|
||||
self.show_details_view(child.get_child())
|
||||
self.show_details_page(child.get_child())
|
||||
break
|
||||
|
||||
index += 1
|
||||
@@ -377,9 +521,9 @@ class CartridgesWindow(Adw.ApplicationWindow):
|
||||
self.toasts.pop((game, undo))
|
||||
|
||||
def on_open_menu_action(self, *_args: Any) -> None:
|
||||
if self.stack.get_visible_child() == self.library_view:
|
||||
if self.navigation_view.get_visible_page() == self.library_page:
|
||||
self.primary_menu_button.popup()
|
||||
elif self.stack.get_visible_child() == self.hidden_library_view:
|
||||
elif self.navigation_view.get_visible_page() == self.hidden_library_page:
|
||||
self.hidden_primary_menu_button.popup()
|
||||
|
||||
def on_close_action(self, *_args: Any) -> None:
|
||||
|
||||