First support for add-ons

This commit is contained in:
Mathieu Comandon 2013-06-18 02:13:03 +02:00
parent 4499c95566
commit 282ac32177
4 changed files with 79 additions and 23 deletions

View file

@ -20,6 +20,20 @@ If the game makes use of (Windows) Steam data, the value should be
``$WINESTEAM:appid:path/to/data``. This will check that the data is available
or install it otherwise.
Installer meta data
===================
Installing mods and add-ons
---------------------------
Mods and add-ons require that a base game is already available on the system.
You can let now the installer that you want to install an add-on by specifying
the ``requires`` directive. The value of ``requires`` must be the canonical
slug name of a game, not one of its aliases. For example, to install the add-on
"The reckoning" for Quake 2, you should add:
``requires: quake-2``
Writing the installation script
===============================

View file

@ -76,7 +76,11 @@ class ScriptInterpreter(object):
raise ScriptingError("Invalid script", (self.script, self.errors))
self.game_name = self.script.get('name')
self.game_slug = slugify(self.game_name)
self.target_path = self.default_target
self.requires = self.script.get('requires')
if self.requires:
self._check_dependecy()
else:
self.target_path = self.default_target
@property
def default_target(self):
@ -84,6 +88,14 @@ class ScriptInterpreter(object):
games_dir = lutris_config.get_path() or os.path.expanduser('~')
return join(games_dir, self.game_slug)
def _check_dependecy(self):
game = pga.get_game_by_slug(self.requires)
if not game or not game['directory']:
raise ScriptingError(
"You need to install {} before".format(self.requires)
)
self.target_path = game['directory']
def _fetch_script(self, game_ref):
if os.path.exists(game_ref):
script_contents = open(game_ref, 'r').read()
@ -230,7 +242,10 @@ class ScriptInterpreter(object):
'realname': self.script['name'],
'runner': runner_name
}
pga.add_game(self.script['name'], runner_name, slug=self.game_slug)
pga.add_game(self.script['name'],
runner_name,
slug=self.game_slug,
directory=self.target_path)
if 'system' in self.script:
config_data['system'] = self.script['system']
if runner_name in self.script:
@ -503,38 +518,45 @@ class InstallerDialog(Gtk.Dialog):
# Interpreter
self.interpreter = ScriptInterpreter(game_ref, self)
self.interpreter.is_valid()
## GUI Setup
# Top label
# Title label
self.status_label = Gtk.Label()
self.status_label.set_markup('<b>Select installation directory:</b>')
self.status_label.set_alignment(0, 0)
self.status_label.set_padding(20, 0)
self.vbox.add(self.status_label)
self.status_label.set_markup("<b>Installing %s</b>"
% self.interpreter.game_name)
# Main widget box
self.widget_box = Gtk.VBox()
self.widget_box.set_margin_right(25)
self.widget_box.set_margin_left(25)
self.vbox.pack_start(self.widget_box, True, True, 10)
# Target chooser
default_path = self.interpreter.default_target
location_entry = FileChooserEntry(default=default_path)
location_entry.entry.connect('changed', self.on_target_changed)
self.widget_box.pack_start(location_entry, False, False, 10)
# Separator
self.vbox.pack_start(Gtk.HSeparator(), True, True, 10)
self.vbox.pack_start(Gtk.HSeparator(), False, False, 0)
# Install button
self.install_button = Gtk.Button('Install')
self.install_button.connect('clicked', self.on_install_clicked)
self.action_buttons = Gtk.Alignment.new(0.95, 0.1, 0.15, 0)
self.action_buttons = Gtk.Alignment.new(0.95, 0, 0.15, 0)
self.action_buttons.add(self.install_button)
self.vbox.pack_start(self.action_buttons, False, False, 0)
self.vbox.pack_start(self.action_buttons, False, False, 25)
# Target chooser
if not self.interpreter.requires:
# Top label
label = Gtk.Label()
label.set_markup('<b>Select installation directory:</b>')
label.set_alignment(0, 0)
self.widget_box.pack_start(label, False, False, 10)
default_path = self.interpreter.default_target
location_entry = FileChooserEntry(default=default_path)
location_entry.entry.connect('changed', self.on_target_changed)
self.widget_box.pack_start(location_entry, False, False, 0)
else:
label = Gtk.Label("Click install to continue")
self.show_all()
def on_target_changed(self, text_entry):

View file

@ -76,12 +76,20 @@ def get_games(name_filter=None):
return game_list
def add_game(name, runner, slug=None):
def get_game_by_slug(slug):
game_result = sql.db_select(PGA_DB, "games", condition=('slug', slug))
if game_result:
return game_result[0]
def add_game(name, runner, slug=None, directory=None):
"""Adds a game to the PGA database."""
if not slug:
slug = slugify(name)
sql.db_insert(PGA_DB, "games",
{'name': name, 'slug': slug, 'runner': runner})
game_data = {'name': name, 'slug': slug, 'runner': runner}
if directory:
game_data['directory'] = directory
sql.db_insert(PGA_DB, "games", game_data)
def delete_game(name):

View file

@ -34,10 +34,22 @@ def db_delete(db_path, table, field, value):
(value,))
def db_select(db_path, table, fields):
field_names = ", ".join(fields)
def db_select(db_path, table, fields=None, condition=None):
if fields:
field_names = ", ".join(fields)
else:
field_names = "*"
print field_names
with db_cursor(db_path) as cursor:
cursor.execute("SELECT {0} FROM {1}".format(field_names, table))
if condition:
assert len(condition) == 2
cursor.execute(
"SELECT {0} FROM {1} where {2}=?".format(
field_names, table, condition[0]
), (condition[1], )
)
else:
cursor.execute("SELECT {0} FROM {1}".format(field_names, table))
rows = cursor.fetchall()
column_names = [column[0] for column in cursor.description]
results = []