Пример #1
0
class RunningGame:
    """Class for manipulating running games"""
    def __init__(self, game_id, application=None, window=None):
        self.application = application
        self.window = window
        self.game_id = game_id
        self.running_game_box = None
        self.game = Game(game_id)
        self.game.connect("game-error", self.window.on_game_error)
        self.game.connect("game-stop", self.on_stop)

    def __str__(self):
        return "Running %s" % self.game.name

    def play(self):
        if self.game.is_installed:
            self.game.play()
        else:
            logger.warning("%s is not available", self.game.slug)
            InstallerWindow(
                game_slug=self.game.slug, parent=self.window, application=self.application
            )

        if self.game.state == Game.STATE_STOPPED:
            return

        self.running_game_box = RunningGameBox(self.game)
        self.running_game_box.stop_button.connect("clicked", self.on_stop)
        self.running_game_box.log_button.connect("clicked", self.on_show_logs)
        self.window.add_running_game(self.running_game_box)

    def on_stop(self, caller):
        """Stops the game"""
        if not isinstance(caller, Game):
            # If the signal is coming from a game, it has already stopped.
            self.game.stop()
        self.running_game_box.destroy()
        try:
            logger.debug("Removing %s from running games", self)
            self.application.running_games.pop(self.application.running_games.index(self))
        except ValueError:
            logger.warning("%s not in running game list", self)
        self.window.remove_running_game()

    def on_show_logs(self, _widget):
        """Display game log in a LogDialog"""
        log_title = u"Log for {}".format(self.game)
        log_window = LogDialog(
            title=log_title, buffer=self.game.log_buffer, parent=self.window
        )
        log_window.run()
        log_window.destroy()
