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