[Checkins] SVN: Products.CMFCore/trunk/Products/CMFCore/ - ActionInformation: extend the ActionInformation and ActionInfo classes

Jens Vagelpohl jens at dataflake.org
Wed Sep 17 17:22:41 EDT 2008


Log message for revision 91221:
  - ActionInformation: extend the ActionInformation and ActionInfo classes
    to support a icon URL just like the newer Action class already does
  

Changed:
  U   Products.CMFCore/trunk/Products/CMFCore/ActionInformation.py
  U   Products.CMFCore/trunk/Products/CMFCore/ActionProviderBase.py
  U   Products.CMFCore/trunk/Products/CMFCore/CHANGES.txt
  U   Products.CMFCore/trunk/Products/CMFCore/TypesTool.py
  U   Products.CMFCore/trunk/Products/CMFCore/dtml/editToolsActions.dtml
  U   Products.CMFCore/trunk/Products/CMFCore/exportimport/tests/test_typeinfo.py
  U   Products.CMFCore/trunk/Products/CMFCore/exportimport/typeinfo.py
  U   Products.CMFCore/trunk/Products/CMFCore/tests/test_ActionInformation.py
  U   Products.CMFCore/trunk/Products/CMFCore/tests/test_ActionProviderBase.py
  U   Products.CMFCore/trunk/Products/CMFCore/tests/test_ActionsTool.py

-=-
Modified: Products.CMFCore/trunk/Products/CMFCore/ActionInformation.py
===================================================================
--- Products.CMFCore/trunk/Products/CMFCore/ActionInformation.py	2008-09-17 21:15:09 UTC (rev 91220)
+++ Products.CMFCore/trunk/Products/CMFCore/ActionInformation.py	2008-09-17 21:22:41 UTC (rev 91221)
@@ -173,6 +173,7 @@
                 self.data.setdefault( 'title', self.data['name'] )
                 del self.data['name']
             self.data.setdefault( 'url', '' )
+            self.data.setdefault( 'icon', '' )
             self.data.setdefault( 'category', 'object' )
             self.data.setdefault( 'visible', True )
             self.data['available'] = True
@@ -200,7 +201,7 @@
 
     def __eq__(self, other):
         # this is expensive, use it with care
-        [ self.__getitem__(key) for key in self._lazy_keys ]
+        [ self.__getitem__(key) for key in self._lazy_keys[:] ]
 
         if isinstance(other, self.__class__):
             [ other[key] for key in other._lazy_keys ]
@@ -261,6 +262,7 @@
                 , priority=10
                 , visible=True
                 , action=''
+                , icon_expr=''
                 ):
         """ Set up an instance.
         """
@@ -273,6 +275,7 @@
                  , priority
                  , visible
                  , action
+                 , icon_expr
                  )
 
     security.declarePrivate('edit')
@@ -286,6 +289,7 @@
             , priority=_unchanged
             , visible=_unchanged
             , action=_unchanged
+            , icon_expr=_unchanged
             ):
         """Edit the specified properties.
         """
@@ -314,6 +318,10 @@
             if action and isinstance(action, basestring):
                 action = Expression(action)
             self.setActionExpression(action)
+        if icon_expr is not _unchanged:
+            if icon_expr and isinstance(icon_expr, basestring):
+                icon_expr = Expression(icon_expr)
+            self.setIconExpression(icon_expr)
 
     security.declareProtected( View, 'Title' )
     def Title(self):
@@ -385,6 +393,36 @@
             action = Expression( action )
         self.action = action
 
