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:
parent
09b3bf29e5
commit
e86c3e331a
7 changed files with 180 additions and 58 deletions
38
README.txt
38
README.txt
|
@ -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,
|
||||
|
|
|
@ -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):
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -22,8 +22,9 @@
|
|||
<tr>
|
||||
<th> </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" />
|
||||
<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">
|
||||
|
|
35
concept.py
35
concept.py
|
@ -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)
|
||||
|
|
|
@ -252,6 +252,11 @@
|
|||
name="loops.conceptTypeSource"
|
||||
/>
|
||||
|
||||
<vocabulary
|
||||
factory="loops.concept.PredicateSourceList"
|
||||
name="loops.PredicateSource"
|
||||
/>
|
||||
|
||||
<vocabulary
|
||||
factory="loops.target.TargetSourceList"
|
||||
name="loops.targetSource"
|
||||
|
|
Loading…
Add table
Reference in a new issue