def get_pixbuf_for_game(game_slug, icon_type, is_installed=True): if icon_type.startswith("banner"): default_icon_path = os.path.join(datapath.get(), "media/default_banner.png") icon_path = resources.get_banner_path(game_slug) elif icon_type.startswith("icon"): default_icon_path = os.path.join(datapath.get(), "media/default_icon.png") icon_path = resources.get_icon_path(game_slug) else: logger.error("Invalid icon type '%s'", icon_type) return None size = IMAGE_SIZES[icon_type] pixbuf = get_pixbuf(icon_path, size, fallback=default_icon_path) if not is_installed: unavailable_game_overlay = os.path.join(datapath.get(), "media/unavailable.png") transparent_pixbuf = get_overlay(unavailable_game_overlay, size).copy() pixbuf.composite( transparent_pixbuf, 0, 0, size[0], size[1], 0, 0, 1, 1, GdkPixbuf.InterpType.NEAREST, 100, ) return transparent_pixbuf return pixbuf
def __init__(self): Gtk.Application.__init__(self, application_id='net.lutris.Lutris', flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE) gettext.bindtextdomain("lutris", "/usr/share/locale") gettext.textdomain("lutris") check_config() migrate() update_platforms() GLib.set_application_name(_('Lutris')) self.window = None self.css_provider = Gtk.CssProvider.new() try: self.css_provider.load_from_path(os.path.join(datapath.get(), 'ui', 'lutris.css')) except GLib.Error as e: logger.exception(e) if hasattr(self, 'add_main_option'): self.add_arguments() else: ErrorDialog("Your Linux distribution is too old, Lutris won't function properly")
def convert_to_background(background_path, target_size=(320, 1080)): """Converts a image to a pane background""" coverart = Image.open(background_path) coverart = coverart.convert("RGBA") target_width, target_height = target_size image_height = int(target_height * 0.80) # 80% of the mask is visible orig_width, orig_height = coverart.size # Resize and crop coverart width = int(orig_width * (image_height / orig_height)) offset = int((width - target_width) / 2) coverart = coverart.resize((width, image_height), resample=Image.BICUBIC) coverart = coverart.crop((offset, 0, target_width + offset, image_height)) # Resize canvas of coverart by putting transparent pixels on the bottom coverart_bg = Image.new('RGBA', (target_width, target_height), (0, 0, 0, 0)) coverart_bg.paste(coverart, (0, 0, target_width, image_height)) # Apply a tint to the base image # tint = Image.new('RGBA', (target_width, target_height), (0, 0, 0, 255)) # coverart = Image.blend(coverart, tint, 0.6) # Paste coverart on transparent image while applying a gradient mask background = Image.new('RGBA', (target_width, target_height), (0, 0, 0, 0)) mask = Image.open(os.path.join(datapath.get(), "media/mask.png")) background.paste(coverart_bg, mask=mask) return background
def __init__(self): super().__init__( application_id="net.lutris.Lutris", flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE, ) init_lutris() gettext.bindtextdomain("lutris", "/usr/share/locale") gettext.textdomain("lutris") GLib.set_application_name(_("Lutris")) self.running_games = Gio.ListStore.new(Game) self.window = None self.tray = None self.css_provider = Gtk.CssProvider.new() self.run_in_background = False if os.geteuid() == 0: ErrorDialog( "Running Lutris as root is not recommended and may cause unexpected issues" ) try: self.css_provider.load_from_path( os.path.join(datapath.get(), "ui", "lutris.css") ) except GLib.Error as e: logger.exception(e) if hasattr(self, "add_main_option"): self.add_arguments() else: ErrorDialog( "Your Linux distribution is too old. Lutris won't function properly." )
def setup_x360ce(self, x360ce_path): if not os.path.isdir(x360ce_path): logger.error("%s is not a valid path for x360ce", x360ce_path) return mode = 'dumbxinputemu' if self.runner_config.get('dumbxinputemu') else 'x360ce' dll_files = ['xinput1_3.dll'] if self.runner_config.get('x360ce-xinput9'): dll_files.append('xinput9_1_0.dll') for dll_file in dll_files: xinput_dest_path = os.path.join(x360ce_path, dll_file) xinput_arch = self.runner_config.get('xinput-arch') or self.wine_arch dll_path = os.path.join(datapath.get(), 'controllers/{}-{}'.format(mode, xinput_arch)) if not os.path.exists(xinput_dest_path): source_file = dll_file if mode == 'dumbxinputemu' else 'xinput1_3.dll' shutil.copyfile(os.path.join(dll_path, source_file), xinput_dest_path) if mode == 'x360ce': if self.runner_config.get('x360ce-dinput'): dinput8_path = os.path.join(dll_path, 'dinput8.dll') dinput8_dest_path = os.path.join(x360ce_path, 'dinput8.dll') shutil.copyfile(dinput8_path, dinput8_dest_path) x360ce_config = X360ce() x360ce_config.populate_controllers() x360ce_config.write(os.path.join(x360ce_path, 'x360ce.ini'))
def get_builder_from_file(glade_file): ui_filename = os.path.join(datapath.get(), "ui", glade_file) if not os.path.exists(ui_filename): raise ValueError("ui file does not exists: %s" % ui_filename) builder = Gtk.Builder() builder.add_from_file(ui_filename) return builder
def __init__(self): GObject.GObject.__init__(self) self.set_title("Configure runners") self.set_size_request(570, 400) label = Gtk.Label() label.set_markup("<b>Install and configure the game runners</b>") scrolled_window = Gtk.ScrolledWindow() scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self.vbox.pack_start(label, False, True, 20) self.vbox.pack_start(scrolled_window, True, True, 10) close_button = Gtk.Button("Close") close_button.connect('clicked', self.close) self.action_area.pack_start(close_button, False, False, 10) runner_list = lutris.runners.__all__ runner_vbox = Gtk.VBox() for runner_name in runner_list: # Get runner details runner = import_runner(runner_name)() platform = runner.platform description = runner.description hbox = Gtk.HBox() #Icon icon_path = os.path.join(datapath.get(), 'media/runner_icons', runner_name + '.png') icon = Gtk.Image() icon.set_from_file(icon_path) hbox.pack_start(icon, False, False, 10) #Label runner_label = Gtk.Label() runner_label.set_markup( "<b>%s</b>\n%s\n <i>Supported platforms : %s</i>" % (runner_name, description, platform) ) runner_label.set_width_chars(38) runner_label.set_line_wrap(True) runner_label.set_alignment(0.0, 0.0) runner_label.set_padding(25, 5) hbox.pack_start(runner_label, True, True, 5) #Button button = Gtk.Button() button.set_size_request(100, 30) button_align = Gtk.Alignment.new(0.0, 1.0, 0.0, 0.0) self.configure_button(button, runner) button_align.add(button) hbox.pack_start(button_align, True, False, 5) runner_vbox.pack_start(hbox, True, True, 5) scrolled_window.add_with_viewport(runner_vbox) self.show_all()
def get_pixbuf_for_panel(game_slug): """Return the pixbuf for the game panel background""" source_path = os.path.join(settings.COVERART_PATH, "%s.jpg" % game_slug) if not os.path.exists(source_path): source_path = os.path.join(datapath.get(), "media/generic-panel-bg.png") dest_path = os.path.join(settings.CACHE_DIR, "panel_bg.png") background = convert_to_background(source_path) background.save(dest_path) return dest_path
def get_runner_icon(runner_name, format='image', size=None): icon_path = os.path.join(datapath.get(), 'media/runner_icons', runner_name + '.png') if format == 'image': icon = Gtk.Image() icon.set_from_file(icon_path) elif format == 'pixbuf' and size: icon = GdkPixbuf.Pixbuf.new_from_file_at_size(icon_path, size[0], size[1]) else: raise ValueError("Invalid arguments") return icon
def do_startup(self): Gtk.Application.do_startup(self) signal.signal(signal.SIGINT, signal.SIG_DFL) action = Gio.SimpleAction.new('quit') action.connect('activate', lambda *x: self.quit()) self.add_action(action) self.add_accelerator('<Primary>q', 'app.quit') builder = Gtk.Builder.new_from_file(os.path.join(datapath.get(), 'ui', 'menus-traditional.ui')) menubar = builder.get_object('menubar') self.set_menubar(menubar)
def do_startup(self): Gtk.Application.do_startup(self) signal.signal(signal.SIGINT, signal.SIG_DFL) action = Gio.SimpleAction.new('quit') action.connect('activate', lambda *x: self.quit()) self.add_action(action) builder = Gtk.Builder.new_from_file( os.path.join(datapath.get(), 'ui', 'menus-traditional.ui')) menubar = builder.get_object('menubar') self.set_menubar(menubar)
def __init__(self, **kwargs): super(GtkBuilderDialog, self).__init__() ui_filename = os.path.join(datapath.get(), 'ui', self.glade_file) if not os.path.exists(ui_filename): raise ValueError("ui file does not exists: %s" % ui_filename) self.builder = Gtk.Builder() self.builder.add_from_file(ui_filename) self.dialog = self.builder.get_object(self.dialog_object) self.builder.connect_signals(self) self.dialog.show_all() self.initialize(**kwargs)
def winetricks(app, prefix=None, winetricks_env=None, silent=True, blocking=False): """Execute winetricks.""" path = (system.find_executable('winetricks') or os.path.join(datapath.get(), 'bin/winetricks')) arch = detect_prefix_arch(prefix) or 'win32' if not winetricks_env: winetricks_env = wine().get_executable() if str(silent).lower() in ('yes', 'on', 'true'): args = "-q " + app else: args = app wineexec(None, prefix=prefix, winetricks_env=winetricks_env, wine_path=path, arch=arch, args=args, blocking=blocking)
def winetricks(app, prefix=None, arch=None, silent=True, wine_path=None, config=None): """Execute winetricks.""" winetricks_path = os.path.join(datapath.get(), 'bin/winetricks') if arch not in ('win32', 'win64'): arch = detect_prefix_arch(prefix) or 'win32' if wine_path: winetricks_wine = wine_path else: winetricks_wine = wine().get_executable() args = app if str(silent).lower() in ('yes', 'on', 'true'): args = "--unattended " + args return wineexec(None, prefix=prefix, winetricks_wine=winetricks_wine, wine_path=winetricks_path, arch=arch, args=args, config=config)
def get_runner_icon(runner_name, format='image', size=None): icon_path = os.path.join(datapath.get(), 'media/runner_icons', runner_name + '.png') if not os.path.exists(icon_path): logger.error("Unable to find icon '%s'", icon_path) return if format == 'image': icon = Gtk.Image() icon.set_from_file(icon_path) elif format == 'pixbuf' and size: icon = get_pixbuf(icon_path, None, size) else: raise ValueError("Invalid arguments") return icon
def winetricks(app, prefix=None, arch=None, silent=True, wine_path=None): """Execute winetricks.""" winetricks_path = os.path.join(datapath.get(), 'bin/winetricks') if arch not in ('win32', 'win64'): arch = detect_prefix_arch(prefix) or 'win32' if wine_path: winetricks_wine = wine_path else: winetricks_wine = wine().get_executable() args = app if str(silent).lower() in ('yes', 'on', 'true'): args = "-q " + args return wineexec(None, prefix=prefix, winetricks_wine=winetricks_wine, wine_path=winetricks_path, arch=arch, args=args)
def get_pixbuf_for_game(game_slug, image_type, is_installed=True): icon_path = "" default_icon_path = "" if ImageType.banner & image_type: default_icon_path = os.path.join(datapath.get(), "media/default_banner.png") icon_path = resources.get_banner_path(game_slug) if ImageType.icon == image_type: default_icon_path = os.path.join(datapath.get(), "media/default_icon.png") icon_path = resources.get_icon_path(game_slug) size = IMAGE_SIZES[image_type] pixbuf = get_pixbuf(icon_path, size, fallback=default_icon_path) if not is_installed: unavailable_game_overlay = os.path.join(datapath.get(), "media/unavailable.png") transparent_pixbuf = get_overlay(unavailable_game_overlay, size).copy() pixbuf.composite( transparent_pixbuf, 0, 0, size[0], size[1], 0, 0, 1, 1, GdkPixbuf.InterpType.NEAREST, 100, ) return transparent_pixbuf return pixbuf
def __init__(self, parent=None, **kwargs): super().__init__() ui_filename = os.path.join(datapath.get(), "ui", self.glade_file) if not os.path.exists(ui_filename): raise ValueError("ui file does not exists: %s" % ui_filename) self.builder = Gtk.Builder() self.builder.add_from_file(ui_filename) self.dialog = self.builder.get_object(self.dialog_object) self.builder.connect_signals(self) if parent: self.dialog.set_transient_for(parent) self.dialog.show_all() self.dialog.connect("delete-event", lambda *x: x[0].destroy()) self.initialize(**kwargs)
def winetricks(app, prefix=None, arch=None, silent=True, wine_path=None, config=None, disable_runtime=False): """Execute winetricks.""" winetricks_path = os.path.join(datapath.get(), 'bin/winetricks') if wine_path: winetricks_wine = wine_path else: winetricks_wine = wine().get_executable() if arch not in ('win32', 'win64'): arch = detect_arch(prefix, winetricks_wine) args = app if str(silent).lower() in ('yes', 'on', 'true'): args = "--unattended " + args return wineexec(None, prefix=prefix, winetricks_wine=winetricks_wine, wine_path=winetricks_path, arch=arch, args=args, config=config, disable_runtime=disable_runtime)
def do_startup(self): Gtk.Application.do_startup(self) signal.signal(signal.SIGINT, signal.SIG_DFL) action = Gio.SimpleAction.new("quit") action.connect("activate", lambda *x: self.quit()) self.add_action(action) self.add_accelerator("<Primary>q", "app.quit") builder = Gtk.Builder.new_from_file( os.path.join(datapath.get(), "ui", "menus.ui")) appmenu = builder.get_object("app-menu") self.set_app_menu(appmenu) menubar = builder.get_object("menubar") self.set_menubar(menubar)
def setup_x360ce(self, x360ce_path): if not os.path.isdir(x360ce_path): logger.error("%s is not a valid path for x360ce", x360ce_path) return xinput_dest_path = os.path.join(x360ce_path, 'xinput1_3.dll') dll_path = os.path.join(datapath.get(), 'controllers/x360ce-{}'.format(self.wine_arch)) if not os.path.exists(xinput_dest_path): xinput1_3_path = os.path.join(dll_path, 'xinput1_3.dll') shutil.copyfile(xinput1_3_path, xinput_dest_path) if self.runner_config.get('x360ce-dinput') and self.wine_arch == 'win32': dinput8_path = os.path.join(dll_path, 'dinput8.dll') dinput8_dest_path = os.path.join(x360ce_path, 'dinput8.dll') shutil.copyfile(dinput8_path, dinput8_dest_path) x360ce_config = X360ce() x360ce_config.populate_controllers() x360ce_config.write(os.path.join(x360ce_path, 'x360ce.ini'))
def do_startup(self): Gtk.Application.do_startup(self) signal.signal(signal.SIGINT, signal.SIG_DFL) action = Gio.SimpleAction.new("quit") action.connect("activate", lambda *x: self.quit()) self.add_action(action) self.add_accelerator("<Primary>q", "app.quit") builder = Gtk.Builder.new_from_file( os.path.join(datapath.get(), "ui", "menus.ui") ) appmenu = builder.get_object("app-menu") self.set_app_menu(appmenu) menubar = builder.get_object("menubar") self.set_menubar(menubar)
def __init__(self): super().__init__( application_id="net.lutris.Lutris", flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE, ) GObject.add_emission_hook(Game, "game-launch", self.on_game_launch) GObject.add_emission_hook(Game, "game-start", self.on_game_start) GObject.add_emission_hook(Game, "game-stop", self.on_game_stop) GObject.add_emission_hook(Game, "game-install", self.on_game_install) GLib.set_application_name(_("Lutris")) self.window = None try: init_lutris() except RuntimeError as ex: ErrorDialog(str(ex)) return self.running_games = Gio.ListStore.new(Game) self.app_windows = {} self.tray = None self.css_provider = Gtk.CssProvider.new() self.run_in_background = False if os.geteuid() == 0: ErrorDialog( _("Running Lutris as root is not recommended and may cause unexpected issues" )) try: self.css_provider.load_from_path( os.path.join(datapath.get(), "ui", "lutris.css")) except GLib.Error as e: logger.exception(e) if hasattr(self, "add_main_option"): self.add_arguments() else: ErrorDialog( _("Your Linux distribution is too old. Lutris won't function properly." ))
def winetricks(app, prefix=None, arch=None, silent=True, wine_path=None, config=None, disable_runtime=False): """Execute winetricks.""" winetricks_path = os.path.join(settings.RUNTIME_DIR, 'winetricks/winetricks') if not system.path_exists(winetricks_path): logger.warning("Could not find local winetricks install, falling back to bundled version") winetricks_path = os.path.join(datapath.get(), 'bin/winetricks') if wine_path: winetricks_wine = wine_path else: winetricks_wine = wine().get_executable() if arch not in ('win32', 'win64'): arch = detect_arch(prefix, winetricks_wine) args = app if str(silent).lower() in ('yes', 'on', 'true'): args = "--unattended " + args return wineexec(None, prefix=prefix, winetricks_wine=winetricks_wine, wine_path=winetricks_path, arch=arch, args=args, config=config, disable_runtime=disable_runtime)
def __init__(self): super().__init__( application_id="net.lutris.Lutris", flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE, ) logger.info("Running Lutris %s", settings.VERSION) set_child_subreaper() gettext.bindtextdomain("lutris", "/usr/share/locale") gettext.textdomain("lutris") check_config() migrate() update_platforms() check_driver() check_libs() check_vulkan() GLib.set_application_name(_("Lutris")) self.running_games = [] self.window = None self.help_overlay = None self.tray = None self.css_provider = Gtk.CssProvider.new() if os.geteuid() == 0: ErrorDialog( "Running Lutris as root is not recommended and may cause unexpected issues" ) try: self.css_provider.load_from_path( os.path.join(datapath.get(), "ui", "lutris.css") ) except GLib.Error as e: logger.exception(e) if hasattr(self, "add_main_option"): self.add_arguments() else: ErrorDialog( "Your Linux distribution is too old, Lutris won't function properly" )
def __init__(self): super().__init__() self.get_style_context().add_class("sidebar") self.installed_runners = [] self.active_platforms = pga.get_used_platforms() self.runners = sorted(runners.__all__) self.platforms = sorted(platforms.__all__) GObject.add_emission_hook(RunnersDialog, "runner-installed", self.update) GObject.add_emission_hook(RunnersDialog, "runner-removed", self.update) GObject.add_emission_hook(Game, "game-updated", self.update) GObject.add_emission_hook(Game, "game-removed", self.update) # TODO: This should be in a more logical location icon_theme = Gtk.IconTheme.get_default() local_theme_path = os.path.join(datapath.get(), "icons") if local_theme_path not in icon_theme.get_search_path(): icon_theme.prepend_search_path(local_theme_path) all_row = SidebarRow(None, "runner", "All", None) self.add(all_row) self.select_row(all_row) for runner in self.runners: icon = Gtk.Image.new_from_icon_name( runner.lower().replace(" ", "") + "-symbolic", Gtk.IconSize.MENU) name = runners.import_runner(runner).human_name self.add(SidebarRow(runner, "runner", name, icon)) self.add(SidebarRow(None, "platform", "All", None)) for platform in self.platforms: icon_name = (platform.lower().replace(" ", "").replace("/", "_") + "-symbolic") icon = Gtk.Image.new_from_icon_name(icon_name, Gtk.IconSize.MENU) self.add(SidebarRow(platform, "platform", platform, icon)) self.set_filter_func(self._filter_func) self.set_header_func(self._header_func) self.update() self.show_all()
def winetricks( app, prefix=None, arch=None, silent=True, wine_path=None, config=None, disable_runtime=False, ): """Execute winetricks.""" wine_config = config or LutrisConfig(runner_slug="wine") system_winetricks = wine_config.runner_config.get("system_winetricks") if system_winetricks: winetricks_path = "/usr/bin/winetricks" else: winetricks_path = os.path.join(settings.RUNTIME_DIR, "winetricks/winetricks") if not system.path_exists(winetricks_path): logger.warning( "Could not find local winetricks install, falling back to bundled version" ) winetricks_path = os.path.join(datapath.get(), "bin/winetricks") if wine_path: winetricks_wine = wine_path else: wine = import_runner("wine") winetricks_wine = wine().get_executable() if arch not in ("win32", "win64"): arch = detect_arch(prefix, winetricks_wine) args = app if str(silent).lower() in ("yes", "on", "true"): args = "--unattended " + args return wineexec( None, prefix=prefix, winetricks_wine=winetricks_wine, wine_path=winetricks_path, arch=arch, args=args, config=config, disable_runtime=disable_runtime, )
def __init__(self): Gtk.Application.__init__( self, application_id='net.lutris.Lutris', flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE) GLib.set_application_name(_('Lutris')) self.window = None self.css_provider = Gtk.CssProvider.new() try: self.css_provider.load_from_path( os.path.join(datapath.get(), 'ui', 'log-window.css')) except GLib.Error as e: logger.exception(e) if hasattr(self, 'add_main_option'): self.add_arguments() else: ErrorDialog( "Your Linux distribution is too old, Lutris won't function properly" )
def setup_x360ce(self, x360ce_path): if not x360ce_path: return x360ce_path = os.path.expanduser(x360ce_path) if not os.path.isdir(x360ce_path): logger.error("%s is not a valid path for x360ce", x360ce_path) return mode = 'dumbxinputemu' if self.runner_config.get( 'dumbxinputemu') else 'x360ce' dll_files = ['xinput1_3.dll'] if self.runner_config.get('x360ce-xinput9'): dll_files.append('xinput9_1_0.dll') for dll_file in dll_files: xinput_dest_path = os.path.join(x360ce_path, dll_file) xinput_arch = self.runner_config.get( 'xinput-arch') or self.wine_arch dll_path = os.path.join( datapath.get(), 'controllers/{}-{}'.format(mode, xinput_arch)) if not os.path.exists(xinput_dest_path): source_file = dll_file if mode == 'dumbxinputemu' else 'xinput1_3.dll' shutil.copyfile(os.path.join(dll_path, source_file), xinput_dest_path) if mode == 'x360ce': if self.runner_config.get('x360ce-dinput'): dinput8_path = os.path.join(dll_path, 'dinput8.dll') dinput8_dest_path = os.path.join(x360ce_path, 'dinput8.dll') shutil.copyfile(dinput8_path, dinput8_dest_path) x360ce_config = X360ce() x360ce_config.populate_controllers() x360ce_config.write(os.path.join(x360ce_path, 'x360ce.ini')) # X360 DLL handling self.dll_overrides['xinput1_3'] = 'native' if self.runner_config.get('x360ce-xinput9'): self.dll_overrides['xinput9_1_0'] = 'native' if self.runner_config.get('x360ce-dinput'): self.dll_overrides['dinput8'] = 'native'
def get_pixbuf(image, size, fallback=None, is_installed=True): """Return a pixbuf from file `image` at `size` or fallback to `fallback`""" width, height = size pixbuf = None if system.path_exists(image, exclude_empty=True): try: pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( image, width, height) pixbuf = pixbuf.scale_simple(width, height, GdkPixbuf.InterpType.NEAREST) except GLib.GError: logger.error("Unable to load icon from image %s", image) else: if not fallback: fallback = get_default_icon(size) if system.path_exists(fallback): pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( fallback, width, height) if is_installed and pixbuf: pixbuf = pixbuf.scale_simple(width, height, GdkPixbuf.InterpType.NEAREST) return pixbuf overlay = os.path.join(datapath.get(), "media/unavailable.png") transparent_pixbuf = get_overlay(overlay, size).copy() if pixbuf: pixbuf.composite( transparent_pixbuf, 0, 0, size[0], size[1], 0, 0, 1, 1, GdkPixbuf.InterpType.NEAREST, 100, ) return transparent_pixbuf
def get_pixbuf_for_game(image_abspath, size, is_installed=True): # icon_path = resources.get_icon_path(game_slug) pixbuf = get_pixbuf(image_abspath, size, fallback=get_default_icon(size)) if not is_installed: unavailable_game_overlay = os.path.join(datapath.get(), "media/unavailable.png") transparent_pixbuf = get_overlay(unavailable_game_overlay, size).copy() pixbuf.composite( transparent_pixbuf, 0, 0, size[0], size[1], 0, 0, 1, 1, GdkPixbuf.InterpType.NEAREST, 100, ) return transparent_pixbuf return pixbuf
def get_runner_hbox(self, runner_name): # Get runner details runner = import_runner(runner_name)() platform = runner.platform description = runner.description hbox = Gtk.HBox() # Icon icon_path = os.path.join(datapath.get(), 'media/runner_icons', runner_name + '.png') icon = Gtk.Image() icon.set_from_file(icon_path) icon.set_alignment(0.5, 0.1) hbox.pack_start(icon, False, False, 10) # Label runner_label = Gtk.Label() if not runner.is_installed(): runner_label.set_sensitive(False) runner_label.set_markup( "<b>%s</b>\n%s\n <i>Supported platforms : %s</i>" % (runner.human_name, description, platform) ) runner_label.set_width_chars(40) runner_label.set_max_width_chars(40) runner_label.set_property('wrap', True) runner_label.set_line_wrap(True) runner_label.set_alignment(0.0, 0.1) runner_label.set_padding(5, 0) self.runner_labels[runner] = runner_label hbox.pack_start(runner_label, True, True, 5) # Button button = Gtk.Button() button.set_size_request(100, 30) button_align = Gtk.Alignment.new(1.0, 0.0, 0.0, 0.0) self.configure_button(button, runner) button_align.add(button) hbox.pack_start(button_align, False, False, 15) return hbox
def __init__(self): super().__init__() self.get_style_context().add_class("sidebar") self.installed_runners = [] self.active_platforms = pga.get_used_platforms() self.runners = sorted(runners.__all__) self.platforms = sorted(platforms.__all__) GObject.add_emission_hook(RunnersDialog, "runner-installed", self.update) GObject.add_emission_hook(RunnersDialog, "runner-removed", self.update) GObject.add_emission_hook(Game, "game-updated", self.update) GObject.add_emission_hook(Game, "game-removed", self.update) # TODO: This should be in a more logical location icon_theme = Gtk.IconTheme.get_default() local_theme_path = os.path.join(datapath.get(), "icons") if local_theme_path not in icon_theme.get_search_path(): icon_theme.prepend_search_path(local_theme_path) all_row = SidebarRow(None, "runner", "All", None) self.add(all_row) self.select_row(all_row) for runner in self.runners: icon = Gtk.Image.new_from_icon_name( runner.lower().replace(" ", "") + "-symbolic", Gtk.IconSize.MENU ) name = runners.import_runner(runner).human_name self.add(SidebarRow(runner, "runner", name, icon)) self.add(SidebarRow(None, "platform", "All", None)) for platform in self.platforms: icon_name = platform.lower().replace(" ", "") + "-symbolic" icon = Gtk.Image.new_from_icon_name(icon_name, Gtk.IconSize.MENU) self.add(SidebarRow(platform, "platform", platform, icon)) self.set_filter_func(self._filter_func) self.set_header_func(self._header_func) self.update() self.show_all()
def play(self): launch_info = {} launch_info["env"] = self.get_env(os_env=False) game_data = pga.get_game_by_field(self.config.game_config_id, "configpath") command = self.launch_args if self.is_native: if not self.runner_config.get("splore"): command.append("-run") cartPath = self.cart_path if not os.path.exists(cartPath): return {"error": "FILE_NOT_FOUND", "file": cartPath} command.append(cartPath) else: command.append("--name") command.append(game_data.get("name") + " - PICO-8") icon = datapath.get_icon_path(game_data.get("slug")) if not os.path.exists(icon): icon = os.path.join(datapath.get(), "media/runner_icons/pico8.png") command.append("--icon") command.append(icon) webargs = { "cartridge": self.cart_path, "engine": self.engine_path, "fullscreen": self.runner_config.get("fullscreen") is True, } command.append("--execjs") command.append("load_config(" + json.dumps(webargs) + ")") launch_info["command"] = command return launch_info
def __init__(self): Gtk.Application.__init__( self, application_id='net.lutris.Lutris', flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE) gettext.bindtextdomain("lutris", "/usr/share/locale") gettext.textdomain("lutris") check_config() init_dxvk_versions() migrate() update_platforms() GLib.set_application_name(_('Lutris')) self.window = None self.tray = None self.css_provider = Gtk.CssProvider.new() if os.geteuid() == 0: ErrorDialog( "Running Lutris as root is not recommended and may cause unexpected issues" ) try: self.css_provider.load_from_path( os.path.join(datapath.get(), 'ui', 'lutris.css')) except GLib.Error as e: logger.exception(e) if hasattr(self, 'add_main_option'): self.add_arguments() else: ErrorDialog( "Your Linux distribution is too old, Lutris won't function properly" )
def winetricks( app, prefix=None, arch=None, silent=True, wine_path=None, config=None, disable_runtime=False, ): """Execute winetricks.""" winetricks_path = os.path.join(settings.RUNTIME_DIR, "winetricks/winetricks") if not system.path_exists(winetricks_path): logger.warning( "Could not find local winetricks install, falling back to bundled version" ) winetricks_path = os.path.join(datapath.get(), "bin/winetricks") if wine_path: winetricks_wine = wine_path else: wine = import_runner("wine") winetricks_wine = wine().get_executable() if arch not in ("win32", "win64"): arch = detect_arch(prefix, winetricks_wine) args = app if str(silent).lower() in ("yes", "on", "true"): args = "--unattended " + args return wineexec( None, prefix=prefix, winetricks_wine=winetricks_wine, wine_path=winetricks_path, arch=arch, args=args, config=config, disable_runtime=disable_runtime, )
class GameControllerDB: db_path = os.path.join(datapath.get(), 'controllers/gamecontrollerdb.txt') def __init__(self): if not system.path_exists(self.db_path): raise OSError( "Path to gamecontrollerdb.txt not provided or invalid") self.controllers = {} self.parsedb() def __str__(self): return "GameControllerDB <%s>" % self.db_path def __getitem__(self, value): return self.controllers[value] def parsedb(self): with open(self.db_path, 'r') as db: for line in db.readlines(): line = line.strip() if not line or line.startswith('#'): continue guid, name, mapping = line.strip().split(',', 2) self.controllers[guid] = ControllerMapping(guid, name, mapping)
def get_icon(icon_name, format="image", size=None, icon_type="runner"): """Return an icon based on the given name, format, size and type. Keyword arguments: icon_name -- The name of the icon to retrieve format -- The format of the icon, which should be either 'image' or 'pixbuf' (default 'image') size -- The size for the desired image (default None) icon_type -- Retrieve either a 'runner' or 'platform' icon (default 'runner') """ filename = icon_name.lower().replace(" ", "") + ".png" icon_path = os.path.join(datapath.get(), "media/" + icon_type + "_icons", filename) if not os.path.exists(icon_path): logger.error("Unable to find icon '%s'", icon_path) return None if format == "image": icon = Gtk.Image() if size: icon.set_from_pixbuf(get_pixbuf(icon_path, size)) else: icon.set_from_file(icon_path) return icon elif format == "pixbuf" and size: return get_pixbuf(icon_path, size) raise ValueError("Invalid arguments")
# -*- coding:Utf-8 -*- """Misc widgets used in the GUI.""" import os from gi.repository import Gtk, GObject, Pango, GdkPixbuf, GLib from IPython.testing.decorators import make_label_dec from gi.repository.GdkPixbuf import Pixbuf from lutris.downloader import Downloader from lutris.util import datapath from lutris import settings MISSING_ICON = os.path.join(datapath.get(), "media/banner.png") UNAVAILABLE_GAME_OVERLAY = os.path.join(datapath.get(), "media/unavailable.png") ICON_SIZE = (184, 69) (COL_ID, COL_NAME, COL_ICON, COL_RUNNER, COL_INSTALLED) = range(5) def sort_func(store, a_iter, b_iter, _user_data): """Default sort function""" a_name = store.get(a_iter, COL_NAME) b_name = store.get(b_iter, COL_NAME) if a_name > b_name: return 1 elif a_name < b_name: return -1 else: return 0
def __init__(self): ui_filename = os.path.join( datapath.get(), 'ui', 'LutrisWindow.ui' ) if not os.path.exists(ui_filename): raise IOError('File %s not found' % ui_filename) self.builder = Gtk.Builder() self.builder.add_from_file(ui_filename) # load config width = int(settings.read_setting('width') or 800) height = int(settings.read_setting('height') or 600) self.window_size = (width, height) view_type = settings.read_setting('view_type') or 'icon' filter_installed_setting = settings.read_setting( 'filter_installed' ) or 'false' self.filter_installed = filter_installed_setting == 'true' show_installed_games_menuitem = self.builder.get_object( 'filter_installed' ) show_installed_games_menuitem.set_active(self.filter_installed) logger.debug("Getting game list") game_list = get_game_list(self.filter_installed) logger.debug("Switching view") self.view = switch_to_view(view_type, game_list) logger.debug("Connecting signals") self.icon_view_menuitem = self.builder.get_object("iconview_menuitem") self.icon_view_menuitem.set_active(view_type == 'icon') self.list_view_menuitem = self.builder.get_object("listview_menuitem") self.list_view_menuitem.set_active(view_type == 'list') self.icon_view_btn = self.builder.get_object('switch_grid_view_btn') self.icon_view_btn.set_active(view_type == 'icon') self.list_view_btn = self.builder.get_object('switch_list_view_btn') self.list_view_btn.set_active(view_type == 'list') # Scroll window self.games_scrollwindow = self.builder.get_object('games_scrollwindow') self.games_scrollwindow.add(self.view) #Status bar self.status_label = self.builder.get_object('status_label') self.joystick_icons = [] # Buttons self.stop_button = self.builder.get_object('stop_button') self.stop_button.set_sensitive(False) self.delete_button = self.builder.get_object('delete_button') self.delete_button.set_sensitive(False) self.play_button = self.builder.get_object('play_button') self.play_button.set_sensitive(False) #Contextual menu menu_callbacks = [ ('play', self.on_game_clicked), ('install', self.on_game_clicked), ('add', self.add_manually), ('configure', self.edit_game_configuration), ('desktop-shortcut', self.create_desktop_shortcut), ('menu-shortcut', self.create_menu_shortcut), ('uninstall', self.on_remove_game), ] self.menu = ContextualMenu(menu_callbacks) self.view.contextual_menu = self.menu #Timer self.timer_id = GLib.timeout_add(2000, self.refresh_status) self.window = self.builder.get_object("window") self.window.resize_to_geometry(width, height) self.window.show_all() self.builder.connect_signals(self) self.connect_signals() if api.read_api_key(): self.status_label.set_text("Connected to lutris.net") self.sync_library() else: async_call(self.sync_icons, None)
from lutris.gui import dialogs from lutris.gui.widgets.sidebar import SidebarListBox from lutris.gui.widgets.services import SyncServiceWindow from lutris.gui.dialogs.runners import RunnersDialog from lutris.gui.config.add_game import AddGameDialog from lutris.gui.config.system import SystemConfigDialog from lutris.gui.views.list import GameListView from lutris.gui.views.grid import GameGridView from lutris.gui.views.menu import ContextualMenu from lutris.gui.views.store import GameStore from lutris.gui.views.game_panel import GamePanel, GenericPanel from lutris.gui.widgets.utils import IMAGE_SIZES, open_uri @GtkTemplate(ui=os.path.join(datapath.get(), "ui", "lutris-window.ui")) class LutrisWindow(Gtk.ApplicationWindow): """Handler class for main window signals.""" default_view_type = "grid" default_width = 800 default_height = 600 __gtype_name__ = "LutrisWindow" main_box = GtkTemplate.Child() games_scrollwindow = GtkTemplate.Child() sidebar_revealer = GtkTemplate.Child() sidebar_scrolled = GtkTemplate.Child() connection_label = GtkTemplate.Child() search_revealer = GtkTemplate.Child()
def __init__(self, service=None): Gtk.Application.__init__( self, application_id="net.lutris.main", flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE ) ui_filename = os.path.join( datapath.get(), 'ui', 'lutris-window.ui' ) if not os.path.exists(ui_filename): raise IOError('File %s not found' % ui_filename) self.service = service self.runtime_updater = RuntimeUpdater() self.running_game = None self.threads_stoppers = [] # Emulate double click to workaround GTK bug #484640 # https://bugzilla.gnome.org/show_bug.cgi?id=484640 self.game_selection_time = 0 self.game_launch_time = 0 self.last_selected_game = None self.selected_runner = None self.builder = Gtk.Builder() self.builder.add_from_file(ui_filename) # Load settings width = int(settings.read_setting('width') or 800) height = int(settings.read_setting('height') or 600) self.window_size = (width, height) window = self.builder.get_object('window') window.resize(width, height) view_type = self.get_view_type() self.load_icon_type_from_settings(view_type) self.filter_installed = \ settings.read_setting('filter_installed') == 'true' self.sidebar_visible = \ settings.read_setting('sidebar_visible') in ['true', None] # Set theme to dark if set in the settings dark_theme_menuitem = self.builder.get_object('dark_theme_menuitem') use_dark_theme = settings.read_setting('dark_theme') == 'true' dark_theme_menuitem.set_active(use_dark_theme) self.set_dark_theme(use_dark_theme) self.game_list = pga.get_games() # Load view self.game_store = GameStore([], self.icon_type, self.filter_installed) self.view = self.get_view(view_type) self.main_box = self.builder.get_object('main_box') self.splash_box = self.builder.get_object('splash_box') self.connect_link = self.builder.get_object('connect_link') # View menu installed_games_only_menuitem =\ self.builder.get_object('filter_installed') installed_games_only_menuitem.set_active(self.filter_installed) self.grid_view_menuitem = self.builder.get_object("gridview_menuitem") self.grid_view_menuitem.set_active(view_type == 'grid') self.list_view_menuitem = self.builder.get_object("listview_menuitem") self.list_view_menuitem.set_active(view_type == 'list') sidebar_menuitem = self.builder.get_object('sidebar_menuitem') sidebar_menuitem.set_active(self.sidebar_visible) # View buttons self.grid_view_btn = self.builder.get_object('switch_grid_view_btn') self.grid_view_btn.set_active(view_type == 'grid') self.list_view_btn = self.builder.get_object('switch_list_view_btn') self.list_view_btn.set_active(view_type == 'list') # Icon type menu self.banner_small_menuitem = \ self.builder.get_object('banner_small_menuitem') self.banner_small_menuitem.set_active(self.icon_type == 'banner_small') self.banner_menuitem = self.builder.get_object('banner_menuitem') self.banner_menuitem.set_active(self.icon_type == 'banner') self.icon_menuitem = self.builder.get_object('icon_menuitem') self.icon_menuitem.set_active(self.icon_type == 'icon') self.search_entry = self.builder.get_object('search_entry') self.search_entry.connect('icon-press', self.on_clear_search) # Scroll window self.games_scrollwindow = self.builder.get_object('games_scrollwindow') self.games_scrollwindow.add(self.view) # Buttons self.stop_button = self.builder.get_object('stop_button') self.stop_button.set_sensitive(False) self.delete_button = self.builder.get_object('delete_button') self.delete_button.set_sensitive(False) self.play_button = self.builder.get_object('play_button') self.play_button.set_sensitive(False) # Contextual menu main_entries = [ ('play', "Play", self.on_game_run), ('install', "Install", self.on_install_clicked), ('add', "Add manually", self.on_add_manually), ('configure', "Configure", self.on_edit_game_configuration), ('browse', "Browse files", self.on_browse_files), ('desktop-shortcut', "Create desktop shortcut", self.create_desktop_shortcut), ('rm-desktop-shortcut', "Delete desktop shortcut", self.remove_desktop_shortcut), ('menu-shortcut', "Create application menu shortcut", self.create_menu_shortcut), ('rm-menu-shortcut', "Delete application menu shortcut", self.remove_menu_shortcut), ('install_more', "Install (add) another version", self.on_install_clicked), ('remove', "Remove", self.on_remove_game), ] self.menu = ContextualMenu(main_entries) self.view.contextual_menu = self.menu # Sidebar self.sidebar_paned = self.builder.get_object('sidebar_paned') self.sidebar_treeview = SidebarTreeView() self.sidebar_treeview.connect('cursor-changed', self.on_sidebar_changed) self.sidebar_viewport = self.builder.get_object('sidebar_viewport') self.sidebar_viewport.add(self.sidebar_treeview) # Window initialization self.window = self.builder.get_object("window") self.window.resize_to_geometry(width, height) self.window.set_default_icon_name('lutris') self.window.show_all() self.builder.connect_signals(self) self.connect_signals() self.statusbar = self.builder.get_object("statusbar") # XXX Hide PGA config menu item until it actually gets implemented pga_menuitem = self.builder.get_object('pga_menuitem') pga_menuitem.hide() # Sync local lutris library with current Steam games before setting up # view steam.sync_with_lutris() self.game_store.fill_store(self.game_list) self.switch_splash_screen() self.show_sidebar() self.update_runtime() # Connect account and/or sync credentials = api.read_api_key() if credentials: self.on_connect_success(None, credentials) else: self.toggle_connection(False) self.sync_library() # Timers self.timer_ids = [GLib.timeout_add(300, self.refresh_status)] steamapps_paths = steam.get_steamapps_paths(flat=True) self.steam_watcher = steam.SteamWatcher(steamapps_paths, self.on_steam_game_changed)
from lutris.gui import dialogs from lutris.gui.sidebar import SidebarTreeView from lutris.gui.logwindow import LogWindow from lutris.gui.sync import SyncServiceDialog from lutris.gui.gi_composites import GtkTemplate from lutris.gui.runnersdialog import RunnersDialog from lutris.gui.installerwindow import InstallerWindow from lutris.gui.uninstallgamedialog import UninstallGameDialog from lutris.gui.config_dialogs import (AddGameDialog, EditGameConfigDialog, SystemConfigDialog) from lutris.gui.gameviews import (GameListView, GameGridView, ContextualMenu, GameStore) @GtkTemplate(ui=os.path.join(datapath.get(), 'ui', 'lutris-window.ui')) class LutrisWindow(Gtk.ApplicationWindow): """Handler class for main window signals.""" __gtype_name__ = 'LutrisWindow' main_box = GtkTemplate.Child() splash_box = GtkTemplate.Child() connect_link = GtkTemplate.Child() games_scrollwindow = GtkTemplate.Child() sidebar_paned = GtkTemplate.Child() sidebar_viewport = GtkTemplate.Child() statusbar = GtkTemplate.Child() connection_label = GtkTemplate.Child() status_box = GtkTemplate.Child()
class RunnersDialog(GtkBuilderDialog): """Dialog to manage the runners.""" glade_file = "runners-dialog.ui" dialog_object = "runners_dialog" runner_entry_ui = os.path.join(datapath.get(), "ui", 'runner-entry.ui') __gsignals__ = { "runner-installed": (GObject.SIGNAL_RUN_FIRST, None, ()), "runner-removed": (GObject.SIGNAL_RUN_FIRST, None, ()), } def initialize(self, **kwargs): width = int(settings.read_setting("runners_manager_width") or 800) height = int(settings.read_setting("runners_manager_height") or 800) self.dialog_size = (width, height) self.dialog.resize(width, height) self.runner_listbox = self.builder.get_object('runners_listbox') self.runner_listbox.set_header_func(self._listbox_header_func) self.refresh_button = self.builder.get_object('refresh_button') self.runner_list = sorted(runners.__all__) # Run this after show_all, else all hidden buttons gets shown self.populate_runners() @staticmethod def _listbox_header_func(row, before): if not row.get_header() and before is not None: row.set_header(Gtk.Separator.new(Gtk.Orientation.HORIZONTAL)) def get_runner_hbox(self, runner_name): # Get runner details runner = runners.import_runner(runner_name)() platform = ", ".join(sorted(list(set(runner.platforms)))) builder = Gtk.Builder() builder.add_from_file(self.runner_entry_ui) hbox = builder.get_object('runner_entry') hbox.show() # Icon runner_icon = builder.get_object('runner_icon') runner_icon.set_from_pixbuf( get_icon(runner_name, format='pixbuf', size=ICON_SIZE)) # Label runner_name = builder.get_object('runner_name') runner_name.set_text(runner.human_name) runner_description = builder.get_object('runner_description') runner_description.set_text(runner.description) runner_platform = builder.get_object('runner_platform') runner_platform.set_text(platform) runner_label = builder.get_object('runner_label') if not runner.is_installed(): runner_label.set_sensitive(False) # Buttons self.versions_button = builder.get_object('manage_versions') self.versions_button.connect("clicked", self.on_versions_clicked, runner, runner_label) self.install_button = builder.get_object('install_runner') self.install_button.connect("clicked", self.on_install_clicked, runner, runner_label) self.remove_button = builder.get_object('remove_runner') self.remove_button.connect("clicked", self.on_remove_clicked, runner, runner_label) self.configure_button = builder.get_object('configure_runner') self.configure_button.connect("clicked", self.on_configure_clicked, runner, runner_label) self.set_button_display(runner) return hbox def populate_runners(self): for runner_name in self.runner_list: hbox = self.get_runner_hbox(runner_name) self.runner_listbox.add(hbox) def set_button_display(self, runner): if runner.multiple_versions: self.versions_button.show() self.install_button.hide() if runner.can_uninstall(): self.remove_button.show() else: self.remove_button.hide() else: self.versions_button.hide() self.remove_button.hide() self.install_button.show() if runner.is_installed(): self.install_button.hide() if runner.can_uninstall(): self.remove_button.show() else: self.remove_button.hide() self.configure_button.show() def on_versions_clicked(self, widget, runner, runner_label): dlg_title = "Manage %s versions" % runner.name versions_dialog = RunnerInstallDialog(dlg_title, self.dialog, runner.name) versions_dialog.connect("destroy", self.set_install_state, runner, runner_label) def on_install_clicked(self, widget, runner, runner_label): """Install a runner.""" if runner.depends_on: dependency = runner.depends_on() dependency.install(downloader=simple_downloader) try: runner.install(downloader=simple_downloader) except ( runners.RunnerInstallationError, runners.NonInstallableRunnerError, ) as ex: ErrorDialog(ex.message, parent=self) if runner.is_installed(): self.emit("runner-installed") self.refresh_button.emit("clicked") def on_configure_clicked(self, widget, runner, runner_label): config_dialog = RunnerConfigDialog(runner, parent=self.dialog) config_dialog.connect("destroy", self.set_install_state, runner, runner_label) def on_remove_clicked(self, widget, runner, runner_label): if not runner.is_installed(): logger.warning("Runner %s is not installed", runner) return if runner.multiple_versions: logger.info("Removing multiple versions") builder = get_builder_from_file( 'runner-remove-all-versions-dialog.ui') builder.connect_signals(self) remove_confirm_button = builder.get_object('remove_confirm_button') remove_confirm_button.connect("clicked", self.on_remove_all_clicked, runner, runner_label) all_versions_label = builder.get_object( 'runner_all_versions_label') all_versions_label.set_markup(all_versions_label.get_label() % runner.human_name) self.all_versions_dialog = builder.get_object( 'runner_remove_all_versions_dialog') self.all_versions_dialog.set_parent(self.dialog) self.all_versions_dialog.show() else: builder = get_builder_from_file('runner-remove-confirm-dialog.ui') builder.connect_signals(self) remove_confirm_button = builder.get_object('remove_confirm_button') remove_confirm_button.connect("clicked", self.on_remove_confirm_clicked, runner, runner_label) runner_remove_label = builder.get_object('runner_remove_label') runner_remove_label.set_markup(runner_remove_label.get_label() % runner.human_name) self.remove_confirm_dialog = builder.get_object( 'runner_remove_confirm_dialog') self.remove_confirm_dialog.show() def on_remove_confirm_clicked(self, widget, runner, runner_label): runner.uninstall() self.refresh_button.emit("clicked") self.emit("runner-removed") self.remove_confirm_dialog.destroy() def on_remove_all_clicked(self, _widget, runner, _runner_label): runner.uninstall() self.refresh_button.emit("clicked") self.emit("runner-removed") self.all_versions_dialog.destroy() def on_cancel_confirm_clicked(self, _widget): self.remove_confirm_dialog.destroy() def on_cancel_all_clicked(self, _widget): self.all_versions_dialog.destroy() @staticmethod def on_folder_clicked(_widget): open_uri("file://" + settings.RUNNER_DIR) def on_refresh_clicked(self, _widget): for child in self.runner_listbox: child.destroy() self.populate_runners() def on_close_clicked(self, _widget): self.destroy() def set_install_state(self, _widget, runner, runner_label): if runner.is_installed(): runner_label.set_sensitive(True) self.emit("runner-installed") else: runner_label.set_sensitive(False) def on_resize(self, _widget, *args): """Store the dialog's new size.""" self.dialog_size = self.dialog.get_size() def on_destroy(self, _widget): # Save window size width, height = self.dialog_size settings.write_setting("runners_manager_width", width) settings.write_setting("runners_manager_height", height)
"""Run web based games""" import os import string from gettext import gettext as _ from urllib.parse import urlparse from lutris import settings from lutris.database.games import get_game_by_field from lutris.runners.runner import Runner from lutris.util import datapath, linux, resources, system from lutris.util.strings import split_arguments DEFAULT_ICON = os.path.join(datapath.get(), "media/default_icon.png") class web(Runner): human_name = _("Web") description = _("Runs web based games") platforms = [_("Web")] game_options = [{ "option": "main_file", "type": "string", "label": _("Full URL or HTML file path"), "help": _("The full address of the game's web page or path to a HTML file."), }] runner_options = [ {
from lutris.gui import dialogs from lutris.gui.sidebar import SidebarTreeView from lutris.gui.logwindow import LogWindow from lutris.gui.gi_composites import GtkTemplate from lutris.gui.runnersdialog import RunnersDialog from lutris.gui.installgamedialog import InstallerDialog from lutris.gui.uninstallgamedialog import UninstallGameDialog from lutris.gui.config_dialogs import ( AddGameDialog, EditGameConfigDialog, SystemConfigDialog ) from lutris.gui.gameviews import ( GameListView, GameGridView, ContextualMenu, GameStore ) @GtkTemplate(ui=os.path.join(datapath.get(), 'ui', 'lutris-window.ui')) class LutrisWindow(Gtk.ApplicationWindow): """Handler class for main window signals.""" __gtype_name__ = 'LutrisWindow' main_box = GtkTemplate.Child() splash_box = GtkTemplate.Child() connect_link = GtkTemplate.Child() games_scrollwindow = GtkTemplate.Child() sidebar_paned = GtkTemplate.Child() sidebar_viewport = GtkTemplate.Child() statusbar = GtkTemplate.Child() connection_label = GtkTemplate.Child() status_box = GtkTemplate.Child()
def get_default_icon(size): if size[0] == size[1]: return os.path.join(datapath.get(), "media/default_icon.png") return os.path.join(datapath.get(), "media/default_banner.png")
def __init__(self): ui_filename = os.path.join(datapath.get(), "ui", "LutrisWindow.ui") if not os.path.exists(ui_filename): raise IOError("File %s not found" % ui_filename) self.running_game = None self.threads_stoppers = [] # Emulate double click to workaround GTK bug #484640 # https://bugzilla.gnome.org/show_bug.cgi?id=484640 self.game_selection_time = 0 self.game_launch_time = 0 self.last_selected_game = None self.builder = Gtk.Builder() self.builder.add_from_file(ui_filename) # Load settings width = int(settings.read_setting("width") or 800) height = int(settings.read_setting("height") or 600) self.window_size = (width, height) view_type = self.get_view_type() self.icon_type = self.get_icon_type(view_type) filter_installed_setting = settings.read_setting("filter_installed") or "false" filter_installed = filter_installed_setting == "true" show_installed_games_menuitem = self.builder.get_object("filter_installed") show_installed_games_menuitem.set_active(filter_installed) # Load view logger.debug("Loading view") self.game_store = GameStore([], self.icon_type, filter_installed) self.view = load_view(view_type, self.game_store) logger.debug("Connecting signals") self.main_box = self.builder.get_object("main_box") self.splash_box = self.builder.get_object("splash_box") # View menu self.grid_view_menuitem = self.builder.get_object("gridview_menuitem") self.grid_view_menuitem.set_active(view_type == "grid") self.list_view_menuitem = self.builder.get_object("listview_menuitem") self.list_view_menuitem.set_active(view_type == "list") # View buttons self.grid_view_btn = self.builder.get_object("switch_grid_view_btn") self.grid_view_btn.set_active(view_type == "grid") self.list_view_btn = self.builder.get_object("switch_list_view_btn") self.list_view_btn.set_active(view_type == "list") # Icon type menu self.banner_small_menuitem = self.builder.get_object("banner_small_menuitem") self.banner_small_menuitem.set_active(self.icon_type == "banner_small") self.banner_menuitem = self.builder.get_object("banner_menuitem") self.banner_menuitem.set_active(self.icon_type == "banner") self.icon_menuitem = self.builder.get_object("icon_menuitem") self.icon_menuitem.set_active(self.icon_type == "icon") self.search_entry = self.builder.get_object("search_entry") self.search_entry.connect("icon-press", self.on_clear_search) # Scroll window self.games_scrollwindow = self.builder.get_object("games_scrollwindow") self.games_scrollwindow.add(self.view) # Status bar self.status_label = self.builder.get_object("status_label") self.joystick_icons = [] # Buttons self.stop_button = self.builder.get_object("stop_button") self.stop_button.set_sensitive(False) self.delete_button = self.builder.get_object("delete_button") self.delete_button.set_sensitive(False) self.play_button = self.builder.get_object("play_button") self.play_button.set_sensitive(False) # Contextual menu main_entries = [ ("play", "Play", self.on_game_run), ("install", "Install", self.on_install_clicked), ("add", "Add manually", self.add_manually), ("configure", "Configure", self.edit_game_configuration), ("browse", "Browse files", self.on_browse_files), ("desktop-shortcut", "Create desktop shortcut", self.create_desktop_shortcut), ("rm-desktop-shortcut", "Delete desktop shortcut", self.remove_desktop_shortcut), ("menu-shortcut", "Create application menu shortcut", self.create_menu_shortcut), ("rm-menu-shortcut", "Delete application menu shortcut", self.remove_menu_shortcut), ("remove", "Remove", self.on_remove_game), ] self.menu = ContextualMenu(main_entries) self.view.contextual_menu = self.menu # Sidebar sidebar_paned = self.builder.get_object("sidebar_paned") sidebar_paned.set_position(150) self.sidebar_treeview = SidebarTreeView() self.sidebar_treeview.connect("cursor-changed", self.on_sidebar_changed) self.sidebar_viewport = self.builder.get_object("sidebar_viewport") self.sidebar_viewport.add(self.sidebar_treeview) # Window initialization self.window = self.builder.get_object("window") self.window.resize_to_geometry(width, height) self.window.show_all() self.builder.connect_signals(self) self.connect_signals() # XXX Hide PGA config menu item until it actually gets implemented pga_menuitem = self.builder.get_object("pga_menuitem") pga_menuitem.hide() self.init_game_store() # Connect account and/or sync credentials = api.read_api_key() if credentials: self.on_connect_success(None, credentials) else: self.toggle_connection(False) self.sync_library() # Timers self.timer_ids = [GLib.timeout_add(300, self.refresh_status), GLib.timeout_add(10000, self.on_sync_timer)]
# -*- coding:Utf-8 -*- """Misc widgets used in the GUI.""" import os from gi.repository import Gtk, GObject, Pango, GdkPixbuf, GLib from gi.repository.GdkPixbuf import Pixbuf from lutris.downloader import Downloader from lutris.util import datapath from lutris import settings DEFAULT_BANNER = os.path.join(datapath.get(), 'media/default_banner.png') DEFAULT_ICON = os.path.join(datapath.get(), 'media/default_icon.png') UNAVAILABLE_GAME_OVERLAY = os.path.join(datapath.get(), 'media/unavailable.png') BANNER_SIZE = (184, 69) BANNER_SMALL_SIZE = (120, 45) ICON_SIZE = (32, 32) ( COL_ID, COL_NAME, COL_ICON, COL_YEAR, COL_RUNNER, COL_INSTALLED, ) = range(6) def sort_func(store, a_iter, b_iter, _user_data): """Default sort function""" a_name = store.get(a_iter, COL_NAME)
# -*- coding: utf-8 -*- import os import string import shlex from urllib.parse import urlparse from lutris.runners.runner import Runner from lutris.util import datapath from lutris import pga, settings DEFAULT_ICON = os.path.join(datapath.get(), 'media/default_icon.png') class web(Runner): human_name = "Web" description = "Runs web based games" platform = "Web based games" description = "Runs web based games" game_options = [ { "option": "main_file", "type": "string", "label": "Full URL or HTML file path", 'help': ("The full address of the game's web page or path to a HTML file.") } ] runner_options = [ { "option": "fullscreen", "label": "Open in fullscreen",
def __init__(self): GObject.GObject.__init__(self) self.set_title("Configure runners") self.set_size_request(700, 600) self.vbox = Gtk.VBox() self.vbox.set_margin_right(10) self.vbox.set_margin_left(10) self.vbox.set_margin_bottom(10) self.add(self.vbox) label = Gtk.Label() label.set_markup("<b>Install and configure the game runners</b>") scrolled_window = Gtk.ScrolledWindow() scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) scrolled_window.set_shadow_type(Gtk.ShadowType.ETCHED_OUT) self.vbox.pack_start(label, False, True, 15) self.vbox.pack_start(scrolled_window, True, True, 0) runner_list = lutris.runners.__all__ runner_vbox = Gtk.VBox() self.runner_labels = {} for runner_name in runner_list: # Get runner details runner = import_runner(runner_name)() platform = runner.platform description = runner.description hbox = Gtk.HBox() # Icon icon_path = os.path.join(datapath.get(), 'media/runner_icons', runner_name + '.png') icon = Gtk.Image() icon.set_from_file(icon_path) icon.set_alignment(0.5, 0.1) hbox.pack_start(icon, False, False, 10) # Label runner_label = Gtk.Label() if not runner.is_installed(): runner_label.set_sensitive(False) runner_label.set_markup( "<b>%s</b>\n%s\n <i>Supported platforms : %s</i>" % (runner_name, description, platform) ) runner_label.set_width_chars(40) runner_label.set_max_width_chars(40) runner_label.set_property('wrap', True) runner_label.set_line_wrap(True) runner_label.set_alignment(0.0, 0.1) runner_label.set_padding(5, 0) self.runner_labels[runner] = runner_label hbox.pack_start(runner_label, True, True, 5) # Button button = Gtk.Button() button.set_size_request(100, 30) button_align = Gtk.Alignment.new(1.0, 0.0, 0.0, 0.0) self.configure_button(button, runner) button_align.add(button) hbox.pack_start(button_align, False, False, 15) runner_vbox.pack_start(hbox, True, True, 5) separator = Gtk.Separator() runner_vbox.pack_start(separator, False, False, 5) scrolled_window.add_with_viewport(runner_vbox) self.show_all()
def show_splash(self): image = Gtk.Image(visible=True) image.set_from_file(os.path.join(datapath.get(), "media/splash.svg")) self.show_overlay(image, Gtk.Align.START, Gtk.Align.START)