Top > OOoPython > ARFLDescription

AnotherRecentFileList Edit

AnotherRecentFileList を題材に PopupMenu コントローラの実装について詳細に説明。

概要 Edit

OpenOffice.org のメニューのうちサブメニューの項目が変化する内容のものは XPopupMenuController インターフェースとして実装されます。たとえば、「ファイル」-「新規作成」や「ツール」-「マクロ」-「マクロの管理」などがあります。

「最近利用したドキュメント」も同じように実装されています。このメニューにはドキュメントの履歴が表示されますが、OOo で利用できる様々なドキュメントの種類が全てごちゃ混ぜに表示されるため分かりにくいと感じる人もいるようです。

そこで、現在のフレームに表示されているドキュメントと同じ種類のドキュメントのみを表示する履歴メニューを作成してみます。

このメニューの作成に必要なものは次のものです。

  • 履歴リスト
  • フィルターリスト
  • XPopupMenuController を備えた UNO コンポーネント
  • Controller の登録
  • メニューへの登録

履歴リストにはファイル名とそのファイルを開く時に利用されたフィルタ名が保存されています。フィルタ名から度のドキュメントとして開かれたのか判定するためにフィルターリストが必要です。

履歴リスト Edit

履歴のリストは OOo の構成ファイル中に保存されています。保存されている nodepath は /org.openoffice.Office.Common/History です。各要素は次のような項目を保持しています。ここではヘルプのブックマークのものは無視しました。

要素名説明
Size全履歴保存サイズ
List全履歴
PickListSizeメニューでの履歴表示項目数
PickListメニューでの履歴表示項目

全ての履歴と「最近使用したドキュメント」メニューに表示される項目で分けられています。Size および PickListSize は変更でき、どちらも 0-100 の値を取ります (最大値規制されています schema 参照)。

List および PickList 要素はサブノードにそれぞれの履歴についてファイルに関する情報を保存しています。

要素説明
URLファイルの URL
Filter開くときのフィルター名 (内部形式)
Titleドキュメントタイトル
Passwordパスワード

フィルターリスト Edit

フィルターのリストは com.sun.star.document.FilterFactory サービスから取得できます。決まった種類のフィルターのリストを取得する場合には com.sun.star.container.XContainerQuery インターフェースを利用すると便利です。

取得されるフィルター情報は FilerDescriptor で指定されます。ここで必要なのはフィルター名 FilterName および DocumentServiceName です。

モジュール名 Edit

ドキュメントのモジュール名はドキュメントを代表するサービス名と同じ名称です。

ポップアップメニュー概要 Edit

ポップアップメニューは com.sun.star.frame.XPopupMenuController インターフェースを実装した UNO コンポーネントが XPopupMenuFactory からインスタンス化されて利用されます。このとき、そのインスタンスはメニューを項目で埋めたり、項目を更新したりといった要求を処理します。

ポップアップメニューを利用するには XPopupMenuController を実装した UNO コンポーネントをコンフィグレーションに登録しておく必要があります。nodepath は /org.openoffice.Office.UI.Controller/Registered/PopupMenu です。

ポップアップメニューコントローラ Edit

ポップアップメニューコントローラを実装していきます。

ポップアップメニューはメニューの一つの項目として挿入されるためそのメニューを特定するコマンド URL が必要です。ここでは独自のプロトコル mytools.frame: にパス ContextSpecificRecentFileList をつなげて mytools.frame:ContextSpecificRecentFileList とします。

また、ポップアップメニューコントローラの実装名は mytools.frame.ContextSpecificRecentFileList としました。

これらはファイルの最初で定義してあります。

必要なインターフェース Edit

ポップアップメニューコントローラには一般的な UNO コンポーネントのインターフェース以外に次のものがあります。

  • com.sun.star.frame.XPopupMenuController
  • com.sun.star.lang.XInitialization
  • com.sun.star.frame.XDispatchProvider
  • com.sun.star.frame.XStatusListener

実装を特定するために XServiceInfo インターフェースが利用されます。登録した実装名を返すようにします。

  • com.sun.star.lang.XServiceInfo

メニュー項目の選択を知るために XMenuListener インターフェースを利用します。

  • com.sun.star.awt.XMenuListener

履歴リストが更新されたときにメニューのリストを更新するために変更の通知を受けます。

  • com.sun.star.container.XContainerListener

