LibreOffice5(4)unoinsp.pyの修正

前の関連記事: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リファレンス。

次の関連記事:LibreOffice5(5)unoinsp.pyでAPIリファレンスへのリンクを付ける

PR

0 件のコメント:

コメントを投稿