concept relations stuff basically OK

git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1094 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2006-02-22 14:54:18 +00:00
parent 09b3bf29e5
commit e86c3e331a
7 changed files with 180 additions and 58 deletions

View file

@ -49,7 +49,7 @@ default predicate concept; the default name for this is 'standard'.
>>> from cybertools.relation.registry import DummyRelationRegistry
>>> from zope.app.testing import ztapi
>>> ztapi.provideUtility(IRelationRegistry, DummyRelationRegistry())
>>> concepts['standard'] = Concept('parent')
>>> concepts['standard'] = Concept(u'subconcept')
Now we can assign the concept c2 as a child to c1 (using the standard
ConceptRelation):
@ -103,7 +103,21 @@ We get a list of types using the ConceptTypeSourceList:
>>> types = ConceptTypeSourceList(cc1)
>>> sorted(t.title for t in types)
[u'Topic', u'Type', u'Unknown Type']
Using a PredicateSourceList we can retrieve a list of the available
predicates. In order for this to work we first have to assign our predicates
a special concept type.
>>> concepts['predicate'] = Concept(u'Predicate')
>>> predicate = concepts['predicate']
>>> concepts['hasType'].conceptType = predicate
>>> concepts['standard'].conceptType = predicate
>>> from loops.concept import PredicateSourceList
>>> predicates = PredicateSourceList(cc1)
>>> sorted(t.title for t in predicates)
[u'has type', u'subconcept']
Concept Views
-------------
@ -151,6 +165,24 @@ We can also create a new concept and assign it:
>>> sorted(c.title for c in cc1.getChildren())
[u'New concept', u'loops for Zope 3']
The concept view provides methods for displaying concept types and
predicates:
>>> from zope.publisher.interfaces.browser import IBrowserRequest
>>> from loops.browser.common import LoopsTerms
>>> from zope.app.form.browser.interfaces import ITerms
>>> from zope.schema.interfaces import IIterableSource
>>> ztapi.provideAdapter(IIterableSource, ITerms, LoopsTerms,
... with=(IBrowserRequest,))
>>> sorted((t.title, t.token) for t in view.conceptTypes())
[(u'Topic', '.loops/concepts/topic'), (u'Type', '.loops/concepts/type'),
(u'Unknown Type', '.loops/concepts/unknown')]
>>> sorted((t.title, t.token) for t in view.predicates())
[(u'has type', '.loops/concepts/hasType'),
(u'subconcept', '.loops/concepts/standard')]
Searchable Text Adapter
-----------------------
@ -406,7 +438,6 @@ objects.) The source is basically a source list:
The form then uses a sort of browser view providing the ITerms interface
based on this source list:
>>> from loops.browser.common import LoopsTerms
>>> terms = LoopsTerms(source, TestRequest())
>>> term = terms.getTerm(doc1)
>>> term.token, term.title, term.value
@ -471,7 +502,6 @@ 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,

View file

