Cleanup: replace dict /w list for module reload
[blender.git] / release / scripts / startup / bl_ui / __init__.py
1 # ##### BEGIN GPL LICENSE BLOCK #####
2 #
3 #  This program is free software; you can redistribute it and/or
4 #  modify it under the terms of the GNU General Public License
5 #  as published by the Free Software Foundation; either version 2
6 #  of the License, or (at your option) any later version.
7 #
8 #  This program is distributed in the hope that it will be useful,
9 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 #  GNU General Public License for more details.
12 #
13 #  You should have received a copy of the GNU General Public License
14 #  along with this program; if not, write to the Free Software Foundation,
15 #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 #
17 # ##### END GPL LICENSE BLOCK #####
18
19 # <pep8 compliant>
20
21 # note, properties_animviz is a helper module only.
22
23 if "bpy" in locals():
24     from importlib import reload
25     for val in _modules_loaded:
26         reload(val)
27     del reload
28
29 _modules = [
30     "properties_animviz",
31     "properties_constraint",
32     "properties_data_armature",
33     "properties_data_bone",
34     "properties_data_camera",
35     "properties_data_curve",
36     "properties_data_empty",
37     "properties_data_lamp",
38     "properties_data_lattice",
39     "properties_data_mesh",
40     "properties_data_metaball",
41     "properties_data_modifier",
42     "properties_data_speaker",
43     "properties_game",
44     "properties_mask_common",
45     "properties_material",
46     "properties_object",
47     "properties_paint_common",
48     "properties_grease_pencil_common",
49     "properties_particle",
50     "properties_physics_cloth",
51     "properties_physics_common",
52     "properties_physics_dynamicpaint",
53     "properties_physics_field",
54     "properties_physics_fluid",
55     "properties_physics_rigidbody",
56     "properties_physics_rigidbody_constraint",
57     "properties_physics_smoke",
58     "properties_physics_softbody",
59     "properties_render",
60     "properties_render_layer",
61     "properties_scene",
62     "properties_texture",
63     "properties_world",
64     "space_clip",
65     "space_console",
66     "space_dopesheet",
67     "space_filebrowser",
68     "space_graph",
69     "space_image",
70     "space_info",
71     "space_logic",
72     "space_nla",
73     "space_node",
74     "space_outliner",
75     "space_properties",
76     "space_sequencer",
77     "space_text",
78     "space_time",
79     "space_userpref",
80     "space_view3d",
81     "space_view3d_toolbar",
82     ]
83
84 import bpy
85
86 if bpy.app.build_options.freestyle:
87     _modules.append("properties_freestyle")
88
89 __import__(name=__name__, fromlist=_modules)
90 _namespace = globals()
91 _modules_loaded = [_namespace[name] for name in _modules]
92 del _namespace
93
94
95 def register():
96     bpy.utils.register_module(__name__)
97
98     # space_userprefs.py
99     from bpy.props import StringProperty, EnumProperty
100     from bpy.types import WindowManager
101
102     def addon_filter_items(self, context):
103         import addon_utils
104
105         items = [('All', "All", "All Add-ons"),
106                  ('User', "User", "All Add-ons Installed by User"),
107                  ('Enabled', "Enabled", "All Enabled Add-ons"),
108                  ('Disabled', "Disabled", "All Disabled Add-ons"),
109                  ]
110
111         items_unique = set()
112
113         for mod in addon_utils.modules(refresh=False):
114             info = addon_utils.module_bl_info(mod)
115             items_unique.add(info["category"])
116
117         items.extend([(cat, cat, "") for cat in sorted(items_unique)])
118         return items
119
120     WindowManager.addon_search = StringProperty(
121             name="Search",
122             description="Search within the selected filter",
123             options={'TEXTEDIT_UPDATE'},
124             )
125     WindowManager.addon_filter = EnumProperty(
126             items=addon_filter_items,
127             name="Category",
128             description="Filter addons by category",
129             )
130
131     WindowManager.addon_support = EnumProperty(
132             items=[('OFFICIAL', "Official", "Officially supported"),
133                    ('COMMUNITY', "Community", "Maintained by community developers"),
134                    ('TESTING', "Testing", "Newly contributed scripts (excluded from release builds)")
135                    ],
136             name="Support",
137             description="Display support level",
138             default={'OFFICIAL', 'COMMUNITY'},
139             options={'ENUM_FLAG'},
140             )
141     # done...
142
143
144 def unregister():
145     bpy.utils.unregister_module(__name__)
146
147
148 # Define a default UIList, when a list does not need any custom drawing...
149 # Keep in sync with its #defined name in UI_interface.h
150 class UI_UL_list(bpy.types.UIList):
151     # These are common filtering or ordering operations (same as the default C ones!).
152     @staticmethod
153     def filter_items_by_name(pattern, bitflag, items, propname="name", flags=None, reverse=False):
154         """
155         Set FILTER_ITEM for items which name matches filter_name one (case-insensitive).
156         pattern is the filtering pattern.
157         propname is the name of the string property to use for filtering.
158         flags must be a list of integers the same length as items, or None!
159         return a list of flags (based on given flags if not None),
160         or an empty list if no flags were given and no filtering has been done.
161         """
162         import fnmatch
163
164         if not pattern or not items:  # Empty pattern or list = no filtering!
165             return flags or []
166
167         if flags is None:
168             flags = [0] * len(items)
169
170         # Implicitly add heading/trailing wildcards.
171         pattern = "*" + pattern + "*"
172
173         for i, item in enumerate(items):
174             name = getattr(item, propname, None)
175             # This is similar to a logical xor
176             if bool(name and fnmatch.fnmatchcase(name, pattern)) is not bool(reverse):
177                 flags[i] |= bitflag
178         return flags
179
180     @staticmethod
181     def sort_items_helper(sort_data, key, reverse=False):
182         """
183         Common sorting utility. Returns a neworder list mapping org_idx -> new_idx.
184         sort_data must be an (unordered) list of tuples [(org_idx, ...), (org_idx, ...), ...].
185         key must be the same kind of callable you would use for sorted() builtin function.
186         reverse will reverse the sorting!
187         """
188         sort_data.sort(key=key, reverse=reverse)
189         neworder = [None] * len(sort_data)
190         for newidx, (orgidx, *_) in enumerate(sort_data):
191             neworder[orgidx] = newidx
192         return neworder
193
194     @classmethod
195     def sort_items_by_name(cls, items, propname="name"):
196         """
197         Re-order items using their names (case-insensitive).
198         propname is the name of the string property to use for sorting.
199         return a list mapping org_idx -> new_idx,
200                or an empty list if no sorting has been done.
201         """
202         _sort = [(idx, getattr(it, propname, "")) for idx, it in enumerate(items)]
203         return cls.sort_items_helper(_sort, lambda e: e[1].lower())
204
205
206 bpy.utils.register_class(UI_UL_list)