diff options
Diffstat (limited to 'doc')
27 files changed, 0 insertions, 3893 deletions
diff --git a/doc/Makefile b/doc/Makefile deleted file mode 100644 index c1eff186583..00000000000 --- a/doc/Makefile +++ /dev/null @@ -1,154 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -q -SPHINXBUILD = sphinx-build -PAPER = -BUILDDIR = _build - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . -# the i18n builder cannot share the environment and doctrees with the others -I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . - -.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext - -help: - @echo "Please use \`make <target>' where <target> is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " singlehtml to make a single large HTML file" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " epub to make an epub" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " text to make text files" - @echo " man to make manual pages" - @echo " texinfo to make Texinfo files" - @echo " info to make Texinfo files and run them through makeinfo" - @echo " gettext to make PO message catalogs" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - -rm -rf $(BUILDDIR)/* - -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - sed -i '/-99999/d' _build/dirhtml/_static/flasky.css - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -singlehtml: - $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - @echo - @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/OpenERPTechnicalDocumentation.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/OpenERPTechnicalDocumentation.qhc" - -devhelp: - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - @echo - @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/OpenERPTechnicalDocumentation" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/OpenERPTechnicalDocumentation" - @echo "# devhelp" - -epub: - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - @echo - @echo "Build finished. The epub file is in $(BUILDDIR)/epub." - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make' in that directory to run these through (pdf)latex" \ - "(use \`make latexpdf' here to do that automatically)." - -latexpdf: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through pdflatex..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -text: - $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - @echo - @echo "Build finished. The text files are in $(BUILDDIR)/text." - -man: - $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - @echo - @echo "Build finished. The manual pages are in $(BUILDDIR)/man." - -texinfo: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo - @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." - @echo "Run \`make' in that directory to run these through makeinfo" \ - "(use \`make info' here to do that automatically)." - -info: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo "Running Texinfo files through makeinfo..." - make -C $(BUILDDIR)/texinfo info - @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." - -gettext: - $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale - @echo - @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." diff --git a/doc/_static/openerp.png b/doc/_static/openerp.png Binary files differdeleted file mode 100644 index d6dbd9d83d1..00000000000 --- a/doc/_static/openerp.png +++ /dev/null diff --git a/doc/_templates/sidebarintro.html b/doc/_templates/sidebarintro.html deleted file mode 100644 index ecd51980e58..00000000000 --- a/doc/_templates/sidebarintro.html +++ /dev/null @@ -1,16 +0,0 @@ -<p class="logo"><a href="http://doc.openerp.com/"> - <img class="logo" src="{{ pathto('_static/openerp.png', 1) }}" alt="Logo"/> -</a></p> - -<h3>Other Docs</h3> -<ul> - <li><a href="http://doc.openerp.com/trunk/developers">OpenERP Developers Documentation</a></li> - <li><a href="http://doc.openerp.com/trunk/developers/server">OpenERP Server Developers Documentation</a></li> - <li><a href="http://doc.openerp.com/trunk/users">OpenERP Users Documentation</a></li> -</ul> - -<h3>Useful Links</h3> -<ul> - <li><a href="http://www.openerp.com/">The OpenERP website</a></li> - <li><a href="http://python.org/">The Python programming language</a></li> -</ul> diff --git a/doc/_templates/sidebarlogo.html b/doc/_templates/sidebarlogo.html deleted file mode 100644 index de6e3e5c851..00000000000 --- a/doc/_templates/sidebarlogo.html +++ /dev/null @@ -1,3 +0,0 @@ -<p class="logo"><a href="{{ pathto(master_doc) }}"> - <img class="logo" src="{{ pathto('_static/openerp.png', 1) }}" alt="Logo"/> -</a></p> diff --git a/doc/_themes/LICENSE b/doc/_themes/LICENSE deleted file mode 100644 index 8daab7ee6ef..00000000000 --- a/doc/_themes/LICENSE +++ /dev/null @@ -1,37 +0,0 @@ -Copyright (c) 2010 by Armin Ronacher. - -Some rights reserved. - -Redistribution and use in source and binary forms of the theme, with or -without modification, are permitted provided that the following conditions -are met: - -* Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - -* The names of the contributors may not be used to endorse or - promote products derived from this software without specific - prior written permission. - -We kindly ask you to only use these themes in an unmodified manner just -for Flask and Flask-related products, not for unrelated projects. If you -like the visual style and want to use it for your own projects, please -consider making some larger changes to the themes (such as changing -font faces, sizes, colors or margins). - -THIS THEME IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS THEME, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. diff --git a/doc/_themes/README b/doc/_themes/README deleted file mode 100644 index b3292bdff8e..00000000000 --- a/doc/_themes/README +++ /dev/null @@ -1,31 +0,0 @@ -Flask Sphinx Styles -=================== - -This repository contains sphinx styles for Flask and Flask related -projects. To use this style in your Sphinx documentation, follow -this guide: - -1. put this folder as _themes into your docs folder. Alternatively - you can also use git submodules to check out the contents there. -2. add this to your conf.py: - - sys.path.append(os.path.abspath('_themes')) - html_theme_path = ['_themes'] - html_theme = 'flask' - -The following themes exist: - -- 'flask' - the standard flask documentation theme for large - projects -- 'flask_small' - small one-page theme. Intended to be used by - very small addon libraries for flask. - -The following options exist for the flask_small theme: - - [options] - index_logo = '' filename of a picture in _static - to be used as replacement for the - h1 in the index.rst file. - index_logo_height = 120px height of the index logo - github_fork = '' repository name on github for the - "fork me" badge diff --git a/doc/_themes/flask/layout.html b/doc/_themes/flask/layout.html deleted file mode 100644 index ad08eccd38d..00000000000 --- a/doc/_themes/flask/layout.html +++ /dev/null @@ -1,25 +0,0 @@ -{%- extends "basic/layout.html" %} -{%- block extrahead %} - {{ super() }} - {% if theme_touch_icon %} - <link rel="apple-touch-icon" href="{{ pathto('_static/' ~ theme_touch_icon, 1) }}" /> - {% endif %} - <link media="only screen and (max-device-width: 480px)" href="{{ - pathto('_static/small_flask.css', 1) }}" type= "text/css" rel="stylesheet" /> -{% endblock %} -{%- block relbar2 %}{% endblock %} -{% block header %} - {{ super() }} - {% if pagename == 'index' %} - <div class=indexwrapper> - {% endif %} -{% endblock %} -{%- block footer %} - <div class="footer"> - © Copyright {{ copyright }} - Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> and a modified <a href="https://github.com/mitsuhiko/flask-sphinx-themes">Flask theme</a>. - </div> - {% if pagename == 'index' %} - </div> - {% endif %} -{%- endblock %} diff --git a/doc/_themes/flask/relations.html b/doc/_themes/flask/relations.html deleted file mode 100644 index 3bbcde85bb4..00000000000 --- a/doc/_themes/flask/relations.html +++ /dev/null @@ -1,19 +0,0 @@ -<h3>Related Topics</h3> -<ul> - <li><a href="{{ pathto(master_doc) }}">Documentation overview</a><ul> - {%- for parent in parents %} - <li><a href="{{ parent.link|e }}">{{ parent.title }}</a><ul> - {%- endfor %} - {%- if prev %} - <li>Previous: <a href="{{ prev.link|e }}" title="{{ _('previous chapter') - }}">{{ prev.title }}</a></li> - {%- endif %} - {%- if next %} - <li>Next: <a href="{{ next.link|e }}" title="{{ _('next chapter') - }}">{{ next.title }}</a></li> - {%- endif %} - {%- for parent in parents %} - </ul></li> - {%- endfor %} - </ul></li> -</ul> diff --git a/doc/_themes/flask/static/flasky.css_t b/doc/_themes/flask/static/flasky.css_t deleted file mode 100644 index 0280e159455..00000000000 --- a/doc/_themes/flask/static/flasky.css_t +++ /dev/null @@ -1,395 +0,0 @@ -/* - * flasky.css_t - * ~~~~~~~~~~~~ - * - * :copyright: Copyright 2010 by Armin Ronacher. - * :license: Flask Design License, see LICENSE for details. - */ - -{% set page_width = '80em' %} -{% set sidebar_width = '16em' %} - -@import url("basic.css"); - -/* -- page layout ----------------------------------------------------------- */ - -body { - font-family: 'Georgia', serif; - font-size: 15px; - background-color: white; - color: #000; - margin: 0; - padding: 0; -} - -div.document { - width: {{ page_width }}; - margin: 30px auto 0 auto; -} - -div.documentwrapper { - float: left; - width: 100%; -} - -div.bodywrapper { - margin: 0 0 0 {{ sidebar_width }}; -} - -div.sphinxsidebar { - width: {{ sidebar_width }}; -} - -hr { - border: 1px solid #B1B4B6; -} - -div.body { - background-color: #ffffff; - color: #3E4349; - padding: 0 0px 0 0px; -} - -img.floatingflask { - padding: 0 0 10px 10px; - float: right; -} - -div.footer { - width: {{ page_width }}; - margin: 20px auto 30px auto; - font-size: 12px; - color: #888; - text-align: right; -} - -div.footer a { - color: #888; -} - -div.related { - display: none; -} - -div.sphinxsidebar a { - color: #444; - text-decoration: none; - border-bottom: 1px dotted #999; -} - -div.sphinxsidebar a:hover { - border-bottom: 1px solid #999; -} - -div.sphinxsidebar { - font-size: 12px; - line-height: 1.5; -} - -div.sphinxsidebarwrapper { - padding: 0px 10px; -} - -div.sphinxsidebarwrapper p.logo { - padding: 0 0 20px 0; - margin: 0; - text-align: center; -} - -div.sphinxsidebar h3, -div.sphinxsidebar h4 { - font-family: 'Garamond', 'Georgia', serif; - color: #444; - font-size: 22px; - font-weight: normal; - margin: 0 0 5px 0; - padding: 0; -} - -div.sphinxsidebar h4 { - font-size: 18px; -} - -div.sphinxsidebar h3 a { - color: #444; -} - -div.sphinxsidebar p.logo a, -div.sphinxsidebar h3 a, -div.sphinxsidebar p.logo a:hover, -div.sphinxsidebar h3 a:hover { - border: none; -} - -div.sphinxsidebar p { - color: #555; - margin: 10px 0; -} - -div.sphinxsidebar ul { - margin: 10px 0; - padding: 0; - color: #000; -} - -div.sphinxsidebar input { - border: 1px solid #ccc; - font-family: 'Georgia', serif; - font-size: 1em; -} - -/* -- body styles ----------------------------------------------------------- */ - -a { - color: #004B6B; - text-decoration: underline; -} - -a:hover { - color: #6D4100; - text-decoration: underline; -} - -div.body h1, -div.body h2, -div.body h3, -div.body h4, -div.body h5, -div.body h6 { - font-family: 'Garamond', 'Georgia', serif; - font-weight: normal; - margin: 30px 0px 10px 0px; - padding: 0; -} - -{% if theme_index_logo %} -div.indexwrapper h1 { - text-indent: -999999px; - background: url({{ theme_index_logo }}) no-repeat center center; - height: {{ theme_index_logo_height }}; -} -{% endif %} - -div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; } -div.body h2 { font-size: 180%; } -div.body h3 { font-size: 150%; } -div.body h4 { font-size: 130%; } -div.body h5 { font-size: 100%; } -div.body h6 { font-size: 100%; } - -a.headerlink { - color: #ddd; - padding: 0 4px; - text-decoration: none; -} - -a.headerlink:hover { - color: #444; - background: #eaeaea; -} - -div.body p, div.body dd, div.body li { - line-height: 1.4em; -} - -div.admonition { - background: #fafafa; - margin: 20px -30px; - padding: 10px 30px; - border-top: 1px solid #ccc; - border-bottom: 1px solid #ccc; -} - -div.admonition tt.xref, div.admonition a tt { - border-bottom: 1px solid #fafafa; -} - -dd div.admonition { - margin-left: -60px; - padding-left: 60px; -} - -div.admonition p.admonition-title { - font-family: 'Garamond', 'Georgia', serif; - font-weight: normal; - font-size: 22px; - margin: 0 0 10px 0; - padding: 0; - line-height: 1; -} - -div.admonition p.last { - margin-bottom: 0; -} - -div.highlight { - background-color: white; -} - -dt:target, .highlight { - background: #FAF3E8; -} - -div.note { - background-color: #eee; - border: 1px solid #ccc; -} - -div.seealso { - background-color: #ffc; - border: 1px solid #ff6; -} - -div.topic { - background-color: #eee; -} - -p.admonition-title { - display: inline; -} - -p.admonition-title:after { - content: ":"; -} - -pre, tt { - font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace; - font-size: 0.9em; -} - -img.screenshot { -} - -tt.descname, tt.descclassname { - font-size: 0.95em; -} - -tt.descname { - padding-right: 0.08em; -} - -img.screenshot { - -moz-box-shadow: 2px 2px 4px #eee; - -webkit-box-shadow: 2px 2px 4px #eee; - box-shadow: 2px 2px 4px #eee; -} - -table.docutils { - border: 1px solid #888; - -moz-box-shadow: 2px 2px 4px #eee; - -webkit-box-shadow: 2px 2px 4px #eee; - box-shadow: 2px 2px 4px #eee; -} - -table.docutils td, table.docutils th { - border: 1px solid #888; - padding: 0.25em 0.7em; -} - -table.field-list, table.footnote { - border: none; - -moz-box-shadow: none; - -webkit-box-shadow: none; - box-shadow: none; -} - -table.footnote { - margin: 15px 0; - width: 100%; - border: 1px solid #eee; - background: #fdfdfd; - font-size: 0.9em; -} - -table.footnote + table.footnote { - margin-top: -15px; - border-top: none; -} - -table.field-list th { - padding: 0 0.8em 0 0; -} - -table.field-list td { - padding: 0; -} - -table.footnote td.label { - width: 0px; - padding: 0.3em 0 0.3em 0.5em; -} - -table.footnote td { - padding: 0.3em 0.5em; -} - -dl { - margin: 0; - padding: 0; -} - -dl dd { - margin-left: 30px; -} - -blockquote { - margin: 0 0 0 30px; - padding: 0; -} - -ul, ol { - margin: 10px 0 10px 30px; - padding: 0; -} - -pre { - background: #eee; - padding: 7px 30px; - margin: 15px -30px; - line-height: 1.3em; -} - -dl pre, blockquote pre, li pre { - margin-left: -60px; - padding-left: 60px; -} - -dl dl pre { - margin-left: -90px; - padding-left: 90px; -} - -tt { - background-color: #ecf0f3; - color: #222; - /* padding: 1px 2px; */ -} - -tt.xref, a tt { - background-color: #FBFBFB; - border-bottom: 1px solid white; -} - -a.reference { - text-decoration: none; - border-bottom: 1px dotted #004B6B; -} - -a.reference:hover { - border-bottom: 1px solid #6D4100; -} - -a.footnote-reference { - text-decoration: none; - font-size: 0.7em; - vertical-align: top; - border-bottom: 1px dotted #004B6B; -} - -a.footnote-reference:hover { - border-bottom: 1px solid #6D4100; -} - -a:hover tt { - background: #EEE; -} diff --git a/doc/_themes/flask/static/small_flask.css b/doc/_themes/flask/static/small_flask.css deleted file mode 100644 index 1c6df309edc..00000000000 --- a/doc/_themes/flask/static/small_flask.css +++ /dev/null @@ -1,70 +0,0 @@ -/* - * small_flask.css_t - * ~~~~~~~~~~~~~~~~~ - * - * :copyright: Copyright 2010 by Armin Ronacher. - * :license: Flask Design License, see LICENSE for details. - */ - -body { - margin: 0; - padding: 20px 30px; -} - -div.documentwrapper { - float: none; - background: white; -} - -div.sphinxsidebar { - display: block; - float: none; - width: 102.5%; - margin: 50px -30px -20px -30px; - padding: 10px 20px; - background: #333; - color: white; -} - -div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, -div.sphinxsidebar h3 a { - color: white; -} - -div.sphinxsidebar a { - color: #aaa; -} - -div.sphinxsidebar p.logo { - display: none; -} - -div.document { - width: 100%; - margin: 0; -} - -div.related { - display: block; - margin: 0; - padding: 10px 0 20px 0; -} - -div.related ul, -div.related ul li { - margin: 0; - padding: 0; -} - -div.footer { - display: none; -} - -div.bodywrapper { - margin: 0; -} - -div.body { - min-height: 0; - padding: 0; -} diff --git a/doc/_themes/flask/theme.conf b/doc/_themes/flask/theme.conf deleted file mode 100644 index 18c720f804c..00000000000 --- a/doc/_themes/flask/theme.conf +++ /dev/null @@ -1,9 +0,0 @@ -[theme] -inherit = basic -stylesheet = flasky.css -pygments_style = flask_theme_support.FlaskyStyle - -[options] -index_logo = '' -index_logo_height = 120px -touch_icon = diff --git a/doc/_themes/flask_small/layout.html b/doc/_themes/flask_small/layout.html deleted file mode 100644 index aa1716aaff0..00000000000 --- a/doc/_themes/flask_small/layout.html +++ /dev/null @@ -1,22 +0,0 @@ -{% extends "basic/layout.html" %} -{% block header %} - {{ super() }} - {% if pagename == 'index' %} - <div class=indexwrapper> - {% endif %} -{% endblock %} -{% block footer %} - {% if pagename == 'index' %} - </div> - {% endif %} -{% endblock %} -{# do not display relbars #} -{% block relbar1 %}{% endblock %} -{% block relbar2 %} - {% if theme_github_fork %} - <a href="http://github.com/{{ theme_github_fork }}"><img style="position: fixed; top: 0; right: 0; border: 0;" - src="http://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub" /></a> - {% endif %} -{% endblock %} -{% block sidebar1 %}{% endblock %} -{% block sidebar2 %}{% endblock %} diff --git a/doc/_themes/flask_small/static/flasky.css_t b/doc/_themes/flask_small/static/flasky.css_t deleted file mode 100644 index fe2141c565e..00000000000 --- a/doc/_themes/flask_small/static/flasky.css_t +++ /dev/null @@ -1,287 +0,0 @@ -/* - * flasky.css_t - * ~~~~~~~~~~~~ - * - * Sphinx stylesheet -- flasky theme based on nature theme. - * - * :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS. - * :license: BSD, see LICENSE for details. - * - */ - -@import url("basic.css"); - -/* -- page layout ----------------------------------------------------------- */ - -body { - font-family: 'Georgia', serif; - font-size: 17px; - color: #000; - background: white; - margin: 0; - padding: 0; -} - -div.documentwrapper { - float: left; - width: 100%; -} - -div.bodywrapper { - margin: 40px auto 0 auto; - width: 700px; -} - -hr { - border: 1px solid #B1B4B6; -} - -div.body { - background-color: #ffffff; - color: #3E4349; - padding: 0 30px 30px 30px; -} - -img.floatingflask { - padding: 0 0 10px 10px; - float: right; -} - -div.footer { - text-align: right; - color: #888; - padding: 10px; - font-size: 14px; - width: 650px; - margin: 0 auto 40px auto; -} - -div.footer a { - color: #888; - text-decoration: underline; -} - -div.related { - line-height: 32px; - color: #888; -} - -div.related ul { - padding: 0 0 0 10px; -} - -div.related a { - color: #444; -} - -/* -- body styles ----------------------------------------------------------- */ - -a { - color: #004B6B; - text-decoration: underline; -} - -a:hover { - color: #6D4100; - text-decoration: underline; -} - -div.body { - padding-bottom: 40px; /* saved for footer */ -} - -div.body h1, -div.body h2, -div.body h3, -div.body h4, -div.body h5, -div.body h6 { - font-family: 'Garamond', 'Georgia', serif; - font-weight: normal; - margin: 30px 0px 10px 0px; - padding: 0; -} - -{% if theme_index_logo %} -div.indexwrapper h1 { - text-indent: -999999px; - background: url({{ theme_index_logo }}) no-repeat center center; - height: {{ theme_index_logo_height }}; -} -{% endif %} - -div.body h2 { font-size: 180%; } -div.body h3 { font-size: 150%; } -div.body h4 { font-size: 130%; } -div.body h5 { font-size: 100%; } -div.body h6 { font-size: 100%; } - -a.headerlink { - color: white; - padding: 0 4px; - text-decoration: none; -} - -a.headerlink:hover { - color: #444; - background: #eaeaea; -} - -div.body p, div.body dd, div.body li { - line-height: 1.4em; -} - -div.admonition { - background: #fafafa; - margin: 20px -30px; - padding: 10px 30px; - border-top: 1px solid #ccc; - border-bottom: 1px solid #ccc; -} - -div.admonition p.admonition-title { - font-family: 'Garamond', 'Georgia', serif; - font-weight: normal; - font-size: 24px; - margin: 0 0 10px 0; - padding: 0; - line-height: 1; -} - -div.admonition p.last { - margin-bottom: 0; -} - -div.highlight{ - background-color: white; -} - -dt:target, .highlight { - background: #FAF3E8; -} - -div.note { - background-color: #eee; - border: 1px solid #ccc; -} - -div.seealso { - background-color: #ffc; - border: 1px solid #ff6; -} - -div.topic { - background-color: #eee; -} - -div.warning { - background-color: #ffe4e4; - border: 1px solid #f66; -} - -p.admonition-title { - display: inline; -} - -p.admonition-title:after { - content: ":"; -} - -pre, tt { - font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace; - font-size: 0.85em; -} - -img.screenshot { -} - -tt.descname, tt.descclassname { - font-size: 0.95em; -} - -tt.descname { - padding-right: 0.08em; -} - -img.screenshot { - -moz-box-shadow: 2px 2px 4px #eee; - -webkit-box-shadow: 2px 2px 4px #eee; - box-shadow: 2px 2px 4px #eee; -} - -table.docutils { - border: 1px solid #888; - -moz-box-shadow: 2px 2px 4px #eee; - -webkit-box-shadow: 2px 2px 4px #eee; - box-shadow: 2px 2px 4px #eee; -} - -table.docutils td, table.docutils th { - border: 1px solid #888; - padding: 0.25em 0.7em; -} - -table.field-list, table.footnote { - border: none; - -moz-box-shadow: none; - -webkit-box-shadow: none; - box-shadow: none; -} - -table.footnote { - margin: 15px 0; - width: 100%; - border: 1px solid #eee; -} - -table.field-list th { - padding: 0 0.8em 0 0; -} - -table.field-list td { - padding: 0; -} - -table.footnote td { - padding: 0.5em; -} - -dl { - margin: 0; - padding: 0; -} - -dl dd { - margin-left: 30px; -} - -pre { - padding: 0; - margin: 15px -30px; - padding: 8px; - line-height: 1.3em; - padding: 7px 30px; - background: #eee; - border-radius: 2px; - -moz-border-radius: 2px; - -webkit-border-radius: 2px; -} - -dl pre { - margin-left: -60px; - padding-left: 60px; -} - -tt { - background-color: #ecf0f3; - color: #222; - /* padding: 1px 2px; */ -} - -tt.xref, a tt { - background-color: #FBFBFB; -} - -a:hover tt { - background: #EEE; -} diff --git a/doc/_themes/flask_small/theme.conf b/doc/_themes/flask_small/theme.conf deleted file mode 100644 index 542b462515d..00000000000 --- a/doc/_themes/flask_small/theme.conf +++ /dev/null @@ -1,10 +0,0 @@ -[theme] -inherit = basic -stylesheet = flasky.css -nosidebar = true -pygments_style = flask_theme_support.FlaskyStyle - -[options] -index_logo = '' -index_logo_height = 120px -github_fork = '' diff --git a/doc/_themes/flask_theme_support.py b/doc/_themes/flask_theme_support.py deleted file mode 100644 index 33f47449c11..00000000000 --- a/doc/_themes/flask_theme_support.py +++ /dev/null @@ -1,86 +0,0 @@ -# flasky extensions. flasky pygments style based on tango style -from pygments.style import Style -from pygments.token import Keyword, Name, Comment, String, Error, \ - Number, Operator, Generic, Whitespace, Punctuation, Other, Literal - - -class FlaskyStyle(Style): - background_color = "#f8f8f8" - default_style = "" - - styles = { - # No corresponding class for the following: - #Text: "", # class: '' - Whitespace: "underline #f8f8f8", # class: 'w' - Error: "#a40000 border:#ef2929", # class: 'err' - Other: "#000000", # class 'x' - - Comment: "italic #8f5902", # class: 'c' - Comment.Preproc: "noitalic", # class: 'cp' - - Keyword: "bold #004461", # class: 'k' - Keyword.Constant: "bold #004461", # class: 'kc' - Keyword.Declaration: "bold #004461", # class: 'kd' - Keyword.Namespace: "bold #004461", # class: 'kn' - Keyword.Pseudo: "bold #004461", # class: 'kp' - Keyword.Reserved: "bold #004461", # class: 'kr' - Keyword.Type: "bold #004461", # class: 'kt' - - Operator: "#582800", # class: 'o' - Operator.Word: "bold #004461", # class: 'ow' - like keywords - - Punctuation: "bold #000000", # class: 'p' - - # because special names such as Name.Class, Name.Function, etc. - # are not recognized as such later in the parsing, we choose them - # to look the same as ordinary variables. - Name: "#000000", # class: 'n' - Name.Attribute: "#c4a000", # class: 'na' - to be revised - Name.Builtin: "#004461", # class: 'nb' - Name.Builtin.Pseudo: "#3465a4", # class: 'bp' - Name.Class: "#000000", # class: 'nc' - to be revised - Name.Constant: "#000000", # class: 'no' - to be revised - Name.Decorator: "#888", # class: 'nd' - to be revised - Name.Entity: "#ce5c00", # class: 'ni' - Name.Exception: "bold #cc0000", # class: 'ne' - Name.Function: "#000000", # class: 'nf' - Name.Property: "#000000", # class: 'py' - Name.Label: "#f57900", # class: 'nl' - Name.Namespace: "#000000", # class: 'nn' - to be revised - Name.Other: "#000000", # class: 'nx' - Name.Tag: "bold #004461", # class: 'nt' - like a keyword - Name.Variable: "#000000", # class: 'nv' - to be revised - Name.Variable.Class: "#000000", # class: 'vc' - to be revised - Name.Variable.Global: "#000000", # class: 'vg' - to be revised - Name.Variable.Instance: "#000000", # class: 'vi' - to be revised - - Number: "#990000", # class: 'm' - - Literal: "#000000", # class: 'l' - Literal.Date: "#000000", # class: 'ld' - - String: "#4e9a06", # class: 's' - String.Backtick: "#4e9a06", # class: 'sb' - String.Char: "#4e9a06", # class: 'sc' - String.Doc: "italic #8f5902", # class: 'sd' - like a comment - String.Double: "#4e9a06", # class: 's2' - String.Escape: "#4e9a06", # class: 'se' - String.Heredoc: "#4e9a06", # class: 'sh' - String.Interpol: "#4e9a06", # class: 'si' - String.Other: "#4e9a06", # class: 'sx' - String.Regex: "#4e9a06", # class: 'sr' - String.Single: "#4e9a06", # class: 's1' - String.Symbol: "#4e9a06", # class: 'ss' - - Generic: "#000000", # class: 'g' - Generic.Deleted: "#a40000", # class: 'gd' - Generic.Emph: "italic #000000", # class: 'ge' - Generic.Error: "#ef2929", # class: 'gr' - Generic.Heading: "bold #000080", # class: 'gh' - Generic.Inserted: "#00A000", # class: 'gi' - Generic.Output: "#888", # class: 'go' - Generic.Prompt: "#745334", # class: 'gp' - Generic.Strong: "bold #000000", # class: 'gs' - Generic.Subheading: "bold #800080", # class: 'gu' - Generic.Traceback: "bold #a40000", # class: 'gt' - } diff --git a/doc/addon-structure.txt b/doc/addon-structure.txt deleted file mode 100644 index 38151749651..00000000000 --- a/doc/addon-structure.txt +++ /dev/null @@ -1,12 +0,0 @@ -<addon name> - +-- __openerp__.py - +-- controllers/ - +-- static/ - +-- lib/ - +-- src/ - +-- css/ - +-- img/ - +-- js/ - +-- xml/ - +-- test/ - +-- test/ diff --git a/doc/async.rst b/doc/async.rst deleted file mode 100644 index 23b3409bd8f..00000000000 --- a/doc/async.rst +++ /dev/null @@ -1,353 +0,0 @@ -Don't stop the world now: asynchronous development and Javascript -================================================================= - -As a language (and runtime), javascript is fundamentally -single-threaded. This means any blocking request or computation will -blocks the whole page (and, in older browsers, the software itself -even preventing users from switching to an other tab): a javascript -environment can be seen as an event-based runloop where application -developers have no control over the runloop itself. - -As a result, performing long-running synchronous network requests or -other types of complex and expensive accesses is frowned upon and -asynchronous APIs are used instead. - -Asynchronous code rarely comes naturally, especially for developers -used to synchronous server-side code (in Python, Java or C#) where the -code will just block until the deed is gone. This is increased further -when asynchronous programming is not a first-class concept and is -instead implemented on top of callbacks-based programming, which is -the case in javascript. - -The goal of this guide is to provide some tools to deal with -asynchronous systems, and warn against systematic issues or dangers. - -Deferreds ---------- - -Deferreds are a form of `promises`_. OpenERP Web currently uses -`jQuery's deferred`_, but any `CommonJS Promises/A`_ implementation -should work. - -The core idea of deferreds is that potentially asynchronous methods -will return a :js:class:`Deferred` object instead of an arbitrary -value or (most commonly) nothing. - -This object can then be used to track the end of the asynchronous -operation by adding callbacks onto it, either success callbacks or -error callbacks. - -A great advantage of deferreds over simply passing callback functions -directly to asynchronous methods is the ability to :ref:`compose them -<deferred-composition>`. - -Using deferreds -~~~~~~~~~~~~~~~ - -`CommonJS Promises/A`_ deferreds have only one method of importance: -:js:func:`Deferred.then`. This method is used to attach new callbacks -to the deferred object. - -* the first parameter attaches a success callback, called when the - deferred object is successfully resolved and provided with the - resolved value(s) for the asynchronous operation. - -* the second parameter attaches a failure callback, called when the - deferred object is rejected and provided with rejection values - (often some sort of error message). - -Callbacks attached to deferreds are never "lost": if a callback is -attached to an already resolved or rejected deferred, the callback -will be called (or ignored) immediately. A deferred is also only ever -resolved or rejected once, and is either resolved or rejected: a given -deferred can not call a single success callback twice, or call both a -success and a failure callbacks. - -:js:func:`~Deferred.then` should be the method you'll use most often -when interacting with deferred objects (and thus asynchronous APIs). - -Building deferreds -~~~~~~~~~~~~~~~~~~ - -After using asynchronous APIs may come the time to build them: for -`mocks`_, to compose deferreds from multiple source in a complex -manner, in order to let the current operations repaint the screen or -give other events the time to unfold, ... - -This is easy using jQuery's deferred objects. - -.. note:: this section is an implementation detail of jQuery Deferred - objects, the creation of promises is not part of any - standard (even tentative) that I know of. If you are using - deferred objects which are not jQuery's, their API may (and - often will) be completely different. - -Deferreds are created by invoking their constructor [#]_ without any -argument. This creates a :js:class:`Deferred` instance object with the -following methods: - -:js:func:`Deferred.resolve` - - As its name indicates, this method moves the deferred to the - "Resolved" state. It can be provided as many arguments as - necessary, these arguments will be provided to any pending success - callback. - -:js:func:`Deferred.reject` - - Similar to :js:func:`~Deferred.resolve`, but moves the deferred to - the "Rejected" state and calls pending failure handlers. - -:js:func:`Deferred.promise` - - Creates a readonly view of the deferred object. It is generally a - good idea to return a promise view of the deferred to prevent - callers from resolving or rejecting the deferred in your stead. - -:js:func:`~Deferred.reject` and :js:func:`~Deferred.resolve` are used -to inform callers that the asynchronous operation has failed (or -succeeded). These methods should simply be called when the -asynchronous operation has ended, to notify anybody interested in its -result(s). - -.. _deferred-composition: - -Composing deferreds -~~~~~~~~~~~~~~~~~~~ - -What we've seen so far is pretty nice, but mostly doable by passing -functions to other functions (well adding functions post-facto would -probably be a chore... still, doable). - -Deferreds truly shine when code needs to compose asynchronous -operations in some way or other, as they can be used as a basis for -such composition. - -There are two main forms of compositions over deferred: multiplexing -and piping/cascading. - -Deferred multiplexing -````````````````````` - -The most common reason for multiplexing deferred is simply performing -2+ asynchronous operations and wanting to wait until all of them are -done before moving on (and executing more stuff). - -The jQuery multiplexing function for promises is :js:func:`when`. - -.. note:: the multiplexing behavior of jQuery's :js:func:`when` is an - (incompatible, mostly) extension of the behavior defined in - `CommonJS Promises/B`_. - -This function can take any number of promises [#]_ and will return a -promise. - -This returned promise will be resolved when *all* multiplexed promises -are resolved, and will be rejected as soon as one of the multiplexed -promises is rejected (it behaves like Python's ``all()``, but with -promise objects instead of boolean-ish). - -The resolved values of the various promises multiplexed via -:js:func:`when` are mapped to the arguments of :js:func:`when`'s -success callback, if they are needed. The resolved values of a promise -are at the same index in the callback's arguments as the promise in -the :js:func:`when` call so you will have: - -.. code-block:: javascript - - $.when(p0, p1, p2, p3).then( - function (results0, results1, results2, results3) { - // code - }); - -.. warning:: - - in a normal mapping, each parameter to the callback would be an - array: each promise is conceptually resolved with an array of 0..n - values and these values are passed to :js:func:`when`'s - callback. But jQuery treats deferreds resolving a single value - specially, and "unwraps" that value. - - For instance, in the code block above if the index of each promise - is the number of values it resolves (0 to 3), ``results0`` is an - empty array, ``results2`` is an array of 2 elements (a pair) but - ``results1`` is the actual value resolved by ``p1``, not an array. - -Deferred chaining -````````````````` - -A second useful composition is starting an asynchronous operation as -the result of an other asynchronous operation, and wanting the result -of both: :js:func:`Deferred.then` returns the deferred on which it was -called, so handle e.g. OpenERP's search/read sequence with this would -require something along the lines of: - -.. code-block:: javascript - - var result = $.Deferred(); - Model.search(condition).then(function (ids) { - Model.read(ids, fields).then(function (records) { - result.resolve(records); - }); - }); - return result.promise(); - -While it doesn't look too bad for trivial code, this quickly gets -unwieldy. - -Instead, jQuery provides a tool to handle this kind of chains: -:js:func:`Deferred.pipe`. - -:js:func:`~Deferred.pipe` has the same signature as -:js:func:`~Deferred.then` and could be used in the same manner -provided its return value was not used. - -It differs from :js:func:`~Deferred.then` in two ways: it returns a -new promise object, not the one it was called with, and the return -values of the callbacks is actually important to it: whichever -callback is called, - -* If the callback is not set (not provided or left to null), the - resolution or rejection value(s) is simply forwarded to - :js:func:`~Deferred.pipe`'s promise (it's essentially a noop) - -* If the callback is set and does not return an observable object (a - deferred or a promise), the value it returns (``undefined`` if it - does not return anything) will replace the value it was given, e.g. - - .. code-block:: javascript - - promise.pipe(function () { - console.log('called'); - }); - - will resolve with the sole value ``undefined``. - -* If the callback is set and returns an observable object, that object - will be the actual resolution (and result) of the pipe. This means a - resolved promise from the failure callback will resolve the pipe, - and a failure promise from the success callback will reject the - pipe. - - This provides an easy way to chain operation successes, and the - previous piece of code can now be rewritten: - - .. code-block:: javascript - - return Model.search(condition).pipe(function (ids) { - return Model.read(ids, fields); - }); - - the result of the whole expression will encode failure if either - ``search`` or ``read`` fails (with the right rejection values), and - will be resolved with ``read``'s resolution values if the chain - executes correctly. - -:js:func:`~Deferred.pipe` is also useful to adapt third-party -promise-based APIs, in order to filter their resolution value counts -for instance (to take advantage of :js:func:`when` 's special treatment -of single-value promises). - -jQuery.Deferred API -~~~~~~~~~~~~~~~~~~~ - -.. js:function:: when(deferreds…) - - :param deferreds: deferred objects to multiplex - :returns: a multiplexed deferred - :rtype: :js:class:`Deferred` - -.. js:class:: Deferred - - .. js:function:: Deferred.then(doneCallback[, failCallback]) - - Attaches new callbacks to the resolution or rejection of the - deferred object. Callbacks are executed in the order they are - attached to the deferred. - - To provide only a failure callback, pass ``null`` as the - ``doneCallback``, to provide only a success callback the - second argument can just be ignored (and not passed at all). - - :param doneCallback: function called when the deferred is resolved - :type doneCallback: Function - :param failCallback: function called when the deferred is rejected - :type failCallback: Function - :returns: the deferred object on which it was called - :rtype: :js:class:`Deferred` - - .. js:function:: Deferred.done(doneCallback) - - Attaches a new success callback to the deferred, shortcut for - ``deferred.then(doneCallback)``. - - This is a jQuery extension to `CommonJS Promises/A`_ providing - little value over calling :js:func:`~Deferred.then` directly, - it should be avoided. - - :param doneCallback: function called when the deferred is resolved - :type doneCallback: Function - :returns: the deferred object on which it was called - :rtype: :js:class:`Deferred` - - .. js:function:: Deferred.fail(failCallback) - - Attaches a new failure callback to the deferred, shortcut for - ``deferred.then(null, failCallback)``. - - A second jQuery extension to `Promises/A <CommonJS - Promises/A>`_. Although it provides more value than - :js:func:`~Deferred.done`, it still is not much and should be - avoided as well. - - :param failCallback: function called when the deferred is rejected - :type failCallback: Function - :returns: the deferred object on which it was called - :rtype: :js:class:`Deferred` - - .. js:function:: Deferred.promise() - - Returns a read-only view of the deferred object, with all - mutators (resolve and reject) methods removed. - - .. js:function:: Deferred.resolve(value…) - - Called to resolve a deferred, any value provided will be - passed onto the success handlers of the deferred object. - - Resolving a deferred which has already been resolved or - rejected has no effect. - - .. js:function:: Deferred.reject(value…) - - Called to reject (fail) a deferred, any value provided will be - passed onto the failure handler of the deferred object. - - Rejecting a deferred which has already been resolved or - rejected has no effect. - - .. js:function:: Deferred.pipe(doneFilter[, failFilter]) - - Filters the result of a deferred, able to transform a success - into failure and a failure into success, or to delay - resolution further. - -.. [#] or simply calling :js:class:`Deferred` as a function, the - result is the same - -.. [#] or not-promises, the `CommonJS Promises/B`_ role of - :js:func:`when` is to be able to treat values and promises - uniformly: :js:func:`when` will pass promises through directly, - but non-promise values and objects will be transformed into a - resolved promise (resolving themselves with the value itself). - - jQuery's :js:func:`when` keeps this behavior making deferreds - easy to build from "static" values, or allowing defensive code - where expected promises are wrapped in :js:func:`when` just in - case. - -.. _promises: http://en.wikipedia.org/wiki/Promise_(programming) -.. _jQuery's deferred: http://api.jquery.com/category/deferred-object/ -.. _CommonJS Promises/A: http://wiki.commonjs.org/wiki/Promises/A -.. _CommonJS Promises/B: http://wiki.commonjs.org/wiki/Promises/B -.. _mocks: http://en.wikipedia.org/wiki/Mock_object diff --git a/doc/changelog-7.0.rst b/doc/changelog-7.0.rst deleted file mode 100644 index 00d0236f214..00000000000 --- a/doc/changelog-7.0.rst +++ /dev/null @@ -1,108 +0,0 @@ -API changes from OpenERP Web 6.1 to 7.0 -======================================= - -DataSet -> Model ----------------- - -The 6.1 ``DataSet`` API has been deprecated in favor of the smaller -and more orthogonal :doc:`Model </rpc>` API, which more closely -matches the API in OpenERP Web's Python side and in OpenObject addons -and removes most stateful behavior of DataSet. - -Migration guide -~~~~~~~~~~~~~~~ - -* Actual arbitrary RPC calls can just be remapped on a - :js:class:`~openerp.web.Model` instance: - - .. code-block:: javascript - - dataset.call(method, args) - - or - - .. code-block:: javascript - - dataset.call_and_eval(method, args) - - can be replaced by calls to :js:func:`openerp.web.Model.call`: - - .. code-block:: javascript - - model.call(method, args) - - If callbacks are passed directly to the older methods, they need to - be added to the new one via ``.then()``. - - .. note:: - - The ``context_index`` and ``domain_index`` features were not - ported, context and domain now need to be passed in "in full", - they won't be automatically filled with the user's current - context. - -* Shorcut methods (``name_get``, ``name_search``, ``unlink``, - ``write``, ...) should be ported to - :js:func:`openerp.web.Model.call`, using the server's original - signature. On the other hand, the non-shortcut equivalents can now - use keyword arguments (see :js:func:`~openerp.web.Model.call`'s - signature for details) - -* ``read_slice``, which allowed a single round-trip to perform a - search and a read, should be reimplemented via - :js:class:`~openerp.web.Query` objects (see: - :js:func:`~openerp.web.Model.query`) for clearer and simpler - code. ``read_index`` should be replaced by a - :js:class:`~openerp.web.Query` as well, combining - :js:func:`~openerp.web.Query.offset` and - :js:func:`~openerp.web.Query.first`. - -Rationale -~~~~~~~~~ - -Renaming - - The name *DataSet* exists in the CS community consciousness, and - (as its name implies) it's a set of data (often fetched from a - database, maybe lazily). OpenERP Web's dataset behaves very - differently as it does not store (much) data (only a bunch of ids - and just enough state to break things). The name "Model" matches - the one used on the Python side for the task of building an RPC - proxy to OpenERP objects. - -API simplification - - ``DataSet`` has a number of methods which serve as little more - than shortcuts, or are there due to domain and context evaluation - issues in 6.1. - - The shortcuts really add little value, and OpenERP Web 6.2 embeds - a restricted Python evaluator (in javascript) meaning most of the - context and domain parsing & evaluation can be moved to the - javascript code and does not require cooperative RPC bridging. - -DataGroup -> also Model ------------------------ - -Alongside the deprecation of ``DataSet`` for -:js:class:`~openerp.web.Model`, OpenERP Web 7.0 also deprecates -``DataGroup`` and its subtypes in favor of a single method on -:js:class:`~openerp.web.Query`: -:js:func:`~openerp.web.Query.group_by`. - -Migration guide -~~~~~~~~~~~~~~~ - -Rationale -~~~~~~~~~ - -While the ``DataGroup`` API worked (mostly), it is quite odd and -alien-looking, a bit too Smalltalk-inspired (behaves like a -self-contained flow-control structure for reasons which may or may not -have been good). - -Because it is heavily related to ``DataSet`` (as it *yields* -``DataSet`` objects), deprecating ``DataSet`` automatically deprecates -``DataGroup`` (if we want to stay consistent), which is a good time to -make the API more imperative and look more like what most developers -are used to. diff --git a/doc/conf.py b/doc/conf.py deleted file mode 100644 index ac5b8907e0e..00000000000 --- a/doc/conf.py +++ /dev/null @@ -1,257 +0,0 @@ -# -*- coding: utf-8 -*- -# -# OpenERP Technical Documentation configuration file, created by -# sphinx-quickstart on Fri Feb 17 16:14:06 2012. -# -# This file is execfile()d with the current directory set to its containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys, os - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) -sys.path.append(os.path.abspath('_themes')) -sys.path.append(os.path.abspath('..')) -sys.path.append(os.path.abspath('../openerp')) - -# -- General configuration ----------------------------------------------------- - -# If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.viewcode'] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -#source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'OpenERP Server Developers Documentation' -copyright = u'2012, OpenERP s.a.' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = '7.0' -# The full version, including alpha/beta/rc tags. -release = '7.0b' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = ['_build'] - -# The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - - -# -- Options for HTML output --------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = 'flask' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -html_theme_path = ['_themes'] - -# The name for this set of Sphinx documents. If None, it defaults to -# "<project> v<release> documentation". -#html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -html_sidebars = { - 'index': ['sidebarintro.html', 'sourcelink.html', 'searchbox.html'], - '**': ['sidebarlogo.html', 'localtoc.html', 'relations.html', - 'sourcelink.html', 'searchbox.html'] -} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -#html_domain_indices = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a <link> tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None - -# Output file base name for HTML help builder. -htmlhelp_basename = 'openerp-server-doc' - - -# -- Options for LaTeX output -------------------------------------------------- - -latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -#'papersize': 'letterpaper', - -# The font size ('10pt', '11pt' or '12pt'). -#'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -#'preamble': '', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass [howto/manual]). -latex_documents = [ - ('index', 'openerp-server-doc.tex', u'OpenERP Server Developers Documentation', - u'OpenERP s.a.', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# If true, show page references after internal links. -#latex_show_pagerefs = False - -# If true, show URL addresses after external links. -#latex_show_urls = False - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_domain_indices = True - - -# -- Options for manual page output -------------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'openerp-server-doc', u'OpenERP Server Developers Documentation', - [u'OpenERP s.a.'], 1) -] - -# If true, show URL addresses after external links. -#man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------------ - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ('index', 'OpenERPServerDocumentation', u'OpenERP Server Developers Documentation', - u'OpenERP s.a.', 'OpenERPServerDocumentation', 'Developers documentation for the openobject-server project.', - 'Miscellaneous'), -] - -# Documents to append as an appendix to all manuals. -#texinfo_appendices = [] - -# If false, no module index is generated. -#texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' - - -# Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = { - 'python': ('http://docs.python.org/', None), - 'openerpweb': ('http://doc.openerp.com/trunk/developers/web', None), - 'openerpdev': ('http://doc.openerp.com/trunk/developers', None), -} diff --git a/doc/form-notes.rst b/doc/form-notes.rst deleted file mode 100644 index 98d4a4de67e..00000000000 --- a/doc/form-notes.rst +++ /dev/null @@ -1,55 +0,0 @@ -Notes on the usage of the Form View as a sub-widget -=================================================== - -Undocumented stuff ------------------- - -* ``initial_mode`` *option* defines the starting mode of the form - view, one of ``view`` and ``edit`` (?). Default value is ``view`` - (non-editable form). - -* ``embedded_view`` *attribute* has to be set separately when - providing a view directly, no option available for that usage. - - * View arch **must** contain node with - ``@class="oe_form_container"``, otherwise everything will break - without any info - - * Root element of view arch not being ``form`` may or may not work - correctly, no idea. - - * Freeform views => ``@version="7.0"`` - -* Form is not entirely loaded (some widgets may not appear) unless - ``on_record_loaded`` is called (or ``do_show``, which itself calls - ``on_record_loaded``). - -* "Empty" form => ``on_button_new`` (...), or manually call - ``default_get`` + ``on_record_loaded`` - -* Form fields default to width: 100%, padding, !important margin, can - be reached via ``.oe_form_field`` - -* Form *will* render buttons and a pager, offers options to locate - both outside of form itself (``$buttons`` and ``$pager``), providing - empty jquery objects (``$()``) seems to stop displaying both but not - sure if there are deleterious side-effects. - - Other options: - - * Pass in ``$(document.createDocumentFragment)`` to ensure it's a - DOM-compatible tree completely outside of the actual DOM. - - * ??? - -* readonly fields probably don't have a background, beware if need of - overlay - - * What is the difference between ``readonly`` and - ``effective_readonly``? - -* No facilities for DOM events handling/delegations e.g. handling - keyup/keydown/keypress from a form fields into the form's user. - - * Also no way to reverse from a DOM node (e.g. DOMEvent#target) back to a - form view field easily diff --git a/doc/guides/client-action.rst b/doc/guides/client-action.rst deleted file mode 100644 index 30f0c7eeb27..00000000000 --- a/doc/guides/client-action.rst +++ /dev/null @@ -1,112 +0,0 @@ -.. highlight:: javascript - -Creating a new client action -============================ - -Client actions are the client-side version of OpenERP's "Server -Actions": instead of allowing for semi-arbitrary code to be executed -in the server, they allow for execution of client-customized code. - -On the server side, a client action is an action of type -``ir.actions.client``, which has (at most) two properties: a mandatory -``tag``, which is an arbitrary string by which the client will -identify the action, and an optional ``params`` which is simply a map -of keys and values sent to the client as-is (this way, client actions -can be made generic and reused in multiple contexts). - -General Structure ------------------ - -In the OpenERP Web code, a client action only requires two pieces of -information: - -* Mapping the action's ``tag`` to an object - -* Providing said object. Two different types of objects can be mapped - to a client action: - - * An OpenERP Web widget, which must inherit from - :js:class:`openerp.web.Widget` - - * A regular javascript function - -The major difference is in the lifecycle of these: - -* if the client action maps to a function, the function will simply be - called when executing the action. The function can have no further - interaction with the Web Client itself, although it can return an - action which will be executed after it. - -* if, on the other hand, the client action maps to a - :js:class:`~openerp.web.Widget`, that - :js:class:`~openerp.web.Widget` will be instantiated and added to - the web client's canvas, with the usual - :js:class:`~openerp.web.Widget` lifecycle (essentially, it will - either take over the content area of the client or it will be - integrated within a dialog). - -For example, to create a client action displaying a ``res.widget`` -object:: - - // Registers the object 'openerp.web_dashboard.Widget' to the client - // action tag 'board.home.widgets' - instance.web.client_actions.add( - 'board.home.widgets', 'openerp.web_dashboard.Widget'); - instance.web_dashboard.Widget = instance.web.Widget.extend({ - template: 'HomeWidget' - }); - -At this point, the generic :js:class:`~openerp.web.Widget` lifecycle -takes over, the template is rendered, inserted in the client DOM, -bound on the object's ``$el`` property and the object is started. - -If the client action takes parameters, these parameters are passed in as a -second positional parameter to the constructor:: - - init: function (parent, params) { - // execute the Widget's init - this._super(parent); - // board.home.widgets only takes a single param, the identifier of the - // res.widget object it should display. Store it for later - this.widget_id = params.widget_id; - } - -More complex initialization (DOM manipulations, RPC requests, ...) -should be performed in the :js:func:`~openerp.web.Widget.start()` -method. - -.. note:: - - As required by :js:class:`~openerp.web.Widget`'s contract, if - :js:func:`~openerp.web.Widget.start()` executes any asynchronous - code it should return a ``$.Deferred`` so callers know when it's - ready for interaction. - - Although generally speaking client actions are not really - interacted with. - -.. code-block:: javascript - - start: function () { - return $.when( - this._super(), - // Simply read the res.widget object this action should display - new instance.web.Model('res.widget').call( - 'read', [[this.widget_id], ['title']]) - .then(this.proxy('on_widget_loaded')); - } - -The client action can then behave exactly as it wishes to within its -root (``this.$el``). In this case, it performs further renderings once -its widget's content is retrieved:: - - on_widget_loaded: function (widgets) { - var widget = widgets[0]; - var url = _.sprintf( - '/web_dashboard/widgets/content?session_id=%s&widget_id=%d', - this.session.session_id, widget.id); - this.$el.html(QWeb.render('HomeWidget.content', { - widget: widget, - url: url - })); - } diff --git a/doc/index.rst b/doc/index.rst deleted file mode 100644 index 6a0d8dee2d4..00000000000 --- a/doc/index.rst +++ /dev/null @@ -1,32 +0,0 @@ -.. OpenERP Web documentation master file, created by - sphinx-quickstart on Fri Mar 18 16:31:55 2011. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Welcome to OpenERP Web's documentation! -======================================= - -Contents: - -.. toctree:: - :maxdepth: 1 - - changelog-7.0 - - async - rpc - - widget - search-view - - list-view - form-notes - - guides/client-action - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/doc/list-view.rst b/doc/list-view.rst deleted file mode 100644 index b7cdc1cd039..00000000000 --- a/doc/list-view.rst +++ /dev/null @@ -1,531 +0,0 @@ -List View -========= - -Style Hooks ------------ - -The list view provides a few style hook classes for re-styling of list views in -various situations: - -``.oe_list`` - - The root element of the list view, styling rules should be rooted - on that class. - -``table.oe_list_content`` - - The root table for the listview, accessory components may be - generated or added outside this section, this is the list view - "proper". - -``.oe_list_buttons`` - - The action buttons array for the list view, with its sub-elements - - ``.oe_list_add`` - - The default "Create"/"Add" button of the list view - - ``.oe_alternative`` - - The "alternative choice" for the list view, by default text - along the lines of "or import" with a link. - -``.oe_list_field_cell`` - - The cell (``td``) for a given field of the list view, cells which - are *not* fields (e.g. name of a group, or number of items in a - group) will not have this class. The field cell can be further - specified: - - ``.oe_number`` - - Numeric cell types (integer and float) - - ``.oe_button`` - - Action button (``button`` tag in the view) inside the cell - - ``.oe_readonly`` - - Readonly field cell - - ``.oe_list_field_$type`` - - Additional class for the precise type of the cell, ``$type`` - is the field's @widget if there is one, otherwise it's the - field's type. - -``.oe_list_record_selector`` - - Selector cells - -Editable list view -++++++++++++++++++ - -The editable list view module adds a few supplementary style hook -classes, for edition situations: - -``.oe_list_editable`` - - Added to the ``.oe_list`` when the list is editable (however that - was done). The class may be removed on-the-fly if the list becomes - non-editable. - -``.oe_editing`` - - Added to both ``.oe_list`` and ``.oe_list_button`` (as the - buttons may be outside of the list view) when a row of the list is - currently being edited. - -``tr.oe_edition`` - - Class set on the row being edited itself. Note that the edition - form is *not* contained within the row, this allows for styling or - modifying the row while it's being edited separately. Mostly for - fields which can not be edited (e.g. read-only fields). - -Columns display customization ------------------------------ - -The list view provides a registry to -:js:class:`openerp.web.list.Column` objects allowing for the -customization of a column's display (e.g. so that a binary field is -rendered as a link to the binary file directly in the list view). - -The registry is ``instance.web.list.columns``, the keys are of the -form ``tag.type`` where ``tag`` can be ``field`` or ``button``, and -``type`` can be either the field's type or the field's ``@widget`` (in -the view). - -Most of the time, you'll want to define a ``tag.widget`` key -(e.g. ``field.progressbar``). - -.. js:class:: openerp.web.list.Column(id, tag, attrs) - - .. js:function:: openerp.web.list.Column.format(record_data, options) - - Top-level formatting method, returns an empty string if the - column is invisible (unless the ``process_modifiers=false`` - option is provided); returns ``options.value_if_empty`` or an - empty string if there is no value in the record for the - column. - - Otherwise calls :js:func:`~openerp.web.list.Column._format` - and returns its result. - - This method only needs to be overridden if the column has no - concept of values (and needs to bypass that check), for a - button for instance. - - Otherwise, custom columns should generally override - :js:func:`~openerp.web.list.Column._format` instead. - - :returns: String - - .. js:function:: openerp.web.list.Column._format(record_data, options) - - Never called directly, called if the column is visible and has - a value. - - The default implementation calls - :js:func:`~openerp.web.format_value` and htmlescapes the - result (via ``_.escape``). - - Note that the implementation of - :js:func:`~openerp.web.list.Column._format` *must* escape the - data provided to it, its output will *not* be escaped by - :js:func:`~openerp.web.list.Column.format`. - - :returns: String - -Editable list view ------------------- - -List view edition is an extension to the base listview providing the -capability of inline record edition by delegating to an embedded form -view. - -Editability status -++++++++++++++++++ - -The editability status of a list view can be queried through the -:js:func:`~openerp.web.ListView.editable` method, will return a falsy -value if the listview is not currently editable. - -The editability status is based on three flags: - -``tree/@editable`` - - If present, can be either ``"top"`` or ``"bottom"``. Either will - make the list view editable, with new records being respectively - created at the top or at the bottom of the view. - -``context.set_editable`` - - Boolean flag extracted from a search context (during the - :js:func:`~openerp.web.ListView.do_search`` handler), ``true`` - will make the view editable (from the top), ``false`` or the - absence of the flag is a noop. - -``defaults.editable`` - - Like ``tree/@editable``, one of absent (``null``)), ``"top"`` or - ``"bottom"``, fallback for the list view if none of the previous - two flags are set. - -These three flags can only *make* a listview editable, they can *not* -override a previously set flag. To do that, a listview user should -instead cancel :ref:`the edit:before event <listview-edit-before>`. - -The editable list view module adds a number of methods to the list -view, on top of implementing the :js:class:`EditorDelegate` protocol: - -Interaction Methods -+++++++++++++++++++ - -.. js:function:: openerp.web.ListView.ensure_saved - - Attempts to resolve the pending edition, if any, by saving the - edited row's current state. - - :returns: delegate resolving to all editions having been saved, or - rejected if a pending edition could not be saved - (e.g. validation failure) - -.. js:function:: openerp.web.ListView.start_edition([record][, options]) - - Starts editing the provided record inline, through an overlay form - view of editable fields in the record. - - If no record is provided, creates a new one according to the - editability configuration of the list view. - - This method resolves any pending edition when invoked, before - starting a new edition. - - :param record: record to edit, or null to create a new record - :type record: :js:class:`~openerp.web.list.Record` - :param EditOptions options: - :returns: delegate to the form used for the edition - -.. js:function:: openerp.web.ListView.save_edition - - Resolves the pending edition. - - :returns: delegate to the save being completed, resolves to an - object with two attributes ``created`` (flag indicating - whether the saved record was just created or was - updated) and ``record`` the reloaded record having been - edited. - -.. js:function:: openerp.web.ListView.cancel_edition([force=false]) - - Cancels pending edition, cleans up the list view in case of - creation (removes the empty record being created). - - :param Boolean force: doesn't check if the user has added any - data, discards the edition unconditionally - -Utility Methods -+++++++++++++++ - -.. js:function:: openerp.web.ListView.get_cells_for(row) - - Extracts the cells from a listview row, and puts them in a - {fieldname: cell} mapping for analysis and manipulation. - - :param jQuery row: - :rtype: Object - -.. js:function:: openerp.web.ListView.with_event(event_name, event, action[, args][, trigger_params]) - - Executes ``action`` in the context of the view's editor, - bracketing it with cancellable event signals. - - :param String event_name: base name for the bracketing event, will - be postfixed by ``:before`` and - ``:after`` before being called - (respectively before and after - ``action`` is executed) - :param Object event: object passed to the ``:before`` event - handlers. - :param Function action: function called with the view's editor as - its ``this``. May return a deferred. - :param Array args: arguments passed to ``action`` - :param Array trigger_params: arguments passed to the ``:after`` - event handler alongside the results - of ``action`` - -Behavioral Customizations -+++++++++++++++++++++++++ - -.. js:function:: openerp.web.ListView.handle_onwrite(record) - - Implements the handling of the ``onwrite`` listview attribute: - calls the RPC methods specified by ``@onwrite``, and if that - method returns an array of ids loads or reloads the records - corresponding to those ids. - - :param record: record being written having triggered the - ``onwrite`` callback - :type record: openerp.web.list.Record - :returns: deferred to all reloadings being done - -Events -++++++ - -For simpler interactions by/with external users of the listview, the -view provides a number of dedicated events to its lifecycle. - -.. note:: if an event is defined as *cancellable*, it means its first - parameter is an object on which the ``cancel`` attribute can - be set. If the ``cancel`` attribute is set, the view will - abort its current behavior as soon as possible, and rollback - any state modification. - - Generally speaking, an event should only be cancelled (by - setting the ``cancel`` flag to ``true``), uncancelling an - event is undefined as event handlers are executed on a - first-come-first-serve basis and later handlers may - re-cancel an uncancelled event. - -.. _listview-edit-before: - -``edit:before`` *cancellable* - - Invoked before the list view starts editing a record. - - Provided with an event object with a single property ``record``, - holding the attributes of the record being edited (``record`` is - empty *but not null* for a new record) - -``edit:after`` - - Invoked after the list view has gone into an edition state, - provided with the attributes of the record being edited (see - ``edit:before``) as first parameter and the form used for the - edition as second parameter. - -``save:before`` *cancellable* - - Invoked right before saving a pending edition, provided with an - event object holding the listview's editor (``editor``) and the - edition form (``form``) - -``save:after`` - - Invoked after a save has been completed - -``cancel:before`` *cancellable* - - Invoked before cancelling a pending edition, provided with the - same information as ``save:before``. - -``cancel:after`` - - Invoked after a pending edition has been cancelled. - -DOM events -++++++++++ - -The list view has grown hooks for the ``keyup`` event on its edition -form (during edition): any such event bubbling out of the edition form -will be forwarded to a method ``keyup_EVENTNAME``, where ``EVENTNAME`` -is the name of the key in ``$.ui.keyCode``. - -The method will also get the event object (originally passed to the -``keyup`` handler) as its sole parameter. - -The base editable list view has handlers for the ``ENTER`` and -``ESCAPE`` keys. - -Editor ------- - -The list-edition modules does not generally interact with the embedded -formview, delegating instead to its -:js:class:`~openerp.web.list.Editor`. - -.. js:class:: openerp.web.list.Editor(parent[, options]) - - The editor object provides a more convenient interface to form - views, and simplifies the usage of form views for semi-arbitrary - edition of stuff. - - However, the editor does *not* task itself with being internally - consistent at this point: calling - e.g. :js:func:`~openerp.web.list.Editor.edit` multiple times in a - row without saving or cancelling each edit is undefined. - - :param parent: - :type parent: :js:class:`~openerp.web.Widget` - :param EditorOptions options: - - .. js:function:: openerp.web.list.Editor.is_editing([record_state]) - - Indicates whether the editor is currently in the process of - providing edition for a record. - - Can be filtered by the state of the record being edited - (whether it's a record being *created* or a record being - *altered*), in which case it asserts both that an edition is - underway and that the record being edited respectively does - not yet exist in the database or already exists there. - - :param record_state: state of the record being edited. - Either ``"new"`` or ``"edit"``. - :type record_state: String - :rtype: Boolean - - .. js:function:: openerp.web.list.Editor.edit(record, configureField[, options]) - - Loads the provided record into the internal form view and - displays the form view. - - Will also attempt to focus the first visible field of the form - view. - - :param Object record: record to load into the form view - (key:value mapping similar to the result - of a ``read``) - :param configureField: function called with each field of the - form view right after the form is - displayed, lets whoever called this - method do some last-minute - configuration of form fields. - :type configureField: Function<String, openerp.web.form.Field> - :param EditOptions options: - :returns: jQuery delegate to the form object - - .. js:function:: openerp.web.list.Editor.save - - Attempts to save the internal form, then hide it - - :returns: delegate to the record under edition (with ``id`` - added for a creation). The record is not updated - from when it was passed in, aside from the ``id`` - attribute. - - .. js:function:: openerp.web.list.Editor.cancel([force=false]) - - Attemps to cancel the edition of the internal form, then hide - the form - - :param Boolean force: unconditionally cancels the edition of - the internal form, even if the user has - already entered data in it. - :returns: delegate to the record under edition - -.. js:class:: EditorOptions - - .. js:attribute:: EditorOptions.formView - - Form view (sub)-class to instantiate and delegate edition to. - - By default, :js:class:`~openerp.web.FormView` - - .. js:attribute:: EditorOptions.delegate - - Object used to get various bits of information about how to - display stuff. - - By default, uses the editor's parent widget. See - :js:class:`EditorDelegate` for the methods and attributes to - provide. - -.. js:class:: EditorDelegate - - Informal protocol defining the methods and attributes expected of - the :js:class:`~openerp.web.list.Editor`'s delegate. - - .. js:attribute:: EditorDelegate.dataset - - The dataset passed to the form view to synchronize the form - view and the outer widget. - - .. js:function:: EditorDelegate.edition_view(editor) - - Called by the :js:class:`~openerp.web.list.Editor` object to - get a form view (JSON) to pass along to the form view it - created. - - The result should be a valid form view, see :doc:`Form Notes - <form-notes>` for various peculiarities of the form view - format. - - :param editor: editor object asking for the view - :type editor: :js:class:`~openerp.web.list.Editor` - :returns: form view - :rtype: Object - - .. js:function:: EditorDelegate.prepends_on_create - - By default, the :js:class:`~openerp.web.list.Editor` will - append the ids of newly created records to the - :js:attr:`EditorDelegate.dataset`. If this method returns - ``true``, it will prepend these ids instead. - - :returns: whether new records should be prepended to the - dataset (instead of appended) - :rtype: Boolean - - -.. js:class:: EditOptions - - Options object optionally passed into a method starting an edition - to configure its setup and behavior - - .. js:attribute:: focus_field - - Name of the field to set focus on after setting up the edition - of the record. - - If this option is not provided, or the requested field can not - be focused (invisible, readonly or not in the view), the first - visible non-readonly field is focused. - -Changes from 6.1 ----------------- - -* The editable listview behavior has been rewritten pretty much from - scratch, any code touching on editability will have to be modified - - * The overloading of :js:class:`~openerp.web.ListView.Groups` and - :js:class:`~openerp.web.ListView.List` for editability has been - drastically simplified, and most of the behavior has been moved to - the list view itself. Only - :js:func:`~openerp.web.ListView.List.row_clicked` is still - overridden. - - * A new method ``get_row_for(record) -> jQuery(tr) | null`` has been - added to both ListView.List and ListView.Group, it can be called - from the list view to get the table row matching a record (if such - a row exists). - -* :js:func:`~openerp.web.ListView.do_button_action`'s core behavior - has been split away to - :js:func:`~openerp.web.ListView.handle_button`. This allows bypassing - overrides of :js:func:`~openerp.web.ListView.do_button_action` in a - parent class. - - Ideally, :js:func:`~openerp.web.ListView.handle_button` should not be - overridden. - -* Modifiers handling has been improved (all modifiers information - should now be available through :js:func:`~Column.modifiers_for`, - not just ``invisible``) - -* Changed some handling of the list view's record: a record may now - have no id, and the listview will handle that correctly (for new - records being created) as well as correctly handle the ``id`` being - set. - -* Extended the internal collections structure of the list view with - `#find`_, `#succ`_ and `#pred`_. - -.. _#find: http://underscorejs.org/#find - -.. _#succ: http://hackage.haskell.org/packages/archive/base/latest/doc/html/Prelude.html#v:succ - -.. _#pred: http://hackage.haskell.org/packages/archive/base/latest/doc/html/Prelude.html#v:pred diff --git a/doc/make.bat b/doc/make.bat deleted file mode 100644 index 3e72cadb53b..00000000000 --- a/doc/make.bat +++ /dev/null @@ -1,170 +0,0 @@ -@ECHO OFF - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set BUILDDIR=_build -set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . -if NOT "%PAPER%" == "" ( - set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% -) - -if "%1" == "" goto help - -if "%1" == "help" ( - :help - echo.Please use `make ^<target^>` where ^<target^> is one of - echo. html to make standalone HTML files - echo. dirhtml to make HTML files named index.html in directories - echo. singlehtml to make a single large HTML file - echo. pickle to make pickle files - echo. json to make JSON files - echo. htmlhelp to make HTML files and a HTML help project - echo. qthelp to make HTML files and a qthelp project - echo. devhelp to make HTML files and a Devhelp project - echo. epub to make an epub - echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter - echo. text to make text files - echo. man to make manual pages - echo. changes to make an overview over all changed/added/deprecated items - echo. linkcheck to check all external links for integrity - echo. doctest to run all doctests embedded in the documentation if enabled - goto end -) - -if "%1" == "clean" ( - for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i - del /q /s %BUILDDIR%\* - goto end -) - -if "%1" == "html" ( - %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/html. - goto end -) - -if "%1" == "dirhtml" ( - %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. - goto end -) - -if "%1" == "singlehtml" ( - %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. - goto end -) - -if "%1" == "pickle" ( - %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can process the pickle files. - goto end -) - -if "%1" == "json" ( - %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can process the JSON files. - goto end -) - -if "%1" == "htmlhelp" ( - %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can run HTML Help Workshop with the ^ -.hhp project file in %BUILDDIR%/htmlhelp. - goto end -) - -if "%1" == "qthelp" ( - %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can run "qcollectiongenerator" with the ^ -.qhcp project file in %BUILDDIR%/qthelp, like this: - echo.^> qcollectiongenerator %BUILDDIR%\qthelp\OpenERPWeb.qhcp - echo.To view the help file: - echo.^> assistant -collectionFile %BUILDDIR%\qthelp\OpenERPWeb.ghc - goto end -) - -if "%1" == "devhelp" ( - %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. - goto end -) - -if "%1" == "epub" ( - %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The epub file is in %BUILDDIR%/epub. - goto end -) - -if "%1" == "latex" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. - goto end -) - -if "%1" == "text" ( - %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The text files are in %BUILDDIR%/text. - goto end -) - -if "%1" == "man" ( - %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The manual pages are in %BUILDDIR%/man. - goto end -) - -if "%1" == "changes" ( - %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes - if errorlevel 1 exit /b 1 - echo. - echo.The overview file is in %BUILDDIR%/changes. - goto end -) - -if "%1" == "linkcheck" ( - %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck - if errorlevel 1 exit /b 1 - echo. - echo.Link check complete; look for any errors in the above output ^ -or in %BUILDDIR%/linkcheck/output.txt. - goto end -) - -if "%1" == "doctest" ( - %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest - if errorlevel 1 exit /b 1 - echo. - echo.Testing of doctests in the sources finished, look at the ^ -results in %BUILDDIR%/doctest/output.txt. - goto end -) - -:end diff --git a/doc/rpc.rst b/doc/rpc.rst deleted file mode 100644 index 4787978e187..00000000000 --- a/doc/rpc.rst +++ /dev/null @@ -1,276 +0,0 @@ -Outside the box: network interactions -===================================== - -Building static displays is all nice and good and allows for neat -effects (and sometimes you're given data to display from third parties -so you don't have to make any effort), but a point generally comes -where you'll want to talk to the world and make some network requests. - -OpenERP Web provides two primary APIs to handle this, a low-level -JSON-RPC based API communicating with the Python section of OpenERP -Web (and of your addon, if you have a Python part) and a high-level -API above that allowing your code to talk directly to the OpenERP -server, using familiar-looking calls. - -All networking APIs are :doc:`asynchronous </async>`. As a result, all -of them will return :js:class:`Deferred` objects (whether they resolve -those with values or not). Understanding how those work before before -moving on is probably necessary. - -High-level API: calling into OpenERP models -------------------------------------------- - -Access to OpenERP object methods (made available through XML-RPC from -the server) is done via the :js:class:`openerp.web.Model` class. This -class maps onto the OpenERP server objects via two primary methods, -:js:func:`~openerp.web.Model.call` and -:js:func:`~openerp.web.Model.query`. - -:js:func:`~openerp.web.Model.call` is a direct mapping to the -corresponding method of the OpenERP server object. Its usage is -similar to that of the OpenERP Model API, with three differences: - -* The interface is :doc:`asynchronous </async>`, so instead of - returning results directly RPC method calls will return - :js:class:`Deferred` instances, which will themselves resolve to the - result of the matching RPC call. - -* Because ECMAScript 3/Javascript 1.5 doesnt feature any equivalent to - ``__getattr__`` or ``method_missing``, there needs to be an explicit - method to dispatch RPC methods. - -* No notion of pooler, the model proxy is instantiated where needed, - not fetched from an other (somewhat global) object - -.. code-block:: javascript - - var Users = new Model('res.users'); - - Users.call('change_password', ['oldpassword', 'newpassword'], - {context: some_context}).then(function (result) { - // do something with change_password result - }); - -:js:func:`~openerp.web.Model.query` is a shortcut for a builder-style -interface to searches (``search`` + ``read`` in OpenERP RPC terms). It -returns a :js:class:`~openerp.web.Query` object which is immutable but -allows building new :js:class:`~openerp.web.Query` instances from the -first one, adding new properties or modifiying the parent object's: - -.. code-block:: javascript - - Users.query(['name', 'login', 'user_email', 'signature']) - .filter([['active', '=', true], ['company_id', '=', main_company]]) - .limit(15) - .all().then(function (users) { - // do work with users records - }); - -The query is only actually performed when calling one of the query -serialization methods, :js:func:`~openerp.web.Query.all` and -:js:func:`~openerp.web.Query.first`. These methods will perform a new -RPC call every time they are called. - -For that reason, it's actually possible to keep "intermediate" queries -around and use them differently/add new specifications on them. - -.. js:class:: openerp.web.Model(name) - - .. js:attribute:: openerp.web.Model.name - - name of the OpenERP model this object is bound to - - .. js:function:: openerp.web.Model.call(method[, args][, kwargs]) - - Calls the ``method`` method of the current model, with the - provided positional and keyword arguments. - - :param String method: method to call over rpc on the - :js:attr:`~openerp.web.Model.name` - :param Array<> args: positional arguments to pass to the - method, optional - :param Object<> kwargs: keyword arguments to pass to the - method, optional - :rtype: Deferred<> - - .. js:function:: openerp.web.Model.query(fields) - - :param Array<String> fields: list of fields to fetch during - the search - :returns: a :js:class:`~openerp.web.Query` object - representing the search to perform - -.. js:class:: openerp.web.Query(fields) - - The first set of methods is the "fetching" methods. They perform - RPC queries using the internal data of the object they're called - on. - - .. js:function:: openerp.web.Query.all() - - Fetches the result of the current - :js:class:`~openerp.web.Query` object's search. - - :rtype: Deferred<Array<>> - - .. js:function:: openerp.web.Query.first() - - Fetches the **first** result of the current - :js:class:`~openerp.web.Query`, or ``null`` if the current - :js:class:`~openerp.web.Query` does have any result. - - :rtype: Deferred<Object | null> - - .. js:function:: openerp.web.Query.count() - - Fetches the number of records the current - :js:class:`~openerp.web.Query` would retrieve. - - :rtype: Deferred<Number> - - .. js:function:: openerp.web.Query.group_by(grouping...) - - Fetches the groups for the query, using the first specified - grouping parameter - - :param Array<String> grouping: Lists the levels of grouping - asked of the server. Grouping - can actually be an array or - varargs. - :rtype: Deferred<Array<openerp.web.QueryGroup>> | null - - The second set of methods is the "mutator" methods, they create a - **new** :js:class:`~openerp.web.Query` object with the relevant - (internal) attribute either augmented or replaced. - - .. js:function:: openerp.web.Query.context(ctx) - - Adds the provided ``ctx`` to the query, on top of any existing - context - - .. js:function:: openerp.web.Query.filter(domain) - - Adds the provided domain to the query, this domain is - ``AND``-ed to the existing query domain. - - .. js:function:: opeenrp.web.Query.offset(offset) - - Sets the provided offset on the query. The new offset - *replaces* the old one. - - .. js:function:: openerp.web.Query.limit(limit) - - Sets the provided limit on the query. The new limit *replaces* - the old one. - - .. js:function:: openerp.web.Query.order_by(fields…) - - Overrides the model's natural order with the provided field - specifications. Behaves much like Django's `QuerySet.order_by - <https://docs.djangoproject.com/en/dev/ref/models/querysets/#order-by>`_: - - * Takes 1..n field names, in order of most to least importance - (the first field is the first sorting key). Fields are - provided as strings. - - * A field specifies an ascending order, unless it is prefixed - with the minus sign "``-``" in which case the field is used - in the descending order - - Divergences from Django's sorting include a lack of random sort - (``?`` field) and the inability to "drill down" into relations - for sorting. - -Aggregation (grouping) -~~~~~~~~~~~~~~~~~~~~~~ - -OpenERP has powerful grouping capacities, but they are kind-of strange -in that they're recursive, and level n+1 relies on data provided -directly by the grouping at level n. As a result, while ``read_group`` -works it's not a very intuitive API. - -OpenERP Web 7.0 eschews direct calls to ``read_group`` in favor of -calling a method of :js:class:`~openerp.web.Query`, `much in the way -it is one in SQLAlchemy -<http://docs.sqlalchemy.org/en/latest/orm/query.html#sqlalchemy.orm.query.Query.group_by>`_ [#]_: - -.. code-block:: javascript - - some_query.group_by(['field1', 'field2']).then(function (groups) { - // do things with the fetched groups - }); - -This method is asynchronous when provided with 1..n fields (to group -on) as argument, but it can also be called without any field (empty -fields collection or nothing at all). In this case, instead of -returning a Deferred object it will return ``null``. - -When grouping criterion come from a third-party and may or may not -list fields (e.g. could be an empty list), this provides two ways to -test the presence of actual subgroups (versus the need to perform a -regular query for records): - -* A check on ``group_by``'s result and two completely separate code - paths - - .. code-block:: javascript - - var groups; - if (groups = some_query.group_by(gby)) { - groups.then(function (gs) { - // groups - }); - } - // no groups - -* Or a more coherent code path using :js:func:`when`'s ability to - coerce values into deferreds: - - .. code-block:: javascript - - $.when(some_query.group_by(gby)).then(function (groups) { - if (!groups) { - // No grouping - } else { - // grouping, even if there are no groups (groups - // itself could be an empty array) - } - }); - -The result of a (successful) :js:func:`~openerp.web.Query.group_by` is -an array of :js:class:`~openerp.web.QueryGroup`. - -Low-level API: RPC calls to Python side ---------------------------------------- - -While the previous section is great for calling core OpenERP code -(models code), it does not work if you want to call the Python side of -OpenERP Web. - -For this, a lower-level API exists on on -:js:class:`~openerp.web.Connection` objects (usually available through -``openerp.connection``): the ``rpc`` method. - -This method simply takes an absolute path (which is the combination of -the Python controller's ``_cp_path`` attribute and the name of the -method you want to call) and a mapping of attributes to values (applied -as keyword arguments on the Python method [#]_). This function fetches -the return value of the Python methods, converted to JSON. - -For instance, to call the ``eval_domain_and_context`` of the -:class:`~web.controllers.main.Session` controller: - -.. code-block:: javascript - - openerp.connection.rpc('/web/session/eval_domain_and_context', { - domains: ds, - contexts: cs - }).then(function (result) { - // handle result - }); - -.. [#] with a small twist: SQLAlchemy's ``orm.query.Query.group_by`` - is not terminal, it returns a query which can still be altered. - -.. [#] except for ``context``, which is extracted and stored in the - request object itself. diff --git a/doc/search-view.rst b/doc/search-view.rst deleted file mode 100644 index 16a91c5e9ac..00000000000 --- a/doc/search-view.rst +++ /dev/null @@ -1,549 +0,0 @@ -Search View -=========== - -OpenERP Web 7.0 implements a unified facets-based search view instead -of the previous form-like search view (composed of buttons and -multiple fields). The goal for this change is twofold: - -* Avoid the common issue of users confusing the search view with a - form view and trying to create their records through it (or entering - all their data, hitting the ``Create`` button expecting their record - to be created and losing everything). - -* Improve the looks and behaviors of the view, and the fit within - OpenERP Web's new design. - -The internal structure of the faceted search is inspired by -`VisualSearch <http://documentcloud.github.com/visualsearch/>`_ -[#previous]_. - -As does VisualSearch, the new search view is based on `Backbone`_ and -makes significant use of Backbone's models and collections (OpenERP -Web's widgets make a good replacement for Backbone's own views). As a -result, understanding the implementation details of the OpenERP Web 7 -search view also requires a basic understanding of Backbone's models, -collections and events. - -.. note:: - - This document may mention *fetching* data. This is a shortcut for - "returning a :js:class:`Deferred` to [whatever is being - fetched]". Unless further noted, the function or method may opt to - return nothing by fetching ``null`` (which can easily be done by - returning ``$.when(null)``, which simply wraps the ``null`` in a - Deferred). - -Working with the search view: creating new inputs -------------------------------------------------- - -The primary component of search views, as with all other OpenERP -views, are inputs. The search view has two types of inputs — filters -and fields — but only one is easly customizable: fields. - -The mapping from OpenERP field types (and widgets) to search view -objects is stored in the ``openerp.web.search.fields`` -:js:class:`~openerp.web.Registry` where new field types and widgets -can be added. - -Search view inputs have four main roles: - -Loading defaults -++++++++++++++++ - -Once the search view has initialized all its inputs, it will call -:js:func:`~openerp.web.search.Input.facet_for_defaults` on each input, -passing it a mapping (a javascript object) of ``name:value`` extracted -from the action's context. - -This method should fetch a :js:class:`~openerp.web.search.Facet` (or -an equivalent object) for the field's default value if applicable (if -a default value for the field is found in the ``defaults`` mapping). - -A default implementation is provided which checks if ``defaults`` -contains a non-falsy value for the field's ``@name`` and calls -:js:func:`openerp.web.search.Input.facet_for` with that value. - -There is no default implementation of -:js:func:`openerp.web.search.Input.facet_for` [#no_impl]_, but -:js:class:`openerp.web.search.Field` provides one, which uses the -value as-is to fetch a :js:class:`~openerp.web.search.Facet`. - -Providing completions -+++++++++++++++++++++ - -An important component of the new search view is the auto-completion -pane, and the task of providing completion items is delegated to -inputs through the :js:func:`~openerp.web.search.Input.complete` -method. - -This method should take a single argument (the string being typed by -the user) and should fetch an ``Array`` of possible completions -[#completion]_. - -A default implementation is provided which fetches nothing. - -A completion item is a javascript object with two keys (technically it -can have any number of keys, but only these two will be used by the -search view): - -``label`` - - The string which will be displayed in the completion pane. It may - be formatted using HTML (inline only), as a result if ``value`` is - interpolated into it it *must* be escaped. ``_.escape`` can be - used for this. - -``facet`` - - Either a :js:class:`~openerp.web.search.Facet` object or (more - commonly) the corresponding attributes object. This is the facet - which will be inserted into the search query if the completion - item is selected by the user. - -If the ``facet`` is not provided (not present, ``null``, ``undefined`` -or any other falsy value), the completion item will not be selectable -and will act as a section title of sort (the ``label`` will be -formatted differently). If an input *may* fetch multiple completion -items, it *should* prefix those with a section title using its own -name. This has no technical consequence but is clearer for users. - -Providing drawer/supplementary UI -+++++++++++++++++++++++++++++++++ - -For some inputs (fields or not), interaction via autocompletion may be -awkward or even impossible. - -These may opt to being rendered in a "drawer" as well or instead. In -that case, they will undergo the normal widget lifecycle and be -rendered inside the drawer. - -.. Found no good type-based way to handle this, since there is no MI - (so no type-tagging) and it's possible for both Field and non-Field - input to be put into the drawer, for whatever reason (e.g. some - sort of auto-detector completion item for date widgets, but a - second more usual calendar widget in the drawer for more - obvious/precise interactions) - -Any input can note its desire to be rendered in the drawer by -returning a truthy value from -:js:func:`~openerp.web.search.Input.in_drawer`. - -By default, :js:func:`~openerp.web.search.Input.in_drawer` returns the -value of :js:attr:`~openerp.web.search.Input._in_drawer`, which is -``false``. The behavior can be toggled either by redefining the -attribute to ``true`` (either on the class or on the input), or by -overriding :js:func:`~openerp.web.search.Input.in_drawer` itself. - -The input will be rendered in the full width of the drawer, it will be -started only once (per view). - -.. todo:: drawer API (if a widget wants to close the drawer in some - way), part of the low-level SearchView API/interactions? - - -.. todo:: handle filters and filter groups via a "driver" input which - dynamically collects, lays out and renders filters? => - exercises drawer thingies - -Converting from facet objects -+++++++++++++++++++++++++++++ - -Ultimately, the point of the search view is to allow searching. In -OpenERP this is done via :ref:`domains <openerpserver:domains>`. On -the other hand, the OpenERP Web 7 search view's state is modelled -after a collection of :js:class:`~openerp.web.search.Facet`, and each -field of a search view may have special requirements when it comes to -the domains it produces [#special]_. - -So there needs to be some way of mapping -:js:class:`~openerp.web.search.Facet` objects to OpenERP search data. - -This is done via an input's -:js:func:`~openerp.web.search.Input.get_domain` and -:js:func:`~openerp.web.search.Input.get_context`. Each takes a -:js:class:`~openerp.web.search.Facet` and returns whatever it's -supposed to generate (a domain or a context, respectively). Either can -return ``null`` if the current value does not map to a domain or -context, and can throw an :js:class:`~openerp.web.search.Invalid` -exception if the value is not valid at all for the field. - -.. note:: - - The :js:class:`~openerp.web.search.Facet` object can have any - number of values (from 1 upwards) - -.. note:: - - There is a third conversion method, - :js:func:`~openerp.web.search.Input.get_groupby`, which returns an - ``Array`` of groupby domains rather than a single context. At this - point, it is only implemented on (and used by) filters. - -Programmatic interactions: internal model ------------------------------------------ - -This new searchview is built around an instance of -:js:class:`~openerp.web.search.SearchQuery` available as -:js:attr:`openerp.web.SearchView.query`. - -The query is a `backbone collection`_ of -:js:class:`~openerp.web.search.Facet` objects, which can be interacted -with directly by external objects or search view controls -(e.g. widgets displayed in the drawer). - -.. js:class:: openerp.web.search.SearchQuery - - The current search query of the search view, provides convenience - behaviors for manipulating :js:class:`~openerp.web.search.Facet` - on top of the usual `backbone collection`_ methods. - - The query ensures all of its facets contain at least one - :js:class:`~openerp.web.search.FacetValue` instance. Otherwise, - the facet is automatically removed from the query. - - .. js:function:: openerp.web.search.SearchQuery.add(values, options) - - Overridden from the base ``add`` method so that adding a facet - which is *already* in the collection will merge the value of - the new facet into the old one rather than add a second facet - with different values. - - :param values: facet, facet attributes or array thereof - :returns: the collection itself - - .. js:function:: openerp.web.search.SearchQuery.toggle(value, options) - - Convenience method for toggling facet values in a query: - removes the values (through the facet itself) if they are - present, adds them if they are not. If the facet itself is not - in the collection, adds it automatically. - - A toggling is atomic: only one change event will be triggered - on the facet regardless of the number of values added to or - removed from the facet (if the facet already exists), and the - facet is only removed from the query if it has no value *at - the end* of the toggling. - - :param value: facet or facet attributes - :returns: the collection - -.. js:class:: openerp.web.search.Facet - - A `backbone model`_ representing a single facet of the current - research. May map to a search field, or to a more complex or - fuzzier input (e.g. a custom filter or an advanced search). - - .. js:attribute:: category - - The displayed name of the facet, as a ``String``. This is a - backbone model attribute. - - .. js:attribute:: field - - The :js:class:`~openerp.web.search.Input` instance which - originally created the facet [#facet-field]_, used to delegate - some operations (such as serializing the facet's values to - domains and contexts). This is a backbone model attribute. - - .. js:attribute:: values - - :js:class:`~openerp.web.search.FacetValues` as a javascript - attribute, stores all the values for the facet and helps - propagate their events to the facet. Is also available as a - backbone attribute (via ``#get`` and ``#set``) in which cases - it serializes to and deserializes from javascript arrays (via - ``Collection#toJSON`` and ``Collection#reset``). - - .. js:attribute:: [icon] - - optional, a single ASCII letter (a-z or A-Z) mapping to the - bundled mnmliconsRegular icon font. - - When a facet with an ``icon`` attribute is rendered, the icon - is displayed (in the icon font) in the first section of the - facet instead of the ``category``. - - By default, only filters make use of this facility. - -.. js:class:: openerp.web.search.FacetValues - - `Backbone collection`_ of - :js:class:`~openerp.web.search.FacetValue` instances. - -.. js:class:: openerp.web.search.FacetValue - - `Backbone model`_ representing a single value within a facet, - represents a pair of (displayed name, logical value). - - .. js:attribute:: label - - Backbone model attribute storing the "displayable" - representation of the value, visually output to the - user. Must be a string. - - .. js:attribute:: value - - Backbone model attribute storing the logical/internal value - (of itself), will be used by - :js:class:`~openerp.web.search.Input` to serialize to domains - and contexts. - - Can be of any type. - -Field services --------------- - -:js:class:`~openerp.web.search.Field` provides a default -implementation of :js:func:`~openerp.web.search.Input.get_domain` and -:js:func:`~openerp.web.search.Input.get_context` taking care of most -of the peculiarities pertaining to OpenERP's handling of fields in -search views. It also provides finer hooks to let developers of new -fields and widgets customize the behavior they want without -necessarily having to reimplement all of -:js:func:`~openerp.web.search.Input.get_domain` or -:js:func:`~openerp.web.search.Input.get_context`: - -.. js:function:: openerp.web.search.Field.get_context(facet) - - If the field has no ``@context``, simply returns - ``null``. Otherwise, calls - :js:func:`~openerp.web.search.Field.value_from` once for each - :js:class:`~openerp.web.search.FacetValue` of the current - :js:class:`~openerp.web.search.Facet` (in order to extract the - basic javascript object from the - :js:class:`~openerp.web.search.FacetValue` then evaluates - ``@context`` with each of these values set as ``self``, and - returns the union of all these contexts. - - :param facet: - :type facet: openerp.web.search.Facet - :returns: a context (literal or compound) - -.. js:function:: openerp.web.search.Field.get_domain(facet) - - If the field has no ``@filter_domain``, calls - :js:func:`~openerp.web.search.Field.make_domain` once with each - :js:class:`~openerp.web.search.FacetValue` of the current - :js:class:`~openerp.web.search.Facet` as well as the field's - ``@name`` and either its ``@operator`` or - :js:attr:`~openerp.web.search.Field.default_operator`. - - If the field has an ``@filter_value``, calls - :js:func:`~openerp.web.search.Field.value_from` once per - :js:class:`~openerp.web.search.FacetValue` and evaluates - ``@filter_value`` with each of these values set as ``self``. - - In either case, "ors" all of the resulting domains (using ``|``) - if there is more than one - :js:class:`~openerp.web.search.FacetValue` and returns the union - of the result. - - :param facet: - :type facet: openerp.web.search.Facet - :returns: a domain (literal or compound) - -.. js:function:: openerp.web.search.Field.make_domain(name, operator, facetValue) - - Builds a literal domain from the provided data. Calls - :js:func:`~openerp.web.search.Field.value_from` on the - :js:class:`~openerp.web.search.FacetValue` and evaluates and sets - it as the domain's third value, uses the other two parameters as - the first two values. - - Can be overridden to build more complex default domains. - - :param String name: the field's name - :param String operator: the operator to use in the field's domain - :param facetValue: - :type facetValue: openerp.web.search.FacetValue - :returns: Array<(String, String, Object)> - -.. js:function:: openerp.web.search.Field.value_from(facetValue) - - Extracts a "bare" javascript value from the provided - :js:class:`~openerp.web.search.FacetValue`, and returns it. - - The default implementation will simply return the ``value`` - backbone property of the argument. - - :param facetValue: - :type facetValue: openerp.web.search.FacetValue - :returns: Object - -.. js:attribute:: openerp.web.search.Field.default_operator - - Operator used to build a domain when a field has no ``@operator`` - or ``@filter_domain``. ``"="`` for - :js:class:`~openerp.web.search.Field` - -Arbitrary data storage ----------------------- - -:js:class:`~openerp.web.search.Facet` and -:js:class:`~openerp.web.search.FacetValue` objects (and structures) -provided by your widgets should never be altered by the search view -(or an other widget). This means you are free to add arbitrary fields -in these structures if you need to (because you have more complex -needs than the attributes described in this document). - -Ideally this should be avoided, but the possibility remains. - -Changes -------- - -.. todo:: merge in changelog instead? - -The displaying of the search view was significantly altered from -OpenERP Web 6.1 to OpenERP Web 7. - -As a result, while the external API used to interact with the search -view does not change many internal details — including the interaction -between the search view and its widgets — were significantly altered: - -Internal operations -+++++++++++++++++++ - -* :js:func:`openerp.web.SearchView.do_clear` has been removed -* :js:func:`openerp.web.SearchView.do_toggle_filter` has been removed - -Widgets API -+++++++++++ - -* :js:func:`openerp.web.search.Widget.render` has been removed - -* :js:func:`openerp.web.search.Widget.make_id` has been removed - -* Search field objects are not openerp widgets anymore, their - ``start`` is not generally called - -* :js:func:`~openerp.web.search.Input.clear` has been removed since - clearing the search view now simply consists of removing all search - facets - -* :js:func:`~openerp.web.search.Input.get_domain` and - :js:func:`~openerp.web.search.Input.get_context` now take a - :js:class:`~openerp.web.search.Facet` as parameter, from which it's - their job to get whatever value they want - -* :js:func:`~openerp.web.search.Input.get_groupby` has been added. It returns - an :js:class:`Array` of context-like constructs. By default, it does not do - anything in :js:class:`~openerp.web.search.Field` and it returns the various - contexts of its enabled filters in - :js:class:`~openerp.web.search.FilterGroup`. - -Filters -+++++++ - -* :js:func:`openerp.web.search.Filter.is_enabled` has been removed - -* :js:class:`~openerp.web.search.FilterGroup` instances are still - rendered (and started) in the "advanced search" drawer. - -Fields -++++++ - -* ``get_value`` has been replaced by - :js:func:`~openerp.web.search.Field.value_from` as it now takes a - :js:class:`~openerp.web.search.FacetValue` argument (instead of no - argument). It provides a default implementation returning the - ``value`` property of its argument. - -* The third argument to - :js:func:`~openerp.web.search.Field.make_domain` is now a - :js:class:`~openerp.web.search.FacetValue` so child classes have all - the information they need to derive the "right" resulting domain. - -Custom filters -++++++++++++++ - -Instead of being an intrinsic part of the search view, custom filters -are now a special case of filter groups. They are treated specially -still, but much less so than they used to be. - -Many To One -+++++++++++ - -* Because the autocompletion service is now provided by the search - view itself, - :js:func:`openerp.web.search.ManyToOneField.setup_autocomplete` has - been removed. - -Advanced Search -+++++++++++++++ - -* The advanced search is now a more standard - :js:class:`~openerp.web.search.Input` configured to be rendered in - the drawer. - -* :js:class:`~openerp.web.search.ExtendedSearchProposition.Field` are - now standard widgets, with the "right" behaviors (they don't rebind - their ``$element`` in ``start()``) - -* The ad-hoc optional setting of the openerp field descriptor on a - :js:class:`~openerp.web.search.ExtendedSearchProposition.Field` has - been removed, the field descriptor is now passed as second argument - to the - :js:class:`~openerp.web.search.ExtendedSearchProposition.Field`'s - constructor, and bound to its - :js:attr:`~openerp.web.search.ExtendedSearchProposition.Field.field`. - -* Instead of its former domain triplet ``(field, operator, value)``, - :js:func:`~openerp.web.search.ExtendedSearchProposition.get_proposition` - now returns an object with two fields ``label`` and ``value``, - respectively a human-readable version of the proposition and the - corresponding domain triplet for the proposition. - -.. [#previous] - - the original view was implemented on top of a monkey-patched - VisualSearch, but as our needs diverged from VisualSearch's goal - this made less and less sense ultimately leading to a clean-room - reimplementation - -.. [#no_impl] - - In case you are extending the search view with a brand new type of - input - -.. [#completion] - - Ideally this array should not hold more than about 10 items, but - the search view does not put any constraint on this at the - moment. Note that this may change. - -.. [#facet-field] - - ``field`` does not actually need to be an instance of - :js:class:`~openerp.web.search.Input`, nor does it need to be what - created the facet, it just needs to provide the three - facet-serialization methods - :js:func:`~openerp.web.search.Input.get_domain`, - :js:func:`~openerp.web.search.Input.get_context` and - :js:func:`~openerp.web.search.Input.get_gropuby`, existing - :js:class:`~openerp.web.search.Input` subtypes merely provide - convenient base implementation for those methods. - - Complex search view inputs (especially those living in the drawer) - may prefer using object literals with the right slots returning - closed-over values or some other scheme un-bound to an actual - :js:class:`~openerp.web.search.Input`, as - :js:class:`~openerp.web.search.CustomFilters` and - :js:class:`~openerp.web.search.Advanced` do. - -.. [#special] - - search view fields may also bundle context data to add to the - search context - -.. _Backbone: - http://documentcloud.github.com/backbone/ - -.. _Backbone.Collection: -.. _Backbone collection: - http://documentcloud.github.com/backbone/#Collection - -.. _Backbone model: - http://documentcloud.github.com/backbone/#Model - -.. _commit 3fca87101d: - https://github.com/documentcloud/visualsearch/commit/3fca87101d diff --git a/doc/widget.rst b/doc/widget.rst deleted file mode 100644 index ddfe525227d..00000000000 --- a/doc/widget.rst +++ /dev/null @@ -1,274 +0,0 @@ -User Interaction: Widget -======================== - -This is the base class for all visual components. It corresponds to an MVC -view. It provides a number of services to handle a section of a page: - -* Rendering with QWeb - -* Parenting-child relations - -* Life-cycle management (including facilitating children destruction when a - parent object is removed) - -* DOM insertion, via jQuery-powered insertion methods. Insertion targets can - be anything the corresponding jQuery method accepts (generally selectors, - DOM nodes and jQuery objects): - - :js:func:`~openerp.base.Widget.appendTo` - Renders the widget and inserts it as the last child of the target, uses - `.appendTo()`_ - - :js:func:`~openerp.base.Widget.prependTo` - Renders the widget and inserts it as the first child of the target, uses - `.prependTo()`_ - - :js:func:`~openerp.base.Widget.insertAfter` - Renders the widget and inserts it as the preceding sibling of the target, - uses `.insertAfter()`_ - - :js:func:`~openerp.base.Widget.insertBefore` - Renders the widget and inserts it as the following sibling of the target, - uses `.insertBefore()`_ - -* Backbone-compatible shortcuts - -DOM Root --------- - -A :js:class:`~openerp.web.Widget` is responsible for a section of the -page materialized by the DOM root of the widget. The DOM root is -available via the :js:attr:`~openerp.web.Widget.el` and -:js:attr:`~openerp.web.Widget.$element` attributes, which are -respectively the raw DOM Element and the jQuery wrapper around the DOM -element. - -There are two main ways to define and generate this DOM root: - -.. js:attribute:: openerp.web.Widget.template - - Should be set to the name of a QWeb template (a - :js:class:`String`). If set, the template will be rendered after - the widget has been initialized but before it has been - started. The root element generated by the template will be set as - the DOM root of the widget. - -.. js:attribute:: openerp.web.Widget.tagName - - Used if the widget has no template defined. Defaults to ``div``, - will be used as the tag name to create the DOM element to set as - the widget's DOM root. It is possible to further customize this - generated DOM root with the following attributes: - - .. js:attribute:: openerp.web.Widget.id - - Used to generate an ``id`` attribute on the generated DOM - root. - - .. js:attribute:: openerp.web.Widget.className - - Used to generate a ``class`` attribute on the generated DOM root. - - .. js:attribute:: openerp.web.Widget.attributes - - Mapping (object literal) of attribute names to attribute - values. Each of these k:v pairs will be set as a DOM attribute - on the generated DOM root. - - None of these is used in case a template is specified on the widget. - -The DOM root can also be defined programmatically by overridding - -.. js:function:: openerp.web.Widget.renderElement - - Renders the widget's DOM root and sets it. The default - implementation will render a set template or generate an element - as described above, and will call - :js:func:`~openerp.web.Widget.setElement` on the result. - - Any override to :js:func:`~openerp.web.Widget.renderElement` which - does not call its ``_super`` **must** call - :js:func:`~openerp.web.Widget.setElement` with whatever it - generated or the widget's behavior is undefined.r - - .. note:: - - The default :js:func:`~openerp.web.Widget.renderElement` can - be called repeatedly, it will *replace* the previous DOM root - (using ``replaceWith``). However, this requires that the - widget correctly sets and unsets its events (and children - widgets). Generally, - :js:func:`~openerp.web.Widget.renderElement` should not be - called repeatedly unless the widget advertizes this feature. - -Accessing DOM content -~~~~~~~~~~~~~~~~~~~~~ - -Because a widget is only responsible for the content below its DOM -root, there is a shortcut for selecting sub-sections of a widget's -DOM: - -.. js:function:: openerp.web.Widget.$(selector) - - Applies the CSS selector specified as parameter to the widget's - DOM root. - - .. code-block:: javascript - - this.$(selector); - - is functionally identical to: - - .. code-block:: javascript - - this.$element.find(selector); - - :param String selector: CSS selector - :returns: jQuery object - - .. note:: this helper method is compatible with - ``Backbone.View.$`` - -Resetting the DOM root -~~~~~~~~~~~~~~~~~~~~~~ - -.. js:function:: openerp.web.Widget.setElement(element) - - Re-sets the widget's DOM root to the provided element, also - handles re-setting the various aliases of the DOM root as well as - unsetting and re-setting delegated events. - - :param Element element: a DOM element or jQuery object to set as - the widget's DOM root - - .. note:: should be mostly compatible with `Backbone's - setElement`_ - -DOM events handling -------------------- - -A widget will generally need to respond to user action within its -section of the page. This entails binding events to DOM elements. - -To this end, :js:class:`~openerp.web.Widget` provides an shortcut: - -.. js:attribute:: openerp.web.Widget.events - - Events are a mapping of ``event selector`` (an event name and a - CSS selector separated by a space) to a callback. The callback can - be either a method name in the widget or a function. In either - case, the ``this`` will be set to the widget. - - The selector is used for jQuery's `event delegation`_, the - callback will only be triggered for descendants of the DOM root - matching the selector [0]_. If the selector is left out (only an - event name is specified), the event will be set directly on the - widget's DOM root. - -.. js:function:: openerp.web.Widget.delegateEvents - - This method is in charge of binding - :js:attr:`~openerp.web.Widget.events` to the DOM. It is - automatically called after setting the widget's DOM root. - - It can be overridden to set up more complex events than the - :js:attr:`~openerp.web.Widget.events` map allows, but the parent - should always be called (or :js:attr:`~openerp.web.Widget.events` - won't be handled correctly). - -.. js:function:: openerp.web.Widget.undelegateEvents - - This method is in charge of unbinding - :js:attr:`~openerp.web.Widget.events` from the DOM root when the - widget is destroyed or the DOM root is reset, in order to avoid - leaving "phantom" events. - - It should be overridden to un-set any event set in an override of - :js:func:`~openerp.web.Widget.delegateEvents`. - -.. note:: this behavior should be compatible with `Backbone's - delegateEvents`_, apart from not accepting any argument. - -Subclassing Widget ------------------- - -:js:class:`~openerp.base.Widget` is subclassed in the standard manner (via the -:js:func:`~openerp.base.Class.extend` method), and provides a number of -abstract properties and concrete methods (which you may or may not want to -override). Creating a subclass looks like this: - -.. code-block:: javascript - - var MyWidget = openerp.base.Widget.extend({ - // QWeb template to use when rendering the object - template: "MyQWebTemplate", - - init: function(parent) { - this._super(parent); - // insert code to execute before rendering, for object - // initialization - }, - start: function() { - this._super(); - // post-rendering initialization code, at this point - // ``this.$element`` has been initialized - this.$element.find(".my_button").click(/* an example of event binding * /); - - // if ``start`` is asynchronous, return a promise object so callers - // know when the object is done initializing - return this.rpc(/* … */) - } - }); - -The new class can then be used in the following manner: - -.. code-block:: javascript - - // Create the instance - var my_widget = new MyWidget(this); - // Render and insert into DOM - my_widget.appendTo(".some-div"); - -After these two lines have executed (and any promise returned by ``appendTo`` -has been resolved if needed), the widget is ready to be used. - -.. note:: the insertion methods will start the widget themselves, and will - return the result of :js:func:`~openerp.base.Widget.start()`. - - If for some reason you do not want to call these methods, you will - have to first call :js:func:`~openerp.base.Widget.render()` on the - widget, then insert it into your DOM and start it. - -If the widget is not needed anymore (because it's transient), simply terminate -it: - -.. code-block:: javascript - - my_widget.destroy(); - -will unbind all DOM events, remove the widget's content from the DOM and -destroy all widget data. - -.. [0] not all DOM events are compatible with events delegation - -.. _.appendTo(): - http://api.jquery.com/appendTo/ - -.. _.prependTo(): - http://api.jquery.com/prependTo/ - -.. _.insertAfter(): - http://api.jquery.com/insertAfter/ - -.. _.insertBefore(): - http://api.jquery.com/insertBefore/ - -.. _event delegation: - http://api.jquery.com/delegate/ - -.. _Backbone's setElement: - http://backbonejs.org/#View-setElement - -.. _Backbone's delegateEvents: - http://backbonejs.org/#View-delegateEvents - |
