[Zope3-checkins] CVS: Zope3/src/zope/products/content/browser - __init__.py:1.1.2.1 configure.zcml:1.1.2.1 document.gif:1.1.2.1 file.py:1.1.2.1 file_icon.gif:1.1.2.1 file_upload.hlp:1.1.2.1 folder.py:1.1.2.1 folder_icon.gif:1.1.2.1 fromFS.pt:1.1.2.1 fssync.py:1.1.2.1 i18n.py:1.1.2.1 i18n_edit.pt:1.1.2.1 i18nimage.py:1.1.2.1 i18nimageedit.pt:1.1.2.1 image.py:1.1.2.1 image_icon.gif:1.1.2.1 imageedit.pt:1.1.2.1 preview.pt:1.1.2.1

Philipp von Weitershausen philikon at philikon.de
Sun Feb 8 09:03:49 EST 2004


Update of /cvs-repository/Zope3/src/zope/products/content/browser
In directory cvs.zope.org:/tmp/cvs-serv10229/products/content/browser

Added Files:
      Tag: philikon-movecontent-branch
	__init__.py configure.zcml document.gif file.py file_icon.gif 
	file_upload.hlp folder.py folder_icon.gif fromFS.pt fssync.py 
	i18n.py i18n_edit.pt i18nimage.py i18nimageedit.pt image.py 
	image_icon.gif imageedit.pt preview.pt 
Log Message:
Move zope.app.content,
     zope.app.interfaces.content,
 and zope.app.browser.content
to zope.products.content and zope.products.codecontent, respectively.


=== Added File Zope3/src/zope/products/content/browser/__init__.py ===
#
# This file is necessary to make this directory a package.


=== Added File Zope3/src/zope/products/content/browser/configure.zcml ===
<zope:configure
   xmlns="http://namespaces.zope.org/browser"
   xmlns:zope="http://namespaces.zope.org/zope"
   xmlns:help="http://namespaces.zope.org/help">


  <view
      name="_traverse"
      for="zope.products.content.interfaces.file.IFileContent"
      class="zope.app.publication.traversers.FileContentTraverser"
      permission="zope.Public"
      />


<!-- File View Directives -->
  
  
  <editform
      name="edit.html"
      schema="zope.products.content.interfaces.file.IFile"
      label="Change a file"
      usage="objectview"
      permission="zope.ManageContent" 
      class=".file.FileTextEdit" 
      />

  <menuItem
      menu="zmi_views" title="Edit"
      for="zope.products.content.interfaces.file.IFile"
      action="edit.html"
      filter="python:context.contentType.startswith('text/')"
      permission="zope.ManageContent" />


  <editform
      name="upload.html"
      menu="zmi_views" title="Upload"
      schema="zope.products.content.interfaces.file.IFile"
      label="Upload a file"
      permission="zope.ManageContent"
      />

  <page
      for="zope.products.content.interfaces.file.IFile"
      name="preview.html"
      menu="zmi_views" title="Preview"
      template="preview.pt"
      permission="zope.ManageContent" />

  <page
      for="zope.products.content.interfaces.file.IFile"
      name="index.html"
      permission="zope.View"
      class=".file.FileView"
      attribute="show" />


  <addMenuItem
      class="zope.products.content.file.File"
      title="File"
      permission="zope.ManageContent"
      view="zope.products.content.file.File"
      />

  <addform
      schema="zope.products.content.interfaces.file.IFile"
      label="Add a File"
      content_factory="zope.products.content.file.File"
      name="zope.products.content.file.File"
      permission="zope.ManageContent"
      />


  <icon
      name="zmi_icon"
      for="zope.products.content.interfaces.file.IFile"
      file="file_icon.gif" />

  <help:register
      id="file_upload"
      title="File Upload Screen"
      parent="ui"
      for="zope.products.content.interfaces.file.IFile"
      view="upload.html"
      doc_path="./file_upload.hlp" />

