173 lines
5.9 KiB
Python
173 lines
5.9 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 = self.parent_widget.data_dir / "cartridges" / "games"
|
|
|
|
if not games_dir.exists():
|
|
return
|
|
|
|
data = json.loads((games_dir / f"{self.game_id}.json").read_text())
|
|
|
|
data["hidden"] = not data["hidden"]
|
|
|
|
save_game(self.parent_widget, 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 = (
|
|
self.parent_widget.data_dir
|
|
/ "cartridges"
|
|
/ "covers"
|
|
/ f"{self.game_id}.tiff"
|
|
)
|
|
|
|
if cover_path.is_file():
|
|
return GdkPixbuf.Pixbuf.new_from_file(str(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()
|