前の関連記事:Calc(48)ドキュメントイベントを調べる
デスクトップに追加できるリスナーの一覧
LibreOffice5(95)デスクトップのサービスとインターフェイスの一覧から探したものです。
XTerminateListener
デスクトップを終了する間際と終了時に発火するメソッドがあります(Using the Desktop - Apache OpenOffice Wiki)。
このリスナーはLibreOfficeが終了するときに除去しないと、次にLibreOfficeが起動しなくなってしまいました。
linuxBean14.04のタスクマネージャでみてみるとLibreOffice終了後にCPU使用率が100%になって、soffice.binのプロセスが残ったままになっていました。
この状態でLibreOfficeを起動しようとするとスプラッシュ画面のまま動きませんでした。
タスクマネージャではsoffice.binが二つになっていました。
終了しているはずのsoffice.binを強制終了にするとLibreOfficeが起動できるようになりました。
XFrameActionListener
enumのFrameActionにあるイベントが発生した時にframeAction()メソッドが発火します(Frames - Apache OpenOffice Wiki)。
発火させたイベントはframeAction()メソッドの引数のFrameActionEvent StructのActionアトリビュートにenumのFrameActionが入っていることで判別できます。
しかし、下のマクロでやったように、デスクトップはフレームそのものではないせいか、このリスナーのメソッドを発火させる状況は見つけられませんでした。
XPropertyChangeListener
XVetoableChangeListener
これらのインターフェイスのメソッドはそれぞれboundプロパティとconstrainedプロパティが変更された時に発火されます。
しかしboundプロパティとconstrainedプロパティが存在しないようですので使う機会はなさそうです(OOobbs2/84 - ...?)。
Defining a Service - Apache OpenOffice Wikiにプロパティの種類一覧があります。
いまのところAPIリファレンスをみてもほとんどがoptionalプロパティかreadonlyプロパティです。
テキストカーサーのParagraphProperties Serviceにようやくmaybevoidプロパティをみつけました。
XPropertiesChangeListener
これは複数のboundプロパティの変更に応じて(or?and?order?)発火するメソッドがありますが、これもboundプロパティがないオブジェクトでは意味がありません。
以下はデスクトップ自身がリスナーになっているインターフェイスです。
XDispatchResultListener
XEventListener
リスナーをみても具体的にどのオブジェクトにリスナーとして追加されているのかはわかりません。
XDispatchResultListenerでディスパッチコマンドの結果を受け取っているようです。
XEventListenerはリスナーが実装しておかないといけない必須メソッドのdisposing()です。
デスクトップに追加できるリスナーのマクロの例
#!/opt/libreoffice5.4/program/python # -*- coding: utf-8 -*- import unohelper # オートメーションには必須(必須なのはuno)。 import os import inspect from datetime import datetime from com.sun.star.frame import XTerminateListener from com.sun.star.frame import XFrameActionListener from com.sun.star.frame.FrameAction import COMPONENT_ATTACHED, COMPONENT_DETACHING, COMPONENT_REATTACHED, FRAME_ACTIVATED, FRAME_DEACTIVATING, CONTEXT_CHANGED, FRAME_UI_ACTIVATED, FRAME_UI_DEACTIVATING # enum def macro(documentevent=None): # 引数は文書のイベント駆動用。OnStartAppでもDocumentEventが入る。LibreOfficeに保存する。 ctx = XSCRIPTCONTEXT.getComponentContext() # コンポーネントコンテクストの取得。 thisscriptpath = unohelper.fileUrlToSystemPath(__file__) # __file__はfileurlで返ってくるのでシステムパスに変換。 dirpath = os.path.dirname(thisscriptpath) # このスクリプトのあるディレクトリのフルパスを取得。 desktop = ctx.getByName('/singletons/com.sun.star.frame.theDesktop') # com.sun.star.frame.Desktopはdeprecatedになっている。 desktop_terminatelistener = TerminateListener(dirpath, "desktop_terminatelistener") # TerminateListener desktop.addTerminateListener(desktop_terminatelistener) # 使い終わったらremoveしないといけない。 desktop_frameactionlistener = FrameActionListener(dirpath, "desktop_frameactionlistener") # FrameActionListener desktop.addFrameActionListener(desktop_frameactionlistener) # いつ呼ばれる? class FrameActionListener(unohelper.Base, XFrameActionListener): # FrameActionListener def __init__(self, dirpath, name): # 出力先ディレクトリのパス、リスナーのインスタンス名。 enums = COMPONENT_ATTACHED, COMPONENT_DETACHING, COMPONENT_REATTACHED, FRAME_ACTIVATED, FRAME_DEACTIVATING, CONTEXT_CHANGED, FRAME_UI_ACTIVATED, FRAME_UI_DEACTIVATING # enum frameactionnames = "COMPONENT_ATTACHED", "COMPONENT_DETACHING", "COMPONENT_REATTACHED", "FRAME_ACTIVATED", "FRAME_DEACTIVATING", "CONTEXT_CHANGED", "FRAME_UI_ACTIVATED", "FRAME_UI_DEACTIVATING" self.args = dirpath, name, zip(enums, frameactionnames) def frameAction(self, frameactionevent): dirpath, name, frameactions = self.args frameaction = frameactionevent.Action for enum, frameactionname in frameactions: if frameaction==enum: methodname = "_".join((name, inspect.currentframe().f_code.co_name)) # このメソッド名を取得。メソッド内で実行する必要がある。 createLog(dirpath, methodname, "frameactionevent.FrameAction(enum): {}".format(frameactionname)) # frameactionのenum名を出力。 return def disposing(self, eventobject): pass class TerminateListener(unohelper.Base, XTerminateListener): # TerminateListener def __init__(self, dirpath, name): # 出力先ディレクトリのパス、リスナーのインスタンス名。 self.args = dirpath, name def queryTermination(self, eventobject): dirpath, name = self.args methodname = "_".join((name, inspect.currentframe().f_code.co_name)) # このメソッド名を取得。メソッド内で実行する必要がある。 createLog(dirpath, methodname, "eventobject.Source: {}".format(eventobject.Source)) # Sourceを出力。 def notifyTermination(self, eventobject): dirpath, name = self.args methodname = "_".join((name, inspect.currentframe().f_code.co_name)) # このメソッド名を取得。メソッド内で実行する必要がある。 createLog(dirpath, methodname, "eventobject.Source: {}".format(eventobject.Source)) # Sourceを出力。 desktop = eventobject.Source desktop.removeTerminateListener(self) # TerminateListenerを除去。除去しなmethodname = inspect.currentframe().f_code.co_nameいとLibreOfficeのプロセスが残って起動できなくなる。 def disposing(self, eventobject): pass def createLog(dirpath, methodname, txt): # 年月日T時分秒リスナーのインスタンス名_methodname.logファイルを作成。txtはファイルに書き込むテキスト。dirpathはファイルを書き出すディレクトリ。 timestamp = datetime.now().isoformat().split(".")[0].replace("-", "").replace(":", "") # コピー先ファイル名に使う年月日T時分秒を結合した文字列を取得。 filename = "".join((timestamp, methodname, ".log")) with open(os.path.join(dirpath, filename), "w") as f: f.write(txt) g_exportedScripts = macro, #マクロセレクターに限定表示させる関数をタプルで指定。このマクロファイルをマイマクロフォルダに置きます。
XTerminateListenerかXFrameActionListenerのメソッドが発火すると、マクロファイルがあるフォルダに発火した年月日T時分秒リスナーのインスタンス名_methodname.logというファイル名のテキストファイルを出力するようにしています。
リスナーのメソッドが発火するイベントが発生する前にこのマクロを起動しておくようにします。
ツール→カスタマイズ、イベントタブ。
一番最初に起動されると思われる「アプリケーションの開始時」にこのマクロを割り当てました。
保存先は「LibreOffice」にしておかないといけません。
保存先をドキュメントにすると「アプリケーションの開始時」に割り当てたマクロは実行されませんでした。
「アプリケーションの開始時」にはドキュメントはロードされていないので当然のことかもしれません。
なので、マクロの引数のDocumentEvent StructのSourceアトリビュートに入っているのもドキュメントモデルではなくNoneが入っていました。
「アプリケーションの開始時」に実行するマクロで新規作成されたドキュメントを取得しようとしましたが、そのマクロが終わってからしかドキュメントが作成されないようで、それはうまくいきませんでした。
ちなみにUNOのStructはHashableでないということで、Pythonの辞書のキーにはできませんでした。
「アプリケーションの開始時」に登録したマクロは不要になったら忘れずに削除しておかないと、永遠と動き続けることになります。
デスクトップのリスナーが発火するとき
上記の設定後LibreOfficeを起動したときからデスクトップに追加したXTerminateListenerかXFrameActionListenerかのメソッドが発火するとマイマクロフォルダに置いたマクロファイルと同じフォルダに発火した年月日T時分秒リスナーのインスタンス名_methodname.logというテキストファイルが作成されます。
LibreOfficeを終了するときにXTerminateListenerのnotifyTermination、queryTerminationという順で発火していることがわかりました。
XFrameActionListenerのメソッドが発火するときはいまのところわかりませんでした。
おそらくデスクトップでは発火しないと思います。
結局デスクトップで発火するリスナーはLibreOfficeを終了するときだけのようですので、どのタイミングでこのマクロを開始しても同じ結果になります。
参考にしたサイト
Using the Desktop - Apache OpenOffice Wiki
XTerminateListenerのメソッドの解説。
Frames - Apache OpenOffice Wiki
Frame Actionsの解説。
OOobbs2/84 - ...?
XPropertyChangeListenerやXVetoableChangeListenerが発火するboundプロパティやconstrainedプロパティはデスクトップにはありませんでした。
Defining a Service - Apache OpenOffice Wiki
old-style Serviceのプロパティの種類の解説。
0 件のコメント:
コメントを投稿