Difference between revisions of "Python container components"
B michaelsen (Talk | contribs) |
|||
Line 456: | Line 456: | ||
and then just make my class do.... | and then just make my class do.... | ||
class IndexContainer( unohelper.Base, XIndexAccess ) | class IndexContainer( unohelper.Base, XIndexAccess ) | ||
+ | [[Category:Python]] |
Revision as of 08:59, 26 March 2010
Python container components
I have been dabbling with creating components in Python. This message is intended as an update on what I have learned and am experimenting with.
As a first experiment, here is a single python component program which implements two services.
The two new services are....
name.dannyBrewer.util.IndexContainer name.dannyBrewer.util.NameContainer
Here is how you install the new component.
- Copy the text of the following python source code.
- Put it into a file named "DannyComponentTest2004052217.py"
- Put the file DannyComponentTest2004052217.py into the uno_components folder of your "user" folder.
The user folder on Windows is probably the folder named "user" under your OOo installation. The user folder on Linux is contained within a folder in your home directory with a name like OpenOffice.org1.1.1. (Note on Linux, be sure that when you copy the python program that it has no carriage returns, but instead has unix linefeeds. Otherwise the component will not install properly!)
(New edit 2005-03-28: It may in fact be important now on ALL platforms to make sure that the ".py" file of python source has its line endings separated by linefeeds only with NO carriage returns!)
- Be sure that OOo is NOT running.
- Run the command "pkgchk" in your OOo\programs folder.
To uninstall do this....
- Remove the DannyComponentTest2004052217.py file from your uno_components folder.
- Be sure that OOo is NOT running.
- Run the pkgchk command.
After installing the component, you have two new data structure services that can be instantiated from any language which can access UNO components. For instance, in OOo Basic, you can simply do...
oItems = createUnoService( "name.dannyBrewer.util.IndexContainer" )
import unohelper g_ImplementationHelper = unohelper.ImplementationHelper() ################################################################## class DannysUnoBaseClass: cServiceName = "" tServiceNames = ( cServiceName, ) # stuff to support the XTypeProvider interface. tInterfaceTypes = ( uno.getTypeByName( "com.sun.star.lang.XServiceName" ), uno.getTypeByName( "com.sun.star.lang.XServiceInfo" ), uno.getTypeByName( "com.sun.star.lang.XTypeProvider" ), ) uuid = uno.generateUuid() # The component must have a ctor with the component context as argument. def __init__( self, oContext ): self.DannysUnoBaseClass_init( oContext ) def DannysUnoBaseClass_init( self, oContext ): self.oContext = oContext self.oCoreReflection = None self.StarDesktop = None self.getDesktop() #---------------------------------------- # Danny's stuff to make programming less convenient. #---------------------------------------- def getServiceManager( self ): """Get the ServiceManager from the running OpenOffice.org. """ return self.oContext.ServiceManager def createUnoService( self, cClass ): """A handy way to create a global objects within the running OOo. """ oServiceManager = self.getServiceManager() oObj = oServiceManager.createInstance( cClass ) return oObj def getDesktop( self ): """An easy way to obtain the Desktop object from a running OOo. """ if self.StarDesktop == None: self.StarDesktop = self.createUnoService( "com.sun.star.frame.Desktop" ) return self.StarDesktop def getCoreReflection( self ): if self.oCoreReflection == None: self.oCoreReflection = self.createUnoService( "com.sun.star.reflection.CoreReflection" ) return oCoreReflection def createUnoStruct( self, cTypeName ): """Create a UNO struct and return it. """ oCoreReflection = self.getCoreReflection() # Get the IDL class for the type name oXIdlClass = oCoreReflection.forName( cTypeName ) # Create the struct. oReturnValue, oStruct = oXIdlClass.createObject( None ) return oStruct def makePropertyValue( self, cName=None, uValue=None, nHandle=None, nState=None ): """Create a com.sun.star.beans.PropertyValue struct and return it. """ oPropertyValue = self.createUnoStruct( "com.sun.star.beans.PropertyValue" ) if cName != None: oPropertyValue.Name = cName if uValue != None: oPropertyValue.Value = uValue if nHandle != None: oPropertyValue.Handle = nHandle if nState != None: oPropertyValue.State = nState return oPropertyValue #---------------------------------------- # Interface: XServiceName #---------------------------------------- # string # getServiceName(); def getServiceName( self ): return self.cServiceName #---------------------------------------- # Interface: XServiceInfo #---------------------------------------- # string # getImplementationName(); def getImplementationName( self ): return self.cServiceName # boolean # supportsService( [in] string ServiceName ); def supportsService( self, cServiceName ): return cServiceName in self.getSupportedServiceNames() # sequence< string > # getSupportedServiceNames(); def getSupportedServiceNames( self ): return self.tServiceNames #---------------------------------------- # Interface: XTypeProvider #---------------------------------------- # sequence< type > # getTypes(); def getTypes( self ): #if self.tInterfaceTypes == None: # self.tInterfaceTypes = () # for cTypeName in self.tInterfaces: # self.tInterfaceTypes += ( uno.getTypeByName( cTypeName ), ) return self.tInterfaceTypes # sequence< byte > # getImplementationId(); def getImplementationId( self ): return self.uuid ################################################################## from com.sun.star.lang import IndexOutOfBoundsException class IndexContainer( DannysUnoBaseClass ): cServiceName = "name.dannyBrewer.util.IndexContainer" tServiceNames = ( cServiceName, ) tInterfaceTypes = DannysUnoBaseClass.tInterfaceTypes + ( uno.getTypeByName( "com.sun.star.container.XIndexContainer" ), uno.getTypeByName( "com.sun.star.container.XIndexReplace" ), uno.getTypeByName( "com.sun.star.container.XIndexAccess" ), uno.getTypeByName( "com.sun.star.container.XElementAccess" ), ) # The component must have a ctor with the component context as argument. def __init__( self, oContext ): # Initialize the base class! self.DannysUnoBaseClass_init( oContext ) # This is the list of items in the IndexContainer. self.items = [] #---------------------------------------- # Interface: com.sun.star.container.XIndexContainer #---------------------------------------- # void # insertByIndex( [in] long nIndex, # [in] any uElement ); def insertByIndex( self, nIndex, uElement ): if nIndex < 0: raise IndexOutOfBoundsException( """You specified an index that was less than zero. """, self ) nItems = len( self.items ) if nIndex > nItems: raise IndexOutOfBoundsException( """You specified an index that was greater than the last item in the container. Since there are """ + str( nItems ) + """ items in the container, you must specify an insert index that is from zero to """ + str( nItems ) + """. """, self ) if nIndex == nItems: self.items += [uElement] return self.items = self.items[0:nIndex] + [uElement] + self.items[nIndex:] # void # removeByIndex( [in] long nIndex ); def removeByIndex( self, nIndex ): if nIndex < 0: raise IndexOutOfBoundsException( """You specified an index that was less than zero. """, self ) nItems = len( self.items ) if nIndex > nItems: raise IndexOutOfBoundsException( """You specified an index that was greater than or equal to the last item in the container. Since there are """ + str( nItems ) + """ items in the container, you must specify an insert index that is from zero to """ + str( nItems-1 ) + """. """, self ) self.items = self.items[0:nIndex] + self.items[nIndex+1:] #---------------------------------------- # Interface: com.sun.star.container.XIndexReplace #---------------------------------------- # void # replaceByIndex( [in] long nIndes, # [in] any uElement ); def replaceByIndex( self, nIndex, uElement ): if nIndex < 0: raise IndexOutOfBoundsException( """You specified an index that was less than zero. """, self ) nItems = len( self.items ) if nIndex > nItems: raise IndexOutOfBoundsException( """You specified an index that was greater than or equal to the last item in the container. Since there are """ + str( nItems ) + """ items in the container, you must specify an insert index that is from zero to """ + str( nItems-1 ) + """. """, self ) self.items = self.items[0:nIndex] + [uElement] + self.items[nIndex+1:] #---------------------------------------- # Interface: com.sun.star.container.XIndexAccess #---------------------------------------- # long # getCount(); def getCount( self ): return len( self.items ) # any # getByIndex( [in] long nIndex ); def getByIndex( self, nIndex ): if nIndex < 0: raise IndexOutOfBoundsException( """You specified an index that was less than zero. """, self ) nItems = len( self.items ) if nIndex > nItems: raise IndexOutOfBoundsException( """You specified an index that was greater than or equal to the last item in the container. Since there are """ + str( nItems ) + """ items in the container, you must specify an insert index that is from zero to """ + str( nItems-1 ) + """. """, self ) return self.items[ nIndex ] #---------------------------------------- # Interface: com.sun.star.container.XElementAccess #---------------------------------------- # type # getElementType(); def getElementType( self ): return None # boolean # hasElements(); def hasElements( self ): return len( self.items ) > 0 # Add the class to the implementation container, # which the loader uses to register/instantiate the component. g_ImplementationHelper.addImplementation( # The class IndexContainer, # The implementation name. # Change this name for your own service. IndexContainer.cServiceName, # A list of services that that are implemented. IndexContainer.tServiceNames, ) ################################################################## from com.sun.star.lang import IndexOutOfBoundsException from com.sun.star.container import ElementExistException from com.sun.star.container import NoSuchElementException class NameContainer( DannysUnoBaseClass ): cServiceName = "name.dannyBrewer.util.NameContainer" tServiceNames = ( cServiceName, ) tInterfaceTypes = DannysUnoBaseClass.tInterfaceTypes + ( uno.getTypeByName( "com.sun.star.container.XNameContainer" ), uno.getTypeByName( "com.sun.star.container.XNameReplace" ), uno.getTypeByName( "com.sun.star.container.XNameAccess" ), uno.getTypeByName( "com.sun.star.container.XIndexAccess" ), uno.getTypeByName( "com.sun.star.container.XElementAccess" ), ) # The component must have a ctor with the component context as argument. def __init__( self, oContext ): # Initialize the base class! self.DannysUnoBaseClass_init( oContext ) # This is the dictionary of items in the NameContainer. self.items = {} #---------------------------------------- # Interface: com.sun.star.container.XNameContainer #---------------------------------------- # void # insertByName( [in] string cName, # [in] any uElement ); def insertByName( self, cName, uElement ): if self.items.has_key( cName ): raise ElementExistException( """You specified an element name of \"""" + cName + """\" which is already present in the container. """, self ) self.items[ cName ] = uElement # void # removeByName( [in] string cName ); def removeByName( self, cName ): if not self.items.has_key( cName ): raise NoSuchElementException( """You specified an element name of \"""" + cName + """\" which does not exist in the container. """, self ) del self.items[ cName ] #---------------------------------------- # Interface: com.sun.star.container.XNameReplace #---------------------------------------- # void # replaceByName( [in] string cName, # [in] any uElement ); def replaceByName( self, cName, uElement ): if not self.items.has_key( cName ): raise NoSuchElementException( """You specified an element name of \"""" + cName + """\" which does not exist in the container. """, self ) self.items[ cName ] = uElement #---------------------------------------- # Interface: com.sun.star.container.XNameAccess #---------------------------------------- # any # getByName( [in] string cName ); def getByName( self, cName ): if not self.items.has_key( cName ): raise NoSuchElementException( """You specified an element name of \"""" + cName + """\" which does not exist in the container. """, self ) return self.items[ cName ] # boolean # hasByName( [in] string cName ); def hasByName( self, cName ): return self.items.has_key( cName ) # sequence< string > # getElementNames(); def getElementNames( self ): ret = () for item in self.items.keys(): ret += ( item, ) return ret #---------------------------------------- # Interface: com.sun.star.container.XIndexAccess #---------------------------------------- # long # getCount(); def getCount( self ): return len( self.items ) # any # getByIndex( [in] long nIndex ); def getByIndex( self, nIndex ): if nIndex < 0: raise IndexOutOfBoundsException( """You specified an index that was less than zero. """, self ) nItems = len( self.items ) if nIndex > nItems: raise IndexOutOfBoundsException( """You specified an index that was greater than or equal to the last item in the container. Since there are """ + str( nItems ) + """ items in the container, you must specify an insert index that is from zero to """ + str( nItems-1 ) + """. """, self ) return self.items.values()[ nIndex ] #---------------------------------------- # Interface: com.sun.star.container.XElementAccess #---------------------------------------- # type # getElementType(); def getElementType( self ): return None # boolean # hasElements(); def hasElements( self ): return len( self.items ) > 0 # Add the class to the implementation container, # which the loader uses to register/instantiate the component. g_ImplementationHelper.addImplementation( # The class NameContainer, # The implementation name. # Change this name for your own service. NameContainer.cServiceName, # A list of services that that are implemented. NameContainer.tServiceNames, )
There are still some issues I am working out. I just want other interested people to be able to take my experimentation further or in different directions.
The above demonstrates several useful features.
- Component code written in pure python.
- Two services in one component.
- Two components which inherit from a base class which implements some of the underlying "plumbing" machinery.
- A way to inherit from multiple interfaces.
So why don't I just
from com.sun.star.container import XIndexAccess
and then just make my class do....
class IndexContainer( unohelper.Base, XIndexAccess )