remove use of gettext: _("...") style translation now its handled by rna.
[blender.git] / release / scripts / startup / bl_ui / space_userpref.py
index c598788006c67a6d2e26e9c284e62f7ed96d583f..9573f6b0f5c96ef3cec413017096f69e36741274 100644 (file)
@@ -18,6 +18,7 @@
 
 # <pep8 compliant>
 import bpy
+from bpy.types import Header, Menu, Operator, Panel
 import os
 import addon_utils
 
@@ -75,7 +76,7 @@ def opengl_lamp_buttons(column, lamp):
     col.prop(lamp, "direction", text="")
 
 
-class USERPREF_HT_header(bpy.types.Header):
+class USERPREF_HT_header(Header):
     bl_space_type = 'USER_PREFERENCES'
 
     def draw(self, context):
@@ -99,7 +100,7 @@ class USERPREF_HT_header(bpy.types.Header):
             layout.operator("ui.reset_default_theme")
 
 
-class USERPREF_PT_tabs(bpy.types.Panel):
+class USERPREF_PT_tabs(Panel):
     bl_label = ""
     bl_space_type = 'USER_PREFERENCES'
     bl_region_type = 'WINDOW'
@@ -113,26 +114,26 @@ class USERPREF_PT_tabs(bpy.types.Panel):
         layout.prop(userpref, "active_section", expand=True)
 
 
-class USERPREF_MT_interaction_presets(bpy.types.Menu):
+class USERPREF_MT_interaction_presets(Menu):
     bl_label = "Presets"
     preset_subdir = "interaction"
     preset_operator = "script.execute_preset"
-    draw = bpy.types.Menu.draw_preset
+    draw = Menu.draw_preset
 
 
-class USERPREF_MT_appconfigs(bpy.types.Menu):
+class USERPREF_MT_appconfigs(Menu):
     bl_label = "AppPresets"
     preset_subdir = "keyconfig"
     preset_operator = "wm.appconfig_activate"
 
     def draw(self, context):
-        props = self.layout.operator("wm.appconfig_default", text="Blender (default)")
+        self.layout.operator("wm.appconfig_default", text="Blender (default)")
 
         # now draw the presets
-        bpy.types.Menu.draw_preset(self, context)
+        Menu.draw_preset(self, context)
 
 
-class USERPREF_MT_splash(bpy.types.Menu):
+class USERPREF_MT_splash(Menu):
     bl_label = "Splash"
 
     def draw(self, context):
@@ -149,7 +150,7 @@ class USERPREF_MT_splash(bpy.types.Menu):
         row.menu("USERPREF_MT_appconfigs", text="Preset")
 
 
-class USERPREF_PT_interface(bpy.types.Panel):
+class USERPREF_PT_interface(Panel):
     bl_space_type = 'USER_PREFERENCES'
     bl_label = "Interface"
     bl_region_type = 'WINDOW'
@@ -246,7 +247,7 @@ class USERPREF_PT_interface(bpy.types.Panel):
         col.prop(view, "show_splash")
 
 
-class USERPREF_PT_edit(bpy.types.Panel):
+class USERPREF_PT_edit(Panel):
     bl_space_type = 'USER_PREFERENCES'
     bl_label = "Edit"
     bl_region_type = 'WINDOW'
@@ -359,7 +360,7 @@ class USERPREF_PT_edit(bpy.types.Panel):
         col.prop(edit, "use_duplicate_particle", text="Particle")
 
 
-class USERPREF_PT_system(bpy.types.Panel):
+class USERPREF_PT_system(Panel):
     bl_space_type = 'USER_PREFERENCES'
     bl_label = "System"
     bl_region_type = 'WINDOW'
@@ -416,20 +417,6 @@ class USERPREF_PT_system(bpy.types.Panel):
         col.separator()
         col.separator()
 
-        #column = split.column()
-        #colsplit = column.split(percentage=0.85)
-
-        # No translation in 2.5 yet
-        #col.prop(system, "language")
-        #col.label(text="Translate:")
-        #col.prop(system, "use_translate_tooltips", text="Tooltips")
-        #col.prop(system, "use_translate_buttons", text="Labels")
-        #col.prop(system, "use_translate_toolbox", text="Toolbox")
-
-        #col.separator()
-
-        #col.prop(system, "use_textured_fonts")
-
         # 2. Column
         column = split.column()
         colsplit = column.split(percentage=0.85)
