--- a/devtools/testlib.py Tue Jan 11 12:05:12 2011 +0100
+++ b/devtools/testlib.py Tue Jan 11 12:19:36 2011 +0100
@@ -480,9 +480,7 @@
def items(self):
return self
class fake_box(object):
- def mk_action(self, label, url, **kwargs):
- return (label, url)
- def box_action(self, action, **kwargs):
+ def action_link(self, action, **kwargs):
return (action.title, action.url())
submenu = fake_menu()
action.fill_menu(fake_box(), submenu)
--- a/web/action.py Tue Jan 11 12:05:12 2011 +0100
+++ b/web/action.py Tue Jan 11 12:19:36 2011 +0100
@@ -43,7 +43,7 @@
def fill_menu(self, box, menu):
"""add action(s) to the given submenu of the given box"""
for action in self.actual_actions():
- menu.append(box.box_action(action))
+ menu.append(box.action_link(action))
def html_class(self):
if self._cw.selected(self.url()):
--- a/web/component.py Tue Jan 11 12:05:12 2011 +0100
+++ b/web/component.py Tue Jan 11 12:19:36 2011 +0100
@@ -24,7 +24,7 @@
from warnings import warn
-from logilab.common.deprecation import class_deprecated, class_renamed
+from logilab.common.deprecation import class_deprecated, class_renamed, deprecated
from logilab.mtconverter import xml_escape
from cubicweb import Unauthorized, role, target, tags
@@ -36,7 +36,7 @@
non_final_entity, partial_relation_possible,
partial_has_related_entities)
from cubicweb.appobject import AppObject
-from cubicweb.web import INTERNAL_FIELD_VALUE, htmlwidgets, stdmsgs
+from cubicweb.web import INTERNAL_FIELD_VALUE, stdmsgs
# abstract base class for navigation components ################################
@@ -163,6 +163,57 @@
rendered
"""
+
+class Link(object):
+ """a link to a view or action in the ui.
+
+ Use this rather than `cw.web.htmlwidgets.BoxLink`.
+
+ Note this class could probably be avoided with a proper DOM on the server
+ side.
+ """
+ newstyle = True
+
+ def __init__(self, href, label, **attrs):
+ self.href = href
+ self.label = label
+ self.attrs = attrs
+
+ def __unicode__(self):
+ return tags.a(self.label, href=self.href, **self.attrs)
+
+ def render(self, w):
+ w(tags.a(self.label, href=self.href, **self.attrs))
+
+
+class Separator(object):
+ """a menu separator.
+
+ Use this rather than `cw.web.htmlwidgets.BoxSeparator`.
+ """
+ newstyle = True
+
+ def render(self, w):
+ w(u'<hr class="boxSeparator"/>')
+
+
+def _bwcompatible_render_item(w, item):
+ if hasattr(item, 'render'):
+ if getattr(item, 'newstyle', False):
+ if isinstance(item, Separator):
+ w(u'</ul>')
+ item.render(w)
+ w(u'<ul>')
+ else:
+ w(u'<li>')
+ item.render(w)
+ w(u'</li>')
+ else:
+ item.render(w) # XXX displays <li> by itself
+ else:
+ w(u'<li>%s</li>' % item)
+
+
class Layout(Component):
__regid__ = 'layout'
__abstract__ = True
@@ -289,20 +340,31 @@
assert items
w(u'<ul class="%s">' % klass)
for item in items:
- if hasattr(item, 'render'):
- item.render(w) # XXX displays <li> by itself
- else:
- w(u'<li>')
- w(item)
- w(u'</li>')
+ _bwcompatible_render_item(w, item)
w(u'</ul>')
def append(self, item):
self.items.append(item)
+ def action_link(self, action):
+ return self.link(self._cw._(action.title), action.url())
+
+ def link(self, title, url, **kwargs):
+ if self._cw.selected(url):
+ try:
+ kwargs['klass'] += ' selected'
+ except KeyError:
+ kwargs['klass'] = 'selected'
+ return Link(url, title, **kwargs)
+
+ def separator(self):
+ return Separator()
+
+ @deprecated('[3.10] use action_link() / link()')
def box_action(self, action): # XXX action_link
return self.build_link(self._cw._(action.title), action.url())
+ @deprecated('[3.10] use action_link() / link()')
def build_link(self, title, url, **kwargs):
if self._cw.selected(url):
try:
@@ -362,9 +424,9 @@
items = []
for i, (eid, label) in enumerate(rset):
entity = rset.get_entity(i, 0)
- items.append(self.build_link(label, entity.absolute_url()))
+ items.append(self.link(label, entity.absolute_url()))
else:
- items = [self.build_link(e.dc_title(), e.absolute_url())
+ items = [self.link(e.dc_title(), e.absolute_url())
for e in rset.entities()]
self.render_items(w, items)
--- a/web/htmlwidgets.py Tue Jan 11 12:05:12 2011 +0100
+++ b/web/htmlwidgets.py Tue Jan 11 12:19:36 2011 +0100
@@ -25,10 +25,12 @@
from math import floor
from logilab.mtconverter import xml_escape
+from logilab.common.deprecation import class_deprecated
from cubicweb.utils import UStringIO
from cubicweb.uilib import toggle_action, htmlescape
from cubicweb.web import jsonize
+from cubicweb.web.component import _bwcompatible_render_item
# XXX HTMLWidgets should have access to req (for datadir / static urls,
# i18n strings, etc.)
@@ -54,7 +56,8 @@
return False
-class BoxWidget(HTMLWidget):
+class BoxWidget(HTMLWidget): # XXX Deprecated
+
def __init__(self, title, id, items=None, _class="boxFrame",
islist=True, shadow=True, escape=True):
self.title = title
@@ -107,16 +110,16 @@
if self.items:
self.box_begin_content()
for item in self.items:
- if hasattr(item, 'render'):
- item.render(self.w)
- else:
- self.w(u'<li>%s</li>' % item)
+ _bwcompatible_render_item(self.w, item)
self.box_end_content()
self.w(u'</div>')
class SideBoxWidget(BoxWidget):
"""default CubicWeb's sidebox widget"""
+ __metaclass__ = class_deprecated
+ __deprecation_warning__ = '[3.10] class %(cls)s is deprecated'
+
title_class = u'sideBoxTitle'
main_div_class = u'sideBoxBody'
listing_class = ''
@@ -127,6 +130,7 @@
class MenuWidget(BoxWidget):
+
main_div_class = 'menuContent'
listing_class = 'menuListing'
@@ -136,8 +140,9 @@
self.w(u'</div>\n')
-class RawBoxItem(HTMLWidget):
+class RawBoxItem(HTMLWidget): # XXX deprecated
"""a simpe box item displaying raw data"""
+
def __init__(self, label, liclass=None):
self.label = label
self.liclass = liclass
@@ -156,6 +161,7 @@
class BoxMenu(RawBoxItem):
"""a menu in a box"""
+
link_class = 'boxMenu'
def __init__(self, label, items=None, isitem=True, liclass=None, ident=None,
@@ -184,10 +190,7 @@
toggle_action(ident), self.link_class, self.label))
self._begin_menu(ident)
for item in self.items:
- if hasattr(item, 'render'):
- item.render(self.w)
- else:
- self.w(u'<li>%s</li>' % item)
+ _bwcompatible_render_item(self.w, item)
self._end_menu()
if self.isitem:
self.w(u'</li>')
@@ -208,6 +211,8 @@
class BoxField(HTMLWidget):
"""couples label / value meant to be displayed in a box"""
+ __metaclass__ = class_deprecated
+ __deprecation_warning__ = '[3.10] class %(cls)s is deprecated'
def __init__(self, label, value):
self.label = label
self.value = value
@@ -219,6 +224,8 @@
class BoxSeparator(HTMLWidget):
"""a menu separator"""
+ __metaclass__ = class_deprecated
+ __deprecation_warning__ = '[3.10] class %(cls)s is deprecated'
def _render(self):
self.w(u'</ul><hr class="boxSeparator"/><ul>')
@@ -226,6 +233,8 @@
class BoxLink(HTMLWidget):
"""a link in a box"""
+ __metaclass__ = class_deprecated
+ __deprecation_warning__ = '[3.10] class %(cls)s is deprecated'
def __init__(self, href, label, _class='', title='', ident='', escape=False):
self.href = href
if escape:
@@ -247,6 +256,8 @@
class BoxHtml(HTMLWidget):
"""a form in a box"""
+ __metaclass__ = class_deprecated
+ __deprecation_warning__ = '[3.10] class %(cls)s is deprecated'
def __init__(self, rawhtml):
self.rawhtml = rawhtml
@@ -272,6 +283,7 @@
def add_attr(self, attr, value):
self.cell_attrs[attr] = value
+
class SimpleTableModel(object):
"""
uses a list of lists as a storage backend
@@ -283,7 +295,6 @@
def __init__(self, rows):
self._rows = rows
-
def get_rows(self):
return self._rows
--- a/web/views/basecomponents.py Tue Jan 11 12:05:12 2011 +0100
+++ b/web/views/basecomponents.py Tue Jan 11 12:19:36 2011 +0100
@@ -36,8 +36,7 @@
from cubicweb.utils import wrap_on_write
from cubicweb.uilib import toggle_action
from cubicweb.web import component, uicfg
-from cubicweb.web.htmlwidgets import (MenuWidget, PopupBoxMenu, BoxSeparator,
- BoxLink)
+from cubicweb.web.htmlwidgets import MenuWidget, PopupBoxMenu
VISIBLE_PROP_DEF = {
_('visible'): dict(type='Boolean', default=True,
@@ -167,13 +166,11 @@
menu = PopupBoxMenu(self._cw.user.login, isitem=False)
box.append(menu)
for action in actions.get('useractions', ()):
- menu.append(BoxLink(action.url(), self._cw._(action.title),
- action.html_class()))
+ menu.append(self.action_link(action))
if actions.get('useractions') and actions.get('siteactions'):
- menu.append(BoxSeparator())
+ menu.append(self.separator())
for action in actions.get('siteactions', ()):
- menu.append(BoxLink(action.url(), self._cw._(action.title),
- action.html_class()))
+ menu.append(self.action_link(action))
box.render(w=w)
--- a/web/views/bookmark.py Tue Jan 11 12:05:12 2011 +0100
+++ b/web/views/bookmark.py Tue Jan 11 12:19:36 2011 +0100
@@ -98,7 +98,7 @@
if self.can_delete:
req.add_js('cubicweb.ajax.js')
for bookmark in self.bookmarks_rset.entities():
- label = self.build_link(bookmark.title, bookmark.action_url())
+ label = self.link(bookmark.title, bookmark.action_url())
if self.can_delete:
dlink = u'[<a class="action" href="javascript:removeBookmark(%s)" title="%s">-</a>]' % (
bookmark.eid, req._('delete this bookmark'))
@@ -114,7 +114,7 @@
# default value for bookmark's title
url = req.vreg['etypes'].etype_class('Bookmark').cw_create_url(
req, __linkto=linkto, path=path)
- menu.append(self.build_link(req._('bookmark this page'), url))
+ menu.append(self.link(req._('bookmark this page'), url))
if self.bookmarks_rset:
if req.user.is_in_group('managers'):
bookmarksrql = 'Bookmark B WHERE B bookmarked_by U, U eid %s' % ueid
@@ -127,9 +127,9 @@
bookmarksrql %= {'x': ueid}
if erset:
url = req.build_url(vid='muledit', rql=bookmarksrql)
- menu.append(self.build_link(req._('edit bookmarks'), url))
+ menu.append(self.link(req._('edit bookmarks'), url))
url = req.user.absolute_url(vid='xaddrelation', rtype='bookmarked_by',
target='subject')
- menu.append(self.build_link(req._('pick existing bookmarks'), url))
+ menu.append(self.link(req._('pick existing bookmarks'), url))
self.append(menu)
self.render_items(w)
--- a/web/views/boxes.py Tue Jan 11 12:05:12 2011 +0100
+++ b/web/views/boxes.py Tue Jan 11 12:19:36 2011 +0100
@@ -51,7 +51,7 @@
class EditBox(component.CtxComponent): # XXX rename to ActionsBox
"""
box with all actions impacting the entity displayed: edit, copy, delete
- change state, add related entities
+ change state, add related entities...
"""
__regid__ = 'edit_box'
__select__ = component.CtxComponent.__select__ & non_final_entity()
@@ -127,7 +127,7 @@
if hasattr(boxlink, 'label'):
boxlink.label = u'%s %s' % (submenu.label_prefix, boxlink.label)
else:
- submenu.items[0] = u'%s %s' % (submenu.label_prefix, boxlink)
+ boxlink = u'%s %s' % (submenu.label_prefix, boxlink)
box.append(boxlink)
elif submenu.items:
box.append(submenu)
@@ -187,7 +187,7 @@
for category, views in box.sort_by_category(self.views):
menu = htmlwidgets.BoxMenu(category)
for view in views:
- menu.append(self.box_action(view))
+ menu.append(self.action_link(view))
self.append(menu)
self.render_items(w)
--- a/web/views/tableview.py Tue Jan 11 12:05:12 2011 +0100
+++ b/web/views/tableview.py Tue Jan 11 12:19:36 2011 +0100
@@ -28,8 +28,9 @@
from cubicweb import tags
from cubicweb.uilib import toggle_action, limitsize, htmlescape
from cubicweb.web import jsonize
+from cubicweb.web.component import Link
from cubicweb.web.htmlwidgets import (TableWidget, TableColumn, MenuWidget,
- PopupBoxMenu, BoxLink)
+ PopupBoxMenu)
from cubicweb.web.facet import prepare_facets_rqlst, filter_hiddens
class TableView(AnyRsetView):
@@ -212,7 +213,7 @@
ident='%sActions' % divid)
box.append(menu)
for url, label, klass, ident in actions:
- menu.append(BoxLink(url, label, klass, ident=ident, escape=True))
+ menu.append(Link(url, label, klass=klass, id=ident))
box.render(w=self.w)
self.w(u'<div class="clear"/>')