Пример #2
0
class GameActions:
    """Regroup a list of callbacks for a game"""

    def __init__(self, application=None, window=None):
        self.application = application or Gio.Application.get_default()
        self.window = window
        self.game_id = None
        self._game = None

    @property
    def game(self):
        if not self._game:
            self._game = self.application.get_game_by_id(self.game_id)
            if not self._game:
                self._game = Game(self.game_id)
            self._game.connect("game-error", self.window.on_game_error)
        return self._game

    @property
    def is_game_running(self):
        return bool(self.application.get_game_by_id(self.game_id))

    def set_game(self, game=None, game_id=None):
        if game:
            self._game = game
            self.game_id = game.id
        else:
            self._game = None
            self.game_id = game_id

    def get_game_actions(self):
        """Return a list of game actions and their callbacks"""
        return [
            ("play", _("Play"), self.on_game_launch),
            ("stop", _("Stop"), self.on_game_stop),
            ("install", _("Install"), self.on_install_clicked),
            ("update", _("Install updates"), self.on_update_clicked),
            ("install_dlcs", "Install DLCs", self.on_install_dlc_clicked),
            ("show_logs", _("Show logs"), self.on_show_logs),
            ("add", _("Add installed game"), self.on_add_manually),
            ("configure", _("Configure"), self.on_edit_game_configuration),
            ("favorite", _("Add to favorites"), self.on_add_favorite_game),
            ("deletefavorite", _("Remove from favorites"), self.on_delete_favorite_game),
            ("execute-script", _("Execute script"), self.on_execute_script_clicked),
            ("browse", _("Browse files"), self.on_browse_files),
            (
                "desktop-shortcut",
                _("Create desktop shortcut"),
                self.on_create_desktop_shortcut,
            ),
            (
                "rm-desktop-shortcut",
                _("Delete desktop shortcut"),
                self.on_remove_desktop_shortcut,
            ),
            (
                "menu-shortcut",
                _("Create application menu shortcut"),
                self.on_create_menu_shortcut,
            ),
            (
                "rm-menu-shortcut",
                _("Delete application menu shortcut"),
                self.on_remove_menu_shortcut,
            ),
            ("install_more", _("Install another version"), self.on_install_clicked),
            ("remove", _("Remove"), self.on_remove_game),
            ("view", _("View on Lutris.net"), self.on_view_game),
            ("hide", _("Hide game from library"), self.on_hide_game),
            ("unhide", _("Unhide game from library"), self.on_unhide_game),
        ]

    def get_displayed_entries(self):
        """Return a dictionary of actions that should be shown for a game"""
        return {
            "add": not self.game.is_installed,
            "install": not self.game.is_installed,
            "play": self.game.is_installed and not self.is_game_running,
            "update": self.game.is_updatable,
            "install_dlcs": self.game.is_updatable,
            "stop": self.is_game_running,
            "configure": bool(self.game.is_installed),
            "browse": self.game.is_installed and self.game.runner_name != "browser",
            "show_logs": self.game.is_installed,
            "favorite": not self.game.is_favorite,
            "deletefavorite": self.game.is_favorite,
            "install_more": not self.game.service and self.game.is_installed,
            "execute-script": bool(
                self.game.is_installed and self.game.runner
                and self.game.runner.system_config.get("manual_command")
            ),
            "desktop-shortcut": (
                self.game.is_installed
                and not xdgshortcuts.desktop_launcher_exists(self.game.slug, self.game.id)
            ),
            "menu-shortcut": (
                self.game.is_installed
                and not xdgshortcuts.menu_launcher_exists(self.game.slug, self.game.id)
            ),
            "rm-desktop-shortcut": bool(
                self.game.is_installed
                and xdgshortcuts.desktop_launcher_exists(self.game.slug, self.game.id)
            ),
            "rm-menu-shortcut": bool(
                self.game.is_installed
                and xdgshortcuts.menu_launcher_exists(self.game.slug, self.game.id)
            ),
            "remove": True,
            "view": True,
            "hide": self.game.is_installed and not self.game.is_hidden,
            "unhide": self.game.is_hidden,
        }

    def on_game_launch(self, *_args):
        """Launch a game"""
        self.game.launch()

    def get_running_game(self):
        ids = self.application.get_running_game_ids()
        for game_id in ids:
            if str(game_id) == str(self.game.id):
                return self.game
        logger.warning("Game %s not in %s", self.game_id, ids)

    def on_game_stop(self, _caller):
        """Stops the game"""
        game = self.get_running_game()
        if game:
            game.force_stop()

    def on_show_logs(self, _widget):
        """Display game log"""
        _buffer = self.game.log_buffer
        if not _buffer:
            logger.info("No log for game %s", self.game)
        return LogWindow(
            title=_("Log for {}").format(self.game),
            buffer=_buffer,
            application=self.application
        )

    def on_install_clicked(self, *_args):
        """Install a game"""
        # Install the currently selected game in the UI
        if not self.game.slug:
            raise RuntimeError("No game to install: %s" % self.game.id)
        self.game.emit("game-install")

    def on_update_clicked(self, _widget):
        self.game.emit("game-install-update")

    def on_install_dlc_clicked(self, _widget):
        self.game.emit("game-install-dlc")

    def on_locate_installed_game(self, _button, game):
        """Show the user a dialog to import an existing install to a DRM free service

        Params:
            game (Game): Game instance without a database ID, populated with a fields the service can provides
        """
        AddGameDialog(self.window, game=game)

    def on_add_manually(self, _widget, *_args):
        """Callback that presents the Add game dialog"""
        return AddGameDialog(self.window, game=self.game, runner=self.game.runner_name)

    def on_edit_game_configuration(self, _widget):
        """Edit game preferences"""
        self.application.show_window(EditGameConfigDialog, game=self.game, parent=self.window)

    def on_add_favorite_game(self, _widget):
        """Add to favorite Games list"""
        self.game.add_to_favorites()

    def on_delete_favorite_game(self, _widget):
        """delete from favorites"""
        self.game.remove_from_favorites()

    def on_hide_game(self, _widget):
        """Add a game to the list of hidden games"""
        self.game.set_hidden(True)

    def on_unhide_game(self, _widget):
        """Removes a game from the list of hidden games"""
        self.game.set_hidden(False)

    def on_execute_script_clicked(self, _widget):
        """Execute the game's associated script"""
        manual_command = self.game.runner.system_config.get("manual_command")
        if path_exists(manual_command):
            MonitoredCommand(
                [manual_command],
                include_processes=[os.path.basename(manual_command)],
                cwd=self.game.directory,
            ).start()
            logger.info("Running %s in the background", manual_command)

    def on_browse_files(self, _widget):
        """Callback to open a game folder in the file browser"""
        path = self.game.get_browse_dir()
        if not path:
            dialogs.NoticeDialog(_("This game has no installation directory"))
        elif path_exists(path):
            open_uri("file://%s" % path)
        else:
            dialogs.NoticeDialog(_("Can't open %s \nThe folder doesn't exist.") % path)

    def on_create_menu_shortcut(self, *_args):
        """Add the selected game to the system's Games menu."""
        xdgshortcuts.create_launcher(self.game.slug, self.game.id, self.game.name, menu=True)

    def on_create_desktop_shortcut(self, *_args):
        """Create a desktop launcher for the selected game."""
        xdgshortcuts.create_launcher(self.game.slug, self.game.id, self.game.name, desktop=True)

    def on_remove_menu_shortcut(self, *_args):
        """Remove an XDG menu shortcut"""
        xdgshortcuts.remove_launcher(self.game.slug, self.game.id, menu=True)

    def on_remove_desktop_shortcut(self, *_args):
        """Remove a .desktop shortcut"""
        xdgshortcuts.remove_launcher(self.game.slug, self.game.id, desktop=True)

    def on_view_game(self, _widget):
        """Callback to open a game on lutris.net"""
        open_uri("https://lutris.net/games/%s" % self.game.slug)

    def on_remove_game(self, *_args):
        """Callback that present the uninstall dialog to the user"""
        if self.game.is_installed:
            UninstallGameDialog(game_id=self.game.id, parent=self.window)
        else:
            RemoveGameDialog(game_id=self.game.id, parent=self.window)