@@ -479,15 +466,11 @@ class USERPREF_PT_system(bpy.types.Panel):
         lamp = system.solid_lights[2]
         opengl_lamp_buttons(column, lamp)
 
-        column.separator()
-        column.separator()
         column.separator()
 
         column.label(text="Color Picker Type:")
         column.row().prop(system, "color_picker_type", text="")
 
-        column.separator()
-        column.separator()
         column.separator()
 
         column.prop(system, "use_weight_color_range", text="Custom Weight Paint Range")
@@ -495,8 +478,18 @@ class USERPREF_PT_system(bpy.types.Panel):
         sub.active = system.use_weight_color_range
         sub.template_color_ramp(system, "weight_color_range", expand=True)
 
+        column.separator()
+
+        column.prop(system, "use_international_fonts")
+        if system.use_international_fonts:
+            column.prop(system, "language")
+            row = column.row()
+            row.label(text="Translate:")
+            row.prop(system, "use_translate_interface", text="Interface")
+            row.prop(system, "use_translate_tooltips", text="Tooltips")
+
 
-class USERPREF_PT_theme(bpy.types.Panel):
+class USERPREF_PT_theme(Panel):
     bl_space_type = 'USER_PREFERENCES'
     bl_label = "Themes"
     bl_region_type = 'WINDOW'
@@ -656,7 +649,7 @@ class USERPREF_PT_theme(bpy.types.Panel):
             col = split.column()
 
             for i, ui in enumerate(theme.bone_color_sets):
-                col.label(text="Color Set %d:" % (i + 1))  # i starts from 0
+                col.label(text="Color Set" + " %d:" % (i + 1))  # i starts from 0
 
                 row = col.row()
 
@@ -679,7 +672,7 @@ class USERPREF_PT_theme(bpy.types.Panel):
             self._theme_generic(split, getattr(theme, theme.theme_area.lower()))
 
 
-class USERPREF_PT_file(bpy.types.Panel):
+class USERPREF_PT_file(Panel):
     bl_space_type = 'USER_PREFERENCES'
     bl_label = "Files"
     bl_region_type = 'WINDOW'
@@ -755,7 +748,43 @@ class USERPREF_PT_file(bpy.types.Panel):
 from bl_ui.space_userpref_keymap import InputKeyMapPanel
 
 
-class USERPREF_PT_input(bpy.types.Panel, InputKeyMapPanel):
+class USERPREF_MT_ndof_settings(Menu):
+    # accessed from the window keybindings in C (only)
+    bl_label = "3D Mouse Settings"
+
+    def draw(self, context):
+        layout = self.layout
+        input_prefs = context.user_preferences.inputs
+
+        layout.separator()
+        layout.prop(input_prefs, "ndof_sensitivity")
+
+        if context.space_data.type == 'VIEW_3D':
+            layout.separator()
+            layout.prop(input_prefs, "ndof_show_guide")
+
+            layout.separator()
+            layout.label(text="orbit options")
+            if input_prefs.view_rotate_method == 'TRACKBALL':
+                layout.prop(input_prefs, "ndof_roll_invert_axis")
+                layout.prop(input_prefs, "ndof_tilt_invert_axis")
+                layout.prop(input_prefs, "ndof_rotate_invert_axis")
+            else:
+                layout.prop(input_prefs, "ndof_orbit_invert_axes")
+
+            layout.separator()
+            layout.label(text="pan options")
+            layout.prop(input_prefs, "ndof_panx_invert_axis")
+            layout.prop(input_prefs, "ndof_pany_invert_axis")
+            layout.prop(input_prefs, "ndof_panz_invert_axis")
+
+            layout.separator()
+            layout.label(text="fly options")
+            layout.prop(input_prefs, "ndof_fly_helicopter", icon='NDOF_FLY')
+            layout.prop(input_prefs, "ndof_lock_horizon", icon='NDOF_DOM')
+
+
+class USERPREF_PT_input(Panel, InputKeyMapPanel):
     bl_space_type = 'USER_PREFERENCES'
     bl_label = "Input"
 