メニューに表示するファイルパスが長いときに省略するために次のインターフェースを利用します。

  • com.sun.star.util.XStringAbbreviation
  • com.sun.star.util.XStringWidth

__init__ Edit

ここで作成するポップアップメニューコントローラは簡単な構造なため全てのインターフェースを継承したクラスを一つだけ作成します。XMenuListener や XContainerListener インターフェースなどは別にクラスを用意するのも手です。

上記のように Py-UNO で実装したポップアップメニューコントローラは XInitialize インターフェースを介さずに __init__ に引数が渡されて初期化されます。XInitialization インターフェースの initialize メソッドに渡して引数を処理しています。

  0
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
class pmc(unohelper.Base,
    XPopupMenuController,
    XInitialization,XStatusListener,
    XDispatchProvider,
    XMenuListener,XContainerListener,XServiceInfo):
    """ PopupMenuController implemenation """
    
    def __init__(self,ctx,*args):
        """Initialization of the popupmenu controller.
		
		PopumuMenuController implemented by Py-UNO is instantiated with __init__ function 
		not initialize method of .lang.XInitialization interface.
		"""
        #args are .beans.PropertyValue|s. Frame, CommandURL and ModuleName
        self.ctx = ctx
        self.frame = None # frame of the document
        self.modname = "" # module name
        self.command = ""
        self.list_changed = False
        self.file_list = []
        self.menu = None
        self.history_list = None
        if args:
            self.initialize(args)
        if self.frame:
            self.frame.addEventListener(self)

XInitialization Edit

ここで、フレーム Frame やモジュール名 ModuleName を取得します。複数の種類のコマンドを一つのポップアップメニューコントローラで処理するのであれば CommandURL を取得しておきます。

  0
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
    # XInitialization
    def initialize(self,args):
        """Frame is passed as an argument at the initialization process."""
        for arg in args:
            
            if arg.Name == u'Frame':
                self.frame = arg.Value
                
            elif arg.Name == u'ModuleName':
                #self.modname = arg.Value
                if arg.Value.startswith(Mod_sdb_prefix):
                    # all database modules as OfficeDatabaseDocument
                    self.modname = Mod_Database
                elif arg.Value == Mod_Chart2:
                    self.modname = Mod_Spreadsheet
                else:
                    self.modname = arg.Value
                
            elif arg.Name == u'CommandURL':
                self.command = arg.Value

XServiceInfo Edit

UNO コンポーネントを PopupMenuController サービスに実装名 IMPL_NAME として登録するため、XServiceInfo インターフェースのメソッドでは次のような値を返します。このインターフェースを実装していない場合はポップアップメニューコントローラを見つけられなくなります。

  0
  1
  2
  3
  4
  5
  6
  7
  8
  9
IMPL_NAME = u'mytools.frame.ContextSpecificRecentFileList'
SERVICE_NAME = u'com.sun.star.frame.PopupMenuController'
 
    # XServiceInfo interface is used to identify the component by the ImplementationName.
    def supportsService(self,name):
        return (name == SERVICE_NAME)
    def getImplementationName(self):
        return IMPL_NAME
    def getSupportedServiceNames(self):
        return (SERVICE_NAME,)

XDispatchProvider Edit

メニューからコマンドで呼ばれるためこのインターフェースが必要です。コマンドが不正であれば無効化することもできます。詳細は DispatchProvider サービスの実装を参考にしてください。

  0
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
    # XDispatchProvider
    def queryDispatch(self,url,name,flag):
        #print "pmc: querydispatch...",url.Complete
        if url.Protocol == Protocol:
            if url.Path == Menu_Path:
                return self
        return None
    
    def queryDispatches(self,args):
        disps = []
        for arg in args:
            disps.append(
                self.queryDispatch(arg.FeatureURL,arg.FrameName,arg.SearchFlags))
        return tuple(disps)

XStatusListener Edit

ステータスの変更を受け取ります。これも DispatchPovider やメニュー、ツールバーコントローラと同じように利用します。ここでは特にステータスの変更は行いません。

  0
  1
  2
  3
    # XStatusListener
    def statusChanged(self,state):
        """This menu is always enabled."""
        pass

XPopupMenuController Edit

