Merge pull request #174 from kra-mo/desktop-file-importer

Desktop file importer
This commit is contained in:
kramo
2023-08-25 21:53:26 +02:00
committed by GitHub
13 changed files with 574 additions and 218 deletions

View File

@@ -2,153 +2,159 @@ using Gtk 4.0;
using Adw 1; using Adw 1;
template $DetailsWindow : Adw.Window { template $DetailsWindow : Adw.Window {
default-width: 480; // Same as Nautilus' properties window default-width: 480; // Same as Nautilus' properties window
default-height: -1; default-height: -1;
modal: true; modal: true;
ShortcutController { ShortcutController {
Shortcut { Shortcut {
trigger: "Escape"; trigger: "Escape";
action: "action(window.close)"; 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",
]
}
} }
Box { Adw.PreferencesPage {
orientation: vertical; vexpand: true;
Adw.HeaderBar HeaderBar { Adw.PreferencesGroup cover_group {
show-start-title-buttons: false; Adw.Clamp cover_clamp {
show-end-title-buttons: false; maximum-size: 200;
[start] Overlay {
Button cancel_button { [overlay]
label: _("Cancel"); Spinner spinner {
action-name: "window.close"; margin-start: 72;
margin-end: 72;
} }
[end] Overlay cover_overlay {
Button apply_button { 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;
styles [ styles [
"suggested-action" "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",
]
}
} }
}
}
}
Adw.PreferencesGroup {
Adw.EntryRow name {
title: _("Title");
} }
Adw.PreferencesPage { Adw.EntryRow developer {
vexpand: true; title: _("Developer (optional)");
Adw.PreferencesGroup cover_group {
Adw.Clamp cover_clamp {
maximum-size: 200;
Overlay {
[overlay]
Spinner spinner {
margin-start: 72;
margin-end: 72;
}
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;
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"
]
}
}
}
}
}
Adw.PreferencesGroup {
Adw.EntryRow name {
title: _("Title");
}
Adw.EntryRow developer {
title: _("Developer (optional)");
}
}
Adw.PreferencesGroup {
Adw.EntryRow executable {
title: _("Executable");
[suffix]
Gtk.Button file_chooser_button {
valign: center;
icon-name: "document-open-symbolic";
tooltip-text: _("Select File");
styles [
"flat"
]
}
[suffix]
Gtk.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"
]
}
}
}
} }
}
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;
}
}
;
styles [
"flat",
]
}
}
}
} }
} }
}

View File

@@ -76,7 +76,6 @@ template $PreferencesWindow : Adw.PreferencesWindow {
] ]
} }
} }
} }
} }
@@ -311,6 +310,35 @@ template $PreferencesWindow : Adw.PreferencesWindow {
} }
} }
} }
Adw.ExpanderRow desktop_expander_row {
title: _("Desktop Entries");
show-enable-switch: true;
Adw.ComboRow desktop_terminal_exec_row {
title: _("Terminal");
subtitle: _("Used only by games that require one to run");
model: StringList {
strings [
_("Custom"),
"xdg-terminal-exec",
"GNOME Console",
"GNOME Terminal",
"Konsole",
"XTerm"
]
};
[suffix]
Revealer desktop_tereminal_custom_exec_revealer {
transition-type: slide_right;
Entry desktop_tereminal_custom_exec {
valign: center;
placeholder-text: _("Executable");
}
}
}
}
} }
} }

View File

