fix for keymap export, move functions common for the UI and operators into bpy_extras...
authorCampbell Barton <ideasman42@gmail.com>
Mon, 26 Sep 2011 11:22:07 +0000 (11:22 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Mon, 26 Sep 2011 11:22:07 +0000 (11:22 +0000)
release/scripts/modules/bpy_extras/__init__.py
release/scripts/modules/bpy_extras/keyconfig_utils.py [new file with mode: 0644]
release/scripts/startup/bl_operators/wm.py
release/scripts/startup/bl_ui/space_userpref_keymap.py

index fd653a4129ca67fe65b5d2eb43806d23a9c0c7b9..7d74bc32f91f2ec6934f1e689fe23c82a8909cc7 100644 (file)
@@ -27,6 +27,7 @@ __all__ = (
     "object_utils",
     "io_utils",
     "image_utils",
+    "keyconfig_utils",
     "mesh_utils",
     "view3d_utils",
     )
diff --git a/release/scripts/modules/bpy_extras/keyconfig_utils.py b/release/scripts/modules/bpy_extras/keyconfig_utils.py
new file mode 100644 (file)
index 0000000..081b078
--- /dev/null
@@ -0,0 +1,303 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+KM_HIERARCHY = [
+    ('Window', 'EMPTY', 'WINDOW', []),  # file save, window change, exit
+    ('Screen', 'EMPTY', 'WINDOW', [     # full screen, undo, screenshot
+        ('Screen Editing', 'EMPTY', 'WINDOW', []),    # resizing, action corners
+        ]),
+
+    ('View2D', 'EMPTY', 'WINDOW', []),    # view 2d navigation (per region)
+    ('View2D Buttons List', 'EMPTY', 'WINDOW', []),  # view 2d with buttons navigation
+    ('Header', 'EMPTY', 'WINDOW', []),    # header stuff (per region)
+    ('Grease Pencil', 'EMPTY', 'WINDOW', []),  # grease pencil stuff (per region)
+
+    ('3D View', 'VIEW_3D', 'WINDOW', [  # view 3d navigation and generic stuff (select, transform)
+        ('Object Mode', 'EMPTY', 'WINDOW', []),
+        ('Mesh', 'EMPTY', 'WINDOW', []),
+        ('Curve', 'EMPTY', 'WINDOW', []),
+        ('Armature', 'EMPTY', 'WINDOW', []),
+        ('Metaball', 'EMPTY', 'WINDOW', []),
+        ('Lattice', 'EMPTY', 'WINDOW', []),
+        ('Font', 'EMPTY', 'WINDOW', []),
+
+        ('Pose', 'EMPTY', 'WINDOW', []),
+
+        ('Vertex Paint', 'EMPTY', 'WINDOW', []),
+        ('Weight Paint', 'EMPTY', 'WINDOW', []),
+        ('Face Mask', 'EMPTY', 'WINDOW', []),
+        ('Image Paint', 'EMPTY', 'WINDOW', []),  # image and view3d
+        ('Sculpt', 'EMPTY', 'WINDOW', []),
+
+        ('Armature Sketch', 'EMPTY', 'WINDOW', []),
+        ('Particle', 'EMPTY', 'WINDOW', []),
+
+        ('Object Non-modal', 'EMPTY', 'WINDOW', []),  # mode change
+
+        ('3D View Generic', 'VIEW_3D', 'WINDOW', [])    # toolbar and properties
+        ]),
+
+    ('Frames', 'EMPTY', 'WINDOW', []),    # frame navigation (per region)
+    ('Markers', 'EMPTY', 'WINDOW', []),    # markers (per region)
+    ('Animation', 'EMPTY', 'WINDOW', []),    # frame change on click, preview range (per region)
+    ('Animation Channels', 'EMPTY', 'WINDOW', []),
+    ('Graph Editor', 'GRAPH_EDITOR', 'WINDOW', [
+        ('Graph Editor Generic', 'GRAPH_EDITOR', 'WINDOW', [])
+        ]),
+    ('Dopesheet', 'DOPESHEET_EDITOR', 'WINDOW', []),
+    ('NLA Editor', 'NLA_EDITOR', 'WINDOW', [
+        ('NLA Channels', 'NLA_EDITOR', 'WINDOW', []),
+        ('NLA Generic', 'NLA_EDITOR', 'WINDOW', [])
+        ]),
+
+    ('Image', 'IMAGE_EDITOR', 'WINDOW', [
+        ('UV Editor', 'EMPTY', 'WINDOW', []),  # image (reverse order, UVEdit before Image
+        ('Image Paint', 'EMPTY', 'WINDOW', []),  # image and view3d
+        ('Image Generic', 'IMAGE_EDITOR', 'WINDOW', [])
+        ]),
+
+    ('Timeline', 'TIMELINE', 'WINDOW', []),
+    ('Outliner', 'OUTLINER', 'WINDOW', []),
+
+    ('Node Editor', 'NODE_EDITOR', 'WINDOW', [
+        ('Node Generic', 'NODE_EDITOR', 'WINDOW', [])
+        ]),
+    ('Sequencer', 'SEQUENCE_EDITOR', 'WINDOW', []),
+    ('Logic Editor', 'LOGIC_EDITOR', 'WINDOW', []),
+
+    ('File Browser', 'FILE_BROWSER', 'WINDOW', [
+        ('File Browser Main', 'FILE_BROWSER', 'WINDOW', []),
+        ('File Browser Buttons', 'FILE_BROWSER', 'WINDOW', [])
+        ]),
+
+    ('Property Editor', 'PROPERTIES', 'WINDOW', []),  # align context menu
+
+    ('Script', 'SCRIPTS_WINDOW', 'WINDOW', []),
+    ('Text', 'TEXT_EDITOR', 'WINDOW', []),
+    ('Console', 'CONSOLE', 'WINDOW', []),
+
+    ('View3D Gesture Circle', 'EMPTY', 'WINDOW', []),
+    ('Gesture Border', 'EMPTY', 'WINDOW', []),
+    ('Standard Modal Map', 'EMPTY', 'WINDOW', []),
+    ('Transform Modal Map', 'EMPTY', 'WINDOW', []),
+    ('View3D Fly Modal', 'EMPTY', 'WINDOW', []),
+    ('View3D Rotate Modal', 'EMPTY', 'WINDOW', []),
+    ('View3D Move Modal', 'EMPTY', 'WINDOW', []),
+    ('View3D Zoom Modal', 'EMPTY', 'WINDOW', []),
+    ]
+
+
+# -----------------------------------------------------------------------------
+# Utility functions
+
+def km_exists_in(km, export_keymaps):
+    for km2, kc in export_keymaps:
+        if km2.name == km.name:
+            return True
+    return False
+
+
+def keyconfig_merge(kc1, kc2):
+    """ note: kc1 takes priority over kc2
+    """
+    merged_keymaps = [(km, kc1) for km in kc1.keymaps]
+    if kc1 != kc2:
+        merged_keymaps.extend((km, kc2) for km in kc2.keymaps if not _km_exists_in(km, merged_keymaps))
+
+    return merged_keymaps
+
+
+def keyconfig_export(wm, kc, filepath):
+    from bpy.types import OperatorProperties
+
+    def string_value(value):
+        if isinstance(value, str) or isinstance(value, bool) or isinstance(value, float) or isinstance(value, int):
+            result = repr(value)
+        elif getattr(value, '__len__', False):
+            return repr(list(value))
+        else:
+            print("Export key configuration: can't write ", value)
+
+        return result
+
+    def export_properties(prefix, properties, lines=None):
+        if lines is None:
+            lines = []
+
+        for pname in properties.bl_rna.properties.keys():
+            if pname != "rna_type" and not properties.is_property_hidden(pname):
+                value = getattr(properties, pname)
+                if isinstance(value, OperatorProperties):
+                    export_properties(prefix + "." + pname, value, lines)
+                elif properties.is_property_set(pname):
+                    value = string_value(value)
+                    if value != "":
+                        lines.append("%s.%s = %s\n" % (prefix, pname, value))
+        return lines
+
+    f = open(filepath, "w")
+
+    f.write("import bpy\n")
+    f.write("import os\n\n")
+    f.write("wm = bpy.context.window_manager\n")
+    f.write("kc = wm.keyconfigs.new(os.path.splitext(os.path.basename(__file__))[0])\n\n")  # keymap must be created by caller
+
+    # Generate a list of keymaps to export:
+    #
+    # First add all user_modified keymaps (found in keyconfigs.user.keymaps list),
+    # then add all remaining keymaps from the currently active custom keyconfig.
+    #
+    # This will create a final list of keymaps that can be used as a 'diff' against
+    # the default blender keyconfig, recreating the current setup from a fresh blender
+    # without needing to export keymaps which haven't been edited.
+
+    class FakeKeyConfig():
+        keymaps = []
+    edited_kc = FakeKeyConfig()
+    for km in wm.keyconfigs.user.keymaps:
+        if km.is_user_modified:
+            edited_kc.keymaps.append(km)
+    # merge edited keymaps with non-default keyconfig, if it exists
+    if kc != wm.keyconfigs.default:
+        export_keymaps = keyconfig_merge(edited_kc, kc)
+    else:
+        export_keymaps = keyconfig_merge(edited_kc, edited_kc)
+
+    for km, kc_x in export_keymaps:
+
+        km = km.active()
+
+        f.write("# Map %s\n" % km.name)
+        f.write("km = kc.keymaps.new('%s', space_type='%s', region_type='%s', modal=%s)\n\n" % (km.name, km.space_type, km.region_type, km.is_modal))
+        for kmi in km.keymap_items:
+            if km.is_modal:
+                f.write("kmi = km.keymap_items.new_modal('%s', '%s', '%s'" % (kmi.propvalue, kmi.type, kmi.value))
+            else:
+                f.write("kmi = km.keymap_items.new('%s', '%s', '%s'" % (kmi.idname, kmi.type, kmi.value))
+            if kmi.any:
+                f.write(", any=True")
+            else:
+                if kmi.shift:
+                    f.write(", shift=True")
+                if kmi.ctrl:
+                    f.write(", ctrl=True")
+                if kmi.alt:
+                    f.write(", alt=True")
+                if kmi.oskey:
+                    f.write(", oskey=True")
+            if kmi.key_modifier and kmi.key_modifier != 'NONE':
+                f.write(", key_modifier='%s'" % kmi.key_modifier)
+            f.write(")\n")
+
+            props = kmi.properties
+
+            if props is not None:
+                f.write("".join(export_properties("kmi.properties", props)))
+
+        f.write("\n")
+
+    f.close()
+
+
+def keyconfig_test(kc):
+
+    def testEntry(self, kc, entry, src=None, parent=None):
+        result = False
+
+        def kmistr(kmi):
+            if km.is_modal:
+                s = ["kmi = km.keymap_items.new_modal(\'%s\', \'%s\', \'%s\'" % (kmi.propvalue, kmi.type, kmi.value)]
+            else:
+                s = ["kmi = km.keymap_items.new(\'%s\', \'%s\', \'%s\'" % (kmi.idname, kmi.type, kmi.value)]
+
+            if kmi.any:
+                s.append(", any=True")
+            else:
+                if kmi.shift:
+                    s.append(", shift=True")
+                if kmi.ctrl:
+                    s.append(", ctrl=True")
+                if kmi.alt:
+                    s.append(", alt=True")
+                if kmi.oskey:
+                    s.append(", oskey=True")
+            if kmi.key_modifier and kmi.key_modifier != 'NONE':
+                s.append(", key_modifier=\'%s\'" % kmi.key_modifier)
+
+            s.append(")\n")
+
+            props = kmi.properties
+
+            if props is not None:
+                export_properties("kmi.properties", props, s)
+
+            return "".join(s).strip()
+
+        idname, spaceid, regionid, children = entry
+
+        km = kc.keymaps.find(idname, space_type=spaceid, region_type=regionid)
+
+        if km:
+            km = km.active()
+
+            if src:
+                for item in km.keymap_items:
+                    if src.compare(item):
+                        print("===========")
+                        print(parent.name)
+                        print(kmistr(src))
+                        print(km.name)
+                        print(kmistr(item))
+                        result = True
+
+                for child in children:
+                    if testEntry(kc, child, src, parent):
+                        result = True
+            else:
+                for i in range(len(km.keymap_items)):
+                    src = km.keymap_items[i]
+
+                    for child in children:
+                        if testEntry(kc, child, src, km):
+                            result = True
+
+                    for j in range(len(km.keymap_items) - i - 1):
+                        item = km.keymap_items[j + i + 1]
+                        if src.compare(item):
+                            print("===========")
+                            print(km.name)
+                            print(kmistr(src))
+                            print(kmistr(item))
+                            result = True
+
+                for child in children:
+                    if testEntry(kc, child):
+                        result = True
+
+        return result
+
+    # -------------------------------------------------------------------------
+    # Function body
+
+    result = False
+    for entry in KM_HIERARCHY:
+        if testEntry(kc, entry):
+            result = True
+    return result
index d4ed8879e40c81ff8d1936d084b755a6d5b5f533..72efdeeb5b31b44d143f352a697d58b7ae30f26b 100644 (file)
@@ -1186,109 +1186,18 @@ class WM_OT_keyconfig_test(Operator):
     bl_idname = "wm.keyconfig_test"
     bl_label = "Test Key Configuration for Conflicts"
 
-    def testEntry(self, kc, entry, src=None, parent=None):
-        result = False
-
-        def kmistr(kmi):
-            if km.is_modal:
-                s = ["kmi = km.keymap_items.new_modal(\'%s\', \'%s\', \'%s\'" % (kmi.propvalue, kmi.type, kmi.value)]
-            else:
-                s = ["kmi = km.keymap_items.new(\'%s\', \'%s\', \'%s\'" % (kmi.idname, kmi.type, kmi.value)]
-
-            if kmi.any:
-                s.append(", any=True")
-            else:
-                if kmi.shift:
-                    s.append(", shift=True")
-                if kmi.ctrl:
-                    s.append(", ctrl=True")
-                if kmi.alt:
-                    s.append(", alt=True")
-                if kmi.oskey:
-                    s.append(", oskey=True")
-            if kmi.key_modifier and kmi.key_modifier != 'NONE':
-                s.append(", key_modifier=\'%s\'" % kmi.key_modifier)
-
-            s.append(")\n")
-
-            props = kmi.properties
-
-            if props is not None:
-                export_properties("kmi.properties", props, s)
-
-            return "".join(s).strip()
-
-        idname, spaceid, regionid, children = entry
-
-        km = kc.keymaps.find(idname, space_type=spaceid, region_type=regionid)
-
-        if km:
-            km = km.active()
-
-            if src:
-                for item in km.keymap_items:
-                    if src.compare(item):
-                        print("===========")
-                        print(parent.name)
-                        print(kmistr(src))
-                        print(km.name)
-                        print(kmistr(item))
-                        result = True
-
-                for child in children:
-                    if self.testEntry(kc, child, src, parent):
-                        result = True
-            else:
-                for i in range(len(km.keymap_items)):
-                    src = km.keymap_items[i]
-
-                    for child in children:
-                        if self.testEntry(kc, child, src, km):
-                            result = True
-
-                    for j in range(len(km.keymap_items) - i - 1):
-                        item = km.keymap_items[j + i + 1]
-                        if src.compare(item):
-                            print("===========")
-                            print(km.name)
-                            print(kmistr(src))
-                            print(kmistr(item))
-                            result = True
-
-                for child in children:
-                    if self.testEntry(kc, child):
-                        result = True
-
-        return result
-
-    def testConfig(self, kc):
-        result = False
-        for entry in KM_HIERARCHY:
-            if self.testEntry(kc, entry):
-                result = True
-        return result
-
     def execute(self, context):
+        from bpy_extras import keyconfig_utils
+
         wm = context.window_manager
         kc = wm.keyconfigs.default
 
-        if self.testConfig(kc):
+        if keyconfig_utils.keyconfig_test(kc):
             print("CONFLICT")
 
         return {'FINISHED'}
 
 
-def _string_value(value):
-    if isinstance(value, str) or isinstance(value, bool) or isinstance(value, float) or isinstance(value, int):
-        result = repr(value)
-    elif getattr(value, '__len__', False):
-        return repr(list(value))
-    else:
-        print("Export key configuration: can't write ", value)
-
-    return result
-
-
 class WM_OT_keyconfig_import(Operator):
     "Import key configuration from a python script"
     bl_idname = "wm.keyconfig_import"
@@ -1383,79 +1292,20 @@ class WM_OT_keyconfig_export(Operator):
             )
 
     def execute(self, context):