このインターフェースはメニュー項目のエントリーの作成およびメニュー項目の更新時に呼ばれるメソッドを提供します。

初期化後、メニューが表示される前に setPopupMenu メソッドが呼ばれます。引数として表示するポップアップメニューが渡されます。このメニューは項目更新時に必要であれば変数に保存しておきます。

渡されるのは com.sun.star.awt.XPopupMenu です。

  0
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
    # XPopupMenuController
    def setPopupMenu(self,menu):
        """Set content of the popup menu passed by the factory."""
        if not self.frame: return
        if not menu: return
        
        self.menu = menu # keep the menu
        try:
            self.fill_menu()
        except Exception,e:
            print e
            return
        # add menu listener
        self.menu.addMenuListener(self)
        # adds container listener
        self.register_listener()
    
    def updatePopupMenu(self):
        """updatePopupMenu call."""
        #print "update pm"
        try:
            if self.list_changed:
                self.clear_menu()
                self.fill_menu()
                self.register_listener()
            self.list_changed = False
        except Exception,e:
            print e

メニューを埋める Edit

独自のコンテキスト依存の履歴を作成してメニューに挿入します。

まず、履歴のリストとフィルタのリストから現在のドキュメントと同じ種類のドキュメントから成る履歴リストを作成します。そのままメニューに表示すると文字列が長すぎることがあるため省略して表示します。

省略表示は URL を短縮表示に変換 -> システムパスに変換の順に行いますが、win 環境ではこの変換に失敗するため別の方法で行います。また、pyuno の fileUrlToSystemPath による URL からシステムパスへの変換時にマルチバイト文字が含まれていると失敗するバグがあるため変換は urllib を利用することにします (このバグは OOo 2.4.1 で修正されたことになっていますが、日本語が含まれると失敗してしまいます)。

  0
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
    def fill_menu(self):
        """Fill menu with entries."""
        self.file_list = []
        
        reader = self.__get_history_reader()
        
        # create history list according to the module name
        if self.modname in (Mod_StartModule,Mod_BasicIDE,Mod_Database):
            self.create_general_history(reader)
        else:
            self.file_list = create_context_spacific_history(
                    self.ctx, reader, self.modname)
        
        if not self.file_list:
            self.menu.insertItem(1,u'~No Documents.',0,1)
            self.menu.enableItem(1,False)
            return
        
        ua = self.ctx.ServiceManager.createInstanceWithContext(
            u'com.sun.star.util.UriAbbreviation', self.ctx)
        sw = string_width()
        
        urlStr = u'URL'
        entries = []
        
        if sep == chr(0x5C):
            for i,v in enumerate(self.file_list):
                
                if v[urlStr].startswith(u'file:///'):
                    syspath = self.abbreviation(
                        unicode(
                            unquote(
                            v[urlStr].encode('ascii')),'utf8'
                        )[8:].replace('/','\\'), 46, '\\')
                else:
                    
                    syspath = ua.abbreviateString(sw,46,v[urlStr])
                label = u'~%s: %s' % (i+1, syspath)
                
                self.menu.insertItem(i+1,label,0,i)
        
        else:
            for i,v in enumerate(self.file_list):
                if v[urlStr].startswith(u'file:///'):
                    syspath = uno.fileUrlToSystemPath(
                        ua.abbreviateString(sw,46,v[urlStr]))
                else:
                    syspath = ua.abbreviateString(sw,46,v[urlStr])
                label = u'~%s: %s' % (i+1, syspath)
                
                self.menu.insertItem(i+1,label,0,i)

履歴の作成 Edit

履歴を作成するには履歴リストの取得およびフィルタリストが必要です。履歴には PickListSize と同じ数だけ項目を表示します。

