Always show a summary of imported games (Closes #2000)

This commit is contained in:
Mathieu Comandon 2019-11-03 16:11:28 -08:00
parent 280a641182
commit 0318557c83
7 changed files with 66 additions and 41 deletions

View file

@ -56,7 +56,6 @@ class MonitoredCommand:
self.include_processes = include_processes or []
self.exclude_processes = exclude_processes or []
# Keep a copy of previously running processes
self.cwd = self.get_cwd(cwd)
self._stdout = io.StringIO()

View file

@ -9,6 +9,9 @@ from lutris.util.log import logger
if NOTIFY_SUPPORT:
Notify.init("lutris")
else:
logger.warning("Notifications are disabled, please install"
" GObject bindings for 'Notify' to enable them.")
def send_notification(title, text, file_path_to_icon=""):

View file

@ -61,13 +61,13 @@ class ServiceSyncBox(Gtk.Box):
actions = Gtk.Box(spacing=6)
self.pack_start(actions, False, False, 0)
self.sync_button = Gtk.Button("Import games")
self.sync_button.set_sensitive(False)
self.sync_button.set_tooltip_text("Sync now")
self.sync_button.connect(
self.import_button = Gtk.Button("Import games")
self.import_button.set_sensitive(False)
self.import_button.set_tooltip_text("Sync now")
self.import_button.connect(
"clicked", self.on_sync_button_clicked, service.SYNCER.sync
)
actions.pack_start(self.sync_button, False, False, 0)
actions.pack_start(self.import_button, False, False, 0)
self.sync_switch = Gtk.Switch()
self.sync_switch.props.valign = Gtk.Align.CENTER
@ -81,7 +81,7 @@ class ServiceSyncBox(Gtk.Box):
if service.ONLINE and not service.is_connected():
self.sync_switch.set_sensitive(False)
self.sync_button.set_sensitive(False)
self.import_button.set_sensitive(False)
def get_content_widget(self):
center_alignment = Gtk.Alignment()
@ -124,7 +124,7 @@ class ServiceSyncBox(Gtk.Box):
def on_connect_clicked(self, _button):
if self.service.is_connected():
self.unload_games()
self.sync_button.set_sensitive(False)
self.import_button.set_sensitive(False)
self.sync_switch.set_sensitive(False)
# Disable sync on disconnect
if self.sync_switch and self.sync_switch.get_active():
@ -136,7 +136,7 @@ class ServiceSyncBox(Gtk.Box):
self.service.connect()
self._connect_button_toggle()
self.sync_switch.set_sensitive(True)
self.sync_button.set_sensitive(True)
self.import_button.set_sensitive(True)
self.load_games()
return False
@ -164,20 +164,34 @@ class ServiceSyncBox(Gtk.Box):
self.get_imported_games()
)
def on_service_synced(self, games, _extra):
def on_service_synced(self, sync_results, _extra):
"""Called when games are imported"""
window = get_main_window(self)
if not window:
logger.warning("Unable to get main window")
return
if games:
send_notification(
"Games imported",
"%s game%s imported to Lutris" %
(len(games), "s were" if len(games) > 1 else " was")
added_games, original_games = sync_results
skipped_import = len(original_games) - len(added_games)
if added_games:
added_message = "%s game%s imported. " % (
len(added_games),
"s were" if len(added_games) > 1 else " was"
)
for game_id in games:
window.game_store.add_or_update(game_id)
else:
added_message = "No games were added. "
if skipped_import:
skipped_message = "%s game%s already in the library" % (
skipped_import,
"s are" if skipped_import > 1 else " is"
)
else:
skipped_message = ""
send_notification("Games imported", added_message + skipped_message)
for game_id in added_games:
window.game_store.add_or_update(game_id)
def on_switch_changed(self, switch, _data):
write_setting("sync_at_startup", switch.get_active(), self.identifier)
@ -212,7 +226,7 @@ class ServiceSyncBox(Gtk.Box):
self.num_selected += 1
else:
self.num_selected -= 1
self.sync_button.set_sensitive(bool(self.num_selected))
self.import_button.set_sensitive(bool(self.num_selected))
self.store_filter[game_index][col] = new_state
def on_select_all(self, widget):
@ -221,7 +235,7 @@ class ServiceSyncBox(Gtk.Box):
if widget.get_active():
self.num_selected += 1
game[self.COL_SELECTED] = widget.get_active()
self.sync_button.set_sensitive(bool(self.num_selected))
self.import_button.set_sensitive(bool(self.num_selected))
def get_store(self):
"""Return a ListStore for the games to import"""

View file

@ -300,7 +300,7 @@ class GOGSyncer:
}
added_games.append(pga.add_or_update(**game_data))
if not full:
return added_games
return added_games, games
return added_games, []

View file

@ -4,6 +4,7 @@ from lutris import pga
class ServiceGame:
"""Representation of a game from a 3rd party service"""
store = NotImplemented
installer_slug = NotImplemented

View file

@ -160,7 +160,7 @@ class SteamSyncer:
added_games.append(game.install(pga_game))
if not full:
return added_games
return added_games, games
removed_games = []
unavailable_ids = self.lutris_steamids.difference(available_ids)

View file

@ -33,6 +33,7 @@ def get_appid(app):
class XDGGame(ServiceGame):
"""XDG game (Linux game with a desktop launcher)"""
store = "xdg"
runner = "linux"
installer_slug = "desktopapp"
@ -56,11 +57,13 @@ class XDGGame(ServiceGame):
def create_config(self):
"""Create a Lutris config for the current game"""
config = LutrisConfig(runner_slug=self.runner, game_config_id=self.config_id)
config.raw_game_config.update({
"appid": self.appid,
"exe": self.details["exe"],
"args": self.details["args"]
})
config.raw_game_config.update(
{
"appid": self.appid,
"exe": self.details["exe"],
"args": self.details["args"],
}
)
config.raw_system_config.update({"disable_runtime": True})
config.save()
@ -69,7 +72,9 @@ class XDGGame(ServiceGame):
"""Return a tuple with absolute command path and an argument string"""
command = shlex.split(app.get_commandline())
# remove %U etc. and change %% to % in arguments
args = list(map(lambda arg: re.sub("%[^%]", "", arg).replace("%%", "%"), command[1:]))
args = list(
map(lambda arg: re.sub("%[^%]", "", arg).replace("%%", "%"), command[1:])
)
exe = command[0]
if not exe.startswith("/"):
exe = system.find_executable(exe)
@ -83,6 +88,7 @@ class XDGGame(ServiceGame):
class XDGSyncer:
"""Sync games available in a XDG compliant menu to Lutris"""
ignored_games = (
"lutris",
"mame",
@ -119,53 +125,55 @@ class XDGSyncer:
@property
def lutris_games(self):
"""Iterates through Lutris games imported from XDG"""
for game in pga.get_games_where(runner=XDGGame.runner,
installer_slug=XDGGame.installer_slug,
installed=1):
for game in pga.get_games_where(
runner=XDGGame.runner, installer_slug=XDGGame.installer_slug, installed=1
):
yield game
@classmethod
def is_importable(cls, app):
"""Returns whether a XDG game is importable to Lutris"""
appid = get_appid(app)
executable = app.get_executable() or ''
if any([
executable = app.get_executable() or ""
if any(
[
app.get_nodisplay() or app.get_is_hidden(), # App is hidden
not executable, # Check app has an executable
appid.startswith("net.lutris"), # Skip lutris created shortcuts
appid.lower() in map(str.lower, cls.ignored_games), # game blacklisted
executable.lower() in cls.ignored_executables, # exe blacklisted
]):
]
):
return False
# must be in Game category
categories = app.get_categories() or ''
categories = app.get_categories() or ""
categories = list(filter(None, categories.lower().split(";")))
if "game" not in categories:
return False
# contains a blacklisted category
if bool([
if bool(
[
category
for category in categories
if category in map(str.lower, cls.ignored_categories)
]):
]
):
return False
return True
@classmethod
def load(cls, force_reload=False):
"""Return the list of games stored in the XDG menu."""
return [
XDGGame.new_from_xdg_app(app)
for app in cls.iter_xdg_games()
]
return [XDGGame.new_from_xdg_app(app) for app in cls.iter_xdg_games()]
def sync(self, games, full=False):
"""Sync the given games to the lutris library
Params:
games (list): List of ServiceGames to sync
full (bool): Run a full sync, removes games not found from the lutris library
Return:
tuple: 2-tuple of added and removed game ID lists
@ -181,7 +189,7 @@ class XDGSyncer:
added_games.append(game_id)
if not full:
return added_games
return added_games, games
for slug in set(installed_games.keys()).difference(available_games):
game_id = installed_games[slug]["id"]