merge branch master

This commit is contained in:
Helmut Merz 2012-10-15 08:20:14 +02:00
commit d50498bdaf
17 changed files with 114 additions and 40 deletions

View file

@ -413,7 +413,7 @@ class ConceptView(BaseView):
if r.order != pos:
r.order = pos
def resources(self):
def getResources(self):
form = self.request.form
#if form.get('loops.viewName') == 'index.html' and self.editable:
if self.editable:
@ -430,6 +430,9 @@ class ConceptView(BaseView):
if fv.check(r.first):
yield ResourceRelationView(r, self.request, contextIsSecond=True)
def resources(self):
return self.getResources()
@Lazy
def resourcesList(self):
from loops.browser.resource import ResourceRelationView

View file

@ -1,5 +1,5 @@
#
# Copyright (c) 2011 Helmut Merz helmutm@cy55.de
# Copyright (c) 2012 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
@ -98,7 +98,7 @@ class AdapterBase(object):
adapts(IConcept)
_adapterAttributes = ('context', '__parent__')
_adapterAttributes = ('context', '__parent__', 'request')
_contextAttributes = list(IConcept)
_noexportAttributes = ()
_textIndexAttributes = ()
@ -106,6 +106,7 @@ class AdapterBase(object):
__is_dummy__ = False
__type__ = None
request = None
languageInfo = None
def __init__(self, context):

View file

@ -77,6 +77,30 @@ class SectionView(Base, ConceptView):
def sectionType(self):
return self.conceptManager['section']
def getResources(self):
relViews = super(SectionView, self).getResources()
return relViews
@Lazy
def textResources(self):
self.images = [[]]
result = []
idx = 0
for rv in self.getResources():
if rv.context.contentType.startswith('text/'):
idx += 1
result.append(rv)
self.images.append([])
else:
self.registerDojoLightbox()
url = self.nodeView.getUrlForTarget(rv.context)
src = '%s/mediaasset.html?v=small' % url
fullSrc = '%s/mediaasset.html?v=medium' % url
img = dict(src=src, fullImageUrl=fullSrc, title=rv.title,
description=rv.description, url=url, object=rv)
self.images[idx].append(img)
return result
def getCssClassForResource(self, r):
for c in r.context.getConcepts([self.defaultPredicate]):
if c.conceptType == self.documentTypeType:

View file

