API Navigator: Cleanup, UI fixes

Bumped version to 1.0.3
Pep8 cleanup
imports as tuples
Removed an empty operator FakeButton
too much fuss for a tooltip
UI uses embossed buttons set to True
Moved the list size filter to the top
Moved the PropertyGroup out of register
This commit is contained in:
Vuk Gardašević 2017-03-30 11:45:23 +02:00
parent ba89ec341c
commit 3a1b03b5a6
1 changed files with 168 additions and 168 deletions

View File

@ -2,7 +2,6 @@
#
# ***** 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
@ -22,12 +21,12 @@
bl_info = {
"name": "API Navigator",
"author": "Dany Lebel (Axon_D)",
"version": (1, 0, 2),
"version": (1, 0, 3),
"blender": (2, 57, 0),
"location": "Text Editor > Properties > API Navigator Panel",
"description": "Allows exploration of the python api via the user interface",
"warning": "",
"wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/"
"wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6/Py/"
"Scripts/Text_Editor/API_Navigator",
"category": "Development",
}
@ -58,77 +57,73 @@ with the Escape key. (but a bug prevent the keymap to register correctly at star
"""
import bpy
from bpy.types import (
Operator,
Panel,
PropertyGroup,
)
from bpy.props import (
StringProperty,
IntProperty,
PointerProperty
)
from console.complete_import import get_root_modules
############ Global Variables ############
last_text = None # last text data block
root_module = None # root module of the tree
root_m_path = '' # root_module + path as a string
# ########## Global Variables ##########
last_text = None # last text data block
root_module = None # root module of the tree
root_m_path = '' # root_module + path as a string
current_module = None # the object itself in the tree structure
tree_level = None # the list of objects from the current_module
tree_level = None # the list of objects from the current_module
def init_tree_level():
global tree_level
tree_level = [[],[],[],[],[],[],[], [], []]
tree_level = [[], [], [], [], [], [], [], [], []]
init_tree_level()
api_doc_ = '' # the documentation formated for the API Navigator
api_doc_ = '' # the documentation formated for the API Navigator
module_type = None # the type of current_module
return_report = '' # what current_module returns
filter_mem = {} # remember last filters entered for each path
too_long = False # is tree_level list too long to display in a panel?
filter_mem = {} # remember last filters entered for each path
too_long = False # is tree_level list too long to display in a panel?
############ Functions ############
# ########## Functions ############
def get_root_module(path):
#print('get_root_module')
global root_module
if '.' in path:
root = path[:path.find('.')]
else :
else:
root = path
try :
try:
root_module = __import__(root)
except :
except:
root_module = None
def evaluate(module):
#print('evaluate')
global root_module, tree_level, root_m_path
# path = bpy.context.window_manager.api_nav_props.path
try :
try:
len_name = root_module.__name__.__len__()
root_m_path = 'root_module' + module[len_name:]
current_module = eval(root_m_path)
return current_module
except :
except:
init_tree_level
return None
def get_tree_level():
#print('get_tree_level')
path = bpy.context.window_manager.api_nav_props.path
def object_list():
#print('object_list')
global current_module, root_m_path
itm, val, mod, typ, props, struct, met, att, bug = [], [], [], [], [], [], [], [], []
@ -138,22 +133,19 @@ def get_tree_level():
current_type = str(module_type)
if current_type != "<class 'str'>":
if iterable == 'a':
#if iterable == 'a':
#current_type.__iter__()
itm = list(current_module.keys())
if not itm:
val = list(current_module)
else :
else:
val = list(current_module)
for i in dir(current_module):
try :
try:
t = str(type(eval(root_m_path + '.' + i)))
except (AttributeError, SyntaxError):
bug += [i]
continue
if t == "<class 'module'>":
mod += [i]
elif t[0:16] == "<class 'bpy_prop":
@ -164,7 +156,7 @@ def get_tree_level():
met += [i]
elif t == "<class 'type'>":
typ += [i]
else :
else:
att += [i]
return [itm, val, mod, typ, props, struct, met, att, bug]
@ -176,8 +168,6 @@ def get_tree_level():
def parent(path):
"""Returns the parent path"""
#print('parent')
parent = path
if parent[-1] == ']' and '[' in parent:
while parent[-1] != '[':
@ -185,7 +175,7 @@ def parent(path):
elif '.' in parent:
while parent[-1] != '.':
parent = parent[:-1]
else :
else:
return ''
parent = parent[:-1]
return parent
@ -195,19 +185,18 @@ def update_filter():
"""Update the filter according to the current path"""
global filter_mem
try :
try:
bpy.context.window_manager.api_nav_props.filter = filter_mem[bpy.context.window_manager.api_nav_props.path]
except :
except:
bpy.context.window_manager.api_nav_props.filter = ''
def isiterable(mod):
try :
try:
iter(mod)
except :
except:
return False
try :
try:
mod['']
return 'a'
except KeyError:
@ -221,13 +210,13 @@ def fill_filter_mem():
filter = bpy.context.window_manager.api_nav_props.filter
if filter:
filter_mem[bpy.context.window_manager.api_nav_props.old_path] = bpy.context.window_manager.api_nav_props.filter
else :
filter_mem[bpy.context.window_manager.api_nav_props.old_path] = \
bpy.context.window_manager.api_nav_props.filter
else:
filter_mem.pop(bpy.context.window_manager.api_nav_props.old_path, None)
###### API Navigator parent class #######
# #### API Navigator parent class ######
class ApiNavigator():
"""Parent class for API Navigator"""
@ -242,7 +231,7 @@ class ApiNavigator():
last_text = bpy.context.space_data.text.name
elif bpy.data.texts.__len__() < 2:
last_text = None
else :
else:
last_text = None
bpy.context.window_manager.api_nav_props.pages = 0
get_root_module(bpy.context.window_manager.api_nav_props.path)
@ -254,7 +243,7 @@ class ApiNavigator():
if tree_level.__len__() > 30:
global too_long
too_long = True
else :
else:
too_long = False
ApiNavigator.generate_api_doc()
@ -266,7 +255,7 @@ class ApiNavigator():
global current_module, api_doc_, return_report, module_type
path = bpy.context.window_manager.api_nav_props.path
line = "-" * (path.__len__()+2)
line = "-" * (path.__len__() + 2)
header = """\n\n\n\t\t%s\n\t %s\n\
_____________________________________________\n\
\n\
@ -300,11 +289,11 @@ _____________________________________________\n\
space_data = bpy.context.space_data
try :
try:
doc_text = bpy.data.texts['api_doc_']
space_data.text = doc_text
doc_text.clear()
except :
except:
bpy.data.texts.new(name='api_doc_')
doc_text = bpy.data.texts['api_doc_']
space_data.text = doc_text
@ -313,8 +302,7 @@ _____________________________________________\n\
return {'FINISHED'}
############ Operators ############
# ######### Operators ###########
def api_update(context):
if bpy.context.window_manager.api_nav_props.path != bpy.context.window_manager.api_nav_props.old_path:
fill_filter_mem()
@ -324,7 +312,7 @@ def api_update(context):
ApiNavigator.doc_text_datablock()
class Update(ApiNavigator, bpy.types.Operator):
class Update(ApiNavigator, Operator):
"""Update the tree structure"""
bl_idname = "api_navigator.update"
bl_label = "API Navigator Update"
@ -334,8 +322,8 @@ class Update(ApiNavigator, bpy.types.Operator):
return {'FINISHED'}
class BackToBpy(ApiNavigator, bpy.types.Operator):
"""go back to module bpy"""
class BackToBpy(ApiNavigator, Operator):
"""Go back to module bpy"""
bl_idname = "api_navigator.back_to_bpy"
bl_label = "Back to bpy"
@ -343,7 +331,7 @@ class BackToBpy(ApiNavigator, bpy.types.Operator):
fill_filter_mem()
if not bpy.context.window_manager.api_nav_props.path:
bpy.context.window_manager.api_nav_props.old_path = bpy.context.window_manager.api_nav_props.path = 'bpy'
else :
else:
bpy.context.window_manager.api_nav_props.old_path = bpy.context.window_manager.api_nav_props.path = 'bpy'
update_filter()
self.generate_global_values()
@ -351,20 +339,27 @@ class BackToBpy(ApiNavigator, bpy.types.Operator):
return {'FINISHED'}
class Down(ApiNavigator, bpy.types.Operator):
"""go to this Module"""
class Down(ApiNavigator, Operator):
"""Go to this Module"""
bl_idname = "api_navigator.down"
bl_label = "API Navigator Down"
pointed_module = bpy.props.StringProperty(name='Current Module', default='')
pointed_module = StringProperty(
name="Current Module",
default=""
)
def execute(self, context):
fill_filter_mem()
if not bpy.context.window_manager.api_nav_props.path:
bpy.context.window_manager.api_nav_props.old_path = bpy.context.window_manager.api_nav_props.path = bpy.context.window_manager.api_nav_props.path + self.pointed_module
else :
bpy.context.window_manager.api_nav_props.old_path = bpy.context.window_manager.api_nav_props.path = bpy.context.window_manager.api_nav_props.path + '.' + self.pointed_module
bpy.context.window_manager.api_nav_props.old_path = \
bpy.context.window_manager.api_nav_props.path = \
bpy.context.window_manager.api_nav_props.path + self.pointed_module
else:
bpy.context.window_manager.api_nav_props.old_path = \
bpy.context.window_manager.api_nav_props.path = \
bpy.context.window_manager.api_nav_props.path + '.' + self.pointed_module
update_filter()
self.generate_global_values()
@ -372,18 +367,19 @@ class Down(ApiNavigator, bpy.types.Operator):
return {'FINISHED'}
class Parent(ApiNavigator, bpy.types.Operator):
"""go to Parent Module"""
class Parent(ApiNavigator, Operator):
"""Go to Parent Module"""
bl_idname = "api_navigator.parent"
bl_label = "API Navigator Parent"
def execute(self, context):
path = bpy.context.window_manager.api_nav_props.path
if path:
fill_filter_mem()
bpy.context.window_manager.api_nav_props.old_path = bpy.context.window_manager.api_nav_props.path = parent(bpy.context.window_manager.api_nav_props.path)
bpy.context.window_manager.api_nav_props.old_path = \
bpy.context.window_manager.api_nav_props.path = \
parent(bpy.context.window_manager.api_nav_props.path)
update_filter()
self.generate_global_values()
self.doc_text_datablock()
@ -391,52 +387,52 @@ class Parent(ApiNavigator, bpy.types.Operator):
return {'FINISHED'}
class ClearFilter(ApiNavigator, bpy.types.Operator):
class ClearFilter(ApiNavigator, Operator):
"""Clear the filter"""
bl_idname = 'api_navigator.clear_filter'
bl_label = 'API Nav clear filter'
bl_idname = "api_navigator.clear_filter"
bl_label = "API Nav clear filter"
def execute(self, context):
bpy.context.window_manager.api_nav_props.filter = ''
return {'FINISHED'}
class FakeButton(ApiNavigator, bpy.types.Operator):
"""The list is not displayed completely""" # only serve as an indicator
bl_idname = 'api_navigator.fake_button'
bl_label = ''
class Subscript(ApiNavigator, bpy.types.Operator):
class Subscript(ApiNavigator, Operator):
"""Subscript to this Item"""
bl_idname = "api_navigator.subscript"
bl_label = "API Navigator Subscript"
subscription = bpy.props.StringProperty(name='', default='')
subscription = StringProperty(
name="",
default=""
)
def execute(self, context):
fill_filter_mem()
bpy.context.window_manager.api_nav_props.old_path = bpy.context.window_manager.api_nav_props.path = bpy.context.window_manager.api_nav_props.path + '[' + self.subscription + ']'
bpy.context.window_manager.api_nav_props.old_path = \
bpy.context.window_manager.api_nav_props.path = \
bpy.context.window_manager.api_nav_props.path + '[' + self.subscription + ']'
update_filter()
self.generate_global_values()
self.doc_text_datablock()
return {'FINISHED'}
class Toggle_doc(ApiNavigator, bpy.types.Operator):
class Toggle_doc(ApiNavigator, Operator):
"""Toggle on or off api_doc_ Text"""
bl_idname = 'api_navigator.toggle_doc'
bl_label = 'Toggle api_doc_'
bl_idname = "api_navigator.toggle_doc"
bl_label = "Toggle api_doc_"
def execute(self, context):
global last_text
try :
try:
if bpy.context.space_data.text.name != "api_doc_":
last_text = bpy.context.space_data.text.name
except : pass
except:
pass
try :
try:
text = bpy.data.texts["api_doc_"]
bpy.data.texts["api_doc_"].clear()
bpy.data.texts.remove(text)
@ -444,31 +440,30 @@ class Toggle_doc(ApiNavigator, bpy.types.Operator):
self.doc_text_datablock()
return {'FINISHED'}
try :
try:
text = bpy.data.texts[last_text]
bpy.context.space_data.text = text
#line = bpy.ops.text.line_number() # operator doesn't seems to work ???
#bpy.ops.text.jump(line=line)
return {'FINISHED'}
except : pass
except:
pass
bpy.context.space_data.text = None
return {'FINISHED'}
############ UI Panels ############
class OBJECT_PT_api_navigator(ApiNavigator, bpy.types.Panel):
# ######### UI Panels ############
class OBJECT_PT_api_navigator(ApiNavigator, Panel):
bl_idname = 'api_navigator'
bl_space_type = "TEXT_EDITOR"
bl_region_type = "UI"
bl_label = "API Navigator"
bl_options = {'DEFAULT_CLOSED'}
columns = 3
def iterable_draw(self):
# Note: Currently unused method
global tree_level, current_module
iterable = isiterable(current_module)
@ -481,11 +476,9 @@ class OBJECT_PT_api_navigator(ApiNavigator, bpy.types.Panel):
return {'FINISHED'}
col = self.layout
# filter = bpy.context.window_manager.api_nav_props.filter # UNUSED
reduce_to = bpy.context.window_manager.api_nav_props.reduce_to * self.columns
pages = bpy.context.window_manager.api_nav_props.pages
page_index = reduce_to*pages
# rank = 0 # UNUSED
page_index = reduce_to * pages
count = 0
i = 0
filtered = 0
@ -509,7 +502,8 @@ class OBJECT_PT_api_navigator(ApiNavigator, bpy.types.Panel):
if not (i % self.columns):
row = col.row()
row.operator('api_navigator.subscript', text=mod, emboss=False).subscription = '"' + mod + '"'
row.operator("api_navigator.subscript",
text=mod, emboss=True).subscription = '"' + mod + '"'
filtered += 1
i += 1
count += 1
@ -532,7 +526,8 @@ class OBJECT_PT_api_navigator(ApiNavigator, bpy.types.Panel):
if not (i % self.columns):
row = col.row()
row.operator('api_navigator.subscript', text=mod, emboss=False).subscription = str(i)
row.operator("api_navigator.subscript",
text=mod, emboss=True).subscription = str(i)
filtered += 1
i += 1
count += 1
@ -541,34 +536,25 @@ class OBJECT_PT_api_navigator(ApiNavigator, bpy.types.Panel):
if too_long:
row = col.row()
row.prop(bpy.context.window_manager.api_nav_props, 'reduce_to')
row.operator('api_navigator.fake_button', text='', emboss=False, icon="DOTSDOWN")
row.prop(bpy.context.window_manager.api_nav_props, 'pages', text='Pages')
row.prop(bpy.context.window_manager.api_nav_props, "reduce_to")
row.label(text="", icon="DOTSDOWN")
row.prop(bpy.context.window_manager.api_nav_props, "pages", text="Pages")
return {'FINISHED'}
def list_draw(self, t, pages, icon, label=None, emboss=False):
def list_draw(self, t, pages, icon, label=None, emboss=True):
global tree_level, current_module
def reduced(too_long):
if too_long:
row = col.row()
row.prop(bpy.context.window_manager.api_nav_props, 'reduce_to')
row.operator('api_navigator.fake_button', text='', emboss=False, icon="DOTSDOWN")
row.prop(bpy.context.window_manager.api_nav_props, 'pages', text='Pages')
def reduced(row, too_long):
if row and too_long:
sub_row = row.row(align=True)
sub_row.prop(bpy.context.window_manager.api_nav_props, "reduce_to")
sub_row.prop(bpy.context.window_manager.api_nav_props, "pages", text="Pages")
layout = self.layout
filter = bpy.context.window_manager.api_nav_props.filter
reduce_to = bpy.context.window_manager.api_nav_props.reduce_to * self.columns
page_index = reduce_to*pages
page_index = reduce_to * pages
len = tree_level[t].__len__()
too_long = len > reduce_to
@ -577,8 +563,11 @@ class OBJECT_PT_api_navigator(ApiNavigator, bpy.types.Panel):
col = layout.column()
box = col.box()
row = box.row()
row.label(text=label, icon=icon)
row = box.row(align=True)
title_box = row.box()
title_box.label(text=label, icon=icon)
reduced(title_box, too_long)
if t < 2:
box = box.box()
@ -601,43 +590,42 @@ class OBJECT_PT_api_navigator(ApiNavigator, bpy.types.Panel):
continue
if not (objects % self.columns):
row = col.row()
row = col.row(align=True)
if t > 1:
row.operator("api_navigator.down", text=obj, emboss=emboss).pointed_module = obj
row.operator("api_navigator.down",
text=obj, emboss=emboss).pointed_module = obj
elif t == 0:
row.operator('api_navigator.subscript', text=str(obj), emboss=False).subscription = '"' + obj + '"'
else :
row.operator('api_navigator.subscript', text=str(obj), emboss=False).subscription = str(i)
row.operator("api_navigator.subscript",
text=str(obj), emboss=emboss).subscription = '"' + obj + '"'
else:
row.operator("api_navigator.subscript",
text=str(obj), emboss=emboss).subscription = str(i)
filtered += 1
i += 1
objects += 1
count += 1
reduced(too_long)
return {'FINISHED'}
def draw(self, context):
global tree_level, current_module, module_type, return_report
api_update(context)
###### layout ######
layout = self.layout
layout.label(text="Tree Structure:")
col = layout.column(align=True)
col = layout.column(align=True)
col.prop(bpy.context.window_manager.api_nav_props, 'path', text='')
row = col.row()
row = col.row(align=True)
row.operator("api_navigator.parent", text="Parent", icon="BACK")
row.operator("api_navigator.back_to_bpy", text='', emboss=True, icon="FILE_PARENT")
col = layout.column()
row = col.row(align=True)
row.prop(bpy.context.window_manager.api_nav_props, 'filter')
row.operator('api_navigator.clear_filter', text='', icon='PANEL_CLOSE')
row.prop(bpy.context.window_manager.api_nav_props, "filter", text="Filter")
row.operator("api_navigator.clear_filter", text="", icon="PANEL_CLOSE")
col = layout.column()
@ -645,17 +633,50 @@ class OBJECT_PT_api_navigator(ApiNavigator, bpy.types.Panel):
self.list_draw(0, pages, "DOTSDOWN", label="Items")
self.list_draw(1, pages, "DOTSDOWN", label="Item Values")
self.list_draw(2, pages, "PACKAGE", label="Modules", emboss=True)
self.list_draw(3, pages, "WORDWRAP_ON", label="Types", emboss=False)
self.list_draw(4, pages, "BUTS", label="Properties", emboss=False)
self.list_draw(3, pages, "WORDWRAP_ON", label="Types", emboss=True)
self.list_draw(4, pages, "BUTS", label="Properties", emboss=True)
self.list_draw(5, pages, "OOPS", label="Structs and Functions")
self.list_draw(6, pages, "SCRIPTWIN", label="Methods and Functions")
self.list_draw(7, pages, "INFO", label="Attributes")
self.list_draw(8, pages, "ERROR", label="Inaccessible")
########### Menu functions ###############
# ###### Properties #######
class ApiNavProps(PropertyGroup):
"""
Fake module like class.
bpy.context.window_manager.api_nav_props
"""
path = StringProperty(
name="path",
description="Enter bpy.ops.api_navigator to see the documentation",
default="bpy"
)
old_path = StringProperty(
name="old_path",
default=""
)
filter = StringProperty(
name="filter",
description="Filter the resulting modules",
default=""
)
reduce_to = IntProperty(
name="Reduce to",
description="Display a maximum number of x entries by pages",
default=10,
min=1
)
pages = IntProperty(
name="Pages",
description="Display a Page",
default=0,
min=0
)
# ######## Register #########
def register_keymaps():
kc = bpy.context.window_manager.keyconfigs.addon
if kc:
@ -672,34 +693,13 @@ def unregister_keymaps():
def register():
from bpy.props import StringProperty, IntProperty, PointerProperty
class ApiNavProps(bpy.types.PropertyGroup):
"""
Fake module like class.
bpy.context.window_manager.api_nav_props
"""
path = StringProperty(name='path',
description='Enter bpy.ops.api_navigator to see the documentation',
default='bpy')
old_path = StringProperty(name='old_path', default='')
filter = StringProperty(name='filter',
description='Filter the resulting modules', default='')
reduce_to = IntProperty(name='Reduce to ',
description='Display a maximum number of x entries by pages',
default=10, min=1)
pages = IntProperty(name='Pages',
description='Display a Page', default=0, min=0)
bpy.utils.register_module(__name__)
bpy.types.WindowManager.api_nav_props = PointerProperty(
type=ApiNavProps, name='API Nav Props', description='')
type=ApiNavProps,
name="API Nav Props",
description=""
)
register_keymaps()
#print(get_tree_level())
def unregister():