merge tls-sprint
authorAurelien Campeas <aurelien.campeas@logilab.fr>
Tue, 24 Feb 2009 11:35:08 +0100
branchtls-sprint
changeset 939 ad72e06320e2
parent 913 5dfba71b1872 (current diff)
parent 931 7b701df4dbef (diff)
child 940 15dcdc863965
merge
debian/control
debian/cubicweb-client.dirs
debian/cubicweb-common.dirs
debian/cubicweb-core.dirs
debian/cubicweb-dev.dirs
debian/cubicweb-documentation.dirs
debian/cubicweb-documentation.install
debian/cubicweb-server.dirs
debian/cubicweb-twisted.dirs
debian/cubicweb-web.dirs
web/views/basecomponents.py
web/views/basetemplates.py
web/views/bookmark.py
web/views/boxes.py
web/views/owl.py
web/views/startup.py
web/views/tableview.py
web/views/tabs.py
web/views/treeview.py
--- a/__pkginfo__.py	Fri Feb 20 17:40:07 2009 +0100
+++ b/__pkginfo__.py	Tue Feb 24 11:35:08 2009 +0100
@@ -6,11 +6,11 @@
 distname = "cubicweb"
 modname = "cubicweb"
 
-numversion = (3, 0, 4)
+numversion = (3, 0, 10)
 version = '.'.join(str(num) for num in numversion)
 
-license = 'LCL'
-copyright = '''Copyright (c) 2003-2008 LOGILAB S.A. (Paris, FRANCE).
+license = 'GPL'
+copyright = '''Copyright (c) 2003-2009 LOGILAB S.A. (Paris, FRANCE).
 http://www.logilab.fr/ -- mailto:contact@logilab.fr'''
 
 author = "Logilab"
@@ -27,11 +27,12 @@
 * a bunch of other management tools
 """
 
-web = ''
-ftp = ''
-pyversions = ['2.4']
+web = 'http://www.cubicweb.org'
+ftp = 'ftp://ftp.logilab.org/pub/cubicweb'
+pyversions = ['2.4', '2.5']
 
 
+import sys
 from os import listdir, environ
 from os.path import join, isdir
 import glob
@@ -60,7 +61,8 @@
     # --home install
     pydir = 'python'
 else:
-    pydir = join('python2.4', 'site-packages')
+    python_version = '.'.join(str(num) for num in sys.version_info[0:2])
+    pydir = join('python' + python_version, 'site-packages')
 
 try:
     data_files = [
@@ -90,7 +92,6 @@
         [join('share', 'cubicweb', 'cubes', 'shared', 'i18n'),
          [join(i18n_dir, fname) for fname in listdir(i18n_dir)]],
         # skeleton
-        
         ]
 except OSError:
     # we are in an installed directory, don't care about this
--- a/common/migration.py	Fri Feb 20 17:40:07 2009 +0100
+++ b/common/migration.py	Tue Feb 24 11:35:08 2009 +0100
@@ -312,12 +312,18 @@
         """a configuration option's type has changed"""
         self._option_changes.append(('typechanged', optname, oldtype, newvalue))
         
-    def cmd_add_cube(self, cube):
+    def cmd_add_cubes(self, cubes):
+        """modify the list of used cubes in the in-memory config
+        returns newly inserted cubes, including dependencies
+        """
+        if isinstance(cubes, basestring):
+            cubes = (cubes,)
         origcubes = self.config.cubes()
-        newcubes = [p for p in self.config.expand_cubes([cube]) 
+        newcubes = [p for p in self.config.expand_cubes(cubes) 
                        if not p in origcubes]
         if newcubes:
-            assert cube in newcubes
+            for cube in cubes:
+                assert cube in newcubes
             self.config.add_cubes(newcubes)
         return newcubes
 
--- a/debian/changelog	Fri Feb 20 17:40:07 2009 +0100
+++ b/debian/changelog	Tue Feb 24 11:35:08 2009 +0100
@@ -1,3 +1,10 @@
+cubicweb (3.0.10-1) unstable; urgency=low
+
+  * merge cubicweb-core package into cubicweb-common
+  * simplify debian/rules
+
+ -- Julien Jehannet <julien.jehannet@logilab.fr>  Thu, 19 Feb 2009 16:24:09 +0100
+
 cubicweb (3.0.9-1) unstable; urgency=low
 
   * new upstream (interim) release
--- a/debian/compat	Fri Feb 20 17:40:07 2009 +0100
+++ b/debian/compat	Tue Feb 24 11:35:08 2009 +0100
@@ -1,1 +1,1 @@
-5
+7
--- a/debian/control	Fri Feb 20 17:40:07 2009 +0100
+++ b/debian/control	Tue Feb 24 11:35:08 2009 +0100
@@ -2,8 +2,9 @@
 Section: web
 Priority: optional
 Maintainer: Logilab Packaging Team <contact@logilab.fr>
-Uploaders: Sylvain Thenault <sylvain.thenault@logilab.fr> 
-Build-Depends: debhelper (>= 5.0.37.1), python (>=2.4), python-dev (>=2.4), python-central (>= 0.5)
+Uploaders: Sylvain Thenault <sylvain.thenault@logilab.fr>,
+           Julien Jehannet <julien.jehannet@logilab.fr>
+Build-Depends: debhelper (>= 7), python-dev (>=2.4), python-central (>= 0.5)
 Standards-Version: 3.8.0
 Homepage: http://www.cubicweb.org
 XS-Python-Version: >= 2.4, << 2.6
@@ -12,7 +13,7 @@
 Architecture: all
 XB-Python-Version: ${python:Versions}
 Depends: ${python:Depends}, cubicweb-server (= ${source:Version}), cubicweb-twisted (= ${source:Version}), cubicweb-client (= ${source:Version})
-XBS-Recommends: (postgresql, postgresql-plpython, postgresql-contrib) | mysql | sqlite3
+XB-Recommends: (postgresql, postgresql-plpython, postgresql-contrib) | mysql | sqlite3
 Recommends: postgresql | mysql | sqlite3
 Description: the complete CubicWeb framework
  CubicWeb is a semantic web application framework.
@@ -73,8 +74,10 @@
 Package: cubicweb-common
 Architecture: all
 XB-Python-Version: ${python:Versions}
-Depends: ${python:Depends}, cubicweb-core (= ${source:Version}), python-logilab-mtconverter (>= 0.4.0), graphviz, gettext, python-lxml
-Recommends: python-psyco, python-simpletal (>= 4.0)
+Depends: ${python:Depends}, python-logilab-mtconverter (>= 0.4.0), python-simpletal (>= 4.0), graphviz, gettext, python-lxml, python-logilab-common (>= 0.37.2), python-yams (>= 0.20.2), python-rql (>= 0.20.2)
+Recommends: python-psyco
+Conflicts: cubicweb-core
+Replaces: cubicweb-core
 Description: common library for the CubicWeb framework
  CubicWeb is a semantic web application framework.
  .
@@ -85,7 +88,7 @@
 Package: cubicweb-ctl
 Architecture: all
 XB-Python-Version: ${python:Versions}
-Depends: ${python:Depends}, cubicweb-core (= ${source:Version})
+Depends: ${python:Depends}, cubicweb-common (= ${source:Version})
 Description: tool to manage the CubicWeb framework
  CubicWeb is a semantic web application framework.
  .
@@ -105,17 +108,6 @@
  pyro to connect to a repository server.
 
 
-Package: cubicweb-core
-Architecture: all
-XB-Python-Version: ${python:Versions}
-Depends: ${python:Depends}, python-logilab-common (>= 0.37.2), python-yams (>= 0.20.2), python-rql (>= 0.20.2)
-Description: core library for the CubicWeb framework
- CubicWeb is a semantic web application framework.
- .
- This package provides the core part of the library used by anyone having 
- to do some cubicweb programming in Python.
-
-
 Package: cubicweb-dev
 Architecture: all
 XB-Python-Version: ${python:Versions}
--- a/debian/cubicweb-client.dirs	Fri Feb 20 17:40:07 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-usr/lib/python2.4/site-packages/cubicweb/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/cubicweb-client.install.in	Tue Feb 24 11:35:08 2009 +0100
@@ -0,0 +1,1 @@
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/hercule.py usr/lib/PY_VERSION/site-packages/cubicweb
--- a/debian/cubicweb-common.dirs	Fri Feb 20 17:40:07 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-usr/lib/python2.4/site-packages/cubicweb
-usr/lib/python2.4/site-packages/cubicweb/common
-usr/share/cubicweb/cubes/shared
-usr/share/doc/cubicweb-common
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/cubicweb-common.install.in	Tue Feb 24 11:35:08 2009 +0100
@@ -0,0 +1,17 @@
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/common/ usr/lib/PY_VERSION/site-packages/cubicweb
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/entities/ usr/lib/PY_VERSION/site-packages/cubicweb
+debian/tmp/usr/share/cubicweb/cubes/shared/i18n usr/share/cubicweb/cubes/shared/
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/rset.py usr/share/pyshared/cubicweb
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/gettext.py usr/share/pyshared/cubicweb
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/toolsutils.py usr/share/pyshared/cubicweb
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/cwvreg.py usr/share/pyshared/cubicweb
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/_exceptions.py usr/share/pyshared/cubicweb
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/schemaviewer.py usr/share/pyshared/cubicweb
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/dbapi.py usr/share/pyshared/cubicweb
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/cwconfig.py usr/share/pyshared/cubicweb
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/__init__.py usr/share/pyshared/cubicweb
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/md5crypt.py usr/share/pyshared/cubicweb
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/schema.py usr/share/pyshared/cubicweb
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/interfaces.py usr/share/pyshared/cubicweb
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/vregistry.py usr/share/pyshared/cubicweb
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/__pkginfo__.py usr/share/pyshared/cubicweb
--- a/debian/cubicweb-core.dirs	Fri Feb 20 17:40:07 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-usr/lib/python2.4/site-packages/cubicweb
-usr/share/doc/cubicweb-core
--- a/debian/cubicweb-ctl.cubicweb.init	Fri Feb 20 17:40:07 2009 +0100
+++ b/debian/cubicweb-ctl.cubicweb.init	Tue Feb 24 11:35:08 2009 +0100
@@ -11,5 +11,22 @@
 # Short-Description: Start cubicweb application at boot time
 ### END INIT INFO
 
+# FIXME Seems to be inadequate here
+# FIXME If related to pyro, try instead:
+# export PYRO_STORAGE="/tmp"
 cd /tmp
-/usr/bin/cubicweb-ctl $1 --force
+
+# FIXME Work-around about the following lintian error
+#     E: cubicweb-ctl: init.d-script-does-not-implement-required-option /etc/init.d/cubicweb start
+#
+# Check if we are sure to not want the start-stop-daemon machinery here
+# Refer to Debian Policy Manual section 9.3.2 (Writing the scripts) for details.
+
+case "$1" in
+	"force-reload")
+		/usr/bin/cubicweb-ctl reload --force
+		;;
+	"*|restart")
+		/usr/bin/cubicweb-ctl $1 --force
+		;;
+esac
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/cubicweb-ctl.install.in	Tue Feb 24 11:35:08 2009 +0100
@@ -0,0 +1,3 @@
+debian/tmp/usr/bin/cubicweb-ctl usr/bin/
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/cwctl.py usr/lib/PY_VERSION/site-packages/cubicweb
+debian/cubicweb-ctl.bash_completion etc/bash_completion.d/cubicweb-ctl
--- a/debian/cubicweb-dev.dirs	Fri Feb 20 17:40:07 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-usr/lib/python2.4/site-packages/cubicweb
-usr/lib/python2.4/site-packages/cubicweb/common
-usr/lib/python2.4/site-packages/cubicweb/web
-usr/lib/python2.4/site-packages/cubicweb/server
-usr/lib/python2.4/site-packages/cubicweb/sobjects
-usr/lib/python2.4/site-packages/cubicweb/entities
-usr/share/doc/cubicweb-dev
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/cubicweb-dev.install.in	Tue Feb 24 11:35:08 2009 +0100
@@ -0,0 +1,7 @@
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/devtools/ usr/lib/PY_VERSION/site-packages/cubicweb/
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/skeleton/ usr/lib/PY_VERSION/site-packages/cubicweb/
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/test usr/lib/PY_VERSION/site-packages/cubicweb/
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/common/test usr/lib/PY_VERSION/site-packages/cubicweb/common/
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/server/test usr/lib/PY_VERSION/site-packages/cubicweb/server/
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/sobjects/test usr/lib/PY_VERSION/site-packages/cubicweb/sobjects/
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/web/test usr/lib/PY_VERSION/site-packages/cubicweb/web/
--- a/debian/cubicweb-documentation.dirs	Fri Feb 20 17:40:07 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-usr/share/doc/cubicweb-documentation/
-usr/share/doc/cubicweb-documentation/devmanual_fr
-usr/share/doc-base/
--- a/debian/cubicweb-documentation.install	Fri Feb 20 17:40:07 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-debian/cubicweb-doc usr/share/doc-base/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/cubicweb-documentation.install.in	Tue Feb 24 11:35:08 2009 +0100
@@ -0,0 +1,2 @@
+doc/book usr/share/doc/cubicweb-documentation
+debian/cubicweb-doc usr/share/doc-base/cubicweb-doc
--- a/debian/cubicweb-server.dirs	Fri Feb 20 17:40:07 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-usr/lib/python2.4/site-packages/cubicweb/
-usr/share/cubicweb
-usr/share/doc/cubicweb-server
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/cubicweb-server.install.in	Tue Feb 24 11:35:08 2009 +0100
@@ -0,0 +1,4 @@
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/server/ usr/lib/PY_VERSION/site-packages/cubicweb
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/sobjects/ usr/lib/PY_VERSION/site-packages/cubicweb
+debian/tmp/usr/share/cubicweb/schemas/ usr/share/cubicweb/
+debian/tmp/usr/share/cubicweb/migration/ usr/share/cubicweb/
--- a/debian/cubicweb-twisted.dirs	Fri Feb 20 17:40:07 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-usr/lib/python2.4/site-packages
-usr/lib/python2.4/site-packages/cubicweb
-usr/share/doc/cubicweb-twisted
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/cubicweb-twisted.install.in	Tue Feb 24 11:35:08 2009 +0100
@@ -0,0 +1,1 @@
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/etwist/ usr/lib/PY_VERSION/site-packages/cubicweb/
--- a/debian/cubicweb-web.dirs	Fri Feb 20 17:40:07 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-usr/lib/python2.4/site-packages/
-usr/lib/python2.4/site-packages/cubicweb
-usr/share/cubicweb/cubes/shared
-usr/share/doc/cubicweb-web
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/cubicweb-web.install.in	Tue Feb 24 11:35:08 2009 +0100
@@ -0,0 +1,3 @@
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/web usr/lib/PY_VERSION/site-packages/cubicweb
+debian/tmp/usr/share/cubicweb/cubes/shared/data usr/share/cubicweb/cubes/shared
+debian/tmp/usr/share/cubicweb/cubes/shared/wdoc usr/share/cubicweb/cubes/shared
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/cubicweb-web.lintian-overrides	Tue Feb 24 11:35:08 2009 +0100
@@ -0,0 +1,1 @@
+cubicweb-web: embedded-javascript-library usr/share/cubicweb/cubes/shared/data/jquery.js
--- a/debian/rules	Fri Feb 20 17:40:07 2009 +0100
+++ b/debian/rules	Tue Feb 24 11:35:08 2009 +0100
@@ -4,12 +4,16 @@
 
 # Uncomment this to turn on verbose mode.
 #export DH_VERBOSE=1
