Prepare for Windows builds

This commit is contained in:
kramo
2023-03-19 01:06:00 +01:00
parent e709617370
commit c5b263c71e
7 changed files with 198 additions and 138 deletions

View File

@@ -5,7 +5,7 @@ template PreferencesWindow : Adw.PreferencesWindow {
search-enabled: false; search-enabled: false;
default-height: 500; default-height: 500;
Adw.PreferencesPage { Adw.PreferencesPage page {
Adw.PreferencesGroup { Adw.PreferencesGroup {
title: _("General"); title: _("General");
@@ -18,7 +18,7 @@ template PreferencesWindow : Adw.PreferencesWindow {
} }
} }
Adw.PreferencesGroup { Adw.PreferencesGroup steam_group {
title: "Steam"; title: "Steam";
Adw.ActionRow { Adw.ActionRow {
@@ -32,7 +32,7 @@ template PreferencesWindow : Adw.PreferencesWindow {
} }
} }
Adw.PreferencesGroup { Adw.PreferencesGroup heroic_group {
title: "Heroic"; title: "Heroic";
Adw.ActionRow { Adw.ActionRow {
@@ -70,7 +70,7 @@ template PreferencesWindow : Adw.PreferencesWindow {
} }
} }
Adw.PreferencesGroup { Adw.PreferencesGroup bottles_group {
title: "Bottles"; title: "Bottles";
Adw.ActionRow { Adw.ActionRow {

View File

@@ -392,6 +392,7 @@ menu add_games {
item { item {
label: _("Bottles"); label: _("Bottles");
action: "app.bottles_import"; action: "app.bottles_import";
hidden-when: "action-disabled";
} }
} }
} }

View File

@@ -17,6 +17,7 @@
# #
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
import os
import sys import sys
import time import time
@@ -58,6 +59,9 @@ class CartridgesApplication(Adw.Application):
self.create_action("add_game", self.on_add_game_action, ["<primary>n"]) self.create_action("add_game", self.on_add_game_action, ["<primary>n"])
self.create_action("remove_game", self.on_remove_game_action) self.create_action("remove_game", self.on_remove_game_action)
if os.name == "nt":
self.lookup_action("bottles_import").set_enabled(False)
self.win = None self.win = None
def do_activate(self): def do_activate(self):

View File

@@ -17,6 +17,8 @@
# #
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
import os
from gi.repository import Adw, Gio, GLib, Gtk from gi.repository import Adw, Gio, GLib, Gtk
@@ -24,6 +26,9 @@ from gi.repository import Adw, Gio, GLib, Gtk
class PreferencesWindow(Adw.PreferencesWindow): class PreferencesWindow(Adw.PreferencesWindow):
__gtype_name__ = "PreferencesWindow" __gtype_name__ = "PreferencesWindow"
page = Gtk.Template.Child()
bottles_group = Gtk.Template.Child()
exit_after_launch_switch = Gtk.Template.Child() exit_after_launch_switch = Gtk.Template.Child()
import_epic_games_switch = Gtk.Template.Child() import_epic_games_switch = Gtk.Template.Child()
import_gog_games_switch = Gtk.Template.Child() import_gog_games_switch = Gtk.Template.Child()
@@ -102,3 +107,6 @@ class PreferencesWindow(Adw.PreferencesWindow):
self.bottles_file_chooser_button.connect( self.bottles_file_chooser_button.connect(
"clicked", choose_folder, set_bottles_dir "clicked", choose_folder, set_bottles_dir
) )
if os.name == "nt":
self.page.remove(self.bottles_group)

View File

@@ -57,6 +57,11 @@ def heroic_parser(parent_widget, action):
), ),
) )
action(None, None) action(None, None)
elif os.path.exists(os.path.join(os.getenv("appdata"), "heroic")):
schema.set_string(
"heroic-location", os.path.join(os.getenv("appdata"), "heroic")
)
action(None, None)
else: else:
filechooser = Gtk.FileDialog.new() filechooser = Gtk.FileDialog.new()

View File

@@ -25,12 +25,13 @@ from gi.repository import Gio
def run_command(executable): def run_command(executable):
with subprocess.Popen( subprocess.Popen(
["flatpak-spawn --host " + executable] ["flatpak-spawn --host " + executable]
if os.getenv("FLATPAK_ID") == "hu.kramo.Cartridges" if os.getenv("FLATPAK_ID") == "hu.kramo.Cartridges"
else [executable], else [executable],
shell=True, shell=True,
start_new_session=True, 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() if Gio.Settings.new("hu.kramo.Cartridges").get_boolean("exit-after-launch"):
sys.exit()

View File

@@ -21,14 +21,172 @@ import json
import os import os
import re import re
import time import time
import urllib.request
from gi.repository import Gio, GLib, Gtk, Adw from gi.repository import Adw, Gio, GLib, Gtk
from .create_dialog import create_dialog from .create_dialog import create_dialog
from .save_cover import save_cover from .save_cover import save_cover
from .save_games import save_games from .save_games import save_games
def upadte_values_from_data(content, values):
basic_data = json.loads(content)[values["appid"]]
if not basic_data["success"]:
values["blacklisted"] = True
else:
data = basic_data["data"]
values["developer"] = ", ".join(data["developers"])
if data["type"] != "game":
values["blacklisted"] = True
return values
def get_game(task, datatypes, current_time, parent_widget, appmanifest, steam_dir):
values = {}
with open(appmanifest, "r") as open_file:
data = open_file.read()
open_file.close()
for datatype in datatypes:
value = re.findall('"' + datatype + '"\t\t"(.*)"\n', data)
values[datatype] = value[0]
values["game_id"] = "steam_" + values["appid"]
if (
values["game_id"] in parent_widget.games
and not parent_widget.games[values["game_id"]].removed
):
task.return_value(None)
return
values["executable"] = "xdg-open steam://rungameid/" + values["appid"]
values["hidden"] = False
values["source"] = "steam"
values["added"] = current_time
values["last_played"] = 0
url = "https://store.steampowered.com/api/appdetails?appids=" + values["appid"]
# On Linux the request is made through gvfs so the app can run without network permissions
if os.name == "nt":
try:
with urllib.request.urlopen(url, timeout=10) as open_file:
content = open_file.read().decode("utf-8")
except urllib.error.URLError:
content = None
else:
open_file = Gio.File.new_for_uri(url)
try:
content = open_file.load_contents()[1]
except GLib.GError:
content = None
if content:
values = upadte_values_from_data(content, values)
if os.path.isfile(
os.path.join(
steam_dir,
"appcache",
"librarycache",
values["appid"] + "_library_600x900.jpg",
)
):
save_cover(
values,
parent_widget,
os.path.join(
steam_dir,
"appcache",
"librarycache",
values["appid"] + "_library_600x900.jpg",
),
)
task.return_value(values)
return
def get_games_async(parent_widget, appmanifests, steam_dir, import_dialog):
datatypes = ["appid", "name"]
current_time = int(time.time())
steam_games = {}
queue = 0
# Wrap the function with another one as Gio.Task.run_in_thread does not allow for passing args
def create_func(datatypes, current_time, parent_widget, appmanifest, steam_dir):
def wrapper(task, *_unused):
get_game(
task, datatypes, current_time, parent_widget, appmanifest, steam_dir
)
return wrapper
def update_games(_task, result, parent_widget):
nonlocal queue
nonlocal import_dialog
queue -= 1
try:
final_values = result.propagate_value()[1]
steam_games[final_values["game_id"]] = final_values
except (TypeError, GLib.GError):
pass
if queue == 0:
save_games(steam_games)
parent_widget.update_games(steam_games)
import_dialog.close()
games_no = len(
{
game_id: final_values
for game_id, final_values in steam_games.items()
if "blacklisted" not in final_values.keys()
}
)
if games_no == 0:
create_dialog(
parent_widget,
_("No Games Found"),
_("No new games were found in the Steam library."),
)
elif games_no == 1:
create_dialog(
parent_widget,
_("Steam Games Imported"),
_("Successfully imported 1 game."),
)
elif games_no > 1:
create_dialog(
parent_widget,
_("Steam Games Imported"),
_("Successfully imported")
+ " "
+ str(games_no)
+ " "
+ _("games."),
)
for appmanifest in appmanifests:
queue += 1
cancellable = Gio.Cancellable.new()
GLib.timeout_add_seconds(5, cancellable.cancel)
task = Gio.Task.new(None, cancellable, update_games, parent_widget)
task.set_return_on_cancel(True)
task.run_in_thread(
create_func(datatypes, current_time, parent_widget, appmanifest, steam_dir)
)
def steam_parser(parent_widget, action): def steam_parser(parent_widget, action):
schema = parent_widget.schema schema = parent_widget.schema
steam_dir = os.path.expanduser(schema.get_string("steam-location")) steam_dir = os.path.expanduser(schema.get_string("steam-location"))
@@ -44,6 +202,11 @@ def steam_parser(parent_widget, action):
elif os.path.exists(os.path.expanduser("~/.steam/steam/")): elif os.path.exists(os.path.expanduser("~/.steam/steam/")):
schema.set_string("steam-location", "~/.steam/steam/") schema.set_string("steam-location", "~/.steam/steam/")
action(None, None) action(None, None)
elif os.path.exists(os.path.join(os.getenv("programfiles(x86)"), "Steam")):
schema.set_string(
"steam-location", os.path.join(os.getenv("programfiles(x86)"), "Steam")
)
action(None, None)
else: else:
filechooser = Gtk.FileDialog.new() filechooser = Gtk.FileDialog.new()
@@ -84,16 +247,6 @@ def steam_parser(parent_widget, action):
steam_dir = os.path.expanduser(schema.get_string("steam-location")) steam_dir = os.path.expanduser(schema.get_string("steam-location"))
appmanifests = []
datatypes = ["appid", "name"]
steam_games = {}
current_time = int(time.time())
for open_file in os.listdir(os.path.join(steam_dir, "steamapps")):
path = os.path.join(steam_dir, "steamapps", open_file)
if os.path.isfile(path) and "appmanifest" in open_file:
appmanifests.append(path)
import_statuspage = Adw.StatusPage( import_statuspage = Adw.StatusPage(
title=_("Importing Games..."), title=_("Importing Games..."),
description=_("Talking to Steam"), description=_("Talking to Steam"),
@@ -108,125 +261,13 @@ def steam_parser(parent_widget, action):
deletable=False, deletable=False,
) )
queue = [] import_dialog.present()
cancellables = []
for appmanifest in appmanifests: appmanifests = []
values = {}
with open(appmanifest, "r") as open_file:
data = open_file.read()
open_file.close()
for datatype in datatypes:
value = re.findall('"' + datatype + '"\t\t"(.*)"\n', data)
values[datatype] = value[0]
values["game_id"] = "steam_" + values["appid"] for open_file in os.listdir(os.path.join(steam_dir, "steamapps")):
path = os.path.join(steam_dir, "steamapps", open_file)
if os.path.isfile(path) and "appmanifest" in open_file:
appmanifests.append(path)
if ( get_games_async(parent_widget, appmanifests, steam_dir, import_dialog)
values["game_id"] in parent_widget.games
and not parent_widget.games[values["game_id"]].removed
):
continue
values["executable"] = "xdg-open steam://rungameid/" + values["appid"]
values["hidden"] = False
values["source"] = "steam"
values["added"] = current_time
values["last_played"] = 0
def steam_api_callback(current_file, result, values):
try:
_success, content, _etag = current_file.load_contents_finish(result)
basic_data = json.loads(content)[values["appid"]]
if not basic_data["success"]:
steam_games[values["game_id"]]["blacklisted"] = True
else:
data = basic_data["data"]
steam_games[values["game_id"]]["developer"] = ", ".join(
data["developers"]
)
if data["type"] != "game":
steam_games[values["game_id"]]["blacklisted"] = True
except GLib.GError:
pass
queue.remove(values["appid"])
if not queue:
import_dialog.close()
games_no = len(
{
game_id: final_values
for game_id, final_values in steam_games.items()
if "blacklisted" not in final_values.keys()
}
)
if games_no == 1:
create_dialog(
parent_widget,
_("Steam Games Imported"),
_("Successfully imported 1 game."),
)
elif games_no > 1:
create_dialog(
parent_widget,
_("Steam Games Imported"),
_("Successfully imported")
+ " "
+ str(games_no)
+ " "
+ _("games."),
)
save_games(steam_games)
parent_widget.update_games(steam_games.keys())
open_file = Gio.File.new_for_uri(
"https://store.steampowered.com/api/appdetails?appids=" + values["appid"]
)
if not import_dialog.is_visible():
import_dialog.show()
queue.append(values["appid"])
cancellables.append(Gio.Cancellable())
open_file.load_contents_async(cancellables[-1], steam_api_callback, values)
GLib.timeout_add_seconds(10, timeout, cancellables[-1])
if os.path.isfile(
os.path.join(
steam_dir,
"appcache",
"librarycache",
values["appid"] + "_library_600x900.jpg",
)
):
save_cover(
values,
parent_widget,
os.path.join(
steam_dir,
"appcache",
"librarycache",
values["appid"] + "_library_600x900.jpg",
),
)
steam_games[values["game_id"]] = values
if not steam_games:
create_dialog(
parent_widget,
_("No Games Found"),
_("No new games were found in the Steam library."),
)
def timeout(cancellable):
cancellable.cancel()
return False