Author: jmorliaguet Date: Sun Oct 2 21:21:50 2005 New Revision: 27833 Modified: z3lab/cpsskins/branches/jmo-perspectives/Makefile z3lab/cpsskins/branches/jmo-perspectives/browser/authoring/__init__.py z3lab/cpsskins/branches/jmo-perspectives/browser/authoring/configure.zcml z3lab/cpsskins/branches/jmo-perspectives/browser/authoring/editing.css z3lab/cpsskins/branches/jmo-perspectives/browser/authoring/view_editor.pt z3lab/cpsskins/branches/jmo-perspectives/elements/formats/__init__.py z3lab/cpsskins/branches/jmo-perspectives/elements/interfaces.py z3lab/cpsskins/branches/jmo-perspectives/elements/views.py z3lab/cpsskins/branches/jmo-perspectives/relations/tool.py z3lab/cpsskins/branches/jmo-perspectives/storage/__init__.py z3lab/cpsskins/branches/jmo-perspectives/storage/interfaces.py z3lab/cpsskins/branches/jmo-perspectives/storage/relations.py Log:
- added methods to customize / uncustomize formats (functional view editor) Modified: z3lab/cpsskins/branches/jmo-perspectives/Makefile ============================================================================== --- z3lab/cpsskins/branches/jmo-perspectives/Makefile (original) +++ z3lab/cpsskins/branches/jmo-perspectives/Makefile Sun Oct 2 21:21:50 2005 @@ -3,7 +3,7 @@ all: i18n clean i18n: - python ~/Zope3/utilities/i18nextract.py -d cpsskins -p ./ -o ./locales/ + python2.4 ~/Zope3/utilities/i18nextract.py -d cpsskins -p ./ -o ./locales/ clean: find . \( -name "*.pyc" -o -name "*.pyo" -o -name "*~" \) -exec rm -f {} \; Modified: z3lab/cpsskins/branches/jmo-perspectives/browser/authoring/__init__.py ============================================================================== --- z3lab/cpsskins/branches/jmo-perspectives/browser/authoring/__init__.py (original) +++ z3lab/cpsskins/branches/jmo-perspectives/browser/authoring/__init__.py Sun Oct 2 21:21:50 2005 @@ -129,6 +129,19 @@ IViewable(self.context).removeView(perspective) self._redirect() + def customizeFormat(self, name='', perspective=None): + tmutil = getThemeManager() + theme = tmutil.getEffectiveTheme(self.context) + perspective = theme.getPerspectiveById(perspective) + IViewable(self.context).customizeFormat(name, perspective) + self._redirect() + + def uncustomizeFormat(self, name='', perspective=None): + tmutil = getThemeManager() + theme = tmutil.getEffectiveTheme(self.context) + perspective = theme.getPerspectiveById(perspective) + IViewable(self.context).uncustomizeFormat(name, perspective) + self._redirect() class Editing(BrowserView): Modified: z3lab/cpsskins/branches/jmo-perspectives/browser/authoring/configure.zcml ============================================================================== --- z3lab/cpsskins/branches/jmo-perspectives/browser/authoring/configure.zcml (original) +++ z3lab/cpsskins/branches/jmo-perspectives/browser/authoring/configure.zcml Sun Oct 2 21:21:50 2005 @@ -155,6 +155,16 @@ attribute="removeView" /> + <page + name="customizeFormat" + attribute="customizeFormat" + /> + + <page + name="uncustomizeFormat" + attribute="uncustomizeFormat" + /> + </pages> Modified: z3lab/cpsskins/branches/jmo-perspectives/browser/authoring/editing.css ============================================================================== --- z3lab/cpsskins/branches/jmo-perspectives/browser/authoring/editing.css (original) +++ z3lab/cpsskins/branches/jmo-perspectives/browser/authoring/editing.css Sun Oct 2 21:21:50 2005 @@ -212,7 +212,7 @@ color: #666; } -.views a { +.views a, .views a:visited { text-decoration: none; } Modified: z3lab/cpsskins/branches/jmo-perspectives/browser/authoring/view_editor.pt ============================================================================== --- z3lab/cpsskins/branches/jmo-perspectives/browser/authoring/view_editor.pt (original) +++ z3lab/cpsskins/branches/jmo-perspectives/browser/authoring/view_editor.pt Sun Oct 2 21:21:50 2005 @@ -22,15 +22,18 @@ <tr tal:define="info views/?view; even repeat/view/even; display info/display; + formats info/formats; perspective info/perspective" tal:attributes="class python: even and 'even' or nothing"> - <td tal:content="view" /> + <td tal:content="view" /> + + <!-- Display --> <td> <tal:block condition="perspective"> <a title="Add view" tal:condition="not:display" - tal:attributes="href string:@@addView?perspective=$perspective"> + tal:attributes="href string:@@cloneView?perspective=$perspective"> <img src="/++skin++cpsskins/@@/add-16.png" /> </a> <a title="Remove view" @@ -44,13 +47,25 @@ </tal:block> </td> + <!-- Formats --> <td style="text-align: center" tal:repeat="format_name format_names"> - <tal:block condition="python: display and perspective"> - <img src="/++skin++cpsskins/@@/unchecked-16.png" /> - </tal:block> - <tal:block condition="python: not perspective"> - <img src="/++skin++cpsskins/@@/checked-disabled-16.png" /> + <tal:block condition="formats"> + <tal:block define="format_info formats/?format_name; + customizable format_info/customizable"> + <tal:block condition="perspective"> + <a tal:condition="customizable" + tal:attributes="href string:@@customizeFormat?name=$format_name&perspective=$perspective"> + <img src="/++skin++cpsskins/@@/unchecked-16.png" /> + </a> + <a tal:condition="not:customizable" + tal:attributes="href string:@@uncustomizeFormat?name=$format_name&perspective=$perspective"> + <img src="/++skin++cpsskins/@@/checked-16.png" /> + </a> + </tal:block> + <img tal:condition="not:perspective" + src="/++skin++cpsskins/@@/checked-disabled-16.png" /> + </tal:block> </tal:block> </td> Modified: z3lab/cpsskins/branches/jmo-perspectives/elements/formats/__init__.py ============================================================================== --- z3lab/cpsskins/branches/jmo-perspectives/elements/formats/__init__.py (original) +++ z3lab/cpsskins/branches/jmo-perspectives/elements/formats/__init__.py Sun Oct 2 21:21:50 2005 @@ -22,6 +22,7 @@ from zope.app.traversing.interfaces import TraversalError from zope.component import getUtility from zope.interface import implements +from zope.security.proxy import removeSecurityProxy from cpsskins.configuration.interfaces import IRegistry from cpsskins.elements import Element @@ -100,13 +101,17 @@ return getattr(self, name) def storeFormat(self, format=None): - context = self.context - tmutil = getThemeManager() - theme = tmutil.getThemeInContext(context) + theme = tmutil.getThemeInContext(self.context) formats = theme.getStorage(IFormatStorage) return formats.add(format) + def unstoreFormat(self, format=None): + tmutil = getThemeManager() + theme = tmutil.getThemeInContext(self.context) + formats = theme.getStorage(IFormatStorage) + return formats.remove(format) + def getFormats(self, name=''): context = self.context reltool = RelationTool(context) @@ -121,35 +126,39 @@ return None def getFormatNames(self): - """Return the list of format names. + """Return the list of format names in alphabetical order. """ - return [f.formatname for f in self.getFormats()] + names = [f.formatname for f in self.getFormats()] + names.sort() + return names def addFormat(self, name='', id=''): format = self.factory(name, id) self.storeFormat(format) - predicate = format_registry.get(name)['predicate'] - return self.setFormat(format, predicate) + return self.setFormat(format) - def setFormat(self, format, predicate): - context = self.context - relation = DyadicRelation(predicate, context, format) - reltool = RelationTool(context) - return reltool.add(relation) + def setFormat(self, format=None): + """Assign a format to a display. + + The formerly associated format -- if it exists -- is replaced. - def cloneFormat(self, name): - """Clone the format """ context = self.context reltool = RelationTool(context) - new_format = locationCopy(self.getFormat(name)) - self.storeFormat(new_format) - - predicate = format_registry.get(name)['predicate'] + predicate = format_registry.get(format.formatname)['predicate'] relations = reltool.search(first=context, predicate=predicate) reltool.remove(relations) - return self.setFormat(new_format, predicate) + + relation = DyadicRelation(first=context, second=format, + predicate=predicate) + reltool.add(relation) + + def cloneFormat(self, format): + """Clone the format + """ + new_format = locationCopy(removeSecurityProxy(format)) + return self.storeFormat(new_format) def factory(self, name='', id=''): """Display factory. Return a display element. Modified: z3lab/cpsskins/branches/jmo-perspectives/elements/interfaces.py ============================================================================== --- z3lab/cpsskins/branches/jmo-perspectives/elements/interfaces.py (original) +++ z3lab/cpsskins/branches/jmo-perspectives/elements/interfaces.py Sun Oct 2 21:21:50 2005 @@ -148,7 +148,10 @@ def addFormat(name): """Add a format to a formattable element.""" - def cloneFormat(name): + def setFormat(format): + """ """ + + def cloneFormat(format): """ """ def storeFormat(format): @@ -170,6 +173,12 @@ def removeView(perspective): """ """ + def customizeFormat(name, perspective): + """ """ + + def uncustomizeFormat(name, perspective): + """ """ + # The different categories of elements class ICanvas(IInnerNode): Modified: z3lab/cpsskins/branches/jmo-perspectives/elements/views.py ============================================================================== --- z3lab/cpsskins/branches/jmo-perspectives/elements/views.py (original) +++ z3lab/cpsskins/branches/jmo-perspectives/elements/views.py Sun Oct 2 21:21:50 2005 @@ -20,8 +20,10 @@ from zope.app.traversing.interfaces import IPathAdapter from zope.interface import implements from zope.app.location.pickling import locationCopy +from zope.component import getUtility from cpsskins.configuration.elements import factories +from cpsskins.configuration.interfaces import IRegistry from cpsskins.elements.interfaces import IDisplayable, IFormattable from cpsskins.ontology import hasFormat, hasDisplay, hasDisplayFromPerspective from cpsskins.relations.tool import RelationTool @@ -29,6 +31,8 @@ from cpsskins.thememanager import getThemeManager from interfaces import IViewable +format_registry = getUtility(IRegistry, 'formats') + class Viewable(object): """This adapter makes elements viewable, i.e. displayable and formattable according to the factory settings. @@ -83,16 +87,55 @@ for r in reltool.search(first=default_display, predicate=hasFormat): rel = reltool.get(r) format = rel.second - predicate = rel() - formattable.setFormat(format, predicate) + formattable.setFormat(format) def removeView(self, perspective=None): - """Remove a view associated to an element + """Remove a view associated to an element. """ context = self.context displayable = IDisplayable(context) display = displayable.removeDisplay(perspective) + def customizeFormat(self, name='', perspective=None): + """Customize a format in a given perspective. + """ + if perspective is None: + raise ValueError("Must specify a perspective.") + + context = self.context + reltool = RelationTool(context) + + displayable = IDisplayable(context) + display = displayable.getDisplay(perspective) + + formattable = IFormattable(display) + current_format = formattable.getFormat(name) + format = formattable.cloneFormat(current_format) + + predicate = format_registry.get(name)['predicate'] + relations = reltool.search(first=display, predicate=predicate) + reltool.remove(relations) + + formattable.setFormat(format) + + def uncustomizeFormat(self, name='', perspective=None): + """Uncustomize a format in a given perspective. + """ + if perspective is None: + raise ValueError("Must specify a perspective.") + + context = self.context + reltool = RelationTool(context) + + display = IDisplayable(context).getDisplay(perspective) + default_display = IDisplayable(context).getDisplay() + + format = IFormattable(display).getFormat(name) + default_format = IFormattable(default_display).getFormat(name) + IFormattable(display).setFormat(default_format) + + + def getViewInfo(self): """Return a dictionary with information about display and formats associated to the element in various views / perspectives. @@ -114,19 +157,30 @@ 'perspective': perspective} # override initial values - for r in reltool.search(predicate=hasDisplay, first=object) \ - + reltool.search(predicate=hasDisplayFromPerspective, - first=object): + for r in reltool.search(first=object, predicate=hasDisplay) \ + + reltool.search(first=object, + predicate=hasDisplayFromPerspective): rel = reltool.get(r) display = rel.second formattable = IFormattable(display) perspective = len(rel) == 3 and rel.third or None view_id = perspective and str(perspective) or 'default' + formats_info = {} + for format in formattable.getFormats(): + format_info = formats_info[format.formatname] = {} + format_info['format'] = format + + customizable = False + if perspective is not None: + used_by = reltool.search(second=format, predicate=hasFormat) + customizable = len(used_by) > 1 + format_info['customizable'] = customizable + views[view_id] = { 'relation': rel, 'display': display, - 'formats': formattable.getFormats(), + 'formats': formats_info, 'perspective': perspective, } Modified: z3lab/cpsskins/branches/jmo-perspectives/relations/tool.py ============================================================================== --- z3lab/cpsskins/branches/jmo-perspectives/relations/tool.py (original) +++ z3lab/cpsskins/branches/jmo-perspectives/relations/tool.py Sun Oct 2 21:21:50 2005 @@ -63,11 +63,5 @@ return self.getStorage().getThirds(**kw) def remove(self, ids=[]): - storage = self.getStorage() - if isinstance(ids, str): - ids = [ids] - for id in ids: - if id in storage: - del storage[id] - continue - raise KeyError, "No such relation (%s) in the storage." % id + if ids: + return self.getStorage().remove(ids) Modified: z3lab/cpsskins/branches/jmo-perspectives/storage/__init__.py ============================================================================== --- z3lab/cpsskins/branches/jmo-perspectives/storage/__init__.py (original) +++ z3lab/cpsskins/branches/jmo-perspectives/storage/__init__.py Sun Oct 2 21:21:50 2005 @@ -24,6 +24,7 @@ from zope.event import notify from zope.interface import implements +from cpsskins.elements.interfaces import IElement from interfaces import IStorage class Storage(BTreeContainer, Contained): @@ -38,9 +39,12 @@ notify(ObjectAddedEvent(object)) return self[name] - def remove(self, object): - name = object.name() - if name in self: - del self[name] - else: - raise KeyError("%s not in the storage." % repr(object)) + def remove(self, objects): + if not isinstance(objects, (list, tuple)): + objects = [objects] + for obj in objects: + if IElement.providedBy(obj): + obj = obj.name() + if obj not in self: + raise KeyError("%s not in the storage." % obj) + del self[obj] Modified: z3lab/cpsskins/branches/jmo-perspectives/storage/interfaces.py ============================================================================== --- z3lab/cpsskins/branches/jmo-perspectives/storage/interfaces.py (original) +++ z3lab/cpsskins/branches/jmo-perspectives/storage/interfaces.py Sun Oct 2 21:21:50 2005 @@ -30,7 +30,7 @@ def add(object): """ """ - def remove(object): + def remove(objects): """ """ def __setitem__(item): Modified: z3lab/cpsskins/branches/jmo-perspectives/storage/relations.py ============================================================================== --- z3lab/cpsskins/branches/jmo-perspectives/storage/relations.py (original) +++ z3lab/cpsskins/branches/jmo-perspectives/storage/relations.py Sun Oct 2 21:21:50 2005 @@ -24,6 +24,8 @@ from zope.app.container.interfaces import INameChooser from zope.app.location.traversing import LocationPhysicallyLocatable from zope.interface import implements +from zope.proxy import isProxy +from zope.security.proxy import removeSecurityProxy from cpsskins.relations import Predicate, CompoundPredicate from cpsskins.relations.interfaces import IRelation @@ -235,10 +237,22 @@ name = str(relation).replace('_', '').replace(' ', '') relation_name = chooser.chooseName(name, relation) self[relation_name] = relation - logger.log(DEBUG, "Added a relation '%s' connecting %s" - % (str(relation), list(relation)) + logger.log(DEBUG, + "Added a relation with id '%s' and predicate '%s' connecting %s" + % (relation_name, str(relation), list(relation)) ) + def remove(self, ids=[]): + """Remove relations for the storage. + """ + if isinstance(ids, str): + ids = [ids] + for id in ids: + if id not in self: + raise KeyError, "No such relation (%s) in the storage." % id + del self[id] + logger.log(DEBUG, "Removed the relations with ids: '%s'" % ids) + # Relation index def reindex(self): """Reindex the relations. @@ -317,6 +331,9 @@ if predicate is None: raise ValueError, "Must specify a predicate in the query." + if isProxy(predicate): + predicate = removeSecurityProxy(predicate) + if not isinstance(predicate, (Predicate, CompoundPredicate)): raise TypeError, "This type of predicate is not supported." -- http://lists.nuxeo.com/mailman/listinfo/z3lab-checkins