[Zope] icons not in __init__.py

Brian Lloyd brian.lloyd@zope.com
Thu, 4 Oct 2001 15:23:09 -0400


> When stating which icon to use for a python product you do that 
> like this in __init__.py
> icon="event.gif" 
> 
> But what about subclasses which are object on their own? They 
> don't use the initialize() method.
> 
> I have tried:
> 
> class SubClassObject(ObjectManager, etc):
>         meta_type='Event'
>         icon='event.gif'
> 
> where event.gif is a valid gif next to the .py file I write this in.
> That didn't work!
> 
> So, I have also tried:
> 
>   icon="misc_/MyProduct/event.gif"  and  icon="misc_/MyProduct/event"
> and
>   icon="/misc_/MyProduct/event.gif"  and  icon="/misc_/MyProduct/event"
> 
> Nothing has worked?
> Zope 2.4.0
> What's the trick?

[ Brian's product development tip-o-the-day :) ]

Sorry for the long inclusion above, but I thought it will be 
useful one day to have the context when someone searches the 
mailing list for the answer to this...

The "normal" way that icons get associated with classes is 
somewhat opaque:

(in an __init__.py):

    context.registerClass(
        instance_class = MyModule.MyClass,
        meta_type      = 'My Object',
        permission     = 'Add My Objects',
        constructors   = MyModule.constructors,
        icon           = 'www/MyClass.gif'
      )

The 'registerClass' helper automatically sets up your icon. It 
can do that because it gets and / or knows:

  o the class object

  o the relative path to the file you want to use for
    the icon ('www/MyClass.gif')

  o the package that is being registered

So what it does is:

  o creates an ImageFile object (the ImageFile class is located 
    in the App.ImageFile module)

  o adds the ImageFile instance to a special place where 
    miscellanous static web-accessible resources for use 
    by products are kept

  o adds an 'icon' attribute to the class being registered 
    whose value is the url to the ImageFile instance

This is the 'misc_' funny business you see in icon urls. The
'misc_' object is a child of the root Zope object. When 
a product is initialized, a generic container is created in 
misc_, named after the product being initialized. registerClass
does a setattr on the generic container for the product, making 
the ImageFile instance available through traversal as 
/misc_/ProductName/filename.

(Note that these things are set as class attributes rather than 
instance attributes, so they are not persistent and go away at 
shutdown, and are rebuilt at the next startup).

So... to set up an icon for an object that is not registered 
using registerClass, we just need to change the __init__.py 
to create ImageFiles for the extra icons we need, add those 
ImageFile instances to the container for our product in 
misc_, and add appropriate 'icon' attributes to our classes 
whose values are url paths to the appropriate ImageFiles.



(in __init__.py)

def initialize(context):
    # standard registration for MyClass, which is a normal
    # through-the-web creatable object. Note that after
    # registering MyClass, we call our registerIcon helper 
    # function to register icons for MyOtherClass1 and MyOtherClass2,
    # which are not directly registered using registerClass.

    context.registerClass(
        instance_class = MyModule.MyClass,
        meta_type      = 'My Object',
        permission     = 'Add My Objects',
        constructors   = MyModule.constructors,
        icon           = 'www/MyClass.gif'
      )

    registerIcon('MyOtherClass1.gif')
    registerIcon('MyOtherClass2.gif')


import OFS, App

def registerIcon(filename):
    # A helper function that takes an image filename (assumed
    # to live in a 'www' subdirectory of this package). It 
    # creates an ImageFile instance and adds it as an attribute
    # of misc_.MyPackage of the zope application object (note
    # that misc_.MyPackage has already been created by the product
    # initialization machinery by the time registerIcon is called).

    setattr(OFS.misc_.misc_.MyPackage, 
            filename, 
            App.ImageFile.ImageFile('www/%s' % filename, globals())
            )


Now we just need to add 'icon' attributes to our 'Other' classes:


(in MyModule.py)

class MyOtherClass1:

  icon = 'misc_/MyProduct/MyOtherClass1.gif'
  ...

class MyOtherClass2:

  icon = 'misc_/MyProduct/MyOtherClass2.gif'
  ...


Hope this helps!


Brian Lloyd        brian@zope.com
Software Engineer  540.361.1716       
Zope Corporation   http://www.zope.com