@@ -817,12 +846,9 @@ class USERPREF_PT_input(bpy.types.Panel, InputKeyMapPanel):
         #sub.prop(view, "wheel_scroll_lines", text="Scroll Lines")
 
         col.separator()
-        ''' not implemented yet
         sub = col.column()
         sub.label(text="NDOF Device:")
-        sub.prop(inputs, "ndof_pan_speed", text="Pan Speed")
-        sub.prop(inputs, "ndof_rotate_speed", text="Orbit Speed")
-        '''
+        sub.prop(inputs, "ndof_sensitivity", text="NDOF Sensitivity")
 
         row.separator()
 
@@ -848,18 +874,18 @@ class USERPREF_PT_input(bpy.types.Panel, InputKeyMapPanel):
         #print("runtime", time.time() - start)
 
 
-class USERPREF_MT_addons_dev_guides(bpy.types.Menu):
+class USERPREF_MT_addons_dev_guides(Menu):
     bl_label = "Development Guides"
 
     # menu to open webpages with addons development guides
     def draw(self, context):
         layout = self.layout
-        layout.operator('wm.url_open', text='API Concepts', icon='URL').url = 'http://wiki.blender.org/index.php/Dev:2.5/Py/API/Intro'
-        layout.operator('wm.url_open', text='Addon Guidelines', icon='URL').url = 'http://wiki.blender.org/index.php/Dev:2.5/Py/Scripts/Guidelines/Addons'
-        layout.operator('wm.url_open', text='How to share your addon', icon='URL').url = 'http://wiki.blender.org/index.php/Dev:Py/Sharing'
+        layout.operator("wm.url_open", text="API Concepts", icon='URL').url = "http://wiki.blender.org/index.php/Dev:2.5/Py/API/Intro"
+        layout.operator("wm.url_open", text="Addon Guidelines", icon='URL').url = "http://wiki.blender.org/index.php/Dev:2.5/Py/Scripts/Guidelines/Addons"
+        layout.operator("wm.url_open", text="How to share your addon", icon='URL').url = "http://wiki.blender.org/index.php/Dev:Py/Sharing"
 
 
-class USERPREF_PT_addons(bpy.types.Panel):
+class USERPREF_PT_addons(Panel):
     bl_space_type = 'USER_PREFERENCES'
     bl_label = "Addons"
     bl_region_type = 'WINDOW'
@@ -881,7 +907,7 @@ class USERPREF_PT_addons(bpy.types.Panel):
         if not user_addon_paths:
             user_script_path = bpy.utils.user_script_path()
             if user_script_path is not None:
-                user_addon_paths.append(os.path.join(user_script_path(), "addons"))
+                user_addon_paths.append(os.path.join(user_script_path, "addons"))
             user_addon_paths.append(os.path.join(bpy.utils.resource_path('USER'), "scripts", "addons"))
 
         for path in user_addon_paths:
@@ -889,6 +915,16 @@ class USERPREF_PT_addons(bpy.types.Panel):
                 return True
         return False
 
+    @staticmethod
+    def draw_error(layout, message):
+        lines = message.split("\n")
+        box = layout.box()
+        rowsub = box.row()
+        rowsub.label(lines[0])
+        rowsub.label(icon='ERROR')
+        for l in lines[1:]:
+            box.label(l)
+
     def draw(self, context):
         layout = self.layout
 
@@ -909,6 +945,20 @@ class USERPREF_PT_addons(bpy.types.Panel):
 
         col = split.column()
 
+        # set in addon_utils.modules(...)
+        if addon_utils.error_duplicates:
+            self.draw_error(col,
+                            "Multiple addons using the same name found!\n"
+                            "likely a problem with the script search path.\n"
+                            "(see console for details)",
+                            )
+
+        if addon_utils.error_encoding:
+            self.draw_error(col,
+                            "One or more addons do not have UTF-8 encoding\n"
+                            "(see console for details)",
+                            )
+
         filter = context.window_manager.addon_filter
         search = context.window_manager.addon_search.lower()
         support = context.window_manager.addon_support
@@ -967,26 +1017,26 @@ class USERPREF_PT_addons(bpy.types.Panel):
                 if info["show_expanded"]:
                     if info["description"]:
                         split = colsub.row().split(percentage=0.15)