+        from bpy_extras import keyconfig_utils
+
         if not self.filepath:
             raise Exception("Filepath not set")
 
         if not self.filepath.endswith('.py'):
             self.filepath += '.py'
 
-        f = open(self.filepath, "w")
-        if not f:
-            raise Exception("Could not open file")
-
         wm = context.window_manager
-        kc = wm.keyconfigs.active
-
-        f.write("import bpy\n")
-        f.write("import os\n\n")
-        f.write("wm = bpy.context.window_manager\n")
-        f.write("kc = wm.keyconfigs.new(os.path.splitext(os.path.basename(__file__))[0])\n\n")  # keymap must be created by caller
-
-        # Generate a list of keymaps to export:
-        #
-        # First add all user_modified keymaps (found in keyconfigs.user.keymaps list),
-        # then add all remaining keymaps from the currently active custom keyconfig.
-        #
-        # This will create a final list of keymaps that can be used as a 'diff' against
-        # the default blender keyconfig, recreating the current setup from a fresh blender
-        # without needing to export keymaps which haven't been edited.
-
-        class FakeKeyConfig():
-            keymaps = []
-        edited_kc = FakeKeyConfig()
-        for km in wm.keyconfigs.user.keymaps:
-            if km.is_user_modified:
-                edited_kc.keymaps.append(km)
-        # merge edited keymaps with non-default keyconfig, if it exists
-        if kc != wm.keyconfigs.default:
-            export_keymaps = _merge_keymaps(edited_kc, kc)
-        else:
-            export_keymaps = _merge_keymaps(edited_kc, edited_kc)
-
-        for km, kc_x in export_keymaps:
 
