Merge branch 'blender-v4.0-release'
[blender-addons.git] / development_iskeyfree.py
blobc93e10385548a0435a5102542a67aa37a5f3c9a6
1 # SPDX-FileCopyrightText: 2017-2022 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
5 # PEP8 compliant (https://www.python.org/dev/peps/pep-0008)
7 bl_info = {
8 "name": "Is key Free",
9 "author": "Antonio Vazquez (antonioya)",
10 "version": (1, 1, 3),
11 "blender": (2, 80, 0),
12 "location": "Text Editor > Sidebar > Dev Tab",
13 "description": "Find free shortcuts, inform about used and print a key list",
14 "doc_url": "{BLENDER_MANUAL_URL}/addons/development/is_key_free.html",
15 "category": "Development",
18 import bpy
20 from bpy.props import (
21 BoolProperty,
22 EnumProperty,
23 StringProperty,
24 PointerProperty,
26 from bpy.types import (
27 Operator,
28 Panel,
29 PropertyGroup,
32 import unicodedata
34 # ------------------------------------------------------
35 # Class to find keymaps
36 # ------------------------------------------------------
38 class MyChecker():
39 lastfind = None
40 lastkey = None
41 mylist = []
43 # Init
44 def __init__(self):
45 self.var = 5
47 # Verify if the key is used
48 @classmethod
49 def check(cls, findkey, ctrl, alt, shift, oskey):
50 if len(findkey) > 0:
51 cmd = ""
52 if ctrl :
53 cmd += "Ctrl+"
54 if alt :
55 cmd += "Alt+"
56 if shift :
57 cmd += "Shift+"
58 if oskey :
59 cmd += "OsKey+"
60 cls.lastfind = cmd + findkey.upper()
61 cls.lastkey = findkey.upper()
62 else:
63 cls.lastfind = None
64 cls.lastkey = None
66 wm = bpy.context.window_manager
67 mykeys = []
69 for context, keyboardmap in wm.keyconfigs.user.keymaps.items():
70 for myitem in keyboardmap.keymap_items:
71 if myitem.active and myitem.type == findkey:
72 if ctrl and not myitem.ctrl:
73 continue
74 if alt and not myitem.alt:
75 continue
76 if shift and not myitem.shift:
77 continue
78 if oskey and not myitem.oskey:
79 continue
80 t = (context,
81 myitem.type,
82 "Ctrl" if myitem.ctrl else "",
83 "Alt" if myitem.alt else "",
84 "Shift" if myitem.shift else "",
85 "OsKey" if myitem.oskey else "",
86 myitem.name)
88 mykeys.append(t)
90 sortkeys = sorted(mykeys, key=lambda key: (key[0], key[1], key[2], key[3], key[4], key[5]))
92 cls.mylist.clear()
93 for e in sortkeys:
94 cmd = ""
95 if e[2] != "":
96 cmd += e[2] + "+"
97 if e[3] != "":
98 cmd += e[3] + "+"
99 if e[4] != "":
100 cmd += e[4] + "+"
101 if e[5] != "":
102 cmd += e[5] + "+"
104 cmd += e[1]
106 if e[6] != "":
107 cmd += " " + e[6]
108 cls.mylist.append([e[0], cmd])
110 # return context
111 @classmethod
112 def getcontext(cls):
113 return str(bpy.context.screen.name)
115 # return last search
116 @classmethod
117 def getlast(cls):
118 return cls.lastfind
120 # return last key
121 @classmethod
122 def getlastkey(cls):
123 return cls.lastkey
125 # return result of last search
126 @classmethod
127 def getlist(cls):
128 return cls.mylist
130 # verify if key is valid
131 @classmethod
132 def isvalidkey(cls, txt):
133 allkeys = [
134 "LEFTMOUSE", "MIDDLEMOUSE", "RIGHTMOUSE", "BUTTON4MOUSE", "BUTTON5MOUSE", "BUTTON6MOUSE",
135 "BUTTON7MOUSE",
136 "MOUSEMOVE", "INBETWEEN_MOUSEMOVE", "TRACKPADPAN", "TRACKPADZOOM",
137 "MOUSEROTATE", "WHEELUPMOUSE", "WHEELDOWNMOUSE", "WHEELINMOUSE", "WHEELOUTMOUSE",
138 "A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
139 "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "ZERO", "ONE", "TWO",
140 "THREE", "FOUR", "FIVE", "SIX", "SEVEN", "EIGHT", "NINE", "LEFT_CTRL", "LEFT_ALT", "LEFT_SHIFT",
141 "RIGHT_ALT",
142 "RIGHT_CTRL", "RIGHT_SHIFT", "OSKEY", "GRLESS", "ESC", "TAB", "RET", "SPACE", "LINE_FEED",
143 "BACK_SPACE",
144 "DEL", "SEMI_COLON", "PERIOD", "COMMA", "QUOTE", "ACCENT_GRAVE", "MINUS", "SLASH", "BACK_SLASH",
145 "EQUAL",
146 "LEFT_BRACKET", "RIGHT_BRACKET", "LEFT_ARROW", "DOWN_ARROW", "RIGHT_ARROW", "UP_ARROW", "NUMPAD_2",
147 "NUMPAD_4", "NUMPAD_6", "NUMPAD_8", "NUMPAD_1", "NUMPAD_3", "NUMPAD_5", "NUMPAD_7", "NUMPAD_9",
148 "NUMPAD_PERIOD", "NUMPAD_SLASH", "NUMPAD_ASTERIX", "NUMPAD_0", "NUMPAD_MINUS", "NUMPAD_ENTER",
149 "NUMPAD_PLUS",
150 "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15",
151 "F16", "F17",
152 "F18", "F19", "PAUSE", "INSERT", "HOME", "PAGE_UP", "PAGE_DOWN", "END", "MEDIA_PLAY", "MEDIA_STOP",
153 "MEDIA_FIRST", "MEDIA_LAST", "TEXTINPUT", "WINDOW_DEACTIVATE", "TIMER", "TIMER0", "TIMER1", "TIMER2",
154 "TIMER_JOBS", "TIMER_AUTOSAVE", "TIMER_REPORT", "TIMERREGION", "NDOF_MOTION", "NDOF_BUTTON_MENU",
155 "NDOF_BUTTON_FIT", "NDOF_BUTTON_TOP", "NDOF_BUTTON_BOTTOM", "NDOF_BUTTON_LEFT", "NDOF_BUTTON_RIGHT",
156 "NDOF_BUTTON_FRONT", "NDOF_BUTTON_BACK", "NDOF_BUTTON_ISO1", "NDOF_BUTTON_ISO2",
157 "NDOF_BUTTON_ROLL_CW",
158 "NDOF_BUTTON_ROLL_CCW", "NDOF_BUTTON_SPIN_CW", "NDOF_BUTTON_SPIN_CCW", "NDOF_BUTTON_TILT_CW",
159 "NDOF_BUTTON_TILT_CCW", "NDOF_BUTTON_ROTATE", "NDOF_BUTTON_PANZOOM", "NDOF_BUTTON_DOMINANT",
160 "NDOF_BUTTON_PLUS", "NDOF_BUTTON_MINUS", "NDOF_BUTTON_ESC", "NDOF_BUTTON_ALT", "NDOF_BUTTON_SHIFT",
161 "NDOF_BUTTON_CTRL", "NDOF_BUTTON_1", "NDOF_BUTTON_2", "NDOF_BUTTON_3", "NDOF_BUTTON_4",
162 "NDOF_BUTTON_5",
163 "NDOF_BUTTON_6", "NDOF_BUTTON_7", "NDOF_BUTTON_8", "NDOF_BUTTON_9", "NDOF_BUTTON_10",
164 "NDOF_BUTTON_A",
165 "NDOF_BUTTON_B", "NDOF_BUTTON_C"
167 try:
168 allkeys.index(txt)
169 return True
170 except ValueError:
171 return False
174 mychecker = MyChecker() # Global class handler
177 # ------------------------------------------------------
178 # Button: Class for search button
179 # ------------------------------------------------------
180 class RunActionCheck(Operator):
181 bl_idname = "iskeyfree.action_check"
182 bl_label = ""
183 bl_description = "Verify if the selected shortcut is free"
185 # noinspection PyUnusedLocal
186 def execute(self, context):
187 scene = context.scene.is_keyfree
188 txt = scene.data.upper()
189 global mychecker
190 mychecker.check(txt, scene.use_crtl, scene.use_alt, scene.use_shift,
191 scene.use_oskey)
193 return {'FINISHED'}
196 # ------------------------------------------------------
197 # Defines UI panel
198 # ------------------------------------------------------
199 class UIControlPanel(Panel):
200 bl_idname = "DEVISKEYFREE_PT_ui"
201 bl_space_type = "TEXT_EDITOR"
202 bl_region_type = "UI"
203 bl_label = "Is Key Free"
204 bl_category = 'Dev'
205 bl_options = {'DEFAULT_CLOSED'}
207 # noinspection PyUnusedLocal
208 def draw(self, context):
209 layout = self.layout
210 scene = context.scene.is_keyfree
212 row = layout.row(align=True)
213 row.prop(scene, "data")
214 row.operator("iskeyfree.action_check", icon="VIEWZOOM")
216 row = layout.row(align=True)
217 row.prop(scene, "use_crtl", toggle=True)
218 row.prop(scene, "use_alt", toggle=True)
219 row.prop(scene, "use_shift", toggle=True)
220 row.prop(scene, "use_oskey", toggle=True)
222 row = layout.row()
223 row.prop(scene, "numpad")
225 layout.operator("iskeyfree.run_export_keys", icon="FILE_TEXT")
227 global mychecker
228 mylist = mychecker.getlist()
229 oldcontext = None
231 box = None
232 if len(mylist) > 0:
233 cmd = mychecker.getlast()
234 if cmd is not None:
235 row = layout.row()
236 row.label(text="Current uses of " + str(cmd), icon="PARTICLE_DATA")
237 for e in mylist:
238 if oldcontext != e[0]:
239 box = layout.box()
240 box.label(text=e[0], icon="UNPINNED")
241 oldcontext = e[0]
243 row = box.row(align=True)
244 row.label(text=e[1])
245 else:
246 cmd = mychecker.getlast()
247 if cmd is not None:
248 box = layout.box()
249 if mychecker.isvalidkey(mychecker.getlastkey()) is False:
250 box.label(text=str(mychecker.getlastkey()) + " looks not valid key", icon="ERROR")
251 else:
252 box.label(text=str(cmd) + " is free", icon="FILE_TICK")
255 # ------------------------------------------------------
256 # Update key (special values) event handler
257 # ------------------------------------------------------
258 # noinspection PyUnusedLocal
259 def update_data(self, context):
260 scene = context.scene.is_keyfree
261 if scene.numpad != "NONE":
262 scene.data = scene.numpad
265 class IskeyFreeProperties(PropertyGroup):
266 data: StringProperty(
267 name="Key", maxlen=32,
268 description="Shortcut to verify"
270 use_crtl: BoolProperty(
271 name="Ctrl",
272 description="Ctrl key used in shortcut",
273 default=False
275 use_alt: BoolProperty(
276 name="Alt",
277 description="Alt key used in shortcut",
278 default=False
280 use_shift: BoolProperty(
281 name="Shift",
282 description="Shift key used in shortcut",
283 default=False
285 use_oskey: BoolProperty(
286 name="OsKey",
287 description="Operating system key used in shortcut",
288 default=False
290 numpad: EnumProperty(
291 items=(
292 ('NONE', "Select key", ""),
293 ("LEFTMOUSE", "LEFTMOUSE", ""),
294 ("MIDDLEMOUSE", "MIDDLEMOUSE", ""),
295 ("RIGHTMOUSE", "RIGHTMOUSE", ""),
296 ("BUTTON4MOUSE", "BUTTON4MOUSE", ""),
297 ("BUTTON5MOUSE", "BUTTON5MOUSE", ""),
298 ("BUTTON6MOUSE", "BUTTON6MOUSE", ""),
299 ("BUTTON7MOUSE", "BUTTON7MOUSE", ""),
300 ("MOUSEMOVE", "MOUSEMOVE", ""),
301 ("INBETWEEN_MOUSEMOVE", "INBETWEEN_MOUSEMOVE", ""),
302 ("TRACKPADPAN", "TRACKPADPAN", ""),
303 ("TRACKPADZOOM", "TRACKPADZOOM", ""),
304 ("MOUSEROTATE", "MOUSEROTATE", ""),
305 ("WHEELUPMOUSE", "WHEELUPMOUSE", ""),
306 ("WHEELDOWNMOUSE", "WHEELDOWNMOUSE", ""),
307 ("WHEELINMOUSE", "WHEELINMOUSE", ""),
308 ("WHEELOUTMOUSE", "WHEELOUTMOUSE", ""),
309 ("A", "A", ""),
310 ("B", "B", ""),
311 ("C", "C", ""),
312 ("D", "D", ""),
313 ("E", "E", ""),
314 ("F", "F", ""),
315 ("G", "G", ""),
316 ("H", "H", ""),
317 ("I", "I", ""),
318 ("J", "J", ""),
319 ("K", "K", ""),
320 ("L", "L", ""),
321 ("M", "M", ""),
322 ("N", "N", ""),
323 ("O", "O", ""),
324 ("P", "P", ""),
325 ("Q", "Q", ""),
326 ("R", "R", ""),
327 ("S", "S", ""),
328 ("T", "T", ""),
329 ("U", "U", ""),
330 ("V", "V", ""),
331 ("W", "W", ""),
332 ("X", "X", ""),
333 ("Y", "Y", ""),
334 ("Z", "Z", ""),
335 ("ZERO", "ZERO", ""),
336 ("ONE", "ONE", ""),
337 ("TWO", "TWO", ""),
338 ("THREE", "THREE", ""),
339 ("FOUR", "FOUR", ""),
340 ("FIVE", "FIVE", ""),
341 ("SIX", "SIX", ""),
342 ("SEVEN", "SEVEN", ""),
343 ("EIGHT", "EIGHT", ""),
344 ("NINE", "NINE", ""),
345 ("LEFT_CTRL", "LEFT_CTRL", ""),
346 ("LEFT_ALT", "LEFT_ALT", ""),
347 ("LEFT_SHIFT", "LEFT_SHIFT", ""),
348 ("RIGHT_ALT", "RIGHT_ALT", ""),
349 ("RIGHT_CTRL", "RIGHT_CTRL", ""),
350 ("RIGHT_SHIFT", "RIGHT_SHIFT", ""),
351 ("OSKEY", "OSKEY", ""),
352 ("GRLESS", "GRLESS", ""),
353 ("ESC", "ESC", ""),
354 ("TAB", "TAB", ""),
355 ("RET", "RET", ""),
356 ("SPACE", "SPACE", ""),
357 ("LINE_FEED", "LINE_FEED", ""),
358 ("BACK_SPACE", "BACK_SPACE", ""),
359 ("DEL", "DEL", ""),
360 ("SEMI_COLON", "SEMI_COLON", ""),
361 ("PERIOD", "PERIOD", ""),
362 ("COMMA", "COMMA", ""),
363 ("QUOTE", "QUOTE", ""),
364 ("ACCENT_GRAVE", "ACCENT_GRAVE", ""),
365 ("MINUS", "MINUS", ""),
366 ("SLASH", "SLASH", ""),
367 ("BACK_SLASH", "BACK_SLASH", ""),
368 ("EQUAL", "EQUAL", ""),
369 ("LEFT_BRACKET", "LEFT_BRACKET", ""),
370 ("RIGHT_BRACKET", "RIGHT_BRACKET", ""),
371 ("LEFT_ARROW", "LEFT_ARROW", ""),
372 ("DOWN_ARROW", "DOWN_ARROW", ""),
373 ("RIGHT_ARROW", "RIGHT_ARROW", ""),
374 ("UP_ARROW", "UP_ARROW", ""),
375 ("NUMPAD_1", "NUMPAD_1", ""),
376 ("NUMPAD_2", "NUMPAD_2", ""),
377 ("NUMPAD_3", "NUMPAD_3", ""),
378 ("NUMPAD_4", "NUMPAD_4", ""),
379 ("NUMPAD_5", "NUMPAD_5", ""),
380 ("NUMPAD_6", "NUMPAD_6", ""),
381 ("NUMPAD_7", "NUMPAD_7", ""),
382 ("NUMPAD_8", "NUMPAD_8", ""),
383 ("NUMPAD_9", "NUMPAD_9", ""),
384 ("NUMPAD_0", "NUMPAD_0", ""),
385 ("NUMPAD_PERIOD", "NUMPAD_PERIOD", ""),
386 ("NUMPAD_SLASH", "NUMPAD_SLASH", ""),
387 ("NUMPAD_ASTERIX", "NUMPAD_ASTERIX", ""),
388 ("NUMPAD_MINUS", "NUMPAD_MINUS", ""),
389 ("NUMPAD_ENTER", "NUMPAD_ENTER", ""),
390 ("NUMPAD_PLUS", "NUMPAD_PLUS", ""),
391 ("F1", "F1", ""),
392 ("F2", "F2", ""),
393 ("F3", "F3", ""),
394 ("F4", "F4", ""),
395 ("F5", "F5", ""),
396 ("F6", "F6", ""),
397 ("F7", "F7", ""),
398 ("F8", "F8", ""),
399 ("F9", "F9", ""),
400 ("F10", "F10", ""),
401 ("F11", "F11", ""),
402 ("F12", "F12", ""),
403 ("F13", "F13", ""),
404 ("F14", "F14", ""),
405 ("F15", "F15", ""),
406 ("F16", "F16", ""),
407 ("F17", "F17", ""),
408 ("F18", "F18", ""),
409 ("F19", "F19", ""),
410 ("PAUSE", "PAUSE", ""),
411 ("INSERT", "INSERT", ""),
412 ("HOME", "HOME", ""),
413 ("PAGE_UP", "PAGE_UP", ""),
414 ("PAGE_DOWN", "PAGE_DOWN", ""),
415 ("END", "END", ""),
416 ("MEDIA_PLAY", "MEDIA_PLAY", ""),
417 ("MEDIA_STOP", "MEDIA_STOP", ""),
418 ("MEDIA_FIRST", "MEDIA_FIRST", ""),
419 ("MEDIA_LAST", "MEDIA_LAST", ""),
420 ("TEXTINPUT", "TEXTINPUT", ""),
421 ("WINDOW_DEACTIVATE", "WINDOW_DEACTIVATE", ""),
422 ("TIMER", "TIMER", ""),
423 ("TIMER0", "TIMER0", ""),
424 ("TIMER1", "TIMER1", ""),
425 ("TIMER2", "TIMER2", ""),
426 ("TIMER_JOBS", "TIMER_JOBS", ""),
427 ("TIMER_AUTOSAVE", "TIMER_AUTOSAVE", ""),
428 ("TIMER_REPORT", "TIMER_REPORT", ""),
429 ("TIMERREGION", "TIMERREGION", ""),
430 ("NDOF_MOTION", "NDOF_MOTION", ""),
431 ("NDOF_BUTTON_MENU", "NDOF_BUTTON_MENU", ""),
432 ("NDOF_BUTTON_FIT", "NDOF_BUTTON_FIT", ""),
433 ("NDOF_BUTTON_TOP", "NDOF_BUTTON_TOP", ""),
434 ("NDOF_BUTTON_BOTTOM", "NDOF_BUTTON_BOTTOM", ""),
435 ("NDOF_BUTTON_LEFT", "NDOF_BUTTON_LEFT", ""),
436 ("NDOF_BUTTON_RIGHT", "NDOF_BUTTON_RIGHT", ""),
437 ("NDOF_BUTTON_FRONT", "NDOF_BUTTON_FRONT", ""),
438 ("NDOF_BUTTON_BACK", "NDOF_BUTTON_BACK", ""),
439 ("NDOF_BUTTON_ISO1", "NDOF_BUTTON_ISO1", ""),
440 ("NDOF_BUTTON_ISO2", "NDOF_BUTTON_ISO2", ""),
441 ("NDOF_BUTTON_ROLL_CW", "NDOF_BUTTON_ROLL_CW", ""),
442 ("NDOF_BUTTON_ROLL_CCW", "NDOF_BUTTON_ROLL_CCW", ""),
443 ("NDOF_BUTTON_SPIN_CW", "NDOF_BUTTON_SPIN_CW", ""),
444 ("NDOF_BUTTON_SPIN_CCW", "NDOF_BUTTON_SPIN_CCW", ""),
445 ("NDOF_BUTTON_TILT_CW", "NDOF_BUTTON_TILT_CW", ""),
446 ("NDOF_BUTTON_TILT_CCW", "NDOF_BUTTON_TILT_CCW", ""),
447 ("NDOF_BUTTON_ROTATE", "NDOF_BUTTON_ROTATE", ""),
448 ("NDOF_BUTTON_PANZOOM", "NDOF_BUTTON_PANZOOM", ""),
449 ("NDOF_BUTTON_DOMINANT", "NDOF_BUTTON_DOMINANT", ""),
450 ("NDOF_BUTTON_PLUS", "NDOF_BUTTON_PLUS", ""),
451 ("NDOF_BUTTON_MINUS", "NDOF_BUTTON_MINUS", ""),
452 ("NDOF_BUTTON_ESC", "NDOF_BUTTON_ESC", ""),
453 ("NDOF_BUTTON_ALT", "NDOF_BUTTON_ALT", ""),
454 ("NDOF_BUTTON_SHIFT", "NDOF_BUTTON_SHIFT", ""),
455 ("NDOF_BUTTON_CTRL", "NDOF_BUTTON_CTRL", ""),
456 ("NDOF_BUTTON_1", "NDOF_BUTTON_1", ""),
457 ("NDOF_BUTTON_2", "NDOF_BUTTON_2", ""),
458 ("NDOF_BUTTON_3", "NDOF_BUTTON_3", ""),
459 ("NDOF_BUTTON_4", "NDOF_BUTTON_4", ""),
460 ("NDOF_BUTTON_5", "NDOF_BUTTON_5", ""),
461 ("NDOF_BUTTON_6", "NDOF_BUTTON_6", ""),
462 ("NDOF_BUTTON_7", "NDOF_BUTTON_7", ""),
463 ("NDOF_BUTTON_8", "NDOF_BUTTON_8", ""),
464 ("NDOF_BUTTON_9", "NDOF_BUTTON_9", ""),
465 ("NDOF_BUTTON_10", "NDOF_BUTTON_10", ""),
466 ("NDOF_BUTTON_A", "NDOF_BUTTON_A", ""),
467 ("NDOF_BUTTON_B", "NDOF_BUTTON_B", ""),
468 ("NDOF_BUTTON_C", "NDOF_BUTTON_C", "")
470 name="Quick Type",
471 description="Enter key code in find text",
472 update=update_data
476 class IsKeyFreeRunExportKeys(Operator):
477 bl_idname = "iskeyfree.run_export_keys"
478 bl_label = "List all Shortcuts"
479 bl_description = ("List all existing shortcuts in a text block\n"
480 "The newly generated list will be made active in the Text Editor\n"
481 "To access the previous ones, select them from the Header dropdown")
483 def all_shortcuts_name(self, context):
484 new_name, def_name, ext = "", "All_Shortcuts", ".txt"
485 suffix = 1
486 try:
487 # first slap a simple linear count + 1 for numeric suffix, if it fails
488 # harvest for the rightmost numbers and append the max value
489 list_txt = []
490 data_txt = bpy.data.texts
491 list_txt = [txt.name for txt in data_txt if txt.name.startswith("All_Shortcuts")]
492 new_name = "{}_{}{}".format(def_name, len(list_txt) + 1, ext)
494 if new_name in list_txt:
495 from re import findall
496 test_num = [findall(r"\d+", words) for words in list_txt]
497 suffix += max([int(l[-1]) for l in test_num])
498 new_name = "{}_{}{}".format(def_name, suffix, ext)
499 return new_name
500 except:
501 return None
503 def unicodelen(self, string):
504 n = 0
505 for c in string:
506 if unicodedata.east_asian_width(c) in 'FWA':
507 n += 2
508 else:
509 n += 1
510 return n
512 def execute(self, context):
513 wm = bpy.context.window_manager
514 from collections import defaultdict
515 mykeys = defaultdict(list)
516 file_name = self.all_shortcuts_name(context) or "All_Shortcut.txt"
517 start_note = "# Note: Some of the shortcuts entries don't have a name. Mostly Modal stuff\n"
518 col_width, col_shortcuts = 2, 2
520 for ctx_type, keyboardmap in wm.keyconfigs.user.keymaps.items():
521 for myitem in keyboardmap.keymap_items:
522 padding = len(myitem.name)
523 col_width = padding + 2 if padding > col_width else col_width
525 short_type = myitem.type if myitem.type else "UNKNOWN"
526 is_ctrl = " Ctrl" if myitem.ctrl else ""
527 is_alt = " Alt" if myitem.alt else ""
528 is_shift = " Shift" if myitem.shift else ""
529 is_oskey = " OsKey" if myitem.oskey else ""
530 short_cuts = "{}{}{}{}{}".format(short_type, is_ctrl, is_alt, is_shift, is_oskey)
532 t = (
533 myitem.name if myitem.name else "No Name",
534 short_cuts,
536 mykeys[ctx_type].append(t)
537 padding_s = len(short_cuts) + 2
538 col_shortcuts = padding_s if padding_s > col_shortcuts else col_shortcuts
540 max_line = col_shortcuts + col_width + 4
541 textblock = bpy.data.texts.new(file_name)
542 total = sum([len(mykeys[ctxs]) for ctxs in mykeys])
543 textblock.write('# %d Total Shortcuts\n\n' % total)
544 textblock.write(start_note)
546 for ctx in mykeys:
547 textblock.write("\n[%s]\nEntries: %s\n\n" % (ctx, len(mykeys[ctx])))
548 line_k = sorted(mykeys[ctx])
549 for keys in line_k:
550 add_ticks = "-" * (max_line - (self.unicodelen(keys[0]) + len(keys[1])))
551 entries = "{ticks} {entry}".format(ticks=add_ticks, entry=keys[1])
552 textblock.write("{name} {entry}\n".format(name=keys[0], entry=entries))
554 textblock.write("\n\n")
556 # try to set the created text block to active
557 if context.area.type in {"TEXT_EDITOR"}:
558 bpy.context.space_data.text = bpy.data.texts[file_name]
560 self.report({'INFO'}, "See %s textblock" % file_name)
562 return {"FINISHED"}
565 # -----------------------------------------------------
566 # Registration
567 # ------------------------------------------------------
568 classes = (
569 IskeyFreeProperties,
570 RunActionCheck,
571 UIControlPanel,
572 IsKeyFreeRunExportKeys,
576 def register():
577 for cls in classes:
578 bpy.utils.register_class(cls)
579 bpy.types.Scene.is_keyfree = PointerProperty(type=IskeyFreeProperties)
582 def unregister():
583 for cls in classes:
584 bpy.utils.unregister_class(cls)
585 del bpy.types.Scene.is_keyfree