@@ -194,13 +194,19 @@ template $CartridgesWindow : Adw.ApplicationWindow {
action-name: "app.edit_game"; action-name: "app.edit_game";
tooltip-text: _("Edit"); tooltip-text: _("Edit");
styles ["raised", "circular"] styles [
"raised",
"circular",
]
} }
Button details_view_hide_button { Button details_view_hide_button {
action-name: "app.hide_game"; action-name: "app.hide_game";
styles ["raised", "circular"] styles [
"raised",
"circular",
]
} }
Button { Button {
@@ -208,7 +214,10 @@ template $CartridgesWindow : Adw.ApplicationWindow {
action-name: "app.remove_game"; action-name: "app.remove_game";
tooltip-text: _("Remove"); tooltip-text: _("Remove");
styles ["raised", "circular"] styles [
"raised",
"circular",
]
} }
MenuButton { MenuButton {
@@ -216,7 +225,10 @@ template $CartridgesWindow : Adw.ApplicationWindow {
menu-model: search; menu-model: search;
tooltip-text: _("Search"); tooltip-text: _("Search");
styles ["raised", "circular"] styles [
"raised",
"circular",
]
} }
styles [ styles [

View File

@@ -1,5 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<schemalist gettext-domain="cartridges"> <schemalist gettext-domain="cartridges">
<enum id="@APP_ID@.terminals">
<value nick="custom" value="0"/>
<value nick="xdg-terminal-exec" value="1"/>
<value nick="kgx" value="2"/>
<value nick="gnome-terminal" value="3"/>
<value nick="konsole" value="4"/>
<value nick="xterm" value="5"/>
</enum>
<schema id="@APP_ID@" path="@PREFIX@/"> <schema id="@APP_ID@" path="@PREFIX@/">
<key name="exit-after-launch" type="b"> <key name="exit-after-launch" type="b">
<default>false</default> <default>false</default>
@@ -76,6 +86,15 @@
<key name="retroarch-location" type="s"> <key name="retroarch-location" type="s">
<default>"~/.var/app/org.libretro.RetroArch/config/retroarch/"</default> <default>"~/.var/app/org.libretro.RetroArch/config/retroarch/"</default>
</key> </key>
<key name="desktop" type="b">
<default>true</default>
</key>
<key name="desktop-terminal" enum="@APP_ID@.terminals">
<default>"xdg-terminal-exec"</default>
</key>
<key name="desktop-terminal-custom-exec" type="s">
<default>""</default>
</key>
<key name="flatpak" type="b"> <key name="flatpak" type="b">
<default>true</default> <default>true</default>
</key> </key>
@@ -98,6 +117,7 @@
<default>false</default> <default>false</default>
</key> </key>
</schema> </schema>
<schema id="@APP_ID@.State" path="@PREFIX@/State/"> <schema id="@APP_ID@.State" path="@PREFIX@/State/">
<key name="width" type="i"> <key name="width" type="i">
<default>1110</default> <default>1110</default>
@@ -121,5 +141,8 @@
<key name="steam-limiter-tokens-history" type="s"> <key name="steam-limiter-tokens-history" type="s">
<default>"[]"</default> <default>"[]"</default>
</key> </key>
<key name="terminal-check-done" type="b">
<default>false</default>
</key>
</schema> </schema>
</schemalist> </schemalist>

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Cartridges\n" "Project-Id-Version: Cartridges\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-08-19 12:45+0200\n" "POT-Creation-Date: 2023-08-21 16:18+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -19,7 +19,7 @@ msgstr ""
#: data/hu.kramo.Cartridges.desktop.in:3 #: data/hu.kramo.Cartridges.desktop.in:3
#: data/hu.kramo.Cartridges.metainfo.xml.in:6 data/gtk/window.blp:47 #: data/hu.kramo.Cartridges.metainfo.xml.in:6 data/gtk/window.blp:47
#: src/main.py:173 #: src/main.py:174
msgid "Cartridges" msgid "Cartridges"
msgstr "" msgstr ""
@@ -58,7 +58,7 @@ msgstr ""
msgid "Game Details" msgid "Game Details"
msgstr "" msgstr ""
#: data/hu.kramo.Cartridges.metainfo.xml.in:42 data/gtk/window.blp:418 #: data/hu.kramo.Cartridges.metainfo.xml.in:42 data/gtk/window.blp:430
#: src/details_window.py:263 src/importer/importer.py:301 #: src/details_window.py:263 src/importer/importer.py:301
#: src/importer/importer.py:352 #: src/importer/importer.py:352
msgid "Preferences" msgid "Preferences"
@@ -68,31 +68,31 @@ msgstr ""
msgid "Cancel" msgid "Cancel"
msgstr "" msgstr ""
#: data/gtk/details-window.blp:57 #: data/gtk/details-window.blp:58
msgid "New Cover" msgid "New Cover"
msgstr "" msgstr ""
#: data/gtk/details-window.blp:75 #: data/gtk/details-window.blp:77
msgid "Delete Cover" msgid "Delete Cover"
msgstr "" msgstr ""
#: data/gtk/details-window.blp:102 data/gtk/game.blp:80 #: data/gtk/details-window.blp:105 data/gtk/game.blp:80
msgid "Title" msgid "Title"
msgstr "" msgstr ""
#: data/gtk/details-window.blp:105 #: data/gtk/details-window.blp:109
msgid "Developer (optional)" msgid "Developer (optional)"
msgstr "" msgstr ""
#: data/gtk/details-window.blp:110 #: data/gtk/details-window.blp:115 data/gtk/preferences.blp:310
msgid "Executable" msgid "Executable"
msgstr "" msgstr ""
#: data/gtk/details-window.blp:116 #: data/gtk/details-window.blp:121
msgid "Select File" msgid "Select File"
msgstr "" msgstr ""
#: data/gtk/details-window.blp:127 #: data/gtk/details-window.blp:132
msgid "More Info" msgid "More Info"
msgstr "" msgstr ""
@@ -105,7 +105,7 @@ msgid "Hide"
msgstr "" msgstr ""
#: data/gtk/game.blp:112 data/gtk/game.blp:131 data/gtk/preferences.blp:56 #: data/gtk/game.blp:112 data/gtk/game.blp:131 data/gtk/preferences.blp:56
#: data/gtk/window.blp:209 #: data/gtk/window.blp:215
msgid "Remove" msgid "Remove"
msgstr "" msgstr ""
@@ -121,8 +121,8 @@ msgstr ""
msgid "Quit" msgid "Quit"
msgstr "" msgstr ""
#: data/gtk/help-overlay.blp:19 data/gtk/window.blp:217 data/gtk/window.blp:257 #: data/gtk/help-overlay.blp:19 data/gtk/window.blp:226 data/gtk/window.blp:269
#: data/gtk/window.blp:324 #: data/gtk/window.blp:336
msgid "Search" msgid "Search"
msgstr "" msgstr ""
@@ -134,7 +134,7 @@ msgstr ""
msgid "Shortcuts" msgid "Shortcuts"
msgstr "" msgstr ""
#: data/gtk/help-overlay.blp:34 src/game.py:105 src/preferences.py:122 #: data/gtk/help-overlay.blp:34 src/game.py:105 src/preferences.py:128
#: src/importer/importer.py:376 #: src/importer/importer.py:376
msgid "Undo" msgid "Undo"
msgstr "" msgstr ""
@@ -163,8 +163,8 @@ msgstr ""
msgid "Remove game" msgid "Remove game"
msgstr "" msgstr ""
#: data/gtk/preferences.blp:13 data/gtk/preferences.blp:89 #: data/gtk/preferences.blp:13 data/gtk/preferences.blp:88
#: data/gtk/preferences.blp:304 #: data/gtk/preferences.blp:332
msgid "Behavior" msgid "Behavior"
msgstr "" msgstr ""
@@ -200,114 +200,130 @@ msgstr ""
msgid "Remove All Games" msgid "Remove All Games"
msgstr "" msgstr ""
#: data/gtk/preferences.blp:85 data/gtk/window.blp:27 data/gtk/window.blp:444 #: data/gtk/preferences.blp:84 data/gtk/window.blp:27 data/gtk/window.blp:456
msgid "Import" msgid "Import"
msgstr "" msgstr ""
#: data/gtk/preferences.blp:92 #: data/gtk/preferences.blp:91
msgid "Remove Uninstalled Games" msgid "Remove Uninstalled Games"
msgstr "" msgstr ""
#: data/gtk/preferences.blp:102 #: data/gtk/preferences.blp:101
msgid "Sources" msgid "Sources"
msgstr "" msgstr ""
#: data/gtk/preferences.blp:105 #: data/gtk/preferences.blp:104
msgid "Steam" msgid "Steam"
msgstr "" msgstr ""
#: data/gtk/preferences.blp:109 data/gtk/preferences.blp:123 #: data/gtk/preferences.blp:108 data/gtk/preferences.blp:122
#: data/gtk/preferences.blp:164 data/gtk/preferences.blp:214 #: data/gtk/preferences.blp:163 data/gtk/preferences.blp:213
#: data/gtk/preferences.blp:228 data/gtk/preferences.blp:242 #: data/gtk/preferences.blp:227 data/gtk/preferences.blp:241
#: data/gtk/preferences.blp:256 data/gtk/preferences.blp:270 #: data/gtk/preferences.blp:255 data/gtk/preferences.blp:269
msgid "Install Location" msgid "Install Location"
msgstr "" msgstr ""
#: data/gtk/preferences.blp:119 #: data/gtk/preferences.blp:118
msgid "Lutris" msgid "Lutris"
msgstr "" msgstr ""
#: data/gtk/preferences.blp:132 #: data/gtk/preferences.blp:131
msgid "Cache Location" msgid "Cache Location"
msgstr "" msgstr ""
#: data/gtk/preferences.blp:141 #: data/gtk/preferences.blp:140
msgid "Import Steam Games" msgid "Import Steam Games"
msgstr "" msgstr ""
#: data/gtk/preferences.blp:150 #: data/gtk/preferences.blp:149
msgid "Import Flatpak Games" msgid "Import Flatpak Games"
msgstr "" msgstr ""
#: data/gtk/preferences.blp:160 #: data/gtk/preferences.blp:159
msgid "Heroic" msgid "Heroic"
msgstr "" msgstr ""
#: data/gtk/preferences.blp:173 #: data/gtk/preferences.blp:172
msgid "Import Epic Games" msgid "Import Epic Games"
msgstr "" msgstr ""
#: data/gtk/preferences.blp:182 #: data/gtk/preferences.blp:181
msgid "Import GOG Games" msgid "Import GOG Games"
msgstr "" msgstr ""
#: data/gtk/preferences.blp:191 #: data/gtk/preferences.blp:190
msgid "Import Amazon Games" msgid "Import Amazon Games"
msgstr "" msgstr ""
#: data/gtk/preferences.blp:200 #: data/gtk/preferences.blp:199
msgid "Import Sideloaded Games" msgid "Import Sideloaded Games"
msgstr "" msgstr ""
#: data/gtk/preferences.blp:210 #: data/gtk/preferences.blp:209
msgid "Bottles" msgid "Bottles"
msgstr "" msgstr ""
#: data/gtk/preferences.blp:224 #: data/gtk/preferences.blp:223
msgid "itch" msgid "itch"
msgstr "" msgstr ""
#: data/gtk/preferences.blp:238 #: data/gtk/preferences.blp:237
msgid "Legendary" msgid "Legendary"
msgstr "" msgstr ""
#: data/gtk/preferences.blp:252 #: data/gtk/preferences.blp:251
msgid "RetroArch" msgid "RetroArch"
msgstr "" msgstr ""
#: data/gtk/preferences.blp:266 #: data/gtk/preferences.blp:265
msgid "Flatpak" msgid "Flatpak"
msgstr "" msgstr ""
#: data/gtk/preferences.blp:279 #: data/gtk/preferences.blp:278
msgid "Import Game Launchers" msgid "Import Game Launchers"
msgstr "" msgstr ""
#: data/gtk/preferences.blp:288
msgid "Desktop Entries"
msgstr ""
#: data/gtk/preferences.blp:292 #: data/gtk/preferences.blp:292
msgid "SteamGridDB" msgid "Terminal"
msgstr ""
#: data/gtk/preferences.blp:293
msgid "Used only by games that require one to run"
msgstr "" msgstr ""
#: data/gtk/preferences.blp:296 #: data/gtk/preferences.blp:296
msgid "Custom"
msgstr ""
#: data/gtk/preferences.blp:320
msgid "SteamGridDB"
msgstr ""
#: data/gtk/preferences.blp:324
msgid "Authentication" msgid "Authentication"
msgstr "" msgstr ""
#: data/gtk/preferences.blp:299 #: data/gtk/preferences.blp:327
msgid "API Key" msgid "API Key"
msgstr "" msgstr ""
#: data/gtk/preferences.blp:307 #: data/gtk/preferences.blp:335
msgid "Use SteamGridDB" msgid "Use SteamGridDB"
msgstr "" msgstr ""
#: data/gtk/preferences.blp:308 #: data/gtk/preferences.blp:336
msgid "Download images when adding or importing games" msgid "Download images when adding or importing games"
msgstr "" msgstr ""
#: data/gtk/preferences.blp:317 #: data/gtk/preferences.blp:345
msgid "Prefer Over Official Images" msgid "Prefer Over Official Images"
msgstr "" msgstr ""
#: data/gtk/preferences.blp:326 #: data/gtk/preferences.blp:354
msgid "Prefer Animated Images" msgid "Prefer Animated Images"
msgstr "" msgstr ""
@@ -335,7 +351,7 @@ msgstr ""
msgid "Games you hide will appear here." msgid "Games you hide will appear here."
msgstr "" msgstr ""
#: data/gtk/window.blp:64 data/gtk/window.blp:305 #: data/gtk/window.blp:64 data/gtk/window.blp:317
msgid "Back" msgid "Back"
msgstr "" msgstr ""
@@ -347,64 +363,64 @@ msgstr ""
msgid "Play" msgid "Play"
msgstr "" msgstr ""
#: data/gtk/window.blp:243 data/gtk/window.blp:437 #: data/gtk/window.blp:255 data/gtk/window.blp:449
msgid "Add Game" msgid "Add Game"
msgstr "" msgstr ""
#: data/gtk/window.blp:250 data/gtk/window.blp:317 #: data/gtk/window.blp:262 data/gtk/window.blp:329
msgid "Main Menu" msgid "Main Menu"
msgstr "" msgstr ""
#: data/gtk/window.blp:272 #: data/gtk/window.blp:284
msgid "Search games" msgid "Search games"
msgstr "" msgstr ""
#: data/gtk/window.blp:312 #: data/gtk/window.blp:324
msgid "Hidden Games" msgid "Hidden Games"
msgstr "" msgstr ""
#: data/gtk/window.blp:339 #: data/gtk/window.blp:351
msgid "Search hidden games" msgid "Search hidden games"
msgstr "" msgstr ""
#: data/gtk/window.blp:376 #: data/gtk/window.blp:388
msgid "Sort" msgid "Sort"
msgstr "" msgstr ""
#: data/gtk/window.blp:379 #: data/gtk/window.blp:391
msgid "A-Z" msgid "A-Z"
msgstr "" msgstr ""
#: data/gtk/window.blp:385 #: data/gtk/window.blp:397
msgid "Z-A" msgid "Z-A"
msgstr "" msgstr ""
#: data/gtk/window.blp:391 #: data/gtk/window.blp:403
msgid "Newest" msgid "Newest"
msgstr "" msgstr ""
#: data/gtk/window.blp:397 #: data/gtk/window.blp:409
msgid "Oldest" msgid "Oldest"
msgstr "" msgstr ""
#: data/gtk/window.blp:403 #: data/gtk/window.blp:415
msgid "Last Played" msgid "Last Played"
msgstr "" msgstr ""
#: data/gtk/window.blp:410 #: data/gtk/window.blp:422
msgid "Show Hidden" msgid "Show Hidden"
msgstr "" msgstr ""
#: data/gtk/window.blp:423 #: data/gtk/window.blp:435
msgid "Keyboard Shortcuts" msgid "Keyboard Shortcuts"
msgstr "" msgstr ""
#: data/gtk/window.blp:428 #: data/gtk/window.blp:440
msgid "About Cartridges" msgid "About Cartridges"
msgstr "" msgstr ""
#. Translators: Replace this with your name for it to show up in the about window #. Translators: Replace this with your name for it to show up in the about window
#: src/main.py:192 #: src/main.py:193
msgid "translator_credits" msgid "translator_credits"
msgstr "" msgstr ""
@@ -434,8 +450,7 @@ msgstr ""
msgid "Add" msgid "Add"
msgstr "" msgstr ""
#. Gdk.Texture supports .svg but PIL doesn't #: src/details_window.py:91
#: src/details_window.py:88
msgid "Executables" msgid "Executables"
msgstr "" msgstr ""
@@ -508,28 +523,28 @@ msgstr ""
msgid "{} removed" msgid "{} removed"
msgstr "" msgstr ""
#: src/preferences.py:121 #: src/preferences.py:127
msgid "All games removed" msgid "All games removed"
msgstr "" msgstr ""
#: src/preferences.py:170 #: src/preferences.py:207
msgid "" msgid ""
"An API key is required to use SteamGridDB. You can generate one {}here{}." "An API key is required to use SteamGridDB. You can generate one {}here{}."
msgstr "" msgstr ""
#: src/preferences.py:298 #: src/preferences.py:335
msgid "Installation Not Found" msgid "Installation Not Found"
msgstr "" msgstr ""
#: src/preferences.py:300 #: src/preferences.py:337
msgid "Select a valid directory." msgid "Select a valid directory."
msgstr "" msgstr ""
#: src/preferences.py:356 #: src/preferences.py:393
msgid "Invalid Directory" msgid "Invalid Directory"
msgstr "" msgstr ""
#: src/preferences.py:362 #: src/preferences.py:399
msgid "Set Location" msgid "Set Location"
msgstr "" msgstr ""
@@ -537,7 +552,7 @@ msgstr ""
msgid "Dismiss" msgid "Dismiss"
msgstr "" msgstr ""
#: src/importer/importer.py:135 #: src/importer/importer.py:137
msgid "Importing Games…" msgid "Importing Games…"
msgstr "" msgstr ""

View File

@@ -73,7 +73,6 @@ class BottlesSourceIterable(SourceIterable):
image_path = bottles_location / bottle_path / "grids" / image_name image_path = bottles_location / bottle_path / "grids" / image_name
additional_data = {"local_image_path": image_path} additional_data = {"local_image_path": image_path}
# Produce game
yield (game, additional_data) yield (game, additional_data)

View File

@@ -0,0 +1,214 @@
# desktop_source.py
#
# Copyright 2023 kramo
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# SPDX-License-Identifier: GPL-3.0-or-later
import shlex
from hashlib import sha3_256
from pathlib import Path
from time import time
from typing import NamedTuple
from gi.repository import GLib, Gtk
from src import shared
from src.game import Game
from src.importer.sources.source import Source, SourceIterable
class DesktopSourceIterable(SourceIterable):
source: "DesktopSource"
def __iter__(self):
"""Generator method producing games"""
added_time = int(time())
icon_theme = Gtk.IconTheme.new()
search_paths = [
shared.home / ".local" / "share",
"/run/host/usr/local/share",
"/run/host/usr/share",
"/run/host/usr/share/pixmaps",
"/usr/share/pixmaps",
] + GLib.get_system_data_dirs()
for search_path in search_paths:
path = Path(search_path)
if not str(search_path).endswith("/pixmaps"):
path = path / "icons"
if not path.is_dir():
continue
if str(path).startswith("/app/"):
continue
icon_theme.add_search_path(str(path))
terminal_exec = self.get_terminal_exec()
for path in search_paths:
if str(path).startswith("/app/"):
continue
path = Path(path) / "applications"
if not path.is_dir():
continue
for entry in path.iterdir():
if entry.suffix != ".desktop":
continue
# Skip Lutris games
if str(entry.name).startswith("net.lutris."):
continue
keyfile = GLib.KeyFile.new()
try:
keyfile.load_from_file(str(entry), 0)
if "Game" not in keyfile.get_string_list(
"Desktop Entry", "Categories"
):
continue
name = keyfile.get_string("Desktop Entry", "Name")
executable = keyfile.get_string("Desktop Entry", "Exec").split(
" %"
)[0]
except GLib.GError:
continue
# Skip Steam games
if "steam://rungameid/" in executable:
continue
# Skip Heroic games
if "heroic://launch/" in executable:
continue
# Skip Bottles games
if "bottles-cli " in executable:
continue
try:
if keyfile.get_boolean("Desktop Entry", "NoDisplay"):
continue
except GLib.GError:
pass
try:
terminal = keyfile.get_boolean("Desktop Entry", "Terminal")
except GLib.GError:
terminal = False
try:
cd_path = (
"cd " + keyfile.get_string("Desktop Entry", "Path") + " && "
)
except GLib.GError:
cd_path = ""
values = {
"source": self.source.source_id,
"added": added_time,
"name": name,
"game_id": "desktop_"
+ sha3_256(
str(entry).encode("utf-8"), usedforsecurity=False
).hexdigest(),
"executable": cd_path
+ (
(terminal_exec + shlex.quote(executable))
if terminal
else executable
),
}
game = Game(values)
additional_data = {}
try:
icon_str = keyfile.get_string("Desktop Entry", "Icon")
except GLib.GError:
print("AAAAAAAAAAAAAAAAAAAAAAA")
yield game
continue
else:
if "/" in icon_str:
additional_data = {"local_icon_path": Path(icon_str)}
yield (game, additional_data)
continue
try:
if (
icon_path := icon_theme.lookup_icon(
icon_str,
None,
512,
1,
shared.win.get_direction(),
0,
)
.get_file()
.get_path()
):
additional_data = {"local_icon_path": Path(icon_path)}
except GLib.GError:
pass
yield (game, additional_data)
def get_terminal_exec(self) -> str:
match shared.schema.get_enum("desktop-terminal"):
case 0:
terminal_exec = shared.schema.get_string("desktop-terminal-custom-exec")
case 1:
terminal_exec = "xdg-terminal-exec"
case 2:
terminal_exec = "kgx -e"
case 3:
terminal_exec = "gnome-terminal --"
case 4:
terminal_exec = "konsole -e"
case 5:
terminal_exec = "xterm -e"
return terminal_exec + " "
class DesktopLocations(NamedTuple):
pass
class DesktopSource(Source):
"""Generic Flatpak source"""
source_id = "desktop"
name = _("Desktop")
iterable_class = DesktopSourceIterable
available_on = {"linux"}
locations: DesktopLocations
def __init__(self) -> None:
super().__init__()
self.locations = DesktopLocations()

View File

@@ -109,7 +109,6 @@ class FlatpakSourceIterable(SourceIterable):
except GLib.GError: except GLib.GError:
pass pass
# Produce game
yield (game, additional_data) yield (game, additional_data)

View File

@@ -77,7 +77,6 @@ class LutrisSourceIterable(SourceIterable):
image_path = self.source.locations.cache["coverart"] / f"{row[2]}.jpg" image_path = self.source.locations.cache["coverart"] / f"{row[2]}.jpg"
additional_data = {"local_image_path": image_path} additional_data = {"local_image_path": image_path}
# Produce game
yield (game, additional_data) yield (game, additional_data)
# Cleanup # Cleanup

View File

@@ -78,7 +78,6 @@ class Source(Iterable):
def is_available(self) -> bool: def is_available(self) -> bool:
return sys.platform in self.available_on return sys.platform in self.available_on
@abstractmethod
def make_executable(self, *args, **kwargs) -> str: def make_executable(self, *args, **kwargs) -> str:
""" """
Create a game executable command. Create a game executable command.

View File

@@ -105,7 +105,6 @@ class SteamSourceIterable(SourceIterable):
) )
additional_data = {"local_image_path": image_path, "steam_appid": appid} additional_data = {"local_image_path": image_path, "steam_appid": appid}
# Produce game
yield (game, additional_data) yield (game, additional_data)

View File

@@ -20,6 +20,8 @@
import json import json
import lzma import lzma
import os import os
import shlex
import subprocess
import sys import sys
from typing import Any, Optional from typing import Any, Optional
@@ -36,6 +38,7 @@ from src.details_window import DetailsWindow
from src.game import Game from src.game import Game
from src.importer.importer import Importer from src.importer.importer import Importer
from src.importer.sources.bottles_source import BottlesSource from src.importer.sources.bottles_source import BottlesSource
from src.importer.sources.desktop_source import DesktopSource
from src.importer.sources.flatpak_source import FlatpakSource from src.importer.sources.flatpak_source import FlatpakSource
from src.importer.sources.heroic_source import HeroicSource from src.importer.sources.heroic_source import HeroicSource
from src.importer.sources.itch_source import ItchSource from src.importer.sources.itch_source import ItchSource
@@ -72,6 +75,10 @@ class CartridgesApplication(Adw.Application):
if os.name == "nt": if os.name == "nt":
migrate_files_v1_to_v2() migrate_files_v1_to_v2()
else:
if not shared.state_schema.get_boolean("terminal-check-done"):
self.check_desktop_terminals()
shared.state_schema.set_boolean("terminal-check-done", True)
# Set fallback icon-name # Set fallback icon-name
Gtk.Window.set_default_icon_name(shared.APP_ID) Gtk.Window.set_default_icon_name(shared.APP_ID)
@@ -142,6 +149,22 @@ class CartridgesApplication(Adw.Application):
self.win.present() self.win.present()
def check_desktop_terminals(self) -> None:
"""Look for an installed terminal for desktop entries and set the relevant gsetting"""
terminals = ("xdg-terminal-exec", "kgx", "gnome-terminal", "konsole", "xterm")
for index, command in enumerate(terminals):
command = f"type {command} &> /dev/null"
if os.getenv("FLATPAK_ID") == shared.APP_ID:
command = "flatpak-spawn --host /bin/sh -c " + shlex.quote(command)
try:
subprocess.run(command, shell=True, check=True)
shared.schema.set_enum("desktop-terminal", index + 1)
return
except subprocess.CalledProcessError:
pass
def load_games_from_disk(self) -> None: def load_games_from_disk(self) -> None:
if shared.games_dir.is_dir(): if shared.games_dir.is_dir():
for game_file in shared.games_dir.iterdir(): for game_file in shared.games_dir.iterdir():
@@ -155,9 +178,9 @@ class CartridgesApplication(Adw.Application):
def on_about_action(self, *_args: Any) -> None: def on_about_action(self, *_args: Any) -> None:
# Get the debug info from the log files # Get the debug info from the log files
debug_str = "" debug_str = ""
for i, path in enumerate(shared.log_files): for index, path in enumerate(shared.log_files):
# Add a horizontal line between runs # Add a horizontal line between runs
if i > 0: if index > 0:
debug_str += "" * 37 + "\n" debug_str += "" * 37 + "\n"
# Add the run's logs # Add the run's logs
log_file = ( log_file = (
@@ -241,6 +264,9 @@ class CartridgesApplication(Adw.Application):
if shared.schema.get_boolean("flatpak"): if shared.schema.get_boolean("flatpak"):
shared.importer.add_source(FlatpakSource()) shared.importer.add_source(FlatpakSource())
if shared.schema.get_boolean("desktop"):
shared.importer.add_source(DesktopSource())
if shared.schema.get_boolean("itch"): if shared.schema.get_boolean("itch"):
shared.importer.add_source(ItchSource()) shared.importer.add_source(ItchSource())

View File

@@ -28,6 +28,7 @@ from gi.repository import Adw, Gio, GLib, Gtk
from src import shared from src import shared
from src.game import Game from src.game import Game
from src.importer.sources.bottles_source import BottlesSource from src.importer.sources.bottles_source import BottlesSource
from src.importer.sources.desktop_source import DesktopSource
from src.importer.sources.flatpak_source import FlatpakSource from src.importer.sources.flatpak_source import FlatpakSource
from src.importer.sources.heroic_source import HeroicSource from src.importer.sources.heroic_source import HeroicSource
from src.importer.sources.itch_source import ItchSource from src.importer.sources.itch_source import ItchSource
@@ -97,6 +98,11 @@ class PreferencesWindow(Adw.PreferencesWindow):
flatpak_data_file_chooser_button = Gtk.Template.Child() flatpak_data_file_chooser_button = Gtk.Template.Child()
flatpak_import_launchers_switch = Gtk.Template.Child() flatpak_import_launchers_switch = Gtk.Template.Child()
desktop_expander_row = Gtk.Template.Child()
desktop_terminal_exec_row = Gtk.Template.Child()
desktop_tereminal_custom_exec_revealer = Gtk.Template.Child()
desktop_tereminal_custom_exec = Gtk.Template.Child()
sgdb_key_group = Gtk.Template.Child() sgdb_key_group = Gtk.Template.Child()
sgdb_key_entry_row = Gtk.Template.Child() sgdb_key_entry_row = Gtk.Template.Child()
sgdb_switch = Gtk.Template.Child() sgdb_switch = Gtk.Template.Child()
@@ -144,6 +150,7 @@ class PreferencesWindow(Adw.PreferencesWindow):
for source_class in ( for source_class in (
BottlesSource, BottlesSource,
FlatpakSource, FlatpakSource,
DesktopSource,
HeroicSource, HeroicSource,
ItchSource, ItchSource,
LegendarySource, LegendarySource,
@@ -158,6 +165,36 @@ class PreferencesWindow(Adw.PreferencesWindow):
else: else:
self.init_source_row(source) self.init_source_row(source)
# Desktop Terminal Executable
def set_terminal_exec(widget: Adw.ComboRow, _param: Any) -> None:
shared.schema.set_enum("desktop-terminal", widget.get_selected())
self.desktop_tereminal_custom_exec_revealer.set_reveal_child(
widget.get_selected() == 0
)
self.desktop_terminal_exec_row.connect("notify::selected", set_terminal_exec)
self.desktop_terminal_exec_row.set_selected(
terminal_value := shared.schema.get_enum("desktop-terminal")
)
if not terminal_value:
set_terminal_exec(
self.desktop_terminal_exec_row, None
) # The default value is supposed to be 4294967295, but it's 0 and I can't change it
self.desktop_tereminal_custom_exec.set_text(
shared.schema.get_string("desktop-terminal-custom-exec")
)
def desktop_custom_exec_changed(*_args: Any) -> None:
shared.schema.set_string(
"desktop-terminal-custom-exec",
self.desktop_tereminal_custom_exec.get_text(),
)
self.desktop_tereminal_custom_exec.connect(
"changed", desktop_custom_exec_changed
)
# SteamGridDB # SteamGridDB
def sgdb_key_changed(*_args: Any) -> None: def sgdb_key_changed(*_args: Any) -> None:
shared.schema.set_string("sgdb-key", self.sgdb_key_entry_row.get_text()) shared.schema.set_string("sgdb-key", self.sgdb_key_entry_row.get_text())