<!-- I18n File View Directives -->

  <page
      name="index.html"
      for="zope.products.content.interfaces.i18nfile.II18nFile"
      permission="zope.View"
      class=".i18n.I18nFileView" />

  <pages
      for="zope.products.content.interfaces.i18nfile.II18nFile"
      permission="zope.View"
      class=".i18n.I18nFileEdit">

    <page name="editForm.html" template="i18n_edit.pt" />
    <page name="edit.html" attribute="action" />

  </pages>

  <menuItems menu="zmi_views"
      for="zope.products.content.interfaces.i18nfile.II18nFile">

      <!-- Keep original edit view, for now -->
      <menuItem title="Edit" action="editForm.html" />

      <!-- Supress the upload view from file -->
      <menuItem title="Upload" action="editForm.html"
                        filter="python: 0" />

  </menuItems>

  <menuItem menu="add_content"
      for="zope.app.interfaces.container.IAdding"
      title="I18n File"
      action="zope.products.content.I18nFile"
      description="A file that supports multiple locales."
      permission="zope.ManageContent"
      />

<!-- Image -->

  <editform
      schema="zope.products.content.image.IImage"
      name="upload.html"
      menu="zmi_views" title="Upload"
      label="Upload an image"
      permission="zope.ManageContent"
      class=".image.ImageUpload"
      template="imageedit.pt"
      />

  <page
      name="index.html"
      for="zope.products.content.image.IImage"
      permission="zope.View"
      allowed_attributes="__call__ tag"
      class=".image.ImageData"
      />

  <page
      for="zope.products.content.interfaces.image.IImage"
      name="preview.html"
      menu="zmi_views" title="Preview"
      template="preview.pt"
      permission="zope.ManageContent"
      />

  <icon
      name="zmi_icon"
      for="zope.products.content.image.IImage"
      file="image_icon.gif"
      />

  <addMenuItem
      class="zope.products.content.image.Image"
      title="Image"
      permission="zope.ManageContent"
      view="zope.products.content.image.Image"
      />

  <addform
      schema="zope.products.content.interfaces.image.IImage"
      label="Add a Image"
      content_factory="zope.products.content.image.Image"
      name="zope.products.content.image.Image"
      permission="zope.ManageContent"
      />


<!-- I18n Image -->

  <page
      name="index.html"
      for="zope.products.content.interfaces.i18nimage.II18nImage"
      permission="zope.View"
      allowed_attributes="__call__ tag"
      class=".i18nimage.I18nImageData"
      />

  <pages
      for="zope.products.content.i18nimage.II18nImage"
      permission="zope.ManageContent"
      class=".i18nimage.I18nImageEdit">

      <page name="upload.html" template="i18nimageedit.pt" />
      <page name="uploadAction.html" attribute="action" />

      </pages>

  <menuItems
      menu="zmi_views"
      for="zope.products.content.i18nimage.II18nImage"
      >

      <!-- Keep the old "edit" form -->
      <menuItem title="Edit" action="upload.html"/>

      <!-- Suppress upload form (from IFile) -->
      <menuItem title="Upload" action="upload.html"
                        filter="python: 0" />

  </menuItems>

  <menuItem
      menu="add_content"
      for="zope.app.interfaces.container.IAdding"
      title="I18n Image"
      action="I18nImage"
      description="A multi-locale version of an Image." 
      permission="zope.ManageContent"
      />