+
+PY_VERSION:=$(shell pyversions -d)
+
 build: build-stamp
 build-stamp: 
 	dh_testdir
 	# XXX doesn't work if logilab-doctools, logilab-xml are not in build depends
 	# and I can't get pbuilder find them in its chroot :(
-	#cd doc && make
+	# cd doc && make
+	# FIXME cleanup and use sphinx-build as build-depends ?
 	python setup.py build
 	touch build-stamp
 
@@ -18,78 +22,42 @@
 	dh_testroot
 	rm -f build-stamp configure-stamp
 	rm -rf build
-	rm -rf debian/cubicweb-*/
-	find . -name "*.pyc" | xargs rm -f
+	#rm -rf debian/cubicweb-*/
+	find . -name "*.pyc" -delete
+	rm -f $(basename $(wildcard debian/*.in))
 	dh_clean
 
-install: build
+install: build $(basename $(wildcard debian/*.in))
 	dh_testdir
 	dh_testroot
-	dh_clean -k
+	dh_clean
 	dh_installdirs
-	########## core package #############################################
-	# put : 
-	# * all the python library and data in cubicweb-core
-	# * scripts in cubicweb-server
-	#
-	# pick from each latter to construct each package
-	python setup.py -q install_lib --no-compile --install-dir=debian/cubicweb-core/usr/lib/python2.4/site-packages/
-	python setup.py -q install_data --install-dir=debian/cubicweb-core/usr/
-	python setup.py -q install_scripts --install-dir=debian/cubicweb-server/usr/bin/
-	########## common package #############################################
-	mv debian/cubicweb-core/usr/lib/python2.4/site-packages/cubicweb/common/ debian/cubicweb-common/usr/lib/python2.4/site-packages/cubicweb
-	mv debian/cubicweb-core/usr/lib/python2.4/site-packages/cubicweb/entities/ debian/cubicweb-common/usr/lib/python2.4/site-packages/cubicweb
-	# data
-	mv debian/cubicweb-core/usr/share/cubicweb/cubes/shared/i18n debian/cubicweb-common/usr/share/cubicweb/cubes/shared/
+
+	#python setup.py install_lib --no-compile --install-dir=debian/cubicweb-common/usr/lib/python2.4/site-packages/
+	python setup.py -q install --no-compile --prefix=debian/tmp/usr
+
+	# Put all the python library and data in cubicweb-common
+	# and scripts in cubicweb-server
+	dh_install -vi
+	dh_lintian
+
+	# Remove unittests directory (should be available in cubicweb-dev only)
+	rm -rf debian/cubicweb-server/usr/lib/${PY_VERSION}/site-packages/cubicweb/server/test
+	rm -rf debian/cubicweb-server/usr/lib/${PY_VERSION}/site-packages/cubicweb/sobjects/test
+	rm -rf debian/cubicweb-web/usr/lib/${PY_VERSION}/site-packages/cubicweb/web/test
+	rm -rf debian/cubicweb-common/usr/lib/${PY_VERSION}/site-packages/cubicweb/common/test
+
+	# cubes directory must be managed as a valid python module
+	ls -l debian/cubicweb-common/usr/share/cubicweb/cubes
 	touch debian/cubicweb-common/usr/share/cubicweb/cubes/__init__.py
-	########## server package #############################################
-	# library
-	mv debian/cubicweb-core/usr/lib/python2.4/site-packages/cubicweb/server/ debian/cubicweb-server/usr/lib/python2.4/site-packages/cubicweb
-	mv debian/cubicweb-core/usr/lib/python2.4/site-packages/cubicweb/sobjects/ debian/cubicweb-server/usr/lib/python2.4/site-packages/cubicweb
-	# data
-	mv debian/cubicweb-core/usr/share/cubicweb/schemas/ debian/cubicweb-server/usr/share/cubicweb/
-	mv debian/cubicweb-core/usr/share/cubicweb/migration/ debian/cubicweb-server/usr/share/cubicweb/
-	########## twisted package ############################################
-	# library
-	mv debian/cubicweb-core/usr/lib/python2.4/site-packages/cubicweb/etwist/ debian/cubicweb-twisted/usr/lib/python2.4/site-packages/cubicweb/
-	########## web package ################################################
-	# library
-	mv debian/cubicweb-core/usr/lib/python2.4/site-packages/cubicweb/web/ debian/cubicweb-web/usr/lib/python2.4/site-packages/cubicweb/
-	# data / web documentation
-	mv debian/cubicweb-core/usr/share/cubicweb/cubes/shared/data debian/cubicweb-web/usr/share/cubicweb/cubes/shared/
-	mv debian/cubicweb-core/usr/share/cubicweb/cubes/shared/wdoc debian/cubicweb-web/usr/share/cubicweb/cubes/shared/
-	########## ctl package ################################################
-	# scripts
-	mv debian/cubicweb-server/usr/bin/cubicweb-ctl debian/cubicweb-ctl/usr/bin/
-	mv debian/cubicweb-core/usr/lib/python2.4/site-packages/cubicweb/cwctl.py debian/cubicweb-ctl/usr/lib/python2.4/site-packages/cubicweb
-	mv debian/cubicweb-ctl.bash_completion debian/cubicweb-ctl/etc/bash_completion.d/cubicweb-ctl
-	########## client package #############################################
-	# library
-	mv debian/cubicweb-core/usr/lib/python2.4/site-packages/cubicweb/hercule.py debian/cubicweb-client/usr/lib/python2.4/site-packages/cubicweb
-	########## dev package ################################################
-	# devtools package
-	mv debian/cubicweb-core/usr/lib/python2.4/site-packages/cubicweb/devtools/ debian/cubicweb-dev/usr/lib/python2.4/site-packages/cubicweb/
-	mv debian/cubicweb-core/usr/lib/python2.4/site-packages/cubicweb/skeleton/ debian/cubicweb-dev/usr/lib/python2.4/site-packages/cubicweb/
-	# tests directories
-	mv debian/cubicweb-core/usr/lib/python2.4/site-packages/cubicweb/test debian/cubicweb-dev/usr/lib/python2.4/site-packages/cubicweb/
-	mv debian/cubicweb-common/usr/lib/python2.4/site-packages/cubicweb/common/test debian/cubicweb-dev/usr/lib/python2.4/site-packages/cubicweb/common/
-	mv debian/cubicweb-server/usr/lib/python2.4/site-packages/cubicweb/server/test debian/cubicweb-dev/usr/lib/python2.4/site-packages/cubicweb/server/
-	mv debian/cubicweb-server/usr/lib/python2.4/site-packages/cubicweb/sobjects/test debian/cubicweb-dev/usr/lib/python2.4/site-packages/cubicweb/sobjects/
-	mv debian/cubicweb-web/usr/lib/python2.4/site-packages/cubicweb/web/test debian/cubicweb-dev/usr/lib/python2.4/site-packages/cubicweb/web/
-	########## documentation package ######################################
-	cp -r doc/book debian/cubicweb-documentation/usr/share/doc/cubicweb-documentation/
-	########## core package ###############################################
-	# small cleanup
-	rm -rf debian/cubicweb-core/usr/share/cubicweb/
-	# undistributed for now
-	rm -rf debian/cubicweb-core/usr/lib/python2.4/site-packages/cubicweb/goa
-	rm -rf debian/cubicweb-core/usr/lib/python2.4/site-packages/cubicweb/wsgi
+
+%: %.in
+	sed "s/PY_VERSION/${PY_VERSION}/g" < $< > $@
 
 # Build architecture-independent files here.
 binary-indep: build install
 	dh_testdir
 	dh_testroot -i
-	dh_install -i
 	dh_pycentral -i
 	dh_installinit -i -n --name cubicweb -u"defaults 99"
 	dh_installlogrotate -i
--- a/doc/book/en/B0020-define-workflows.en.txt	Fri Feb 20 17:40:07 2009 +0100
+++ b/doc/book/en/B0020-define-workflows.en.txt	Tue Feb 24 11:35:08 2009 +0100
@@ -155,4 +155,3 @@
 defined by the workflow. This transition, as defined in the workflow,
 will only being displayed for the users belonging to the group
 moderators of managers.
-
--- a/doc/book/en/B1060-templates.en.txt	Fri Feb 20 17:40:07 2009 +0100
+++ b/doc/book/en/B1060-templates.en.txt	Tue Feb 24 11:35:08 2009 +0100
@@ -196,11 +196,9 @@
 the case we want to create new CSS style, the best is to define it a in a new
 CSS located under ``myapp/data/``.
 
-If you want to modify an existing CSS styling property, you will have to use
-``!important`` declaration to override the existing property. The application
-apply a higher priority on the default CSS and you can not change that. 
-Customized CSS will not be read first.
 
+.. [TRANSLATE ME FROM FRENCH]
+.. 03-XX-external_resources.fr.txt
 
 [TODO]
 Add login menu in left column
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/fr/03-XX-external_resources.fr.txt	Tue Feb 24 11:35:08 2009 +0100
@@ -0,0 +1,135 @@
+.. -*- coding: utf-8 -*-
+
+
+Les ressources externes
+=======================
+
+Les ressources externes à une application regroupent l'ensemble des fichiers qui seront chargés dans l'entête des pages XHTML générées.
+Elles sont donc constituées principalement des feuilles de styles, des scripts javascripts et de certaines ressources graphiques comme l'icône favicon par exemple.
+
+
+Liste des feuilles de styles utilisées par défaut
+-------------------------------------------------
+
+Les fichiers par défaut se trouve dans les sources du framework. En voici le tableau récapitulatif:
+
++--------------------------------------+----------------------------------------------------+-----------------------------------+
+| Fichiers                             | Utilisation                                        | Vues ou widget concernés          |
++======================================+====================================================+===================================+
+| web/data/cubicweb.acl.css            | formulaires pour le contrôle aux accès             | editgroups, security              |
+| web/data/cubicweb.calendar.css       | calendriers                                        | onemonthcal, oneweekcal           |
+| web/data/cubicweb.calendar_popup.css | popup calendriers                                  | DateWidget                        |
+| web/data/cubicweb.css                | gabarit principal de l'application                 |                                   |
+| web/data/cubicweb.facets.css         | surcharge du `MIT Simile Exhibit Web Widgets`_     | filter_box                        |
+| web/data/cubicweb.form.css           | formulaires                                        | creation, inline-creation, copya, |
+|                                      |                                                    | inline-edition, edition, muledit  |
+| web/data/cubicweb.html_tree.css      | style pour les widgets d'arborescence              |                                   |
+| web/data/cubicweb.ie.css             | dédié aux comportements de Internet Explorer       |                                   |
+| web/data/cubicweb.iprogress.css      | style pour les widgets d'avancement                |                                   |
+| web/data/cubicweb.login.css          | page et popup d'authentification                   | logform                           |
+| web/data/cubicweb.mailform.css       | style utilisé dans les formulaires d'envoi de mail |                                   |
+| web/data/cubicweb.preferences.css    | style pour la page des préférences utilisateurs    | systemepropertiesform             |
+| web/data/cubicweb.print.css          | style dédié à l'impression                         |                                   |
+| web/data/cubicweb.schema.css         | style dédié au schéma de l'application             |                                   |
+| web/data/cubicweb.suggest.css        | surcharge utilisée pour les suggestions            |                                   |
+| web/data/cubicweb.tablesorter.css    | surcharge pour le tri dans les tableau             |                                   |
+| web/data/cubicweb.tableview.css      | surcharge pour le tri sélectif                     |                                   |
+| web/data/cubicweb.timetable.css      | style pour le widget Timetable                     | timetable                         |
+| web/data/jquery.autocomplete.css     | surcharge pour le widget `jQuery autocompleter`_   |                                   |
+| web/data/jquery.treeview.css         | surcharge pour le widget `jQuery treeview`_        |                                   |
+| web/data/pygments.css                | style pour la coloration des blocs de code         |                                   |
+| web/data/timeline-bundle.css         | surcharge du `MIT Simile Timeline Web Widgets`_    | TimelineWidget                    |
+| web/data/ui.tabs.css                 | surcharge pour le widget Tabs de `jQuery UI`_      |                                   |
++--------------------------------------+----------------------------------------------------+-----------------------------------+
+
+.. _MIT Simile Exhibit Web Widgets: http://code.google.com/p/simile-widgets/wiki/Exhibit
+.. _MIT Simile Timeline Web Widgets: http://code.google.com/p/simile-widgets/wiki/Timeline
+.. _jQuery autocompleter: http://www.dyve.net/jquery/?autocomplete
+.. _jQuery treeview: http://plugins.jquery.com/project/treeview
+.. _jQuery UI: http://docs.jquery.com/UI
+
+D'une manière générale, si vous réutiliser un nom de fichier existant, vous écrasez le contenu du fichier d'origine.
+
+
+Changer les feuilles de styles
+------------------------------
+
+Configuration statique
+~~~~~~~~~~~~~~~~~~~~~~
+Dans les sources de votre nouveau cube, vous devez éditer le fichier *data/external_resources* et définir la variable de configuration:
+
+    # CSS stylesheets to include in HTML headers
+    # uncomment the line below to use template specific stylesheet
+    STYLESHEETS = DATADIR/cubicweb.css
+
+Les styles sont définis dans le fichier external_resources par 3 variables:
+
+- la variable STYLESHEETS est défine pour tous les types de médias
+- la variable STYLESHEETS_PRINT sont les styles applicables pour l'impression
+- la variable IE_STYLESHEETS s'appliquent uniquement aux versions d'Internet Explorer
+
+En copiant le fichier d'origine **cubicweb.css**, il est alors possible de modifier le gabarit de base du framework CubicWeb.
+Il est également possible de réutiliser le fichier d'origine.
+
+En créant un nouveau fichier **cubes.(le_nom_du_cube).css** dans le répertoire **data/** et en ajoutant une directive css @import, il est possible de réutiliser les styles définis par défaut:
+
+    @import url("cubicweb.css");
+
+
+Chargement dynamique de feuilles de style dans vos vues
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Il est possible de charger des css spécifiques pour une vue par l'utilisation de la méthode add_css():
+
+    self.req.add_css('mon_cube.css')
+
+
+Les ressources graphiques de base
+---------------------------------
+
+Vous pouvez changer certaines ressources graphiques comme:
+
+- le logo du site:
+
+    # path to the logo (relative to the application main script, seen as a
+    # directory, hence .. when you are not using an absolute path)
+    LOGO = DATADIR/logo.png
+
+- la 'favicon' du site:
+
+    FAVICON = DATADIR/favicon.ico
+
+- le logo des flux RSS:
+
+    RSS_LOGO = DATADIR/rss.png
+
+- l'icône permettant l'appel au widget 'calendrier':
+
+    CALENDAR_ICON = DATADIR/calendar.png
+
+- l'icône utilisée pour la validation d'une recherche:
+
+    SEARCH_GO = DATADIR/go.png
+
+- l'icône d'aide en ligne:
+
+    HELP = DATADIR/help.png
+
+
+Ajouter vos scripts javascripts
+-------------------------------
+
+Configuration statique
+~~~~~~~~~~~~~~~~~~~~~~
+Vous devez surcharger la variable JAVASCRIPTS dans le fichier *data/external_resources*  de votre cube.
+
+Chargement dynamique de script javascript dans vos vues
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Il est possible de charger vos scripts par la méthode add_js():
+
+    self.req.add_js('mon_script.js')
+
+
+Problèmes connus
+----------------
+
+Il est important de noter que la méthode de chargement dynamique ne marche pas avec les widgets Ajax. Vos fichiers devront déjà être au préalable avoir été chargés.
--- a/server/migractions.py	Fri Feb 20 17:40:07 2009 +0100
+++ b/server/migractions.py	Tue Feb 24 11:35:08 2009 +0100
@@ -264,13 +264,15 @@
             self.commit()
 
     def cmd_add_cube(self, cube, update_database=True):
+        self.cmd_add_cubes( (cube,), update_database)
+    
+    def cmd_add_cubes(self, cubes, update_database=True):
         """update_database is telling if the database schema should be updated
         or if only the relevant eproperty should be inserted (for the case where
         a cube has been extracted from an existing application, so the
         cube schema is already in there)
         """
-        newcubes = super(ServerMigrationHelper, self).cmd_add_cube(
-            cube)
+        newcubes = super(ServerMigrationHelper, self).cmd_add_cubes(cubes)
         if not newcubes:
             return
         for pack in newcubes:
@@ -279,22 +281,22 @@
         if not update_database:
             self.commit()
             return
-        self.new_schema = self.config.load_schema()
+        with_new_cubes = self.config.load_schema()
         new = set()
         # execute pre-create files
         for pack in reversed(newcubes):
             self.exec_event_script('precreate', self.config.cube_dir(pack))
         # add new entity and relation types
-        for rschema in self.new_schema.relations():
+        for rschema in with_new_cubes.relations():
             if not rschema in self.repo.schema:
                 self.cmd_add_relation_type(rschema.type)
                 new.add(rschema.type)
-        for eschema in self.new_schema.entities():
+        for eschema in with_new_cubes.entities():
             if not eschema in self.repo.schema:
                 self.cmd_add_entity_type(eschema.type)
                 new.add(eschema.type)
         # check if attributes has been added to existing entities
-        for rschema in self.new_schema.relations():
+        for rschema in with_new_cubes.relations():
             existingschema = self.repo.schema.rschema(rschema.type)
             for (fromtype, totype) in rschema.iter_rdefs():
                 if existingschema.has_rdef(fromtype, totype):
--- a/server/session.py	Fri Feb 20 17:40:07 2009 +0100
+++ b/server/session.py	Tue Feb 24 11:35:08 2009 +0100
@@ -21,6 +21,18 @@
 from cubicweb.common.utils import make_uid
 from cubicweb.server.rqlrewrite import RQLRewriter
 
+_ETYPE_PYOBJ_MAP = { bool: 'Boolean',
+                     int: 'Int',
+                     long: 'Int',
+                     float: 'Float',
+                     Decimal: 'Decimal',
+                     unicode: 'String',
+                     NoneType: None,
+                     Binary: 'Bytes',
+                     DateTimeType: 'Datetime',
+                     DateTimeDeltaType: 'Interval',
+                     }
+
 def etype_from_pyobj(value):
     """guess yams type from python value"""
     # note:
@@ -28,17 +40,7 @@
     # * use type(value) and not value.__class__ since mx instances have no
     #   __class__ attribute
     # * XXX Date, Time
-    return {bool: 'Boolean',
-            int: 'Int',
-            long: 'Int',
-            float: 'Float',
-            Decimal: 'Decimal',
-            unicode: 'String',
-            NoneType: None,
-            Binary: 'Bytes',
-            DateTimeType: 'Datetime',
-            DateTimeDeltaType: 'Interval',
-            }[type(value)]
+    return _ETYPE_PYOBJ_MAP[type(value)]
 
 def is_final(rqlst, variable, args):
     # try to find if this is a final var or not
@@ -58,35 +60,8 @@
         description.append(term.get_type(solution, args))
     return description
 
-#XXX rql <= 0.18.3 bw compat
 from rql import stmts
-if not hasattr(stmts.Union, 'get_variable_variables'):
-    def _union_get_variable_variables(self):
-        """return the set of variable names which take different type according to
-        the solution
-        """
-        change = set()
-        values = {}
-        for select in self.children:
-            change.update(select.get_variable_variables(values))
-        return change
-    stmts.Union.get_variable_variables = _union_get_variable_variables
-                        
-    def _select_get_variable_variables(self, _values=None):
-        """return the set of variable names which take different type according to
-        the solution
-        """
-        change = set()
-        if _values is None:
-            _values = {}
-        for solution in self.solutions:
-            for vname, etype in solution.iteritems():
-                if not vname in _values:
-                    _values[vname] = etype
-                elif _values[vname] != etype:
-                    change.add(vname)
-        return change
-    stmts.Select.get_variable_variables = _select_get_variable_variables
+assert hasattr(stmts.Union, 'get_variable_variables'), "You need RQL > 0.18.3"
 
 class Session(RequestSessionMixIn):
     """tie session id, user, connections pool and other session data all
--- a/web/data/cubicweb.calendar.css	Fri Feb 20 17:40:07 2009 +0100
+++ b/web/data/cubicweb.calendar.css	Tue Feb 24 11:35:08 2009 +0100
@@ -74,7 +74,7 @@
 }
 
 table.omcalendar tr td div.calCellTitle div.stopper {
-  clear:pos;
+ /* clear:pos; # FIXME : pos is not a clear value*/
 }
 
 table.omcalendar tr td {
--- a/web/data/cubicweb.calendar_popup.css	Fri Feb 20 17:40:07 2009 +0100
+++ b/web/data/cubicweb.calendar_popup.css	Tue Feb 24 11:35:08 2009 +0100
@@ -45,7 +45,7 @@
 
 table.popupCalendar th.prev,
 table.popupCalendar th.next {
-  color: orangered;
+  color: #ff4500;
   font-size: 50%;
   font-weight: bold;
   padding: 2px 0px;
--- a/web/data/cubicweb.css	Fri Feb 20 17:40:07 2009 +0100
+++ b/web/data/cubicweb.css	Tue Feb 24 11:35:08 2009 +0100
@@ -3,10 +3,9 @@
  *  :copyright: 2003-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
  *  :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
  */
-
-/******************************************************************************/
-/* main styles                                                                */
-/******************************************************************************/
+/***************************************/
+/* xhtml tags styles                   */
+/***************************************/
 
 *{
   margin:0px;
@@ -23,14 +22,12 @@
   font-family: Verdana, sans-serif;
 }
 
-
 h1 {
   font-size: 188%;
   margin: 0.2em 0px 0.3em;
   border-bottom: 1px solid #000;
 }
 
-
 h2, h3 {
   margin-top: 0.2em;
   margin-bottom: 0.3em;
@@ -57,7 +54,7 @@
   font-size:105%;
 }
 
-a, a:active, a:link, a:visited {
+a, a:active, a:visited, a:link {
   color: #ff4500;
   text-decoration: none;
 }
@@ -66,33 +63,17 @@
   text-decoration: underline;
 }
 
-a.grayedout {
-  display: block;
-  padding-left: 2px;
-  color: #808080;
-}
-
-a.grayedout:visited{
-  color: #808080;
-}
-
-a.grayedout:hover {
-  color: #000;
-}
-
 a img {
   border: none;
   text-align: center;
 }
 
 p {
-  margin-top: 0em;
-  margin-bottom: 0.2em;
+  margin: 0em 0px 0.2em;
   padding-top: 2px;
 }
 
-
-table, td, input, select {
+table, td, input, select{
   font-size: 100%;
 }
 
@@ -107,7 +88,7 @@
 
 table td img {
   vertical-align: middle;
-  margin: 0px 10px 0px 0px;
+  margin-right: 10px;
 }
 
 ol {
@@ -125,29 +106,22 @@
   background: url("bullet_orange.png") 0% 6px no-repeat;
 }
 
-pre {
-  font-family: Courier, "Courier New", Monaco, monospace;
-  font-size: 100%;
-  color: #000;
-  background-color: #f2f2f2;
-  border: 1px solid #ccc;
-  /*overflow:auto; */
+dt {
+  font-size:1.17em;
+  font-weight:600;
 }
 
-blockquote {
-  font-family: Courier, "Courier New", serif;
-  font-size: 120%;
-  margin: 5px 0px;
-  padding: 0.8em;
-  background-color: #f2f2f2;
-  border: 1px solid #ccc;
+dd {
+  margin: 0.6em 0 1.5em 2em;
 }
 
-note, code {
-  font-size: 120%;
-  color: #000;
-  background-color: #f2f2f2;
-  border: 1px solid #ccc;
+fieldset {
+  border: none;
+}
+
+legend {
+  padding: 0px 2px;
+  font: bold 1em Verdana, sans-serif;
 }
 
 input, textarea {
@@ -160,35 +134,41 @@
   border: 1px inset #ff7700;
 }
 
-fieldset {
-  border: none;
-}
-
-legend {
-  padding: 0px 2px;
-  font: bold 1em Verdana, sans-serif;
-}
-
 label, .label {
-  font-weight: bold ! important;
+  font-weight: bold;
 }
 
 iframe {
   border: 0px;
 }
 
-dt {
-	font-size:	1.17em;
-	font-weight:	600;
+pre {
+  font-family: Courier, "Courier New", Monaco, monospace;
+  font-size: 100%;
+  color: #000;
+  background-color: #f2f2f2;
+  border: 1px solid #ccc;
 }
 
-dd {
-	margin: 0.6em 0 1.5em 2em;
+code {
+  font-size: 120%;
+  color: #000;
+  background-color: #f2f2f2;
+  border: 1px solid #ccc;
 }
 
-/******************************************************************************/
-/* generic classes                                                            */
-/******************************************************************************/
+blockquote {
+  font-family: Courier, "Courier New", serif;
+  font-size: 120%;
+  margin: 5px 0px;
+  padding: 0.8em;
+  background-color: #f2f2f2;
+  border: 1px solid #ccc;
+}
+
+/***************************************/
+/* generic classes                     */
+/***************************************/
 
 .odd {
   background-color: #f7f6f1;
@@ -215,77 +195,70 @@
   clear: both;
 }
 
-.noborder {
-  border: none;
-}
-
-.strong{
-  font-weight:bold;
-}
-
-.title {
-  text-align: left;
-  font-size:  large;
-  font-weight: bold;
-}
-
-.titleUnderline {
-  color: #000;
-  clear: left;
-  margin: 0px;
-  padding-top: 0.5em;
-  border-bottom: 1px solid black;
-}
-
-.helper{
-  font-size: 96%;
-  color: #555544;
-}
-
-.helper:hover {
-  color: #000;
-  cursor: default;
-}
-
 .hidden {
   display: none;
   visibility: hidden;
 }
 
-.needsvalidation {
-  font-style: italic;
-  color: grey ! important;
-}
 
-.folder {
-  /* disable odd/even under folder class */
-  background-color: transparent;
-}
+/* FIXME need to be moved to cubicweb.forms.css */
+li.invisible { list-style: none; background: none; padding: 0px 0px
+1px 1px; }
 
-li.invisible {
-  list-style: none;
-  background: none;
-  padding: 0px 0px 1px 1px;
-}
-
+/* FIXME Should use span in html insteed */
 li.invisible div {
   display: inline;
 }
 
-div.row {
- clear: both;
- padding-bottom:0.4px
+
+/***************************************/
+/*   LAYOUT                            */
+/***************************************/
+
+/* header */
+
+table#header {
+  background: #ff7700 url("banner.png") left top repeat-x;
+  text-align: left;
+}
+
+table#header td {
+  vertical-align: middle;
+}
+
+table#header a {
+color: #000;
 }
 
-div.row span.label{ 
- padding-right:1em
+span#appliName {
+ font-weight: bold;
+ color: #000;
+ white-space: nowrap;
+}
+
+table#header td#headtext {
+  width: 100%;
 }
 
-div.field {
-  margin-left: 0.2em;
-  display: inline;
+a.help{
+  display: block;
+  margin: 0px 5px 0px 8px;
+  height: 17px;
+  width: 17px;
+  background: url('help.png') 0% 0% no-repeat;
 }
 
+a.help:hover {
+  background-position: 0px -16px;
+  text-decoration: none;
+}
+
+/* FIXME appear with 4px width in IE6 */
+div#stateheader{
+  min-width: 66%;
+}
+
+/* Popup on login box and userActionBox */
 div.popup {
   position: absolute;
   z-index: 400;
@@ -300,42 +273,7 @@
   color: black;
 }
 
-/******************************************************************************/
-/* header / layout                                                            */
-/******************************************************************************/
-
-.logo {
- background: #fff;
- border-left: #f2f2f2;
-}
-
-span#appliName {
- font-weight: bold;
- color: #000;
- white-space: nowrap;
-}
-
-#header {
-  background: #ff7700 url("banner.png") left top repeat-x;
-  text-align: left;
-}
-
-table#header td {
-  vertical-align: middle;
-}
-
-table#header a {
-color: #000;
-}
-
-td#headtext {
-  width: 100%;
-}
-
-/*FIXME appear with 4px width in IE6*/
-div#stateheader{
-  width: 66%;
-}
+/* main zone */
 
 div#page {
   background: #e2e2e2;
