Merging into main branch

This commit is contained in:
Mathieu Comandon 2012-09-19 13:18:57 +02:00
commit 7f5fcd4eb4
9 changed files with 154 additions and 179 deletions

View file

@ -90,17 +90,6 @@
<signal name="activate" handler="import_scummvm" swapped="no"/>
</object>
</child>
<child>
<object class="GtkMenuItem" id="steam_menuitem">
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Steam</property>
<property name="use_underline">True</property>
<signal name="activate" handler="import_steam" swapped="no"/>
</object>
</child>
</object>
</child>
</object>
@ -195,23 +184,6 @@
<property name="can_focus">False</property>
<property name="toolbar_style">icons</property>
<property name="icon_size">6</property>
<child>
<object class="GtkToolButton" id="add_game_button">
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Add game</property>
<property name="use_action_appearance">False</property>
<property name="label" translatable="yes">Add Game</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-add</property>
<signal name="clicked" handler="add_game" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
<child>
<object class="GtkToolButton" id="play_button">
<property name="use_action_appearance">False</property>
@ -222,7 +194,7 @@
<property name="label" translatable="yes">Play</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-media-play</property>
<signal name="clicked" handler="on_play_clicked" swapped="no"/>
<signal name="clicked" handler="game_launch" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
@ -246,6 +218,23 @@
<property name="homogeneous">True</property>
</packing>
</child>
<child>
<object class="GtkToolButton" id="add_game_button">
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Add game</property>
<property name="use_action_appearance">False</property>
<property name="label" translatable="yes">Add Game</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-add</property>
<signal name="clicked" handler="add_game" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
<child>
<object class="GtkToolButton" id="delete_button">
<property name="use_action_appearance">False</property>

View file

