🚧 Various fixes

- Platform-dependent sources
- Added heroic schema keys
- Moved location and is_installed to Source
This commit is contained in:
GeoffreyCoulaud
2023-05-31 22:43:30 +02:00
parent ed66109404
commit 97b770cbf2
5 changed files with 81 additions and 85 deletions

View File

@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<schemalist gettext-domain="cartridges"> <schemalist gettext-domain="cartridges">
<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>
</key> </key>
<key name="cover-launches-game" type="b"> <key name="cover-launches-game" type="b">
<default>false</default> <default>false</default>
</key> </key>
@@ -44,21 +44,27 @@
<default>true</default> <default>true</default>
</key> </key>
<key name="heroic-location" type="s"> <key name="heroic-location" type="s">
<default>"~/.config/heroic/"</default>
</key>
<key name="heroic-flatpak-location" type="s">
<default>"~/.var/app/com.heroicgameslauncher.hgl/config/heroic/"</default> <default>"~/.var/app/com.heroicgameslauncher.hgl/config/heroic/"</default>
</key> </key>
<key name="heroic-import-epic" type="b"> <key name="heroic-windows-location" type="s">
<default>true</default> <default>""</default>
</key> </key>
<key name="heroic-import-gog" type="b"> <key name="heroic-import-epic" type="b">
<default>true</default> <default>true</default>
</key> </key>
<key name="heroic-import-sideload" type="b"> <key name="heroic-import-gog" type="b">
<default>true</default> <default>true</default>
</key> </key>
<key name="heroic-import-sideload" type="b">
<default>true</default>
</key>
<key name="bottles" type="b"> <key name="bottles" type="b">
<default>true</default> <default>true</default>
</key> </key>
<key name="bottles-location" type="s"> <key name="bottles-location" type="s">
<default>"~/.var/app/com.usebottles.bottles/data/bottles/"</default> <default>"~/.var/app/com.usebottles.bottles/data/bottles/"</default>
</key> </key>
<key name="itch" type="b"> <key name="itch" type="b">
@@ -79,7 +85,7 @@
<key name="sgdb-animated" type="b"> <key name="sgdb-animated" type="b">
<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>
@@ -92,13 +98,13 @@
</key> </key>
<key name="sort-mode" type="s"> <key name="sort-mode" type="s">
<choices> <choices>
<choice value="a-z"/> <choice value="a-z" />
<choice value="z-a"/> <choice value="z-a" />
<choice value="newest"/> <choice value="newest" />
<choice value="oldest"/> <choice value="oldest" />
<choice value="last_played"/> <choice value="last_played" />
</choices> </choices>
<default>"a-z"</default> <default>"a-z"</default>
</key> </key>
</schema> </schema>
</schemalist> </schemalist>

View File

