前の関連記事:LibreOffice5(3)IPython NotebookでUNOオブジェクトの属性を木で出力する
LibreOffice5(3)IPython NotebookでUNOオブジェクトの属性を木で出力するのunoinsp.pyで出力されていないUNOオブジェクトのインターフェイスがあることに気が付きました。UNOオブジェクトにはサービスをインスタンス化したものとインターフェイスしかもたないもの、の2種類しかないと勘違いしていたのが原因です。
Writerのコントローラはサービス以外に直接インターフェイスを持っていた
linuxBean14.04(88)LibreOffice5をIPython Notebookから操作するのソケット通信の状態で起動したLibreOfficeを操作する方法でLibreOfficeを起動した状態でPyCharmから実行します。
import unopy XSCRIPTCONTEXT = unopy.connect() if not XSCRIPTCONTEXT: print("Failed to connect.") import sys sys.exit(0) else: import unoinsp ins = unoinsp.ObjInsp(XSCRIPTCONTEXT) xDoc = XSCRIPTCONTEXT.getDocument() xController = xDoc.getCurrentController() ins.tree(xController)これでWriterのコントローラの属性とメソッドが出力されるはずです。
.text.TextDocumentView │ boolean IsConstantSpellcheck │ boolean IsHideSpellMarks │ long LineCount │ long PageCount ├─.beans.XPropertySet │ void addPropertyChangeListener( [in] string aPropertyName, │ [in] .beans.XPropertyChangeListener xListener │ ) raises ( .lang.WrappedTargetException, │ .beans.UnknownPropertyException) │ void addVetoableChangeListener( [in] string PropertyName, │ [in] .beans.XVetoableChangeListener aListener │ ) raises ( .lang.WrappedTargetException, │ .beans.UnknownPropertyException) │ .beans.XPropertySetInfo getPropertySetInfo() │ any getPropertyValue( [in] string PropertyName │ ) raises ( .lang.WrappedTargetException, │ .beans.UnknownPropertyException) │ void removePropertyChangeListener( [in] string aPropertyName, │ [in] .beans.XPropertyChangeListener aListener │ ) raises ( .lang.WrappedTargetException, │ .beans.UnknownPropertyException) │ void removeVetoableChangeListener( [in] string PropertyName, │ [in] .beans.XVetoableChangeListener aListener │ ) raises ( .lang.WrappedTargetException, │ .beans.UnknownPropertyException) │ void setPropertyValue( [in] string aPropertyName, │ [in] any aValue │ ) raises ( .lang.WrappedTargetException, │ .lang.IllegalArgumentException, │ .beans.PropertyVetoException, │ .beans.UnknownPropertyException) ├─.text.XTextViewCursorSupplier │ .text.XTextViewCursor getViewCursor() ├─.view.XViewSettingsSupplier │ .beans.XPropertySet getViewSettings() └─.view.OfficeDocumentView ├─.view.XControlAccess │ .awt.XControl getControl( [in] .awt.XControlModel xModel │ ) raises ( .container.NoSuchElementException) └─.view.XSelectionSupplier void addSelectionChangeListener( [in] .view.XSelectionChangeListener xListener) any getSelection() void removeSelectionChangeListener( [in] .view.XSelectionChangeListener xListener) boolean select( [in] any xSelection ) raises ( .lang.IllegalArgumentException)インターフェイスは5つしかでてきません。
ところがprint(xController)とするともっとインターフェイスが存在していることがわかります。
com.sun.star.frame.XController2,
com.sun.star.frame.XControllerBorder,
com.sun.star.frame.XDispatchProvider,
com.sun.star.task.XStatusIndicatorSupplier,
com.sun.star.ui.XContextMenuInterception,
com.sun.star.awt.XUserInputInterception,
com.sun.star.frame.XDispatchInformationProvider,
com.sun.star.frame.XTitle,
com.sun.star.frame.XTitleChangeBroadcaster,
com.sun.star.lang.XInitialization,
com.sun.star.lang.XServiceInfo,
com.sun.star.view.XFormLayerAccess,
com.sun.star.text.XRubySelection,
com.sun.star.datatransfer.XTransferableSupplier
unoinsp.pyで出力を抑制しているインターフェイス以外にこれら14個のインターフェイスが出力されていません。
これはunoinsp.pyでUNOオブジェクトをサービスを持っているものと持っていないものの2種類にしか場合わけしていないのが原因です。
サービスを持っているのにさらにインターフェイスもUNOオブジェクトが直接持っているものがあるとは想定していませんでした。
(2015.11.8追記。デベロッパーマニュアルにちゃんと書いてあったのを忘れていました。
Moreover, since a component developer is free to implement services and interfaces as required, there is not necessarily a one-to-one relationship between a certain service specification and a real object. The real object can be capable of more things than specified in a service definition.)
Understanding the API Reference - Apache OpenOffice Wiki
これを修正することにします。
ちなみにprint(xController)ではなぜかcom.sun.star.view.XControlAccessが出力されていませんが、print(hasattr(xController, "getControl"))はTrueが返ってきます。
サービスをもっているUNOオブジェクトが直接もっているインターフェイスも取得する
unoinsp.py
UNOオブジェクトがサービスをサポートしていてもさらにサービスを通さずにサポートしているインターフェイスを検索するようにしました。
.text.TextDocumentView │ boolean IsConstantSpellcheck │ boolean IsHideSpellMarks │ long LineCount │ long PageCount ├─.beans.XPropertySet │ void addPropertyChangeListener( [in] string aPropertyName, │ [in] .beans.XPropertyChangeListener xListener │ ) raises ( .lang.WrappedTargetException, │ .beans.UnknownPropertyException) │ void addVetoableChangeListener( [in] string PropertyName, │ [in] .beans.XVetoableChangeListener aListener │ ) raises ( .lang.WrappedTargetException, │ .beans.UnknownPropertyException) │ .beans.XPropertySetInfo getPropertySetInfo() │ any getPropertyValue( [in] string PropertyName │ ) raises ( .lang.WrappedTargetException, │ .beans.UnknownPropertyException) │ void removePropertyChangeListener( [in] string aPropertyName, │ [in] .beans.XPropertyChangeListener aListener │ ) raises ( .lang.WrappedTargetException, │ .beans.UnknownPropertyException) │ void removeVetoableChangeListener( [in] string PropertyName, │ [in] .beans.XVetoableChangeListener aListener │ ) raises ( .lang.WrappedTargetException, │ .beans.UnknownPropertyException) │ void setPropertyValue( [in] string aPropertyName, │ [in] any aValue │ ) raises ( .lang.WrappedTargetException, │ .lang.IllegalArgumentException, │ .beans.PropertyVetoException, │ .beans.UnknownPropertyException) ├─.text.XTextViewCursorSupplier │ .text.XTextViewCursor getViewCursor() ├─.view.XViewSettingsSupplier │ .beans.XPropertySet getViewSettings() └─.view.OfficeDocumentView ├─.view.XControlAccess │ .awt.XControl getControl( [in] .awt.XControlModel xModel │ ) raises ( .container.NoSuchElementException) └─.view.XSelectionSupplier void addSelectionChangeListener( [in] .view.XSelectionChangeListener xListener) any getSelection() void removeSelectionChangeListener( [in] .view.XSelectionChangeListener xListener) boolean select( [in] any xSelection ) raises ( .lang.IllegalArgumentException) .awt.XUserInputInterception void addKeyHandler( [in] .awt.XKeyHandler xHandler) void addMouseClickHandler( [in] .awt.XMouseClickHandler xHandler) void removeKeyHandler( [in] .awt.XKeyHandler xHandler) void removeMouseClickHandler( [in] .awt.XMouseClickHandler xHandler) .datatransfer.XTransferableSupplier .datatransfer.XTransferable getTransferable() void insertTransferable( [in] .datatransfer.XTransferable xTrans ) raises ( .datatransfer.UnsupportedFlavorException) .frame.XController2 │ .awt.XWindow ComponentWindow │ [.beans.PropertyValue] CreationArguments │ string ViewControllerName └─.frame.XController │ void attachFrame( [in] .frame.XFrame Frame) │ boolean attachModel( [in] .frame.XModel Model) │ .frame.XFrame getFrame() │ .frame.XModel getModel() │ any getViewData() │ void restoreViewData( [in] any Data) │ boolean suspend( [in] boolean Suspend) └─.lang.XComponent void addEventListener( [in] .lang.XEventListener xListener) void dispose() void removeEventListener( [in] .lang.XEventListener aListener) .frame.XControllerBorder void addBorderResizeListener( [in] .frame.XBorderResizeListener xListener) .frame.BorderWidths getBorder() .awt.Rectangle queryBorderedArea( [in] .awt.Rectangle aPreliminaryRectangle) void removeBorderResizeListener( [in] .frame.XBorderResizeListener xListener) .frame.XDispatchInformationProvider [.frame.DispatchInformation] getConfigurableDispatchInformation( [in] short CommandGroup) [short] getSupportedCommandGroups() .frame.XDispatchProvider .frame.XDispatch queryDispatch( [in] .util.URL URL, [in] string TargetFrameName, [in] long SearchFlags) [.frame.XDispatch] queryDispatches( [in] [.frame.DispatchDescriptor] Requests) .frame.XTitle string getTitle() void setTitle( [in] string sTitle) .frame.XTitleChangeBroadcaster void addTitleChangeListener( [in] .frame.XTitleChangeListener xListener) void removeTitleChangeListener( [in] .frame.XTitleChangeListener xListener) .lang.XInitialization void initialize( [in] [any] aArguments ) raises ( .uno.Exception) .lang.XServiceInfo string getImplementationName() [string] getSupportedServiceNames() boolean supportsService( [in] string ServiceName) .task.XStatusIndicatorSupplier .task.XStatusIndicator getStatusIndicator() .text.XRubySelection [.beans.PropertyValues] getRubyList( [in] boolean Automatic) void setRubyList( [in] [.beans.PropertyValues] RubyList, [in] boolean Automatic) .ui.XContextMenuInterception void registerContextMenuInterceptor( [in] .ui.XContextMenuInterceptor Interceptor) void releaseContextMenuInterceptor( [in] .ui.XContextMenuInterceptor Interceptor) .view.XFormLayerAccess .form.runtime.XFormController getFormController( [in] .form.XForm Form) boolean isFormDesignMode() void setFormDesignMode( [in] boolean DesignMode)これですべてのインターフェイスが出力されるようになりました。
unoinsp.pyを読み直しているとサービスは親子関係を確認して親は木の根にしないようにしているのに、インターフェイスは同様の処理をしていないのでUNOオブジェクトが直接もっているインターフェイスは親子関係が表現できていないものがあるのではないかと心配しましたが、インターフェイスはサービスと違って異なる階層にあるものは出力されていなかったのでサービスでやったような処理は必要ではありませんでした。
ここで使っている[親子関係」とはunoinsp.pyのコメントと同様にLibreOffice: Class Listのクラス図にあるA→B(A inherited from B)のAを子、Bを親と言っています。
AにメソッドがなければBに探しにいくのでA(子)→B(親)という矢印の方向になっています。
ins.tree()出力結果ではLibreOffice: Class Listのクラス図の天地を入れ替えた関係になっています。
.frame.XController2についての出力とそのクラス図を比較するとよくわかります。
参考にしたサイト
LibreOffice: Class List
LibreOffice APIリファレンス。
0 件のコメント:
コメントを投稿