+    security.declarePrivate( '_getIconExpressionObject' )
+    def _getIconExpressionObject( self ):
+
+        """ Find the icon expression object, working around name changes.
+        """
+        return getattr( self, 'icon_expr', None )
+
+    security.declarePublic( 'getIconExpression' )
+    def getIconExpression( self ):
+
+        """ Return the text of the TALES expression for our icon URL.
+        """
+        icon_expr = self._getIconExpressionObject()
+        expr = icon_expr and icon_expr.text or ''
+        if expr and isinstance(expr, basestring):
+            if ( not expr.startswith('string:')
+                 and not expr.startswith('python:') ):
+                expr = 'string:${object_url}/%s' % expr
+                self.icon_expr = Expression( expr )
+        return expr
+
+    security.declarePrivate( 'setIconExpression' )
+    def setIconExpression(self, icon_expr):
+        if icon_expr and isinstance(icon_expr, basestring):
+            if ( not icon_expr.startswith('string:')
+                 and not icon_expr.startswith('python:') ):
+                icon_expr = 'string:${object_url}/%s' % icon_expr
+            icon_expr = Expression( icon_expr )
+        self.icon_expr = icon_expr
+
     security.declarePublic( 'getCondition' )
     def getCondition(self):
 
@@ -427,7 +465,8 @@
                               and self.condition.text or '',
                  'permissions': self.permissions,
                  'visible': bool(self.visible),
-                 'action': self.getActionExpression() }
+                 'action': self.getActionExpression(),
+                 'icon_expr' : self.getIconExpression() }
 
     security.declarePrivate('clone')
     def clone( self ):
@@ -449,6 +488,13 @@
             lazy_map['url'] = ''
         del lazy_map['action']
 
+        if lazy_map['icon_expr']:
+            lazy_map['icon'] = self._getIconExpressionObject()
+            lazy_keys.append('icon')
+        else:
+            lazy_map['icon'] = ''
+        del lazy_map['icon_expr']
+
         if lazy_map['condition']:
             lazy_map['available'] = self.testCondition
             lazy_keys.append('available')

Modified: Products.CMFCore/trunk/Products/CMFCore/ActionProviderBase.py
===================================================================
--- Products.CMFCore/trunk/Products/CMFCore/ActionProviderBase.py	2008-09-17 21:15:09 UTC (rev 91220)
+++ Products.CMFCore/trunk/Products/CMFCore/ActionProviderBase.py	2008-09-17 21:22:41 UTC (rev 91221)
@@ -168,6 +168,7 @@
                  , permission
                  , category
                  , visible=1