-            km = km.active()
-
-            f.write("# Map %s\n" % km.name)
-            f.write("km = kc.keymaps.new('%s', space_type='%s', region_type='%s', modal=%s)\n\n" % (km.name, km.space_type, km.region_type, km.is_modal))
-            for kmi in km.keymap_items:
-                if km.is_modal:
-                    f.write("kmi = km.keymap_items.new_modal('%s', '%s', '%s'" % (kmi.propvalue, kmi.type, kmi.value))
-                else:
-                    f.write("kmi = km.keymap_items.new('%s', '%s', '%s'" % (kmi.idname, kmi.type, kmi.value))
-                if kmi.any:
-                    f.write(", any=True")
-                else:
-                    if kmi.shift:
-                        f.write(", shift=True")
-                    if kmi.ctrl:
-                        f.write(", ctrl=True")
-                    if kmi.alt:
-                        f.write(", alt=True")
-                    if kmi.oskey:
-                        f.write(", oskey=True")
-                if kmi.key_modifier and kmi.key_modifier != 'NONE':
-                    f.write(", key_modifier='%s'" % kmi.key_modifier)
-                f.write(")\n")
-
-                props = kmi.properties
-
-                if props is not None:
-                    f.write("".join(export_properties("kmi.properties", props)))
-
-            f.write("\n")
-
-        f.close()
+        keyconfig_utils.keyconfig_export(wm,
+                                         wm.keyconfigs.active,
+                                         self.filepath,
+                                         )
 
         return {'FINISHED'}
 
