diff --git a/README.txt b/README.txt index 459c930..bcd3868 100755 --- a/README.txt +++ b/README.txt @@ -81,12 +81,39 @@ Concept Views >>> sorted([c.title for c in view.children()]) [u'Zope 3'] +The concept view allows to get a list of terms (sort of vocabulary) that +can be used to show the objects in a listing: + + >>> from zope.publisher.interfaces.browser import IBrowserRequest + >>> from zope.app.form.browser.interfaces import ITerms + >>> from loops.concept import ConceptSourceList + >>> from loops.browser.common import LoopsTerms + >>> ztapi.provideAdapter(ConceptSourceList, ITerms, LoopsTerms, + ... with=(IBrowserRequest,)) >>> voc = view.getVocabularyForRelated() >>> for term in voc: ... print term.token, term.title - .loops/concepts/cc1 + .loops/concepts/cc1 cc1 .loops/concepts/cc2 Zope 3 - + +The concept view allows updating the underlying context object: + + >>> cc3 = Concept(u'loops for Zope 3') + >>> concepts['cc3'] = cc3 + >>> view = ConceptView(cc1, + ... TestRequest(action='assign', tokens=['.loops/concepts/cc3'])) + >>> view.update() + True + >>> sorted(c.title for c in cc1.getChildren()) + [u'Zope 3', u'loops for Zope 3'] + + >>> view = ConceptView(cc1, + ... TestRequest(action='remove', qualifier='children', + ... tokens=['.loops/concepts/cc2'])) + >>> view.update() + True + >>> sorted(c.title for c in cc1.getChildren()) + [u'loops for Zope 3'] Resources and what they have to do with Concepts ================================================ @@ -329,14 +356,14 @@ objects.) The source is basically a source list: >>> from loops.target import TargetSourceList >>> source = TargetSourceList(m111) >>> len(source) - 3 + 4 >>> sorted([zapi.getName(s) for s in source]) - [u'cc1', u'cc2', u'doc1'] + [u'cc1', u'cc2', u'cc3', u'doc1'] The form then uses a sort of browser view providing the ITerms interface based on this source list: - >>> from loops.browser.terms import LoopsTerms + >>> from loops.browser.common import LoopsTerms >>> terms = LoopsTerms(source, TestRequest()) >>> term = terms.getTerm(doc1) >>> term.token, term.title, term.value @@ -402,7 +429,6 @@ method. This makes use of a browser view registered for the target interface, and of a lot of other stuff needed for the rendering machine. >>> from zope.app.publisher.interfaces.browser import IBrowserView - >>> from zope.publisher.interfaces.browser import IBrowserRequest >>> from loops.browser.resource import DocumentView >>> ztapi.provideAdapter(IDocument, Interface, DocumentView, ... with=(IBrowserRequest,)) diff --git a/browser/common.py b/browser/common.py index 8b3c84a..91a8858 100644 --- a/browser/common.py +++ b/browser/common.py @@ -24,7 +24,10 @@ $Id$ from zope.app import zapi from zope.app.dublincore.interfaces import ICMFDublinCore +from zope.app.form.browser.interfaces import ITerms from zope.cachedescriptors.property import Lazy +from zope.interface import implements +#from zope.schema.vocabulary import SimpleTerm from zope.security.proxy import removeSecurityProxy class BaseView(object): @@ -56,5 +59,37 @@ class BaseView(object): @Lazy def title(self): - return self.context.title + return self.context.title or zapi.getName(self.context) + + @Lazy + def value(self): + return self.context + + +class LoopsTerms(object): + """ Provide the ITerms interface, e.g. for usage in selection + lists. + """ + + implements(ITerms) + + def __init__(self, source, request): + # the source parameter is a view or adapter of a real context object: + self.source = source + self.context = source.context + self.request = request + + @Lazy + def loopsRoot(self): + return self.context.getLoopsRoot() + + def getTerm(self, value): + return BaseView(value, self.request) + #token = self.loopsRoot.getLoopsUri(value) + #title = value.title or zapi.getName(value) + #return SimpleTerm(value, token, title) + + def getValue(self, token): + return self.loopsRoot.loopsTraverse(token) + diff --git a/browser/concept.py b/browser/concept.py index a06b171..3c0112c 100644 --- a/browser/concept.py +++ b/browser/concept.py @@ -24,12 +24,14 @@ $Id$ from zope.app import zapi from zope.app.dublincore.interfaces import ICMFDublinCore +from zope.app.form.browser.interfaces import ITerms from zope.cachedescriptors.property import Lazy from zope.interface import implements +from zope.publisher.interfaces import BadRequest from zope import schema from zope.security.proxy import removeSecurityProxy -from loops.browser.common import BaseView -from loops.browser.terms import LoopsTerms +from loops.concept import ConceptSourceList +from loops.browser.common import BaseView, LoopsTerms class ConceptView(BaseView): @@ -45,32 +47,29 @@ class ConceptView(BaseView): yield ConceptView(c, request) def update(self): - concept_name = self.request.get('concept_name', None) - if concept_name: - concept = zapi.getParent(self.context)[concept_name] - self.context.assignChild(removeSecurityProxy(concept)) + action = self.request.get('action', None) + if action is None: + return True + tokens = self.request.get('tokens', []) + for token in tokens: + concept = self.loopsRoot.loopsTraverse(token) + if action == 'assign': + self.context.assignChild(removeSecurityProxy(concept)) + elif action == 'remove': + qualifier = self.request.get('qualifier', None) + if qualifier == 'parents': + self.context.deassignParents(concept) + elif qualifier == 'children': + self.context.deassignChildren(concept) + else: + raise(BadRequest, 'Illegal qualifier: %s.' % qualifier) + else: + raise(BadRequest, 'Illegal action: %s.' % action) return True def getVocabularyForRelated(self): source = ConceptSourceList(self.context) + terms = zapi.getMultiAdapter((source, self.request), ITerms) for candidate in source: - yield LoopsTerms(ConceptView(candidate, self.request), self.request) - - -class ConceptSourceList(object): - - implements(schema.interfaces.IIterableSource) - - def __init__(self, context): - #self.context = context - self.context = removeSecurityProxy(context) - root = self.context.getLoopsRoot() - self.concepts = root.getConceptManager() - - def __iter__(self): - for obj in self.concepts.values(): - yield obj - - def __len__(self): - return len(self.concepts) + yield terms.getTerm(candidate) diff --git a/browser/concept_related.pt b/browser/concept_related.pt index c43defe..8569e9f 100644 --- a/browser/concept_related.pt +++ b/browser/concept_related.pt @@ -8,39 +8,34 @@