@ -31,9 +31,11 @@ from zope.cachedescriptors.property import Lazy
from zope.event import notify
from zope.interface import implements
from zope.publisher.interfaces import BadRequest
from zope.publisher.interfaces.browser import IBrowserRequest
from zope import schema
from zope.schema.interfaces import IIterableSource
from zope.security.proxy import removeSecurityProxy
from loops.concept import Concept
from loops.concept import Concept, ConceptTypeSourceList, PredicateSourceList
from loops.browser.common import BaseView, LoopsTerms
@ -46,30 +48,16 @@ class ConceptView(BaseView):
def parents(self):
for r in self.context.getParentRelations():
yield ConceptRelationView(r, self.request)
#rels = self.context.getParentRelations()
#result = []
#for r in rels:
# p = r.first
#if p is None: # this should not be necessary
# print 'Warning: parents() got a None first on', \
# zapi.getName(self.context), zapi.getName(r.predicate)
# continue
# p.predicate = r.predicate
#return result and self.viewIterator(result) or []
def viewIterator(self, objs):
request = self.request
for o in objs:
yield ConceptView(o, request)
def update(self):
action = self.request.get('action')
request = self.request
action = request.get('action')
if action is None:
return True
if action == 'create':
self.createAndAssign()
return True
tokens = self.request.get('tokens', [])
tokens = request.get('tokens', [])
for token in tokens:
parts = token.split(':')
token = parts[0]
@ -77,16 +65,20 @@ class ConceptView(BaseView):
relToken = parts[1]
concept = self.loopsRoot.loopsTraverse(token)
if action == 'assign':
assignAs = self.request.get('assignAs', 'child')
assignAs = request.get('assignAs', 'child')
predicate = request.get('predicate') or None
if predicate:
predicate = removeSecurityProxy(
self.loopsRoot.loopsTraverse(predicate))
if assignAs == 'child':
self.context.assignChild(removeSecurityProxy(concept))
self.context.assignChild(removeSecurityProxy(concept), predicate)
elif assignAs == 'parent':
self.context.assignParent(removeSecurityProxy(concept))
self.context.assignParent(removeSecurityProxy(concept), predicate)
else:
raise(BadRequest, 'Illegal assignAs parameter: %s.' % assignAs)
elif action == 'remove':
predicate = self.loopsRoot.loopsTraverse(relToken)
qualifier = self.request.get('qualifier')
qualifier = request.get('qualifier')
if qualifier == 'parents':
self.context.deassignParent(concept, [predicate])
elif qualifier == 'children':
@ -103,17 +95,23 @@ class ConceptView(BaseView):
if not name:
raise(BadRequest, 'Empty name.')
title = request.get('create.title', u'')
type = request.get('create.type')
conceptType = request.get('create.type')
concept = Concept(title)
container = self.loopsRoot.getConceptManager()
container[name] = concept
# TODO: notify ObjectCreatedEvent() (?)
#notify(ObjectCreatedEvent(removeSecurityProxy(concept)))
if conceptType:
ctype = self.loopsRoot.loopsTraverse(conceptType)
concept.conceptType = ctype
notify(ObjectCreatedEvent(removeSecurityProxy(concept)))
assignAs = self.request.get('assignAs', 'child')
predicate = request.get('create.predicate') or None
if predicate:
predicate = removeSecurityProxy(
self.loopsRoot.loopsTraverse(predicate))
if assignAs == 'child':
self.context.assignChild(removeSecurityProxy(concept))
self.context.assignChild(removeSecurityProxy(concept), predicate)
elif assignAs == 'parent':
self.context.assignParent(removeSecurityProxy(concept))
self.context.assignParent(removeSecurityProxy(concept), predicate)
else:
raise(BadRequest, 'Illegal assignAs parameter: %s.' % assignAs)
@ -127,8 +125,32 @@ class ConceptView(BaseView):
result = cat.searchResults(loops_searchableText=searchTerm)
else:
result = self.loopsRoot.getConceptManager().values()
searchType = request.get('searchType', '*')
# TODO: query catalog for type
if not searchType:
result = [r for r in result if r.conceptType is None]
elif searchType != '*':
type = self.loopsRoot.loopsTraverse(searchType)
result = [r for r in result if r.conceptType == type]
return self.viewIterator(result)
def viewIterator(self, objs):
request = self.request
for o in objs:
yield ConceptView(o, request)
def conceptTypes(self):
types = ConceptTypeSourceList(self.context)
terms = zapi.getMultiAdapter((types, self.request), ITerms)
for type in types:
yield terms.getTerm(type)
def predicates(self):
preds = PredicateSourceList(self.context)
terms = zapi.getMultiAdapter((preds, self.request), ITerms)
for pred in preds:
yield terms.getTerm(pred)
class ConceptRelationView(object):

View file

@ -12,6 +12,7 @@
qualifier string:parents;
summary string:Currently assigned objects;
legend string:Parent Concepts;
showPredicate string:yes;
buttonText string:Remove Parents;"
style="float:left; padding-right:20px">
<metal:parents use-macro="views/relation_macros/listing" />
@ -21,6 +22,7 @@
qualifier string:children;
summary string:Currently assigned objects;
legend string:Child Concepts;
showPredicate string:yes;
buttonText string:Remove Children;"
style="padding-right:20px">
<metal:children use-macro="views/relation_macros/listing" />
@ -37,6 +39,7 @@
qualifier nothing;
summary string:Assignment candidates;
legend string:Search;
showPredicate nothing;
buttonText string:Assign;"
style="padding-right:20px">
<metal:assign use-macro="views/relation_macros/listing">
@ -49,7 +52,15 @@
<option value="child" selected i18n:translate="">Child</option>
<option value="parent" i18n:translate="">Parent</option>
</select>
object(s)
Object(s) using Predicate
<select name="predicate">
<tal:types repeat="pred view/predicates">
<option value=".loops/concepts/hasType"
i18n:translate=""
tal:attributes="value pred/token"
tal:content="pred/title">Predicate</option>
</tal:types>
</select>
</metal:special>
</metal:assign>
</div>

View file

@ -418,6 +418,10 @@
for="loops.concept.ConceptTypeSourceList
zope.publisher.interfaces.browser.IBrowserRequest" />
<zope:adapter factory="loops.browser.common.LoopsTerms"
for="loops.concept.PredicateSourceList
zope.publisher.interfaces.browser.IBrowserRequest" />
<zope:adapter factory="loops.browser.common.LoopsTerms"
for="loops.target.TargetSourceList
zope.publisher.interfaces.browser.IBrowserRequest" />

View file

