summaryrefslogtreecommitdiff
path: root/doc/reference
diff options
context:
space:
mode:
authorXavier Morel <xmo@openerp.com>2014-11-03 17:31:54 +0100
committerXavier Morel <xmo@openerp.com>2014-11-03 17:39:24 +0100
commit03e9a38a1d1586139d61b753ecfcf7373e6b1f2c (patch)
tree6aad04672595efcd5e2fae66e169ca9d5f37ff5e /doc/reference
parentfb6892f8577087c1902c2a85dfc8badeac98aafa (diff)
[IMP] doc: remove guides section, move themes to tutorials and rest to reference
also pass PNGs through crusher, turns out dot produces pretty terrible PNGs
Diffstat (limited to 'doc/reference')
-rw-r--r--doc/reference/forms/header.pngbin0 -> 4099 bytes
-rw-r--r--doc/reference/forms/header2.pngbin0 -> 7059 bytes
-rw-r--r--doc/reference/forms/header3.pngbin0 -> 8661 bytes
-rw-r--r--doc/reference/forms/nosheet.pngbin0 -> 13630 bytes
-rw-r--r--doc/reference/forms/oppreadonly.pngbin0 -> 51033 bytes
-rw-r--r--doc/reference/forms/placeholder.pngbin0 -> 5422 bytes
-rw-r--r--doc/reference/forms/screenshot-00.pngbin0 -> 15903 bytes
-rw-r--r--doc/reference/forms/screenshot-01.pngbin0 -> 2936 bytes
-rw-r--r--doc/reference/forms/screenshot-02.pngbin0 -> 20109 bytes
-rw-r--r--doc/reference/forms/screenshot-03.pngbin0 -> 3805 bytes
-rw-r--r--doc/reference/forms/screenshot-04.pngbin0 -> 2876 bytes
-rw-r--r--doc/reference/forms/sheet.pngbin0 -> 25000 bytes
-rw-r--r--doc/reference/forms/status.pngbin0 -> 8995 bytes
-rw-r--r--doc/reference/forms/status1.pngbin0 -> 4373 bytes
-rw-r--r--doc/reference/forms/status2.pngbin0 -> 4419 bytes
-rw-r--r--doc/reference/forms/wizard-popup.pngbin0 -> 12028 bytes
-rw-r--r--doc/reference/images/runner.pngbin3963 -> 3791 bytes
-rw-r--r--doc/reference/images/runner2.pngbin6807 -> 6601 bytes
-rw-r--r--doc/reference/images/tests.pngbin65388 -> 63426 bytes
-rw-r--r--doc/reference/images/tests2.pngbin20114 -> 19446 bytes
-rw-r--r--doc/reference/images/tests3.pngbin20382 -> 19698 bytes
-rw-r--r--doc/reference/views.rst324
-rw-r--r--doc/reference/workflow/Makefile20
-rw-r--r--doc/reference/workflow/join.dot10
-rw-r--r--doc/reference/workflow/join.pngbin0 -> 2687 bytes
-rw-r--r--doc/reference/workflow/join.svg36
-rw-r--r--doc/reference/workflow/order_0.dot9
-rw-r--r--doc/reference/workflow/order_0.pngbin0 -> 12078 bytes
-rw-r--r--doc/reference/workflow/order_0.svg48
-rw-r--r--doc/reference/workflow/order_1.dot11
-rw-r--r--doc/reference/workflow/order_1.pngbin0 -> 20662 bytes
-rw-r--r--doc/reference/workflow/order_1.svg66
-rw-r--r--doc/reference/workflow/split.dot10
-rw-r--r--doc/reference/workflow/split.pngbin0 -> 2694 bytes
-rw-r--r--doc/reference/workflow/split.svg36
-rw-r--r--doc/reference/workflows.rst324
36 files changed, 889 insertions, 5 deletions
diff --git a/doc/reference/forms/header.png b/doc/reference/forms/header.png
new file mode 100644
index 00000000000..bf97b8cd05c
--- /dev/null
+++ b/doc/reference/forms/header.png
Binary files differ
diff --git a/doc/reference/forms/header2.png b/doc/reference/forms/header2.png
new file mode 100644
index 00000000000..0d0dbbf9eca
--- /dev/null
+++ b/doc/reference/forms/header2.png
Binary files differ
diff --git a/doc/reference/forms/header3.png b/doc/reference/forms/header3.png
new file mode 100644
index 00000000000..17e8fb9c2fd
--- /dev/null
+++ b/doc/reference/forms/header3.png
Binary files differ
diff --git a/doc/reference/forms/nosheet.png b/doc/reference/forms/nosheet.png
new file mode 100644
index 00000000000..99d915c98f0
--- /dev/null
+++ b/doc/reference/forms/nosheet.png
Binary files differ
diff --git a/doc/reference/forms/oppreadonly.png b/doc/reference/forms/oppreadonly.png
new file mode 100644
index 00000000000..447e7bbffa5
--- /dev/null
+++ b/doc/reference/forms/oppreadonly.png
Binary files differ
diff --git a/doc/reference/forms/placeholder.png b/doc/reference/forms/placeholder.png
new file mode 100644
index 00000000000..ab7d592f885
--- /dev/null
+++ b/doc/reference/forms/placeholder.png
Binary files differ
diff --git a/doc/reference/forms/screenshot-00.png b/doc/reference/forms/screenshot-00.png
new file mode 100644
index 00000000000..dca05afeb2a
--- /dev/null
+++ b/doc/reference/forms/screenshot-00.png
Binary files differ
diff --git a/doc/reference/forms/screenshot-01.png b/doc/reference/forms/screenshot-01.png
new file mode 100644
index 00000000000..464a23740a1
--- /dev/null
+++ b/doc/reference/forms/screenshot-01.png
Binary files differ
diff --git a/doc/reference/forms/screenshot-02.png b/doc/reference/forms/screenshot-02.png
new file mode 100644
index 00000000000..ea6ec7705e2
--- /dev/null
+++ b/doc/reference/forms/screenshot-02.png
Binary files differ
diff --git a/doc/reference/forms/screenshot-03.png b/doc/reference/forms/screenshot-03.png
new file mode 100644
index 00000000000..3a59801cff9
--- /dev/null
+++ b/doc/reference/forms/screenshot-03.png
Binary files differ
diff --git a/doc/reference/forms/screenshot-04.png b/doc/reference/forms/screenshot-04.png
new file mode 100644
index 00000000000..b0de67d5185
--- /dev/null
+++ b/doc/reference/forms/screenshot-04.png
Binary files differ
diff --git a/doc/reference/forms/sheet.png b/doc/reference/forms/sheet.png
new file mode 100644
index 00000000000..dee87a0e4b7
--- /dev/null
+++ b/doc/reference/forms/sheet.png
Binary files differ
diff --git a/doc/reference/forms/status.png b/doc/reference/forms/status.png
new file mode 100644
index 00000000000..4f4a0cb1c11
--- /dev/null
+++ b/doc/reference/forms/status.png
Binary files differ
diff --git a/doc/reference/forms/status1.png b/doc/reference/forms/status1.png
new file mode 100644
index 00000000000..7ccd80bb532
--- /dev/null
+++ b/doc/reference/forms/status1.png
Binary files differ
diff --git a/doc/reference/forms/status2.png b/doc/reference/forms/status2.png
new file mode 100644
index 00000000000..b0d01bd2e97
--- /dev/null
+++ b/doc/reference/forms/status2.png
Binary files differ
diff --git a/doc/reference/forms/wizard-popup.png b/doc/reference/forms/wizard-popup.png
new file mode 100644
index 00000000000..d36549f8687
--- /dev/null
+++ b/doc/reference/forms/wizard-popup.png
Binary files differ
diff --git a/doc/reference/images/runner.png b/doc/reference/images/runner.png
index bd48e9d2922..9991fce45a1 100644
--- a/doc/reference/images/runner.png
+++ b/doc/reference/images/runner.png
Binary files differ
diff --git a/doc/reference/images/runner2.png b/doc/reference/images/runner2.png
index 38ea2949cfc..ff8f5bfe722 100644
--- a/doc/reference/images/runner2.png
+++ b/doc/reference/images/runner2.png
Binary files differ
diff --git a/doc/reference/images/tests.png b/doc/reference/images/tests.png
index 84083d9e5ed..bc3ce8b43fc 100644
--- a/doc/reference/images/tests.png
+++ b/doc/reference/images/tests.png
Binary files differ
diff --git a/doc/reference/images/tests2.png b/doc/reference/images/tests2.png
index c8a6f8ae9ee..361fb7fb54b 100644
--- a/doc/reference/images/tests2.png
+++ b/doc/reference/images/tests2.png
Binary files differ
diff --git a/doc/reference/images/tests3.png b/doc/reference/images/tests3.png
index 247f70716af..d323360497d 100644
--- a/doc/reference/images/tests3.png
+++ b/doc/reference/images/tests3.png
Binary files differ
diff --git a/doc/reference/views.rst b/doc/reference/views.rst
index 3b678a37b3c..9eaab61b324 100644
--- a/doc/reference/views.rst
+++ b/doc/reference/views.rst
@@ -1,3 +1,5 @@
+.. highlight:: xml
+
.. _reference/views:
=====
@@ -6,8 +8,8 @@ Views
.. _reference/views/structure:
-Structure
-=========
+Common Structure
+================
View objects expose a number of fields, they are optional unless specified
otherwise)
@@ -421,6 +423,315 @@ system. Available semantic components are:
.. todo:: widgets?
+Business Views guidelines
+-------------------------
+
+.. sectionauthor:: Aline Preillon, Raphael Collet
+
+Business views are targeted at regular users, not advanced users. Examples
+are: Opportunities, Products, Partners, Tasks, Projects, etc.
+
+.. image:: forms/oppreadonly.png
+ :class: img-responsive
+
+In general, a business view is composed of
+
+1. a status bar on top (with technical or business flow),
+2. a sheet in the middle (the form itself),
+3. a bottom part with History and Comments.
+
+Technically, the new form views are structured as follows in XML::
+
+ <form>
+ <header> ... content of the status bar ... </header>
+ <sheet> ... content of the sheet ... </sheet>
+ <div class="oe_chatter"> ... content of the bottom part ... </div>
+ </form>
+
+The Status Bar
+''''''''''''''
+
+The purpose of the status bar is to show the status of the current record and
+the action buttons.
+
+.. image:: forms/status.png
+ :class: img-responsive
+
+The Buttons
+...........
+
+The order of buttons follows the business flow. For instance, in a sale order,
+the logical steps are:
+
+1. Send the quotation
+2. Confirm the quotation
+3. Create the final invoice
+4. Send the goods
+
+Highlighted buttons (in red by default) emphasize the logical next step, to
+help the user. It is usually the first active button. On the other hand,
+:guilabel:`cancel` buttons *must* remain grey (normal). For instance, in
+Invoice the button :guilabel:`Refund` must never be red.
+
+Technically, buttons are highlighted by adding the class "oe_highlight"::
+
+ <button class="oe_highlight" name="..." type="..." states="..."/>
+
+The Status
+..........
+
+Uses the ``statusbar`` widget, and shows the current state in red. States
+common to all flows (for instance, a sale order begins as a quotation, then we
+send it, then it becomes a full sale order, and finally it is done) should be
+visible at all times but exceptions or states depending on particular sub-flow
+should only be visible when current.
+
+.. image:: forms/status1.png
+ :class: img-responsive
+
+.. image:: forms/status2.png
+ :class: img-responsive
+
+The states are shown following the order used in the field (the list in a
+selection field, etc). States that are always visible are specified with the
+attribute ``statusbar_visible``.
+
+``statusbar_colors`` can be used to give a custom color to specific states.
+
+::
+
+ <field name="state" widget="statusbar"
+ statusbar_visible="draft,sent,progress,invoiced,done"
+ statusbar_colors="{'shipping_except':'red','waiting_date':'blue'}"/>
+
+The Sheet
+'''''''''
+
+All business views should look like a printed sheet:
+
+.. image:: forms/sheet.png
+ :class: img-responsive
+
+1. Elements inside a ``<form>`` or ``<page>`` do not define groups, elements
+ inside them are laid out according to normal HTML rules. They content can
+ be explicitly grouped using ``<group>`` or regular ``<div>`` elements.
+2. By default, the element ``<group>`` defines two columns inside, unless an
+ attribute ``col="n"`` is used. The columns have the same width (1/n th of
+ the group's width). Use a ``<group>`` element to produce a column of fields.
+3. To give a title to a section, add a ``string`` attribute to a ``<group>`` element::
+
+ <group string="Time-sensitive operations">
+
+ this replaces the former use of ``<separator string="XXX"/>``.
+4. The ``<field>`` element does not produce a label, except as direct children
+ of a ``<group>`` element\ [#backwards-compatibility]_. Use :samp:`<label
+ for="{field_name}>` to produce a label of a field.
+
+Sheet Headers
+.............
+
+Some sheets have headers with one or more fields, and the labels of those
+fields are only shown in edit mode.
+
+.. list-table::
+ :header-rows: 1
+
+ * - View mode
+ - Edit mode
+ * - .. image:: forms/header.png
+ :class: img-responsive
+ - .. image:: forms/header2.png
+ :class: img-responsive
+
+Use HTML text, ``<div>``, ``<h1>``, ``<h2>``… to produce nice headers, and
+``<label>`` with the class ``oe_edit_only`` to only display the field's label
+in edit mode. The class ``oe_inline`` will make fields inline (instead of
+blocks): content following the field will be displayed on the same line rather
+than on the line below it. The form above is produced by the following XML::
+
+ <label for="name" class="oe_edit_only"/>
+ <h1><field name="name"/></h1>
+
+ <label for="planned_revenue" class="oe_edit_only"/>
+ <h2>
+ <field name="planned_revenue" class="oe_inline"/>
+ <field name="company_currency" class="oe_inline oe_edit_only"/> at
+ <field name="probability" class="oe_inline"/> % success rate
+ </h2>
+
+Button Box
+..........
+
+Many relevant actions or links can be displayed in the form. For example, in
+Opportunity form, the actions "Schedule a Call" and "Schedule a Meeting" take
+an important place in the use of the CRM. Instead of placing them in the
+"More" menu, put them directly in the sheet as buttons (on the top right) to
+make them more visible and more easily accessible.
+
+.. image:: forms/header3.png
+ :class: img-responsive
+
+Technically, the buttons are placed inside a <div> to group them as a block on
+the right-hand side of the sheet.
+
+::
+
+ <div class="oe_button_box oe_right">
+ <button string="Schedule/Log Call" name="..." type="action"/>
+ <button string="Schedule Meeting" name="action_makeMeeting" type="object"/>
+ </div>
+
+Groups and Titles
+.................
+
+A column of fields is now produced with a ``<group>`` element, with an
+optional title.
+
+.. image:: forms/screenshot-03.png
+ :class: img-responsive
+
+::
+
+ <group string="Payment Options">
+ <field name="writeoff_amount"/>
+ <field name="payment_option"/>
+ </group>
+
+It is recommended to have two columns of fields on the form. For this, simply
+put the ``<group>`` elements that contain the fields inside a top-level
+``<group>`` element.
+
+To make :ref:`view extension <reference/views/inheritance>` simpler, it is
+recommended to put a ``name`` attribute on ``<group>`` elements, so new fields
+can easily be added at the right place.
+
+Special Case: Subtotals
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Some classes are defined to render subtotals like in invoice forms:
+
+.. image:: forms/screenshot-00.png
+ :class: img-responsive
+
+::
+
+ <group class="oe_subtotal_footer">
+ <field name="amount_untaxed"/>
+ <field name="amount_tax"/>
+ <field name="amount_total" class="oe_subtotal_footer_separator"/>
+ <field name="residual" style="margin-top: 10px"/>
+ </group>
+
+Placeholders and Inline Fields
+..............................
+
+Sometimes field labels make the form too complex. One can omit field labels,
+and instead put a placeholder inside the field. The placeholder text is
+visible only when the field is empty. The placeholder should tell what to
+place inside the field, it *must not* be an example as they are often confused
+with filled data.
+
+One can also group fields together by rendering them "inline" inside an
+explicit block element like `<div>``. This allows grouping semantically
+related fields as if they were a single (composite) fields.
+
+The following example, taken from the *Leads* form, shows both placeholders and
+inline fields (zip and city).
+
+.. list-table::
+ :header-rows: 1
+
+ * - Edit mode
+ - View mode
+ * - .. image:: forms/placeholder.png
+ :class: img-responsive
+ - .. image:: forms/screenshot-01.png
+ :class: img-responsive
+
+::
+
+ <group>
+ <label for="street" string="Address"/>
+ <div>
+ <field name="street" placeholder="Street..."/>
+ <field name="street2"/>
+ <div>
+ <field name="zip" class="oe_inline" placeholder="ZIP"/>
+ <field name="city" class="oe_inline" placeholder="City"/>
+ </div>
+ <field name="state_id" placeholder="State"/>
+ <field name="country_id" placeholder="Country"/>
+ </div>
+ </group>
+
+Images
+......
+
+Images, like avatars, should be displayed on the right of the sheet. The
+product form looks like:
+
+.. image:: forms/screenshot-02.png
+ :class: img-responsive
+
+The form above contains a <sheet> element that starts with:
+
+::
+
+ <field name="product_image" widget="image" class="oe_avatar oe_right"/>
+
+Tags
+....
+
+Most :class:`~openerp.fields.Many2many` fields, like categories, are better
+rendered as a list of tags. Use the widget ``many2many_tags`` for this:
+
+.. image:: forms/screenshot-04.png
+ :class: img-responsive
+
+::
+
+ <field name="category_id" widget="many2many_tags"/>
+
+Configuration forms guidelines
+------------------------------
+
+Examples of configuration forms: Stages, Leave Type, etc. This concerns all
+menu items under Configuration of each application (like Sales/Configuration).
+
+.. image:: forms/nosheet.png
+ :class: img-responsive
+
+1. no header (because no state, no workflow, no button)
+2. no sheet
+
+Dialog forms guidelines
+-----------------------
+
+Example: "Schedule a Call" from an opportunity.
+
+.. image:: forms/wizard-popup.png
+ :class: img-responsive
+
+1. avoid separators (the title is already in the popup title bar, so another
+ separator is not relevant)
+2. avoid cancel buttons (user generally close the popup window to get the same
+ effect)
+3. action buttons must be highlighted (red)
+4. when there is a text area, use a placeholder instead of a label or a
+ separator
+5. like in regular form views, put buttons in the <header> element
+
+Configuration Wizards guidelines
+--------------------------------
+
+Example: Settings / Configuration / Sales.
+
+1. always in line (no popup)
+2. no sheet
+3. keep the cancel button (users cannot close the window)
+4. the button "Apply" must be red
+
+
.. _reference/views/graph:
Graphs
@@ -846,7 +1157,7 @@ Possible children elements of the search view are:
as inclusively composited: they will be composed with ``OR`` rather
than the usual ``AND``, e.g.
- .. code-block:: xml
+ ::
<filter domain="[('state', '=', 'draft')]"/>
<filter domain="[('state', '=', 'done')]"/>
@@ -854,7 +1165,7 @@ Possible children elements of the search view are:
if both filters are selected, will select the records whose ``state``
is ``draft`` or ``done``, but
- .. code-block:: xml
+ ::
<filter domain="[('state', '=', 'draft')]"/>
<separator/>
@@ -877,7 +1188,9 @@ Search defaults
Search fields and filters can be configured through the action's ``context``
using :samp:`search_default_{name}` keys. For fields, the value should be the
value to set in the field, for filters it's a boolean value. For instance,
-assuming ``foo`` is a field and ``bar`` is a filter an action context of::
+assuming ``foo`` is a field and ``bar`` is a filter an action context of:
+
+.. code-block:: python
{
'search_default_foo': 'acro',
@@ -902,6 +1215,7 @@ template's name *must* match the view's complete (including module name)
:ref:`reference/data/template` should be used as a shortcut to define QWeb
views.
+.. [#backwards-compatibility] for backwards compatibility reasons
.. [#hasclass] an extension function is added for simpler matching in QWeb
views: ``hasclass(*classes)`` matches if the context node has
all the specified classes
diff --git a/doc/reference/workflow/Makefile b/doc/reference/workflow/Makefile
new file mode 100644
index 00000000000..07bbb67dd55
--- /dev/null
+++ b/doc/reference/workflow/Makefile
@@ -0,0 +1,20 @@
+DOTFILES:=$(wildcard *.dot)
+SVGFILES:=$(patsubst %.dot,%.svg,$(DOTFILES))
+PNGFILES:=$(patsubst %.dot,%.png,$(DOTFILES))
+
+# try to disable implicit rules
+.SUFFIXES:
+
+.PHONY: all clean
+
+all: $(SVGFILES) $(PNGFILES)
+
+# must -f to ignore errors when running clean multiple times in a row
+clean:
+ rm -f *.png *.svg
+
+%.svg: %.dot
+ dot -Tsvg $< > $@
+
+%.png: %.dot
+ dot -Tpng $< > $@
diff --git a/doc/reference/workflow/join.dot b/doc/reference/workflow/join.dot
new file mode 100644
index 00000000000..e413a8a8ebc
--- /dev/null
+++ b/doc/reference/workflow/join.dot
@@ -0,0 +1,10 @@
+digraph join {
+ // dummy sources as support for edges, make invisible and height 0
+ a [style=invis height=0 fontsize=0]
+ b [style=invis height=0 fontsize=0]
+ c [style=invis height=0 fontsize=0]
+
+ a -> Activity
+ b -> Activity
+ c -> Activity
+}
diff --git a/doc/reference/workflow/join.png b/doc/reference/workflow/join.png
new file mode 100644
index 00000000000..cdc0bafb2ca
--- /dev/null
+++ b/doc/reference/workflow/join.png
Binary files differ
diff --git a/doc/reference/workflow/join.svg b/doc/reference/workflow/join.svg
new file mode 100644
index 00000000000..1462281977f
--- /dev/null
+++ b/doc/reference/workflow/join.svg
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Generated by graphviz version 2.38.0 (20140413.2041)
+ -->
+<!-- Title: join Pages: 1 -->
+<svg width="206pt" height="93pt"
+ viewBox="0.00 0.00 206.00 92.73" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 88.7279)">
+<title>join</title>
+<polygon fill="white" stroke="none" points="-4,4 -4,-88.7279 202,-88.7279 202,4 -4,4"/>
+<!-- a -->
+<!-- Activity -->
+<g id="node4" class="node"><title>Activity</title>
+<ellipse fill="none" stroke="black" cx="99" cy="-18" rx="40.0939" ry="18"/>
+<text text-anchor="middle" x="99" y="-14.3" font-family="Times,serif" font-size="14.00">Activity</text>
+</g>
+<!-- a&#45;&gt;Activity -->
+<g id="edge1" class="edge"><title>a&#45;&gt;Activity</title>
+<path fill="none" stroke="black" d="M33.6445,-71.9778C42.4332,-64.8537 58.4442,-51.875 72.4186,-40.5472"/>
+<polygon fill="black" stroke="black" points="74.7768,-43.1411 80.3411,-34.1251 70.3688,-37.7033 74.7768,-43.1411"/>
+</g>
+<!-- b -->
+<!-- b&#45;&gt;Activity -->
+<g id="edge2" class="edge"><title>b&#45;&gt;Activity</title>
+<path fill="none" stroke="black" d="M99,-71.9778C99,-66.0508 99,-56.0715 99,-46.3619"/>
+<polygon fill="black" stroke="black" points="102.5,-46.1364 99,-36.1364 95.5001,-46.1365 102.5,-46.1364"/>
+</g>
+<!-- c -->
+<!-- c&#45;&gt;Activity -->
+<g id="edge3" class="edge"><title>c&#45;&gt;Activity</title>
+<path fill="none" stroke="black" d="M164.355,-71.9778C155.567,-64.8537 139.556,-51.875 125.581,-40.5472"/>
+<polygon fill="black" stroke="black" points="127.631,-37.7033 117.659,-34.1251 123.223,-43.1411 127.631,-37.7033"/>
+</g>
+</g>
+</svg>
diff --git a/doc/reference/workflow/order_0.dot b/doc/reference/workflow/order_0.dot
new file mode 100644
index 00000000000..3932040e914
--- /dev/null
+++ b/doc/reference/workflow/order_0.dot
@@ -0,0 +1,9 @@
+digraph order {
+ Draft [style=filled fillcolor="#73fa79"]
+ Closed [style=filled fillcolor="#98c7df"]
+ Canceled [style=filled fillcolor="#98c7df"]
+
+ Draft -> Confirmed
+ Confirmed -> Closed
+ Confirmed -> Canceled
+}
diff --git a/doc/reference/workflow/order_0.png b/doc/reference/workflow/order_0.png
new file mode 100644
index 00000000000..7d16f96dcbc
--- /dev/null
+++ b/doc/reference/workflow/order_0.png
Binary files differ
diff --git a/doc/reference/workflow/order_0.svg b/doc/reference/workflow/order_0.svg
new file mode 100644
index 00000000000..54a5c050238
--- /dev/null
+++ b/doc/reference/workflow/order_0.svg
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Generated by graphviz version 2.38.0 (20140413.2041)
+ -->
+<!-- Title: order Pages: 1 -->
+<svg width="188pt" height="188pt"
+ viewBox="0.00 0.00 188.24 188.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 184)">
+<title>order</title>
+<polygon fill="white" stroke="none" points="-4,4 -4,-184 184.243,-184 184.243,4 -4,4"/>
+<!-- Draft -->
+<g id="node1" class="node"><title>Draft</title>
+<ellipse fill="#73fa79" stroke="black" cx="85.3968" cy="-162" rx="30.5947" ry="18"/>
+<text text-anchor="middle" x="85.3968" y="-158.3" font-family="Times,serif" font-size="14.00">Draft</text>
+</g>
+<!-- Confirmed -->
+<g id="node4" class="node"><title>Confirmed</title>
+<ellipse fill="none" stroke="black" cx="85.3968" cy="-90" rx="51.9908" ry="18"/>
+<text text-anchor="middle" x="85.3968" y="-86.3" font-family="Times,serif" font-size="14.00">Confirmed</text>
+</g>
+<!-- Draft&#45;&gt;Confirmed -->
+<g id="edge1" class="edge"><title>Draft&#45;&gt;Confirmed</title>
+<path fill="none" stroke="black" d="M85.3968,-143.697C85.3968,-135.983 85.3968,-126.712 85.3968,-118.112"/>
+<polygon fill="black" stroke="black" points="88.8969,-118.104 85.3968,-108.104 81.8969,-118.104 88.8969,-118.104"/>
+</g>
+<!-- Closed -->
+<g id="node2" class="node"><title>Closed</title>
+<ellipse fill="#98c7df" stroke="black" cx="36.3968" cy="-18" rx="36.2938" ry="18"/>
+<text text-anchor="middle" x="36.3968" y="-14.3" font-family="Times,serif" font-size="14.00">Closed</text>
+</g>
+<!-- Canceled -->
+<g id="node3" class="node"><title>Canceled</title>
+<ellipse fill="#98c7df" stroke="black" cx="135.397" cy="-18" rx="44.6926" ry="18"/>
+<text text-anchor="middle" x="135.397" y="-14.3" font-family="Times,serif" font-size="14.00">Canceled</text>
+</g>
+<!-- Confirmed&#45;&gt;Closed -->
+<g id="edge2" class="edge"><title>Confirmed&#45;&gt;Closed</title>
+<path fill="none" stroke="black" d="M73.7845,-72.411C67.8042,-63.8677 60.3917,-53.2785 53.7479,-43.7874"/>
+<polygon fill="black" stroke="black" points="56.5277,-41.6552 47.9257,-35.4699 50.7931,-45.6694 56.5277,-41.6552"/>
+</g>
+<!-- Confirmed&#45;&gt;Canceled -->
+<g id="edge3" class="edge"><title>Confirmed&#45;&gt;Canceled</title>
+<path fill="none" stroke="black" d="M97.2461,-72.411C103.348,-63.8677 110.912,-53.2785 117.692,-43.7874"/>
+<polygon fill="black" stroke="black" points="120.668,-45.6416 123.633,-35.4699 114.972,-41.573 120.668,-45.6416"/>
+</g>
+</g>
+</svg>
diff --git a/doc/reference/workflow/order_1.dot b/doc/reference/workflow/order_1.dot
new file mode 100644
index 00000000000..cc204343172
--- /dev/null
+++ b/doc/reference/workflow/order_1.dot
@@ -0,0 +1,11 @@
+digraph order {
+ Draft [style=filled fillcolor="#73fa79"]
+ Closed [style=filled fillcolor="#98c7df"]
+ Canceled [style=filled fillcolor="#98c7df"]
+
+ Draft -> Confirmed [label="discount <= 15%"]
+ Draft -> Validation [label="discount > 15%"]
+ Validation -> Confirmed [label="Accept"]
+ Confirmed -> Closed
+ Confirmed -> Canceled
+}
diff --git a/doc/reference/workflow/order_1.png b/doc/reference/workflow/order_1.png
new file mode 100644
index 00000000000..0c38acd0413
--- /dev/null
+++ b/doc/reference/workflow/order_1.png
Binary files differ
diff --git a/doc/reference/workflow/order_1.svg b/doc/reference/workflow/order_1.svg
new file mode 100644
index 00000000000..08f099e34c9
--- /dev/null
+++ b/doc/reference/workflow/order_1.svg
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Generated by graphviz version 2.38.0 (20140413.2041)
+ -->
+<!-- Title: order Pages: 1 -->
+<svg width="260pt" height="291pt"
+ viewBox="0.00 0.00 259.79 291.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 287)">
+<title>order</title>
+<polygon fill="white" stroke="none" points="-4,4 -4,-287 255.792,-287 255.792,4 -4,4"/>
+<!-- Draft -->
+<g id="node1" class="node"><title>Draft</title>
+<ellipse fill="#73fa79" stroke="black" cx="85.3968" cy="-265" rx="30.5947" ry="18"/>
+<text text-anchor="middle" x="85.3968" y="-261.3" font-family="Times,serif" font-size="14.00">Draft</text>
+</g>
+<!-- Confirmed -->
+<g id="node4" class="node"><title>Confirmed</title>
+<ellipse fill="none" stroke="black" cx="85.3968" cy="-91" rx="51.9908" ry="18"/>
+<text text-anchor="middle" x="85.3968" y="-87.3" font-family="Times,serif" font-size="14.00">Confirmed</text>
+</g>
+<!-- Draft&#45;&gt;Confirmed -->
+<g id="edge1" class="edge"><title>Draft&#45;&gt;Confirmed</title>
+<path fill="none" stroke="black" d="M72.5816,-248.399C62.7132,-235.312 49.8641,-215.656 44.3968,-196 40.1092,-180.585 40.1092,-175.415 44.3968,-160 48.7071,-144.503 57.6054,-129.007 66.0142,-116.73"/>
+<polygon fill="black" stroke="black" points="68.9995,-118.572 71.9779,-108.405 63.3089,-114.496 68.9995,-118.572"/>
+<text text-anchor="middle" x="94.3968" y="-174.3" font-family="Times,serif" font-size="14.00">discount &lt;= 15%</text>
+</g>
+<!-- Validation -->
+<g id="node5" class="node"><title>Validation</title>
+<ellipse fill="none" stroke="black" cx="202.397" cy="-178" rx="49.2915" ry="18"/>
+<text text-anchor="middle" x="202.397" y="-174.3" font-family="Times,serif" font-size="14.00">Validation</text>
+</g>
+<!-- Draft&#45;&gt;Validation -->
+<g id="edge2" class="edge"><title>Draft&#45;&gt;Validation</title>
+<path fill="none" stroke="black" d="M103.936,-250.531C122.48,-237.059 151.286,-216.131 172.959,-200.386"/>
+<polygon fill="black" stroke="black" points="175.139,-203.129 181.172,-194.42 171.024,-197.466 175.139,-203.129"/>
+<text text-anchor="middle" x="195.897" y="-217.8" font-family="Times,serif" font-size="14.00">discount &gt; 15%</text>
+</g>
+<!-- Closed -->
+<g id="node2" class="node"><title>Closed</title>
+<ellipse fill="#98c7df" stroke="black" cx="36.3968" cy="-18" rx="36.2938" ry="18"/>
+<text text-anchor="middle" x="36.3968" y="-14.3" font-family="Times,serif" font-size="14.00">Closed</text>
+</g>
+<!-- Canceled -->
+<g id="node3" class="node"><title>Canceled</title>
+<ellipse fill="#98c7df" stroke="black" cx="135.397" cy="-18" rx="44.6926" ry="18"/>
+<text text-anchor="middle" x="135.397" y="-14.3" font-family="Times,serif" font-size="14.00">Canceled</text>
+</g>
+<!-- Confirmed&#45;&gt;Closed -->
+<g id="edge4" class="edge"><title>Confirmed&#45;&gt;Closed</title>
+<path fill="none" stroke="black" d="M73.7845,-73.174C67.7175,-64.3831 60.1766,-53.4564 53.4596,-43.7236"/>
+<polygon fill="black" stroke="black" points="56.1491,-41.4588 47.5884,-35.2165 50.3879,-45.4348 56.1491,-41.4588"/>
+</g>
+<!-- Confirmed&#45;&gt;Canceled -->
+<g id="edge5" class="edge"><title>Confirmed&#45;&gt;Canceled</title>
+<path fill="none" stroke="black" d="M97.2461,-73.174C103.348,-64.5087 110.912,-53.7682 117.692,-44.1415"/>
+<polygon fill="black" stroke="black" points="120.736,-45.8965 123.633,-35.7052 115.013,-41.8661 120.736,-45.8965"/>
+</g>
+<!-- Validation&#45;&gt;Confirmed -->
+<g id="edge3" class="edge"><title>Validation&#45;&gt;Confirmed</title>
+<path fill="none" stroke="black" d="M181.209,-161.607C162.688,-148.152 135.604,-128.475 114.953,-113.472"/>
+<polygon fill="black" stroke="black" points="116.97,-110.612 106.822,-107.566 112.856,-116.275 116.97,-110.612"/>
+<text text-anchor="middle" x="170.397" y="-130.8" font-family="Times,serif" font-size="14.00">Accept</text>
+</g>
+</g>
+</svg>
diff --git a/doc/reference/workflow/split.dot b/doc/reference/workflow/split.dot
new file mode 100644
index 00000000000..b0f3831854a
--- /dev/null
+++ b/doc/reference/workflow/split.dot
@@ -0,0 +1,10 @@
+digraph split {
+ // dummy destinations as support for edges, make invisible and height 0
+ a [style=invis height=0 fontsize=0]
+ b [style=invis height=0 fontsize=0]
+ c [style=invis height=0 fontsize=0]
+
+ Activity -> a
+ Activity -> b
+ Activity -> c
+}
diff --git a/doc/reference/workflow/split.png b/doc/reference/workflow/split.png
new file mode 100644
index 00000000000..d9d512cffa3
--- /dev/null
+++ b/doc/reference/workflow/split.png
Binary files differ
diff --git a/doc/reference/workflow/split.svg b/doc/reference/workflow/split.svg
new file mode 100644
index 00000000000..139874fdc75
--- /dev/null
+++ b/doc/reference/workflow/split.svg
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Generated by graphviz version 2.38.0 (20140413.2041)
+ -->
+<!-- Title: split Pages: 1 -->
+<svg width="206pt" height="93pt"
+ viewBox="0.00 0.00 206.00 92.73" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 88.7279)">
+<title>split</title>
+<polygon fill="white" stroke="none" points="-4,4 -4,-88.7279 202,-88.7279 202,4 -4,4"/>
+<!-- a -->
+<!-- b -->
+<!-- c -->
+<!-- Activity -->
+<g id="node4" class="node"><title>Activity</title>
+<ellipse fill="none" stroke="black" cx="99" cy="-66.7279" rx="40.0939" ry="18"/>
+<text text-anchor="middle" x="99" y="-63.0279" font-family="Times,serif" font-size="14.00">Activity</text>
+</g>
+<!-- Activity&#45;&gt;a -->
+<g id="edge1" class="edge"><title>Activity&#45;&gt;a</title>
+<path fill="none" stroke="black" d="M80.4582,-50.6978C68.3594,-40.8903 52.7894,-28.2691 41.577,-19.1802"/>
+<polygon fill="black" stroke="black" points="43.641,-16.3478 33.6687,-12.7696 39.233,-21.7857 43.641,-16.3478"/>
+</g>
+<!-- Activity&#45;&gt;b -->
+<g id="edge2" class="edge"><title>Activity&#45;&gt;b</title>
+<path fill="none" stroke="black" d="M99,-48.5325C99,-40.494 99,-30.9869 99,-23.1351"/>
+<polygon fill="black" stroke="black" points="102.5,-22.8941 99,-12.8941 95.5001,-22.8942 102.5,-22.8941"/>
+</g>
+<!-- Activity&#45;&gt;c -->
+<g id="edge3" class="edge"><title>Activity&#45;&gt;c</title>
+<path fill="none" stroke="black" d="M117.542,-50.6978C129.641,-40.8903 145.211,-28.2691 156.423,-19.1802"/>
+<polygon fill="black" stroke="black" points="158.767,-21.7857 164.331,-12.7696 154.359,-16.3478 158.767,-21.7857"/>
+</g>
+</g>
+</svg>
diff --git a/doc/reference/workflows.rst b/doc/reference/workflows.rst
new file mode 100644
index 00000000000..210213e5f55
--- /dev/null
+++ b/doc/reference/workflows.rst
@@ -0,0 +1,324 @@
+.. _reference/workflows:
+
+Workflows
+=========
+
+In Odoo, a workflow is a technical artefact to manage a set of "things to
+do" associated to the records of a model. The workflow provides a higher-level
+way to organize tasks to perform with or on a record.
+
+More specifically, a workflow is a directed graph where the nodes are called
+"activities" and the arcs are called "transitions".
+
+- Activities define work that should be done within the Odoo server, such
+ as changing the state of some records, or sending emails.
+- Transitions control how the workflow progresses from activity to activity.
+
+In the definition of a workflow, one can attach conditions, signals, and
+triggers to transitions, so that the behavior of the workflow depends on user
+actions (such as clicking on a button), changes to records, or arbitrary
+Python code.
+
+All in all, Odoo's workflow system provides:
+
+* a description of the evolution of a record (document) over time
+* automatic actions based on various and flexible conditions
+* management of company roles and validation steps
+* management of interactions between objects
+* a visual representation of document flows through their lifecycle
+
+For instance, a basic order could have the following flow:
+
+.. sphinx.ext.graphviz would be nice, but it requires ``dot`` on any machine
+.. where the doc is compiled... otoh this is a pain in the ass because you
+.. need 2 compilation steps (dot -> image and rst -> html) every time
+
+.. image:: workflow/order_0.*
+ :align: center
+
+Orders start in the *Draft* state, can be *Confirmed* by a user, and then
+either shipped (*Closed*) or *Canceled*.
+
+A company using Odoo may want to add discount support to orders, where sales
+staff has discretionary discounting powers up to 15%, but manager validation
+is required for discounts beyond 15%. The workflow can be altered online to
+add the relevant steps without editing Python or XML files:
+
+.. image:: workflow/order_1.*
+ :align: center
+
+Because Activities can perform arbitrary actions, the *Validation* can
+automatically send a validation request to the relevant employee.
+
+.. note:: the order view needs to be modified to add an *Accept Discount*
+ button for managers
+
+Basics
+------
+
+Defining a workflow with data files is straightforward: a record "workflow" is
+given together with records for the activities and the transitions. For
+instance, here is a simple sequence of two activities defined in XML
+
+.. code-block:: xml
+
+ <record id="test_workflow" model="workflow">
+ <field name="name">test.workflow</field>
+ <field name="osv">test.workflow.model</field>
+ <field name="on_create">True</field>
+ </record>
+
+ <record id="activity_a" model="workflow.activity">
+ <field name="wkf_id" ref="test_workflow"/>
+ <field name="flow_start">True</field>
+ <field name="name">a</field>
+ <field name="kind">function</field>
+ <field name="action">print_a()</field>
+ </record>
+ <record id="activity_b" model="workflow.activity">
+ <field name="wkf_id" ref="test_workflow"/>
+ <field name="flow_stop">True</field>
+ <field name="name">b</field>
+ <field name="kind">function</field>
+ <field name="action">print_b()</field>
+ </record>
+
+ <record id="trans_a_b" model="workflow.transition">
+ <field name="act_from" ref="activity_a"/>
+ <field name="act_to" ref="activity_b"/>
+ </record>
+
+A worfklow is always defined with respect to a particular model (the model is
+given by the attribute ``osv`` on the model ``workflow``). Methods specified
+in the activities or transitions will be called on that model.
+
+In the example code above, a workflow called "test_workflow" is created. It is
+made up of two activies, named "a" and "b", and one transition, going from "a"
+to "b".
+
+The first activity has its attribute ``flow_start`` set to ``True`` so that
+Odoo knows where to start the workflow traversal after it is instanciated.
+Because ``on_create`` is set to True on the workflow record, the workflow is
+instanciated for each newly created record. (Otherwise, the workflow should be
+instanciated by other means, such as from some module Python code.)
+
+When the workflow is instanciated, it begins with activity "a". That activity
+is of kind ``function``, which means that the action ``print_a()`` is a method
+call on the model ``test.workflow`` (the usual ``cr, uid, ids, context``
+arguments are passed for you).
+
+The transition between "a" and "b" does not specify any condition. This means
+that the workflow instance immediately goes from "a" to "b" after "a" has been
+processed, and thus also processes activity "b".
+
+Activities
+----------
+
+While the transitions can be seen as the control structures of the workflows,
+activities are the places where everything happens, from changing record
+states to sending email.
+
+Different kinds of activities exist: ``Dummy``, ``Function``, ``Subflow``, and
+``Stop all``, each doing different things when the activity is processed. In
+addition to their kind, activies have other properties, detailed in the next
+sections.
+
+Flow start and flow stop
+''''''''''''''''''''''''
+
+The attribute ``flow_start`` is a boolean value specifying whether the activity
+is processed when the workflow is instanciated. Multiple activities can have
+their attribute ``flow_start`` set to ``True``. When instanciating a workflow
+for a record, Odoo simply processes all of them, and evaluate all their
+outgoing transitions afterwards.
+
+The attribute ``flow_stop`` is a boolean value specifying whether the activity
+stops the workflow instance. A workflow instance is considered completed when
+all its activities with the attribute ``flow_stop`` set to ``True`` are
+completed.
+
+It is important for Odoo to know when a workflow instance is completed. A
+workflow can have an activity that is actually another workflow (called a
+subflow); that activity is completed when the subflow is completed.
+
+Subflow
+'''''''
+
+An activity can embed a complete workflow, called a subflow (the embedding
+workflow is called the parent workflow). The workflow to instanciate is
+specified by attribute ``subflow_id``.
+
+.. note:: In the GUI, that attribute can not be set unless the kind of the
+ activity is ``Subflow``.
+
+The activity is considered completed (and its outgoing transitions ready to be
+evaluated) when the subflow is completed (see attribute ``flow_stop`` above).
+
+Sending a signal from a subflow
+'''''''''''''''''''''''''''''''
+
+When a workflow is embedded in an activity (as a subflow) of a workflow, the
+sublow can send a signal from its own activities to the parent workflow by
+giving a signal name in the attribute ``signal_send``. Odoo processes those
+activities by sending the value of ``signal_send`` prefixed by "subflow." to
+the parent workflow instance.
+
+In other words, it is possible to react and get transitions in the parent
+workflow as activities are executed in the sublow.
+
+Server actions
+''''''''''''''
+
+An activity can run a "Server Action" by specifying its ID in the attribute
+``action_id``.
+
+Python action
+'''''''''''''
+
+An activity can execute some Python code, given by the attribute ``action``.
+The evaluation environment is the same as the one explained in the section
+`Conditions`_.
+
+Split mode
+''''''''''
+
+After an activity has been processed, Odoo evaluates its transition to reach
+the next activity in the flow.
+
+However if an activity has more than one transition, Odoo must decide which
+activity or activities to follow.
+
+.. image:: workflow/split.*
+ :align: center
+
+This choice is controlled by the ``split_mode`` attribute:
+
+``XOR`` (default)
+ By default, Odoo will use the first transition (in ``sequence`` order)
+ whose condition is satisfied. All other transitions are ignored.
+``OR``
+ In ``OR`` mode, all transitions with a satisfied condition are traversed
+ simultanously. Transitions not yet valid will be ignored, even if they
+ become valid later.
+``AND``
+ In ``AND`` mode, Odoo will wait until *all* transitions are satisfied, and
+ will traverse all of them (much like the ``OR`` mode).
+
+Both ``OR`` and ``AND`` mode will lead to activities being active in the same
+workflow.
+
+Join mode
+'''''''''
+
+Just like outgoing transition conditions can be combined together to decide
+whether they can be traversed or not, incoming transitions can be combined
+together to decide if and when an activity may be processed.
+
+.. image:: workflow/join.*
+ :align: center
+
+The ``join_mode`` attribute controls that behavior:
+
+``XOR`` (default)
+ Any incoming transition enables the activity and starts its processing.
+``AND``
+ The activity is enabled and processed only once *all* incoming transitions
+ have been traversed.
+
+Kinds
+'''''
+
+An activity's kind defines the type of work an activity can perform.
+
+Dummy (``dummy``, default)
+ Do nothing at all, or call a server action. Often used as dispatch or
+ gather "hubs" for transitions.
+Function (``function``)
+ Run some python code, execute a server action.
+Stop all (``stopall``)
+ Completely stops the workflow instance and marks it as completed.
+Subflow (``subflow``)
+ Starts executing an other workflow, once that workflow is completed the
+ activity is done processing.
+
+ By default, the subflow is instanciated for the same record as the parent
+ workflow. It is possible to change that behavior by providing Python code
+ that returns a record ID (of the same data model as the subflow). The
+ embedded subflow instance is then the one of the given record.
+
+
+Transitions
+-----------
+
+Transitions provide the control structures to orchestrate a workflow. When an
+activity is completed, the workflow engine tries to get across transitions
+departing from the completed activity, towards the next activities. In their
+simplest form (as in the example above), they link activities sequentially:
+activities are processed as soon as the activities preceding them are
+completed.
+
+Instead of running all activities in one fell swoop, it is also possible to
+wait on transitions, going through them only when some criteria are met. The
+criteria are the conditions, the signals, and the triggers. They are detailed
+in the following sections.
+
+Conditions
+''''''''''
+
+When an activity has been completed, its outgoing transitions are inspected to
+determine whether it is possible for the workflow instance to proceed through
+them and reach the next activities. When only a condition is defined (i.e., no
+signal or trigger is defined), the condition is evaluated by Odoo, and if
+it evaluates to ``True``, the worklfow instance progresses through the
+transition. If the condition is not met, it will be reevaluated every time
+the associated record is modified, or by an explicit method call to do it.
+
+By default, the attribute ``condition`` (i.e., the expression to be evaluated)
+is just "True", which trivially evaluates to ``True``. Note that the condition
+may be several lines long; in that case, the value of the last one determines
+whether the transition can be taken.
+
+In the condition evaluation environment, several symbols are conveniently
+defined (in addition to the Odoo ``safe_eval`` environment):
+
+- all the model column names, and
+- all the browse record's attributes.
+
+Signals
+'''''''
+
+In addition to a condition, a transition can specify a signal name. When such
+a signal name is present, the transition is not taken directly, even if the
+condition evaluates to ``True``. Instead the transition blocks, waiting to be
+woken up.
+
+In order to wake up a transition with a defined signal name, the signal must
+be sent to the workflow instance. A common way to send a signal is to use a
+button in the user interface, using the element ``<button/>`` with the signal
+name as the attribute ``name`` of the button. Once the button is clicked, the
+signal is sent to the workflow instance of the current record.
+
+.. note:: The condition is still evaluated when the signal is sent to the
+ workflow instance.
+
+Triggers
+''''''''
+
+With conditions that evaluate to ``False``, transitions are not taken (and
+thus the activity it leads to is not processed immediately). Still, the
+workflow instance can get new chances to progress across that transition by
+providing so-called triggers. The idea is that when the condition is not
+satisfied, triggers are recorded in database. Later, it is possible to wake up
+specifically the workflow instances that installed those triggers, offering
+them to reevaluate their transition conditions. This mechanism makes it
+cheaper to wake up workflow instances by targetting just a few of them (those
+that have installed the triggers) instead of all of them.
+
+Triggers are recorded in database as record IDs (together with the model name)
+and refer to the workflow instance waiting for those records. The transition
+definition provides a model name (attribute ``trigger_model``) and a Python
+expression (attribute ``trigger_expression``) that evaluates to a list of
+record IDs in the given model. Any of those records can wake up the workflow
+instance they are associated with.
+
+.. note:: triggers are not re-installed whenever the transition is re-tried.