+                 , icon_expr=''
                  , REQUEST=None
                  ):
         """ Add an action to our list.
@@ -190,6 +191,7 @@
                                       , permissions=permission
                                       , visible=bool(visible)
                                       , action=action
+                                      , icon_expr=icon_expr
                                       )
 
         new_actions.append( new_action )
@@ -312,6 +314,7 @@
         id          = str( properties.get( 'id_%d'          % index, '' ) )
         title       = str( properties.get( 'name_%d'        % index, '' ) )
         action      = str( properties.get( 'action_%d'      % index, '' ) )
+        icon_expr   = str( properties.get( 'icon_expr_%d'   % index, '' ) )
         condition   = str( properties.get( 'condition_%d'   % index, '' ) )
         category    = str( properties.get( 'category_%d'    % index, '' ))
         visible     = bool( properties.get('visible_%d'     % index, False) )
@@ -333,6 +336,7 @@
                                 , permissions=permissions
                                 , category=category
                                 , visible=visible
+                                , icon_expr=icon_expr
                                 )
 
     def _getOAI(self, object):

Modified: Products.CMFCore/trunk/Products/CMFCore/CHANGES.txt
===================================================================
--- Products.CMFCore/trunk/Products/CMFCore/CHANGES.txt	2008-09-17 21:15:09 UTC (rev 91220)
+++ Products.CMFCore/trunk/Products/CMFCore/CHANGES.txt	2008-09-17 21:22:41 UTC (rev 91221)
@@ -4,6 +4,9 @@
 2.2.0 (unreleased)
 ------------------
 
+- ActionInformation: extend the ActionInformation and ActionInfo classes 
+  to support a icon URL just like the newer Action class already does
+
 - WorkflowTool: Passing the "magic" chain name "(Default)" to the
   setChainForPortalTypes method did not set the chain to the default 
   chain value as expected.

Modified: Products.CMFCore/trunk/Products/CMFCore/TypesTool.py
===================================================================
--- Products.CMFCore/trunk/Products/CMFCore/TypesTool.py	2008-09-17 21:15:09 UTC (rev 91220)
+++ Products.CMFCore/trunk/Products/CMFCore/TypesTool.py	2008-09-17 21:22:41 UTC (rev 91221)
@@ -156,6 +156,7 @@
                 , permission=action.get( 'permissions', () )
                 , category=action.get('category', 'object')
                 , visible=action.get('visible', True)
+                , icon_expr=action.get('icon_expr', '')
                 )
 
         self.setMethodAliases(kw.get('aliases', {}))

Modified: Products.CMFCore/trunk/Products/CMFCore/dtml/editToolsActions.dtml
===================================================================
--- Products.CMFCore/trunk/Products/CMFCore/dtml/editToolsActions.dtml	2008-09-17 21:15:09 UTC (rev 91220)
+++ Products.CMFCore/trunk/Products/CMFCore/dtml/editToolsActions.dtml	2008-09-17 21:22:41 UTC (rev 91221)
@@ -70,6 +70,20 @@
 <td></td>
 <td>
   <div class="form-label">
+  Icon (Expression)
+  </div>
+</td>
+<td>
+  <div class="form-element">
+  <input type="text" name="icon_expr_&dtml-index;" value="&dtml-icon_expr;" size="80" />
+  </div>
+</td>
+</tr>
+
+<tr>
+<td></td>
+<td>
+  <div class="form-label">
   Condition (Expression)
   </div>
 </td>
@@ -205,10 +219,25 @@
   </div>
 </td>
 </tr>
+
 <tr>
 <td></td>
 <td>
   <div class="form-label">
+  Icon (Expression)
+  </div>
+</td>
+<td>
+  <div class="form-element">
+  <input type="text" name="icon_expr" value="" size="80" />
+  </div>
+</td>
+</tr>
+
+<tr>
+<td></td>
+<td>
+  <div class="form-label">
   Condition (Expression)
   </div>
 </td>

Modified: Products.CMFCore/trunk/Products/CMFCore/exportimport/tests/test_typeinfo.py
===================================================================
--- Products.CMFCore/trunk/Products/CMFCore/exportimport/tests/test_typeinfo.py	2008-09-17 21:15:09 UTC (rev 91220)
+++ Products.CMFCore/trunk/Products/CMFCore/exportimport/tests/test_typeinfo.py	2008-09-17 21:22:41 UTC (rev 91221)
@@ -52,8 +52,8 @@
  <alias from="(Default)" to="foo"/>
  <alias from="view" to="foo"/>
  <action title="Foo" action_id="foo_action" category="Bar"
-    condition_expr="python:1" url_expr="string:${object_url}/foo"
-    visible="True"/>
+    condition_expr="python:1" icon_expr="string:${portal_url}/icon.png"
+    url_expr="string:${object_url}/foo" visible="True"/>
 </object>
 """
 
@@ -86,16 +86,19 @@
     'actions': ({'id':     'view',
                  'title':  'View',
                  'action': 'string:${object_url}/foo_view',
+                 'icon_expr': 'string:${portal_url}/preview_icon.png',
                  'permissions': (View,),
                  },
                 {'id':     'edit',
                  'title':  'Edit',
                  'action': 'string:${object_url}/foo_edit_form',
+                 'icon_expr': 'string:${portal_url}/edit_icon.png',
                  'permissions': (ModifyPortalContent,),
                  },
                 {'id':     'metadata',
                  'title':  'Metadata',
                  'action': 'string:${object_url}/metadata_edit_form',
+                 'icon_expr': 'string:${portal_url}/metadata_icon.png',
                  'permissions': (ModifyPortalContent,),
                  },
                 ),
