From 1c1147cda9796bc02de27e91851527dcdc78885b Mon Sep 17 00:00:00 2001 From: helmutm Date: Thu, 5 Feb 2009 10:29:01 +0000 Subject: [PATCH] open up media asset type for all kinds of external files git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@3205 fd906abe-77d9-0310-91a1-e0d9ade77398 --- browser/common.py | 4 + browser/configure.zcml | 21 +++- browser/contents.pt | 234 +++++++++++++++++++++++++++++++++++++++++ browser/form.py | 1 + browser/resource.py | 6 +- common.py | 8 ++ config/base.py | 7 +- config/configure.zcml | 5 + interfaces.py | 9 +- media/browser/asset.py | 8 +- resource.py | 22 +++- schema/factory.py | 20 +++- tests/setup.py | 3 +- 13 files changed, 332 insertions(+), 16 deletions(-) create mode 100644 browser/contents.pt diff --git a/browser/common.py b/browser/common.py index 9cee707..c31c722 100644 --- a/browser/common.py +++ b/browser/common.py @@ -403,6 +403,10 @@ class BaseView(GenericView, I18NView): def globalOptions(self): return IOptions(self.loopsRoot) + @Lazy + def typeOptions(self): + return IOptions(adapted(self.typeProvider)) + # versioning @Lazy diff --git a/browser/configure.zcml b/browser/configure.zcml index b687024..f50054d 100644 --- a/browser/configure.zcml +++ b/browser/configure.zcml @@ -140,9 +140,16 @@ + + + permission="zope.ManageContent" /> + + + + + + + + + + +
+ +
+ + +
+ + + + + + + + + +
+ Error message +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ NameTitleSizeCreatedModified
+ + + + + + + + + foo + + + Title + +    
+ Pages: + + 1 + ... + 2 + 3 + 3 + ... + 5 + +
+ +
+ + + + + +
+
+ + + +
+
+
+ + + + + +
+
+ +
+ + +
+ +
+
+ + + +
+ + +
+ + diff --git a/browser/form.py b/browser/form.py index d79e3e8..42b8f3a 100644 --- a/browser/form.py +++ b/browser/form.py @@ -283,6 +283,7 @@ class CreateObjectForm(ObjectForm): def adapted(self): ad = self.typeInterface(Resource()) ad.storageName = 'unknown' # hack for file objects: don't try to retrieve data + ad.__type__ = adapted(self.typeConcept) return ad @Lazy diff --git a/browser/resource.py b/browser/resource.py index aec6830..24cd874 100644 --- a/browser/resource.py +++ b/browser/resource.py @@ -58,6 +58,9 @@ from loops.versioning.interfaces import IVersionable from loops.util import _ +resource_macros = ViewPageTemplateFile('resource_macros.pt') + + class CustomFileWidget(FileWidget): def hasInput(self): @@ -103,7 +106,8 @@ class MediaAssetEditForm(EditForm): class ResourceView(BaseView): - template = ViewPageTemplateFile('resource_macros.pt') + #template = ViewPageTemplateFile('resource_macros.pt') + template = resource_macros @Lazy def icon(self): diff --git a/common.py b/common.py index b150e5e..5d96514 100644 --- a/common.py +++ b/common.py @@ -97,6 +97,7 @@ class AdapterBase(object): _textIndexAttributes = () __is_dummy__ = False + __type__ = None languageInfo = None @@ -138,6 +139,13 @@ class AdapterBase(object): def name(self): return getName(self.context) + @Lazy + def type(self): + return self.__type__ or self.getType() + + def getType(self): + return adapted(self.context.getType()) + @Lazy def uid(self): return util.getUidForObject(self.context) diff --git a/config/base.py b/config/base.py index 1010b8d..56081c2 100644 --- a/config/base.py +++ b/config/base.py @@ -33,7 +33,7 @@ from cybertools.meta.config import GlobalOptions as BaseGlobalOptions from cybertools.meta.interfaces import IOptions from cybertools.meta.namespace import Executor, ExecutionError from cybertools.typology.interfaces import IType -from loops.interfaces import ILoops, ILoopsObject +from loops.interfaces import ILoops, ILoopsObject, ITypeConcept #from loops.query import IQueryConcept from loops.expert.concept import IQueryConcept from loops import util @@ -91,6 +91,11 @@ class LoopsOptions(Options): raise ExecutionError('\n' + rc) +class TypeOptions(LoopsOptions): + + adapts(ITypeConcept) + + class QueryOptions(LoopsOptions): adapts(IQueryConcept) diff --git a/config/configure.zcml b/config/configure.zcml index 28b0c02..c8f975b 100644 --- a/config/configure.zcml +++ b/config/configure.zcml @@ -12,6 +12,11 @@ + + + + + diff --git a/interfaces.py b/interfaces.py index fedbb28..aa37006 100644 --- a/interfaces.py +++ b/interfaces.py @@ -763,8 +763,13 @@ class IExternalFile(IFile): missing_value='', required=False) - externalAddress = Attribute('The full address for accessing the object ' - 'on the external storage, e.g. a filename or path.') + externalAddress = schema.BytesLine( + title=_(u'External Address'), + description=_(u'The full address for accessing the object ' + 'on the external storage, e.g. a filename or path.'), + default='', + missing_value='', + required=False) class IAddressableExternalFile(IExternalFile): diff --git a/media/browser/asset.py b/media/browser/asset.py index 10f81bc..40caa91 100644 --- a/media/browser/asset.py +++ b/media/browser/asset.py @@ -28,7 +28,7 @@ from zope.app.pagetemplate import ViewPageTemplateFile from zope.cachedescriptors.property import Lazy from loops.browser.node import NodeView -from loops.browser.resource import ResourceView +from loops.browser.resource import ResourceView, resource_macros from loops.common import adapted from loops import util @@ -39,7 +39,11 @@ class MediaAssetView(ResourceView): @Lazy def macro(self): - return template.macros['asset'] + #return template.macros['asset'] + if 'image/' in self.context.contentType: + return template.macros['asset'] + else: + return resource_macros.macros['download'] def show(self, useAttachment=False): versionId = self.request.get('v') diff --git a/resource.py b/resource.py index 9cbbbb6..86bbb74 100644 --- a/resource.py +++ b/resource.py @@ -224,6 +224,11 @@ class Resource(Image, Contained): def getSize(self): if self._size: return self._size + size = getattr(adapted(self), 'size', None) + if size is None: + return len(adapted(self).data) + return size + tp = IType(self, None) if tp is not None: ti = tp.typeInterface @@ -357,9 +362,15 @@ class ExternalFileAdapter(FileAdapter): storageParams = property(getStorageParams, setStorageParams) def getExternalAddress(self): - return getattr(self.context, '_externalAddress', self.context.__name__) + return getattr(self.context, '_externalAddress', None) or self.context.__name__ def setExternalAddress(self, addr): self.context._externalAddress = addr + if addr: + data = self.data + self.context._size = len(data) + contentType = guess_content_type(addr, self.data[:100]) + if contentType: + self.contentType = contentType[0] externalAddress = property(getExternalAddress, setExternalAddress) @property @@ -372,12 +383,14 @@ class ExternalFileAdapter(FileAdapter): def setData(self, data): storageParams = self.storageParams storageName = self.storageName + externalAddress = self.externalAddress storage = component.getUtility(IExternalStorage, name=storageName) storage.setData(self.externalAddress, data, params=storageParams) self.context._size = len(data) # remember storage settings: self.storageParams = storageParams self.storageName = storageName + self.externalAddress = externalAddress def getData(self): if self.storageName in ('unknown', None): # object not set up yet @@ -387,6 +400,13 @@ class ExternalFileAdapter(FileAdapter): data = property(getData, setData) + @property + def size(self): + if self.storageName in ('unknown', None): # object not set up yet + return '' + storage = component.getUtility(IExternalStorage, name=self.storageName) + return storage.getSize(self.externalAddress, params=self.storageParams) + class AddressableExternalFileAdapter(ExternalFileAdapter): diff --git a/schema/factory.py b/schema/factory.py index 9df0f6d..c4b28ab 100644 --- a/schema/factory.py +++ b/schema/factory.py @@ -25,7 +25,10 @@ $Id$ from zope.component import adapts from cybertools.composer.schema.factory import SchemaFactory +from loops.common import adapted from loops.interfaces import IResourceAdapter, IFile, INote, IAddressableExternalFile +from cybertools.meta.interfaces import IOptions +from cybertools.typology.interfaces import IType class ResourceSchemaFactory(SchemaFactory): @@ -47,10 +50,19 @@ class FileSchemaFactory(SchemaFactory): def __call__(self, interface, **kw): schema = super(FileSchemaFactory, self).__call__(interface, **kw) - if 'request' in kw: - principal = kw['request'].principal - if not principal or principal.id != 'rootadmin': - schema.fields.remove('contentType') + options = IOptions(self.context.type) + hide = options('hide_fields') or [] + show = options('show_fields') or [] + for f in ('contentType', 'externalAddress',): + if f in schema.fields and f not in show: + schema.fields.remove(f) + for f in hide: + if f in schema.fields: + schema.fields.remove(f) + #if 'request' in kw: + # principal = kw['request'].principal + # if not principal or principal.id != 'rootadmin': + # schema.fields.remove('contentType') return schema diff --git a/tests/setup.py b/tests/setup.py index d830da4..e749c7d 100644 --- a/tests/setup.py +++ b/tests/setup.py @@ -50,7 +50,7 @@ from loops.browser.node import ViewPropertiesConfigurator from loops.common import NameChooser from loops.concept import Concept from loops.concept import IndexAttributes as ConceptIndexAttributes -from loops.config.base import GlobalOptions, LoopsOptions, QueryOptions +from loops.config.base import GlobalOptions, LoopsOptions, QueryOptions, TypeOptions from loops.interfaces import ILoopsObject, IIndexAttributes from loops.interfaces import IDocument, IFile, ITextDocument from loops.layout.base import LayoutNode @@ -132,6 +132,7 @@ class TestSite(object): component.provideAdapter(BaseSecuritySetter) component.provideAdapter(LoopsOptions) component.provideAdapter(QueryOptions) + component.provideAdapter(TypeOptions) component.provideUtility(GlobalOptions()) component.provideAdapter(Instance)