-                        split.label(text='Description:')
+                        split.label(text="Description:")
                         split.label(text=info["description"])
                     if info["location"]:
                         split = colsub.row().split(percentage=0.15)
-                        split.label(text='Location:')
+                        split.label(text="Location:")
                         split.label(text=info["location"])
                     if info["author"]:
                         split = colsub.row().split(percentage=0.15)
-                        split.label(text='Author:')
+                        split.label(text="Author:")
                         split.label(text=info["author"])
                     if info["version"]:
                         split = colsub.row().split(percentage=0.15)
-                        split.label(text='Version:')
+                        split.label(text="Version:")
                         split.label(text='.'.join(str(x) for x in info["version"]))
                     if info["warning"]:
                         split = colsub.row().split(percentage=0.15)
                         split.label(text="Warning:")
                         split.label(text='  ' + info["warning"], icon='ERROR')
 
-                    user_addon = __class__.is_user_addon(mod, user_addon_paths)
+                    user_addon = USERPREF_PT_addons.is_user_addon(mod, user_addon_paths)
                     tot_row = bool(info["wiki_url"]) + bool(info["tracker_url"]) + bool(user_addon)
 
                     if tot_row:
@@ -1002,7 +1052,6 @@ class USERPREF_PT_addons(bpy.types.Panel):
                         for i in range(4 - tot_row):
                             split.separator()
 
-
         # Append missing scripts
         # First collect scripts that are used but have no script file.
         module_names = {mod.__name__ for mod, info in addons}
@@ -1026,54 +1075,84 @@ class USERPREF_PT_addons(bpy.types.Panel):
                     row.operator("wm.addon_disable", icon='CHECKBOX_HLT', text="", emboss=False).module = module_name
 
 
-class WM_OT_addon_enable(bpy.types.Operator):
+class WM_OT_addon_enable(Operator):
     "Enable an addon"
     bl_idname = "wm.addon_enable"
     bl_label = "Enable Add-On"
 
-    module = StringProperty(name="Module", description="Module name of the addon to enable")
+    module = StringProperty(
+            name="Module",
+            description="Module name of the addon to enable",
+            )
 
     def execute(self, context):
         mod = addon_utils.enable(self.module)
 
         if mod:
-            # check if add-on is written for current blender version, or raise a warning
             info = addon_utils.module_bl_info(mod)
 
-            if info.get("blender", (0, 0, 0)) > bpy.app.version:
-                self.report("WARNING','This script was written for a newer version of Blender and might not function (correctly).\nThe script is enabled though.")
+            info_ver = info.get("blender", (0, 0, 0))
+
+            if info_ver > bpy.app.version:
+                self.report({'WARNING'}, ("This script was written Blender "
+                                          "version %d.%d.%d and might not "
+                                          "function (correctly), "
+                                          "though it is enabled") %
+                                         info_ver)
             return {'FINISHED'}
         else:
             return {'CANCELLED'}
 
 
-class WM_OT_addon_disable(bpy.types.Operator):
+class WM_OT_addon_disable(Operator):
     "Disable an addon"
     bl_idname = "wm.addon_disable"
     bl_label = "Disable Add-On"
 
-    module = StringProperty(name="Module", description="Module name of the addon to disable")
+    module = StringProperty(
+            name="Module",
+            description="Module name of the addon to disable",
+            )
 
     def execute(self, context):
         addon_utils.disable(self.module)
         return {'FINISHED'}
 
 
-class WM_OT_addon_install(bpy.types.Operator):
+class WM_OT_addon_install(Operator):
     "Install an addon"
     bl_idname = "wm.addon_install"
     bl_label = "Install Add-On..."
 