<!-- Folder View Directives -->
  <icon
      name="zmi_icon"
      for="zope.app.interfaces.folder.IFolder"
      file="folder_icon.gif" />

  <addMenuItem
      class="zope.app.folder.Folder"
      title="Folder"
      permission="zope.ManageContent"
      />

  <page
      name="contents.html"
      menu="zmi_views" title="Contents"
      for="zope.app.interfaces.folder.IFolder"
      permission="zope.ManageContent"
      class="zope.app.browser.container.contents.Contents"
      attribute="contents" />

  <page
      name="index.html"
      for="zope.app.interfaces.folder.IFolder"
      permission="zope.View"
      class="zope.app.browser.container.contents.Contents"
      attribute="index" />

  <page
      for="zope.app.interfaces.folder.IFolder"
      name="preview.html"
      menu="zmi_views" title="Preview"
      template="preview.pt"
      permission="zope.ManageContent" />

  <!-- ApplicationController navigation -->

  <menuItem 
      menu="zmi_actions"
      for="zope.app.interfaces.traversing.IContainmentRoot"
      title="Manage Process" 
      action="++etc++process/index.html" />


  <!-- toFS.snarf and fromFS.snarf views, for new fssync tools -->

  <!-- fssync checkout, update -->
  <page
      for="zope.interface.Interface"
      name="toFS.snarf"
      permission="zope.ManageServices"
      class=".fssync.SnarfFile"
      attribute="show" />

  <!-- fssync commit -->
  <page
      for="zope.interface.Interface"
      name="fromFS.snarf"
      permission="zope.ManageServices"
      class=".fssync.SnarfCommit"
      attribute="run" />

  <!-- fssync checkin -->
  <page
      for="zope.interface.Interface"
      name="checkin.snarf"
      permission="zope.ManageServices"
      class=".fssync.SnarfCheckin"
      attribute="run" />

</zope:configure>


=== Added File Zope3/src/zope/products/content/browser/document.gif ===
  <Binary-ish file>

=== Added File Zope3/src/zope/products/content/browser/file.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""File views.

$Id: file.py,v 1.1.2.1 2004/02/08 14:03:44 philikon Exp $
"""
from zope.app.browser.form.widget import BytesAreaWidget
from zope.app.form.widget import CustomWidgetFactory

__metaclass__ = type

class FileView:

    def show(self):
        """Call the File"""
        request = self.request
        if request is not None:
            request.response.setHeader('Content-Type',
                                       self.context.getContentType())
            request.response.setHeader('Content-Length',
                                       self.context.getSize())

        return self.context.getData()


class FileTextEdit:
    """File editing mix-in that uses a file-upload widget."""

    data_widget = CustomWidgetFactory(BytesAreaWidget)


=== Added File Zope3/src/zope/products/content/browser/file_icon.gif ===
  <Binary-ish file>

=== Added File Zope3/src/zope/products/content/browser/file_upload.hlp ===
This screen allows to upload new file data.

=== Added File Zope3/src/zope/products/content/browser/folder.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Felder-spcific view classes

$Id: folder.py,v 1.1.2.1 2004/02/08 14:03:44 philikon Exp $
"""
from zope.interface import implements
from zope.app.browser.container.adding import Adding
from zope.app.interfaces.content.folder import IFolderAdding

class FolderAdding(Adding):
    implements(IFolderAdding)


=== Added File Zope3/src/zope/products/content/browser/folder_icon.gif ===
  <Binary-ish file>

=== Added File Zope3/src/zope/products/content/browser/fromFS.pt ===
<html metal:use-macro="views/standard_macros/page">
<body>
<div metal:fill-slot="body">

  <h1 i18n:translate="">Commit Action</h1>

  <div tal:define="status view/update"
       tal:condition="status"
       i18n:translate="">
  Commit results:
  <pre tal:content="status" i18n:name="results">
    Status from update method goes here.
  </pre>
  </div>

  <p i18n:translate="">Upload a zipfile in the following form</p>

  <form method="post" action="@@fromFS.html" enctype="multipart/form-data">
    <input type="file" name="zipfile" size="40" />
    <input type="submit" value="Upload"
           i18n:attributes="value upload-button"/>
  </form>

</div>
</body>
</html>


