diff --git a/README.txt b/README.txt index 9201734..7bfacdd 100755 --- a/README.txt +++ b/README.txt @@ -536,9 +536,20 @@ view for rendering.) >>> doc1.data = u'Test data\n\nAnother paragraph' >>> view.renderTarget() u'
Test data\n\nAnother paragraph
' + >>> doc1.contentType = 'text/restructured' + >>> doc1.data = u'Test data\n\nAnother `paragraph `_' + >>> from loops.wiki.base import wikiLinksActive >>> view.renderTarget() - u'

Test data

\n

Another paragraph

\n' + u'

Test data

\n

Another paragraph

\n' + +u'

Test data

\n

Another ?paragraph

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