class HelpDialog(object): def __init__(self, mainmenu): self.mainmenu = mainmenu self.widgets = mainmenu.widgets self.keyconf = KeyConfig() # before _build_strings self.HELPSTRING_LAYOUT = None self._build_strings() self._is_displayed = False LanguageChanged.subscribe(lambda msg: self._build_strings()) def _build_strings(self): """ Loads the help strings from pychan object widgets (containing no key definitions) and adds the keys defined in the keyconfig configuration object in front of them. The layout is defined through HELPSTRING_LAYOUT and translated. """ # i18n this defines how each line in our help looks like. Default: '[C] = Chat' self.HELPSTRING_LAYOUT = _("[{key}] = {text}") # xgettext:python-format widgets = self.widgets["help"] labels = widgets.getNamedChildren() # filter misc labels that do not describe key functions labels = dict((name[4:], lbl[0]) for (name, lbl) in labels.iteritems() if name.startswith("lbl_")) # now prepend the actual keys to the function strings defined in xml for (name, lbl) in labels.items(): if name == "SHIFT": # TODO #HACK hardcoded shift key keyname = "SHIFT" else: # TODO Display all keys per action, not just the first keyname = self.keyconf.get_current_keys(name)[0] lbl.explanation = _(lbl.text) lbl.text = self.HELPSTRING_LAYOUT.format(text=lbl.explanation, key=keyname) def toggle(self): """Called on help action. Toggles help screen via static variable *help_is_displayed*. Can be called both from main menu and in-game interface. """ help_dlg = self.widgets["help"] if not self._is_displayed: self._is_displayed = True # make game pause if there is a game and we're not in the main menu if self.mainmenu.session is not None and self.mainmenu.current != self.widgets["ingamemenu"]: PauseCommand().execute(self.mainmenu.session) if self.mainmenu.session is not None: self.mainmenu.session.ingame_gui.on_escape() # close dialogs that might be open self.mainmenu.show_dialog(help_dlg, {OkButton.DEFAULT_NAME: True}) self.toggle() # toggle state else: self._is_displayed = False if self.mainmenu.session is not None and self.mainmenu.current != self.widgets["ingamemenu"]: UnPauseCommand().execute(self.mainmenu.session) help_dlg.hide()
class HelpDialog(Window): def __init__(self, windows, session=None): super(HelpDialog, self).__init__(windows) self._session = session self.widget = load_uh_widget('help.xml') self.keyconf = KeyConfig() # before _build_strings self.HELPSTRING_LAYOUT = None self._build_strings() self._is_displayed = False self.widget.findChild(name=OkButton.DEFAULT_NAME).capture(self._windows.close) LanguageChanged.subscribe(lambda msg: self._build_strings()) def _build_strings(self): """ Loads the help strings from pychan object widgets (containing no key definitions) and adds the keys defined in the keyconfig configuration object in front of them. The layout is defined through HELPSTRING_LAYOUT and translated. """ #i18n this defines how each line in our help looks like. Default: '[C] = Chat' self.HELPSTRING_LAYOUT = _('[{key}] = {text}') #xgettext:python-format labels = self.widget.getNamedChildren() # filter misc labels that do not describe key functions labels = dict( (name[4:], lbl[0]) for (name, lbl) in labels.iteritems() if name.startswith('lbl_') ) # now prepend the actual keys to the function strings defined in xml for (name, lbl) in labels.items(): if name == 'SHIFT': #TODO #HACK hardcoded shift key keyname = 'SHIFT' else: #TODO Display all keys per action, not just the first keyname = self.keyconf.get_current_keys(name)[0] lbl.explanation = _(lbl.text) lbl.text = self.HELPSTRING_LAYOUT.format(text=lbl.explanation, key=keyname) def show(self): self.widget.show() if self._session: PauseCommand().execute(self._session) def hide(self): if self._session: UnPauseCommand().execute(self._session) self.widget.hide()
class HelpDialog(Window): def __init__(self, windows, session=None): super(HelpDialog, self).__init__(windows) self._session = session self.widget = load_uh_widget('help.xml') self.keyconf = KeyConfig() # before _build_strings self.HELPSTRING_LAYOUT = None self._build_strings() self._is_displayed = False self.widget.findChild(name=OkButton.DEFAULT_NAME).capture(self._windows.close) LanguageChanged.subscribe(lambda msg: self._build_strings()) def _build_strings(self): """ Loads the help strings from pychan object widgets (containing no key definitions) and adds the keys defined in the keyconfig configuration object in front of them. The layout is defined through HELPSTRING_LAYOUT and translated. """ #i18n this defines how each line in our help looks like. Default: '[C] = Chat' self.HELPSTRING_LAYOUT = _('[{key}] = {text}') #xgettext:python-format labels = self.widget.getNamedChildren() # filter misc labels that do not describe key functions labels = dict( (name[4:], lbl[0]) for (name, lbl) in labels.iteritems() if name.startswith('lbl_') ) # now prepend the actual keys to the function strings defined in xml for (name, lbl) in labels.items(): if name == 'SHIFT': #TODO #HACK hardcoded shift key keyname = 'SHIFT' else: #TODO Display all keys per action, not just the first keyname = self.keyconf.get_current_keys(name)[0] lbl.explanation = _(lbl.text) lbl.text = self.HELPSTRING_LAYOUT.format(text=lbl.explanation, key=keyname) def show(self): self.widget.show() if self._session: PauseCommand().execute(self._session) def hide(self): if self._session: UnPauseCommand().execute(self._session) self.widget.hide()
class HotkeyConfiguration(object): def __init__(self): super(HotkeyConfiguration, self).__init__() self.widget = load_uh_widget('hotkeys.xml') self.buttons = [] self.secondary_buttons = [] self.keyconf = KeyConfig() self.actions = self.keyconf.get_bindable_actions_by_name() self.keys = self.keyconf.get_keys_by_value() self.HELPSTRING_LAYOUT = None self._is_displayed = False self._build_interface() # When detecing is True, the interface detects keypresses and binds them to actions self.detecting = False self.current_button = None self.current_index = None self.last_combination = [] # Stores whether the last button pressed was for a primary or secondary binding (1 or 2) self.last_column = 1 # There are some keys which are not detected by the event widget/keyPressed # In that case, the key presses are detected by the listener, which calls _detect_keypress self.listener = HotkeysListener(self._detect_keypress) self.widget.mapEvents({self.widget.name + '/keyPressed' : self._detect_keypress}) self.widget.findChild(name=OkButton.DEFAULT_NAME).capture(self.save_settings) self.widget.mapEvents({OkButton.DEFAULT_NAME : self.save_settings}) self.widget.findChild(name="reset_to_default").capture(self.reset_to_default) def _build_interface(self): button_container = self.widget.findChild(name='button_container') sec_button_container = self.widget.findChild(name='sec_button_container') for i, action in enumerate(self.actions): button = self._create_button(action, i) sec_button = self._create_button(action, i) button.mapEvents({button.name + '/mouseClicked' : Callback(self._detect_click_on_button, button, 1)}) sec_button.mapEvents({button.name + '/mouseClicked' : Callback(self._detect_click_on_button, sec_button, 2)}) button_container.addChild(button) sec_button_container.addChild(sec_button) self.buttons.append(button) self.secondary_buttons.append(sec_button) self.update_buttons_text() def _create_button(self, action, index): """Important! The button name is set to index so that when a button is pressed, we know its index""" button = Button() button.name = str(index) button.max_size = button.min_size = (100, 18) return button def _detect_click_on_button(self, button, column): """Starts the listener and remembers the position and index of the pressed button""" self.detecting = True self.current_button = button self.current_index = int(button.name) self.current_column = column self.listener.activate() self.update_buttons_text() button.text = _("Press desired key") def _detect_keypress(self, event): if not self.detecting: return key = event.getKey() # if the key is not supported, act as if it was not detected if not self.key_name(key): return self.last_combination.append(key) self.detecting = False self.listener.deactivate() self.apply_change() def update_buttons_text(self): for i, button in enumerate(self.buttons): action = self.actions[i] bindings = self.keyconf.get_current_keys(action) for j in range(len(bindings)): if bindings[j] == 'UNASSIGNED': bindings[j] = '-' secondary_button = self.secondary_buttons[i] button.text = unicode(bindings[0]) if len(bindings) > 1: secondary_button.text = unicode(bindings[1]) else: secondary_button.text = u"-" def apply_change(self): """Binds the last keypress to the corresponding action and resets the interface to the state where it is listening for clicks on buttons""" key = self.last_combination[0] key_name = self.key_name(key) action = self.actions[self.current_index] column = self.current_column # Escape is used to unassign bindings if key_name == 'ESCAPE': key_name = 'UNASSIGNED' # If *key* is already set, replace the entry for *key* with UNASSIGNED for the last action. # This is done to avoid binding one key for two actions. elif self.key_is_set(key): oldaction = self.get_action_name(key) message = _("{key} is already set to {action}.").format(key=key_name, action=oldaction) message += u" " + _("Would you like to overwrite it?") confirmed = horizons.main._modules.gui.show_popup(_("Confirmation for overwriting"), message, show_cancel_button=True) if confirmed: horizons.globals.fife.replace_key_for_action(oldaction, key_name, "UNASSIGNED") else: self.update_buttons_text() self.last_combination = [] return bindings = self.keyconf.get_current_keys(action) if column == 1: bindings[0] = key_name elif column == 2: if len(bindings) < 2: bindings.append(key_name) else: bindings[1] = key_name horizons.globals.fife.set_key_for_action(action, bindings) self.update_buttons_text() self.last_combination = [] def key_name(self, key): value = key.getValue() return self.keys.get(value) def key_is_set(self, key): key_name = self.key_name(key) custom_key_actions = horizons.globals.fife.get_hotkey_settings() for k in custom_key_actions.itervalues(): if key_name in k: return True return False def get_current_bindings(self): """ Returns a dict mapping action -> list of keys """ bindings = {} for action in self.actions: keys = self.keyconf.get_current_keys(action) bindings[action] = keys return bindings def get_action_name(self, key): key_name = self.key_name(key) custom_key_actions = horizons.globals.fife.get_hotkey_settings() for action in custom_key_actions: k = custom_key_actions[action] if key_name in k: return action print "Action name not found. Key name must be wrong. This is not supposed to ever happen" def reset_to_default(self): """Resets all bindings to default""" for action in self.actions: default_key = horizons.globals.fife.get_keys_for_action(action, default=True) horizons.globals.fife.set_key_for_action(action, default_key) self.update_buttons_text() def save_settings(self): """Saves the settings and reloads the keyConfiguration so that the settings take effect without a restart""" horizons.globals.fife.save_settings() self.keyconf.loadKeyConfiguration() def show(self): self.widget.show() def hide(self): self.widget.hide()
class HotkeyConfiguration(object): def __init__(self): super(HotkeyConfiguration, self).__init__() self.widget = load_uh_widget('hotkeys.xml') self.buttons = [] self.secondary_buttons = [] self.keyconf = KeyConfig() self.actions = self.keyconf.get_bindable_actions_by_name() self.keys = self.keyconf.get_keys_by_value() self.HELPSTRING_LAYOUT = None self._is_displayed = False self._build_interface() # When detecing is True, the interface detects keypresses and binds them to actions self.detecting = False self.current_button = None self.current_index = None self.last_combination = [] # Stores whether the last button pressed was for a primary or secondary binding (1 or 2) self.last_column = 1 # There are some keys which are not detected by the event widget/keyPressed # In that case, the key presses are detected by the listener, which calls _detect_keypress self.listener = HotkeysListener(self._detect_keypress) self.widget.mapEvents({self.widget.name + '/keyPressed' : self._detect_keypress}) self.widget.findChild(name=OkButton.DEFAULT_NAME).capture(self.save_settings) self.widget.mapEvents({OkButton.DEFAULT_NAME : self.save_settings}) self.widget.findChild(name="reset_to_default").capture(self.reset_to_default) def _build_interface(self): button_container = self.widget.findChild(name='button_container') sec_button_container = self.widget.findChild(name='sec_button_container') for i, action in enumerate(self.actions): button = self._create_button(action, i) sec_button = self._create_button(action, i) button.mapEvents({button.name + '/mouseClicked' : Callback(self._detect_click_on_button, button, 1)}) sec_button.mapEvents({button.name + '/mouseClicked' : Callback(self._detect_click_on_button, sec_button, 2)}) button_container.addChild(button) sec_button_container.addChild(sec_button) self.buttons.append(button) self.secondary_buttons.append(sec_button) self.update_buttons_text() def _create_button(self, action, index): """Important! The button name is set to index so that when a button is pressed, we know its index""" button = Button() button.name = str(index) button.max_size = button.min_size = (100, 18) return button def _detect_click_on_button(self, button, column): """Starts the listener and remembers the position and index of the pressed button""" self.detecting = True self.current_button = button self.current_index = int(button.name) self.current_column = column self.listener.activate() self.update_buttons_text() button.text = _("Press desired key") def _detect_keypress(self, event): if not self.detecting: return key = event.getKey() # if the key is not supported, act as if it was not detected if not self.key_name(key): return self.last_combination.append(key) self.detecting = False self.listener.deactivate() self.apply_change() def update_buttons_text(self): for i, button in enumerate(self.buttons): action = self.actions[i] bindings = self.keyconf.get_current_keys(action) for j in range(len(bindings)): if bindings[j] == 'UNASSIGNED': bindings[j] = '-' secondary_button = self.secondary_buttons[i] button.text = unicode(bindings[0]) if len(bindings) > 1: secondary_button.text = unicode(bindings[1]) else: secondary_button.text = u"-" def apply_change(self): """Binds the last keypress to the corresponding action and resets the interface to the state where it is listening for clicks on buttons""" key = self.last_combination[0] key_name = self.key_name(key) action = self.actions[self.current_index] column = self.current_column # Escape is used to unassign bindings if key_name == 'ESCAPE': key_name = 'UNASSIGNED' # If *key* is already set, replace the entry for *key* with UNASSIGNED for the last action. # This is done to avoid binding one key for two actions. elif self.key_is_set(key): oldaction = self.get_action_name(key) #xgettext:python-format message = _("{key} is already set to {action}.").format(key=key_name, action=oldaction) message += u" " + _("Would you like to overwrite it?") confirmed = horizons.main._modules.gui.show_popup(_("Confirmation for overwriting"), message, show_cancel_button=True) if confirmed: horizons.globals.fife.replace_key_for_action(oldaction, key_name, "UNASSIGNED") else: self.update_buttons_text() self.last_combination = [] return bindings = self.keyconf.get_current_keys(action) if column == 1: bindings[0] = key_name elif column == 2: if len(bindings) < 2: bindings.append(key_name) else: bindings[1] = key_name horizons.globals.fife.set_key_for_action(action, bindings) self.update_buttons_text() self.last_combination = [] def key_name(self, key): value = key.getValue() return self.keys.get(value) def key_is_set(self, key): key_name = self.key_name(key) custom_key_actions = horizons.globals.fife.get_hotkey_settings() for k in custom_key_actions.itervalues(): if key_name in k: return True return False def get_current_bindings(self): """ Returns a dict mapping action -> list of keys """ bindings = {} for action in self.actions: keys = self.keyconf.get_current_keys(action) bindings[action] = keys return bindings def get_action_name(self, key): key_name = self.key_name(key) custom_key_actions = horizons.globals.fife.get_hotkey_settings() for action in custom_key_actions: k = custom_key_actions[action] if key_name in k: return action print "Action name not found. Key name must be wrong. This is not supposed to ever happen" def reset_to_default(self): """Resets all bindings to default""" for action in self.actions: default_key = horizons.globals.fife.get_keys_for_action(action, default=True) horizons.globals.fife.set_key_for_action(action, default_key) self.update_buttons_text() def save_settings(self): """Saves the settings and reloads the keyConfiguration so that the settings take effect without a restart""" horizons.globals.fife.save_settings() self.keyconf.loadKeyConfiguration() def show(self): self.widget.show() def hide(self): self.widget.hide()