=== Added File Zope3/src/zope/products/content/browser/fssync.py ===
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
# 
##############################################################################
"""Code for the toFS.snarf view and its inverse, fromFS.snarf.

$Id: fssync.py,v 1.1.2.1 2004/02/08 14:03:44 philikon Exp $
"""
import os
import cgi
import shutil
import tempfile

from transaction import get_transaction

from zope.app.publisher.browser import BrowserView
from zope.app.traversing import getName, getParent, getRoot
from zope.fssync.snarf import Snarfer, Unsnarfer
from zope.app.fssync import syncer
from zope.app.fssync.committer import Committer, Checker
from zope.fssync.metadata import Metadata

from zope.app.i18n import ZopeMessageIDFactory as _

def snarf_dir(response, dirname):
    """Helper to snarf a directory to the response."""
    response.setStatus(200)
    response.setHeader("Content-Type", "application/x-snarf")
    snf = Snarfer(response)
    snf.addtree(dirname)
    return ""

class SnarfFile(BrowserView):
    """View returning a snarfed representation of an object tree.

    This applies to any object (for="zope.interface.Interface").
    """

    def show(self):
        """Return the snarfed response."""
        dirname = tempfile.mktemp()
        try:
            os.mkdir(dirname)
            syncer.toFS(self.context,
                        getName(self.context) or "root",
                        dirname)
            return snarf_dir(self.request.response, dirname)
        finally:
            if os.path.isdir(dirname):
                shutil.rmtree(dirname)

class NewMetadata(Metadata):
    """Subclass of Metadata that sets the 'added' flag in all entries."""

    def getentry(self, file):
        entry = Metadata.getentry(self, file)
        if entry:
            entry["flag"] = "added"
        return entry


class SnarfSubmission(BrowserView):
    """Base class for the commit and checkin views."""

    def run(self):
        self.check_content_type()
        self.set_transaction()
        self.parse_args()
        self.set_note()
        try:
            self.make_tempdir()
            self.set_arguments()
            self.make_metadata()
            self.unsnarf_body()
            return self.run_submission()
        finally:
            self.remove_tempdir()

    def check_content_type(self):
        if not self.request.getHeader("Content-Type") == "application/x-snarf":
            raise ValueError(_("Content-Type is not application/x-snarf"))

    def set_transaction(self):
        self.txn = get_transaction()

    def parse_args(self):
        # The query string in the URL didn't get parsed, because we're
        # getting a POST request with an unrecognized content-type
        qs = self.request._environ.get("QUERY_STRING")
        if qs:
            self.args = cgi.parse_qs(qs)
        else:
            self.args = {}

    def get_arg(self, key):
        value = self.request.get(key)
        if value is None:
            values = self.args.get(key)
            if values is not None:
                value = " ".join(values)
        return value

    def set_note(self):
        note = self.get_arg("note")
        if note:
            self.txn.note(note)

    tempdir = None

    def make_tempdir(self):
        self.tempdir = tempfile.mktemp()
        os.mkdir(self.tempdir)

    def remove_tempdir(self):
        if self.tempdir and os.path.exists(self.tempdir):
            shutil.rmtree(self.tempdir)

    def unsnarf_body(self):
        fp = self.request.bodyFile
        fp.seek(0)
        uns = Unsnarfer(fp)
        uns.unsnarf(self.tempdir)

    def call_committer(self):
        c = Committer(syncer.getSerializer, self.metadata,
                      getAnnotations=syncer.getAnnotations)
        c.synch(self.container, self.name, self.fspath)


class SnarfCheckin(SnarfSubmission):
    """View for checking a new sub-tree into Zope.

    The input should be a POST request whose data is a snarf archive.
    This creates a brand new tree and doesn't return anything.
    """

    def run_submission(self):
        # XXX need to make sure the top-level name doesn't already
        # exist, or existing site data can get screwed
        self.call_committer()
        return ""

    def set_arguments(self):
        # Compute self.{name, container, fspath} for checkin()
        name = self.get_arg("name")
        if not name:
            raise ValueError(_("required argument 'name' missing"))
        src = self.get_arg("src")
        if not src:
            src = name
        self.container = self.context
        self.name = name
        self.fspath = os.path.join(self.tempdir, src)

    def make_metadata(self):
        self.metadata = NewMetadata()