@@ -343,16 +281,16 @@
   min-height: 800px;
 }
  
-td#contentcol {
-  padding: 8px 5px 5px 10px;
+table#mainLayout{ 
+ margin:0px 3px;
 }
 
+table#mainLayout td#contentcol {
+  padding: 8px 10px 5px;
+}
 
-div#pageContent {
-  clear: both;
-  padding: 10px 1em 2em;
-  background: #ffffff;
-  border: 1px solid #ccc;
+table#mainLayout td.navcol {
+  width: 16em;
 }
 
 #contentheader {
@@ -364,157 +302,29 @@
   color: #000;
 }
 
-td.firstcolumn {
-  width: 220px;
-}
-
-td.navcol {
-  width: 16em;
-}
-
-div.footer {
-  text-align: center;
-}
-div.footer a {
-  color: #000;
-  text-decoration: none;
+div#pageContent {
+  clear: both;
+  padding: 10px 1em 2em;
+  background: #ffffff;
+  border: 1px solid #ccc;
 }
 
-/******************************************************************************/
-/* help button                                                                */
-/******************************************************************************/
-
-a.help{
-  display: block;
-  margin: 0px 5px 0px 8px;
-  height: 17px;
-  width: 17px;
-  background: url('help.png') 0% 0% no-repeat;
-}
+/* rql bar */
 