Пример #3
0
class GameActions:
    """Regroup a list of callbacks for a game"""
    def __init__(self, application=None, window=None):
        self.application = application or Gio.Application.get_default()
        self.window = window
        self.game_id = None
        self._game = None

    @property
    def game(self):
        if not self._game:
            self._game = self.application.get_game_by_id(self.game_id)
            if not self._game:
                self._game = Game(self.game_id)
            self._game.connect("game-error", self.window.on_game_error)
        return self._game

    @property
    def is_game_running(self):
        return bool(self.application.get_game_by_id(self.game_id))

    def set_game(self, game=None, game_id=None):
        if game:
            self._game = game
            self.game_id = game.id
        else:
            self._game = None
            self.game_id = game_id

    def get_game_actions(self):
        """Return a list of game actions and their callbacks"""
        return [
            ("play", "Play", self.on_game_run),
            ("stop", "Stop", self.on_stop),
            ("show_logs", "Show logs", self.on_show_logs),
            ("install", "Install", self.on_install_clicked),
            ("add", "Add installed game", self.on_add_manually),
            ("configure", "Configure", self.on_edit_game_configuration),
            ("execute-script", "Execute script",
             self.on_execute_script_clicked),
            ("browse", "Browse files", self.on_browse_files),
            (
                "desktop-shortcut",
                "Create desktop shortcut",
                self.on_create_desktop_shortcut,
            ),
            (
                "rm-desktop-shortcut",
                "Delete desktop shortcut",
                self.on_remove_desktop_shortcut,
            ),
            (
                "menu-shortcut",
                "Create application menu shortcut",
                self.on_create_menu_shortcut,
            ),
            (
                "rm-menu-shortcut",
                "Delete application menu shortcut",
                self.on_remove_menu_shortcut,
            ),
            ("install_more", "Install another version",
             self.on_install_clicked),
            ("remove", "Remove", self.on_remove_game),
            ("view", "View on Lutris.net", self.on_view_game),
            ("hide", "Hide game from library", self.on_hide_game),
            ("unhide", "Unhide game from library", self.on_unhide_game),
        ]

    def on_hide_game(self, _widget):
        """Add a game to the list of hidden games"""
        game = Game(self.window.view.selected_game.id)

        # Append the new hidden ID and save it
        ignores = pga.get_hidden_ids() + [game.id]
        pga.set_hidden_ids(ignores)

        # Update the GUI
        if not self.window.show_hidden_games:
            self.window.game_store.remove_game(game.id)

    def on_unhide_game(self, _widget):
        """Removes a game from the list of hidden games"""
        game = Game(self.window.view.selected_game.id)

        # Remove the ID to unhide and save it
        ignores = pga.get_hidden_ids()
        ignores.remove(game.id)
        pga.set_hidden_ids(ignores)

    @staticmethod
    def is_game_hidden(game):
        """Returns whether a game is on the list of hidden games"""
        return game.id in pga.get_hidden_ids()

    def get_displayed_entries(self):
        """Return a dictionary of actions that should be shown for a game"""
        return {
            "add":
            not self.game.is_installed and not self.game.is_search_result,
            "install":
            not self.game.is_installed,
            "play":
            self.game.is_installed and not self.is_game_running,
            "stop":
            self.is_game_running,
            "show_logs":
            self.game.is_installed,
            "configure":
            bool(self.game.is_installed),
            "install_more":
            self.game.is_installed and not self.game.is_search_result,
            "execute-script":
            bool(self.game.is_installed
                 and self.game.runner.system_config.get("manual_command")),
            "desktop-shortcut": (self.game.is_installed
                                 and not xdgshortcuts.desktop_launcher_exists(
                                     self.game.slug, self.game.id)),
            "menu-shortcut": (self.game.is_installed
                              and not xdgshortcuts.menu_launcher_exists(
                                  self.game.slug, self.game.id)),
            "rm-desktop-shortcut":
            bool(self.game.is_installed
                 and xdgshortcuts.desktop_launcher_exists(
                     self.game.slug, self.game.id)),
            "rm-menu-shortcut":
            bool(self.game.is_installed and xdgshortcuts.menu_launcher_exists(
                self.game.slug, self.game.id)),
            "browse":
            self.game.is_installed and self.game.runner_name != "browser",
            "remove":
            not self.game.is_search_result,
            "view":
            True,
            "hide":
            not GameActions.is_game_hidden(self.game),
            "unhide":
            GameActions.is_game_hidden(self.game)
        }

    def on_game_run(self, *_args):
        """Launch a game"""
        self.application.launch(self.game)

    def get_running_game(self):
        for i in range(self.application.running_games.get_n_items()):
            game = self.application.running_games.get_item(i)
            if game == self.game:
                return game

    def on_stop(self, caller):
        """Stops the game"""

        matched_game = self.get_running_game()
        if not matched_game:
            logger.warning("Game %s not in running game list", self.game_id)
            return
        if not matched_game.game_thread:
            logger.warning(
                "Game %s doesn't appear to be running, not killing it",
                self.game_id)
            return
        try:
            os.kill(matched_game.game_thread.game_process.pid, signal.SIGTERM)
        except ProcessLookupError:
            pass
        logger.debug("Removed game with ID %s from running games",
                     self.game_id)

    def on_show_logs(self, _widget):
        """Display game log"""
        return LogWindow(title="Log for {}".format(self.game),
                         buffer=self.game.log_buffer,
                         application=self.application)

    def on_install_clicked(self, *_args):
        """Install a game"""
        # Install the currently selected game in the UI
        return InstallerWindow(
            parent=self.window,
            game_slug=self.game.slug,
            application=self.application,
        )

    def on_add_manually(self, _widget, *_args):
        """Callback that presents the Add game dialog"""
        AddGameDialog(self.window,
                      game=self.game,
                      runner=self.game.runner_name)

    def on_edit_game_configuration(self, _widget):
        """Edit game preferences"""
        EditGameConfigDialog(self.window, self.game)

    def on_execute_script_clicked(self, _widget):
        """Execute the game's associated script"""
        manual_command = self.game.runner.system_config.get("manual_command")
        if path_exists(manual_command):
            MonitoredCommand(
                [manual_command],
                include_processes=[os.path.basename(manual_command)],
                cwd=self.game.directory,
            ).start()
            logger.info("Running %s in the background", manual_command)

    def on_browse_files(self, _widget):
        """Callback to open a game folder in the file browser"""
        path = self.game.get_browse_dir()
        if not path:
            dialogs.NoticeDialog("This game has no installation directory")
        elif path_exists(path):
            open_uri("file://%s" % path)
        else:
            dialogs.NoticeDialog("Can't open %s \nThe folder doesn't exist." %
                                 path)

    def on_create_menu_shortcut(self, *_args):
        """Add the selected game to the system's Games menu."""
        xdgshortcuts.create_launcher(self.game.slug,
                                     self.game.id,
                                     self.game.name,
                                     menu=True)

    def on_create_desktop_shortcut(self, *_args):
        """Create a desktop launcher for the selected game."""
        xdgshortcuts.create_launcher(self.game.slug,
                                     self.game.id,
                                     self.game.name,
                                     desktop=True)

    def on_remove_menu_shortcut(self, *_args):
        """Remove an XDG menu shortcut"""
        xdgshortcuts.remove_launcher(self.game.slug, self.game.id, menu=True)

    def on_remove_desktop_shortcut(self, *_args):
        """Remove a .desktop shortcut"""
        xdgshortcuts.remove_launcher(self.game.slug,
                                     self.game.id,
                                     desktop=True)

    def on_view_game(self, _widget):
        """Callback to open a game on lutris.net"""
        open_uri("https://lutris.net/games/%s" % self.game.slug)

    def on_remove_game(self, *_args):
        """Callback that present the uninstall dialog to the user"""
        UninstallGameDialog(game_id=self.game.id,
                            callback=self.window.remove_game_from_view,
                            parent=self.window)
