Source code for eye.helpers.keys

# this project is licensed under the WTFPLv2, see COPYING.txt for details

"""
Shortcut keys file format
-------------------------

The format is based on INI format (parsed by :doc:`configparser`). The file describes shortcuts
for triggering actions or slots of objects belonging to categories (see :doc:`eye.connector`
for a description of categories).

The config file should contain sections, each section describing a category (named like the section).
Within a section, each key is an action name, and the value is the description of the shortcut triggering the action.

Shortcut description
''''''''''''''''''''

The shortcut description should be in a string format accepted by :doc:`QKeySequence`.
Examples:

* ``Ctrl+S``: a simple keyboard shortcut where the S key is pressed while the Control key is held
* ``Alt+Up``: another shortcut where the up arrow key is pressed while Alt is held
* ``Ctrl+G,B``: a more complex shortcut, where G should be pressed while Ctrl is held, then B is
  pressed with no other key held

Optionally, the shortcut description can be prefixed to describe the context in which the shortcut is accepted:

* ``widget:`` (the default): the shortcut is only recognized when the widget has focus
* ``children:``: the shortcut is recognized if the widget or a children widget has focus
* ``window:``: the shortcut is recognized when the window has focus
* ``application:``: the shortcut is recognized when the app has focus

.. TODO if "window" context, can shortcut be recognized by a narrower context?

File example
''''''''''''

Here's an example of a suitable ``keyboard.ini`` (see :any:`DEFAULT_KEYS_FILE`)::

	# this is a comment

	[editor]
	# when Ctrl+S is pressed while a widget with "editor" category has focus,
	# the saveFile slot of the editor is triggered
	save_file = Ctrl+S

	[location_list]
	# when Ctrl+P is pressed in the same window as a widget with the "location_list" widget,
	# the activateNext slot of the location_list is triggered
	activate_next = window:Ctrl+P
	activate_previous = window:Ctrl+Shift+P

	[window]
	# when Ctrl+N is pressed in any child or grandchild of a widget with "window" category,
	# the bufferNew slot of the window is triggered
	buffer_new = children:Ctrl+N
	buffer_close = children:Ctrl+W

Module contents
---------------
"""

from configparser import ConfigParser

from PyQt5.QtCore import Qt
from PyQt5.QtGui import QKeySequence

from eye.helpers.actions import register_action_shortcut
from eye.pathutils import get_config_file_path

__all__ = ('load_keys_config', 'DEFAULT_KEYS_FILE')


DEFAULT_KEYS_FILE = 'keyboard.ini'

"""Default filename used by `loadKeysConfig`."""


[docs] def load_keys_config(path=None): """Load keys config file. If path is ``None``, a file named :any:`DEFAULT_KEYS_FILE` will be looked for in the config directory. :param path: path of the keyboard configuration file """ if path is None: path = get_config_file_path(DEFAULT_KEYS_FILE) cfg = ConfigParser() cfg.optionxform = str cfg.read([path]) for category in cfg.sections(): for action_name in cfg.options(category): keystr = cfg.get(category, action_name) context = Qt.WidgetShortcut if keystr.startswith('widget:'): keystr = keystr.split(':', 1)[1] elif keystr.startswith('window:'): keystr = keystr.split(':', 1)[1] context = Qt.WindowShortcut elif keystr.startswith('children:'): keystr = keystr.split(':', 1)[1] context = Qt.WidgetWithChildrenShortcut elif keystr.startswith('application:'): keystr = keystr.split(':', 1)[1] context = Qt.ApplicationShortcut qks = QKeySequence(keystr) register_action_shortcut(category, action_name, qks, context)