-a.help:hover {
-  background-position: 0px -16px;
-  text-decoration: none;
-}
-
-/******************************************************************************/
-/* rql bar                                                                    */
-/******************************************************************************/
-
-div#rqlform {
-  width: 100%;
+div#rqlinput {
+  border: 1px solid #cfceb7;
+  margin-bottom: 8px;
+  padding: 3px;
+  background: #cfceb7;
 }
 
 input#rql{
- width: 80%;
- margin-left: 12px;
-}
-
-/******************************************************************************/
-/* user actions menu                                                          */
-/******************************************************************************/
-
-a.logout, a.logout:visited, a.logout:hover{
-  color: #fff;
-  text-decoration: none;
-}
-
-div#userActionsBox {
-  width: 14em;
-  text-align: right;
-}
-
-div#userActionsBox a.popupMenu {
-  color: black;
-  text-decoration: underline;
-}
-
-/******************************************************************************/
-/* buttons                                                                    */
-/******************************************************************************/
-
-input#rqlboxsubmit, input#rqlboxsubmit2 {
-  background: #fffff8 url("go.png") 50% 50% no-repeat;
-  width: 20px;
-  height: 20px;
-  margin: 0px;
-}
-
-input.button,
-input.formButton,
-input.validateButton,
-input.searchButton,
-input.loginButton {
-  border-top: 1px solid #edecd2;
-  border-left: 1px solid #edecd2;
-  border-right: 1px solid #cfceb7;
-  border-bottom: 1px solid #cfceb7;
-  background: #fffff8 url("button.png") bottom left repeat-x;
-}
-
-input.searchButton {
-  background: #f0eff0 url("gradient-grey-up.png") left top repeat-x;
-}
-
-input.button,
-input.validateButton {
-  margin: 1em 1em 0px 0px ! important;
+  width: 95%;
 }
 
-/******************************************************************************/
-/* primary view                                                               */
-/******************************************************************************/
-
-.mainInfo  {
-  margin-right: 1em;
-  padding: 0.2em;
-}
-
-div.mainRelated {
-  border: none;
-  margin-right: 1em;
-  padding: 0.5em 0.2em 0.2em;
-}
-
-div.sideRelated h4,
-div.sideRelated h5 {
-  margin-top: 0px;
-  margin-bottom: 0px;
-}
-
-div.sideRelated {
-  margin-right: 1em;
-  padding: 12px 0px 12px 12px;
-  min-width: 21em;
-  max-width: 50em;
-}
-
-div.metadata {
-  font-size: 90%;
-  margin: 5px 0px 3px;
-  color: #666;
-  font-style: italic;
-  text-align: right;
-}
-
-div.section {
-  margin-top: 0.5em;
-  width:100%;
-}
-
-div.section a:hover {
-  text-decoration: none;
-}
-
-
-
-/******************************************************************************/
-/* boxes                                                                      */
-/******************************************************************************/
-
+/* boxes */
 div.navboxes {
-  padding-left: 3px;
-  margin-top: 8px;
+ margin-top: 8px; 
 }
 
 div.boxFrame {
@@ -594,12 +404,14 @@
   color: #111100;
 }
 
+
 a.boxMenu {
   background: transparent url("puce_down.png") 98% 6px no-repeat;
   display: block;
   padding: 1px 9px 1px 3px;
 }
 
+
 a.popupMenu {
   background: transparent url("puce_down_black.png") 2% 6px no-repeat;
   padding-left: 2em;
@@ -648,6 +460,12 @@
   background: #eeedd9;
 }
 
+ul.sideBox li{ 
+ list-style: none;
+ background: none; 
+ padding: 0px 0px 1px 1px;
+ }
+
 div.sideBoxBody {
   padding: 0.2em 5px;
 }
@@ -680,62 +498,45 @@
  padding:0px 5px;
 }
 
-/******************************************************************************/
-/* inline edition and generic form classes                                    */
-/******************************************************************************/
+/* FIXME rqlboxsubmit2 still necessary ? */
 
-div.inlineedit {
-  display: none;
+input.rqlsubmit, 
+input#rqlboxsubmit2 {
+  background: #fffff8 url("go.png") 50% 50% no-repeat;
+  width: 20px;
+  height: 20px;
+  margin: 0px;
 }
 
-div.editableField {
-  display: inline;
-}
-
-div.editableField:hover,
-div.editableField p:hover {
-  background-color: #eeedd9;
+input#norql{
+  width:13em;
+  margin-right: 2px;
 }
 
-option.separator {
-  font-weight: bold;
-  background: #ccc;
-  text-align: center;
-}
-
-input.error {
-  background: transparent url("error.png") 100% 50% no-repeat;
+/* user actions menu */
+a.logout, a.logout:visited, a.logout:hover{
+  color: #fff;
+  text-decoration: none;
 }
 
-span.error {
-  display: block;
-  font-weight: bold;
-  color: #ed0d0d;
+div#userActionsBox {
+  width: 14em;
+  text-align: right;
 }
 
-/******************************************************************************/
-/* navigation                                                                 */
-/******************************************************************************/
+div#userActionsBox a.popupMenu {
+  color: black;
+  text-decoration: underline;
+}
 
+/**************/
+/* navigation */
+/**************/
 div#etyperestriction {
   margin-bottom: 1ex;
   border-bottom: 1px solid #ccc;
 }
 
-div.navigation a {
-  text-align: center;
-  text-decoration: none;
-}
-
-div.prevnext {
-  width: 100%;
-  margin-bottom: 1em;
-}
-
-div.prevnext a {
-  color: #000;
-}
-
 span.slice a:visited,
 span.slice a:hover{
   color: #555544;
@@ -746,15 +547,95 @@
   color: #000;
 }
 
-/******************************************************************************/
-/* messages                                                                   */
-/******************************************************************************/
+/* FIXME should be moved to cubes/folder */
+div.navigation a {
+  text-align: center;
+  text-decoration: none;
+}
+
+/* FIXME seems to be not used in cubicweb framework */
+div.prevnext {
+  width: 100%;
+  margin-bottom: 1em;
+}
+
+div.prevnext a {
+  color: #000;
+}
+
+
+/***************************************/
+/* entity views                        */
+/***************************************/
+
+.mainInfo  {
+  margin-right: 1em;
+  padding: 0.2em;
+}
+
+
+div.mainRelated {
+  border: none;
+  margin-right: 1em;
+  padding: 0.5em 0.2em 0.2em;
+}
+
+div.sideRelated h4,
+div.sideRelated h5 {
+  margin-top: 0px;
+  margin-bottom: 0px;
+}
+
+div.sideRelated {
+  margin-right: 1em;
+  float: right;
+  padding: 12px 0px 12px 12px;
+  min-width: 21em;
+  max-width: 50em;
+}
+
+div.metadata {
+  font-size: 90%;
+  margin: 5px 0px 3px;
+  color: #666;
+  font-style: italic;
+  text-align: right;
+}
+
+div.section {
+  margin-top: 0.5em;
+  width:100%;
+}
+
+div.section a:hover {
+  text-decoration: none;
+}
+
+/* basic entity view */
+
+div.row {
+ clear: both;
+ padding-bottom:0.4px
+}
+
+div.row span.label{ 
+ padding-right:1em
+}
+
+div.field {
+  margin-left: 0.2em;
+  display: inline;
+}
+
+
+/***************************************/
+/* messages                            */
+/***************************************/
 
 .warning,
 .message,
-.errorMessage,
-.searchMessage,
-.statemessage {
+.errorMessage ,
+.searchMessage{
   padding: 0.3em 0.3em 0.3em 1em;
   font-weight: bold;
 }
@@ -772,13 +653,6 @@
   background: #f8f8ee;
 }
 
-div#rqlinput {
-  border: 1px solid #cfceb7;
-  margin-bottom: 8px;
-  padding: 3px;
-  background: #cfceb7;
-}
-
 .message {
   margin: 0px;
   background: #f8f8ee url("information.png") 5px center no-repeat;
@@ -823,9 +697,9 @@
   display: none;
 }
 
-/******************************************************************************/
-/* listing table                                                              */
-/******************************************************************************/
+/***************************************/
+/* listing table                       */
+/***************************************/
 
 table.listing {
  margin: 10px 0em;
@@ -872,9 +746,10 @@
   top: -1px;
 }
 
-/******************************************************************************/
-/* drag and drop zone (XXX only used in seo for now)                          */
-/******************************************************************************/
+/***************************************/
+/* drag and drop zone                  */
+/* (XXX only used in seo for now)      */
+/***************************************/
 
 div.droppable {
   border: 1px dashed black;
@@ -887,19 +762,11 @@
   background: #f4f5ed;
 }
 
-/******************************************************************************/
-/* search box                                                                 */
-/******************************************************************************/
+/****************************************/
+/* filter box  FIXME is not used anymore*/
+/****************************************/
 
-input#norql{
-  width:13em;
-  margin-right: 2px;
-}
-
-/******************************************************************************/
-/* filter box                                                                 */
-/******************************************************************************/
-
+/*
 #filter_box input {
   width: 180px;
 }
@@ -916,38 +783,11 @@
 #filter_box option.disabled {
   background: lightgray;
 }
-
-/******************************************************************************/
-/* table filter form                                                          */
-/******************************************************************************/
-
-table.filter th {
-  font-weight: bold;
-  background: #ebe8d9 url("button.png") repeat-x;
-  padding: 0.3em;
-  border-bottom: 1px solid #cfceb7;
-  text-align: left;
-}
+*/
 
-table.filter div.facet {
-  padding: 0.6em 0.2em;
-  margin: 0em 1em;
-  border: 1px solid #ccc;
-}
-
-table.filter div.facetTitle {
-  font-weight: bold;
-}
-
-
-div#tableActionsBox {
- direction:rtl;
- float:right
-}
-
-/******************************************************************************/
-/* error view (views/management.py)                                           */
-/******************************************************************************/
+/***************************************/
+/* error view (views/management.py)    */
+/***************************************/
 
 div.pycontext { /* html traceback */
   font-family: Verdana, sans-serif;
@@ -961,32 +801,10 @@
   color: #ff0000;
 }
 
-/******************************************************************************/
-/* index view (views/startup.py)                                              */
-/******************************************************************************/
 
-table.startup {
-  width: 100%;
-}
-
-table.startup td {
-  padding: 0.1em 0.2em;
-}
-
-table.startup td.addcol {
-  text-align: right;
-  width: 0.5em;
-}
-
-table.startup th{
-  padding-top: 3px;
-  padding-bottom: 3px;
-  text-align: left;
-}
-
-/******************************************************************************/
-/* addcombobox                                                                */
-/******************************************************************************/
+/***************************************/
+/* addcombobox                         */
+/***************************************/
 
 input#newopt{ 
  width:120px ; 
@@ -1005,3 +823,51 @@
  display:block;
  float:left;
 }
