Merge branch 'master' into bbmaster

This commit is contained in:
Helmut Merz 2012-01-23 11:11:31 +01:00
commit 3132fc9947
6 changed files with 91 additions and 11 deletions

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 # 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 # it under the terms of the GNU General Public License as published by
@ -58,6 +58,7 @@ from cybertools.relation.interfaces import IRelationRegistry
from cybertools.stateful.interfaces import IStateful from cybertools.stateful.interfaces import IStateful
from cybertools.text import mimetypes from cybertools.text import mimetypes
from cybertools.typology.interfaces import IType, ITypeManager from cybertools.typology.interfaces import IType, ITypeManager
from cybertools.util.jeep import Jeep
from loops.browser.util import normalizeForUrl from loops.browser.util import normalizeForUrl
from loops.common import adapted, baseObject from loops.common import adapted, baseObject
from loops.config.base import DummyOptions from loops.config.base import DummyOptions
@ -74,7 +75,7 @@ from loops.versioning.interfaces import IVersionable
concept_macros = ViewPageTemplateFile('concept_macros.pt') concept_macros = ViewPageTemplateFile('concept_macros.pt')
conceptMacrosTemplate = concept_macros # conceptMacrosTemplate = concept_macros
resource_macros = ViewPageTemplateFile('resource_macros.pt') resource_macros = ViewPageTemplateFile('resource_macros.pt')
@ -84,14 +85,28 @@ class NameField(schema.ASCIILine):
super(NameField, self)._validate(value) super(NameField, self)._validate(value)
class ViewMode(object):
def __init__(self, name='view', title=None, url=None, active=False,
description=u''):
self.name = name
self.title = title
self.url = url
self.active = active
self.description = description
@property
def cssClass(self):
return self.active and u'active' or u'inactive'
class IAddForm(Interface): class IAddForm(Interface):
name = NameField( name = NameField(
title=_(u'Object name'), title=_(u'Object name'),
description=_(u'Name of the object - will be used for addressing the ' description=_(u'Name of the object - will be used for addressing the '
'object via a URL; should therefore be unique within ' u'object via a URL; should therefore be unique within '
'the container and not contain special characters') u'the container and not contain special characters'))
)
class AddForm(form.AddForm): class AddForm(form.AddForm):
@ -115,6 +130,7 @@ class BaseView(GenericView, I18NView):
actions = {} actions = {}
icon = None icon = None
modeName = 'view'
def __init__(self, context, request): def __init__(self, context, request):
super(BaseView, self).__init__(context, request) super(BaseView, self).__init__(context, request)
@ -148,6 +164,9 @@ class BaseView(GenericView, I18NView):
def breadcrumbs(self): def breadcrumbs(self):
return [] return []
def viewModes(self):
return Jeep()
@Lazy @Lazy
def name(self): def name(self):
return getName(self.context) return getName(self.context)

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 # 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 # it under the terms of the GNU General Public License as published by
@ -48,10 +48,11 @@ from cybertools.browser.action import Action
from cybertools.browser.view import GenericView from cybertools.browser.view import GenericView
from cybertools.stateful.interfaces import IStateful from cybertools.stateful.interfaces import IStateful
from cybertools.typology.interfaces import IType, ITypeManager from cybertools.typology.interfaces import IType, ITypeManager
from cybertools.util.jeep import Jeep
from cybertools.xedit.browser import ExternalEditorView from cybertools.xedit.browser import ExternalEditorView
from loops.browser.action import actions, DialogAction from loops.browser.action import actions, DialogAction
from loops.common import adapted, AdapterBase from loops.common import adapted, AdapterBase
from loops.i18n.browser import i18n_macros from loops.i18n.browser import i18n_macros, LanguageInfo
from loops.interfaces import IConcept, IResource, IDocument, IMediaAsset, INode from loops.interfaces import IConcept, IResource, IDocument, IMediaAsset, INode
from loops.interfaces import IViewConfiguratorSchema from loops.interfaces import IViewConfiguratorSchema
from loops.resource import MediaAsset from loops.resource import MediaAsset
@ -113,6 +114,11 @@ class NodeView(BaseView):
data.extend(self.virtualTarget.breadcrumbs()) data.extend(self.virtualTarget.breadcrumbs())
return data return data
def viewModes(self):
if self.virtualTarget:
return self.virtualTarget.viewModes()
return Jeep()
def recordAccess(self, viewName=''): def recordAccess(self, viewName=''):
target = self.virtualTargetObject target = self.virtualTargetObject
targetUid = target is not None and util.getUidForObject(target) or '' targetUid = target is not None and util.getUidForObject(target) or ''
@ -911,6 +917,15 @@ class NodeTraverser(ItemTraverser):
# we'll use the target object in the node's context # we'll use the target object in the node's context
viewAnnotations['target'] = target viewAnnotations['target'] = target
return self.context return self.context
target = viewAnnotations.get('target')
if target is not None: # name may be a view name for target
langInfo = LanguageInfo(self.context, request)
adTarget = adapted(target, langInfo)
view = component.queryMultiAdapter((adTarget, request), name=name)
if view is not None:
viewAnnotations['targetView'] = view
view.logInfo('NodeTraverser:targetView = %r' % view)
return self.context
obj = super(NodeTraverser, self).publishTraverse(request, name) obj = super(NodeTraverser, self).publishTraverse(request, name)
return obj return obj

