diff --git a/README.txt b/README.txt
index f85d921..6ec4233 100755
--- a/README.txt
+++ b/README.txt
@@ -30,6 +30,8 @@ top-level loops container and a concept manager:
>>> concepts['cc1'] = cc1
>>> cc1.title
u''
+ >>> loopsRoot.getLoopsUri(cc1)
+ '.loops/concepts/cc1'
>>> cc2 = Concept(u'Zope 3')
>>> concepts['cc2'] = cc2
@@ -277,13 +279,17 @@ target may be moved or renamed without any problems.)
>>> nodeConfig = INodeConfigSchema(m111)
>>> nodeConfig.targetUri
- u'.loops/concepts/cc2'
+ '.loops/concepts/cc2'
>>> nodeConfig.title = u'New title for m111'
>>> nodeConfig.title
u'New title for m111'
>>> m111.title
u'New title for m111'
>>> nodeConfig.targetUri = '.loops/resources/doc1'
+
+We have to get a new adapter to avoid problems with lazy variables:
+
+ >>> nodeConfig = INodeConfigSchema(m111)
>>> nodeConfig.title = 'New title for m111'
>>> m111.target is doc1
True
@@ -305,12 +311,22 @@ application uses a subclass that does all the other stuff for form handling.)
>>> form = {'field.createTarget': True,
... 'field.targetUri': '.loops/resources/ma07',
... 'field.targetType': 'loops.resource.MediaAsset'}
- >>> view = ConfigureBaseView(INodeConfigSchema(m111), TestRequest(form=form))
>>> view = ConfigureBaseView(m111, TestRequest(form=form))
- >>> view.checkCreateTarget()
+ >>> m111.target = view.checkCreateTarget()
>>> sorted(resources.keys())
[u'doc1', u'ma07']
-
+ >>> isinstance(resources['ma07'], MediaAsset)
+ True
+
+ >>> form = {'field.createTarget': True,
+ ... 'field.targetType': 'loops.resource.Document'}
+ >>> view = ConfigureBaseView(m111, TestRequest(form=form))
+ >>> m111.target = view.checkCreateTarget()
+ >>> sorted(resources.keys())
+ [u'doc1', u'm1.m11.m111', u'ma07']
+ >>> isinstance(resources['m1.m11.m111'], Document)
+ True
+
It is also possible to edit a target's attributes directly in an
edit form provided by the node:
@@ -318,6 +334,11 @@ edit form provided by the node:
>>> ztapi.provideAdapter(INode, IDocument, DocumentProxy)
>>> ztapi.provideAdapter(INode, IMediaAsset, MediaAssetProxy)
+ >>> proxy = zapi.getAdapter(m111, IDocument)
+ >>> proxy.title = u'Set via proxy'
+ >>> resources['m1.m11.m111'].title
+ u'Set via proxy'
+
Ordering Nodes
--------------
@@ -335,10 +356,10 @@ to the bottom, and to the top
>>> from cybertools.container.ordered import OrderedContainerView
>>> view = OrderedContainerView(m11, TestRequest())
- >>> view.moveToBottom(('m113',))
+ >>> view.move_bottom(('m113',))
>>> m11.keys()
['m111', 'm112', 'm114', 'm113']
- >>> view.moveUp(('m114',), 1)
+ >>> view.move_up(('m114',), 1)
>>> m11.keys()
['m111', 'm114', 'm112', 'm113']
diff --git a/__init__.py b/__init__.py
index 6c9ffbb..17abd30 100644
--- a/__init__.py
+++ b/__init__.py
@@ -23,8 +23,9 @@
$Id$
"""
-from zope.interface import implements
+from zope.app import zapi
from zope.app.folder.folder import Folder
+from zope.interface import implements
from interfaces import ILoops
class Loops(Folder):
@@ -34,3 +35,9 @@ class Loops(Folder):
def getLoopsRoot(self):
return self
+ def getViewManager(self):
+ return self['views']
+
+ def getLoopsUri(self, obj):
+ return str('.loops' + zapi.getPath(obj)[len(zapi.getPath(self)):])
+
diff --git a/browser/configure.zcml b/browser/configure.zcml
index 0e5e472..5db0a57 100644
--- a/browser/configure.zcml
+++ b/browser/configure.zcml
@@ -247,7 +247,6 @@
@@ -274,6 +273,7 @@
content_factory="loops.view.Node"
schema="loops.interfaces.INodeConfigSchema"
fields="title description nodeType targetType targetUri createTarget"
+ class="loops.browser.node.ConfigureView"
permission="zope.ManageContent">
@@ -304,6 +304,12 @@
+
+
+
+
+
+
-
-
diff --git a/browser/node.py b/browser/node.py
index c7c5656..0988888 100644
--- a/browser/node.py
+++ b/browser/node.py
@@ -26,6 +26,7 @@ from zope.cachedescriptors.property import Lazy
from zope.app import zapi
from zope.app.container.browser.contents import JustContents
from zope.app.dublincore.interfaces import ICMFDublinCore
+from zope.configuration.config import ConfigurationContext
from zope.proxy import removeAllProxies
from zope.security import canAccess, canWrite
from zope.security.proxy import removeSecurityProxy
@@ -104,18 +105,41 @@ class ConfigureBaseView(object):
self.context = removeSecurityProxy(context)
self.request = request
+ @Lazy
+ def loopsRoot(self):
+ return self.context.getLoopsRoot()
+
def checkCreateTarget(self):
form = self.request.form
- if 'field.createTarget' in form:
+ if form.get('field.createTarget', False):
type = self.request.form.get('field.targetType',
'loops.resource.MediaAsset')
- # TODO: find class (better: factory) from type name
+ factory = ConfigurationContext().resolve(type)
uri = self.request.form.get('field.targetUri', None)
- # TODO: generate uri/__name__ if not given
if uri:
- # TODO: find container
- self.context.getLoopsRoot()['resources']['ma07'] = MediaAsset()
- #self.context.loopsRoot['resources']['ma07'] = MediaAsset()
+ path = uri.split('/')
+ containerName = path[-2]
+ name = path[-1]
+ else:
+ containerName = 'resource' in type and 'resources' or 'concepts'
+ viewManagerPath = zapi.getPath(self.context.getViewManager())
+ name = zapi.getPath(self.context)[len(viewManagerPath)+1:]
+ name = name.replace('/', '.')
+ container = self.loopsRoot[containerName]
+ # check for duplicates:
+ num = 1
+ basename = name
+ while name in container:
+ name = '%s-%d' % (basename, num)
+ num += 1
+ # create target:
+ container[name] = factory()
+ target = container[name]
+ # set possibly new targetUri in request for further processing:
+ targetUri = self.loopsRoot.getLoopsUri(target)
+ form['field.targetUri'] = targetUri
+ return target
+
class ConfigureView(object):
""" An editing view for configuring a node, optionally creating
diff --git a/concept.py b/concept.py
index a56f4b2..1bbd42d 100644
--- a/concept.py
+++ b/concept.py
@@ -65,6 +65,9 @@ class Concept(Contained, Persistent):
def getLoopsRoot(self):
return zapi.getParent(self).getLoopsRoot()
+ def getViewManager(self):
+ return self.getLoopsRoot().getViewManager()
+
# concept relations
def getSubConcepts(self, relationships=None):
@@ -128,3 +131,8 @@ class ConceptManager(BTreeContainer):
def getLoopsRoot(self):
return zapi.getParent(self)
+ def getViewManager(self):
+ return self.getLoopsRoot().getViewManager()
+
+
+
diff --git a/configure.zcml b/configure.zcml
index 4bb0309..4e69e35 100644
--- a/configure.zcml
+++ b/configure.zcml
@@ -218,8 +218,10 @@
-
-
+
+
1:
- raise ValueError, 'There may be only one target for a View object.'
+ raise ValueError('There may be only one target for a View object: %s - %s'
+ % (zapi.getName(self), `[zapi.getName(r.second) for r in rels]`))
return list(rels)[0].second
def setTarget(self, target):
@@ -72,8 +73,9 @@ class View(object):
return
else:
registry.unregister(oldRel)
- rel = TargetRelation(self, target)
- registry.register(rel)
+ if target:
+ rel = TargetRelation(self, target)
+ registry.register(rel)
target = property(getTarget, setTarget)
@@ -85,6 +87,9 @@ class View(object):
def getLoopsRoot(self):
return zapi.getParent(self).getLoopsRoot()
+ def getViewManager(self):
+ return zapi.getParent(self).getViewManager()
+
class Node(View, OrderedContainer):
@@ -141,6 +146,9 @@ class ViewManager(OrderedContainer):
def getLoopsRoot(self):
return zapi.getParent(self)
+ def getViewManager(self):
+ return self
+
class TargetRelation(DyadicRelation):
""" A relation between a view and another object.
@@ -186,24 +194,30 @@ class NodeConfigAdapter(object):
@Lazy
def loopsRoot(self): return self.context.getLoopsRoot()
+ @Lazy
+ def target(self):
+ return self.context.target
+
def getTargetUri(self):
- rootPath = zapi.getPath(self.loopsRoot)
- if self.context.target is not None:
- path = zapi.getPath(self.context.target)[len(rootPath):]
- return '.loops' + path
+ target = self.target
+ if target is not None:
+ return self.loopsRoot.getLoopsUri(target)
else:
return ''
def setTargetUri(self, uri):
- names = uri.split('/')
- if names[0] == '.loops':
- path = '/'.join(names[1:])
- self.context.target = zapi.traverse(self.loopsRoot, path)
+ if uri:
+ names = uri.split('/')
+ if names[0] == '.loops':
+ path = '/'.join(names[1:])
+ self.context.target = zapi.traverse(self.loopsRoot, path)
+ else:
+ self.context.target = None
targetUri = property(getTargetUri, setTargetUri)
def getTargetType(self):
- target = self.context.target
+ target = self.target
if target:
return '%s.%s' % (target.__module__, target.__class__.__name__)
return None