class SnarfCommit(SnarfSubmission):
    """View for committing changes to an existing tree.

    The input should be a POST request whose data is a snarf archive.
    It returns an updated snarf archive, or a text document with
    errors.
    """

    def run_submission(self):
        self.call_checker()
        if self.errors:
            return self.send_errors()
        else:
            self.call_committer()
            self.write_to_filesystem()
            return self.send_archive()

    def set_arguments(self):
        # Compute self.{name, container, fspath} for commit()
        self.name = getName(self.context)
        self.container = getParent(self.context)
        if self.container is None and self.name == "":
            # Hack to get loading the root to work
            self.container = getRoot(self.context)
            self.fspath = os.path.join(self.tempdir, "root")
        else:
            self.fspath = os.path.join(self.tempdir, self.name)

    def make_metadata(self):
        self.metadata = Metadata()

    def get_checker(self, raise_on_conflicts=False):
        return Checker(syncer.getSerializer,
                       self.metadata,
                       raise_on_conflicts,
                       getAnnotations=syncer.getAnnotations)

    def call_checker(self):
        if self.get_arg("raise"):
            c = self.get_checker(True)
        else:
            c = self.get_checker()
        c.check(self.container, self.name, self.fspath)
        self.errors = c.errors()

    def send_errors(self):
        self.txn.abort()
        lines = [_("Up-to-date check failed:")]
        tempdir_sep = os.path.join(self.tempdir, "") # E.g. foo -> foo/
        for e in self.errors:
            lines.append(e.replace(tempdir_sep, ""))
        lines.append("")
        self.request.response.setHeader("Content-Type", "text/plain")
        return "\n".join(lines)

    def write_to_filesystem(self):
        shutil.rmtree(self.tempdir) # Start with clean slate
        os.mkdir(self.tempdir)
        syncer.toFS(self.context,
                    getName(self.context) or "root",
                    self.tempdir)

    def send_archive(self):
        return snarf_dir(self.request.response, self.tempdir)


=== Added File Zope3/src/zope/products/content/browser/i18n.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""I18n versions of several content objects.