@@ -197,16 +200,18 @@
  <alias from="(Default)" to="foo_view"/>
  <alias from="view" to="foo_view"/>
  <action title="View" action_id="view" category="object" condition_expr=""
-    url_expr="string:${object_url}/foo_view" visible="True">
+    url_expr="string:${object_url}/foo_view" 
+    icon_expr="string:${portal_url}/preview_icon.png" visible="True">
   <permission value="View"/>
  </action>
  <action title="Edit" action_id="edit" category="object" condition_expr=""
-    url_expr="string:${object_url}/foo_edit_form" visible="True">
+    url_expr="string:${object_url}/foo_edit_form" 
+    icon_expr="string:${portal_url}/edit_icon.png" visible="True">
   <permission value="Modify portal content"/>
  </action>
  <action title="Metadata" action_id="metadata" category="object"
     condition_expr="" url_expr="string:${object_url}/metadata_edit_form"
-    visible="True">
+    icon_expr="string:${portal_url}/metadata_icon.png" visible="True">
   <permission value="Modify portal content"/>
  </action>
 </object>
@@ -233,21 +238,23 @@
  <alias from="(Default)" to="bar_view"/>
  <alias from="view" to="bar_view"/>
  <action title="View" action_id="view" category="object" condition_expr=""
-    url_expr="string:${object_url}/bar_view" visible="True">
+    url_expr="string:${object_url}/bar_view" 
+    icon_expr="" visible="True">
   <permission value="View"/>
  </action>
  <action title="Edit" action_id="edit" category="object" condition_expr=""
-    url_expr="string:${object_url}/bar_edit_form" visible="True">
+    url_expr="string:${object_url}/bar_edit_form"
+    icon_expr="" visible="True">
   <permission value="Modify portal content"/>
  </action>
  <action title="Contents" action_id="contents" category="object"
     condition_expr="" url_expr="string:${object_url}/folder_contents"
-    visible="True">
+    icon_expr="" visible="True">
   <permission value="Access contents information"/>
  </action>
  <action title="Metadata" action_id="metadata" category="object"
     condition_expr="" url_expr="string:${object_url}/metadata_edit_form"
-    visible="True">
+    icon_expr="" visible="True">
   <permission value="Modify portal content"/>
  </action>
 </object>
@@ -273,7 +280,8 @@
     def _populate(self, obj):
         obj.setMethodAliases({'(Default)': 'foo', 'view': 'foo'})
         obj.addAction('foo_action', 'Foo', 'string:${object_url}/foo',
-                      'python:1', (), 'Bar')
+                      'python:1', (), 'Bar', 
+                      icon_expr="string:${portal_url}/icon.png")
 
     def _verifyImport(self, obj):
         self.assertEqual(type(obj._aliases), dict)
@@ -291,6 +299,9 @@
         self.assertEqual(obj._actions[0].category, 'Bar')
         self.assertEqual(type(obj._actions[0].condition.text), str)
         self.assertEqual(obj._actions[0].condition.text, 'python:1')
+        self.assertEqual(type(obj._actions[0].icon_expr.text), str)
+        self.assertEqual(obj._actions[0].icon_expr.text, 
+                                  "string:${portal_url}/icon.png")
 
     def setUp(self):
         self._obj = FactoryTypeInformation('foo_fti')

Modified: Products.CMFCore/trunk/Products/CMFCore/exportimport/typeinfo.py
===================================================================
--- Products.CMFCore/trunk/Products/CMFCore/exportimport/typeinfo.py	2008-09-17 21:15:09 UTC (rev 91220)
+++ Products.CMFCore/trunk/Products/CMFCore/exportimport/typeinfo.py	2008-09-17 21:22:41 UTC (rev 91221)
@@ -101,6 +101,7 @@
             child.setAttribute('category', ai_info['category'])
             child.setAttribute('condition_expr', ai_info['condition'])
             child.setAttribute('url_expr', ai_info['action'])
