Source

fsgamer / fsgamer / FsgamerWindow.py

# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-

import gettext
from gettext import gettext as _
gettext.textdomain('fsgamer')

from gi.repository import Gtk # pylint: disable=E0611
from gi.repository.GdkPixbuf import Pixbuf # pylint: disable=E0611
import logging
logger = logging.getLogger('fsgamer')

from fsgamer_lib import Window
from fsgamer.AboutFsgamerDialog import AboutFsgamerDialog
from fsgamer.ChooseDialog import ChooseDialog
from fsgamer.FsgrunDialog import FsgrunDialog

import fsgamer_app as fsg_app
import sys
import utils


OPTION_DEFAULTS = {
    'notifications_tts': False,
    'xorg_conf': '',
    'before_script': '',
    'xserver_script': '',
    'openbox_config': '',
}

NO_APP_INSTRUCTIONS = """
Welcome to FSGamer!

Click on the Add button to the left to add your favorite games.

Click on an app to the left to run or configure it.
"""

APP_INSTRUCTIONS = """
Application is now configured to run fullscreen with FS Gamer. Start it by
clicking the ludicrously large button to the right.

Ctrl+Alt+F7  will take you back to your desktop from the game.
""".replace("y\n", "y ").strip()


def get_buffer_for_widget(widget):
    if hasattr(widget, 'get_text'):
        return widget
    else:
        return widget.get_buffer()


