Work in progress: concept assignments

git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1078 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2006-02-14 12:05:04 +00:00
parent e95943cbf3
commit 1ded8434db
9 changed files with 159 additions and 127 deletions

View file

@ -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,))

View file

@ -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)

View file

@ -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)

View file

@ -8,39 +8,34 @@
<h1 tal:content="context/title">Concept Title</h1><br />
<tal:block define="items view/parents;
action string:remove;
qualifier string:parents;
legend string:Parent Concepts">
<metal:parents use-macro="views/relation_macros/assignments" />
summary string:Currently assigned objects;
legend string:Parent Concepts;
buttonText string:Remove Assignment(s);
">
<metal:parents use-macro="views/relation_macros/listing" />
</tal:block>
<tal:block define="items view/children;
action string:remove;
qualifier string:children;
legend string:Child Concepts">
<metal:children use-macro="views/relation_macros/assignments" />
summary string:Currently assigned objects;
legend string:Child Concepts;
buttonText string:Remove Assignment(s);
">
<metal:children use-macro="views/relation_macros/listing" />
</tal:block>
<tal:block define="items view/getVocabularyForRelated;
action string:assign;
qualifier nothing;
summary string:Assignment candidates;
legend string:Assign as Children;
buttonText string:Assign Object(s);
">
<metal:assign use-macro="views/relation_macros/listing" />
</tal:block>
<form action="." method="post"
tal:attributes="action request/URL">
<div class="row">
<span class="label">Concept Name</span>:
<span class="field">
<input type="test" name="concept_name" />
</span>
</div>
<div class="row">
<select name="concept">
<tal:option repeat="term view/getVocabularyForRelated">
<option tal:content="term/title"
tal:attributes="value term/token">
Concept Abc
</option>
</tal:option>
</select>
</div>
<div class="row">
<input type="submit" name="concept_assign" value="Assign Concept" />
</div>
</form>
</div>
</body>
</html>

View file

@ -414,12 +414,12 @@
<!-- vocabulary, traversing, and other stuff -->
<zope:adapter factory="loops.browser.terms.LoopsTerms"
<zope:adapter factory="loops.browser.common.LoopsTerms"
for="loops.target.TargetSourceList
zope.publisher.interfaces.browser.IBrowserRequest" />
<zope:adapter factory="loops.browser.terms.LoopsTerms"
for="loops.browser.concept.ConceptSourceList
<zope:adapter factory="loops.browser.common.LoopsTerms"
for="loops.concept.ConceptSourceList
zope.publisher.interfaces.browser.IBrowserRequest" />
<zope:view factory="loops.view.NodeTraverser"

View file

@ -1,16 +1,21 @@
<html i18n:domain="loops">
<metal:assignments define-macro="assignments">
<form method="post" name="remove" action="."
<metal:assignments define-macro="listing">
<form method="post" name="listing" action="."
tal:attributes="action request/URL"
tal:condition="items">
<input type="hidden" name="action" value="remove" />
<input type="hidden" name="action" value="remove"
tal:attributes="value action" />
<input type="hidden" name="qualifier" value="parents"
tal:condition="qualifier"
tal:attributes="value qualifier" />
<fieldset>
<legend tal:content="legend">Parent Concepts</legend>
<table class="listing" summary="Currently assigned objects">
<legend tal:content="legend"
i18n:translate="">Parent Concepts</legend>
<table class="listing" summary="Currently assigned objects"
i18n:attributes="summary"
tal:attributes="summary summary">
<thead>
<tr>
<th>&nbsp;</th>
@ -32,9 +37,10 @@
</tbody>
</table>
<div class="formControls">
<input class="context" type="submit" name="form.button.Remove"
<input class="context" type="submit" name="form.button.submit"
value="Remove Assignment(s)"
i18n:attributes="value" />
i18n:attributes="value"
tal:attributes="value buttonText" />
</div>
</fieldset>
</form>

View file

@ -1,54 +0,0 @@
#
# Copyright (c) 2006 Helmut Merz helmutm@cy55.de
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
Class(es) for representing a related object , to be used e.g. for
vocabularies and widgets.
$Id$
"""
from zope.app import zapi
from zope.app.form.browser.interfaces import ITerms
from zope.schema.vocabulary import SimpleTerm
from zope.cachedescriptors.property import Lazy
from zope.interface import implements
from zope.security.proxy import removeSecurityProxy
from loops.browser.common import BaseView
class LoopsTerms(BaseView):
implements(ITerms)
def __init__(self, context, request):
self.context = context.context # the context parameter is the source object
self.request = request
@Lazy
def loopsRoot(self):
return self.context.getLoopsRoot()
def getTerm(self, value):
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)

View file

@ -26,6 +26,8 @@ from zope.app import zapi
from zope.app.container.btree import BTreeContainer
from zope.app.container.contained import Contained
from zope.interface import implements
from zope import schema
from zope.security.proxy import removeSecurityProxy
from persistent import Persistent
from cybertools.relation import DyadicRelation
@ -96,10 +98,12 @@ class Concept(Contained, Persistent):
if relationships is None:
relationships = [ConceptRelation]
registry = zapi.getUtility(IRelationRegistry)
relations = registry.query(first=self, second=concept,
relationships=relationships)
relations = []
for rs in relationships:
relations.extend(registry.query(first=self, second=concept,
relationship=rs))
for rel in relations:
registry.unregister(relation)
registry.unregister(rel)
def deassignParents(self, concept, relationships=None):
concept.deassignChildren(self, relationships)
@ -140,3 +144,24 @@ class ConceptManager(BTreeContainer):
def getViewManager(self):
return self.getLoopsRoot().getViewManager()
# adapters and similar components
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)

View file

@ -49,7 +49,7 @@
<require
permission="zope.View"
attributes="getLoopsUri" />
attributes="getLoopsUri loopsTraverse" />
</content>