+            child.setAttribute('icon_expr', ai_info['icon_expr'])
             child.setAttribute('visible', str(bool(ai_info['visible'])))
             for permission in ai_info['permissions']:
                 sub = self._doc.createElement('permission')
@@ -121,6 +122,7 @@
             category = str(child.getAttribute('category'))
             condition = str(child.getAttribute('condition_expr'))
             action = str(child.getAttribute('url_expr'))
+            icon_expr = str(child.getAttribute('icon_expr'))
             visible = self._convertToBoolean(child.getAttribute('visible'))
             permissions = []
             for sub in child.childNodes:
@@ -131,10 +133,11 @@
             action_obj = self.context.getActionObject(category+'/'+id)
             if action_obj is None:
                 self.context.addAction(id, title, action, condition,
-                                       tuple(permissions), category, visible)
+                                       tuple(permissions), category, visible,
+                                       icon_expr=icon_expr)
             else:
                 action_obj.edit(title=title, action=action,
-                                condition=condition,
+                                icon_expr=icon_expr, condition=condition,
                                 permissions=tuple(permissions),
                                 visible=visible)
 

Modified: Products.CMFCore/trunk/Products/CMFCore/tests/test_ActionInformation.py
===================================================================
--- Products.CMFCore/trunk/Products/CMFCore/tests/test_ActionInformation.py	2008-09-17 21:15:09 UTC (rev 91220)
+++ Products.CMFCore/trunk/Products/CMFCore/tests/test_ActionInformation.py	2008-09-17 21:22:41 UTC (rev 91221)
@@ -167,7 +167,7 @@
 
         WANTED = {'allowed': True, 'available': True, 'category': 'object',
                   'description': '', 'id': 'foo', 'title': 'foo', 'url': '',
-                  'visible': True}
+                  'visible': True, 'icon': ''}
 
         action = ActionInformation(id='foo')
         ec = None
@@ -177,6 +177,7 @@
         self.assertEqual( ai['title'], WANTED['title'] )
         self.assertEqual( ai['description'], WANTED['description'] )
         self.assertEqual( ai['url'], WANTED['url'] )
+        self.assertEqual( ai['icon'], WANTED['icon'] )
         self.assertEqual( ai['category'], WANTED['category'] )
         self.assertEqual( ai['visible'], WANTED['visible'] )
         self.assertEqual( ai['available'], WANTED['available'] )
@@ -185,7 +186,8 @@
 
     def test_create_from_dict(self):
         WANTED = {'allowed': True, 'available': True, 'category': 'object',
-                  'id': 'foo', 'title': 'foo', 'url': '', 'visible': True}
+                  'id': 'foo', 'title': 'foo', 'url': '', 'visible': True,
+                  'icon': '' }
 
         action = {'name': 'foo', 'url': ''}
         ec = None
@@ -194,6 +196,7 @@
         self.assertEqual( ai['id'], WANTED['id'] )
         self.assertEqual( ai['title'], WANTED['title'] )
         self.assertEqual( ai['url'], WANTED['url'] )
+        self.assertEqual( ai['icon'], WANTED['icon'] )
         self.assertEqual( ai['category'], WANTED['category'] )
         self.assertEqual( ai['visible'], WANTED['visible'] )
         self.assertEqual( ai['available'], WANTED['available'] )
@@ -215,7 +218,8 @@
 
     def test_create_from_dict(self):
         WANTED = {'allowed': True, 'available': True, 'category': 'object',
-                  'id': 'foo', 'title': 'foo', 'url': '', 'visible': True}
+                  'id': 'foo', 'title': 'foo', 'url': '', 'visible': True,
+                  'icon': ''}
 
         action = {'name': 'foo', 'url': '', 'permissions': ('View',)}
         ec = createExprContext(self.site, self.site, None)
@@ -224,6 +228,7 @@
         self.assertEqual( ai['id'], WANTED['id'] )
         self.assertEqual( ai['title'], WANTED['title'] )
         self.assertEqual( ai['url'], WANTED['url'] )
