Files
cartridges/src/game.py
Bananaman 77b083e219 A few minor code cleanups and fixes (#47)
* Avoid exception if trying to delete missing "removed" key

`.pop(key)` throws an exception if that `key` is missing. Using a default value (in this case None) means we don't throw any errors when deleting a missing key. Which is what we want here, for safety. We just want to delete the key. We don't care if it's existing or not.

There are other places in the codebase that also use `.pop(key)`, but all of those first check the validity of the key before popping, so this was the only one that needed fixing.

* Improve performance by removing keys() calls

Every `.keys()` call create a new `[list...]` of all keys from the given dictionary. It's a total waste of performance, since we can already check if a key exists in a dictionary by just using `if "key" in the_dict`.

* Use more pythonic "not in" syntax

The syntax is supposed to be `if "thing" not in other_thing`. We already use this proper `not in` syntax everywhere else in the codebase. Just fixing this location.
2023-03-31 15:24:02 +02:00

180 lines
6.2 KiB
Python

# game.py
#
# Copyright 2022-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 json
import os
import shlex # pylint: disable=unused-import
import subprocess
import sys
from gi.repository import GdkPixbuf, Gio, Gtk
from .save_game import save_game
@Gtk.Template(resource_path="/hu/kramo/Cartridges/gtk/game.ui")
class game(Gtk.Box): # pylint: disable=invalid-name
__gtype_name__ = "game"
overlay = Gtk.Template.Child()
title = Gtk.Template.Child()
button_play = Gtk.Template.Child()
cover = Gtk.Template.Child()
cover_button = Gtk.Template.Child()
menu_button = Gtk.Template.Child()
play_revealer = Gtk.Template.Child()
title_revealer = Gtk.Template.Child()
game_options = Gtk.Template.Child()
hidden_game_options = Gtk.Template.Child()
def __init__(self, parent_widget, data, **kwargs):
super().__init__(**kwargs)
self.parent_widget = parent_widget
self.added = data["added"]
self.executable = data["executable"]
self.game_id = data["game_id"]
self.hidden = data["hidden"]
self.last_played = data["last_played"]
self.name = data["name"]
self.developer = data["developer"] if "developer" in data else None
self.removed = "removed" in data
self.blacklisted = "blacklisted" in data
self.pixbuf = self.get_cover()
self.cover.set_pixbuf(self.pixbuf)
self.title.set_label(self.name)
self.event_contoller_motion = Gtk.EventControllerMotion.new()
self.add_controller(self.event_contoller_motion)
self.overlay.set_measure_overlay(self.play_revealer, True)
self.set_play_label()
self.cover_button.connect("clicked", self.cover_button_clicked)
self.button_play.connect("clicked", self.button_play_clicked)
self.event_contoller_motion.connect("enter", self.show_play)
self.event_contoller_motion.connect("leave", self.hide_play)
self.parent_widget.schema.connect("changed", self.schema_changed)
if self.hidden:
self.menu_button.set_menu_model(self.hidden_game_options)
else:
self.menu_button.set_menu_model(self.game_options)
self.menu_button.get_popover().connect("notify::visible", self.hide_play)
def launch(self):
# Generate launch arguments, either list (no shell) or a string (for shell).
args = (
["flatpak-spawn", "--host", *self.executable] # Flatpak
if os.getenv("FLATPAK_ID") == "hu.kramo.Cartridges"
else shlex.join(
self.executable
) # Windows (We need shell to support its "open" built-in).
if os.name == "nt"
else self.executable # Linux/Others
)
# The host environment vars are automatically passed through by Popen.
subprocess.Popen(
args,
shell=isinstance(args, str),
start_new_session=True,
creationflags=subprocess.CREATE_NEW_PROCESS_GROUP if os.name == "nt" else 0,
)
if Gio.Settings.new("hu.kramo.Cartridges").get_boolean("exit-after-launch"):
sys.exit()
def toggle_hidden(self):
games_dir = os.path.join(
os.getenv("XDG_DATA_HOME")
or os.path.expanduser(os.path.join("~", ".local", "share")),
"cartridges",
"games",
)
if not os.path.exists(games_dir):
return
with open(os.path.join(games_dir, f"{self.game_id}.json"), "r") as open_file:
data = json.loads(open_file.read())
data["hidden"] = not data["hidden"]
save_game(data)
def get_cover(self):
# If the cover is already in memory, return
if self.game_id in self.parent_widget.pixbufs:
return self.parent_widget.pixbufs[self.game_id]
# Create a new pixbuf
cover_path = os.path.join(
os.getenv("XDG_DATA_HOME")
or os.path.expanduser(os.path.join("~", ".local", "share")),
"cartridges",
"covers",
f"{self.game_id}.tiff",
)
if os.path.isfile(cover_path):
return GdkPixbuf.Pixbuf.new_from_file(cover_path)
# Return the placeholder pixbuf
return self.parent_widget.placeholder_pixbuf
def show_play(self, _widget, *_unused):
self.play_revealer.set_reveal_child(True)
self.title_revealer.set_reveal_child(False)
def hide_play(self, _widget, *_unused):
if not self.menu_button.get_active():
self.play_revealer.set_reveal_child(False)
self.title_revealer.set_reveal_child(True)
def launch_game(self, _widget, *_unused):
self.parent_widget.set_active_game(None, None, self.game_id)
self.parent_widget.get_application().on_launch_game_action(None)
def cover_button_clicked(self, _widget):
if self.parent_widget.schema.get_boolean("cover-launches-game"):
self.launch_game(None)
else:
self.parent_widget.show_overview(None, self.game_id)
def button_play_clicked(self, _widget):
if self.parent_widget.schema.get_boolean("cover-launches-game"):
self.parent_widget.show_overview(None, self.game_id)
else:
self.launch_game(None)
def set_play_label(self):
if self.parent_widget.schema.get_boolean("cover-launches-game"):
self.button_play.set_label(_("Details"))
else:
self.button_play.set_label(_("Play"))
def schema_changed(self, _settings, key):
if key == "cover-launches-game":
self.set_play_label()