履歴の List には保存情報が含まれないため、PickList から一部を取得します。

  0
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
def create_context_spacific_history(ctx,reader,modname):
    """Context specific history."""
    # make a module specific list
    iFlag = 0x1
    eFlag = 0x8 + 0x1000 + 0x40000
    
    filter_list = get_filter_list(ctx,modname,iFlag,eFlag)
    
    if not filter_list.has_key(modname):
        # not found
        return create_general_history(reader)
    
    file_list = []
    
    # size of the list
    pk_size = reader.getPropertyValue(u'PickListSize')
    
    # module specific filter names
    if modname == Mod_Global:
        # GlobalDocument: Global + Text
        Global_filters = Set(filter_list.get(Mod_Global,[]))
        Text_filters = Set(filter_list.get(Mod_Text,[]))
        mod_filters = Global_filters | Text_filters
    else:
        mod_filters = Set(filter_list[modname])
    
    filterName = u'Filter'
    urlStr = u'URL'
    
    # "List" does not list stored file. So, get files form "PickList" and 
    # complement remains from "List".
    
    # PickList keeps Recent Files entries.
    pk_list = reader.getPropertyValue(u'PickList')
    
    if pk_list.hasElements():
        for name in pk_list.getElementNames():
            
            pk = pk_list.getByName(name)
            fl = pk.getPropertyValue(filterName)
            
            # check the filter
            if fl in mod_filters:
                element = {}
                element[urlStr] = pk.getPropertyValue(urlStr)
                element[filterName] = fl
                
                file_list.append(element)
    
    # List keeps all file histories.
    hist_list = reader.getPropertyValue(u'List')
    
    if hist_list.hasElements():
        for name in hist_list.getElementNames():
            
            hist = hist_list.getByName(name)
            fl = hist.getPropertyValue(filterName)
            
            if fl in mod_filters:
                element = {}
                element[urlStr] = hist.getPropertyValue(urlStr)
                element[filterName] = fl
                
                if not element in file_list:
                    file_list.append(element)
                
                if len(file_list) >= pk_size: break
    return file_list

フィルタリストの取得 Edit

フィルタリストの取得は FilterFactory からモジュール名およびフラッグを指定して行います。特定のドキュメントの種類で利用されるフィルタのみが取得できます。また、フラッグで内部フィルタなどを排除しています。指定するフィルタは OOo のソースコードを参照。

  0
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
def get_filter_info(descs):
    docService = u'DocumentService'
    filterName = u'Name'
    service = ""
    name = ""
    
    for desc in descs:
        if desc.Name == docService:
            service = desc.Value
        elif desc.Name == filterName:
            name = desc.Value
    return service,name
 
 
def get_filter_list(ctx,mod="",iFlag=0,eFlag=0):
    """Get filter list from FilterFactory.
	
	Returned filters are categorized in their module.
	filer_list["com.sun.star.sheet.SpreadsheetDocument": ["calc8", "..."], "": ... ]
	"""
    ff = ctx.ServiceManager.createInstanceWithContext(
        u'com.sun.star.document.FilterFactory' ,ctx)
    que = u'getSortedFilterList():module=%s:iflags=%s:eflags=%s' % (mod,iFlag,eFlag)
    filters = ff.createSubSetEnumerationByQuery(que)
    
    filter_list = {}
    
    get_info = get_filter_info
    
    while filters.hasMoreElements():
        fl = filters.nextElement()
        service,name = get_info(fl)
        if filter_list.has_key(service):
            filter_list[service].append(name)
        else:
            filter_list[service] = [name]
    
    return filter_list

XContainerListener Edit

履歴リストが更新されたときに通知を受けます。何度も受けても仕方ないのでリスナーを削除しておきます。メニュー内容の更新は updatePopupMenu メソッドが呼ばれたときに行うことにします。また、そのときに再度リスナーを設定します。

  0
  1
  2
  3
  4
  5
  6
  7
  8
  9
    # XContainerListener
    def elementInserted(self,ev):
        self.list_changed = True
        self.unregister_listener()
    def elementRemoved(self,ev):
        self.list_changed = True
        self.unregister_listener()
    def elementReplaced(self,ev):
        self.list_changed = True
        self.unregister_listener()

XMenuListener Edit

メニューの項目がクリックされるとファイルを開きます。ポップアップメニューの MenuId が 0 はキャンセルに予約されているので利用してはいけません。

  0
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
    # XMenuListener
    def hihglight(self,ev):
        pass
    def activate(self,ev):
        pass
    def deactivate(self,ev):
        pass
    def select(self,ev):
        menu_id = ev.MenuId
        if menu_id <= 0: return
        
        if self.file_list and len(self.file_list) < menu_id -1:
            self.open_file( self.file_list[menu_id -1] )

ファイルを開く Edit