Пример #4
0
class GameActions:
    """Regroup a list of callbacks for a game"""
    def __init__(self, application=None, window=None):
        self.application = application or Gio.Application.get_default()
        self.window = window
        self.game_id = None
        self._game = None

    @property
    def game(self):
        if not self._game:
            self._game = self.application.get_game_by_id(self.game_id)
            if not self._game:
                self._game = Game(self.game_id)
            self._game.connect("game-error", self.window.on_game_error)
        return self._game

    @property
    def is_game_running(self):
        return bool(self.application.get_game_by_id(self.game_id))

    def set_game(self, game=None, game_id=None):
        if game:
            self._game = game
            self.game_id = game.id
        else:
            self._game = None
            self.game_id = game_id

    def get_game_actions(self):
        """Return a list of game actions and their callbacks"""
        return [
            (
                "play", "Play",
                self.on_game_run
            ),
            (
                "stop", "Stop",
                self.on_stop
            ),
            (
                "show_logs", "Show logs",
                self.on_show_logs
            ),
            (
                "install", "Install",
                self.on_install_clicked
            ),
            (
                "add", "Add installed game",
                self.on_add_manually
            ),
            (
                "configure", "Configure",
                self.on_edit_game_configuration
            ),
            (
                "execute-script", "Execute script",
                self.on_execute_script_clicked
            ),
            (
                "browse", "Browse files",
                self.on_browse_files
            ),
            (
                "desktop-shortcut", "Create desktop shortcut",
                self.on_create_desktop_shortcut,
            ),
            (
                "rm-desktop-shortcut", "Delete desktop shortcut",
                self.on_remove_desktop_shortcut,
            ),
            (
                "menu-shortcut", "Create application menu shortcut",
                self.on_create_menu_shortcut,
            ),
            (
                "rm-menu-shortcut", "Delete application menu shortcut",
                self.on_remove_menu_shortcut,
            ),
            (
                "install_more", "Install another version",
                self.on_install_clicked
            ),
            (
                "remove", "Remove",
                self.on_remove_game
            ),
            (
                "view", "View on Lutris.net",
                self.on_view_game
            ),
        ]

    def get_displayed_entries(self):
        """Return a dictionary of actions that should be shown for a game"""
        return {
            "add": not self.game.is_installed and not self.game.is_search_result,
            "install": not self.game.is_installed,
            "play": self.game.is_installed and not self.is_game_running,
            "stop": self.is_game_running,
            "show_logs": self.game.is_installed,
            "configure": bool(self.game.is_installed),
            "install_more": self.game.is_installed and not self.game.is_search_result,
            "execute-script": bool(
                self.game.is_installed
                and self.game.runner.system_config.get("manual_command")
            ),
            "desktop-shortcut": (
                self.game.is_installed
                and not xdgshortcuts.desktop_launcher_exists(self.game.slug, self.game.id)
            ),
            "menu-shortcut": (
                self.game.is_installed
                and not xdgshortcuts.menu_launcher_exists(self.game.slug, self.game.id)
            ),
            "rm-desktop-shortcut": bool(
                self.game.is_installed
                and xdgshortcuts.desktop_launcher_exists(self.game.slug, self.game.id)
            ),
            "rm-menu-shortcut": bool(
                self.game.is_installed
                and xdgshortcuts.menu_launcher_exists(self.game.slug, self.game.id)
            ),
            "browse": self.game.is_installed and self.game.runner_name != "browser",
            "remove": not self.game.is_search_result,
            "view": True
        }

    def on_game_run(self, *_args):
        """Launch a game"""
        self.application.launch(self.game)

    def get_running_game(self):
        for i in range(self.application.running_games.get_n_items()):
            game = self.application.running_games.get_item(i)
            if game == self.game:
                return game

    def on_stop(self, caller):
        """Stops the game"""

        matched_game = self.get_running_game()
        if not matched_game:
            logger.warning("%s not in running game list", self.game_id)
            return

        try:
            os.kill(matched_game.game_thread.game_process.pid, signal.SIGTERM)
        except ProcessLookupError:
            pass
        logger.debug("Removed game with ID %s from running games", self.game_id)

    def on_show_logs(self, _widget):
        """Display game log"""
        return LogWindow(
            title="Log for {}".format(self.game),
            buffer=self.game.log_buffer,
            application=self.application
        )

    def on_install_clicked(self, *_args):
        """Install a game"""
        # Install the currently selected game in the UI
        return InstallerWindow(
            parent=self.window,
            game_slug=self.game.slug,
            application=self.application,
        )

    def on_add_manually(self, _widget, *_args):
        """Callback that presents the Add game dialog"""
        AddGameDialog(self.window, game=self.game, runner=self.game.runner_name)

    def on_edit_game_configuration(self, _widget):
        """Edit game preferences"""
        EditGameConfigDialog(self.window, self.game)

    def on_execute_script_clicked(self, _widget):
        """Execute the game's associated script"""
        manual_command = self.game.runner.system_config.get("manual_command")
        if path_exists(manual_command):
            MonitoredCommand(
                [manual_command],
                include_processes=[os.path.basename(manual_command)],
                cwd=self.game.directory,
            ).start()
            logger.info("Running %s in the background", manual_command)

    def on_browse_files(self, _widget):
        """Callback to open a game folder in the file browser"""
        path = self.game.get_browse_dir()
        if not path:
            dialogs.NoticeDialog("This game has no installation directory")
        elif path_exists(path):
            open_uri("file://%s" % path)
        else:
            dialogs.NoticeDialog("Can't open %s \nThe folder doesn't exist." % path)

    def on_create_menu_shortcut(self, *_args):
        """Add the selected game to the system's Games menu."""
        xdgshortcuts.create_launcher(self.game.slug, self.game.id, self.game.name, menu=True)

    def on_create_desktop_shortcut(self, *_args):
        """Create a desktop launcher for the selected game."""
        xdgshortcuts.create_launcher(self.game.slug, self.game.id, self.game.name, desktop=True)

    def on_remove_menu_shortcut(self, *_args):
        """Remove an XDG menu shortcut"""
        xdgshortcuts.remove_launcher(self.game.slug, self.game.id, menu=True)

    def on_remove_desktop_shortcut(self, *_args):
        """Remove a .desktop shortcut"""
        xdgshortcuts.remove_launcher(self.game.slug, self.game.id, desktop=True)

    def on_view_game(self, _widget):
        """Callback to open a game on lutris.net"""
        open_uri("https://lutris.net/games/%s" % self.game.slug)

    def on_remove_game(self, *_args):
        """Callback that present the uninstall dialog to the user"""
        UninstallGameDialog(
            game_id=self.game.id, callback=self.window.remove_game_from_view, parent=self.window
        )