@@ -1842,6 +1692,7 @@ class WM_OT_addon_remove(Operator):
 
     def execute(self, context):
         import addon_utils
+        import os
 
         path, isdir = WM_OT_addon_remove.path_from_addon(self.module)
         if path is None:
index dcf9a7d2d7feb245595519260bcc45554f8e1670..79b13e3bec0d0608089ddeedec7bdafddc2b9bbd 100644 (file)
@@ -22,109 +22,6 @@ from bpy.types import Menu, OperatorProperties
 import os
 
 
-KM_HIERARCHY = [
-    ('Window', 'EMPTY', 'WINDOW', []),  # file save, window change, exit
-    ('Screen', 'EMPTY', 'WINDOW', [     # full screen, undo, screenshot
-        ('Screen Editing', 'EMPTY', 'WINDOW', []),    # resizing, action corners
-        ]),
-
-    ('View2D', 'EMPTY', 'WINDOW', []),    # view 2d navigation (per region)
-    ('View2D Buttons List', 'EMPTY', 'WINDOW', []),  # view 2d with buttons navigation
-    ('Header', 'EMPTY', 'WINDOW', []),    # header stuff (per region)
-    ('Grease Pencil', 'EMPTY', 'WINDOW', []),  # grease pencil stuff (per region)
-
-    ('3D View', 'VIEW_3D', 'WINDOW', [  # view 3d navigation and generic stuff (select, transform)
-        ('Object Mode', 'EMPTY', 'WINDOW', []),
-        ('Mesh', 'EMPTY', 'WINDOW', []),
-        ('Curve', 'EMPTY', 'WINDOW', []),
-        ('Armature', 'EMPTY', 'WINDOW', []),
-        ('Metaball', 'EMPTY', 'WINDOW', []),
-        ('Lattice', 'EMPTY', 'WINDOW', []),
-        ('Font', 'EMPTY', 'WINDOW', []),
-
-        ('Pose', 'EMPTY', 'WINDOW', []),
-
-        ('Vertex Paint', 'EMPTY', 'WINDOW', []),
-        ('Weight Paint', 'EMPTY', 'WINDOW', []),
-        ('Face Mask', 'EMPTY', 'WINDOW', []),
-        ('Image Paint', 'EMPTY', 'WINDOW', []),  # image and view3d
-        ('Sculpt', 'EMPTY', 'WINDOW', []),
-
-        ('Armature Sketch', 'EMPTY', 'WINDOW', []),
-        ('Particle', 'EMPTY', 'WINDOW', []),
-
-        ('Object Non-modal', 'EMPTY', 'WINDOW', []),  # mode change
-
-        ('3D View Generic', 'VIEW_3D', 'WINDOW', [])    # toolbar and properties
-        ]),
-
-    ('Frames', 'EMPTY', 'WINDOW', []),    # frame navigation (per region)
-    ('Markers', 'EMPTY', 'WINDOW', []),    # markers (per region)
-    ('Animation', 'EMPTY', 'WINDOW', []),    # frame change on click, preview range (per region)
-    ('Animation Channels', 'EMPTY', 'WINDOW', []),
-    ('Graph Editor', 'GRAPH_EDITOR', 'WINDOW', [
-        ('Graph Editor Generic', 'GRAPH_EDITOR', 'WINDOW', [])
-        ]),
-    ('Dopesheet', 'DOPESHEET_EDITOR', 'WINDOW', []),
-    ('NLA Editor', 'NLA_EDITOR', 'WINDOW', [
-        ('NLA Channels', 'NLA_EDITOR', 'WINDOW', []),
-        ('NLA Generic', 'NLA_EDITOR', 'WINDOW', [])
-        ]),
-
-    ('Image', 'IMAGE_EDITOR', 'WINDOW', [
-        ('UV Editor', 'EMPTY', 'WINDOW', []),  # image (reverse order, UVEdit before Image
-        ('Image Paint', 'EMPTY', 'WINDOW', []),  # image and view3d
-        ('Image Generic', 'IMAGE_EDITOR', 'WINDOW', [])
-        ]),
-
-    ('Timeline', 'TIMELINE', 'WINDOW', []),
-    ('Outliner', 'OUTLINER', 'WINDOW', []),
-
-    ('Node Editor', 'NODE_EDITOR', 'WINDOW', [
-        ('Node Generic', 'NODE_EDITOR', 'WINDOW', [])
-        ]),
-    ('Sequencer', 'SEQUENCE_EDITOR', 'WINDOW', []),
-    ('Logic Editor', 'LOGIC_EDITOR', 'WINDOW', []),
-
-    ('File Browser', 'FILE_BROWSER', 'WINDOW', [
-        ('File Browser Main', 'FILE_BROWSER', 'WINDOW', []),
-        ('File Browser Buttons', 'FILE_BROWSER', 'WINDOW', [])
-        ]),
-
-    ('Property Editor', 'PROPERTIES', 'WINDOW', []),  # align context menu
-
-    ('Script', 'SCRIPTS_WINDOW', 'WINDOW', []),
-    ('Text', 'TEXT_EDITOR', 'WINDOW', []),
-    ('Console', 'CONSOLE', 'WINDOW', []),
-
-    ('View3D Gesture Circle', 'EMPTY', 'WINDOW', []),
-    ('Gesture Border', 'EMPTY', 'WINDOW', []),
-    ('Standard Modal Map', 'EMPTY', 'WINDOW', []),
-    ('Transform Modal Map', 'EMPTY', 'WINDOW', []),
-    ('View3D Fly Modal', 'EMPTY', 'WINDOW', []),
-    ('View3D Rotate Modal', 'EMPTY', 'WINDOW', []),
-    ('View3D Move Modal', 'EMPTY', 'WINDOW', []),
-    ('View3D Zoom Modal', 'EMPTY', 'WINDOW', []),
-    ]
-
-
-def _km_exists_in(km, export_keymaps):
-    for km2, kc in export_keymaps:
-        if km2.name == km.name:
-            return True
-    return False
-
-
-def _merge_keymaps(kc1, kc2):
-    """ note: kc1 takes priority over kc2
-    """
-    merged_keymaps = [(km, kc1) for km in kc1.keymaps]
-    if kc1 != kc2:
-        merged_keymaps.extend((km, kc2) for km in kc2.keymaps if not _km_exists_in(km, merged_keymaps))
-
-    return merged_keymaps
-
-
 class USERPREF_MT_keyconfigs(Menu):
     bl_label = "KeyPresets"
     preset_subdir = "keyconfig"