+        self.assertEqual( ai['icon'], WANTED['icon'] )
         self.assertEqual( ai['category'], WANTED['category'] )
         self.assertEqual( ai['visible'], WANTED['visible'] )
         self.assertEqual( ai['available'], WANTED['available'] )
@@ -418,7 +423,7 @@
     def test_getInfoData_empty(self):
         WANTED = ( {'available': True, 'category': 'object',
                     'description': '', 'id': 'foo', 'permissions': (),
-                    'title': 'foo', 'url': '', 'visible': True}, [] )
+                    'title': 'foo', 'url': '', 'visible': True, 'icon': ''},[])
         a = self._makeOne('foo')
         self.assertEqual( a.getInfoData(), WANTED )
 
@@ -427,14 +432,16 @@
                           title='Foo Title',
                           description='Foo description.',
                           action='string:${object_url}/foo_url',
+                          icon_expr='string:${object_url}/icon.gif',
                           condition='',
                           permissions=('View',),
                           visible=False)
         WANTED = ( {'available': True, 'category': 'object',
                     'description': 'Foo description.', 'id': 'foo',
                     'permissions': ('View',), 'title': 'Foo Title',
-                    'url': a._getActionObject(), 'visible': False},
-                   ['url'] )
+                    'url': a._getActionObject(), 'visible': False,
+                    'icon': a._getIconExpressionObject(), },
+                   ['url', 'icon'] )
         self.assertEqual( a.getInfoData(), WANTED )
 
 

Modified: Products.CMFCore/trunk/Products/CMFCore/tests/test_ActionProviderBase.py
===================================================================
--- Products.CMFCore/trunk/Products/CMFCore/tests/test_ActionProviderBase.py	2008-09-17 21:15:09 UTC (rev 91220)
+++ Products.CMFCore/trunk/Products/CMFCore/tests/test_ActionProviderBase.py	2008-09-17 21:22:41 UTC (rev 91221)
@@ -239,7 +239,7 @@
     def test_listActionInfos(self):
         wanted = [{'id': 'an_id', 'title': 'A Title', 'description': '',
                    'url': '', 'category': 'object', 'visible': False,
-                   'available': True, 'allowed': True}]
+                   'available': True, 'allowed': True, 'icon': ''}]
 
         apb = self.site._setObject( 'portal_apb', self._makeProvider(1) )
         rval = apb.listActionInfos()
@@ -260,7 +260,7 @@
     def test_getActionInfo(self):
         wanted = {'id': 'an_id', 'title': 'A Title', 'description': '',
                   'url': '', 'category': 'object', 'visible': False,
-                  'available': True, 'allowed': True}
+                  'available': True, 'allowed': True, 'icon': ''}
 
         apb = self.site._setObject( 'portal_apb', self._makeProvider(1) )
         rval = apb.getActionInfo( ('object/an_id',) )

Modified: Products.CMFCore/trunk/Products/CMFCore/tests/test_ActionsTool.py
===================================================================
--- Products.CMFCore/trunk/Products/CMFCore/tests/test_ActionsTool.py	2008-09-17 21:15:09 UTC (rev 91220)
+++ Products.CMFCore/trunk/Products/CMFCore/tests/test_ActionsTool.py	2008-09-17 21:22:41 UTC (rev 91221)
@@ -120,6 +120,8 @@
                                 title='Folder contents',
                                 action=Expression(text='string:'
                                              '${folder_url}/folder_contents'),
+                                icon_expr=Expression(text='string:'
+                                             '${folder_url}/icon.gif'),
                                 condition=Expression(text='python: '
                                                       'folder is not object'),
                                 permissions=('List folder contents',),
@@ -133,6 +135,7 @@
                           'object': [],
                           'folder': [{'id': 'folderContents',
                                       'url': 'http://nohost/folder_contents',
+                                      'icon': 'http://nohost/icon.gif',
                                       'title': 'Folder contents',
                                       'description': '',
                                       'visible': True,



More information about the Checkins mailing list