+
+/***************************************/
+/* buttons                             */
+/***************************************/
+
+input.button{  
+  margin: 1em 1em 0px 0px;
+  border: 1px solid #edecd2;
+  border-color:#edecd2 #cfceb7 #cfceb7  #edecd2;
+  background: #fffff8 url("button.png") bottom left repeat-x;
+}
+
+/* FileItemInnerView  jquery.treeview.css */
+.folder {
+  /* disable odd/even under folder class */
+  background-color: transparent;
+}
+
+/***************************************/
+/* footer                              */
+/***************************************/
+
+div.footer {
+  text-align: center;
+}
+div.footer a {
+  color: #000;
+  text-decoration: none;
+}
+
+
+/****************************************/
+/* FIXME must by managed by cubes       */
+/****************************************/
+.needsvalidation {
+  font-style: italic;
+  color: gray;
+}
+
+
+/***************************************/
+/* FIXME : Deprecated ? entity view ?  */
+/***************************************/
+.title {
+  text-align: left;
+  font-size:  large;
+  font-weight: bold;
+}
--- a/web/data/cubicweb.facets.css	Fri Feb 20 17:40:07 2009 +0100
+++ b/web/data/cubicweb.facets.css	Tue Feb 24 11:35:08 2009 +0100
@@ -69,7 +69,7 @@
 }
 
 div#filter_box div.boxTitle {
-  visibility: none;
+  visibility: hidden;
   display: none;
 }
 
--- a/web/data/cubicweb.form.css	Fri Feb 20 17:40:07 2009 +0100
+++ b/web/data/cubicweb.form.css	Tue Feb 24 11:35:08 2009 +0100
@@ -9,7 +9,7 @@
   width: 100%;
   font-size : 160%;
   font-weight: bold;
-  color: orangered;
+  color: #ff4500;
   padding-bottom : 0.4em;
   text-transform: capitalize;
   background: url("bg_trame_grise.png") left bottom repeat-x;
@@ -178,6 +178,35 @@
   margin-left: 2em;
 }
 
+/*FIXME inlineedit not used ?*/
+div.inlineedit {
+  display: none;}
+
+div.editableField {
+  display: inline;
+}
+
+div.editableField:hover,
+div.editableField p:hover {
+  background-color: #eeedd9;
+}
+
+input.error {
+  background: transparent url("error.png") 100% 50% no-repeat;
+}
+
+span.error {
+  display: block;
+  font-weight: bold;
+  color: #ed0d0d;
+}
+
+option.separator {
+  font-weight: bold;
+  background: #ccc;
+  text-align: center;
+}
+
 div.trame_grise {
   background: url("bg_trame_grise.png") left top repeat-x;
 }
@@ -189,3 +218,21 @@
   padding-left: 2em;
   background : #f8f8ee url("information.png") 5px center no-repeat ;
 }
+
+.helper{
+  font-size: 96%;
+  color: #555544;
+}
+
+.helper:hover {
+  color: #000;
+  cursor: default;
+}
+
+input.validateButton {  
+  margin: 1em 1em 0px 0px;
+  border: 1px solid #edecd2;
+  border-color:#edecd2 #cfceb7 #cfceb7  #edecd2;
+  background: #fffff8 url("button.png") bottom left repeat-x;
+}
+
--- a/web/data/cubicweb.login.css	Fri Feb 20 17:40:07 2009 +0100
+++ b/web/data/cubicweb.login.css	Tue Feb 24 11:35:08 2009 +0100
@@ -76,7 +76,8 @@
 }
 
 input.loginButton {
-  display:block;
+  border: 1px solid #edecd2;
+  border-color:#edecd2 #cfceb7 #cfceb7  #edecd2;
   margin: 2px 0px 0px;
   background: #f0eff0 url("gradient-grey-up.png") left top repeat-x; 
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/data/cubicweb.manageview.css	Tue Feb 24 11:35:08 2009 +0100
@@ -0,0 +1,22 @@
+/***************************************/
+/* Manage view (views/startup.py)      */
+/***************************************/
+
+table.startup {
+  width: 100%;
+}
+
+table.startup td {
+  padding: 0.1em 0.2em;
+}
+
+table.startup td.addcol {
+  text-align: right;
+  width: 0.5em;
+}
+
+table.startup th{
+  padding-top: 3px;
+  padding-bottom: 3px;
+  text-align: left;
+}
--- a/web/data/cubicweb.schema.css	Fri Feb 20 17:40:07 2009 +0100
+++ b/web/data/cubicweb.schema.css	Tue Feb 24 11:35:08 2009 +0100
@@ -5,6 +5,16 @@
  *  :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
  */
 
+
+.titleUnderline {
+  color: #000;
+  clear: left;
+  margin: 0px;
+  padding-top: 0.5em;
+  border-bottom: 1px solid black;
+}
+
+
 div.relationDefinition { 
   float: left;   
   position: relative;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/data/cubicweb.tableview.css	Tue Feb 24 11:35:08 2009 +0100
@@ -0,0 +1,27 @@
+/***************************************/
+/* filter table form                   */
+/***************************************/
+
+table.filter th {
+  font-weight: bold;
+  background: #ebe8d9 url("button.png") repeat-x;
+  padding: 0.3em;
+  border-bottom: 1px solid #cfceb7;
+  text-align: left;
+}
+
+table.filter div.facet {
+  padding: 0.6em 0.2em;
+  margin: 0em 1em;
+  border: 1px solid #ccc;
+}
+
+table.filter div.facetTitle {
+  font-weight: bold;
+}
+
+
+div#tableActionsBox {
+ direction:rtl;
+ float:right
+}
--- a/web/data/cubicweb.timetable.css	Fri Feb 20 17:40:07 2009 +0100
+++ b/web/data/cubicweb.timetable.css	Tue Feb 24 11:35:08 2009 +0100
@@ -12,7 +12,7 @@
 
 table.timetable th { 
   padding:1pt;
-  align:center;
+  text-align:center;
 }
 
 
@@ -52,7 +52,7 @@
   font-family: Verdana, sans-serif;
   padding-left: 4pt;
   padding-right: 4pt;
-  align: left;
+  text-align: left;
   width: auto;
 }
 
--- a/web/data/cubicweb.widgets.js	Fri Feb 20 17:40:07 2009 +0100
+++ b/web/data/cubicweb.widgets.js	Tue Feb 24 11:35:08 2009 +0100
@@ -181,14 +181,6 @@
     }
 }
 