@@ -363,10 +260,13 @@ class InputKeyMapPanel:
                 subcol.operator("wm.keyitem_add", text="Add New", icon='ZOOMIN')
 
     def draw_hierarchy(self, display_keymaps, layout):
-        for entry in KM_HIERARCHY:
+        from bpy_extras import keyconfig_utils
+        for entry in keyconfig_utils.KM_HIERARCHY:
             self.draw_entry(display_keymaps, entry, layout)
 
     def draw_keymaps(self, context, layout):
+        from bpy_extras import keyconfig_utils
+
         wm = context.window_manager
         kc = wm.keyconfigs.user
 
@@ -393,7 +293,7 @@ class InputKeyMapPanel:
 
         col.separator()
 
-        display_keymaps = _merge_keymaps(kc, kc)
+        display_keymaps = keyconfig_utils.keyconfig_merge(kc, kc)
         if context.space_data.filter_text != "":
             filter_text = context.space_data.filter_text.lower()
             self.draw_filtered(display_keymaps, filter_text, col)
@@ -401,20 +301,5 @@ class InputKeyMapPanel:
             self.draw_hierarchy(display_keymaps, col)
 
 
-def export_properties(prefix, properties, lines=None):
-    if lines is None:
-        lines = []
-
-    for pname in properties.bl_rna.properties.keys():
-        if pname != "rna_type" and not properties.is_property_hidden(pname):
-            value = getattr(properties, pname)
-            if isinstance(value, OperatorProperties):
-                export_properties(prefix + "." + pname, value, lines)
-            elif properties.is_property_set(pname):
-                value = _string_value(value)
-                if value != "":
-                    lines.append("%s.%s = %s\n" % (prefix, pname, value))
-    return lines
-
 if __name__ == "__main__":  # only for live edit.
     bpy.utils.register_module(__name__)