Skip to content

Instantly share code, notes, and snippets.

@p--q
Last active August 29, 2015 14:04
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save p--q/a1abde78b9da7d100104 to your computer and use it in GitHub Desktop.
Save p--q/a1abde78b9da7d100104 to your computer and use it in GitHub Desktop.
# -*- coding: utf-8 -*-
def libreoffice54():
obj = XSCRIPTCONTEXT.getDocument() # 調査対象のオブジェクトを取得。old-styleサービスの例。LibreOfficeドキュメントを開いておく必要がある。
# obj = XSCRIPTCONTEXT.getDesktop().getCurrentFrame().getContainerWindow().getToolkit() # 調査対象のオブジェクトを取得。new-styleサービスの例。
# obj = XSCRIPTCONTEXT.getComponentContext() # 調査対象のオブジェクトを取得。サービスがないオブジェクトの例。
objinsp(obj)
def objinsp(obj):
from com.sun.star.uno.TypeClass import SERVICE, INTERFACE, PROPERTY
tdm = XSCRIPTCONTEXT.getComponentContext().getByName('/singletons/com.sun.star.reflection.theTypeDescriptionManager') # TypeDescriptionManagerをシングルトンでインスタンス化。
st_omi = {'com.sun.star.uno.XInterface', 'com.sun.star.uno.XWeak', 'com.sun.star.lang.XTypeProvider'} # 結果を出力しないインターフェイス名の集合。'com.sun.star.uno.XInterface'は必ず指定が必要。
stack = list() # スタック。
if hasattr(obj, "getSupportedServiceNames"): # オブジェクトがサービスを持っているとき。
st_ss = set(obj.getSupportedServiceNames()) # オブジェクトのサポートサービス名一覧の集合を得る。
st_sups = set() # 親サービスを入れる集合。
if len(st_ss) > 1: # サポートしているサービス名が複数ある場合。
stack = [tdm.getByHierarchicalName(i) for i in st_ss] # サポートサービスのTypeDescriptionオブジェクトをスタックに取得。
while stack: # スタックがある間実行。
j = stack.pop() # サービスのTypeDescriptionオブジェクトを取得。
t_std = j.getMandatoryServices() + j.getOptionalServices() # 親サービスのタプルを取得。
lst_std = [i for i in t_std if not i.Name in st_sups] # 親サービスのTypeDescriptionオブジェクトのうち既に取得した親サービスにないものだけを取得。
stack.extend(lst_std) # スタックに新たなサービスのTypeDescriptionオブジェクトのみ追加。
st_sups.update([i.Name for i in lst_std]) # 既に取得した親サービス名の集合型に新たに取得したサービス名を追加。
st_ss.difference_update(st_sups) # オブジェクトのサポートサービスのうち親サービスにないものだけにする=これがサービスの末裔。
stack = [tdm.getByHierarchicalName(i) for i in st_ss] # TypeDescriptionオブジェクトに変換。
if stack: stack.sort(key=lambda x: x.Name, reverse=True) # Name属性で降順に並べる。
else: # サポートしているサービスがないときはインターフェイス名一覧を得る。
if hasattr(obj, "getTypes"): # サポートしているインターフェイスがある場合。
st_si = set([i.typeName for i in obj.getTypes()]) # サポートインターフェイス名を集合型で取得。
lst_si = sorted(list(st_si.difference(st_omi)), reverse=True) # 除外するインターフェイス名を除いて降順のリストにする。
stack = [tdm.getByHierarchicalName(i) for i in lst_si] # TypeDescriptionオブジェクトに変換。
if stack: # 起点となるサービスかインターフェイスがあるとき。
lst_level = [0 for i in stack] # stackの要素すべてについて階層を取得。
indent = " " # インデントを設定。
m = 0 # 最大文字数を初期化。
while stack: # スタックがある間実行。
j = stack.pop() # スタックからTypeDescriptionオブジェクトをpop。
level = lst_level.pop() # jの階層を取得。
branch = ["", "", ""] # 枝をリセット。jに直接つながる枝のみ1番目の要素に入れる。それ以外の枝は0番目の要素に加える。2番目の要素にはjの名前を入れる。
t_itd = tuple() # インターフェイスのTypeDescriptionオブジェクトの入れ物を初期化。
t_spd = tuple() # サービス属性のTypeDescriptionオブジェクトの入れ物を初期化。
if level > 1: # 階層が2以上のとき。
for i in range(1, level): # 階層iから出た枝が次行の階層i-1の枝になる。
if i in lst_level: # iは枝の階層ではなく、枝のより上の行にあるその枝がでた階層になる。
branch[0] += "│ " # 縦枝を加える。
else:
branch[0] += indent
if level > 0: # 階層が1以上のとき
if level in lst_level: # スタックに同じ階層があるとき。
branch[1] = "├─"
else:
branch[1] = "└─"
if j.getTypeClass() == SERVICE: # jがサービスのときtdはXServiceTypeDescriptionインターフェイスをもつ。
branch[2] = j.Name
t_std = j.getMandatoryServices() + j.getOptionalServices() # 親サービスを取得。
stack.extend(sorted(list(t_std), key=lambda x: x.Name, reverse=True)) # 親サービス名で降順に並べてサービスのTypeDescriptionオブジェクトをスタックに追加。
lst_level.extend([level + 1 for i in t_std]) # 階層を取得。
itd = j.getInterface() # new-styleサービスのインターフェイスを取得。TypeDescriptionオブジェクト。
if itd: # new-styleサービスのインターフェイスがあるとき。
t_itd = itd, # XInterfaceTypeDescription2インターフェイスをもつTypeDescriptionオブジェクト。
else: # new-styleサービスのインターフェイスがないときはold-styleサービスのインターフェイスを取得。
t_itd = j.getMandatoryInterfaces() + j.getOptionalInterfaces() # XInterfaceTypeDescriptionインターフェイスをもつTypeDescriptionオブジェクト。
t_spd = j.Properties # サービスからXPropertyTypeDescriptionインターフェイスをもつオブジェクトのタプルを取得。
elif j.getTypeClass() == INTERFACE: # インターフェイスのとき。XInterfaceTypeDescription2インターフェイスをもつTypeDescriptionオブジェクト。
branch[2] = j.Name
t_itd = j.getBaseTypes() + j.getOptionalBaseTypes() # 親インターフェイスを取得。
elif j.getTypeClass() == PROPERTY: # サービス属性のとき。
if stack[lst_level.index(level)].getTypeClass() == SERVICE or INTERFACE: # スタックにある同じ階層のもので先頭の要素がサービスかインターフェイスのとき。
branch[1] = "│ "
else:
branch[1] = indent
typ = j.getPropertyTypeDescription().Name # 属性の型
if typ[1] == "]": # 属性がシークエンスのとき[]の表記を修正。
typ = typ.replace("]", "") + "]"
branch[2] = typ.rjust(m) + " " + j.Name # 型は最大文字数で右寄せにする。
print("".join(branch)) # 枝をつけて出力。
if t_itd: # 親インターフェイスがあるとき。(TypeDescriptionオブジェクト)
lst_itd = [i for i in t_itd if not i.Name in st_omi] # st_omiを除く。
stack.extend(sorted(lst_itd, key=lambda x: x.Name, reverse=True)) # 降順にしてスタックに追加。
lst_level.extend([level + 1 for i in lst_itd]) # 階層を取得。
st_omi.update([i.Name for i in lst_itd]) # すでにでてきたインターフェイス名をst_omiに追加して次は使わないようにする。
if t_spd: # サービス属性があるとき。
stack.extend(sorted(list(t_spd), key=lambda x: x.Name, reverse=True)) # 降順にしてスタックに追加。
lst_level.extend([level + 1 for i in t_spd]) # 階層を取得。
m = max([len(i.getPropertyTypeDescription().Name) for i in t_spd]) # サービス属性名の型のうち最大文字数を取得。
if __name__ == "__main__":
import unopy
XSCRIPTCONTEXT = unopy.connect()
if not XSCRIPTCONTEXT:
print("Failed to connect.")
import sys
sys.exit(0)
libreoffice54()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment