From 5abf3f300da43dd106b62b2796e452ebec9d2faf Mon Sep 17 00:00:00 2001 From: kramo Date: Tue, 15 Aug 2023 20:11:06 +0200 Subject: [PATCH] Remove missing games - closes #85 --- data/gtk/preferences.blp | 13 ++++++++++ data/hu.kramo.Cartridges.gschema.xml.in | 3 +++ src/importer/importer.py | 34 +++++++++++++++++++++++++ src/preferences.py | 3 +++ src/store/store.py | 8 +++++- 5 files changed, 60 insertions(+), 1 deletion(-) diff --git a/data/gtk/preferences.blp b/data/gtk/preferences.blp index 9654c29..543a993 100644 --- a/data/gtk/preferences.blp +++ b/data/gtk/preferences.blp @@ -85,6 +85,19 @@ template $PreferencesWindow : Adw.PreferencesWindow { title: _("Import"); icon-name: "document-save-symbolic"; + Adw.PreferencesGroup import_behavior_group { + title: _("Behavior"); + + Adw.ActionRow { + title: _("Remove Missing Games"); + activatable-widget: remove_missing_switch; + + Switch remove_missing_switch { + valign: center; + } + } + } + Adw.PreferencesGroup sources_group { title: _("Sources"); diff --git a/data/hu.kramo.Cartridges.gschema.xml.in b/data/hu.kramo.Cartridges.gschema.xml.in index d31c2ed..9003a93 100644 --- a/data/hu.kramo.Cartridges.gschema.xml.in +++ b/data/hu.kramo.Cartridges.gschema.xml.in @@ -10,6 +10,9 @@ false + + true + true diff --git a/src/importer/importer.py b/src/importer/importer.py index 756ea3b..f3d95cb 100644 --- a/src/importer/importer.py +++ b/src/importer/importer.py @@ -49,8 +49,15 @@ class Importer(ErrorProducer): n_pipelines_done: int = 0 game_pipelines: set[Pipeline] = None + removed_games: set[Game] = set() + def __init__(self): super().__init__() + + # TODO: make this stateful + shared.store.new_game_ids = set() + shared.store.duplicate_game_ids = set() + self.game_pipelines = set() self.sources = set() @@ -217,9 +224,36 @@ class Importer(ErrorProducer): if self.finished: self.import_callback() + def remove_games(self): + """Set removed to True for missing games""" + if not shared.schema.get_boolean("remove-missing"): + return + + for game in shared.store: + if game.removed: + continue + if game.source == "imported": + continue + if not shared.schema.get_boolean(game.base_source): + continue + if game.game_id in shared.store.duplicate_game_ids: + continue + if game.game_id in shared.store.new_game_ids: + continue + + logging.debug("Removing missing game %s (%s)", game.name, game.game_id) + + game.removed = True + game.save() + game.update() + self.removed_games.add(game) + def import_callback(self): """Callback called when importing has finished""" logging.info("Import done") + self.remove_games() + shared.store.new_game_ids = set() + shared.store.duplicate_game_ids = set() self.import_dialog.close() self.summary_toast = self.create_summary_toast() self.create_error_dialog() diff --git a/src/preferences.py b/src/preferences.py index 6b7d105..a3172ac 100644 --- a/src/preferences.py +++ b/src/preferences.py @@ -52,6 +52,8 @@ class PreferencesWindow(Adw.PreferencesWindow): cover_launches_game_switch = Gtk.Template.Child() high_quality_images_switch = Gtk.Template.Child() + remove_missing_switch = Gtk.Template.Child() + steam_expander_row = Gtk.Template.Child() steam_data_action_row = Gtk.Template.Child() steam_data_file_chooser_button = Gtk.Template.Child() @@ -184,6 +186,7 @@ class PreferencesWindow(Adw.PreferencesWindow): "exit-after-launch", "cover-launches-game", "high-quality-images", + "remove-missing", "lutris-import-steam", "lutris-import-flatpak", "heroic-import-epic", diff --git a/src/store/store.py b/src/store/store.py index 231bbdc..0e07749 100644 --- a/src/store/store.py +++ b/src/store/store.py @@ -18,7 +18,7 @@ # SPDX-License-Identifier: GPL-3.0-or-later import logging -from typing import MutableMapping, Generator, Any +from typing import Any, Generator, MutableMapping from src import shared from src.game import Game @@ -33,12 +33,16 @@ class Store: pipeline_managers: set[Manager] pipelines: dict[str, Pipeline] source_games: MutableMapping[str, MutableMapping[str, Game]] + new_game_ids: set[str] + duplicate_game_ids: set[str] def __init__(self) -> None: self.managers = {} self.pipeline_managers = set() self.pipelines = {} self.source_games = {} + self.new_game_ids = set() + self.duplicate_game_ids = set() def __contains__(self, obj: object) -> bool: """Check if the game is present in the store with the `in` keyword""" @@ -114,6 +118,7 @@ class Store: if not stored_game: # New game, do as normal logging.debug("New store game %s (%s)", game.name, game.game_id) + self.new_game_ids.add(game.game_id) elif stored_game.removed: # Will replace a removed game, cleanup its remains logging.debug( @@ -125,6 +130,7 @@ class Store: else: # Duplicate game, ignore it logging.debug("Duplicate store game %s (%s)", game.name, game.game_id) + self.duplicate_game_ids.add(game.game_id) return None # Connect signals