$Id: i18n.py,v 1.1.2.1 2004/02/08 14:03:44 philikon Exp $
"""
from zope.i18n.negotiator import negotiator


class I18nFileView:

    def __call__(self):
        """Call the File"""
        request = self.request
        language = None
        if request is not None:
            langs = self.context.getAvailableLanguages()
            language = negotiator.getLanguage(langs, request)

            request.response.setHeader('Content-Type',
                                       self.context.getContentType())
            request.response.setHeader('Content-Length',
                                       self.context.getSize(language))

        return self.context.getData(language)


class I18nFileEdit:

    name = 'editForm'
    title = 'Edit Form'
    description = ('This edit form allows you to make changes to the ' +
                   'properties of this file.')

    def action(self, contentType, data, language, defaultLanguage,
               selectLanguage=None, removeLanguage=None,
               addLanguage=None, newLanguage=None):
        if selectLanguage:
            pass
        elif removeLanguage:
            self.context.removeLanguage(language)
            language = self.context.getDefaultLanguage()
        else:
            if addLanguage:
                language = newLanguage
            self.context.setDefaultLanguage(defaultLanguage)
            self.context.edit(data, contentType, language)
        return self.request.response.redirect(self.request.URL[-1] +
                      "/editForm.html?language=%s" %language)  # XXX url_quote


=== Added File Zope3/src/zope/products/content/browser/i18n_edit.pt ===
<html metal:use-macro="views/standard_macros/page">
<head>
  <style metal:fill-slot="headers" type="text/css">
    <!--
    .ContentIcon {
        width: 20px;
    }

    .ContentTitle {
        text-align: left;
    }
    -->
  </style>
</head>

<body>
<div metal:fill-slot="body">

  <p tal:content="context/msg"
     tal:condition="python: hasattr(context, 'msg')">
    Message will go here.
  </p>

  <p tal:content="view/description">
    Description of the Form.
  </p>

  <form action="edit.html" method="post">

    <div class="row">
      <div class="label" i18n:translate="">Content Type</div>
      <div class="field">
        <input name="contentType" type="text" size="20"
               tal:attributes="value context/getContentType" />
      </div>
    </div>
    
    <div class="row">
      <div class="label" i18n:translate="">Default Language</div>
      <div class="field">
        <select name="defaultLanguage">
          <span tal:repeat="lang context/getAvailableLanguages"
                tal:omit-tag="">
          <option tal:attributes="
                      value lang;
                      selected python:context.getDefaultLanguage() == lang"
                  tal:content="lang" />
         </span>
        </select>
      </div>
    </div>
    <hr />
    <div class="row">
      <div class="label" i18n:translate="">Language</div>
      <div class="field">
        <select name="language">
          <span tal:repeat="lang context/getAvailableLanguages"
                tal:omit-tag="">
          <option tal:attributes="
                      value lang;
                      selected python:request.get('language',
                                      context.getDefaultLanguage()) == lang"
                  tal:content="lang" />
         </span>
        </select>
        <input type="submit" name="selectLanguage" value="Show" 
               i18n:attributes="value show-button"/>
        <input type="submit" name="removeLanguage"
               i18n:attributes="value remove-button"/>
        &nbsp;&nbsp;
        <input type="submit" name="addLanguage"
               value="Add new language"
               i18n:attributes="value" />
        <input type="text" name="newLanguage" size="10" />
      </div>
    </div>
    <div class="row">
      <div class="label" i18n:translate="">Data</div>
      <div class="field">
        <textarea name="data" cols="70" rows="10"
             tal:content="python:context.getData(request.get('language'))" />
      </div>
    </div>

    <div class="row">
      <div class="controls">
        <input type="submit" name="edit" value="Save Changes" 
               i18n:attributes="value save-changes-button"/>
      </div>
    </div>

  </form>

</div>
</body>
</html>




=== Added File Zope3/src/zope/products/content/browser/i18nimage.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Define view component for image editing.

$Id: i18nimage.py,v 1.1.2.1 2004/02/08 14:03:44 philikon Exp $
"""
from zope.i18n.negotiator import negotiator
from zope.app.i18n import ZopeMessageIDFactory as _

from image import ImageData

class I18nImageEdit:

    name = 'editForm'
    title = _('Edit Form')
    description = _('This edit form allows you to make changes to the ' +
                   'properties of this image.')

    def getImageSize(self, language=None):
        # XXX Change to ISizeable adapter
        size = self.context.getImageSize(language)
        return "%d x %d" % (size[0], size[1])

    def action(self, contentType, data, language, defaultLanguage,
               selectLanguage=None, removeLanguage=None,
               addLanguage=None, newLanguage=None):
        if selectLanguage:
            pass
        elif removeLanguage:
            self.context.removeLanguage(language)
            language = self.context.getDefaultLanguage()
        else:
            if addLanguage:
                language = newLanguage
            self.context.setDefaultLanguage(defaultLanguage)
            self.context.edit(data, contentType, language)
        return self.request.response.redirect(self.request.URL[-1] +
                      "/editForm.html?language=%s" % language)  # XXX url_quote


