-
-
Save p--q/a1abde78b9da7d100104 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- 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