Skip to content

Instantly share code, notes, and snippets.

@p--q
Last active August 29, 2015 14:04
Show Gist options
  • 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
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'は必ず指定が必要。
st_s = set() # 起点となるサービスやインターフェイスを入れる集合型。
if hasattr(obj, "getSupportedServiceNames"): # オブジェクトがサービスを持っているとき。
st_ss = set(obj.getSupportedServiceNames()) # オブジェクトのサポートサービス名一覧の集合を得る。
st_sups = set() # 親サービスを入れる集合。
if len(st_ss) > 1: # サポートしているサービス名が複数ある場合。
stack = st_ss.copy() # サポートサービス名をスタックに取得。(このスタックは集合型。)
while stack: # スタックがある間実行。
std = tdm.getByHierarchicalName(stack.pop()) # スタックから要素を1つpopしてサービスのTypeDescriptionオブジェクトを取得。
t_std = std.getMandatoryServices()+std.getOptionalServices() # 親サービスのタプルを取得。
if t_std: # 親サービスがあるとき。
st_s = set([i.Name for i in t_std]).difference(st_sups) # 親サービスのTypeDescriptionオブジェクトからサービス名を得て集合型で既に取得した親サービスにないものだけを取得。
if st_s:
stack.update(st_s) # スタックに新たなサービスのみ追加。
st_sups.update(st_s) # 既に取得した親サービスに追加。
st_s = st_ss.difference(st_sups) # オブジェクトのサポートサービスのうち親サービスにないものだけにする=これがサービスの末裔。
else: # サポートしているサービスがないときはインターフェイス名一覧を得る。
if hasattr(obj, "getTypes"): # サポートしているインターフェイスがある場合。
t_sid = obj.getTypes() # サポートインターフェイスのTypeDescriptionオブジェクトを取得。
if t_sid: # サポートインターフェイスがあるとき。
st_s = set([i.typeName for i in t_sid]).difference(st_omi) # 除外するインターフェイス名を除いてサポートインターフェイス名一覧を集合型で取得。
if st_s: # 起点となるサービスかインターフェイスがあるとき。
stack = sorted(list(st_s), reverse=True) # リストにして降順に並べてスタックに取得。
lst_level = [0 for i in stack] # stackの要素すべてについて階層を取得。
indent = " " # インデントを設定。
while stack: # スタックがある間実行。
j = stack.pop() # スタックからpop。
level = lst_level.pop() # jの階層に1を加えて取得。
branch = ["", ""] # 枝をリセット。
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] = "└─"
print("".join(branch) + j) # 枝をつけて出力。
td = tdm.getByHierarchicalName(j) # jのTypeDescriptionオブジェクトを取得。
if td.getTypeClass() == SERVICE: # jがサービスのときtdはXServiceTypeDescriptionインターフェイスをもつ。
t_std = td.getMandatoryServices()+td.getOptionalServices() # 親サービスを取得。
if t_std: # 親サービスがあるとき。
stack.extend(sorted([i.Name for i in t_std], reverse=True)) # 親サービス名を取得して降順に並べてスタックに追加。
lst_level.extend([level + 1 for i in t_std]) # 階層を取得。
itd = td.getInterface() # new-styleサービスのインターフェイスを取得。TypeDescriptionオブジェクト。
if itd: # new-styleサービスのインターフェイスがあるとき。
t_i = itd, # XInterfaceTypeDescription2インターフェイスをもつTypeDescriptionオブジェクト。
else: # new-styleサービスのインターフェイスがないときはold-styleサービスのインターフェイスを取得。
t_i = td.getMandatoryInterfaces() + td.getOptionalInterfaces() # XInterfaceTypeDescriptionインターフェイスをもつTypeDescriptionオブジェクト。
elif td.getTypeClass() == INTERFACE: # インターフェイスのとき。XInterfaceTypeDescription2インターフェイスをもつTypeDescriptionオブジェクト。
t_i = td.getBaseTypes()+td.getOptionalBaseTypes() # さらなる親インターフェイスのリストをo_omiを除いて取得。
if t_i: # 親インターフェイスがあるとき。(TypeDescriptionオブジェクト)
st_i = set([i.Name for i in t_i]).difference(st_omi) # st_omiを除いてインターフェイス名を取得。
t_i = tuple() # 次のループのためにインターフェイスのTypeDescriptionオブジェクトの入れ物を初期化。
if st_i: # インターフェイス名の集合型があるとき。
stack.extend(sorted(list(st_i), reverse=True)) # 集合型をリストに変換して降順にしてスタックに追加。
lst_level.extend([level + 1 for i in list(st_i)]) # 階層を取得。
st_omi.update(st_i) # すでにでてきたインターフェイス名をst_omiに追加して次は使わないようにする。
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