Kデスクトップ環境

3.3. コンポーネントのようなQWidget? - OpenParts::Part インタフェース

OpenParts では、独自のGUIを持ち、メインウインドウに表示されることになっているあらゆるウインドウが Part(ちょうど上記例での数式エディタビューまたはワードプロセッサのドキュメントビューのようなものです。)として呼ばれ、OPPartIfクラスから派生するOpenParts::Partインタフェースを実装します。

ウィジェットクラスをフル機能の Part コンポーネントにしたいなら、 標準的なQt/KDEウィジェットフレームワークに固執し、以前の処理を行うよりも別のことを処理すべきです。 実際ウィジェットは、もはやデータを表示する単なるウインドウではありません、いいえ、Part はこれ以上です。 特に Part は、それがウインドウ(もちろんサブウインドウ、またはその他のPart(OPFrameドキュメントをご覧ください)を含むウィジェット)でありながら、フル機能GUIを備えています。それは、メニュ用メニュバー、ツールバー、ステータスバーで構成されています。

GUIを使用する素晴らしい点は、作成、処理/使用、そして無効にする際の方法にあります。 ユーザーが今アクティブにしたい Part を決定するので、これは高度に動的でなければなりません。 OpenParts は次の基本的なフレームワークを提供します:

まず、しなければならない最初の段階は、OpenParts に Part インタフェース(OPPartIf)、そこから継承すべきクラス、実際のウィジェットが何かを通知することです。というのはOPartIfはQWidgetから継承しないからです。 これは、Part コンポーネントが実際のウィジェットから切り離されているので柔軟です。 しかしこれを行う必要はありません。 単純に、OPartIfQWidget、もしくは適当なウィジェットクラスから多様な継承がおこなえます。 どの場合でも、setWidget( your_widget_here )を呼ぶことで、Part ウィジェットを指定します。 多くの場合、Part コンポーネントが同時にウィジェットである場合、単にsetWidget( this )を呼びます :-)。 このコールはクラスの構造内で行われなければなりません。

次に重要なポイントは、OPPartIfの仮想init()関数を再実装が必要でしょう。 これは是非推奨したいところです。 というのはこの関数は、Part がメインウインドウに登録された後に呼ばれるからです。 この関数に背後にある意図は、Part の構成が実行される時、Part 自体はまだ明確にメインウインドウに登録されないということろにあります。 しかし実際、自分の Part が GUI サーバントオブジェクトにいつ登録されたか知る必要があります。というのは、GUIサーバントオブジェクトに Part が登録されるため、メインウィンドウインタフェース経由のみ有効だからです。 メインウインドウへのリファレンスは、m_vMainWindow変数で可能です。このは、メインウインド上の登録が行われるとに自動的に初期化されます。ですからinit()関数が呼ばれる前にこの変数を使用しないでください。(m_vMainWindowはとにかく、nil になります。)

init()関数の詳細についてです。 ここでは、メインウィンドウへの登録に従う全初期設定を行うべきでしょう。 更に、GUI管理オブジェクトに上述の登録を行うことができます。 通常、これは以下のサンプルのようです:
   1 void MyPart::init()
   2 {
   3   //メニュウバーを使用/表示したいならメニュウバーマネージャに登録
   4   OpenParts::MenuBarManager_var menuBarManager = m_vMainWindow->menuBarManager();
   5   if ( !CORBA::is_nil( menuBarManager ) ) //ウィンドウシェルがメニュバーを持てるかのチェック
   6     menuBarManager->registerClient( id(), this ); //更に詳しい説明は
   7               //*バーマネージャオブジェクトの章
   8               //をご覧下さい。
   9 
  10   //...ツールバーと同様。
  11   OpenParts::ToolBarManager_var toolBarManager = m_vMainWindow->toolBarManager();
  12   if ( !CORBA::is_nil( toolBarManager ) )
  13     toolBarManager->registerClient( id(), this );
  14 
  15   //もちろん、広義クラス変数を定義したほうがよい。
  16   OpenPartsUI::StatusBar_var m_vMyStatusBar;
  17 
  18   OpenParts::StatusBarManager_var statusBarManager = m_vMainWindow->statusBarManager();
  19   if ( !CORBA::is_nil( statusBarManager ) )
  20     m_vMyStatusBar = statusBarManager->registerClient( id() );
  21 }

ただし、これら3つのGUI要素登録コールは、実際に使用したいときにのみ必要です。 たとえば、Part でツールバーを表示させたくないなら、それに対応するコールを無視させなければなしません。 更に、たとえとしてtoolBarManager()コールが nil のリファレンスを返すようなことがあるかもしれません。つまり、メインウィンドウはその Part にツールバーを持たせないように指示するということです。 当然同じようなことがメニューバーやステータスバーにも当てはまります。

OpenParts は Part に GUI の構成/破棄についての伝達をKOMイベントに任せます。これらは特に:

設定された引数は OpenPartsUI::MenuBarです。

設定された引数はOpenPartsUI::ToolBarFactoryです。

Part がメニューバーやツールバーを表示するかしないかに従って、オブジェクト管理はそれに2つのイベントを発動します。 実装に関しては、これはevent()関数を再実装しなければならないということです。(認識事項:Part は完全なKOMコンポーネント機能です。)

用いられたイベント引数は、ツールバーやメニューバーが作成されるか、削除されるかを指示します。 CORBA::is_nil()に対するこれらの引数について調べれば理解できるでしょう:-)。

OpenParts ステータスバーは、メニューバー/ツールバーと比べると異なった処理を行います。 事実これは操作が簡単です。 OpenParts ステータスバーマネージャに登録すると、返り値としてOpenParts::StatusBarを受け取ります。 そうすると、Part のどこででもステータスバー使うことができ、それが可視的(アクティブ)であるかどうかに関係しません。

init()関数で、多数の登録がなされます。 そしてこれに関連してcleanUp()関数(KOM::Base の章をご覧ください。) では、GUIサーバントオブジェクトから登録を解除し、全ての適切なリファレンスを解放しなければ張りません。それはシンメトリックリファレンスや接続といったKOMのモデルにしたがいます。 コードは次のような感じです:
   1 void MyPart::cleanUp()
   2 {
   3   if ( m_bIsClean )
   4     return;
   5 
   6   //メニューバーの登録解除
   7   OpenParts::MenuBarManager_var menuBarManager = m_vMainWindow->menuBarManager();
   8   if ( !CORBA::is_nil( menuBarManager ) )
   9     menuBarManager->unregisterClient( id() );
  10 
  11   //...ツールバーと同様
  12   OpenParts::ToolBarManager_var toolBarManager = m_vMainWindow->toolBarManager();
  13   if ( !CORBA::is_nil( toolBarManager ) )
  14     toolBarManager->unregisterClient( id() );
  15 
  16   OpenParts::StatusBarManager_var statusBarManager = m_vMainWindow->statusBarManager();
  17   if ( !CORBA::is_nil( statusBarManager ) )
  18     statusBarManager->unregisterClient( id() );
  19 
  20   //ここでその他のリファレンスを解放
  21   //...
  22 
  23   //これは重要!!!
  24   //常に、 cleanUp() を基本クラスの手段として呼んで下さい。
  25   OPPartIf::cleanUp();
  26 }