class I18nImageData(ImageData):

    def __call__(self):
        image = self.context
        language = None
        if self.request is not None:
            langs = self.context.getAvailableLanguages()
            language = negotiator.getLanguage(langs, self.request)

            self.request.response.setHeader('content-type',
                                                 image.getContentType())
            # XXX: no content-length?  See ImageData.__call__
        return image.getData(language)


    def tag(self, height=None, width=None, **args):
        """See ImageData.tag."""

        language = None
        if self.request is not None and \
           (width is None or height is None):
            langs = self.context.getAvailableLanguages()
            language = negotiator.getLanguage(langs, self.request)

        if width is None:
            width = self.context.getImageSize(language)[0]
        if height is None:
            height = self.context.getImageSize(language)[1]
        return ImageData.tag(self, width=width, height=height, **args)


=== Added File Zope3/src/zope/products/content/browser/i18nimageedit.pt ===
<html metal:use-macro="views/standard_macros/page">
<head>
  <style metal:fill-slot="headers" type="text/css">
    <!--
    .ContentIcon {
        width: 20px;
    }

    .ContentTitle {
        text-align: left;
    }
    -->
  </style>
</head>

<body>
<div metal:fill-slot="body">


  <p tal:content="options/msg | nothing">
    Message will go here.
  </p>

  <p tal:content="view/description">
    Description of the Form.
  </p>

  <form action="uploadAction.html" method="post" 
        enctype="multipart/form-data">

    <div class="row">
      <div class="label" i18n:translate="">Content Type</div>
      <div class="field">
        <input name="contentType" type="text" size="20"
               tal:attributes="value context/getContentType" />
      </div>
    </div>
    
    <div class="row">
      <div class="label" i18n:translate="">Default Language</div>
      <div class="field">
        <select name="defaultLanguage">
          <span tal:repeat="lang context/getAvailableLanguages"
                tal:omit-tag="">
          <option tal:attributes="
                      value lang;
                      selected python:context.getDefaultLanguage() == lang"
                  tal:content="lang" />
         </span>
        </select>
      </div>
    </div>
    <hr />
    <div class="row">
      <div class="label" i18n:translate="">Language</div>
      <div class="field">
        <select name="language">
          <span tal:repeat="lang context/getAvailableLanguages"
                tal:omit-tag="">
          <option tal:attributes="
                      value lang;
                      selected python:request.get('language',
                                      context.getDefaultLanguage()) == lang"
                  tal:content="lang" />
         </span>
        </select>
        <input type="submit" name="selectLanguage" value="Show" 
               i18n:attributes="value show-button"/>
        <input type="submit" name="removeLanguage"
               i18n:attributes="value remove-button"/>
        &nbsp;&nbsp;
        <input type="submit" name="addLanguage"
               value="Add new language"
               i18n:attributes="value" />
        <input type="text" name="newLanguage" size="10" />
      </div>
    </div>
    <div class="row">
      <div class="label" i18n:translate="">Data</div>
      <div class="field">
        <input type="file" name="data" size="20" />
      </div>
    </div>
    <div class="row">
      <div class="label" i18n:translate="">Dimensions</div>
      <div class="field"
          tal:content="python:view.getImageSize(request.get('language'))">
        40 x 40
      </div>
    </div>
    <div class="row">
      <div class="label" i18n:translate="">Dimensions</div>
      <div class="field"
          tal:content="python:view.getSize(request.get('language'))">
        40 kB
      </div>
    </div>

    <div class="row">
      <div class="controls">
        <input type="submit" name="edit" value="Save Changes" 
               i18n:attributes="value save-changes-button"/>
      </div>
    </div>

  </form>

</div>
</body>
</html>


=== Added File Zope3/src/zope/products/content/browser/image.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Define view component for naive file editing.