@@ -1,5 +1,5 @@
import json import json
from abc import abstractmethod import logging
from hashlib import sha256 from hashlib import sha256
from json import JSONDecodeError from json import JSONDecodeError
from pathlib import Path from pathlib import Path
@@ -8,7 +8,7 @@ from typing import Generator, Optional, TypedDict
from src import shared from src import shared
from src.game import Game from src.game import Game
from src.importer.sources.source import Source, SourceIterator from src.importer.sources.source import NTSource, PosixSource, Source, SourceIterator
from src.utils.decorators import ( from src.utils.decorators import (
replaced_by_env_path, replaced_by_env_path,
replaced_by_path, replaced_by_path,
@@ -87,9 +87,9 @@ class HeroicSourceIterator(SourceIterator):
def sub_sources_generator(self): def sub_sources_generator(self):
"""Generator method producing games from all the Heroic sub-sources""" """Generator method producing games from all the Heroic sub-sources"""
for key, sub_source in self.sub_sources.items(): for _key, sub_source in self.sub_sources.items():
# Skip disabled sub-sources # Skip disabled sub-sources
if not shared.schema.get_boolean("heroic-import-" + key): if not shared.schema.get_boolean("heroic-import-" + sub_source["service"]):
continue continue
# Load games from JSON # Load games from JSON
try: try:
@@ -124,32 +124,19 @@ class HeroicSource(Source):
name = "Heroic" name = "Heroic"
executable_format = "xdg-open heroic://launch/{app_name}" executable_format = "xdg-open heroic://launch/{app_name}"
@property
@abstractmethod
def location(self) -> Path:
pass
@property @property
def game_id_format(self) -> str: def game_id_format(self) -> str:
"""The string format used to construct game IDs""" """The string format used to construct game IDs"""
return self.name.lower() + "_{service}_{game_id}" return self.name.lower() + "_{service}_{game_id}"
@property
def is_installed(self):
# pylint: disable=pointless-statement
try:
self.location
except FileNotFoundError:
return False
return True
def __iter__(self): def __iter__(self):
return HeroicSourceIterator(source=self) return HeroicSourceIterator(source=self)
class HeroicNativeSource(HeroicSource): class HeroicNativeSource(HeroicSource, PosixSource):
variant = "native" variant = "native"
@property
@replaced_by_schema_key("heroic-location") @replaced_by_schema_key("heroic-location")
@replaced_by_env_path("XDG_CONFIG_HOME", "heroic/") @replaced_by_env_path("XDG_CONFIG_HOME", "heroic/")
@replaced_by_path("~/.config/heroic/") @replaced_by_path("~/.config/heroic/")
@@ -157,19 +144,21 @@ class HeroicNativeSource(HeroicSource):
raise FileNotFoundError() raise FileNotFoundError()
class HeroicFlatpakSource(HeroicSource): class HeroicFlatpakSource(HeroicSource, PosixSource):
variant = "flatpak" variant = "flatpak"
@property
@replaced_by_schema_key("heroic-flatpak-location") @replaced_by_schema_key("heroic-flatpak-location")
@replaced_by_path("~/.var/app/com.heroicgameslauncher.hgl/config/heroic/") @replaced_by_path("~/.var/app/com.heroicgameslauncher.hgl/config/heroic/")
def location(self) -> Path: def location(self) -> Path:
raise FileNotFoundError() raise FileNotFoundError()
class HeroicWindowsSource(HeroicSource): class HeroicWindowsSource(HeroicSource, NTSource):
variant = "windows" variant = "windows"
executable_format = "start heroic://launch/{app_name}" executable_format = "start heroic://launch/{app_name}"
@property
@replaced_by_schema_key("heroic-windows-location") @replaced_by_schema_key("heroic-windows-location")
@replaced_by_env_path("appdata", "heroic/") @replaced_by_env_path("appdata", "heroic/")
def location(self) -> Path: def location(self) -> Path:

View File

@@ -1,11 +1,9 @@
from abc import abstractmethod
from pathlib import Path
from sqlite3 import connect from sqlite3 import connect
from time import time from time import time
from src import shared from src import shared
from src.game import Game from src.game import Game
from src.importer.sources.source import Source, SourceIterator from src.importer.sources.source import PosixSource, Source, SourceIterator
from src.utils.decorators import replaced_by_path, replaced_by_schema_key from src.utils.decorators import replaced_by_path, replaced_by_schema_key
from src.utils.save_cover import resize_cover, save_cover from src.utils.save_cover import resize_cover, save_cover
@@ -78,29 +76,15 @@ class LutrisSource(Source):
name = "Lutris" name = "Lutris"
executable_format = "xdg-open lutris:rungameid/{game_id}" executable_format = "xdg-open lutris:rungameid/{game_id}"
@property
@abstractmethod
def location(self) -> Path:
pass
@property @property
def game_id_format(self): def game_id_format(self):
return super().game_id_format + "_{game_internal_id}" return super().game_id_format + "_{game_internal_id}"
@property
def is_installed(self):
# pylint: disable=pointless-statement
try:
self.location
except FileNotFoundError:
return False
return True
def __iter__(self): def __iter__(self):
return LutrisSourceIterator(source=self) return LutrisSourceIterator(source=self)
class LutrisNativeSource(LutrisSource): class LutrisNativeSource(LutrisSource, PosixSource):
variant = "native" variant = "native"
@property @property
@@ -110,7 +94,7 @@ class LutrisNativeSource(LutrisSource):
raise FileNotFoundError() raise FileNotFoundError()
class LutrisFlatpakSource(LutrisSource): class LutrisFlatpakSource(LutrisSource, PosixSource):
variant = "flatpak" variant = "flatpak"
@property @property

View File

@@ -1,5 +1,7 @@
import os
from abc import abstractmethod from abc import abstractmethod
from collections.abc import Iterable, Iterator from collections.abc import Iterable, Iterator
from pathlib import Path
from typing import Optional from typing import Optional
from src.game import Game from src.game import Game
@@ -30,6 +32,11 @@ class Source(Iterable):
name: str name: str
variant: str variant: str
available_on: set[str]
def __init__(self) -> None:
super().__init__()
self.available_on = set()
@property @property
def full_name(self) -> str: def full_name(self) -> str:
@@ -52,16 +59,41 @@ class Source(Iterable):
"""The string format used to construct game IDs""" """The string format used to construct game IDs"""
return self.name.lower() + "_{game_id}" return self.name.lower() + "_{game_id}"
@property
def is_installed(self):
# pylint: disable=pointless-statement
try:
self.location
except FileNotFoundError:
return False
return os.name in self.available_on
@property
@abstractmethod
def location(self) -> Path:
"""The source's location on disk"""
@property @property
@abstractmethod @abstractmethod
def executable_format(self) -> str: def executable_format(self) -> str:
"""The executable format used to construct game executables""" """The executable format used to construct game executables"""
@property
@abstractmethod
def is_installed(self) -> bool:
"""Whether the source is detected as installed"""
@abstractmethod @abstractmethod
def __iter__(self) -> SourceIterator: def __iter__(self) -> SourceIterator:
"""Get the source's iterator, to use in for loops""" """Get the source's iterator, to use in for loops"""
class NTSource(Source):
"""Mixin for sources available on Windows"""
def __init__(self) -> None:
super().__init__()
self.available_on.add("nt")
class PosixSource(Source):
"""Mixin for sources available on POXIX-compliant systems"""
def __init__(self) -> None:
super().__init__()
self.available_on.add("posix")

View File

@@ -1,12 +1,11 @@
import re import re
from abc import abstractmethod
from pathlib import Path from pathlib import Path
from time import time from time import time
from typing import Iterator from typing import Iterator
from src import shared from src import shared
from src.game import Game from src.game import Game
from src.importer.sources.source import Source, SourceIterator from src.importer.sources.source import NTSource, PosixSource, Source, SourceIterator
from src.utils.decorators import ( from src.utils.decorators import (
replaced_by_env_path, replaced_by_env_path,
replaced_by_path, replaced_by_path,
@@ -94,25 +93,11 @@ class SteamSource(Source):
name = "Steam" name = "Steam"
executable_format = "xdg-open steam://rungameid/{game_id}" executable_format = "xdg-open steam://rungameid/{game_id}"
@property
@abstractmethod
def location(self) -> Path:
pass
@property
def is_installed(self):
# pylint: disable=pointless-statement
try:
self.location
except FileNotFoundError:
return False
return True
def __iter__(self): def __iter__(self):
return SteamSourceIterator(source=self) return SteamSourceIterator(source=self)
class SteamNativeSource(SteamSource): class SteamNativeSource(SteamSource, PosixSource):
variant = "native" variant = "native"
@property @property
@@ -124,7 +109,7 @@ class SteamNativeSource(SteamSource):
raise FileNotFoundError() raise FileNotFoundError()
class SteamFlatpakSource(SteamSource): class SteamFlatpakSource(SteamSource, PosixSource):
variant = "flatpak" variant = "flatpak"
@property @property
@@ -134,7 +119,7 @@ class SteamFlatpakSource(SteamSource):
raise FileNotFoundError() raise FileNotFoundError()
class SteamWindowsSource(SteamSource): class SteamWindowsSource(SteamSource, NTSource):
variant = "windows" variant = "windows"
executable_format = "start steam://rungameid/{game_id}" executable_format = "start steam://rungameid/{game_id}"