@ -57,20 +57,10 @@ class AddGameDialog(Gtk.Dialog):
runner_liststore.append(("Choose a runner for the list", ""))
for runner_name in lutris.runners.__all__:
runner = import_runner(runner_name)
if hasattr(runner, "description"):
description = runner.description
else:
logger.debug("Please fix %s and add a description attribute",
runner.__name__)
description = ""
if hasattr(runner, "machine"):
machine = runner.machine
else:
logger.debug("Please fix % and add a machine attribute",
runner.__name__)
machine = ""
description = runner.description
if runner.is_installed():
runner_liststore.append((machine + " (" + description + ")",
runner_liststore.append(("%s (%s)" % (runner_name,
description),
runner_name))
runner_combobox = Gtk.ComboBox.new_with_model(runner_liststore)

View file

@ -4,7 +4,7 @@ import os
# pylint: disable=E0611
from gi.repository import Gtk, GObject
from lutris.util import log
#from lutris.util import log
from lutris.settings import get_data_path
from lutris.game import LutrisGame, get_list
from lutris.desktop_control import LutrisDesktopControl
@ -35,68 +35,51 @@ def switch_to_view(view=GAME_VIEW):
class LutrisWindow:
"""Handler class for main window signals"""
def __init__(self):
log.logger.debug("Creating main window")
ui_filename = os.path.join(get_data_path(), 'ui', 'LutrisWindow.ui')
if not os.path.exists(ui_filename):
msg = 'File %s not found' % ui_filename
log.logger.error(msg)
raise IOError(msg)
raise IOError('File %s not found' % ui_filename)
self.builder = Gtk.Builder()
self.builder.add_from_file(ui_filename)
self.builder.connect_signals(self)
log.logger.debug("Fetching game list")
# TODO : do something with this shit
# Game list
#self.game_column = treeview.get_column(1)
#self.game_cell = self.game_column.get_cells()[0]
#self.game_cell.connect('edited', self.game_name_edited_callback)
self.view = switch_to_view()
self.view.connect('button-press-event', self.mouse_menu)
self.view.connect("game-selected", self.game_launch)
self.connect_signals()
# Scroll window
self.games_scrollwindow = self.builder.get_object('games_scrollwindow')
self.games_scrollwindow.add_with_viewport(self.view)
#Status bar
self.status_label = self.builder.get_object('status_label')
self.status_label.set_text('Insert coin')
self.joystick_icons = []
# Buttons
self.reset_button = self.builder.get_object('reset_button')
self.reset_button.set_sensitive(False)
self.delete_button = self.builder.get_object('delete_button')
self.delete_button.set_sensitive(False)
# Set buttons state
self.play_button = self.builder.get_object('play_button')
self.play_button.set_sensitive(False)
#Contextual menu
play = 'Play', self.game_launch
rename = 'Rename', self.edit_game_name
config = 'Configure', self.edit_game_configuration
menu_actions = [('Play', self.game_launch),
('Configure', self.edit_game_configuration)]
self.menu = Gtk.Menu()
for item in [play, rename, config]:
if item == None:
subitem = Gtk.SeparatorMenuItem()
else:
subitem = Gtk.ImageMenuItem(item[0])
subitem.connect('activate', item[1])
self.menu.append(subitem)
for action in menu_actions:
subitem = Gtk.ImageMenuItem(action[0])
subitem.connect('activate', action[1])
self.menu.append(subitem)
self.menu.show_all()
self.view.contextual_menu = self.menu
#Timer
self.timer_id = GObject.timeout_add(1000, self.refresh_status)
self.window = self.builder.get_object("window")
log.logger.debug("Showing main window")
self.window.show_all()
def connect_signals(self):
"""Connects signals from the view with the main window.
This must be called each time the view is rebuilt.
"""
self.view.connect("game-activated", self.game_launch)
self.view.connect("game-selected", self.game_selection_changed)
def refresh_status(self):
"""Refresh status bar"""
if hasattr(self, "running_game"):
@ -111,7 +94,7 @@ class LutrisWindow:
self.status_label.set_text("Playing %s (pid: %r)"\
% (name, pid))
else:
self.status_label.set_text("Welcome to Lutris")
self.status_label.set_text("")
for index in range(4):
self.joystick_icons.append(
self.builder.get_object('js' + str(index) + 'image')
@ -122,19 +105,6 @@ class LutrisWindow:
self.joystick_icons[index].set_visible(False)
return True
def on_destroy(self, *args):
"""Signal for window close"""
log.logger.debug("Sending exit signal")
Gtk.main_quit(*args)
def mouse_menu(self, widget, event):
"""Contextual menu"""
if event.button == 3:
(_, self.paths) = widget.get_selection().get_selected_rows()
if len(self.paths) > 0:
self.menu.popup(None, None, None, None,
event.button, event.time)
def about(self, _widget, _data=None):
"""Opens the about dialog"""
AboutDialog()
@ -144,18 +114,20 @@ class LutrisWindow:
Note: this won't delete the actual game
"""
#game_selection = self.game_treeview.get_selection()
#model, select_iter = game_selection.get_selected()
#game_name = model.get_value(select_iter, 0)
#self.lutris_config.remove(game_name)
#self.game_treeview.remove_row(select_iter)
#self.status_label.set_text("Removed game")
pass
raise NotImplemented("You gotta wait for it")
def on_connect(self, widget):
# =========
# Callbacks
# =========
def on_connect(self, *args):
"""Callback when a user connects to his account"""
NoticeDialog("This functionnality is not yet implemented.")
def on_destroy(self, *args):
"""Signal for window close"""
Gtk.main_quit(*args)
def on_runners_activate(self, _widget, _data=None):
"""Callback when manage runners is activated"""
RunnersDialog()
@ -172,66 +144,46 @@ class LutrisWindow:
self.view.add(new_game)
self.game_treeview.sort_rows()
def import_steam(self, _widget, data=None):
"""Callback for importing Steam games"""
NoticeDialog("Import from steam not yet implemented")
def on_search_entry_changed(self, widget):
self.view.emit('filter-updated', widget.get_text())
def on_play_clicked(self, _widget):
"""Callback for the play button"""
self.game_launch()
def game_launch(self, data):
def game_launch(self, *args):
"""Launch a game"""
print "data", data
game_id = self.view.selected_game
if game_id:
self.running_game = LutrisGame(game_id)
if self.view.selected_game:
self.running_game = LutrisGame(self.view.selected_game)
self.running_game.play()
def reset(self, _widget, _data=None):
def reset(self, *args):
"""Reset the desktop to it's initial state"""
if hasattr(self, "running_game"):
if self.running_game:
self.running_game.quit_game()
self.status_label.set_text("Stopped %s"\
% self.running_game.get_real_name())
self.running_game = None
else:
LutrisDesktopControl().reset_desktop()
def game_selection_changed(self, _widget):
sensitive = True if self.view.selected_game else False
self.play_button.set_sensitive(sensitive)
self.delete_button.set_sensitive(sensitive)
def add_game(self, _widget, _data=None):
""" MAnually add a game """
""" Manually add a game """
add_game_dialog = AddGameDialog(self)
if hasattr(add_game_dialog, "game_info"):
game_info = add_game_dialog.game_info
self.view.add(game_info)
def edit_game_name(self, _button):
pass
# """Change game name"""
# self.game_cell.set_property('editable', True)
# self.game_treeview.set_cursor(self.paths[0][0],
# self.game_column, True)
def game_name_edited_callback(self, _widget, index, new_name):
""" Update the game's name """
#self.game_treeview.get_model()[index][0] = new_name
#new_name_game_config = LutrisConfig(game=self.get_selected_game())
#new_name_game_config.config["realname"] = new_name
#new_name_game_config.save(config_type="game")
#self.game_cell.set_property('editable', False)
pass
def edit_game_configuration(self, _button):
"""Edit game preferences"""
game = self.get_selected_game()
EditGameConfigDialog(self, game)
EditGameConfigDialog(self, self.view.selected_game)
def on_iconview_toggled(self, menuitem):
"""Switches between icon view and list view"""
self.view.destroy()
self.view = None
self.view = switch_to_view('icon' if menuitem.get_active() else 'list')
self.view.contextual_menu = self.menu
self.connect_signals()
self.games_scrollwindow.add_with_viewport(self.view)

View file

@ -19,10 +19,11 @@
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
###############################################################################
from gi.repository import Gtk
import os
from gi.repository import Gtk, GObject
import lutris.runners
from lutris.settings import get_data_path
from lutris.runners import import_runner
from lutris.config import LutrisConfig
from lutris.gui.runnerconfigvbox import RunnerConfigVBox
@ -30,17 +31,17 @@ from lutris.gui.systemconfigvbox import SystemConfigVBox
class RunnerConfigDialog(Gtk.Dialog):
""" """
"""Runners management dialog"""
def __init__(self, runner):
GObject.GObject.__init__(self)
Gtk.Dialog.__init__(self)
self.set_title("Configure %s" % (runner))
self.set_size_request(570, 500)
self.runner = runner
self.lutris_config = LutrisConfig(runner=runner)
#Notebook for choosing between runner and system configuration
self.config_notebook = Gtk.Notebook()
self.vbox.pack_start(self.config_notebook, True, True, 0)
self.notebook = Gtk.Notebook()
self.vbox.pack_start(self.notebook, True, True, 0)
#Runner configuration
self.runner_config_vbox = RunnerConfigVBox(self.lutris_config,
@ -49,8 +50,8 @@ class RunnerConfigDialog(Gtk.Dialog):
runner_scrollwindow.set_policy(Gtk.PolicyType.AUTOMATIC,
Gtk.PolicyType.AUTOMATIC)
runner_scrollwindow.add_with_viewport(self.runner_config_vbox)
self.config_notebook.append_page(runner_scrollwindow,
Gtk.Label(label="Runner configuration"))
self.notebook.append_page(runner_scrollwindow,
Gtk.Label(label="Runner configuration"))
#System configuration
self.system_config_vbox = SystemConfigVBox(self.lutris_config,
@ -59,8 +60,8 @@ class RunnerConfigDialog(Gtk.Dialog):
system_scrollwindow.set_policy(Gtk.PolicyType.AUTOMATIC,
Gtk.PolicyType.AUTOMATIC)
system_scrollwindow.add_with_viewport(self.system_config_vbox)
self.config_notebook.append_page(system_scrollwindow,
Gtk.Label(label="System configuration"))
self.notebook.append_page(system_scrollwindow,
Gtk.Label(label="System configuration"))
#Action buttons
cancel_button = Gtk.Button(None, Gtk.STOCK_CANCEL)
@ -96,9 +97,10 @@ class RunnersDialog(Gtk.Dialog):
""")
scrolled_window = Gtk.ScrolledWindow()
scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
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)
self.vbox.pack_start(scrolled_window, True, True, 10)
runner_list = lutris.runners.__all__
runner_vbox = Gtk.VBox()
@ -111,8 +113,7 @@ class RunnersDialog(Gtk.Dialog):
hbox = Gtk.HBox()
#Icon
icon_path = os.path.join(lutris.constants.DATA_PATH,
'media/runner_icons',
icon_path = os.path.join(get_data_path(), 'media/runner_icons',
runner + '.png')
icon = Gtk.Image()
icon.set_from_file(icon_path)
@ -128,7 +129,7 @@ class RunnersDialog(Gtk.Dialog):
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)
hbox.pack_start(runner_label, True, True, 5)
#Button
button = Gtk.Button("Configure")
button.set_size_request(100, 30)
@ -141,7 +142,7 @@ class RunnersDialog(Gtk.Dialog):
button.set_label('Install')
button.connect("clicked", self.on_install_clicked, runner)
button_align.add(button)
hbox.pack_start(button_align, True, False)
hbox.pack_start(button_align, True, False, 5)
runner_vbox.pack_start(hbox, True, True, 5)
scrolled_window.add_with_viewport(runner_vbox)

View file

@ -42,8 +42,7 @@ MISSING_ICON = os.path.join(get_data_path(), 'media/lutris.svg')
COL_NAME,
COL_ICON,
COL_RUNNER,
COL_RUNNER_ICON
) = range(5)
COL_RUNNER_ICON) = range(5)
def sort_func(store, a_iter, b_iter, _user_data):
@ -106,9 +105,12 @@ def get_pixbuf_for_game(game):
class GameView(object):
__gsignals__ = {
"game-selected": (GObject.SIGNAL_RUN_FIRST, None, ()),
"game-activated": (GObject.SIGNAL_RUN_FIRST, None, ()),
"filter-updated": (GObject.SIGNAL_RUN_FIRST, None, (str,)),
}
selected_game = None
current_path = None
contextual_menu = None
filter_text = ""
games = []
@ -140,22 +142,31 @@ class GameView(object):
for game in self.games:
self.add_game(game)
def popup_contextual_menu(self, view, event):
"""Contextual menu"""
if event.button != 3:
return
try:
view.current_path = view.get_path_at_pos(event.x, event.y)
view.select_path(view.current_path)
except ValueError:
(_, path) = view.get_selection().get_selected()
view.current_path = path
if view.current_path:
self.contextual_menu.popup(None, None, None, None,
event.button, event.time)
def get_selected_game(self):
raise NotImplemented('Implement this method in subclasses of GameView')
class GameTreeView(Gtk.TreeView, GameView):
"""
Show the main list of games
Some code inspired by Ubuntu Software Center
Many thanks to Michael Vogt
"""
"""Show the main list of games"""
__gsignals__ = GameView.__gsignals__
def __init__(self, games):
super(GameTreeView, self).__init__()
store = self.initialize_store(games)
self.initialize_store(games)
# Icon column
image_cell = Gtk.CellRendererPixbuf()
@ -169,8 +180,12 @@ class GameTreeView(Gtk.TreeView, GameView):
column = Gtk.TreeViewColumn("Game", text_cell, markup=COL_NAME)
self.append_column(column)
self.connect('row-activated', self.get_selected_game, store)
self.get_selection().set_mode(Gtk.SelectionMode.SINGLE)
self.connect('row-activated', self.get_selected_game, True)
self.connect('cursor-changed', self.get_selected_game, False)
self.connect('filter-updated', self.update_filter)
self.connect('button-press-event', self.popup_contextual_menu)
def remove_row(self, model_iter):
"""Remove a game from the treeview."""
@ -182,11 +197,16 @@ class GameTreeView(Gtk.TreeView, GameView):
model = self.get_model()
Gtk.TreeModel.sort_new_with_model(model)
def get_selected_game(self, widget, line, column, store):
def get_selected_game(self, widget, line=None, column=None, launch=False):
selection = self.get_selection()
if not selection:
return
model, select_iter = selection.get_selected()
self.selected_game = model.get_value(select_iter, COL_ID)
self.emit("game-selected")
if launch:
self.emit("game-activated")
else:
self.emit("game-selected")
class GameIconView(Gtk.IconView, GameView):
@ -194,27 +214,40 @@ class GameIconView(Gtk.IconView, GameView):
def __init__(self, games):
super(GameIconView, self).__init__()
store = self.initialize_store(games)
self.initialize_store(games)
self.set_markup_column(COL_NAME)
self.set_pixbuf_column(COL_ICON)
self.set_item_width(150)
self.set_spacing(21)
self.connect('item-activated', self.get_selection, store)
self.connect('item-activated', self.on_item_activated)
self.connect('selection-changed', self.on_selection_changed)
self.connect('filter-updated', self.update_filter)
self.connect ("size-allocate", GameIconView.on_size_allocate)
self.connect('size-allocate', GameIconView.on_size_allocate)
self.connect('button-press-event', self.popup_contextual_menu)
def on_size_allocate (self, allocation):
[self.set_columns (m) for m in [1,self.get_columns ()]]
def on_size_allocate(self, allocation):
[self.set_columns(m) for m in [1, self.get_columns()]]
def do_get_preferred_width (self):
return (0,0)
def do_get_preferred_width(self):
return (0, 0)
def get_selection(self, icon_view, tree_path, store):
iter_ = store.get_iter(tree_path)
self.selected_game = store.get(iter_, COL_ID)
self.emit("game-selected")
def on_item_activated(self, view, path):
self.get_selected_game(True)
def on_selection_changed(self, view):
self.get_selected_game(False)
def get_selected_game(self, launch=False):
self.current_path = self.get_selected_items()[0]
store = self.get_model()
self.selected_game = store.get(store.get_iter(self.current_path),
COL_ID)
if launch:
self.emit("game-activated")
else:
self.emit("game-selected")
class GameCover(Gtk.Image):
@ -338,7 +371,6 @@ class DownloadProgressBox(Gtk.HBox):
def cancel(self):
"""Cancel the current download."""
print "cancelling download"
self.downloader.kill()

View file

@ -40,6 +40,7 @@ class dolphin(Runner):
self.executable = "dolphin"
self.machine = "Gamecube, Wii"
self.description = "Emulator for Nintendo Gamecube and Wii games"
self.is_installable = False
def install(self):
NoticeDialog('Please activate the PlayDeb reposiories in order to ' + \

View file

@ -31,14 +31,22 @@ from lutris.util.log import logger
# pylint: disable=C0103
class mednafen(Runner):
"""Use Mednafen"""
"""Mednafen is a multi-platform emulator, including NES, GB/A, PC Engine"""
def __init__(self, settings=None):
super(mednafen, self).__init__()
self.executable = "mednafen"
self.machine = """
Atari Lynx, Game Boy (Color), GameBoy Advance, NES,
PC Engine(TurboGrafx 16), SuperGrafx, Neo Geo Pocket (Color),
PC-FX, and WonderSwan (Color)"""
* Atari Lynx
* GameBoy
* GameBoy Color
* GameBoy Advance
* NES
* PC Engine (TurboGrafx 16)
* PC-FX
* SuperGrafx
* NeoGeo Pocket, NeoGeo Pocket Color
* WonderSwan
"""
self.package = "mednafen"
machine_choices = [("NES", "nes"),
("PC Engine", "pce"),

View file

@ -37,7 +37,7 @@ class Runner(object):
def __init__(self):
""" Initialize runner """
self.executable = None
self.is_installable = True
self.is_installable = False
self.arguments = []
self.error_messages = []
self.game = None

View file

@ -27,12 +27,14 @@ from lutris.runners.runner import Runner
# pylint: disable=C0103
class uae(Runner):
"""Runs Amiga games with UAE, yay"""
"""Run Amiga games with UAE"""
def __init__(self, settings=None):
super(uae, self).__init__()
self.package = "uae"
self.executable = "uae"
self.machine = "Amiga"
self.is_installable = True
self.uae_options = {}
control_choices = [("Mouse", "mouse"), ("Joystick 1", "joy0"),
("Joystick 2", "joy1"), ("Keyboard 1", "kbd1"),