View file

@ -240,6 +240,21 @@
</metal:actions> </metal:actions>
<metal:actions define-macro="view_modes">
<ul class="view-modes"
tal:define="viewModes view/viewModes"
tal:condition="viewModes">
<li tal:repeat="mode viewModes"
tal:attributes="class mode/cssClass">
<a tal:attributes="href mode/url;
title mode/description"
tal:content="mode/title"
i18n:translate="" />
</li>
</ul>
</metal:actions>
<metal:actions define-macro="page_actions"> <metal:actions define-macro="page_actions">
<div class="page-actions" <div class="page-actions"
tal:define="pageActions python:view.globalOptions('action.page') or []" tal:define="pageActions python:view.globalOptions('action.page') or []"

View file

@ -44,6 +44,7 @@
</metal:breadcrumbs> </metal:breadcrumbs>
<div metal:define-slot="actions"></div> <div metal:define-slot="actions"></div>
<div metal:define-slot="message"></div> <div metal:define-slot="message"></div>
<metal:tabs use-macro="views/node_macros/view_modes" />
<metal:content define-slot="content"> <metal:content define-slot="content">
<tal:content define="item nocall:view/item; <tal:content define="item nocall:view/item;
level level|python: 1; level level|python: 1;

View file

@ -4,12 +4,42 @@
*/ */
/* positioning of page sections */ /* page sections */
#portlets { #portlets {
margin-top: 1em; margin-top: 1em;
} }
ul.view-modes {
padding: 0 0 0 2em;
margin: 0.7em 0 0 0;
white-space: nowrap;
list-style-type: none;
border-bottom: #ccc 1px solid;
background-color: transparent;
}
ul.view-modes li {
display: inline
}
ul.view-modes li a {
padding: 0.15em 1.25em 0.15em 1.25em;
margin: 0 0.5em 0 0;
text-decoration: none;
border: #ccc 1px solid;
background-color: transparent;
}
ul.view-modes li.active a {
border-bottom: #eee 1px solid;
background-color: #eee;
}
ul.view-modes li.inactive a:hover {
background-color: #f8f8f8;
}
/* general */ /* general */
h1, h2, h3, h4, h5, h6 { h1, h2, h3, h4, h5, h6 {

View file

@ -1,7 +1,5 @@
""" """
Set up a loops site for testing. Set up a loops site for testing.
$Id$
""" """
from zope import component from zope import component
@ -57,13 +55,14 @@ from cybertools.wiki.dcu.rstx import Parser as DocutilsRstxParser
from loops.base import Loops from loops.base import Loops
from loops import util from loops import util
from loops.browser.node import ViewPropertiesConfigurator from loops.browser.node import ViewPropertiesConfigurator
from loops.browser.concept import ConceptView
from loops.common import NameChooser from loops.common import NameChooser
from loops.concept import Concept from loops.concept import Concept
from loops.concept import IndexAttributes as ConceptIndexAttributes from loops.concept import IndexAttributes as ConceptIndexAttributes
from loops.config.base import GlobalOptions, LoopsOptions from loops.config.base import GlobalOptions, LoopsOptions
from loops.config.base import QueryOptions, PredicateOptions, TypeOptions from loops.config.base import QueryOptions, PredicateOptions, TypeOptions
from loops.interfaces import ILoopsObject, IIndexAttributes from loops.interfaces import ILoopsObject, IIndexAttributes
from loops.interfaces import IDocument, IFile, ITextDocument from loops.interfaces import IConcept, IDocument, IFile, ITextDocument
from loops.interfaces import IIsSubtype from loops.interfaces import IIsSubtype
from loops.layout.base import LayoutNode from loops.layout.base import LayoutNode
from loops.organize.memberinfo import MemberInfoProvider from loops.organize.memberinfo import MemberInfoProvider
@ -133,6 +132,7 @@ class TestSite(object):
name='zope.source.rest') name='zope.source.rest')
component.provideAdapter(ReStructuredTextToHTMLRenderer, component.provideAdapter(ReStructuredTextToHTMLRenderer,
(IReStructuredTextSource, IBrowserRequest), Interface) (IReStructuredTextSource, IBrowserRequest), Interface)
component.provideAdapter(ConceptView, (IConcept, IBrowserRequest), Interface)
component.provideAdapter(LoopsType) component.provideAdapter(LoopsType)
component.provideAdapter(ConceptType) component.provideAdapter(ConceptType)