履歴リストで項目が選択されたときそのファイルを開きます。ファイルを開くのは dispatch で行うと普通にメニューなどから開いたときと同じ動作になります。

  0
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
    def open_file(self,entry):
        """Open file with dispatch."""
        if not self.frame: return
        
        url = URL()
        url.Complete = u'.uno:Open'
        #print entry["URL"],entry["Filter"]
        transformer = self.ctx.ServiceManager.createInstanceWithContext(
            u'com.sun.star.util.URLTransformer', self.ctx)
        d,url = transformer.parseStrict(url)
        
        arg1 = create_PropertyValue(u'Referer', u'private:user')
        arg2 = create_PropertyValue(u'AsTemplate',False)
        arg3 = create_PropertyValue(u'FilterName',entry[u'Filter'])
        arg4 = create_PropertyValue(u'SynchronMode',False)
        arg5 = create_PropertyValue(u'URL',entry[u'URL'])
        arg6 = create_PropertyValue(u'FrameName',u'_default')
        args = (arg1,arg2,arg3,arg4,arg5,arg6)
        
        desktop = self.ctx.ServiceManager.createInstanceWithContext(
            u'com.sun.star.frame.Desktop', self.ctx)
        
        disp = desktop.queryDispatch(url,u'_self',0)
        
        if disp:
            disp.dispatch(url,args)

コントローラの登録 Edit

作成したポップアップメニューコントローラは OOo に認識されるようにコンフィグレーションに登録しなければいけません。登録は /org.openoffice.Office.UI.Controller/Registered/PopupMenu に新しく独自名のノードを追加して行います。テンプレート名は org.openoffice.Office.UI.Controller/ControllerType です。

ノード名は他の人のものと同じにならないように適当に独自の名前を付けます。

  0
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
<?xml version='1.0' encoding='UTF-8'?>
 
<oor:component-data 
xmlns:oor="http://openoffice.org/2001/registry" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
oor:name="Controller" 
oor:package="org.openoffice.Office.UI">
<node oor:name="Registered">
    <node oor:name="PopupMenu">
        <node oor:name="mytools.frame.ContextSpecificRecentFileList" oor:op="replace">
            <prop oor:name="Command">
                <value>mytools.frame:ContextSpecificRecentFileList</value>
            </prop>
            <prop oor:name="Module">
 
                <value></value>
            </prop>
            <prop oor:name="Controller">
                <value>mytools.frame.ContextSpecificRecentFileList</value>
            </prop>
        </node>
    </node>
</node>
</oor:component-data>
項目説明
Commandコマンド名
Module利用するモジュール
Controllerポップアップメニューコントローラを実装するコンポーネントの実装名

メニューへの組み込み Edit

既存メニューへの組み込みは Addons コンフィグレーションにより行われます。詳細はアドオンツールバーとメニューを参照してください。

「ファイル」メニューの「最近利用したファイル」メニューの一つ下に追加することにします。

位置は「ファイル」メニューのコマンド .uno:PickList にある「最近利用したファイル」 .uno:RecentFileList の下のため .uno:PickList\.uno:RecentFileList となります。追加するためのコマンド AddAfter を指定、追加目標メニューがないときには無視するために AddPath を指定しています。 追加されるメニューの URL には mytools.frame:ContextSpecificRecentFileList を指定します。

  0
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
<?xml version='1.0' encoding='UTF-8'?>
<oor:component-data 
xmlns:oor="http://openoffice.org/2001/registry" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
oor:name="Addons" 
oor:package="org.openoffice.Office">
 <node oor:name="AddonUI">
  <node oor:name="OfficeMenuBarMerging">
   <node oor:name="mytools.frame" oor:op="replace">
    <node oor:name="ContextSpecificRecentFileList" oor:op="replace">
     <prop oor:name="MergePoint">
      <value>.uno:PickList\.uno:RecentFileList</value>
     </prop>
     <prop oor:name="MergeCommand">
      <value>AddAfter</value>
     </prop>
     <prop oor:name="MergeFallback">
      <value>AddPath</value>
     </prop>
     <prop oor:name="MergeContext">
      <value>com.sun.star.text.TextDocument,