-    overwrite = BoolProperty(name="Overwrite", description="Remove existing addons with the same ID", default=True)
+    overwrite = BoolProperty(
+            name="Overwrite",
+            description="Remove existing addons with the same ID",
+            default=True,
+            )
     target = EnumProperty(
             name="Target Path",
             items=(('DEFAULT', "Default", ""),
-                   ('PREFS', "User Prefs", "")))
-
-    filepath = StringProperty(name="File Path", description="File path to write file to")
-    filter_folder = BoolProperty(name="Filter folders", description="", default=True, options={'HIDDEN'})
-    filter_python = BoolProperty(name="Filter python", description="", default=True, options={'HIDDEN'})
-    filter_glob = StringProperty(default="*.py;*.zip", options={'HIDDEN'})
+                   ('PREFS', "User Prefs", "")),
+            )
+
+    filepath = StringProperty(
+            name="File Path",
+            description="File path to write file to",
+            )
+    filter_folder = BoolProperty(
+            name="Filter folders",
+            default=True,
+            options={'HIDDEN'},
+            )
+    filter_python = BoolProperty(
+            name="Filter python",
+            default=True,
+            options={'HIDDEN'},
+            )
+    filter_glob = StringProperty(
+            default="*.py;*.zip",
+            options={'HIDDEN'},
+            )
 
     @staticmethod
     def _module_remove(path_addons, module):
@@ -1124,7 +1203,6 @@ class WM_OT_addon_install(bpy.types.Operator):
         del pyfile_dir
         # done checking for exceptional case
 
-        addon_files_old = set(os.listdir(path_addons))
         addons_old = {mod.__name__ for mod in addon_utils.modules(USERPREF_PT_addons._addons_fake_modules)}
 
         #check to see if the file is in compressed format (.zip)
@@ -1137,7 +1215,7 @@ class WM_OT_addon_install(bpy.types.Operator):
 
             if self.overwrite:
                 for f in file_to_extract.namelist():
-                    __class__._module_remove(path_addons, f)
+                    WM_OT_addon_install._module_remove(path_addons, f)
             else:
                 for f in file_to_extract.namelist():
                     path_dest = os.path.join(path_addons, os.path.basename(f))
@@ -1161,7 +1239,7 @@ class WM_OT_addon_install(bpy.types.Operator):
             path_dest = os.path.join(path_addons, os.path.basename(pyfile))
 
             if self.overwrite:
-                __class__._module_remove(path_addons, os.path.basename(pyfile))
+                WM_OT_addon_install._module_remove(path_addons, os.path.basename(pyfile))
             elif os.path.exists(path_dest):
                 self.report({'WARNING'}, "File already installed to %r\n" % path_dest)
                 return {'CANCELLED'}
@@ -1206,12 +1284,15 @@ class WM_OT_addon_install(bpy.types.Operator):
         return {'RUNNING_MODAL'}
 
 
-class WM_OT_addon_remove(bpy.types.Operator):
+class WM_OT_addon_remove(Operator):
     "Disable an addon"
     bl_idname = "wm.addon_remove"
     bl_label = "Remove Add-On"
 
-    module = StringProperty(name="Module", description="Module name of the addon to remove")
+    module = StringProperty(
+            name="Module",
+            description="Module name of the addon to remove",
+            )
 
     @staticmethod
     def path_from_addon(module):
@@ -1226,7 +1307,7 @@ class WM_OT_addon_remove(bpy.types.Operator):
         return None, False
 
     def execute(self, context):
-        path, isdir = __class__.path_from_addon(self.module)
+        path, isdir = WM_OT_addon_remove.path_from_addon(self.module)
         if path is None:
             self.report('WARNING', "Addon path %r could not be found" % path)
             return {'CANCELLED'}
@@ -1246,7 +1327,7 @@ class WM_OT_addon_remove(bpy.types.Operator):
     # lame confirmation check
     def draw(self, context):
         self.layout.label(text="Remove Addon: %r?" % self.module)
-        path, isdir = __class__.path_from_addon(self.module)
+        path, isdir = WM_OT_addon_remove.path_from_addon(self.module)
         self.layout.label(text="Path: %r" % path)
 
     def invoke(self, context, event):
@@ -1254,12 +1335,15 @@ class WM_OT_addon_remove(bpy.types.Operator):
         return wm.invoke_props_dialog(self, width=600)
 
 
-class WM_OT_addon_expand(bpy.types.Operator):
+class WM_OT_addon_expand(Operator):
     "Display more information on this add-on"
     bl_idname = "wm.addon_expand"
     bl_label = ""
 
-    module = StringProperty(name="Module", description="Module name of the addon to expand")
+    module = StringProperty(
+            name="Module",
+            description="Module name of the addon to expand",
+            )
 
     def execute(self, context):
         module_name = self.module