# HG changeset patch # User Aurelien Campeas # Date 1235471708 -3600 # Node ID ad72e06320e2ef17f18748b791660849299e87bf # Parent 5dfba71b1872aba2ecaed1cbaba62303e3212978# Parent 7b701df4dbef6980e304235eafe39a78d56f28e6 merge diff -r 5dfba71b1872 -r ad72e06320e2 __pkginfo__.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 diff -r 5dfba71b1872 -r ad72e06320e2 common/migration.py --- 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 diff -r 5dfba71b1872 -r ad72e06320e2 debian/changelog --- 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 Thu, 19 Feb 2009 16:24:09 +0100 + cubicweb (3.0.9-1) unstable; urgency=low * new upstream (interim) release diff -r 5dfba71b1872 -r ad72e06320e2 debian/compat --- 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 diff -r 5dfba71b1872 -r ad72e06320e2 debian/control --- 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 -Uploaders: Sylvain Thenault -Build-Depends: debhelper (>= 5.0.37.1), python (>=2.4), python-dev (>=2.4), python-central (>= 0.5) +Uploaders: Sylvain Thenault , + Julien Jehannet +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} diff -r 5dfba71b1872 -r ad72e06320e2 debian/cubicweb-client.dirs --- 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/ diff -r 5dfba71b1872 -r ad72e06320e2 debian/cubicweb-client.install.in --- /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 diff -r 5dfba71b1872 -r ad72e06320e2 debian/cubicweb-common.dirs --- 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 diff -r 5dfba71b1872 -r ad72e06320e2 debian/cubicweb-common.install.in --- /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 diff -r 5dfba71b1872 -r ad72e06320e2 debian/cubicweb-core.dirs --- 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 diff -r 5dfba71b1872 -r ad72e06320e2 debian/cubicweb-ctl.cubicweb.init --- 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 diff -r 5dfba71b1872 -r ad72e06320e2 debian/cubicweb-ctl.install.in --- /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 diff -r 5dfba71b1872 -r ad72e06320e2 debian/cubicweb-dev.dirs --- 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 diff -r 5dfba71b1872 -r ad72e06320e2 debian/cubicweb-dev.install.in --- /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/ diff -r 5dfba71b1872 -r ad72e06320e2 debian/cubicweb-documentation.dirs --- 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/ diff -r 5dfba71b1872 -r ad72e06320e2 debian/cubicweb-documentation.install --- 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/ diff -r 5dfba71b1872 -r ad72e06320e2 debian/cubicweb-documentation.install.in --- /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 diff -r 5dfba71b1872 -r ad72e06320e2 debian/cubicweb-server.dirs --- 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 diff -r 5dfba71b1872 -r ad72e06320e2 debian/cubicweb-server.install.in --- /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/ diff -r 5dfba71b1872 -r ad72e06320e2 debian/cubicweb-twisted.dirs --- 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 diff -r 5dfba71b1872 -r ad72e06320e2 debian/cubicweb-twisted.install.in --- /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/ diff -r 5dfba71b1872 -r ad72e06320e2 debian/cubicweb-web.dirs --- 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 diff -r 5dfba71b1872 -r ad72e06320e2 debian/cubicweb-web.install.in --- /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 diff -r 5dfba71b1872 -r ad72e06320e2 debian/cubicweb-web.lintian-overrides --- /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 diff -r 5dfba71b1872 -r ad72e06320e2 debian/rules --- 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 diff -r 5dfba71b1872 -r ad72e06320e2 doc/book/en/B0020-define-workflows.en.txt --- 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. - diff -r 5dfba71b1872 -r ad72e06320e2 doc/book/en/B1060-templates.en.txt --- 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 diff -r 5dfba71b1872 -r ad72e06320e2 doc/book/fr/03-XX-external_resources.fr.txt --- /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. diff -r 5dfba71b1872 -r ad72e06320e2 server/migractions.py --- 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): diff -r 5dfba71b1872 -r ad72e06320e2 server/session.py --- 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 diff -r 5dfba71b1872 -r ad72e06320e2 web/data/cubicweb.calendar.css --- 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 { diff -r 5dfba71b1872 -r ad72e06320e2 web/data/cubicweb.calendar_popup.css --- 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; diff -r 5dfba71b1872 -r ad72e06320e2 web/data/cubicweb.css --- 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; +} diff -r 5dfba71b1872 -r ad72e06320e2 web/data/cubicweb.facets.css --- 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; } diff -r 5dfba71b1872 -r ad72e06320e2 web/data/cubicweb.form.css --- 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; +} + diff -r 5dfba71b1872 -r ad72e06320e2 web/data/cubicweb.login.css --- 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; } diff -r 5dfba71b1872 -r ad72e06320e2 web/data/cubicweb.manageview.css --- /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; +} diff -r 5dfba71b1872 -r ad72e06320e2 web/data/cubicweb.schema.css --- 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; diff -r 5dfba71b1872 -r ad72e06320e2 web/data/cubicweb.tableview.css --- /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 +} diff -r 5dfba71b1872 -r ad72e06320e2 web/data/cubicweb.timetable.css --- 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; } diff -r 5dfba71b1872 -r ad72e06320e2 web/data/cubicweb.widgets.js --- 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/ diff -r 5dfba71b1872 -r ad72e06320e2 web/data/jquery.corner.js --- 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('');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;iu.offset||u.offset==null){u.offset=w.offset;u.color=w.color}if(w.offset')}else if(d){e.push('')}else{var x=Math.max(this.arcScaleX_,this.arcScaleY_)*this.lineWidth;e.push('')}e.push('');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&&e0&&e'+p.html()+'');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=n10)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;i0);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= 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); diff -r 5dfba71b1872 -r ad72e06320e2 web/views/basecomponents.py --- 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 @@
- +
''' % (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'' % ':'.join(req.search_state[1])) diff -r 5dfba71b1872 -r ad72e06320e2 web/views/basetemplates.py --- 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'

%s

\n' % msg) + w(u'

%s

\n' % msg) if self.config['anonymous-user']: indexurl = self.build_url('view', vid='index', __message=msg) w(u'

%s

' % ( diff -r 5dfba71b1872 -r ad72e06320e2 web/views/bookmark.py --- 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'[-]' % ( 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 diff -r 5dfba71b1872 -r ad72e06320e2 web/views/boxes.py --- 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 @@ - +

""" diff -r 5dfba71b1872 -r ad72e06320e2 web/views/owl.py --- 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' % (aname, html_escape(attr), aname)) + self.w(u'<%s>%s' % (aname, xml_escape(attr), aname)) except TransformError: pass self.w(u'') diff -r 5dfba71b1872 -r ad72e06320e2 web/views/startup.py --- 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'
\n') if not self.display_folders(): self._main_index() diff -r 5dfba71b1872 -r ad72e06320e2 web/views/tableview.py --- 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 diff -r 5dfba71b1872 -r ad72e06320e2 web/views/tabs.py --- 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'
' % ( 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'
') + w(u'
' % entity.eid) w(u'
    ') for tab in tabs: w(u'
  • ') @@ -110,38 +118,47 @@ w(u'
') for tab in tabs: w(u'
' % tab) - self.lazyview(tab, entity.eid) + self.lazyview(tab, eid=entity.eid) w(u'
') # 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'

%s

' % self.req._(self.title).capitalize()) + rset = self.entity(row, col).related(self.rtype, role(self)) self.w(u'
') self.wview(self.vid, rset, 'noresult') self.w(u'
') diff -r 5dfba71b1872 -r ad72e06320e2 web/views/treeview.py --- 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'
    ' % self.css_classes) - else: - self.w(u'
      ' - % 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'
        ' % (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'
      ') @@ -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'
      %s
      ' % entity.view('oneline')) + self.w(u'
      %s
      \n' % entity.view('oneline')) else: # XXX define specific CSS classes according to mime types - self.w(u'
      %s
      ' % entity.view('oneline')) + self.w(u'
      %s
      \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'
    • ' % u' '.join(cssclasses)) + if is_last: + liclasses.append('last') + w(u'
    • ' % 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'
    • ' % (url, u' '.join(cssclasses))) - self.w(u'
      ' % 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'
    • ' % u' '.join(liclasses)) + else: + w(u'
    • ' % (url, u' '.join(liclasses))) + if is_leaf: + divtail = '' + else: + divtail = ''' onclick="async_remote_exec('node_clicked', '%s', '%s')"''' % \ + (treeid, entity.eid) + w(u'
      ' % (u' '.join(divclasses), divtail)) + # add empty
        because jquery's treeview plugin checks for # sublists presence - self.w(u'
        • place holder
        ') + if not is_open: + w(u'
        • place holder
        ') + # the local node info self.wview(vid, self.rset, row=row, col=col) - self.w(u'') + if is_open: # recurse if needed + self.wview(parentvid, self.req.execute(rql), treeid=treeid, initial_load=False) + w(u'') + +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)