# See fsgamer_lib.Window.py for more details about how this class works
class FsgamerWindow(Window):
    __gtype_name__ = "FsgamerWindow"

    def finish_initializing(self, builder): # pylint: disable=E1002
        """Set up the main window"""
        super(FsgamerWindow, self).finish_initializing(builder)

        self.AboutDialog = AboutFsgamerDialog
        self.ChooseDialog = ChooseDialog
        self.FsgrunDialog = FsgrunDialog
        self.choose_dialog = None
        self.fsgrun_dialog = None
        self.set_nothing_selected()
        self.refresh()

    def refresh(self):
        self.app_list = fsg_app.ApplicationList()
        self.populate_icon_list(self.app_list)

    def populate_icon_list(self, app_list):
        liststore = Gtk.ListStore(Pixbuf, str)
        self.liststore = liststore
        self.ui.iconview.set_model(liststore)
        self.ui.iconview.set_pixbuf_column(0)
        self.ui.iconview.set_text_column(1)

        icon_theme = Gtk.IconTheme.get_default()
        for app in app_list:
            name = app.get_name()
            pixbuf = app.get_pixbuf(icon_theme)
            self.liststore.append([pixbuf, name])

    def _show_choose_dialog(self):
        if self.choose_dialog is not None:
            logger.debug('show existing choose_dialog')
            self.choose_dialog.present()
        elif self.ChooseDialog is not None:
            logger.debug('create new ChooseDialog')
            self.choose_dialog = self.ChooseDialog() # pylint: disable=E1102
            self.choose_dialog.connect('destroy', self.on_choose_dialog_destroyed)
            self.choose_dialog.connect('hide', self.on_chosen)
            self.choose_dialog.show()

    def _show_fsgrun_dialog(self):
        if self.fsgrun_dialog is not None:
            logger.debug('show existing choose_dialog')
            self.fsgrun_dialog.present()
        elif self.FsgrunDialog is not None:
            logger.debug('create new ChooseDialog')
            self.fsgrun_dialog = self.FsgrunDialog() # pylint: disable=E1102
            #self.fsgrun_dialog.connect('destroy', self.on_choose_dialog_destroyed)
            #self.fsgrun_dialog.connect('hide', self.on_chosen)
            self.fsgrun_dialog.show()


    def add_app_clicked(self, widget):
        self._show_choose_dialog()

    def on_remove_clicked(self, widget):
        self.current_app = self.get_app()
        if self.current_app:
            self.current_app.delete()
            self.refresh()
            self.current_app = None
        self.set_nothing_selected()

    def on_giant_play_button_clicked(self, widget):
        # Do not run directly, start a child process
        #self._show_fsgrun_dialog()
        self.destroy()
        Gtk.main_quit()
        self.current_app.run_outer(replace=True)
        #self.fsgrun_dialog.set_run_application(self.current_app)

    def get_app(self):
        any_selected = self.ui.iconview.get_selected_items()
        if any_selected:
            indices = any_selected[0].get_indices()
            if indices:
                return self.app_list[indices[0]]
        return None

    def on_selection_changed(self, widget, data=None):
        self.current_app = self.get_app()
        if self.current_app:
            self.ui.application_name.set_text(self.current_app.get_name())
            self.ui.info_label.set_text(APP_INSTRUCTIONS)
            self.ui.options_grid.set_visible(True)
            self.ui.advanced_options_expander.set_visible(True)
            self.ui.go_button.set_visible(True)
            self.refresh_check_show_menu_icon()
            self.refresh_options()
        else:
            self.set_nothing_selected()

    def set_nothing_selected(self):
        self.ui.go_button.set_visible(False)
        self.ui.options_grid.set_visible(False)
        self.ui.application_name.set_text('')
        self.ui.info_label.set_text(NO_APP_INSTRUCTIONS)
        self.ui.advanced_options_expander.set_visible(False)

    def refresh_check_show_menu_icon(self):
        if not self.current_app:
            return
        is_on = self.current_app.menu_icon_exists()

        # block set_active from triggering stuff
        self.ui.check_show_menu_icon.handler_block_by_func(
                            self.on_check_show_menu_icon_toggled)
        self.ui.check_show_menu_icon.set_active(is_on)
        # unblock!
        self.ui.check_show_menu_icon.handler_unblock_by_func(
                            self.on_check_show_menu_icon_toggled)


    def refresh_options(self):
        if not self.current_app:
            return

        for key, default_val in OPTION_DEFAULTS.iteritems():
            val = self.current_app.opts.get(key, default_val)
            name = "option_" + key
            widget = getattr(self.ui, name)

            try:
                widget.handler_block_by_func(self.on_options_change)
            except TypeError as e:
                pass

            if isinstance(default_val, bool):
                widget.set_active(val)
            elif isinstance(default_val, basestring):
                w = get_buffer_for_widget(widget)
                w.set_text(val)

            try:
                widget.handler_unblock_by_func(self.on_options_change)
            except TypeError as e:
                pass

            self.refresh_script_previews()


    def on_options_change(self, widget, data=None):
        print "Changing options!"
        if not self.current_app:
            return

        for key, default_val in OPTION_DEFAULTS.iteritems():
            name = "option_" + key
            widget = getattr(self.ui, name)

            if isinstance(default_val, bool):
                val = widget.get_active()
            elif isinstance(default_val, basestring):
                w = get_buffer_for_widget(widget)
                val = w.get_text().strip()
            print "key , val", key, val

            if val != default_val:
                self.current_app.opts[key] = val
            else:
                # don't bother storing settings the same as default
                if key in self.current_app.opts:
                    del self.current_app.opts[key]

            self.refresh_script_previews()

        self.current_app.write_menu_icon()
        self.current_app.write_desktop()

    def refresh_script_previews(self):
        xinit_script = self.current_app.get_xinit_fsgwm()
        xserver_script = self.current_app.get_exec_opts()
        self.ui.preview_options_xinit.set_text(xinit_script)
        self.ui.preview_options_xserver.set_text(xserver_script)

    def on_check_show_menu_icon_toggled(self, widget, data=None):
        if self.current_app:
            self.current_app.toggle_menu_icon()
        self.refresh_check_show_menu_icon()

    def on_choose_dialog_destroyed(self, widget):
        self.fsgrun_dialog = None

    def on_destroy(self, widget, data=None):
        """Called when the FsgamerWindow is closed."""
        # Clean up code for saving application state should be added here.
        Gtk.main_quit()

    def on_chosen(self, widget):
        choice = self.choose_dialog.choice
        if choice:
            # Now write a new desktop entry in ~/.config/fsgamer/
            choice.write_desktop()
            self.refresh()