$Id: image.py,v 1.1.2.1 2004/02/08 14:03:44 philikon Exp $
"""
from zope.app.size import byteDisplay
from zope.app.event.objectevent import ObjectModifiedEvent
from zope.app.event import publish
from zope.app.publisher.browser import BrowserView

class ImageData(BrowserView):

    def __call__(self):
        image = self.context
        if self.request is not None:
            self.request.response.setHeader('content-type',
                                            image.getContentType())
        return image.getData()

    def tag(self, height=None, width=None, alt=None,
            scale=0, xscale=0, yscale=0, css_class=None, **args):
        """
        Generate an HTML IMG tag for this image, with customization.
        Arguments to self.tag() can be any valid attributes of an IMG tag.
        'src' will always be an absolute pathname, to prevent redundant
        downloading of images. Defaults are applied intelligently for
        'height', 'width', and 'alt'. If specified, the 'scale', 'xscale',
        and 'yscale' keyword arguments will be used to automatically adjust
        the output height and width values of the image tag.

        Since 'class' is a Python reserved word, it cannot be passed in
        directly in keyword arguments which is a problem if you are
        trying to use 'tag()' to include a CSS class. The tag() method
        will accept a 'css_class' argument that will be converted to
        'class' in the output tag to work around this.
        """
        if width is None:
            width = self.context.getImageSize()[0]
        if height is None:
            height = self.context.getImageSize()[1]

        # Auto-scaling support
        xdelta = xscale or scale
        ydelta = yscale or scale

        if xdelta and width:
            width = str(int(round(int(width) * xdelta)))
        if ydelta and height:
            height = str(int(round(int(height) * ydelta)))

        result = '<img src="%s"' % (self.absolute_url())

        if alt is None:
            alt = getattr(self, 'title', '')
        result = '%s alt="%s"' % (result, alt)

        if height is not None:
            result = '%s height="%s"' % (result, height)

        if width is not None:
            result = '%s width="%s"' % (result, width)

        if not 'border' in [a.lower() for a in args.keys()]:
            result = '%s border="0"' % result

        if css_class is not None:
            result = '%s class="%s"' % (result, css_class)

        for key in args.keys():
            value = args.get(key)
            result = '%s %s="%s"' % (result, key, value)

        return '%s />' % result


class ImageUpload:
    """Image edit view mix-in that provides access to image size info"""

    def size(self):
        sx, sy = self.context.getImageSize()
        if sx < 0:
            sx = '?'
        if sy < 0:
            sy = '?'
        return "%s x %s pixels, %s" % (
                sx, sy, byteDisplay(self.context.getSize())
                )

    def apply_update(self, data):
        """Apply user inputs

        These inputs have already been validated.

        Return a boolean indicating whether we changed anything,
        """

        unchanged = True

        # if we can compute the content type from the raw data, then
        # that overrides what the user provided, so set the content
        # type first.

        contentType = data.get('contentType')
        if contentType and contentType != self.context.contentType:
            self.context.contentType = contentType
            unchanged = False

        if 'data' in data:
            self.context.data = data['data']
            unchanged = False

        if not unchanged:
            publish(self.context, ObjectModifiedEvent(self.context))

        return unchanged


=== Added File Zope3/src/zope/products/content/browser/image_icon.gif ===
  <Binary-ish file>

=== Added File Zope3/src/zope/products/content/browser/imageedit.pt ===
<html metal:use-macro="views/standard_macros/page">
<body>
<div metal:fill-slot="body">

  <div metal:use-macro="view/generated_form/macros/body">

  <form action=".">   

    <table metal:fill-slot="extra_top">
      <tr>
        <td i18n:translate="">Size</td>
        <td tal:content="view/size" i18n:translate=""
           >103 x 45 pixels, 43KB</td>            
      </tr>
    </table>

    <input type="submit" name="save" value="Save Changes" 
        i18n:attributes="value save-changes-button"/>

  </form>

  </div>
</div>
</body>

</html>


=== Added File Zope3/src/zope/products/content/browser/preview.pt ===
<html metal:use-macro="views/standard_macros/page">
<body>
<div metal:fill-slot="body">

  <iframe src="." height="98%" width="98%"></iframe>

</div>
</body>
</html>




More information about the Zope3-Checkins mailing list