@ -22,8 +22,9 @@
<tr>
<th>&nbsp;</th>
<th i18n:translate="label_title">Title</th>
<th i18n:translate="label_predicate">Predicate</th>
<th i18n:translate="label_type">Type</th>
<th i18n:translate="label_predicate"
tal:condition="showPredicate">Predicate</th>
</tr>
</thead>
<tbody>
@ -39,21 +40,19 @@
Title
</a>
</td>
<tal:relation condition="item/predicateTitle|nothing">
<td>
<a tal:content="item/predicateTitle" href="#"
tal:attributes="href
string:${item/predicateUrl}/@@SelectedManagementView.html">
Type
</a>
</td>
</tal:relation>
<td>
<a tal:condition="item/typeTitle | nothing"
tal:content="item/typeTitle" href="#"
tal:attributes="href
string:${item/typeUrl}/@@SelectedManagementView.html">
Title
Type
</a>
</td>
<td tal:condition="showPredicate">
<a tal:content="item/predicateTitle" href="#"
tal:attributes="href
string:${item/predicateUrl}/@@SelectedManagementView.html">
Predicate
</a>
</td>
</tr>
@ -87,8 +86,13 @@
tal:attributes="value nothing" />&nbsp;
<span i18n:translate="">Type</span>
<select name="create.type">
<option value=".loops/concepts/topic"
i18n:translate="">Topic</option>
<tal:types repeat="type view/conceptTypes">
<option value=".loops/concepts/topic"
i18n:translate=""
tal:attributes="value type/token"
tal:content="type/title">Topic</option>
</tal:types>
<option>None</option>
</select>
</div><br />
<div class="formControls">
@ -96,11 +100,20 @@
value="Create Object"
i18n:attributes="value"
tal:attributes="value buttonText" />
and assign as
<select name="assignAs">
<option value="child" selected i18n:translate="">Child</option>
<option value="parent" i18n:translate="">Parent</option>
</select>
and assign as
<select name="assignAs">
<option value="child" selected i18n:translate="">Child</option>
<option value="parent" i18n:translate="">Parent</option>
</select>
using Predicate
<select name="create.predicate">
<tal:types repeat="pred view/predicates">
<option value=".loops/concepts/hasType"
i18n:translate=""
tal:attributes="value pred/token"
tal:content="pred/title">Predicate</option>
</tal:types>
</select>
</div>
</form>
</fieldset>
@ -111,15 +124,23 @@
<form method="post" name="listing" action="."
tal:attributes="action request/URL">
<input type="hidden" name="action" value="search" />
<div class="row">
<div class="row"
tal:define="searchTerm request/searchTerm | nothing;
searchType request/searchType | nothing;">
<span i18n:translate="">Search Term</span>
<input name="searchTerm"
tal:attributes="value request/searchTerm | nothing" />
tal:attributes="value searchTerm" />
<span i18n:translate="">Type</span>
<select name="search.type">
<select name="searchType">
<option value="*">Any</option>
<option value=".loops/concepts/topic"
i18n:translate="">Topic</option>
<tal:types repeat="type view/conceptTypes">
<option value=".loops/concepts/topic"
i18n:translate=""
tal:attributes="value type/token;
selected python: type.token == searchType"
tal:content="type/title">Topic</option>
</tal:types>
<option>None</option>
</select>
</div>
<div class="formControls">

View file

@ -252,10 +252,9 @@ class ConceptTypeSourceList(object):
result = []
cm = self.concepts
typeObject = cm.getTypeConcept()
unknownType = self.concepts.get('unknown')
unknownType = cm.get('unknown') # does this make sense?
if typeObject is not None:
typeRelation = ConceptRelation(None, typeObject, cm.getTypePredicate())
types = typeObject.getChildren((typeRelation,))
types = typeObject.getChildren([cm.getTypePredicate()])
if typeObject not in types:
result.append(typeObject)
if unknownType is not None and unknownType not in types:
@ -267,6 +266,36 @@ class ConceptTypeSourceList(object):
return len(self.conceptTypes)
class PredicateSourceList(object):
implements(schema.interfaces.IIterableSource)
def __init__(self, context):
self.context = context
self.concepts = self.context.getLoopsRoot().getConceptManager()
def __iter__(self):
return iter(self.predicates)
@Lazy
def predicates(self):
result = []
cm = self.concepts
defPred = cm.getDefaultPredicate()
typePred = cm.getTypePredicate()
if defPred is not None and typePred is not None:
result.append(defPred)
result.append(typePred)
predType = defPred.conceptType
if predType is not None and predType != cm.getTypeConcept():
result.extend(p for p in predType.getChildren([typePred])
if p not in result)
return result
def __len__(self):
return len(self.conceptTypes)
class SearchableText(object):
implements(ISearchableText)

View file

@ -252,6 +252,11 @@
name="loops.conceptTypeSource"
/>
<vocabulary
factory="loops.concept.PredicateSourceList"
name="loops.PredicateSource"
/>
<vocabulary
factory="loops.target.TargetSourceList"
name="loops.targetSource"