-Widgets.TreeView = defclass("TreeView", null, {
-    __init__: function(wdgnode) {
-	jQuery(wdgnode).treeview({toggle: toggleTree,
-				  prerendered: true
-				 });
-    }
-});
-
 
 /* widget based on SIMILE's timeline widget
  * http://code.google.com/p/simile-widgets/
--- a/web/data/jquery.corner.js	Fri Feb 20 17:40:07 2009 +0100
+++ b/web/data/jquery.corner.js	Tue Feb 24 11:35:08 2009 +0100
@@ -1,1 +1,178 @@
-if(!document.createElement('canvas').getContext){(function(){var m=Math;var y=m.round;var z=m.sin;var A=m.cos;var Z=10;var B=Z/2;function getContext(){if(this.context_){return this.context_}return this.context_=new CanvasRenderingContext2D_(this)}var C=Array.prototype.slice;function bind(f,b,c){var a=C.call(arguments,2);return function(){return f.apply(b,a.concat(C.call(arguments)))}}var D={init:function(a){if(/MSIE/.test(navigator.userAgent)&&!window.opera){var b=a||document;b.createElement('canvas');b.attachEvent('onreadystatechange',bind(this.init_,this,b))}},init_:function(a){if(!a.namespaces['g_vml_']){a.namespaces.add('g_vml_','urn:schemas-microsoft-com:vml')}if(!a.styleSheets['ex_canvas_']){var b=a.createStyleSheet();b.owningElement.id='ex_canvas_';b.cssText='canvas{display:inline-block;overflow:hidden;'+'text-align:left;width:300px;height:150px}'+'g_vml_\\:*{behavior:url(#default#VML)}'}},i:function(a){if(!a.getContext){a.getContext=getContext;a.attachEvent('onpropertychange',onPropertyChange);a.attachEvent('onresize',onResize);var b=a.attributes;if(b.width&&b.width.specified){a.style.width=b.width.nodeValue+'px'}else{a.width=a.clientWidth}if(b.height&&b.height.specified){a.style.height=b.height.nodeValue+'px'}else{a.height=a.clientHeight}}return a}};function onPropertyChange(e){var a=e.srcElement;switch(e.propertyName){case'width':a.style.width=a.attributes.width.nodeValue+'px';a.getContext().clearRect();break;case'height':a.style.height=a.attributes.height.nodeValue+'px';a.getContext().clearRect();break}}function onResize(e){var a=e.srcElement;if(a.firstChild){a.firstChild.style.width=a.clientWidth+'px';a.firstChild.style.height=a.clientHeight+'px'}}D.init();var E=[];for(var i=0;i<16;i++){for(var j=0;j<16;j++){E[i*16+j]=i.toString(16)+j.toString(16)}}function createMatrixIdentity(){return[[1,0,0],[0,1,0],[0,0,1]]}function processStyle(a){var b,alpha=1;a=String(a);if(a.substring(0,3)=='rgb'){var c=a.indexOf('(',3);var d=a.indexOf(')',c+1);var e=a.substring(c+1,d).split(',');b='#';for(var i=0;i<3;i++){b+=E[Number(e[i])]}if(e.length==4&&a.substr(3,1)=='a'){alpha=e[3]}}else{b=a}return[b,alpha]}function processLineCap(a){switch(a){case'butt':return'flat';case'round':return'round';case'square':default:return'square'}}function CanvasRenderingContext2D_(a){this.m_=createMatrixIdentity();this.mStack_=[];this.aStack_=[];this.currentPath_=[];this.strokeStyle='#000';this.fillStyle='#000';this.lineWidth=1;this.lineJoin='miter';this.lineCap='butt';this.miterLimit=Z*1;this.globalAlpha=1;this.canvas=a;var b=a.ownerDocument.createElement('div');b.style.width=a.clientWidth+'px';b.style.height=a.clientHeight+'px';b.style.overflow='hidden';b.style.position='absolute';a.appendChild(b);this.element_=b;this.arcScaleX_=1;this.arcScaleY_=1}var F=CanvasRenderingContext2D_.prototype;F.clearRect=function(){this.element_.innerHTML='';this.currentPath_=[]};F.beginPath=function(){this.currentPath_=[]};F.moveTo=function(a,b){var p=this.getCoords_(a,b);this.currentPath_.push({type:'moveTo',x:p.x,y:p.y});this.currentX_=p.x;this.currentY_=p.y};F.lineTo=function(a,b){var p=this.getCoords_(a,b);this.currentPath_.push({type:'lineTo',x:p.x,y:p.y});this.currentX_=p.x;this.currentY_=p.y};F.bezierCurveTo=function(a,b,c,d,e,f){var p=this.getCoords_(e,f);var g=this.getCoords_(a,b);var h=this.getCoords_(c,d);this.currentPath_.push({type:'bezierCurveTo',cp1x:g.x,cp1y:g.y,cp2x:h.x,cp2y:h.y,x:p.x,y:p.y});this.currentX_=p.x;this.currentY_=p.y};F.fillRect=function(a,b,c,d){this.beginPath();this.moveTo(a,b);this.lineTo(a+c,b);this.lineTo(a+c,b+d);this.lineTo(a,b+d);this.closePath();this.fill();this.currentPath_=[]};F.createLinearGradient=function(a,b,c,d){return new CanvasGradient_('gradient')};F.createRadialGradient=function(a,b,c,d,e,f){var g=new CanvasGradient_('gradientradial');g.radius1_=c;g.radius2_=f;g.focus_.x=a;g.focus_.y=b;return g};F.stroke=function(d){var e=[];var f=false;var a=processStyle(d?this.fillStyle:this.strokeStyle);var g=a[0];var h=a[1]*this.globalAlpha;var W=10;var H=10;e.push('<g_vml_:shape',' fillcolor="',g,'"',' filled="',Boolean(d),'"',' style="position:absolute;width:',W,';height:',H,';"',' coordorigin="0 0" coordsize="',Z*W,' ',Z*H,'"',' stroked="',!d,'"',' strokeweight="',this.lineWidth,'"',' strokecolor="',g,'"',' path="');var j=false;var k={x:null,y:null};var l={x:null,y:null};for(var i=0;i<this.currentPath_.length;i++){var p=this.currentPath_[i];var c;switch(p.type){case'moveTo':e.push(' m ');c=p;e.push(y(p.x),',',y(p.y));break;case'lineTo':e.push(' l ');e.push(y(p.x),',',y(p.y));break;case'close':e.push(' x ');p=null;break;case'bezierCurveTo':e.push(' c ');e.push(y(p.cp1x),',',y(p.cp1y),',',y(p.cp2x),',',y(p.cp2y),',',y(p.x),',',y(p.y));break;case'at':case'wa':e.push(' ',p.type,' ');e.push(y(p.x-this.arcScaleX_*p.radius),',',y(p.y-this.arcScaleY_*p.radius),' ',y(p.x+this.arcScaleX_*p.radius),',',y(p.y+this.arcScaleY_*p.radius),' ',y(p.xStart),',',y(p.yStart),' ',y(p.xEnd),',',y(p.yEnd));break}if(p){if(k.x==null||p.x<k.x){k.x=p.x}if(l.x==null||p.x>l.x){l.x=p.x}if(k.y==null||p.y<k.y){k.y=p.y}if(l.y==null||p.y>l.y){l.y=p.y}}}e.push(' ">');if(typeof this.fillStyle=='object'){var m={x:'50%',y:'50%'};var n=l.x-k.x;var o=l.y-k.y;var q=n>o?n:o;m.x=y(this.fillStyle.focus_.x/n*100+50)+'%';m.y=y(this.fillStyle.focus_.y/o*100+50)+'%';var r=[];if(this.fillStyle.type_=='gradientradial'){var s=this.fillStyle.radius1_/q*100;var t=this.fillStyle.radius2_/q*100-s}else{var s=0;var t=100}var u={offset:null,color:null};var v={offset:null,color:null};this.fillStyle.colors_.sort(function(a,b){return a.offset-b.offset});for(var i=0;i<this.fillStyle.colors_.length;i++){var w=this.fillStyle.colors_[i];r.push(w.offset*t+s,'% ',w.color,',');if(w.offset>u.offset||u.offset==null){u.offset=w.offset;u.color=w.color}if(w.offset<v.offset||v.offset==null){v.offset=w.offset;v.color=w.color}}r.pop();e.push('<g_vml_:fill',' color="',v.color,'"',' color2="',u.color,'"',' type="',this.fillStyle.type_,'"',' focusposition="',m.x,', ',m.y,'"',' colors="',r.join(''),'"',' opacity="',h,'" />')}else if(d){e.push('<g_vml_:fill color="',g,'" opacity="',h,'" />')}else{var x=Math.max(this.arcScaleX_,this.arcScaleY_)*this.lineWidth;e.push('<g_vml_:stroke',' opacity="',h,'"',' joinstyle="',this.lineJoin,'"',' miterlimit="',this.miterLimit,'"',' endcap="',processLineCap(this.lineCap),'"',' weight="',x,'px"',' color="',g,'" />')}e.push('</g_vml_:shape>');this.element_.insertAdjacentHTML('beforeEnd',e.join(''))};F.fill=function(){this.stroke(true)};F.closePath=function(){this.currentPath_.push({type:'close'})};F.getCoords_=function(a,b){return{x:Z*(a*this.m_[0][0]+b*this.m_[1][0]+this.m_[2][0])-B,y:Z*(a*this.m_[0][1]+b*this.m_[1][1]+this.m_[2][1])-B}};function CanvasPattern_(){}G_vmlCMjrc=D})()}if(jQuery.browser.msie){document.execCommand("BackgroundImageCache",false,true)}(function($){var N=$.browser.msie;var O=N&&!window.XMLHttpRequest;var P=$.browser.opera;var Q=typeof document.createElement('canvas').getContext=="function";var R=function(i){return parseInt(i,10)||0};var S=function(a,b,c){var x=a,y;if(x.currentStyle){y=x.currentStyle[b]}else if(window.getComputedStyle){if(typeof arguments[2]=="string")b=c;y=document.defaultView.getComputedStyle(x,null).getPropertyValue(b)}return y};var T=function(a,p){return S(a,'border'+p+'Color','border-'+p.toLowerCase()+'-color')};var U=function(a,p){if(a.currentStyle&&!P){w=a.currentStyle['border'+p+'Width'];if(w=='thin')w=2;if(w=='medium'&&!(a.currentStyle['border'+p+'Style']=='none'))w=4;if(w=='thick')w=6}else{p=p.toLowerCase();w=document.defaultView.getComputedStyle(a,null).getPropertyValue('border-'+p+'-width')}return R(w)};var V=function(a,i){return a.tagName.toLowerCase()==i};var W=function(e,a,b,c,d){if(e=='tl')return a;if(e=='tr')return b;if(e=='bl')return c;if(e=='br')return d};var X=function(a,b,c,d,e,f,g){var h,curve_to;if(d.indexOf('rgba')!=-1){var i=/^rgba\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/;var j=i.exec(d);if(j){var k=[R(j[1]),R(j[2]),R(j[3])];d='rgb('+k[0]+', '+k[1]+', '+k[2]+')'}}var l=a.getContext('2d');if(b==1||g=='notch'){if(e>0&&b>1){l.fillStyle=f;l.fillRect(0,0,b,b);l.fillStyle=d;h=W(c,[0-e,0-e],[e,0-e],[0-e,e],[e,e]);l.fillRect(h[0],h[1],b,b)}else{l.fillStyle=d;l.fillRect(0,0,b,b)}return a}else if(g=='bevel'){h=W(c,[0,0,0,b,b,0,0,0],[0,0,b,b,b,0,0,0],[0,0,b,b,0,b,0,0],[b,b,b,0,0,b,b,b]);l.fillStyle=d;l.beginPath();l.moveTo(h[0],h[1]);l.lineTo(h[2],h[3]);l.lineTo(h[4],h[5]);l.lineTo(h[6],h[7]);l.fill();if(e>0&&e<b){l.strokeStyle=f;l.lineWidth=e;l.beginPath();h=W(c,[0,b,b,0],[0,0,b,b],[b,b,0,0],[0,b,b,0]);l.moveTo(h[0],h[1]);l.lineTo(h[2],h[3]);l.stroke()}return a}h=W(c,[0,0,b,0,b,0,0,b,0,0],[b,0,b,b,b,0,0,0,0,0],[0,b,b,b,0,b,0,0,0,b],[b,b,b,0,b,0,0,b,b,b]);l.fillStyle=d;l.beginPath();l.moveTo(h[0],h[1]);l.lineTo(h[2],h[3]);if(c=='br')l.bezierCurveTo(h[4],h[5],b,b,h[6],h[7]);else l.bezierCurveTo(h[4],h[5],0,0,h[6],h[7]);l.lineTo(h[8],h[9]);l.fill();if(e>0&&e<b){var m=e/2;var n=b-m;h=W(c,[n,m,n,m,m,n],[n,n,n,m,m,m],[n,n,m,n,m,m,m,n],[n,m,n,m,m,n,n,n]);curve_to=W(c,[0,0],[0,0],[0,0],[b,b]);l.strokeStyle=f;l.lineWidth=e;l.beginPath();l.moveTo(h[0],h[1]);l.bezierCurveTo(h[2],h[3],curve_to[0],curve_to[1],h[4],h[5]);l.stroke()}return a};var Y=function(p,a){var b=document.createElement('canvas');b.setAttribute("height",a);b.setAttribute("width",a);b.style.display="block";b.style.position="absolute";b.className="jrCorner";Z(p,b);if(!Q&&N){if(typeof G_vmlCanvasManager=="object"){b=G_vmlCanvasManager.initElement(b)}else if(typeof G_vmlCMjrc=="object"){b=G_vmlCMjrc.i(b)}else{throw Error('Could not find excanvas');}}return b};var Z=function(p,a){if(p.is("table")){p.children("tbody").children("tr:first").children("td:first").append(a);p.css('display','block')}else if(p.is("td")){if(p.children(".JrcTdContainer").length===0){p.html('<div class="JrcTdContainer" style="padding:0px;position:relative;margin:-1px;zoom:1;">'+p.html()+'</div>');p.css('zoom','1');if(O){p.children(".JrcTdContainer").get(0).style.setExpression("height","this.parentNode.offsetHeight")}}p.children(".JrcTdContainer").append(a)}else{p.append(a)}};if(N){var ba=document.createStyleSheet();ba.media='print';ba.cssText='.jrcIECanvasDiv { display:none !important; }'}var bb=function(D){if(this.length==0||!(Q||N)){return this}if(D=="destroy"){return this.each(function(){var p,elm=$(this);if(elm.is(".jrcRounded")){if(typeof elm.data("ie6tmr.jrc")=='number')window.clearInterval(elm.data("ie6tmr.jrc"));if(elm.is("table"))p=elm.children("tbody").children("tr:first").children("td:first");else if(elm.is("td"))p=elm.children(".JrcTdContainer");else p=elm;p.children(".jrCorner").remove();elm.unbind('mouseleave.jrc').unbind('mouseenter.jrc').removeClass('jrcRounded').removeData('ie6tmr.jrc');if(elm.is("td"))elm.html(elm.children(".JrcTdContainer").html())}})}var o=(D||"").toLowerCase();var E=R((o.match(/(\d+)px/)||[])[1])||"auto";var F=((o.match(/(#[0-9a-f]+)/)||[])[1])||"auto";var G=/round|bevel|notch/;var H=((o.match(G)||['round'])[0]);var I=/hover/.test(o);var J=/oversized/.test(o);var K=o.match("hiddenparent");if(N){var G=/ie6nofix|ie6fixinit|ie6fixexpr|ie6fixonload|ie6fixwidthint|ie6fixheightint|ie6fixbothint/;var L=((o.match(G)||['ie6fixinit'])[0])}var M={tl:/top|left|tl/.test(o),tr:/top|right|tr/.test(o),bl:/bottom|left|bl/.test(o),br:/bottom|right|br/.test(o)};if(!M.tl&&!M.tr&&!M.bl&&!M.br)M={tl:1,tr:1,bl:1,br:1};this.each(function(){var d=$(this),rbg=null,bg,s,b,pr;var a=this;var e=S(this,'display');var f=S(this,'position');var g=S(this,'lineHeight','line-height');if(F=="auto"){s=d.siblings(".jrcRounded:eq(0)");if(s.length>0){b=s.data("rbg.jrc");if(typeof b=="string"){rbg=b}}}if(K||rbg===null){var h=this.parentNode,hidden_parents=new Array(),a=0;while((typeof h=='object')&&!V(h,'html')){if(K&&S(h,'display')=='none'){hidden_parents.push({originalvisibility:S(h,'visibility'),elm:h});h.style.display='block';h.style.visibility='hidden'}var j=S(h,'backgroundColor','background-color');if(rbg===null&&j!="transparent"&&j!="rgba(0, 0, 0, 0)"){rbg=j}h=h.parentNode}if(rbg===null)rbg="#ffffff"}if(F=="auto"){bg=rbg;d.data("rbg.jrc",rbg)}else{bg=F}if(e=='none'){var k=S(this,'visibility');this.style.display='block';this.style.visibility='hidden';var l=true}else{var m=false}var n=d.height();var p=d.width();if(I){var q=o.replace(/hover|ie6nofix|ie6fixinit|ie6fixexpr|ie6fixonload|ie6fixwidthint|ie6fixheightint|ie6fixbothint/g,"");if(L!='ie6nofix')q="ie6fixinit "+q;d.bind("mouseenter.jrc",function(){d.addClass('jrcHover');d.corner(q)});d.bind("mouseleave.jrc",function(){d.removeClass('jrcHover');d.corner(q)})}if(O&&L!='ie6nofix'){this.style.zoom=1;if(L!='ie6fixexpr'){if(d.width()%2!=0)d.width(d.width()+1);if(d.height()%2!=0)d.height(d.height()+1)}$(window).load(function(){if(L=='ie6fixonload'){if(d.css('height')=='auto')d.height(d.css('height'));if(d.width()%2!=0)d.width(d.width()+1);if(d.height()%2!=0)d.height(d.height()+1)}else if(L=='ie6fixwidthint'||L=='ie6fixheightint'||L=='ie6fixbothint'){var c,ie6FixFunction;if(L=='ie6fixheightint'){ie6FixFunction=function(){d.height('auto');var a=d.height();if(a%2!=0)a=a+1;d.css({height:a})}}else if(L=='ie6fixwidthint'){ie6FixFunction=function(){d.width('auto');var a=d.width();if(a%2!=0)a=a+1;d.css({width:a});d.data('lastWidth.jrc',d.get(0).offsetWidth)}}else if(L=='ie6fixbothint'){ie6FixFunction=function(){d.width('auto');d.height('auto');var a=d.width();var b=d.height();if(b%2!=0)b=b+1;if(a%2!=0)a=a+1;d.css({width:a,height:b})}}c=window.setInterval(ie6FixFunction,100);d.data("ie6tmr.jrc",c)}})}var r=n<p?this.offsetHeight:this.offsetWidth;if(E=="auto"){E=r/2;if(E>10)E=r/4}if(E>r/2&&!J){E=r/2}E=Math.floor(E);var t=U(this,'Top');var u=U(this,'Right');var v=U(this,'Bottom');var w=U(this,'Left');if(f=='static'&&!V(this,'td')){this.style.position='relative'}else if(f=='fixed'&&N&&!(document.compatMode=='CSS1Compat'&&!O)){this.style.position='absolute'}if(t+u+v+w>0){this.style.overflow='visible'}if(l)d.css({display:'none',visibility:k});if(typeof hidden_parents!="undefined"){for(var i=0;i<hidden_parents.length;i++){hidden_parents[i].elm.style.display='none';hidden_parents[i].elm.style.visibility=hidden_parents[i].originalvisibility}}var x=0-t,p_right=0-u,p_bottom=0-v,p_left=0-w;var y=(d.find("canvas").length>0);if(y){if(V(this,'table'))pr=d.children("tbody").children("tr:first").children("td:first");else if(V(this,'td'))pr=d.children(".JrcTdContainer");else pr=d}if(M.tl){bordersWidth=t<w?t:w;if(y)pr.children("canvas.jrcTL").remove();var z=X(Y(d,E),E,'tl',bg,bordersWidth,T(this,'Top'),H);$(z).css({left:p_left,top:x}).addClass('jrcTL')}if(M.tr){bordersWidth=t<u?t:u;if(y)pr.children("canvas.jrcTR").remove();var A=X(Y(d,E),E,'tr',bg,bordersWidth,T(this,'Top'),H);$(A).css({right:p_right,top:x}).addClass('jrcTR')}if(M.bl){bordersWidth=v<w?v:w;if(y)pr.children("canvas.jrcBL").remove();var B=X(Y(d,E),E,'bl',bg,bordersWidth,T(this,'Bottom'),H);$(B).css({left:p_left,bottom:p_bottom}).addClass('jrcBL')}if(M.br){bordersWidth=v<u?v:u;if(y)pr.children("canvas.jrcBR").remove();var C=X(Y(d,E),E,'br',bg,bordersWidth,T(this,'Bottom'),H);$(C).css({right:p_right,bottom:p_bottom}).addClass('jrcBR')}if(N)d.children('canvas.jrCorner').children('div').addClass('jrcIECanvasDiv');if(O&&L=='ie6fixexpr'){if(M.bl){B.style.setExpression("bottom","this.parentNode.offsetHeight % 2 == 0 || this.parentNode.offsetWidth % 2 == 0 ? 0-(parseInt(this.parentNode.currentStyle['borderBottomWidth'])) : 0-(parseInt(this.parentNode.currentStyle['borderBottomWidth'])+1)")}if(M.br){C.style.setExpression("right","this.parentNode.offsetWidth  % 2 == 0 || this.parentNode.offsetWidth % 2 == 0 ? 0-(parseInt(this.parentNode.currentStyle['borderRightWidth']))  : 0-(parseInt(this.parentNode.currentStyle['borderRightWidth'])+1)");C.style.setExpression("bottom","this.parentNode.offsetHeight % 2 == 0 || this.parentNode.offsetWidth % 2 == 0 ? 0-(parseInt(this.parentNode.currentStyle['borderBottomWidth'])) : 0-(parseInt(this.parentNode.currentStyle['borderBottomWidth'])+1)")}if(M.tr){A.style.setExpression("right","this.parentNode.offsetWidth   % 2 == 0 || this.parentNode.offsetWidth % 2 == 0 ? 0-(parseInt(this.parentNode.currentStyle['borderRightWidth']))  : 0-(parseInt(this.parentNode.currentStyle['borderRightWidth'])+1)")}}d.addClass('jrcRounded')});if(typeof arguments[1]=="function")arguments[1](this);return this};$.fn.corner=bb})(jQuery);
\ No newline at end of file
+/*
+ * jQuery corner plugin
+ *
+ * version 1.92 (12/18/2007)
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ */
+
+/**
+ * The corner() method provides a simple way of styling DOM elements.  
+ *
+ * corner() takes a single string argument:  $().corner("effect corners width")
+ *
+ *   effect:  The name of the effect to apply, such as round or bevel. 
+ *            If you don't specify an effect, rounding is used.
+ *
+ *   corners: The corners can be one or more of top, bottom, tr, tl, br, or bl. 
+ *            By default, all four corners are adorned. 
+ *
+ *   width:   The width specifies the width of the effect; in the case of rounded corners this 
+ *            will be the radius of the width. 
+ *            Specify this value using the px suffix such as 10px, and yes it must be pixels.
+ *
+ * For more details see: http://methvin.com/jquery/jq-corner.html
+ * For a full demo see:  http://malsup.com/jquery/corner/
+ *
+ *
+ * @example $('.adorn').corner();
+ * @desc Create round, 10px corners 
+ *
+ * @example $('.adorn').corner("25px");
+ * @desc Create round, 25px corners 
+ *
+ * @example $('.adorn').corner("notch bottom");
+ * @desc Create notched, 10px corners on bottom only
+ *
+ * @example $('.adorn').corner("tr dog 25px");
+ * @desc Create dogeared, 25px corner on the top-right corner only
+ *
+ * @example $('.adorn').corner("round 8px").parent().css('padding', '4px').corner("round 10px");
+ * @desc Create a rounded border effect by styling both the element and its parent
+ * 
+ * @name corner
+ * @type jQuery
+ * @param String options Options which control the corner style
+ * @cat Plugins/Corner
+ * @return jQuery
+ * @author Dave Methvin (dave.methvin@gmail.com)
+ * @author Mike Alsup (malsup@gmail.com)
+ */
+(function($) { 
+
+$.fn.corner = function(o) {
+    var ie6 = $.browser.msie && /MSIE 6.0/.test(navigator.userAgent);
+    function sz(el, p) { return parseInt($.css(el,p))||0; };
+    function hex2(s) {
+        var s = parseInt(s).toString(16);
+        return ( s.length < 2 ) ? '0'+s : s;
+    };
+    function gpc(node) {
+        for ( ; node && node.nodeName.toLowerCase() != 'html'; node = node.parentNode ) {
+            var v = $.css(node,'backgroundColor');
+            if ( v.indexOf('rgb') >= 0 ) { 
+                if ($.browser.safari && v == 'rgba(0, 0, 0, 0)')
+                    continue;
+                var rgb = v.match(/\d+/g); 
+                return '#'+ hex2(rgb[0]) + hex2(rgb[1]) + hex2(rgb[2]);
+            }
+            if ( v && v != 'transparent' )
+                return v;
+        }
+        return '#ffffff';
+    };
+    function getW(i) {
+        switch(fx) {
+        case 'round':  return Math.round(width*(1-Math.cos(Math.asin(i/width))));
+        case 'cool':   return Math.round(width*(1+Math.cos(Math.asin(i/width))));
+        case 'sharp':  return Math.round(width*(1-Math.cos(Math.acos(i/width))));
+        case 'bite':   return Math.round(width*(Math.cos(Math.asin((width-i-1)/width))));
+        case 'slide':  return Math.round(width*(Math.atan2(i,width/i)));
+        case 'jut':    return Math.round(width*(Math.atan2(width,(width-i-1))));
+        case 'curl':   return Math.round(width*(Math.atan(i)));
+        case 'tear':   return Math.round(width*(Math.cos(i)));
+        case 'wicked': return Math.round(width*(Math.tan(i)));
+        case 'long':   return Math.round(width*(Math.sqrt(i)));
+        case 'sculpt': return Math.round(width*(Math.log((width-i-1),width)));
+        case 'dog':    return (i&1) ? (i+1) : width;
+        case 'dog2':   return (i&2) ? (i+1) : width;
+        case 'dog3':   return (i&3) ? (i+1) : width;
+        case 'fray':   return (i%2)*width;
+        case 'notch':  return width; 
+        case 'bevel':  return i+1;
+        }
+    };
+    o = (o||"").toLowerCase();
+    var keep = /keep/.test(o);                       // keep borders?
+    var cc = ((o.match(/cc:(#[0-9a-f]+)/)||[])[1]);  // corner color
+    var sc = ((o.match(/sc:(#[0-9a-f]+)/)||[])[1]);  // strip color
+    var width = parseInt((o.match(/(\d+)px/)||[])[1]) || 10; // corner width
+    var re = /round|bevel|notch|bite|cool|sharp|slide|jut|curl|tear|fray|wicked|sculpt|long|dog3|dog2|dog/;
+    var fx = ((o.match(re)||['round'])[0]);
+    var edges = { T:0, B:1 };
+    var opts = {
+        TL:  /top|tl/.test(o),       TR:  /top|tr/.test(o),
+        BL:  /bottom|bl/.test(o),    BR:  /bottom|br/.test(o)
+    };
+    if ( !opts.TL && !opts.TR && !opts.BL && !opts.BR )
+        opts = { TL:1, TR:1, BL:1, BR:1 };
+    var strip = document.createElement('div');
+    strip.style.overflow = 'hidden';
+    strip.style.height = '1px';
+    strip.style.backgroundColor = sc || 'transparent';
+    strip.style.borderStyle = 'solid';
+    return this.each(function(index){
+        var pad = {
+            T: parseInt($.css(this,'paddingTop'))||0,     R: parseInt($.css(this,'paddingRight'))||0,
+            B: parseInt($.css(this,'paddingBottom'))||0,  L: parseInt($.css(this,'paddingLeft'))||0
+        };
+
+        if ($.browser.msie) this.style.zoom = 1; // force 'hasLayout' in IE
+        if (!keep) this.style.border = 'none';
+        strip.style.borderColor = cc || gpc(this.parentNode);
+        var cssHeight = $.curCSS(this, 'height');
+
+        for (var j in edges) {
+            var bot = edges[j];
+            // only add stips if needed
+            if ((bot && (opts.BL || opts.BR)) || (!bot && (opts.TL || opts.TR))) {
+                strip.style.borderStyle = 'none '+(opts[j+'R']?'solid':'none')+' none '+(opts[j+'L']?'solid':'none');
+                var d = document.createElement('div');
+                $(d).addClass('jquery-corner');
+                var ds = d.style;
+
+                bot ? this.appendChild(d) : this.insertBefore(d, this.firstChild);
+
+                if (bot && cssHeight != 'auto') {
+                    if ($.css(this,'position') == 'static')
+                        this.style.position = 'relative';
+                    ds.position = 'absolute';
+                    ds.bottom = ds.left = ds.padding = ds.margin = '0';
+                    if ($.browser.msie)
+                        ds.setExpression('width', 'this.parentNode.offsetWidth');
+                    else
+                        ds.width = '100%';
+                }
+                else if (!bot && $.browser.msie) {
+                    if ($.css(this,'position') == 'static')
+                        this.style.position = 'relative';
+                    ds.position = 'absolute';
+                    ds.top = ds.left = ds.right = ds.padding = ds.margin = '0';
+                    
+                    // fix ie6 problem when blocked element has a border width
+                    var bw = 0;
+                    if (ie6 || !$.boxModel)
+                        bw = sz(this,'borderLeftWidth') + sz(this,'borderRightWidth');
+                    ie6 ? ds.setExpression('width', 'this.parentNode.offsetWidth - '+bw+'+ "px"') : ds.width = '100%';
+                }
+                else {
+                    ds.margin = !bot ? '-'+pad.T+'px -'+pad.R+'px '+(pad.T-width)+'px -'+pad.L+'px' : 
+                                        (pad.B-width)+'px -'+pad.R+'px -'+pad.B+'px -'+pad.L+'px';                
+                }
+
+                for (var i=0; i < width; i++) {
+                    var w = Math.max(0,getW(i));
+                    var e = strip.cloneNode(false);
+                    e.style.borderWidth = '0 '+(opts[j+'R']?w:0)+'px 0 '+(opts[j+'L']?w:0)+'px';
+                    bot ? d.appendChild(e) : d.insertBefore(e, d.firstChild);
+                }
+            }
+        }
+    });
+};
+
+$.fn.uncorner = function(o) { return $('.jquery-corner', this).remove(); };
+    
+})(jQuery);
--- a/web/views/basecomponents.py	Fri Feb 20 17:40:07 2009 +0100
+++ b/web/views/basecomponents.py	Tue Feb 24 11:35:08 2009 +0100
@@ -44,11 +44,11 @@
           <form action="%s">
 <fieldset>
 <input type="text" id="rql" name="rql" value="%s"  title="%s" tabindex="%s" accesskey="q" class="searchField" />
-<input type="submit" value="%s" class="searchButton" tabindex="%s" />
+<input type="submit" value="" class="rqlsubmit" tabindex="%s" />
 </fieldset>
 ''' % (not self.propval('visible') and 'hidden' or '', 
        self.build_url('view'), html_escape(rql), req._('full text or RQL query'), req.next_tabindex(),
-       req._('search'), req.next_tabindex()))
+        req.next_tabindex()))
         if self.req.search_state[0] != 'normal':
             self.w(u'<input type="hidden" name="__mode" value="%s"/>'
                    % ':'.join(req.search_state[1]))
--- a/web/views/basetemplates.py	Fri Feb 20 17:40:07 2009 +0100
+++ b/web/views/basetemplates.py	Tue Feb 24 11:35:08 2009 +0100
@@ -56,8 +56,9 @@
     title = 'logged out'
 
     def content(self, w):
+        # FIXME Deprecated code ?
         msg = self.req._('you have been logged out')
-        w(u'<h1 class="noborder">%s</h1>\n' % msg)
+        w(u'<h2>%s</h2>\n' % msg)
         if self.config['anonymous-user']:
             indexurl = self.build_url('view', vid='index', __message=msg)
             w(u'<p><a href="%s">%s</a><p>' % (
--- a/web/views/bookmark.py	Fri Feb 20 17:40:07 2009 +0100
+++ b/web/views/bookmark.py	Tue Feb 24 11:35:08 2009 +0100
@@ -81,9 +81,9 @@
                 dlink = u'[<a href="javascript:removeBookmark(%s)" title="%s">-</a>]' % (
                     bookmark.eid, _('delete this bookmark'))
                 label = '%s %s' % (dlink, label)
-            box.append(RawBoxItem(label, liclass=u'invisible'))
+            box.append(RawBoxItem(label))
         if eschema.has_perm(req, 'add') and rschema.has_perm(req, 'add', toeid=ueid):
-            boxmenu = BoxMenu(req._('manage bookmarks'), liclass=u'invisible')
+            boxmenu = BoxMenu(req._('manage bookmarks'))
             linkto = 'bookmarked_by:%s:subject' % ueid
             # use a relative path so that we can move the application without
             # loosing bookmarks
--- a/web/views/boxes.py	Fri Feb 20 17:40:07 2009 +0100
+++ b/web/views/boxes.py	Tue Feb 24 11:35:08 2009 +0100
@@ -145,7 +145,7 @@
 <input type="hidden" name="__fromsearchbox" value="1" />
 <input type="hidden" name="subvid" value="tsearch" />
 </td><td>
-<input tabindex="%s" type="submit" id="rqlboxsubmit" value="" />
+<input tabindex="%s" type="submit" id="rqlboxsubmit" class="rqlsubmit" value="" />
 </td></tr></table>
 </form>"""
 
--- a/web/views/owl.py	Fri Feb 20 17:40:07 2009 +0100
+++ b/web/views/owl.py	Tue Feb 24 11:35:08 2009 +0100
@@ -1,4 +1,4 @@
-from logilab.mtconverter import TransformError, html_escape
+from logilab.mtconverter import TransformError, xml_escape
 
 from cubicweb.common.view import StartupView
 from cubicweb.common.view import EntityView
@@ -159,7 +159,6 @@
     
     def call(self):
         self.w(OWL_OPENING_ROOT % {'appid': self.schema.name})
-        self.wview('owl', None, writeprefix=False)
         for i in xrange(self.rset.rowcount):
             self.cell_call(i, 0)
         self.w(OWL_CLOSING_ROOT)
@@ -190,7 +189,7 @@
             try:
                 attr = entity.printable_value(aname, format='text/plain')
                 if attr:
-                    self.w(u'<%s>%s</%s>' % (aname, html_escape(attr), aname))
+                    self.w(u'<%s>%s</%s>' % (aname, xml_escape(attr), aname))
             except TransformError:
                 pass
         self.w(u'<!--relations -->')
--- a/web/views/startup.py	Fri Feb 20 17:40:07 2009 +0100
+++ b/web/views/startup.py	Tue Feb 24 11:35:08 2009 +0100
@@ -26,6 +26,7 @@
     
     def call(self, **kwargs):
         """The default view representing the application's management"""
+        self.req.add_css('cubicweb.manageview.css')
         self.w(u'<div>\n')
         if not self.display_folders():
             self._main_index()
--- a/web/views/tableview.py	Fri Feb 20 17:40:07 2009 +0100
+++ b/web/views/tableview.py	Tue Feb 24 11:35:08 2009 +0100
@@ -102,7 +102,7 @@
         rset = self.rset
         req = self.req
         req.add_js('jquery.tablesorter.js')
-        req.add_css('cubicweb.tablesorter.css')
+        req.add_css(('cubicweb.tablesorter.css', 'cubicweb.tableview.css'))
         rqlst = rset.syntax_tree()
         # get rql description first since the filter form may remove some
         # necessary information
--- a/web/views/tabs.py	Fri Feb 20 17:40:07 2009 +0100
+++ b/web/views/tabs.py	Tue Feb 24 11:35:08 2009 +0100
@@ -13,6 +13,7 @@
 from cubicweb import NoSelectableObject, role
 from cubicweb.selectors import partial_has_related_entities
 from cubicweb.common.view import EntityView
+from cubicweb.common.selectors import has_related_entities
 from cubicweb.common.utils import HTMLHead
 from cubicweb.common.uilib import rql_for_eid
 
@@ -33,15 +34,22 @@
   });""" % {'event': 'load_%s' % vid, 'vid': vid,
             'reloadable' : str(reloadable).lower()})
 
-    def lazyview(self, vid, eid=None, reloadable=False, show_spinbox=True, w=None):
+    def lazyview(self, vid, rql=None, eid=None, rset=None, static=False,
+                 reloadable=False, show_spinbox=True, w=None):
         """a lazy version of wview
         first version only support lazy viewing for an entity at a time
         """
+        assert rql or eid or rset or static, \
+            'lazyview wants at least : rql, or an eid, or an rset -- or call it with static=True'
         w = w or self.w
         self.req.add_js('cubicweb.lazy.js')
         urlparams = {'vid' : vid, 'mode' : 'html'}
-        if eid:
+        if rql:
+            urlparams['rql'] = rql
+        elif eid:
             urlparams['rql'] = rql_for_eid(eid)
+        elif rset:
+            urlparams['rql'] = rset.printable_rql()
         w(u'<div id="lazy-%s" cubicweb:loadurl="%s">' % (
             vid, html_escape(self.build_url('json', **urlparams))))
         if show_spinbox:
@@ -65,12 +73,12 @@
         return str('%s_active_tab' % self.config.appid)
 
     def active_tab(self, tabs, default):
-        cookie = self.req.get_cookie()
+        cookies = self.req.get_cookie()
         cookiename = self.cookie_name
-        activetab = cookie.get(cookiename)
+        activetab = cookies.get(cookiename)
         if activetab is None:
-            cookie[cookiename] = default
-            self.req.set_cookie(cookie, cookiename)
+            cookies[cookiename] = default
+            self.req.set_cookie(cookies, cookiename)
             tab = default
         else:
             tab = activetab.value
@@ -96,7 +104,7 @@
         active_tab = self.active_tab(tabs, default)
         # build the html structure
         w = self.w
-        w(u'<div id="entity-tabs">')
+        w(u'<div id="entity-tabs-%s">' % entity.eid)
         w(u'<ul>')
         for tab in tabs:
             w(u'<li>')
@@ -110,38 +118,47 @@
         w(u'</div>')
         for tab in tabs:
             w(u'<div id="as-%s">' % tab)
-            self.lazyview(tab, entity.eid)
+            self.lazyview(tab, eid=entity.eid)
             w(u'</div>')
         # call the set_tab() JS function *after* each tab is generated
         # because the callback binding needs to be done before
         self.req.html_headers.add_onload(u"""
-   jQuery('#entity-tabs > ul').tabs( { selected: %(tabindex)s });
+   jQuery('#entity-tabs-%(eeid)s > ul').tabs( { selected: %(tabindex)s });
    set_tab('%(vid)s', '%(cookiename)s');
  """ % {'tabindex'   : tabs.index(active_tab),
         'vid'        : active_tab,
+        'eeid'       : entity.eid,
         'cookiename' : self.cookie_name})
 
 
-
-class EntityRelationView(EntityView):
-    """view displaying entity related stuff. Such a view _must_ provide rtype
-    and target attributes
+class EntityRelatedTab(EntityView):
+    """A view you should inherit from leftmost,
+    to wrap another actual view displaying entity related stuff.
+    Such a view _must_ provide the rtype, target and vid attributes :
 
     Example :
 
     class ProjectScreenshotsView(EntityRelationView):
         '''display project's screenshots'''
         id = title = _('projectscreenshots')
-        __select__ = implements('Project')
+        accepts = ('Project',)
         rtype = 'screenshot'
         target = 'object'
+        vid = 'gallery'
+        __selectors__ = EntityRelationView.__selectors__ + (one_line_rset,)
+
+
+    This is the view we want to have in a tab, only if there is something to show.
+    Then, just define as below, and declare this being the tab content :
+
+    class ProjectScreenshotTab(EntityRelatedTab, ProjectScreenshotsView):
+        id = 'screenshots_tab'
     """
     __select__ = EntityView.__select__ & partial_has_related_entities()
     vid = 'list'
     
     def cell_call(self, row, col):
-        rset = self.rset.get_entity(row, col).related(self.rtype, role(self))
-        self.w(u'<h1>%s</h1>' % self.req._(self.title).capitalize())
+        rset = self.entity(row, col).related(self.rtype, role(self))
         self.w(u'<div class="mainInfo">')
         self.wview(self.vid, rset, 'noresult')
         self.w(u'</div>')
--- a/web/views/treeview.py	Fri Feb 20 17:40:07 2009 +0100
+++ b/web/views/treeview.py	Tue Feb 24 11:35:08 2009 +0100
@@ -1,33 +1,48 @@
+"""Set of tree-building widgets, based on jQuery treeview plugin
+
+:organization: Logilab
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
+"""
+__docformat__ = "restructuredtext en"
+
 from logilab.mtconverter import html_escape
+from cubicweb.interfaces import ITree
+from cubicweb.common.selectors import implement_interface, yes
+from cubicweb.common.view import EntityView
 
 from cubicweb.interfaces import ITree
-from cubicweb.selectors import implements
-from cubicweb.view import EntityView
+from cubicweb.common.selectors import implement_interface, yes
+from cubicweb.common.view import EntityView
+
+def treecookiename(treeid):
+    return str('treestate-%s' % treeid)
 
 class TreeView(EntityView):
     id = 'treeview'
+    accepts = ('Any',)
     itemvid = 'treeitemview'
     css_classes = 'treeview widget'
     title = _('tree view')
-    
-    def call(self, subvid=None):
+
+    def call(self, subvid=None, treeid=None, initial_load=True):
         if subvid is None and 'subvid' in self.req.form:
             subvid = self.req.form.pop('subvid') # consume it
         if subvid is None:
             subvid = 'oneline'
-        self.req.add_css('jquery.treeview.css')
-        self.req.add_js(('cubicweb.ajax.js', 'jquery.treeview.js', 'cubicweb.widgets.js'))
-        # XXX noautoload is a quick hack to avoid treeview to be rebuilt
-        #     after a json query and avoid double toggling bugs.
-        #     Need to find a way to do that cleanly.
-        if 'noautoload' in self.req.form:
-            self.w(u'<ul class="%s" cubicweb:wdgtype="TreeView">' % self.css_classes)
-        else:
-            self.w(u'<ul class="%s" cubicweb:loadtype="auto" cubicweb:wdgtype="TreeView">'
-                   % self.css_classes)
+        if treeid is None and 'treeid' in self.req.form:
+            treeid = self.req.form.pop('treeid')
+        assert treeid is not None
+        if initial_load:
+            self.req.add_css('jquery.treeview.css')
+            self.req.add_js(('cubicweb.ajax.js', 'jquery.treeview.js'))
+            self.req.html_headers.add_onload(u"""
+                 jQuery("#tree-%s").treeview({toggle: toggleTree,
+                                              prerendered: true});""" % treeid)
+        self.w(u'<ul id="tree-%s" class="%s">' % (treeid, self.css_classes))
         for rowidx in xrange(len(self.rset)):
             self.wview(self.itemvid, self.rset, row=rowidx, col=0,
-                       vid=subvid, parentvid=self.id)
+                       vid=subvid, parentvid=self.id, treeid=treeid)
         self.w(u'</ul>')
         
 
@@ -38,10 +53,8 @@
     css_classes = 'treeview widget filetree'
     title = _('file tree view')
 
-    def call(self, subvid=None):
-        super(FileTreeView, self).call(subvid='filetree-oneline')
-
-
+    def call(self, subvid=None, treeid=None, initial_load=True):
+        super(FileTreeView, self).call(treeid=treeid, subvid='filetree-oneline', initial_load=initial_load)
 
 class FileItemInnerView(EntityView):
     """inner view used by the TreeItemView instead of oneline view
@@ -54,18 +67,20 @@
     def cell_call(self, row, col):
         entity = self.entity(row, col)
         if ITree.is_implemented_by(entity.__class__) and not entity.is_leaf():
-            self.w(u'<div class="folder">%s</div>' % entity.view('oneline'))
+            self.w(u'<div class="folder">%s</div>\n' % entity.view('oneline'))
         else:
             # XXX define specific CSS classes according to mime types
-            self.w(u'<div class="file">%s</div>' % entity.view('oneline'))
+            self.w(u'<div class="file">%s</div>\n' % entity.view('oneline'))
 
 
 class DefaultTreeViewItemView(EntityView):
     """default treeitem view for entities which don't implement ITree
     """
     id = 'treeitemview'
-    
-    def cell_call(self, row, col, vid='oneline', parentvid='treeview'):
+    accepts = ('Any',)
+
+    def cell_call(self, row, col, vid='oneline', parentvid='treeview', treeid=None):
+        assert treeid is not None
         entity = self.entity(row, col)
         itemview = self.view(vid, self.rset, row=row, col=col)
         if row == len(self.rset) - 1:
@@ -76,38 +91,91 @@
 
 class TreeViewItemView(EntityView):
     """specific treeitem view for entities which implement ITree
-    
+
     (each item should be exandable if it's not a tree leaf)
     """
     id = 'treeitemview'
-    __select__ = implements(ITree)
-    
-    def cell_call(self, row, col, vid='oneline', parentvid='treeview'):
+    # XXX append yes to make sure we get an higher score than
+    #     the default treeitem view
+    __selectors__ = (implement_interface, yes)
+    accepts_interfaces = (ITree,)
+
+    def open_state(self, eeid, treeid):
+        cookies = self.req.get_cookie()
+        treestate = cookies.get(treecookiename(treeid))
+        if treestate:
+            return str(eeid) in treestate.value.split(';')
+        return False
+
+    def cell_call(self, row, col, treeid, vid='oneline', parentvid='treeview'):
+        w = self.w
         entity = self.entity(row, col)
-        cssclasses = []
+        liclasses = []
         is_leaf = False
-        if row == len(self.rset) - 1:
-            is_leaf = True
+        is_last = row == len(self.rset) - 1
+        is_open = self.open_state(entity.eid, treeid)
         if not hasattr(entity, 'is_leaf') or entity.is_leaf():
-            if is_leaf : cssclasses.append('last')
-            self.w(u'<li class="%s">' % u' '.join(cssclasses))
+            if is_last:
+                liclasses.append('last')
+            w(u'<li class="%s">' % u' '.join(liclasses))
         else:
             rql = entity.children_rql() % {'x': entity.eid}
             url = html_escape(self.build_url('json', rql=rql, vid=parentvid,
                                              pageid=self.req.pageid,
-                                             subvid=vid,
-                                             noautoload=True))
-            cssclasses.append('expandable')
-            divclasses = ['hitarea expandable-hitarea']
-            if is_leaf :
-                cssclasses.append('lastExpandable')
-                divclasses.append('lastExpandable-hitarea')
-            self.w(u'<li cubicweb:loadurl="%s" class="%s">' % (url, u' '.join(cssclasses)))
-            self.w(u'<div class="%s"> </div>' % u' '.join(divclasses))
-                
+                                             treeid=treeid,
+                                             subvid=vid))
+            divclasses = ['hitarea']
+            if is_open:
+                liclasses.append('collapsable')
+                divclasses.append('collapsable-hitarea')
+            else:
+                liclasses.append('expandable')
+                divclasses.append('closed-hitarea expandable-hitarea')
+            if is_last:
+                if is_open:
+                    liclasses.append('lastCollapsable')
+                    divclasses.append('lastCollapsable-hitarea')
+                else:
+                    liclasses.append('lastExpandable')
+                    divclasses.append('lastExpandable-hitarea')
+            if is_open:
+                w(u'<li class="%s">' % u' '.join(liclasses))
+            else:
+                w(u'<li cubicweb:loadurl="%s" class="%s">' % (url, u' '.join(liclasses)))
+            if is_leaf:
+                divtail = ''
+            else:
+                divtail = ''' onclick="async_remote_exec('node_clicked', '%s', '%s')"''' % \
+                    (treeid, entity.eid)
+            w(u'<div class="%s"%s></div>' % (u' '.join(divclasses), divtail))
+
             # add empty <ul> because jquery's treeview plugin checks for
             # sublists presence
-            self.w(u'<ul class="placeholder"><li>place holder</li></ul>')
+            if not is_open:
+                w(u'<ul class="placeholder"><li>place holder</li></ul>')
+        # the local node info
         self.wview(vid, self.rset, row=row, col=col)
-        self.w(u'</li>')
+        if is_open: # recurse if needed
+            self.wview(parentvid, self.req.execute(rql), treeid=treeid, initial_load=False)
+        w(u'</li>')
+
+from logilab.common.decorators import monkeypatch
+from cubicweb.web.views.basecontrollers import JSonController
 
+@monkeypatch(JSonController)
+def js_node_clicked(self, treeid, nodeeid):
+    """add/remove eid in treestate cookie"""
+    cookies = self.req.get_cookie()
+    statename = treecookiename(treeid)
+    treestate = cookies.get(statename)
+    if treestate is None:
+        cookies[statename] = nodeeid
+        self.req.set_cookie(cookies, statename)
+    else:
+        marked = set(filter(None, treestate.value.split(';')))
+        if nodeeid in marked:
+            marked.remove(nodeeid)
+        else:
+            marked.add(nodeeid)
+        cookies[statename] = ';'.join(marked)
+        self.req.set_cookie(cookies, statename)