com.sun.star.sheet.SpreadsheetDocument,
com.sun.star.presentation.PresentationDocument,
com.sun.star.drawing.DrawingDocument,
com.sun.star.text.GlobalDocument,
com.sun.star.text.WebDocument,
com.sun.star.formula.FormulaProperties</value>
     </prop>
     <node oor:name="MenuItems">
      <node oor:name="a11_show1" oor:op="replace">
       <prop oor:name="Title">
        <value xml:lang="en-US">~Recent Documents 2</value>
       </prop>
       <prop oor:name="URL" oor:type="xs:string">
        <value>mytools.frame:ContextSpecificRecentFileList</value>
       </prop>
       <prop oor:name="Target">
        <value>_self</value>
       </prop>
       <prop oor:name="Context">
        <value>com.sun.star.text.TextDocument,
com.sun.star.sheet.SpreadsheetDocument,
com.sun.star.presentation.PresentationDocument,
com.sun.star.drawing.DrawingDocument,
com.sun.star.text.GlobalDocument,
com.sun.star.text.WebDocument,
com.sun.star.formula.FormulaProperties</value>
       </prop>
      </node>
     </node>
    </node>
   </node>
  </node>
 </node>
</oor:component-data>

パッケージ作成 Edit

ZIP アーカイブにひとまとめにしたパッケージを作成するまえに次のようなファイルを作成します。

META-INF Edit

拡張機能に処理させる必要のあるファイルを記述します。

登録する必要があるのは ポップアップメニューコントローラを実装した UNO コンポーネントの pmc.py ファイル、メニューを追加するための Addons.xcu、コントローラを登録するための Controller.xcu ファイルです。これらのファイルは任意の名称に変更します。ファイルの種類は以下のようになります。

  0
  1
  2
  3
  4
  5
  6
  7
<?xml version="1.0" encoding="UTF-8"?>
<manifest:manifest>
 <manifest:file-entry manifest:full-path="pmc.py" 
manifest:media-type="application/vnd.sun.star.uno-component;type=Python"/>
 <manifest:file-entry manifest:full-path="Controller.xcu" 
manifest:media-type="application/vnd.sun.star.configuration-data"/>
 <manifest:file-entry manifest:full-path="Addons.xcu" 
manifest:media-type="application/vnd.sun.star.configuration-data"/>
</manifest:manifest>

description.xml Edit

拡張機能の情報などを記述します。このファイル名は変更してはいけません。

他の拡張機能と区別されるように identifier を指定します。また、バージョンや依存性、ライセンス表示を指定します。

  0
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
<?xml version="1.0" encoding="UTF-8"?>
<description xmlns="http://openoffice.org/extensions/description/2006"
	xmlns:xlink="http://www.w3.org/1999/xlink"
	xmlns:d="http://openoffice.org/extensions/description/2006">
	<identifier value="mytools.frame.ContextSpecificRecentFileList" />
	<version value="0.0.4" />
	<dependencies>
		<OpenOffice.org-minimal-version value="2.3" d:name="OpenOffice.org 2.3" />
	</dependencies>
	<registration>
		<simple-license accept-by="user" default-license-id="this" suppress-on-update="true">
			<license-text xlink:href="LICENSE.txt" license-id="this" />
		</simple-license>
	</registration>
	<display-name>
		<name lang="en">Context specific recent file list.</name>
	</display-name>
</description>

パッケージ化 Edit

パッケージの作成は次のようなファイル配置で行います。description.xml および META-INF/manifest.xml ファイル以外のファイルは上記のファイルに指定した位置に配置します。指定によって自由に変更できます (あまりに複雑にネストしたディレクトリに入れるとパス名長問題が発生する場合があります)。

  • 適当なディレクトリ内
    • META-INF
      • manifest.xml
    • description.xml
    • pmc.py
    • Addons.xcu
    • Controller.xcu
    • LICENSE.txt

これらのファイルを選択して ZIP アーカイブを作成します。このとき、ファイルがアーカイブの最上層にくるようにしてください。そうでなければ拡張機能マネージャが読み込みに失敗します。

ファイル名を適当に .oxt などに変更して完成です。

インストール Edit

  1. OpenOffice.org を起動します
  2. メニュー - ツール - 拡張機能マネージャを選択します
  3. 「マイ拡張機能」を選択、追加ボタンを押します
  4. インストールする拡張機能のファイルを選択します

コメント Edit



Reload   New Lower page making Edit Freeze Diff Upload Copy Rename   Front page List of pages Search Recent changes Backup   Help   RSS of recent changes