Пример #5
0
class GameActions:
    """Regroup a list of callbacks for a game"""
    def __init__(self, application=None, window=None):
        self.application = application or Gio.Application.get_default()
        self.window = window
        self.game_id = None
        self._game = None

    @property
    def game(self):
        if not self._game:
            self._game = self.application.get_game_by_id(self.game_id)
            if not self._game:
                self._game = Game(self.game_id)
            self._game.connect("game-error", self.window.on_game_error)
            self._game.connect("game-stop", self.on_stop)
        return self._game

    @property
    def is_game_running(self):
        return bool(self.application.get_game_by_id(self.game_id))

    def set_game(self, game=None, game_id=None):
        if game:
            self._game = game
            self.game_id = game.id
        else:
            self._game = None
            self.game_id = game_id

    def get_game_actions(self):
        """Return a list of game actions and their callbacks"""
        return [
            ("play", "Play", self.on_game_run),
            ("stop", "Stop", self.on_stop),
            ("show_logs", "Show logs", self.on_show_logs),
            ("install", "Install", self.on_install_clicked),
            ("add", "Add installed game", self.on_add_manually),
            ("configure", "Configure", self.on_edit_game_configuration),
            ("execute-script", "Execute script",
             self.on_execute_script_clicked),
            ("browse", "Browse files", self.on_browse_files),
            (
                "desktop-shortcut",
                "Create desktop shortcut",
                self.on_create_desktop_shortcut,
            ),
            (
                "rm-desktop-shortcut",
                "Delete desktop shortcut",
                self.on_remove_desktop_shortcut,
            ),
            (
                "menu-shortcut",
                "Create application menu shortcut",
                self.on_create_menu_shortcut,
            ),
            (
                "rm-menu-shortcut",
                "Delete application menu shortcut",
                self.on_remove_menu_shortcut,
            ),
            ("install_more", "Install another version",
             self.on_install_clicked),
            ("remove", "Remove", self.on_remove_game),
            ("view", "View on Lutris.net", self.on_view_game),
        ]

    def get_displayed_entries(self):
        """Return a dictionary of actions that should be shown for a game"""
        return {
            "add":
            not self.game.is_installed,
            "install":
            not self.game.is_installed,
            "play":
            self.game.is_installed and not self.is_game_running,
            "stop":
            self.is_game_running,
            "show_logs":
            self.is_game_running,
            "configure":
            bool(self.game.is_installed),
            "install_more":
            self.game.is_installed,
            "execute-script":
            bool(self.game.is_installed
                 and self.game.runner.system_config.get("manual_command")),
            "desktop-shortcut": (self.game.is_installed
                                 and not xdgshortcuts.desktop_launcher_exists(
                                     self.game.slug, self.game.id)),
            "menu-shortcut": (self.game.is_installed
                              and not xdgshortcuts.menu_launcher_exists(
                                  self.game.slug, self.game.id)),
            "rm-desktop-shortcut":
            bool(self.game.is_installed
                 and xdgshortcuts.desktop_launcher_exists(
                     self.game.slug, self.game.id)),
            "rm-menu-shortcut":
            bool(self.game.is_installed and xdgshortcuts.menu_launcher_exists(
                self.game.slug, self.game.id)),
            "browse":
            self.game.is_installed and self.game.runner_name != "browser",
            "remove":
            self.game.is_installed,
            "view":
            True
        }

    def get_disabled_entries(self):
        """Return a dictionary of actions that should be disabled for a game"""
        return {}

    def on_game_run(self, *_args):
        """Launch a game"""
        self.application.launch(self.game)

    def on_stop(self, caller):
        """Stops the game"""
        try:
            game = self.application.running_games.pop(
                self.application.running_games.index(self.game))
            os.kill(game.game_thread.game_process.pid, signal.SIGKILL)
        except ValueError:
            logger.warning("%s not in running game list", self.game_id)
        else:
            logger.debug("Removed game with ID %s from running games",
                         self.game_id)

    def on_show_logs(self, _widget):
        """Display game log in a LogDialog"""
        log_title = u"Log for {}".format(self.game)
        log_window = LogDialog(title=log_title,
                               buffer=self.game.log_buffer,
                               parent=self.window)
        log_window.run()
        log_window.destroy()

    def on_install_clicked(self, *_args):
        """Install a game"""
        # Install the currently selected game in the UI
        return InstallerWindow(
            parent=self.window,
            game_slug=self.game.slug,
            application=self.application,
        )

    def on_add_manually(self, _widget, *_args):
        """Callback that presents the Add game dialog"""
        def on_game_added(game):
            self.window.view.set_installed(game)
            GLib.idle_add(resources.fetch_icon, game.slug,
                          self.window.on_image_downloaded)
            self.window.sidebar_listbox.update()

        AddGameDialog(
            self.window,
            game=self.game,
            runner=self.game.runner_name,
            callback=lambda: on_game_added(self.game),
        )

    def on_edit_game_configuration(self, _widget):
        """Edit game preferences"""
        def on_dialog_saved():
            game_id = dialog.game.id
            self.window.view.remove_game(game_id)
            self.window.view.add_game_by_id(game_id)
            self.window.view.set_selected_game(game_id)
            self.window.sidebar_listbox.update()

        dialog = EditGameConfigDialog(self.window, self.game, on_dialog_saved)

    def on_execute_script_clicked(self, _widget):
        """Execute the game's associated script"""
        manual_command = self.game.runner.system_config.get("manual_command")
        if path_exists(manual_command):
            MonitoredCommand(
                [manual_command],
                include_processes=[os.path.basename(manual_command)],
                cwd=self.game.directory,
            ).start()
            logger.info("Running %s in the background", manual_command)

    def on_browse_files(self, _widget):
        """Callback to open a game folder in the file browser"""
        path = self.game.get_browse_dir()
        if path and os.path.exists(path):
            open_uri("file://%s" % path)
        else:
            dialogs.NoticeDialog("Can't open %s \nThe folder doesn't exist." %
                                 path)

    def on_create_menu_shortcut(self, *_args):
        """Add the selected game to the system's Games menu."""
        xdgshortcuts.create_launcher(self.game.slug,
                                     self.game.id,
                                     self.game.name,
                                     menu=True)

    def on_create_desktop_shortcut(self, *_args):
        """Create a desktop launcher for the selected game."""
        xdgshortcuts.create_launcher(self.game.slug,
                                     self.game.id,
                                     self.game.name,
                                     desktop=True)

    def on_remove_menu_shortcut(self, *_args):
        """Remove an XDG menu shortcut"""
        xdgshortcuts.remove_launcher(self.game.slug, self.game.id, menu=True)

    def on_remove_desktop_shortcut(self, *_args):
        """Remove a .desktop shortcut"""
        xdgshortcuts.remove_launcher(self.game.slug,
                                     self.game.id,
                                     desktop=True)

    def on_view_game(self, _widget):
        """Callback to open a game on lutris.net"""
        open_uri("https://lutris.net/games/%s" % self.game.slug)

    def on_remove_game(self, *_args):
        """Callback that present the uninstall dialog to the user"""
        UninstallGameDialog(game_id=self.game.id,
                            callback=self.window.remove_game_from_view,
                            parent=self.window)
