\n'
+
+ >>> #links = loopsRoot.getRecordManager()['links']
+ >>> #links['0000001']
+
+
If the target object is removed from its container all references
to it are removed as well. (To make this work we have to handle
diff --git a/browser/resource.py b/browser/resource.py
index 6d0d928..44d5824 100644
--- a/browser/resource.py
+++ b/browser/resource.py
@@ -55,7 +55,10 @@ from loops.media.interfaces import IMediaAsset
from loops.organize.stateful.browser import statefulActions
from loops.versioning.browser import version_macros
from loops.versioning.interfaces import IVersionable
+from loops import util
from loops.util import _
+from loops.wiki.base import wikiLinksActive
+from loops.wiki.base import LoopsWikiManager, LoopsWiki, LoopsWikiPage
resource_macros = ViewPageTemplateFile('resource_macros.pt')
@@ -149,7 +152,6 @@ class ResourceView(BaseView):
return component.queryMultiAdapter((context, self.request),
name=viewName)
ct = context.contentType
- #if ct.startswith('text/') and ct != 'text/rtf':
ti = IType(context).typeInterface
if (not ti or issubclass(ti, ITextDocument)
or (ct.startswith('text/') and ct != 'text/rtf')):
@@ -166,10 +168,8 @@ class ResourceView(BaseView):
data = context.data
response = self.request.response
ct = context.contentType
- #if useAttachment or (not ct.startswith('image/') and ct != 'application/pdf'):
if useAttachment:
filename = adapted(self.context).localFilename or getName(self.context)
- #filename = urllib.quote(filename)
filename = NameChooser(getParent(self.context)).normalizeName(filename)
response.setHeader('Content-Disposition',
'attachment; filename=%s' % filename)
@@ -180,6 +180,21 @@ class ResourceView(BaseView):
response.setHeader('Content-Type', ct)
return data
+ def renderText(self, text, contentType):
+ if contentType == 'text/restructured' and wikiLinksActive(self.loopsRoot):
+ # TODO: make this more flexible/configurable
+ wm = LoopsWikiManager(self.loopsRoot)
+ wiki = LoopsWiki('loops')
+ wiki.__parent__ = self.loopsRoot
+ wiki.__name__ = 'wiki'
+ wm.addWiki(wiki)
+ #wp = wiki.createPage(getName(self.context))
+ wp = wiki.addPage(LoopsWikiPage(self.context))
+ wp.text = text
+ #print wp.wiki.getManager()
+ #return util.toUnicode(wp.render(self.request))
+ return super(ResourceView, self).renderText(text, contentType)
+
def download(self):
""" Force download, e.g. of a PDF file """
return self.show(True)
diff --git a/configure.zcml b/configure.zcml
index 3ca344e..c401be7 100644
--- a/configure.zcml
+++ b/configure.zcml
@@ -478,6 +478,7 @@
+
diff --git a/knowledge/configure.zcml b/knowledge/configure.zcml
index 860b00d..9f2f7d1 100644
--- a/knowledge/configure.zcml
+++ b/knowledge/configure.zcml
@@ -3,8 +3,7 @@
+ i18n_domain="loops">
diff --git a/resource.py b/resource.py
index 1e250da..c9728ab 100644
--- a/resource.py
+++ b/resource.py
@@ -144,8 +144,6 @@ class Resource(Image, Contained):
self.resourceType = value
def _setData(self, data):
- #if not data:
- # return
dataFile = StringIO(data) # let File tear it into pieces
super(Resource, self)._setData(dataFile)
if not self.contentType:
@@ -224,18 +222,12 @@ class Resource(Image, Contained):
def getSize(self):
if self._size:
return self._size
- size = getattr(adapted(self), 'size', None)
+ adobj = adapted(self)
+ size = getattr(adobj, 'size', None)
if size is None:
- return len(adapted(self).data)
+ return len(adobj.data)
return size
- tp = IType(self, None)
- if tp is not None:
- ti = tp.typeInterface
- if ti is not None:
- return len(ti(self).data)
- return len(self.data)
-
def sizeForSorting(self):
return 'byte', self.getSize()
diff --git a/tests/setup.py b/tests/setup.py
index f476dd9..aa1b61a 100644
--- a/tests/setup.py
+++ b/tests/setup.py
@@ -44,6 +44,10 @@ from cybertools.relation.registry import invalidateRelations, removeRelation
from cybertools.stateful.interfaces import IStatefulIndexInfo
from cybertools.text.html import HtmlTransform
from cybertools.typology.interfaces import IType
+from cybertools.wiki.base.config import WikiConfiguration
+from cybertools.wiki.dcu.html import Writer as DocutilsHTMLWriter
+from cybertools.wiki.dcu.rstx import Parser as DocutilsRstxParser
+from cybertools.wiki.tracking.link import LinkManager
from loops.base import Loops
from loops import util
@@ -72,6 +76,8 @@ from loops.security.setter import BaseSecuritySetter
from loops.setup import SetupManager, addObject
from loops.type import LoopsType, ConceptType, ResourceType, TypeConcept
from loops.view import Node, NodeAdapter
+from loops.wiki.link import LoopsLinkProcessor
+from loops.wiki.setup import SetupManager as WikiSetupManager
class ClientIdManager(object):
@@ -174,6 +180,13 @@ class TestSite(object):
component.provideAdapter(StatefulResourceIndexInfo)
component.provideHandler(handleTransition)
+ component.provideAdapter(WikiSetupManager, name='wiki')
+ component.provideUtility(WikiConfiguration())
+ component.provideAdapter(LinkManager)
+ component.provideUtility(DocutilsHTMLWriter(), name='docutils.html')
+ component.provideUtility(DocutilsRstxParser(), name='docutils.rstx')
+ component.provideAdapter(LoopsLinkProcessor, name='loops')
+
loopsRoot = self.site['loops'] = Loops()
setup = SetupManager(loopsRoot)
concepts, resources, views = setup.setup()
diff --git a/wiki/__init__.py b/wiki/__init__.py
new file mode 100644
index 0000000..4bc90fb
--- /dev/null
+++ b/wiki/__init__.py
@@ -0,0 +1,4 @@
+"""
+$Id$
+"""
+
diff --git a/wiki/base.py b/wiki/base.py
new file mode 100644
index 0000000..a8b31bc
--- /dev/null
+++ b/wiki/base.py
@@ -0,0 +1,74 @@
+#
+# Copyright (c) 2009 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
+#
+
+"""
+Wiki base implementation for loops.
+
+$Id$
+"""
+
+from zope.traversing.api import getName
+
+from cybertools.wiki.base.wiki import WikiManager, Wiki, WikiPage
+from cybertools.wiki.interfaces import ILinkManager
+
+from loops import util
+
+
+def wikiLinksActive(loops):
+ records = loops.getRecordManager()
+ if records is not None:
+ links = records.get('links')
+ return links is not None
+ return False
+
+
+class LoopsWikiManager(WikiManager):
+ """ An adapter...
+ """
+
+ linkManager = 'tracking'
+ nodeProcessors = dict(reference=['loops'])
+
+ def __init__(self, context):
+ super(LoopsWikiManager, self).__init__()
+ self.context = context
+
+ def getPlugin(self, type, name):
+ if type == ILinkManager and name == 'tracking':
+ return ILinkManager(self.context.getRecordManager()['links'])
+ return super(LoopsWikiManager, self).getPlugin(type, name)
+
+
+class LoopsWiki(Wiki):
+
+ def getPage(self, name):
+ if name.startswith('.target'):
+ return self.getManager().getObject(int(name[7:]))
+
+
+class LoopsWikiPage(WikiPage):
+ """ An adapter...
+ """
+
+ def __init__(self, context):
+ self.context = context
+ self.name = getName(context)
+
+ def getUid(self):
+ return util.getUidForObject(self.context)
diff --git a/wiki/configure.zcml b/wiki/configure.zcml
new file mode 100644
index 0000000..0bcd7b8
--- /dev/null
+++ b/wiki/configure.zcml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/wiki/link.py b/wiki/link.py
new file mode 100644
index 0000000..0fd8dc0
--- /dev/null
+++ b/wiki/link.py
@@ -0,0 +1,36 @@
+#
+# Copyright (c) 2009 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
+#
+
+"""
+Link manager implementation for loops.
+
+$Id$
+"""
+
+from cybertools.wiki.dcu.process import Reference
+
+
+class LoopsLinkProcessor(Reference):
+
+ def getTargetUri(self, obj):
+ ann = self.request.annotations.get('loops.view', {})
+ nodeView = self.viewAnnotations.get('nodeView')
+ if nodeView is not None:
+ return nodeView.getUrlForTarget(obj)
+ return super(LoopsLinkProcessor, self).getTargetUri(obj)
+
diff --git a/wiki/setup.py b/wiki/setup.py
new file mode 100644
index 0000000..21309b8
--- /dev/null
+++ b/wiki/setup.py
@@ -0,0 +1,35 @@
+#
+# Copyright (c) 2009 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
+#
+
+"""
+Automatic setup of a loops site for the wiki package.
+
+$Id$
+"""
+
+from cybertools.tracking.btree import TrackingStorage
+from cybertools.wiki.tracking.link import Link
+from loops.setup import SetupManager as BaseSetupManager
+
+
+class SetupManager(BaseSetupManager):
+
+ def setup(self):
+ records = self.context.getRecordManager()
+ links = self.addObject(records, TrackingStorage, 'links',
+ trackFactory=Link)