From 19e4431cfba3984b3bbcf4891755f9a013011134 Mon Sep 17 00:00:00 2001 From: helmutm Date: Wed, 15 Feb 2006 14:49:27 +0000 Subject: [PATCH] Now concepts may have a type, and the types are concepts themselves, with the 'type' concept on top git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1081 fd906abe-77d9-0310-91a1-e0d9ade77398 --- README.txt | 61 +++++++++++++++++++++++++++-------- browser/concept.py | 63 ++++++++++++++++++++++++++++-------- browser/concept_related.pt | 40 ++++++++++++----------- browser/configure.zcml | 4 +-- browser/relation_macros.pt | 43 +++++++++++++++++-------- concept.py | 66 +++++++++++++++++++++++++++++++++++++- configure.zcml | 9 +++++- interfaces.py | 39 ++++++++++++++++++---- 8 files changed, 255 insertions(+), 70 deletions(-) diff --git a/README.txt b/README.txt index bcd3868..f9c43b0 100755 --- a/README.txt +++ b/README.txt @@ -72,6 +72,33 @@ We can now ask our concepts for their related child and parent concepts: >>> len(cc2.getChildren()) 0 +Each concept should have a concept type; this is in fact provided by a +relation to a special kind of concept object with the magic name 'type'. +This type object is its own type: + + >>> concepts['type'] = Concept(u'Type') + >>> typeObject = concepts['type'] + >>> typeObject.setConceptType(typeObject) + >>> typeObject.getConceptType().title + u'Type' + + >>> concepts['unknown'] = Concept(u'Unknown Type') + >>> unknown = concepts['unknown'] + >>> unknown.setConceptType(typeObject) + >>> unknown.getConceptType().title + u'Type' + + >>> cc1.setConceptType(unknown) + >>> cc1.getConceptType().title + u'Unknown Type' + + >>> concepts['topic'] = Concept(u'Topic') + >>> topic = concepts['topic'] + >>> topic.setConceptType(typeObject) + >>> cc1.setConceptType(topic) + >>> cc1.getConceptType().title + u'Topic' + Concept Views ------------- @@ -84,18 +111,6 @@ Concept Views 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 cc1 - .loops/concepts/cc2 Zope 3 - The concept view allows updating the underlying context object: >>> cc3 = Concept(u'loops for Zope 3') @@ -115,6 +130,23 @@ The concept view allows updating the underlying context object: >>> sorted(c.title for c in cc1.getChildren()) [u'loops for Zope 3'] +We can also create a new concept and assign it: + + >>> params = {'action': 'create', 'create.name': 'cc4', + ... 'create.title': u'New concept'} + >>> view = ConceptView(cc1, TestRequest(**params)) + >>> view.update() + True + >>> sorted(c.title for c in cc1.getChildren()) + [u'New concept', u'loops for Zope 3'] + +Searchable Text Adapter +----------------------- + + >>> from loops.concept import SearchableText + >>> SearchableText(cc2).searchableText() + u'cc2 Zope 3' + Resources and what they have to do with Concepts ================================================ @@ -356,9 +388,9 @@ objects.) The source is basically a source list: >>> from loops.target import TargetSourceList >>> source = TargetSourceList(m111) >>> len(source) - 4 + 8 >>> sorted([zapi.getName(s) for s in source]) - [u'cc1', u'cc2', u'cc3', u'doc1'] + [u'cc1', u'cc2', u'cc3', u'cc4', u'doc1', u'topic', u'type', u'unknown'] The form then uses a sort of browser view providing the ITerms interface based on this source list: @@ -428,6 +460,7 @@ A node's target is rendered using the NodeView's renderTargetBody() 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.publisher.interfaces.browser import IBrowserRequest >>> from zope.app.publisher.interfaces.browser import IBrowserView >>> from loops.browser.resource import DocumentView >>> ztapi.provideAdapter(IDocument, Interface, DocumentView, diff --git a/browser/concept.py b/browser/concept.py index f105db9..f179387 100644 --- a/browser/concept.py +++ b/browser/concept.py @@ -23,6 +23,7 @@ $Id$ """ from zope.app import zapi +from zope.app.catalog.interfaces import ICatalog from zope.app.dublincore.interfaces import ICMFDublinCore from zope.app.form.browser.interfaces import ITerms from zope.cachedescriptors.property import Lazy @@ -30,26 +31,32 @@ from zope.interface import implements from zope.publisher.interfaces import BadRequest from zope import schema from zope.security.proxy import removeSecurityProxy -from loops.concept import ConceptSourceList +from loops.concept import Concept from loops.browser.common import BaseView, LoopsTerms class ConceptView(BaseView): def children(self): - request = self.request - for c in self.context.getChildren(): - yield ConceptView(c, request) + ch = self.context.getChildren() + return ch and self.viewIterator(ch) or [] def parents(self): + p = self.context.getParents() + return p and self.viewIterator(p) or [] + + def viewIterator(self, objs): request = self.request - for c in self.context.getParents(): - yield ConceptView(c, request) + for o in objs: + yield ConceptView(o, request) def update(self): - action = self.request.get('action', None) + action = self.request.get('action') if action is None: return True + if action == 'create': + self.createAndAssign() + return True tokens = self.request.get('tokens', []) for token in tokens: concept = self.loopsRoot.loopsTraverse(token) @@ -62,7 +69,7 @@ class ConceptView(BaseView): else: raise(BadRequest, 'Illegal assignAs parameter: %s.' % assignAs) elif action == 'remove': - qualifier = self.request.get('qualifier', None) + qualifier = self.request.get('qualifier') if qualifier == 'parents': self.context.deassignParents(concept) elif qualifier == 'children': @@ -73,9 +80,39 @@ class ConceptView(BaseView): 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 terms.getTerm(candidate) + def createAndAssign(self): + request = self.request + name = request.get('create.name') + if not name: + raise(BadRequest, 'Empty name.') + title = request.get('create.title', u'') + type = request.get('create.type') + concept = Concept(title) + container = self.loopsRoot.getConceptManager() + container[name] = concept + assignAs = self.request.get('assignAs', 'child') + if assignAs == 'child': + self.context.assignChild(removeSecurityProxy(concept)) + elif assignAs == 'parent': + self.context.assignParent(removeSecurityProxy(concept)) + else: + raise(BadRequest, 'Illegal assignAs parameter: %s.' % assignAs) + + #def getVocabularyForRelated(self): # obsolete + # source = ConceptSourceList(self.context) + # terms = zapi.getMultiAdapter((source, self.request), ITerms) + # for candidate in source: + # yield terms.getTerm(candidate) + + def search(self): + request = self.request + if request.get('action') != 'search': + return [] + searchTerm = request.get('searchTerm', None) + if searchTerm: + cat = zapi.getUtility(ICatalog) + result = cat.searchResults(loops_searchableText=searchTerm) + else: + result = self.loopsRoot.getConceptManager().values() + return self.viewIterator(result) diff --git a/browser/concept_related.pt b/browser/concept_related.pt index f8c87e0..74840b3 100644 --- a/browser/concept_related.pt +++ b/browser/concept_related.pt @@ -7,36 +7,38 @@

Concept Title


- - - - + + +
- - + buttonText string:Remove Children;" + style="padding-right:20px"> + +
- +
- +
- + legend string:Search; + buttonText string:Assign;" + style="padding-right:20px"> @@ -44,13 +46,13 @@ as object(s) - + diff --git a/browser/configure.zcml b/browser/configure.zcml index 9401a95..0ac0c91 100644 --- a/browser/configure.zcml +++ b/browser/configure.zcml @@ -415,11 +415,11 @@
Parent Concepts + i18n:translate="">Listing -
- -
+ +
- Create Object + Create Object
+
Name - +   Title - +   Type - + -
+
+ i18n:attributes="value" + tal:attributes="value buttonText" /> and assign as
@@ -84,9 +91,17 @@
+
Search Term - + + Type +
+ attributes="getLoopsUri loopsTraverse getConceptManager" /> @@ -227,6 +227,8 @@ + + @@ -241,6 +243,11 @@ + +