@ -21,6 +21,7 @@ concept(u'issubtype', u'is Subtype', u'predicate', options=u'hide_children',
# document types
concept(u'keyquestions', u'Leitfragen', u'documenttype')
concept(u'textelement', u'Textabschnitt', u'documenttype')
concept(u'textelement2', u'Textabschnitt separat', u'documenttype')
concept(u'quote', u'Zitat', u'documenttype')
concept(u'story', u'Geschichte', u'documenttype')
concept(u'usecase', u'Fallbeispiel', u'documenttype')

View file

@ -14,7 +14,7 @@
<metal:section define-macro="section">
<metal:info use-macro="view/concept_macros/concepttitle" />
<div tal:repeat="related item/resources">
<div tal:repeat="related item/textResources">
<div class="span-4">
<div tal:attributes="class python:
item.getCssClassForResource(related)"
@ -36,7 +36,8 @@
string:$resourceBase/cybertools.icons/vcard_edit.png" /></a>
<a i18n:translate="" i18n:attributes="title"
title="Edit with external editor."
tal:condition="related/xeditable"
xxtal:condition="related/xeditable"
tal:condition="nothing"
tal:attributes="href string:$url/external_edit?version=this">
<img tal:attributes="src
string:$resourceBase/cybertools.icons/application_edit.png" /></a>
@ -45,6 +46,15 @@
<a tal:content="parent/title"
tal:attributes="href python:view.getUrlForTarget(parent)" />
</div>
<div tal:repeat="image python:
item.images[repeat['related'].index() + 1]">
<a dojoType="dojox.image.Lightbox" group="mediasset"
i18n:attributes="title"
tal:attributes="href image/fullImageUrl;
title image/title">
<img tal:attributes="src image/src;
alt image/title" /></a>
</div>
</div>
</div>
</metal:section>

View file

@ -231,7 +231,7 @@ Extracting Document Properties from MS Office Files
>>> path = os.path.join(dataDir, 'office')
>>> fn = os.path.join(path, 'example.docx')
>>> os.path.getsize(fn)
20337...
23561...
>>> officeFile = addAndConfigureObject(resources, Resource, 'test.docx',
... title=u'Example Word File', resourceType=tOfficeFile,
@ -241,7 +241,7 @@ Extracting Document Properties from MS Office Files
>>> content = aOfficeFile.data
>>> len(content)
17409
20327
Clean up:
>>> shutil.copy(fn + '.sav', fn)

View file

@ -1,5 +1,5 @@
#
# Copyright (c) 2008 Helmut Merz helmutm@cy55.de
# Copyright (c) 2012 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
@ -18,8 +18,6 @@
"""
View class(es) for integrating external objects.
$Id$
"""
from zope import interface, component
@ -42,7 +40,9 @@ class ExternalCollectionView(ConceptView):
def update(self):
if 'update' in self.request.form:
cta = adapted(self.context)
if cta is not None:
cta.request = self.request
cta.update()
if cta.updateMessage is not None:
self.request.form['message'] = cta.updateMessage
return True

View file

@ -1,5 +1,5 @@
#
# Copyright (c) 2009 Helmut Merz helmutm@cy55.de
# Copyright (c) 2012 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
@ -19,8 +19,6 @@
"""
Concept adapter(s) for external collections, e.g. a directory in the
file system.
$Id$
"""
from datetime import datetime
@ -62,10 +60,12 @@ class ExternalCollectionAdapter(AdapterBase):
implements(IExternalCollection)
adapts(IConcept)
_adapterAttributes = ('context', '__parent__', 'exclude', 'newResources')
_adapterAttributes = AdapterBase._adapterAttributes + (
'exclude', 'newResources', 'updateMessage')
_contextAttributes = list(IExternalCollection) + list(IConcept)
newResources = None
updateMessage = None
def getExclude(self):
return getattr(self.context, '_exclude', None) or []
@ -101,12 +101,17 @@ class ExternalCollectionAdapter(AdapterBase):
adobj = adapted(obj)
directory = provider.getDirectory(self)
adobj.storageParams=dict(subdirectory=directory)
adobj.request = self.request
adobj.externalAddress = addr
# collect error information
if adobj.processingErrors:
message = self.updateMessage or u''
message += u'<br />'.join(adobj.processingErrors)
self.updateMessage = message
# force reindexing
notify(ObjectModifiedEvent(obj))
else:
new.append(addr)
#print '*** new', new
if new:
self.newResources = provider.createExtFileObjects(self, new)
for r in self.newResources:
@ -205,7 +210,13 @@ class DirectoryCollectionProvider(object):
contentType=contentType,
)
adobj = adapted(obj)
adobj.request = client.request
adobj.externalAddress = addr # must be set last
# collect error information
if adobj.processingErrors:
message = client.updateMessage or u''
message += u'<br />'.join(adobj.processingErrors)
client.updateMessage = message
yield obj
def getDirectory(self, client):

View file

@ -7,6 +7,10 @@
<metal:block use-macro="view/concept_macros/conceptdata">
<metal:fill tal:condition="item/editable"
fill-slot="fields">
<div class="error"
tal:define="message view/message | request/message | nothing"
tal:condition="message"
tal:content="structure message" />
<metal:block use-macro="view/concept_macros/conceptfields" />
<form method="post">
<input type="submit" name="update" value="Update Collection" />

View file

@ -1,5 +1,5 @@
#
# Copyright (c) 2010 Helmut Merz helmutm@cy55.de
# Copyright (c) 2012 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
@ -18,8 +18,6 @@
"""
Resource adapter(s) for MS Office files.
$Id$
"""
from datetime import date, datetime, timedelta
@ -56,6 +54,7 @@ class OfficeFile(ExternalFileAdapter):
propertyMap = {u'Revision:': 'version'}
propFileName = 'docProps/custom.xml'
corePropFileName = 'docProps/core.xml'
fileExtensions = ('.docm', '.docx', 'dotm', 'dotx', 'pptx', 'potx', 'ppsx',
'.xlsm', '.xlsx', '.xltm', '.xltx')
@ -88,20 +87,32 @@ class OfficeFile(ExternalFileAdapter):
from logging import getLogger
self.logger.warn(e)
return []
if self.corePropFileName not in zf.namelist():
self.logger.warn('Core properties not found in file %s.' %
self.externalAddress)
if self.propFileName not in zf.namelist():
self.logger.warn('Custom properties not found in file %s.' %
self.externalAddress)
propsXml = zf.read(self.propFileName)
corePropsXml = zf.read(self.corePropFileName)
# TODO: read core.xml, return both trees in dictionary
zf.close()
return etree.fromstring(propsXml)
return {'custom': etree.fromstring(propsXml),
'core': etree.fromstring(corePropsXml)}
def getDocProperty(self, pname):
for p in self.docPropertyDom:
for p in self.docPropertyDom['custom']:
name = p.attrib.get('name')
if name == pname:
return p[0].text
return None
def getCoreProperty(self, pname):
for p in self.docPropertyDom['core']:
if p.tag.endswith(pname):
return p.text
return None
def processDocument(self):
changed = False
docVersion = None
@ -109,11 +120,14 @@ class OfficeFile(ExternalFileAdapter):
strType = ('{http://schemas.openxmlformats.org/'
'officeDocument/2006/docPropsVTypes}lpwstr')
attributes = {}
dom = self.docPropertyDom
# get dc:description from core.xml
desc = self.getCoreProperty('description')
if desc is not None:
attributes['comments'] = desc
dom = self.docPropertyDom['custom']
for p in dom:
name = p.attrib.get('name')
value = p[0].text
#print '***', self.externalAddress, name, value, p[0].tag
attr = self.propertyMap.get(name)
if attr == 'version':
docVersion = value
@ -136,7 +150,9 @@ class OfficeFile(ExternalFileAdapter):
newZf.writestr(self.propFileName, etree.tostring(dom))
newZf.close()
shutil.move(newFn, fn)
self.update(attributes)
errors = self.update(attributes)
if errors:
self.processingErrors = errors
def update(self, attributes):
# to be implemented by subclass
@ -146,10 +162,10 @@ class OfficeFile(ExternalFileAdapter):
def parseDate(s):
if not s:
return None
try:
tt = strptime(s, '%Y-%m-%dT%H:%M:%SZ')
#try:
# tt = strptime(s, '%Y-%m-%dT%H:%M:%SZ')
#except ValueError:
except ValueError:
return None
# try:
# tt = strptime(s, '%d.%m.%y')
# except ValueError:

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: $Id$\n"
"POT-Creation-Date: 2007-05-22 12:00 CET\n"
"PO-Revision-Date: 2012-08-20 12:00 CET\n"
"PO-Revision-Date: 2012-09-17 12:00 CET\n"
"Last-Translator: Helmut Merz <helmutm@cy55.de>\n"
"Language-Team: loops developers <helmutm@cy55.de>\n"
"MIME-Version: 1.0\n"
@ -758,6 +758,9 @@ msgstr "Kommentare"
msgid "Add Comment"
msgstr "Kommentar hinzufügen"
msgid "Subject"
msgstr "Thema"
msgid "Selection using: $targets"
msgstr "Auswahl über: $targets"

View file

@ -1,5 +1,5 @@
#
# Copyright (c) 2008 Helmut Merz helmutm@cy55.de
# Copyright (c) 2012 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
@ -18,8 +18,6 @@
"""
Definition of view classes and other browser related stuff for comments.
$Id$
"""
from zope import interface, component
@ -52,6 +50,8 @@ class CommentsView(NodeView):
@Lazy
def allowed(self):
if self.isAnonymous:
return False
return (self.virtualTargetObject is not None and
self.globalOptions('organize.allowComments'))
@ -120,8 +120,8 @@ class CreateComment(EditObject):
def update(self):
form = self.request.form
subject = form.get('subject')
text = form.get('text')
if not subject or not text or self.personId is None or self.object is None:
text = form.get('text') or u''
if not subject or self.personId is None or self.object is None:
return True
#contentType = form.get('contentType') or 'text/restructured'
rm = self.view.loopsRoot.getRecordManager()

View file

@ -58,7 +58,7 @@
</div>
<div class="buttons">
<input value="Save" type="submit"
onClick="return closeDialog(true)"
onClick="if (not this.validate()) return False; return closeDialog(true)"
i18n:attributes="value">
<input type="button" value="Cancel"
onClick="return closeDialog(false)"

View file

@ -1,5 +1,5 @@
#
# Copyright (c) 2011 Helmut Merz helmutm@cy55.de
# Copyright (c) 2012 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
@ -18,8 +18,6 @@
"""
Definition of the Concept class.
$Id$
"""
from cStringIO import StringIO
@ -352,7 +350,10 @@ class ExternalFileAdapter(FileAdapter):
implements(IExternalFile)
_adapterAttributes = (FileAdapter._adapterAttributes
+ ('storageParams', 'externalAddress', 'uniqueAddress'))
+ ('storageParams', 'externalAddress', 'uniqueAddress',
'processingErrors'))
processingErrors = []
def getStorageParams(self):
params = getattr(self.context, '_storageParams', None)