Keymap: update addon register/unregister utilities

Use the same data format and loader that the default key-maps use.

This supports nested properties (needed for macros)
and fixes modal key-maps which weren't supported.

This format still needs to be documented.
This commit is contained in:
Campbell Barton
2018-11-20 12:33:47 +11:00
parent 916446e83f
commit 9a1796797e

View File

@@ -22,71 +22,61 @@
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# Add-on helpers to properly (un)register their own keymaps. # Add-on helpers to properly (un)register their own keymaps.
# Example of keymaps_description: def addon_keymap_register(keymap_data):
keymaps_description_doc = """
keymaps_description is a tuple (((keymap_description), (tuple of keymap_item_descriptions))).
keymap_description is a tuple (name, space_type, region_type, is_modal).
keymap_item_description is a tuple ({kw_args_for_keymap_new}, (tuple of properties)).
kw_args_for_keymap_new is a mapping which keywords match parameters of keymap.new() function.
tuple of properties is a tuple of pairs (prop_name, prop_value) (properties being those of called operator).
Example:
KEYMAPS = (
# First, keymap identifiers (last bool is True for modal km).
(('Sequencer', 'SEQUENCE_EDITOR', 'WINDOW', False), (
# Then a tuple of keymap items, defined by a dict of kwargs for the km new func, and a tuple of tuples (name, val)
# for ops properties, if needing non-default values.
({"idname": export_strips.SEQExportStrip.bl_idname, "type": 'P', "value": 'PRESS', "shift": True, "ctrl": True},
()),
)),
)
"""
def addon_keymap_register(wm, keymaps_description):
""" """
Register a set of keymaps for addons. Register a set of keymaps for addons using a list of keymaps.
See 'blender_defaults.py' for examples of the format this takes.
"""
import bpy
wm = bpy.context.window_manager
from bl_keymap_utils.io import keymap_init_from_data
""" + keymaps_description_doc
kconf = wm.keyconfigs.addon kconf = wm.keyconfigs.addon
if not kconf: if not kconf:
return # happens in background mode... return # happens in background mode...
for km_info, km_items in keymaps_description: for km_name, km_args, km_content in keymap_data:
km_name, km_sptype, km_regtype, km_ismodal = km_info km_space_type = km_args["space_type"]
kmap = [k for k in kconf.keymaps km_region_type = km_args["region_type"]
if k.name == km_name and k.region_type == km_regtype and km_modal = km_args.get("modal", False)
k.space_type == km_sptype and k.is_modal == km_ismodal] kmap = next(iter(
if kmap: k for k in kconf.keymaps
kmap = kmap[0] if k.name == km_name and
else: k.region_type == km_region_type and
kmap = kconf.keymaps.new(km_name, region_type=km_regtype, space_type=km_sptype, modal=km_ismodal) k.space_type == km_space_type and
for kmi_kwargs, props in km_items: k.is_modal == km_modal
kmi = kmap.keymap_items.new(**kmi_kwargs) ), None)
kmi.active = True if kmap is None:
for prop, val in props: kmap = kconf.keymaps.new(km_name, **km_args)
setattr(kmi.properties, prop, val) keymap_init_from_data(kmap, km_content["items"], is_modal=km_modal)
def addon_keymap_unregister(keymap_data):
def addon_keymap_unregister(wm, keymaps_description):
""" """
Unregister a set of keymaps for addons. Unregister a set of keymaps for addons.
"""
""" + keymaps_description_doc
# NOTE: We must also clean up user keyconfig, else, if user has customized one of add-on's shortcut, this # NOTE: We must also clean up user keyconfig, else, if user has customized one of add-on's shortcut, this
# customization remains in memory, and comes back when re-enabling the addon, causing a segfault... :/ # customization remains in memory, and comes back when re-enabling the addon, causing a segfault... :/
import bpy
wm = bpy.context.window_manager
kconfs = wm.keyconfigs kconfs = wm.keyconfigs
for kconf in (kconfs.user, kconfs.addon): for kconf in (kconfs.user, kconfs.addon):
for km_info, km_items in keymaps_description: for km_name, km_args, km_content in keymap_data:
km_name, km_sptype, km_regtype, km_ismodal = km_info km_space_type = km_args["space_type"]
kmaps = (k for k in kconf.keymaps km_region_type = km_args["region_type"]
if k.name == km_name and k.region_type == km_regtype and km_modal = km_args.get("modal", False)
k.space_type == km_sptype and k.is_modal == km_ismodal) kmaps = (
k for k in kconf.keymaps
if k.name == km_name and
k.region_type == km_region_type and
k.space_type == km_space_type and
k.is_modal == km_modal
)
for kmap in kmaps: for kmap in kmaps:
for kmi_kwargs, props in km_items: for kmi_idname, _, _ in km_content["items"]:
idname = kmi_kwargs["idname"]
for kmi in kmap.keymap_items: for kmi in kmap.keymap_items:
if kmi.idname == idname: if kmi.idname == kmi_idname:
kmap.keymap_items.remove(kmi) kmap.keymap_items.remove(kmi)
# NOTE: We won't remove addons keymaps themselves, other addons might also use them! # NOTE: We won't remove addons keymaps themselves, other addons might also use them!