Пример #6
0
class GameActions:
    """Regroup a list of callbacks for a game"""
    def __init__(self, application=None, window=None):
        self.application = application or Gio.Application.get_default()
        self.window = window
        self.game_id = None
        self._game = None

    @property
    def game(self):
        if not self._game:
            self._game = self.application.get_game_by_id(self.game_id)
            if not self._game:
                self._game = Game(self.game_id)
            self._game.connect("game-error", self.window.on_game_error)
        return self._game

    @property
    def is_game_running(self):
        return bool(self.application.get_game_by_id(self.game_id))

    def set_game(self, game=None, game_id=None):
        if game:
            self._game = game
            self.game_id = game.id
        else:
            self._game = None
            self.game_id = game_id

    def get_game_actions(self):
        """Return a list of game actions and their callbacks"""
        return [
            ("play", _("Play"), self.on_game_launch),
            ("stop", _("Stop"), self.on_game_stop),
            ("show_logs", _("Show logs"), self.on_show_logs),
            ("install", _("Install"), self.on_install_clicked),
            ("add", _("Add installed game"), self.on_add_manually),
            ("configure", _("Configure"), self.on_edit_game_configuration),
            ("favorite", _("Add to favorites"), self.on_add_favorite_game),
            ("deletefavorite", _("Remove from favorites"),
             self.on_delete_favorite_game),
            ("execute-script", _("Execute script"),
             self.on_execute_script_clicked),
            ("browse", _("Browse files"), self.on_browse_files),
            (
                "desktop-shortcut",
                _("Create desktop shortcut"),
                self.on_create_desktop_shortcut,
            ),
            (
                "rm-desktop-shortcut",
                _("Delete desktop shortcut"),
                self.on_remove_desktop_shortcut,
            ),
            (
                "menu-shortcut",
                _("Create application menu shortcut"),
                self.on_create_menu_shortcut,
            ),
            (
                "rm-menu-shortcut",
                _("Delete application menu shortcut"),
                self.on_remove_menu_shortcut,
            ),
            ("install_more", _("Install another version"),
             self.on_install_clicked),
            ("remove", _("Remove"), self.on_remove_game),
            ("view", _("View on Lutris.net"), self.on_view_game),
            ("hide", _("Hide game from library"), self.on_hide_game),
            ("unhide", _("Unhide game from library"), self.on_unhide_game),
        ]

    def get_displayed_entries(self):
        """Return a dictionary of actions that should be shown for a game"""
        return {
            "add":
            not self.game.is_installed,
            "install":
            not self.game.is_installed,
            "play":
            self.game.is_installed and not self.is_game_running,
            "stop":
            self.is_game_running,
            "configure":
            bool(self.game.is_installed),
            "browse":
            self.game.is_installed and self.game.runner_name != "browser",
            "show_logs":
            self.game.is_installed,
            "favorite":
            not self.game.is_favorite,
            "deletefavorite":
            self.game.is_favorite,
            "install_more":
            self.game.is_installed,
            "execute-script":
            bool(self.game.is_installed
                 and self.game.runner.system_config.get("manual_command")),
            "desktop-shortcut": (self.game.is_installed
                                 and not xdgshortcuts.desktop_launcher_exists(
                                     self.game.slug, self.game.id)),
            "menu-shortcut": (self.game.is_installed
                              and not xdgshortcuts.menu_launcher_exists(
                                  self.game.slug, self.game.id)),
            "rm-desktop-shortcut":
            bool(self.game.is_installed
                 and xdgshortcuts.desktop_launcher_exists(
                     self.game.slug, self.game.id)),
            "rm-menu-shortcut":
            bool(self.game.is_installed and xdgshortcuts.menu_launcher_exists(
                self.game.slug, self.game.id)),
            "remove":
            self.game.is_installed,
            "view":
            True,
            "hide":
            not self.game.is_hidden,
            "unhide":
            self.game.is_hidden,
        }

    def on_game_launch(self, *_args):
        """Launch a game"""
        self.game.launch()

    def get_running_game(self):
        ids = self.application.get_running_game_ids()
        for game_id in ids:
            if game_id == self.game.id:
                return self.game
        logger.warning("Game %s not in %s", self.game_id, ids)

    def on_game_stop(self, caller):  # pylint: disable=unused-argument
        """Stops the game"""
        matched_game = self.get_running_game()
        if not matched_game:
            return
        if not matched_game.game_thread:
            logger.warning(
                "Game %s doesn't appear to be running, not killing it",
                self.game_id)
            return
        try:
            os.kill(matched_game.game_thread.game_process.pid, signal.SIGTERM)
        except ProcessLookupError as ex:
            logger.debug("Failed to kill game process: %s", ex)

    def on_show_logs(self, _widget):
        """Display game log"""
        _buffer = LOG_BUFFERS.get(self.game.id)
        if not _buffer:
            logger.info("No log for game %s", self.game)
        return LogWindow(title=_("Log for {}").format(self.game),
                         buffer=_buffer,
                         application=self.application)

    def on_install_clicked(self, *_args):
        """Install a game"""
        # Install the currently selected game in the UI
        installers = get_installers(game_slug=self.game.slug)
        self.application.show_installer_window(installers=installers)

    def on_add_manually(self, _widget, *_args):
        """Callback that presents the Add game dialog"""
        AddGameDialog(self.window,
                      game=self.game,
                      runner=self.game.runner_name)

    def on_edit_game_configuration(self, _widget):
        """Edit game preferences"""
        EditGameConfigDialog(self.window, self.game)

    def on_add_favorite_game(self, _widget):
        """Add to favorite Games list"""
        self.game.add_to_favorites()

    def on_delete_favorite_game(self, _widget):
        """delete from favorites"""
        self.game.remove_from_favorites()

    def on_hide_game(self, _widget):
        """Add a game to the list of hidden games"""
        self.game.hide()

    def on_unhide_game(self, _widget):
        """Removes a game from the list of hidden games"""
        self.game.unhide()

    def on_execute_script_clicked(self, _widget):
        """Execute the game's associated script"""
        manual_command = self.game.runner.system_config.get("manual_command")
        if path_exists(manual_command):
            MonitoredCommand(
                [manual_command],
                include_processes=[os.path.basename(manual_command)],
                cwd=self.game.directory,
            ).start()
            logger.info("Running %s in the background", manual_command)

    def on_browse_files(self, _widget):
        """Callback to open a game folder in the file browser"""
        path = self.game.get_browse_dir()
        if not path:
            dialogs.NoticeDialog(_("This game has no installation directory"))
        elif path_exists(path):
            open_uri("file://%s" % path)
        else:
            dialogs.NoticeDialog(
                _("Can't open %s \nThe folder doesn't exist.") % path)

    def on_create_menu_shortcut(self, *_args):
        """Add the selected game to the system's Games menu."""
        xdgshortcuts.create_launcher(self.game.slug,
                                     self.game.id,
                                     self.game.name,
                                     menu=True)

    def on_create_desktop_shortcut(self, *_args):
        """Create a desktop launcher for the selected game."""
        xdgshortcuts.create_launcher(self.game.slug,
                                     self.game.id,
                                     self.game.name,
                                     desktop=True)

    def on_remove_menu_shortcut(self, *_args):
        """Remove an XDG menu shortcut"""
        xdgshortcuts.remove_launcher(self.game.slug, self.game.id, menu=True)

    def on_remove_desktop_shortcut(self, *_args):
        """Remove a .desktop shortcut"""
        xdgshortcuts.remove_launcher(self.game.slug,
                                     self.game.id,
                                     desktop=True)

    def on_view_game(self, _widget):
        """Callback to open a game on lutris.net"""
        open_uri("https://lutris.net/games/%s" % self.game.slug)

    def on_remove_game(self, *_args):
        """Callback that present the uninstall dialog to the user"""
        UninstallGameDialog(game_id=self.game.id,
                            callback=self.window.update_store,
                            parent=self.window)