Difference between revisions of "UNO component packaging"

From Apache OpenOffice Wiki
Jump to: navigation, search
m (See also)
(See also)
 
(20 intermediate revisions by 5 users not shown)
Line 2: Line 2:
 
This page shows you how to pack and deploy already written UNO component. I'm using my ''Wavelet'' class as an example of a very simple component.  
 
This page shows you how to pack and deploy already written UNO component. I'm using my ''Wavelet'' class as an example of a very simple component.  
  
More detailed info is in the [[http://api.openoffice.org/docs/DevelopersGuide/Components/Components.htm Developers Guide]].  
+
More detailed info is in the [[Documentation/DevGuide/WritingUNO/Deployment_Options_for_Components|Developers Guide]].
  
 
=Python loader=
 
=Python loader=
Python loader is not able load classes from more than one file. Thus it's necessary to put all classes in one python source file. (Honestly, I read it somewhere and I didn't test this.)
+
The Python loader is not able load classes that are not it its own path. Thus it's necessary to copy any classes or modules you will use into the OPenOffice Python lib directory, and it may be necessary to restart OOo before they are picked up.  
  
 
=Sample Python component=
 
=Sample Python component=
  
 
==Wavelet class==
 
==Wavelet class==
We will use my sample ''Wavelet'' class which replaces space with non breaking space before the Czech prepositions. Put the following code in the ''Wavelet.py'' file.  
+
We will use my sample ''Wavelet'' class which replaces space with non-breaking space before the Czech prepositions. Put the following code in the ''Wavelet.py'' file.  
 +
 
 +
<syntaxhighlight lang="python">
  
<code>[python]
 
 
import uno
 
import uno
 
import unohelper
 
import unohelper
import string
 
 
 
from com.sun.star.task import XJobExecutor
 
from com.sun.star.task import XJobExecutor
+
 
 
class Wavelet( unohelper.Base, XJobExecutor ):
 
class Wavelet( unohelper.Base, XJobExecutor ):
 
     def __init__( self, ctx ):
 
     def __init__( self, ctx ):
Line 36: Line 35:
 
             found = doc.findFirst( search )
 
             found = doc.findFirst( search )
 
             while found:
 
             while found:
                 found.String = string.replace( found.String, " ", u"\xa0" )
+
                 found.String = found.String.replace( " ", u"\xa0" )
 
                 found = doc.findNext( found.End, search)
 
                 found = doc.findNext( found.End, search)
 
   
 
   
 
         except:
 
         except:
 
             pass
 
             pass
</code>
+
</syntaxhighlight>
 
+
 
+
  
 
==Wavelet class registration==
 
==Wavelet class registration==
You have to tell the OpenOffice.org what is the main class of your component. Put the following code at the end of your ''Wavelet.py'' file.  
+
You have to tell the {{AOo}} what is the main class of your component. Put the following code at the end of your ''Wavelet.py'' file.  
  
<code>[python]
+
<syntaxhighlight lang="python">
 
g_ImplementationHelper = unohelper.ImplementationHelper()
 
g_ImplementationHelper = unohelper.ImplementationHelper()
 
g_ImplementationHelper.addImplementation(
 
g_ImplementationHelper.addImplementation(
Line 54: Line 51:
 
         "name.vojta.openoffice.Wavelet",
 
         "name.vojta.openoffice.Wavelet",
 
         ("com.sun.star.task.Job",),)
 
         ("com.sun.star.task.Job",),)
</code>
+
</syntaxhighlight>
 
+
 
+
  
 
=Component integration=
 
=Component integration=
Line 73: Line 68:
 
The header of this file should contain:  
 
The header of this file should contain:  
  
<code>[xml]
+
<syntaxhighlight lang="xml">
 
<?xml version="1.0" encoding="UTF-8"?>
 
<?xml version="1.0" encoding="UTF-8"?>
 
<oor:component-data xmlns:oor="http://openoffice.org/2001/registry"
 
<oor:component-data xmlns:oor="http://openoffice.org/2001/registry"
Line 80: Line 75:
 
   
 
   
 
     <node oor:name="AddonUI">
 
     <node oor:name="AddonUI">
</code>
+
</syntaxhighlight>
 
+
 
+
  
 
===Office Menu Bar===
 
===Office Menu Bar===
Line 89: Line 82:
 
This menu item is associated with the ''name.vojta.openoffice.Wavelet?execute'' ''URL''. It means, that when you click on the menuitem, ''Wavelet.trigger'' method will be executed with the ''execute'' as an argument.  
 
This menu item is associated with the ''name.vojta.openoffice.Wavelet?execute'' ''URL''. It means, that when you click on the menuitem, ''Wavelet.trigger'' method will be executed with the ''execute'' as an argument.  
  
This menu will be visible in the OpenOffice.org Writer only.  
+
This menu will be visible in the {{AOo}} Writer only.  
  
<code>[xml]
+
<syntaxhighlight lang="xml">
 
         <node oor:name="OfficeMenuBar">
 
         <node oor:name="OfficeMenuBar">
 
             <node oor:name="name.vojta.openoffice.Wavelet" oor:op="replace">
 
             <node oor:name="name.vojta.openoffice.Wavelet" oor:op="replace">
Line 124: Line 117:
 
                 </node>
 
                 </node>
 
             </node>
 
             </node>
        </node>
+
</node>
</code>
+
</syntaxhighlight>
 
+
 
+
  
 
===Office Toolbar===
 
===Office Toolbar===
 
Following part creates new toolbar (with name ''Add-on 1'', ''Add-on 2'', …) and one button. This button is associated with the ''name.vojta.openoffice.Wavelet?execute'' ''URL''. It means that the ''Wavelet.trigger'' method will be executed when you click on the button on the toolbar. ''execute'' will be passed as an argument.  
 
Following part creates new toolbar (with name ''Add-on 1'', ''Add-on 2'', …) and one button. This button is associated with the ''name.vojta.openoffice.Wavelet?execute'' ''URL''. It means that the ''Wavelet.trigger'' method will be executed when you click on the button on the toolbar. ''execute'' will be passed as an argument.  
  
'''Note:''' You can't rename the toolbar. It's due to the backwards compatibility with the 1.1.x version.  
+
{{Note | You can't rename the toolbar. It's due to the backwards compatibility with the 1.1.x version.}}
  
<code>[xml]
+
<syntaxhighlight lang="xml">
 
         <node oor:name="OfficeToolBar">
 
         <node oor:name="OfficeToolBar">
 
             <node oor:name="name.vojta.openoffice.Wavelet" oor:op="replace">
 
             <node oor:name="name.vojta.openoffice.Wavelet" oor:op="replace">
Line 157: Line 148:
 
                 </node>
 
                 </node>
 
             </node>
 
             </node>
        </node>
+
</node>
</code>
+
</syntaxhighlight>
 
+
 
+
  
 
===Icons===
 
===Icons===
 
You can associate your icons with any ''URL''. We will associate our icons with ''name.vojta.openoffice.Wavelet?execute'' ''URL''. It means that all controls (menu item, button, …) associated with the same ''URL'' will use these icons.  
 
You can associate your icons with any ''URL''. We will associate our icons with ''name.vojta.openoffice.Wavelet?execute'' ''URL''. It means that all controls (menu item, button, …) associated with the same ''URL'' will use these icons.  
  
'''Note:''' %origin% is the UNO component package. We will explain it later.  
+
{{Note | %origin% is the UNO component package. We will explain it later.}}
  
<code>[xml]
+
<syntaxhighlight lang="xml">
 
         <node oor:name="Images">
 
         <node oor:name="Images">
 
             <node oor:name="name.vojta.openoffice.Wavelet.image1" oor:op="replace">
 
             <node oor:name="name.vojta.openoffice.Wavelet.image1" oor:op="replace">
Line 182: Line 171:
 
                 </node>
 
                 </node>
 
             </node>
 
             </node>
        </node>
+
</node>
</code>
+
</syntaxhighlight>
 
+
 
+
  
 
===Footer===
 
===Footer===
 
Close all opened sections.  
 
Close all opened sections.  
  
<code>[xml]
+
<syntaxhighlight lang="xml">
 
     </node>
 
     </node>
   
+
  </oor:component-data>
</oor:component-data>
+
</syntaxhighlight>
</code>
+
  
 
=UNO component package=
 
=UNO component package=
Line 202: Line 188:
 
You can pack our sample package with the following command:  
 
You can pack our sample package with the following command:  
  
<code>[shell]
+
<syntaxhighlight lang="bash">
 
zip -r Wavelet.uno.zip Addons.xcu Wavelet.py images
 
zip -r Wavelet.uno.zip Addons.xcu Wavelet.py images
</code>
+
</syntaxhighlight>
 
The final ''Wavelet.uno.zip'' package should contain these files:  
 
The final ''Wavelet.uno.zip'' package should contain these files:  
  
<code>[shell]
+
<syntaxhighlight lang="bash">
 
Wavelet.uno.zip
 
Wavelet.uno.zip
 
   Addons.xcu
 
   Addons.xcu
Line 213: Line 199:
 
   images/WaveletBig.bmp
 
   images/WaveletBig.bmp
 
   images/WaveletSmall.bmp
 
   images/WaveletSmall.bmp
</code>
+
</syntaxhighlight>
'''Note:''' The ''%origin%'' is ''Wavelet.uno.zip'', thus the ''%origin%/images/WaveletBig.bmp'' points to the ''WaveletBig.bmp'' file in your ''Wavelet.uno.zip'' file.  
+
 
 +
{{Note | The ''%origin%'' is ''Wavelet.uno.zip'', thus the ''%origin%/images/WaveletBig.bmp'' points to the ''WaveletBig.bmp'' file in your ''Wavelet.uno.zip'' file.}}
  
 
==Installation==
 
==Installation==
You can install your UNO component with the package manager (somewhere in the ''Tools'' menu) or with the ''unopkg'' tool.  
+
You can install your UNO component with the Extension manager (somewhere in the ''Tools'' menu) or with the ''unopkg'' tool.  
  
<code>[shell]
+
<syntaxhighlight lang="bash">
 
/opt/openoffice.org1.9.103/program/unopkg add Wavelet.uno.zip
 
/opt/openoffice.org1.9.103/program/unopkg add Wavelet.uno.zip
</code>
+
</syntaxhighlight>
  
 
==Uninstallation==
 
==Uninstallation==
You can uninstall your UNO component with the package manager (somewhere in the ''Tools'' menu) or with the ''unopkg'' tool.  
+
You can uninstall your UNO component with the Extension manager (somewhere in the ''Tools'' menu) or with the ''unopkg'' tool.  
  
<code>[shell]
+
<source lang=bash>
 
/opt/openoffice.org1.9.103/program/unopkg remove Wavelet.uno.zip
 
/opt/openoffice.org1.9.103/program/unopkg remove Wavelet.uno.zip
</code>
+
</source>
  
 
=Python component testing=
 
=Python component testing=
It's not necessary to install the Python UNO component to test it. You can connect to the running OpenOffice.org instance and test your UNO component directly.  
+
It's not necessary to install the Python UNO component to test it. You can connect to the running {{AOo}} instance and test your UNO component directly.  
  
 
==Code==
 
==Code==
 
Append the following code at the end of the ''Wavelet.py'' file.  
 
Append the following code at the end of the ''Wavelet.py'' file.  
  
<code>[python]
+
<syntaxhighlight lang="python">
 
if __name__ == "__main__":
 
if __name__ == "__main__":
 
     import os
 
     import os
 
   
 
   
     # Start OpenOffice.org, listen for connections and open testing document
+
     # Start OpenOffice, listen for connections and open testing document
 
     os.system( "/etc/openoffice.org-1.9/program/soffice '-accept=socket,host=localhost,port=2002;urp;' -writer ./WaveletTest.odt &" )
 
     os.system( "/etc/openoffice.org-1.9/program/soffice '-accept=socket,host=localhost,port=2002;urp;' -writer ./WaveletTest.odt &" )
 
   
 
   
Line 250: Line 237:
 
     ctx = None
 
     ctx = None
 
   
 
   
     # Wait until the OO.o starts and connection is established
+
     # Wait until the OpenOffice starts and connection is established
 
     while ctx == None:
 
     while ctx == None:
 
         try:
 
         try:
Line 261: Line 248:
 
     wavelet = Wavelet( ctx )
 
     wavelet = Wavelet( ctx )
 
     wavelet.trigger( () )
 
     wavelet.trigger( () )
</code>
+
</syntaxhighlight>
  
  
Line 268: Line 255:
 
To test your UNO component, just run your ''Wavelet.py'' in the Python interpreter.  
 
To test your UNO component, just run your ''Wavelet.py'' in the Python interpreter.  
  
<code>[shell]
+
<syntaxhighlight lang="bash">
 
/opt/openoffice.org1.9.103/program/python ./Wavelet.py
 
/opt/openoffice.org1.9.103/program/python ./Wavelet.py
</code>
+
</syntaxhighlight>
  
 
==Resume==
 
==Resume==
 
This part does this:  
 
This part does this:  
  
starts OpenOffice.org and opens the ''WaveletTest.odt'' file  
+
starts {{AOo}} and opens the ''WaveletTest.odt'' file  
  
 
loop until the connection will be established  
 
loop until the connection will be established  
  
start your component in the running OpenOffice.org context  
+
start your component in the running {{AOo}} context  
 
+
'''Note:''' Do not forget to remove this part before real UNO component packaging. Or comment it out.
+
  
 +
{{Note | Do not forget to remove this part before real UNO component packaging. Or comment it out.}}
  
 
=See also=
 
=See also=
* Using C++ with OOo SDK : [[Constructing_Components| Constructing Component in C++]]
+
* [[Documentation/DevGuide/Extensions/Extensions|Extensions]] chapter of the Developers Guide
 +
* Using C++ with {{AOo}} SDK : [[Constructing_Components| Constructing Component in C++]]
 
*[[Tutorial_UNO_Library|UNO tutorial]]
 
*[[Tutorial_UNO_Library|UNO tutorial]]
 
*[[Tutorial_UNO_IDL|UNO IDL]]
 
*[[Tutorial_UNO_IDL|UNO IDL]]
 
* [[Uno/Article/Types%26Reflection]]
 
* [[Uno/Article/Types%26Reflection]]
* Daniel Bölzle's [http://udk.openoffice.org/cpp/man/component_tutorial.html tutorial] : Writing a simple UNO component.
+
* Daniel Bölzle's [https://www.openoffice.org/udk/cpp/man/component_tutorial.html tutorial] : Writing a simple UNO component.
 
* [[UNO_component_packaging|Component with Python]]
 
* [[UNO_component_packaging|Component with Python]]
 +
 +
 +
[[Category:Uno]]
 +
[[Category:Extensions]]

Latest revision as of 15:07, 3 February 2021

Python UNO component

This page shows you how to pack and deploy already written UNO component. I'm using my Wavelet class as an example of a very simple component.

More detailed info is in the Developers Guide.

Python loader

The Python loader is not able load classes that are not it its own path. Thus it's necessary to copy any classes or modules you will use into the OPenOffice Python lib directory, and it may be necessary to restart OOo before they are picked up.

Sample Python component

Wavelet class

We will use my sample Wavelet class which replaces space with non-breaking space before the Czech prepositions. Put the following code in the Wavelet.py file.

import uno
import unohelper
from com.sun.star.task import XJobExecutor
 
class Wavelet( unohelper.Base, XJobExecutor ):
    def __init__( self, ctx ):
        self.ctx = ctx
 
    def trigger( self, args ):
        desktop = self.ctx.ServiceManager.createInstanceWithContext(
            "com.sun.star.frame.Desktop", self.ctx )
 
        doc = desktop.getCurrentComponent()
 
        try:
            search = doc.createSearchDescriptor()
            search.SearchRegularExpression = True
            search.SearchString = "\\<(k|s|v|z|o|u|i|a) "
 
            found = doc.findFirst( search )
            while found:
                found.String = found.String.replace( " ", u"\xa0" )
                found = doc.findNext( found.End, search)
 
        except:
            pass

Wavelet class registration

You have to tell the Apache OpenOffice what is the main class of your component. Put the following code at the end of your Wavelet.py file.

g_ImplementationHelper = unohelper.ImplementationHelper()
g_ImplementationHelper.addImplementation(
        Wavelet,
        "name.vojta.openoffice.Wavelet",
        ("com.sun.star.task.Job",),)

Component integration

Icons

You can create your own icons for the Menu item or the Toolbar button. The easiest way is to create two true color BMP files - the first one should be 26×26 and the second one should be 16×16.

If you want to use alpha (transparent color), use #FF00FF (RGB) color.

This possibility is optional and you're not forced to create icons.

Addons.xcu

Component integration configuration is in the Addons.xcu file.

Header

The header of this file should contain:

<?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">

Office Menu Bar

Following part creates new menu item Czech (or Cestina, depends on the UI language) and the Wavelet menu item.

This menu item is associated with the name.vojta.openoffice.Wavelet?execute URL. It means, that when you click on the menuitem, Wavelet.trigger method will be executed with the execute as an argument.

This menu will be visible in the Apache OpenOffice Writer only.

        <node oor:name="OfficeMenuBar">
            <node oor:name="name.vojta.openoffice.Wavelet" oor:op="replace">
                <prop oor:name="Title" oor:type="xs:string">
                    <value/>
                    <value xml:lang="en-US">Czech</value>
                    <value xml:lang="cs">Cestina</value>
                </prop>
                <prop oor:name="Target" oor:type="xs:string">
                    <value>_self</value>
                </prop>
                <prop oor:name="ImageIdentifier" oor:type="xs:string">
                    <value/>
                </prop>
                <node oor:name="Submenu">
                    <node oor:name="m1" oor:op="replace">
                        <prop oor:name="URL" oor:type="xs:string">
                            <value>service:name.vojta.openoffice.Wavelet?execute</value>
                        </prop>
                        <prop oor:name="Title" oor:type="xs:string">
                            <value/>
                            <value xml:lang="en-US">Wavelet</value>
                            <value xml:lang="cs">Vlnka</value>
                        </prop>
                        <prop oor:name="Target" oor:type="xs:string">
                            <value>_self</value>
                        </prop>
                        <prop oor:name="Context" oor:type="xs:string">
                            <value>com.sun.star.text.TextDocument</value>
                        </prop>
                    </node>
                </node>
            </node>
</node>

Office Toolbar

Following part creates new toolbar (with name Add-on 1, Add-on 2, …) and one button. This button is associated with the name.vojta.openoffice.Wavelet?execute URL. It means that the Wavelet.trigger method will be executed when you click on the button on the toolbar. execute will be passed as an argument.

Documentation note.png You can't rename the toolbar. It's due to the backwards compatibility with the 1.1.x version.
        <node oor:name="OfficeToolBar">
            <node oor:name="name.vojta.openoffice.Wavelet" oor:op="replace">
                <node oor:name="m1" oor:op="replace">
                    <prop oor:name="URL" oor:type="xs:string">
                        <value>service:name.vojta.openoffice.Wavelet?execute</value>
                    </prop>
                    <prop oor:name="ImageIdentifier" oor:type="xs:string">
                        <value/>
                    </prop>
                    <prop oor:name="Title" oor:type="xs:string">
                        <value/>
                        <value xml:lang="en-US">Wavelet</value>
                        <value xml:lang="cs">Vlnka</value>
                    </prop>
                    <prop oor:name="Target" oor:type="xs:string">
                        <value>_self</value>
                    </prop>
                    <prop oor:name="Context" oor:type="xs:string">
                        <value>com.sun.star.text.TextDocument</value>
                    </prop>
                </node>
            </node>
</node>

Icons

You can associate your icons with any URL. We will associate our icons with name.vojta.openoffice.Wavelet?execute URL. It means that all controls (menu item, button, …) associated with the same URL will use these icons.

Documentation note.png  %origin% is the UNO component package. We will explain it later.
        <node oor:name="Images">
            <node oor:name="name.vojta.openoffice.Wavelet.image1" oor:op="replace">
                <prop oor:name="URL">
                    <value>service:name.vojta.openoffice.Wavelet?execute</value>
                </prop>
                <node oor:name="UserDefinedImages">
                    <prop oor:name="ImageSmallURL" oor:type="xs:string">
                        <value>%origin%/images/WaveletSmall.bmp</value>
                    </prop>
                    <prop oor:name="ImageBigURL" oor:type="xs:string">
                        <value>%origin%/images/WaveletBig.bmp</value>
                    </prop>
                </node>
            </node>
</node>

Footer

Close all opened sections.

    </node>
 </oor:component-data>

UNO component package

UNO component package is a simple ZIP file. Obviously it contains the Addons.xcu file, images directory with icons and the Python component implementation.

Packing

You can pack our sample package with the following command:

zip -r Wavelet.uno.zip Addons.xcu Wavelet.py images

The final Wavelet.uno.zip package should contain these files:

Wavelet.uno.zip
  Addons.xcu
  Wavelet.py
  images/WaveletBig.bmp
  images/WaveletSmall.bmp
Documentation note.png The %origin% is Wavelet.uno.zip, thus the %origin%/images/WaveletBig.bmp points to the WaveletBig.bmp file in your Wavelet.uno.zip file.

Installation

You can install your UNO component with the Extension manager (somewhere in the Tools menu) or with the unopkg tool.

/opt/openoffice.org1.9.103/program/unopkg add Wavelet.uno.zip

Uninstallation

You can uninstall your UNO component with the Extension manager (somewhere in the Tools menu) or with the unopkg tool.

/opt/openoffice.org1.9.103/program/unopkg remove Wavelet.uno.zip

Python component testing

It's not necessary to install the Python UNO component to test it. You can connect to the running Apache OpenOffice instance and test your UNO component directly.

Code

Append the following code at the end of the Wavelet.py file.

if __name__ == "__main__":
    import os
 
    # Start OpenOffice, listen for connections and open testing document
    os.system( "/etc/openoffice.org-1.9/program/soffice '-accept=socket,host=localhost,port=2002;urp;' -writer ./WaveletTest.odt &" )
 
    # Get local context info
    localContext = uno.getComponentContext()
    resolver = localContext.ServiceManager.createInstanceWithContext(
        "com.sun.star.bridge.UnoUrlResolver", localContext )
 
    ctx = None
 
    # Wait until the OpenOffice starts and connection is established
    while ctx == None:
        try:
            ctx = resolver.resolve(
                "uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext" )
        except:
            pass
 
    # Trigger our job
    wavelet = Wavelet( ctx )
    wavelet.trigger( () )


Testing

To test your UNO component, just run your Wavelet.py in the Python interpreter.

/opt/openoffice.org1.9.103/program/python ./Wavelet.py

Resume

This part does this:

starts Apache OpenOffice and opens the WaveletTest.odt file

loop until the connection will be established

start your component in the running Apache OpenOffice context

Documentation note.png Do not forget to remove this part before real UNO component packaging. Or comment it out.

See also

Personal tools