[sardana] 04/06: New upstream version 2.1.0

Frédéric-Emmanuel Picca picca at moszumanska.debian.org
Fri Sep 30 08:55:49 UTC 2016


This is an automated email from the git hooks/post-receive script.

picca pushed a commit to branch master
in repository sardana.

commit 523f1ff46fbbe9b666f13d0d72da5930096651bb
Author: Picca Frédéric-Emmanuel <picca at debian.org>
Date:   Tue Sep 13 19:56:49 2016 +0200

    New upstream version 2.1.0
---
 PKG-INFO                                           |   4 +-
 doc/man/MacroServer.1                              |   4 +-
 doc/man/Pool.1                                     |   4 +-
 doc/man/Sardana.1                                  |   4 +-
 doc/man/diffractometeralignment.1                  |   4 +-
 doc/man/hklscan.1                                  |   4 +-
 doc/man/macroexecutor.1                            |   4 +-
 doc/man/sequencer.1                                |   4 +-
 doc/man/spock.1                                    |   4 +-
 doc/man/ubmatrix.1                                 |   4 +-
 doc/source/_static/macros/favouriteeditor01.png    | Bin 0 -> 12205 bytes
 doc/source/_static/macros/macroexecutor01.odg      | Bin 0 -> 42236 bytes
 doc/source/_static/macros/macroexecutor01.png      | Bin 0 -> 1111166 bytes
 doc/source/_static/macros/macroexecutor01_raw.png  | Bin 0 -> 21869 bytes
 .../_static/macros/macroparameterseditor01.png     | Bin 0 -> 8124 bytes
 .../_static/macros/macroparameterseditor02.png     | Bin 0 -> 7635 bytes
 .../_static/macros/macroparameterseditor03.odg     | Bin 0 -> 20268 bytes
 .../_static/macros/macroparameterseditor03.png     | Bin 0 -> 604944 bytes
 .../_static/macros/macroparameterseditor03_raw.png | Bin 0 -> 7773 bytes
 .../_static/macros/macroparameterseditor04.odg     | Bin 0 -> 23179 bytes
 .../_static/macros/macroparameterseditor04.png     | Bin 0 -> 604944 bytes
 .../_static/macros/macroparameterseditor04_raw.png | Bin 0 -> 10110 bytes
 .../_static/macros/macroparameterseditor05.odg     | Bin 0 -> 22524 bytes
 .../_static/macros/macroparameterseditor05.png     | Bin 0 -> 604944 bytes
 doc/source/_static/macros/sequenceeditor01.png     | Bin 0 -> 13687 bytes
 doc/source/_static/macros/sequenceeditor02.odg     | Bin 0 -> 27793 bytes
 doc/source/_static/macros/sequenceeditor02.png     | Bin 0 -> 672669 bytes
 doc/source/_static/macros/sequenceeditor02_raw.png | Bin 0 -> 13687 bytes
 doc/source/_static/macros/sequenceeditor03.odg     | Bin 0 -> 30108 bytes
 doc/source/_static/macros/sequenceeditor03.png     | Bin 0 -> 628299 bytes
 doc/source/_static/macros/sequenceeditor03_raw.png | Bin 0 -> 15806 bytes
 doc/source/_static/macros/sequenceeditor04.odg     | Bin 0 -> 29610 bytes
 doc/source/_static/macros/sequenceeditor04.png     | Bin 0 -> 628299 bytes
 doc/source/_static/macros/sequenceeditor05_raw.png | Bin 0 -> 19830 bytes
 doc/source/_static/macros/sequencer01.odg          | Bin 0 -> 47998 bytes
 doc/source/_static/macros/sequencer01.png          | Bin 0 -> 1233154 bytes
 doc/source/_static/macros/sequencer01_raw.png      | Bin 0 -> 29047 bytes
 .../devel/howto_controllers/howto_0dcontroller.rst |  35 ++++-
 .../howto_controllers/howto_motorcontroller.rst    |   4 -
 doc/source/devel/howto_macros/macros_general.rst   |  30 ++--
 doc/source/devel/overview/overview_0D.rst          |  18 ++-
 doc/source/users/index.rst                         |   1 +
 .../users/taurus/experimentconfiguration.rst       |  15 ++
 doc/source/users/taurus/index.rst                  |  15 ++
 doc/source/users/taurus/macroexecutor.rst          | 152 +++++++++++++++++++
 doc/source/users/taurus/sardanaeditor.rst          |  15 ++
 doc/source/users/taurus/sequencer.rst              | 123 +++++++++++++++
 setup.py                                           |   2 +-
 src/sardana/macroserver/macro.py                   |  48 +++++-
 src/sardana/macroserver/macros/demo.py             |  30 ++--
 src/sardana/macroserver/macros/examples/motion.py  |  56 +++++++
 .../macroserver/macros/examples/parameters.py      |   4 +-
 src/sardana/macroserver/macros/hkl.py              |  72 ++++-----
 src/sardana/macroserver/macros/standard.py         |   3 +-
 .../macroserver/macros/test/macroexecutor.py       |   6 +-
 src/sardana/macroserver/msmacromanager.py          |  52 ++++++-
 src/sardana/macroserver/msoptions.py               |   1 +
 src/sardana/macroserver/msparameter.py             | 165 ++++++++++++++++++++-
 src/sardana/macroserver/recorders/output.py        |   9 +-
 src/sardana/macroserver/scan/gscan.py              |  19 ++-
 src/sardana/pool/pool.py                           |   9 +-
 src/sardana/pool/poolacquisition.py                |   8 +-
 src/sardana/pool/poolbasegroup.py                  |   9 +-
 .../poolcontrollers/HklPseudoMotorController.py    |  28 +++-
 src/sardana/pool/poolmeasurementgroup.py           |  21 +--
 src/sardana/pool/poolzerodexpchannel.py            |  15 +-
 src/sardana/release.py                             |   2 +-
 src/sardana/requirements.py                        |   3 +
 src/sardana/spock/ipython_00_10/genutils.py        |  23 ++-
 src/sardana/spock/ipython_00_11/genutils.py        |  92 ++++++++----
 src/sardana/spock/ipython_01_00/genutils.py        | 100 +++++++++----
 src/sardana/spock/magic.py                         |  56 ++++---
 src/sardana/spock/release.py                       |   2 +-
 src/sardana/spock/spockms.py                       |  14 +-
 .../taurus/core/tango/sardana/macroserver.py       |  28 +++-
 src/sardana/taurus/core/tango/sardana/motion.py    |   2 +-
 src/sardana/taurus/core/tango/sardana/pool.py      |  91 ++++++++++--
 .../taurus/qt/qtcore/tango/sardana/macroserver.py  |  31 +++-
 .../taurus/qt/qtgui/extra_macroexecutor/common.py  |  10 +-
 .../qt/qtgui/extra_macroexecutor/macrobutton.py    |  18 +--
 .../qt/qtgui/extra_macroexecutor/macroexecutor.py  |  31 +++-
 .../extra_macroexecutor/sequenceeditor/model.py    |   2 +-
 .../sequenceeditor/sequenceeditor.py               |  31 +++-
 .../taurus/qt/qtgui/extra_pool/poolchannel.py      |   2 +-
 .../taurus/qt/qtgui/extra_pool/poolioregister.py   |   6 +-
 .../taurus/qt/qtgui/extra_pool/poolmotor.py        |  52 ++++---
 .../taurus/qt/qtgui/extra_pool/ui/PoolMotorSlim.ui | 148 ++++++++----------
 .../qt/qtgui/extra_sardana/expdescription.py       |  19 ++-
 .../qt/qtgui/extra_sardana/measurementgroup.py     |  62 +++++++-
 89 files changed, 1421 insertions(+), 409 deletions(-)

diff --git a/PKG-INFO b/PKG-INFO
index 32dacfe..27b64b6 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: sardana
-Version: 2.0.0
+Version: 2.1.0
 Summary: instrument control and data acquisition system
 Home-page: http://www.sardana-controls.org
 Author: Zbigniew Reszela
@@ -32,9 +32,9 @@ Classifier: Programming Language :: Python
 Classifier: Topic :: Scientific/Engineering
 Classifier: Topic :: Software Development :: Libraries
 Requires: PyTango (>=7.2.3)
+Requires: itango (>=0.1.4)
 Requires: taurus (>= 3.6.0)
 Requires: lxml (>=2.1)
-Requires: ipython (>=0.10, !=0.11)
 Provides: sardana
 Provides: sardana.pool
 Provides: sardana.macroserver
diff --git a/doc/man/MacroServer.1 b/doc/man/MacroServer.1
index 1558828..f7a6133 100644
--- a/doc/man/MacroServer.1
+++ b/doc/man/MacroServer.1
@@ -1,7 +1,7 @@
 .\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.43.3.
-.TH MACROSERVER "1" "April 2016" "MacroServer 2.0.0" "User Commands"
+.TH MACROSERVER "1" "September 2016" "MacroServer 2.1.0" "User Commands"
 .SH NAME
-MacroServer \- manual page for MacroServer 2.0.0
+MacroServer \- manual page for MacroServer 2.1.0
 .SH SYNOPSIS
 .B usage:
 \fIMacroServer instance_name \fR[\fIoptions\fR]
diff --git a/doc/man/Pool.1 b/doc/man/Pool.1
index 352b116..dbd19e6 100644
--- a/doc/man/Pool.1
+++ b/doc/man/Pool.1
@@ -1,7 +1,7 @@
 .\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.43.3.
-.TH POOL "1" "April 2016" "Pool 2.0.0" "User Commands"
+.TH POOL "1" "September 2016" "Pool 2.1.0" "User Commands"
 .SH NAME
-Pool \- manual page for Pool 2.0.0
+Pool \- manual page for Pool 2.1.0
 .SH SYNOPSIS
 .B usage:
 \fIPool instance_name \fR[\fIoptions\fR]
diff --git a/doc/man/Sardana.1 b/doc/man/Sardana.1
index d6fae7f..ae4cc6c 100644
--- a/doc/man/Sardana.1
+++ b/doc/man/Sardana.1
@@ -1,7 +1,7 @@
 .\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.43.3.
-.TH SARDANA "1" "April 2016" "Sardana 2.0.0" "User Commands"
+.TH SARDANA "1" "September 2016" "Sardana 2.1.0" "User Commands"
 .SH NAME
-Sardana \- manual page for Sardana 2.0.0
+Sardana \- manual page for Sardana 2.1.0
 .SH SYNOPSIS
 .B usage:
 \fISardana instance_name \fR[\fIoptions\fR]
diff --git a/doc/man/diffractometeralignment.1 b/doc/man/diffractometeralignment.1
index 9110451..0cb837d 100644
--- a/doc/man/diffractometeralignment.1
+++ b/doc/man/diffractometeralignment.1
@@ -1,7 +1,7 @@
 .\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.43.3.
-.TH DIFFRACTOMETERALIGNMENT "1" "April 2016" "diffractometeralignment 2.0.0" "User Commands"
+.TH DIFFRACTOMETERALIGNMENT "1" "September 2016" "diffractometeralignment 2.1.0" "User Commands"
 .SH NAME
-diffractometeralignment \- manual page for diffractometeralignment 2.0.0
+diffractometeralignment \- manual page for diffractometeralignment 2.1.0
 .SH SYNOPSIS
 .B diffractometeralignment
 \fI<model> \fR[\fIdoor_name\fR]
diff --git a/doc/man/hklscan.1 b/doc/man/hklscan.1
index 796e032..8ef6b21 100644
--- a/doc/man/hklscan.1
+++ b/doc/man/hklscan.1
@@ -1,7 +1,7 @@
 .\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.43.3.
-.TH HKLSCAN "1" "April 2016" "hklscan 2.0.0" "User Commands"
+.TH HKLSCAN "1" "September 2016" "hklscan 2.1.0" "User Commands"
 .SH NAME
-hklscan \- manual page for hklscan 2.0.0
+hklscan \- manual page for hklscan 2.1.0
 .SH SYNOPSIS
 .B hklscan
 \fI<model> \fR[\fIdoor_name\fR]
diff --git a/doc/man/macroexecutor.1 b/doc/man/macroexecutor.1
index 039a949..1e73a9f 100644
--- a/doc/man/macroexecutor.1
+++ b/doc/man/macroexecutor.1
@@ -1,7 +1,7 @@
 .\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.43.3.
-.TH MACROEXECUTOR "1" "April 2016" "macroexecutor 2.0.0" "User Commands"
+.TH MACROEXECUTOR "1" "September 2016" "macroexecutor 2.1.0" "User Commands"
 .SH NAME
-macroexecutor \- manual page for macroexecutor 2.0.0
+macroexecutor \- manual page for macroexecutor 2.1.0
 .SH SYNOPSIS
 .B macroexecutor
 [\fIoptions\fR]
diff --git a/doc/man/sequencer.1 b/doc/man/sequencer.1
index 19dcc3e..8fecd58 100644
--- a/doc/man/sequencer.1
+++ b/doc/man/sequencer.1
@@ -1,7 +1,7 @@
 .\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.43.3.
-.TH SEQUENCER "1" "April 2016" "sequencer 2.0.0" "User Commands"
+.TH SEQUENCER "1" "September 2016" "sequencer 2.1.0" "User Commands"
 .SH NAME
-sequencer \- manual page for sequencer 2.0.0
+sequencer \- manual page for sequencer 2.1.0
 .SH SYNOPSIS
 .B sequencer
 [\fIoptions\fR]
diff --git a/doc/man/spock.1 b/doc/man/spock.1
index 8e67216..e57623c 100644
--- a/doc/man/spock.1
+++ b/doc/man/spock.1
@@ -1,7 +1,7 @@
 .\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.43.3.
-.TH SPOCK "1" "April 2016" "spock 2.0.0" "User Commands"
+.TH SPOCK "1" "September 2016" "spock 2.1.0" "User Commands"
 .SH NAME
-spock \- manual page for spock 2.0.0
+spock \- manual page for spock 2.1.0
 .SH DESCRIPTION
 =========
 .IP
diff --git a/doc/man/ubmatrix.1 b/doc/man/ubmatrix.1
index 40c78df..13e52f5 100644
--- a/doc/man/ubmatrix.1
+++ b/doc/man/ubmatrix.1
@@ -1,7 +1,7 @@
 .\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.43.3.
-.TH UBMATRIX "1" "April 2016" "ubmatrix 2.0.0" "User Commands"
+.TH UBMATRIX "1" "September 2016" "ubmatrix 2.1.0" "User Commands"
 .SH NAME
-ubmatrix \- manual page for ubmatrix 2.0.0
+ubmatrix \- manual page for ubmatrix 2.1.0
 .SH SYNOPSIS
 .B ubmatrix
 \fI<model>\fR
diff --git a/doc/source/_static/macros/favouriteeditor01.png b/doc/source/_static/macros/favouriteeditor01.png
new file mode 100644
index 0000000..808e060
Binary files /dev/null and b/doc/source/_static/macros/favouriteeditor01.png differ
diff --git a/doc/source/_static/macros/macroexecutor01.odg b/doc/source/_static/macros/macroexecutor01.odg
new file mode 100644
index 0000000..75113e2
Binary files /dev/null and b/doc/source/_static/macros/macroexecutor01.odg differ
diff --git a/doc/source/_static/macros/macroexecutor01.png b/doc/source/_static/macros/macroexecutor01.png
new file mode 100644
index 0000000..055b58f
Binary files /dev/null and b/doc/source/_static/macros/macroexecutor01.png differ
diff --git a/doc/source/_static/macros/macroexecutor01_raw.png b/doc/source/_static/macros/macroexecutor01_raw.png
new file mode 100644
index 0000000..a244370
Binary files /dev/null and b/doc/source/_static/macros/macroexecutor01_raw.png differ
diff --git a/doc/source/_static/macros/macroparameterseditor01.png b/doc/source/_static/macros/macroparameterseditor01.png
new file mode 100644
index 0000000..69ba02a
Binary files /dev/null and b/doc/source/_static/macros/macroparameterseditor01.png differ
diff --git a/doc/source/_static/macros/macroparameterseditor02.png b/doc/source/_static/macros/macroparameterseditor02.png
new file mode 100644
index 0000000..8847a38
Binary files /dev/null and b/doc/source/_static/macros/macroparameterseditor02.png differ
diff --git a/doc/source/_static/macros/macroparameterseditor03.odg b/doc/source/_static/macros/macroparameterseditor03.odg
new file mode 100644
index 0000000..1002357
Binary files /dev/null and b/doc/source/_static/macros/macroparameterseditor03.odg differ
diff --git a/doc/source/_static/macros/macroparameterseditor03.png b/doc/source/_static/macros/macroparameterseditor03.png
new file mode 100644
index 0000000..10ed847
Binary files /dev/null and b/doc/source/_static/macros/macroparameterseditor03.png differ
diff --git a/doc/source/_static/macros/macroparameterseditor03_raw.png b/doc/source/_static/macros/macroparameterseditor03_raw.png
new file mode 100644
index 0000000..db86a09
Binary files /dev/null and b/doc/source/_static/macros/macroparameterseditor03_raw.png differ
diff --git a/doc/source/_static/macros/macroparameterseditor04.odg b/doc/source/_static/macros/macroparameterseditor04.odg
new file mode 100644
index 0000000..244c2a5
Binary files /dev/null and b/doc/source/_static/macros/macroparameterseditor04.odg differ
diff --git a/doc/source/_static/macros/macroparameterseditor04.png b/doc/source/_static/macros/macroparameterseditor04.png
new file mode 100644
index 0000000..c908572
Binary files /dev/null and b/doc/source/_static/macros/macroparameterseditor04.png differ
diff --git a/doc/source/_static/macros/macroparameterseditor04_raw.png b/doc/source/_static/macros/macroparameterseditor04_raw.png
new file mode 100644
index 0000000..86c2a57
Binary files /dev/null and b/doc/source/_static/macros/macroparameterseditor04_raw.png differ
diff --git a/doc/source/_static/macros/macroparameterseditor05.odg b/doc/source/_static/macros/macroparameterseditor05.odg
new file mode 100644
index 0000000..8007ac6
Binary files /dev/null and b/doc/source/_static/macros/macroparameterseditor05.odg differ
diff --git a/doc/source/_static/macros/macroparameterseditor05.png b/doc/source/_static/macros/macroparameterseditor05.png
new file mode 100644
index 0000000..ab65c57
Binary files /dev/null and b/doc/source/_static/macros/macroparameterseditor05.png differ
diff --git a/doc/source/_static/macros/sequenceeditor01.png b/doc/source/_static/macros/sequenceeditor01.png
new file mode 100644
index 0000000..34dbcfa
Binary files /dev/null and b/doc/source/_static/macros/sequenceeditor01.png differ
diff --git a/doc/source/_static/macros/sequenceeditor02.odg b/doc/source/_static/macros/sequenceeditor02.odg
new file mode 100644
index 0000000..5f4cedb
Binary files /dev/null and b/doc/source/_static/macros/sequenceeditor02.odg differ
diff --git a/doc/source/_static/macros/sequenceeditor02.png b/doc/source/_static/macros/sequenceeditor02.png
new file mode 100644
index 0000000..89b9db3
Binary files /dev/null and b/doc/source/_static/macros/sequenceeditor02.png differ
diff --git a/doc/source/_static/macros/sequenceeditor02_raw.png b/doc/source/_static/macros/sequenceeditor02_raw.png
new file mode 100644
index 0000000..34dbcfa
Binary files /dev/null and b/doc/source/_static/macros/sequenceeditor02_raw.png differ
diff --git a/doc/source/_static/macros/sequenceeditor03.odg b/doc/source/_static/macros/sequenceeditor03.odg
new file mode 100644
index 0000000..497a5f6
Binary files /dev/null and b/doc/source/_static/macros/sequenceeditor03.odg differ
diff --git a/doc/source/_static/macros/sequenceeditor03.png b/doc/source/_static/macros/sequenceeditor03.png
new file mode 100644
index 0000000..b51ab80
Binary files /dev/null and b/doc/source/_static/macros/sequenceeditor03.png differ
diff --git a/doc/source/_static/macros/sequenceeditor03_raw.png b/doc/source/_static/macros/sequenceeditor03_raw.png
new file mode 100644
index 0000000..06acb0b
Binary files /dev/null and b/doc/source/_static/macros/sequenceeditor03_raw.png differ
diff --git a/doc/source/_static/macros/sequenceeditor04.odg b/doc/source/_static/macros/sequenceeditor04.odg
new file mode 100644
index 0000000..3493675
Binary files /dev/null and b/doc/source/_static/macros/sequenceeditor04.odg differ
diff --git a/doc/source/_static/macros/sequenceeditor04.png b/doc/source/_static/macros/sequenceeditor04.png
new file mode 100644
index 0000000..cada20e
Binary files /dev/null and b/doc/source/_static/macros/sequenceeditor04.png differ
diff --git a/doc/source/_static/macros/sequenceeditor05_raw.png b/doc/source/_static/macros/sequenceeditor05_raw.png
new file mode 100644
index 0000000..abc285c
Binary files /dev/null and b/doc/source/_static/macros/sequenceeditor05_raw.png differ
diff --git a/doc/source/_static/macros/sequencer01.odg b/doc/source/_static/macros/sequencer01.odg
new file mode 100644
index 0000000..37868ec
Binary files /dev/null and b/doc/source/_static/macros/sequencer01.odg differ
diff --git a/doc/source/_static/macros/sequencer01.png b/doc/source/_static/macros/sequencer01.png
new file mode 100644
index 0000000..8a563d8
Binary files /dev/null and b/doc/source/_static/macros/sequencer01.png differ
diff --git a/doc/source/_static/macros/sequencer01_raw.png b/doc/source/_static/macros/sequencer01_raw.png
new file mode 100644
index 0000000..a14b78c
Binary files /dev/null and b/doc/source/_static/macros/sequencer01_raw.png differ
diff --git a/doc/source/devel/howto_controllers/howto_0dcontroller.rst b/doc/source/devel/howto_controllers/howto_0dcontroller.rst
index 23c5af6..6be50bd 100644
--- a/doc/source/devel/howto_controllers/howto_0dcontroller.rst
+++ b/doc/source/devel/howto_controllers/howto_0dcontroller.rst
@@ -6,10 +6,39 @@
 How to write a 0D controller
 ============================
 
-The basics
-----------
+.. todo:: complete 0D controller howto
+
+Get 0D state
+~~~~~~~~~~~~~~~
+
+To get the state of a 0D, sardana calls the
+:meth:`~sardana.pool.controller.Controller.StateOne` method. During the
+acquisition loop this method is called only once when it is about to
+exit. This method receives an axis as parameter and should return either:
+
+    - state (:obj:`~sardana.sardanadefs.State`) or
+    - a sequence of two elements:
+        - state (:obj:`~sardana.sardanadefs.State`)
+        - status (:obj:`str`)
+
+The state should be a member of :obj:`~sardana.sardanadefs.State` (For backward
+compatibility reasons, it is also supported to return one of
+:class:`PyTango.DevState`). The status could be any string.
+
+If you don't return a status, sardana will compose a status string with:
+
+    <axis name> is in <state name>
+
+The controller could return on of the four states **On**, **Alarm**, **Fault**
+or **Unknown**. Apart of that sardana could set **Moving** or **Fault** state
+to the 0D. The Moving state is set during the acquisition loop to indicate that
+it is acquiring data. The Fault state is set when the controller software is
+not available (impossible to load it).
+The controller should return Fault if a fault is reported from the hardware
+controller or if the controller software returns an unforeseen state.
+The controller should return Unknown state if an exception occurs during the
+communication between the pool and the hardware controller.
 
-.. todo:: document 0D controller howto
         
 .. _ALBA: http://www.cells.es/
 .. _ANKA: http://http://ankaweb.fzk.de/
diff --git a/doc/source/devel/howto_controllers/howto_motorcontroller.rst b/doc/source/devel/howto_controllers/howto_motorcontroller.rst
index bb2aa27..8237bb9 100644
--- a/doc/source/devel/howto_controllers/howto_motorcontroller.rst
+++ b/doc/source/devel/howto_controllers/howto_motorcontroller.rst
@@ -68,10 +68,6 @@ Get motor state
 
 To get the state of a motor, sardana calls the
 :meth:`~sardana.pool.controller.Controller.StateOne` method. This method
-receives an axis as parameter and should return a sequence of three values:
-
-To get the state of a motor, sardana calls the
-:meth:`~sardana.pool.controller.Controller.StateOne` method. This method
 receives an axis as parameter and should return either:
 
     - state (:obj:`~sardana.sardanadefs.State`) or
diff --git a/doc/source/devel/howto_macros/macros_general.rst b/doc/source/devel/howto_macros/macros_general.rst
index 8f6144d..3f658e6 100644
--- a/doc/source/devel/howto_macros/macros_general.rst
+++ b/doc/source/devel/howto_macros/macros_general.rst
@@ -343,7 +343,7 @@ of items.
 ::
 
     @macro([["moveables", [
-                 "moveable", Type.Moveable, None, "moveable to get position"
+                 ["moveable", Type.Moveable, None, "moveable to get position"]
                  ],
                  None, "list of moveables to get positions"]])
     def where_moveables(self, moveables):
@@ -363,7 +363,7 @@ each item is an internal list of the members.
                  None, "list of moveables and positions to be moved to"]])
     def move_multiple(self, m_p_pairs):
         """This macro moves moveables to the specified positions"""
-        for moveable, position in zip(*m_p_pairs):
+        for moveable, position in m_p_pairs:
             moveable.move(position)
             self.output("%s is now at %s", moveable.getName(), moveable.getPosition())
 
@@ -419,7 +419,7 @@ Here is the new version of *where_moveable* ::
     @macro([["moveable", Type.Moveable, None, "moveable to get position"]])
     def where_moveable(self, moveable):
         """This macro prints the current moveable position"""
-        self.wm([moveable])
+        self.wm([moveable]) # self.wm(moveable) backwards compatibility - see note
 
 ... and the new version of *move* ::
 
@@ -427,15 +427,19 @@ Here is the new version of *where_moveable* ::
              ["position", Type.Float, None, "absolute position"] ])
     def move(self, moveable, position):
         """This macro moves a moveable to the specified position"""
-        self.mv([[moveable, position]])
+        self.mv([moveable, position]) # self.mv(moveable, position) backwards compatibility - see note
         self.output("%s is now at %s", moveable.getName(), moveable.getPosition())
 
 .. note::
-    Both :class:`~sardana.macroserver.macros.standard.wm` and
-    :class:`~sardana.macroserver.macros.standard.mv`
-    use :ref:`repeat parameters <sardana-macro-repeat-parameters>`.
-    From Sardana 2.0 the repeat parameter values must be passed as lists of
-    items. An item of a repeat parameter containing more than one member is a list.
+   Both :class:`~sardana.macroserver.macros.standard.wm` and
+   :class:`~sardana.macroserver.macros.standard.mv`
+   use :ref:`repeat parameters <sardana-macro-repeat-parameters>`.
+   From Sardana 2.0 the repeat parameter values must be passed as lists of
+   items. An item of a repeat parameter containing more than one member is a
+   list. In case when a macro defines only one repeat parameter
+   and it is the last parameter, for the backwards compatibility reasons, the
+   plain list of items' members is allowed.
+	
 
 .. _sardana-macro-environment:
 
@@ -590,6 +594,7 @@ parameters with different *flavors*:
 
         self.execMacro('ascan', motor.getName(), '0', '100', '10', '0.2')
         self.execMacro('mv', [[motor.getName(), '0']])
+        self.execMacro('mv', motor.getName(), '0') # backwards compatibility - see note
 
     * parameters as space separated string (this is not compatible with multiple
       or nested repeat parameters, furthermore the repeat parameter must be the last one)::
@@ -601,12 +606,17 @@ parameters with different *flavors*:
 
         self.execMacro(['ascan', motor, 0, 100, 10, 0.2])
         self.execMacro(['mv', [[motor, 0]]])
+        self.execMacro(['mv', motor, 0]) # backwards compatibility - see note
 
 .. note::
     Macro :class:`~sardana.macroserver.macros.standard.mv`
     use :ref:`repeat parameters <sardana-macro-repeat-parameters>`.
     From Sardana 2.0 the repeat parameter values must be passed as lists of
-    items. An item of a repeat parameter containing more than one member is a list.
+    items. An item of a repeat parameter containing more than one member is a
+    list. In case when a macro defines only one repeat parameter
+    and it is the last parameter, for the backwards compatibility reasons, the
+    plain list of items' members is allowed.
+
 
 Accessing macro data
 ~~~~~~~~~~~~~~~~~~~~
diff --git a/doc/source/devel/overview/overview_0D.rst b/doc/source/devel/overview/overview_0D.rst
index e3d6553..f5ccf05 100644
--- a/doc/source/devel/overview/overview_0D.rst
+++ b/doc/source/devel/overview/overview_0D.rst
@@ -6,12 +6,22 @@
 0D channel overview
 =======================
 
-.. todo:: document 0D experiment channel overview
+The ZeroDExpChannel is used to access any kind of device which returns a scalar
+value and which are not counter or timer. Very often (but not always), this is
+a commercial measurement equipment connected to a GPIB bus. In order to have as
+precise as possible measurement, an acquisition loop is implemented for the
+ZeroDExpChannel device. This acquisition loop will simply read the data from
+the hardware as fast as it can (only “sleeping” 10 mS between each reading) and
+a computation is done on the resulting data set to return only one value.
+Three types of computation are foreseen. The user selects which one he needs
+with an attribute. The time during which this acquisition loop will get data is
+controlled by the counters & timers present in the measurement group - when all
+of them finish acquiring the ZeroD acquisition action will also stop.
+
+.. seealso::
 
-.. seealso:: 
-    
     :ref:`sardana-0d-api`
         the 0D experiment channel :term:`API` 
-    
+
     :class:`~sardana.tango.pool.ZeroDExpChannel.ZeroDExpChannel`
         the 0D experiment channel tango device :term:`API`
diff --git a/doc/source/users/index.rst b/doc/source/users/index.rst
index a137e8a..0651fb4 100644
--- a/doc/source/users/index.rst
+++ b/doc/source/users/index.rst
@@ -10,6 +10,7 @@ User's Guide
     Overview <overview>
     Getting started <getting_started/index>
     Spock <spock>
+    Sardana-Taurus Widgets <taurus/index>
     Scans <scan>
     Standard macro catalog <standard_macro_catalog>
     Screenshots <screenshots>
diff --git a/doc/source/users/taurus/experimentconfiguration.rst b/doc/source/users/taurus/experimentconfiguration.rst
new file mode 100644
index 0000000..d6bcd3e
--- /dev/null
+++ b/doc/source/users/taurus/experimentconfiguration.rst
@@ -0,0 +1,15 @@
+.. currentmodule:: sardana.taurus.qt.qtgui.extra_sardana
+
+.. _expconf_ui:
+
+
+=======================================
+Experiment Configuration user interface
+=======================================
+
+.. contents::
+
+.. todo:: 
+    Experiment Configuration documentation to be written  
+
+ 
\ No newline at end of file
diff --git a/doc/source/users/taurus/index.rst b/doc/source/users/taurus/index.rst
new file mode 100644
index 0000000..9e13137
--- /dev/null
+++ b/doc/source/users/taurus/index.rst
@@ -0,0 +1,15 @@
+
+================================
+Sardana Taurus Extension widgets
+================================
+
+
+Sardana provides several :mod:`taurus`-based widgets for being used in GUIs
+
+.. toctree::
+    :maxdepth: 3
+   
+    MacroExecutor <macroexecutor>
+    Sequencer <sequencer>
+    Experiment Configuration <experimentconfiguration>
+    Sardana Editor <sardanaeditor>
diff --git a/doc/source/users/taurus/macroexecutor.rst b/doc/source/users/taurus/macroexecutor.rst
new file mode 100644
index 0000000..b3675df
--- /dev/null
+++ b/doc/source/users/taurus/macroexecutor.rst
@@ -0,0 +1,152 @@
+.. _macroexecutor_ui:
+
+==========================================
+MacroExecutor User's Interface
+==========================================
+
+
+.. contents::
+
+
+*MacroExecutor* provides an user-friendly graphical interface to macro execution.
+It is divided into 3 main areas: `actions bar`, `parameters editor` and `favourites list`. 
+Their functionalities are supported by `Spock command line` and `macro progress bar`.
+User has full control over macros thanks to action buttons: Start(Resume), Stop, Pause located in `actions bar`     
+Graphical `parameters editor` provides a clear way to set and modify macro execution settings (parameters).
+Macros which are more frequently used can be permanently stored in `favourites list`. 
+Once macro was started Door's state led and `macro progress bar` informs user about its status. 
+Current macro settings (parameters) are translated to spock syntax, and represented in non editable
+`spock command line`.
+
+.. figure:: /_static/macros/macroexecutor01.png
+  :align: center
+
+
+.. _macroexecutor_stand-alone:
+
+
+MacroExecutor as a stand-alone application
+------------------------------------------
+
+You may also use *MacroExecutor* as a stand-alone application. In this case it appears embedded
+in window and some extra functionalities are provided. 
+You can launch the stand-alone *MacroExecutor* with the following command::
+
+    macroexecutor [options] [<macro_executor_dev_name> <door_dev_name>]
+	
+Options::
+ 
+  --taurus-log-level=LEVEL
+                        taurus log level. Allowed values are (case
+                        insensitive): critical, error, warning/warn, info,
+                        debug, trace
+                        
+  --taurus-polling-period=MILLISEC
+                        taurus global polling period in milliseconds
+                        
+  --taurus-serialization-mode=SERIAL
+                        taurus serialization mode. Allowed values are (case
+                        insensitive): serial, concurrent (default)
+  
+  --tango-host=TANGO_HOST
+                        Tango host name
+
+    
+The model list is optional and is a space-separated list of two device names: macro server and door.
+If not provided at the application startup, models can be later on changed in configuration dialog.   
+   
+Extra functionalities:
+
+- Changing macro configuration
+
+.. todo:: 
+	This chapter is not ready... Sorry for inconvenience.
+	
+- Configuring custom editors
+ 
+.. todo:: 
+	This chapter is not ready... Sorry for inconvenience.
+
+	
+.. _editing_macro_parameters:
+
+Editing macro parameters
+------------------------
+
+.. _editing_macro_parameters_standard:
+
+Using standard editor
+'''''''''''''''''''''
+
+If no custom parameter editor is assigned to macro, default editor is used to configure execution settings (parameters).
+Parameters are represented in form of tree (with hidden root node) - every parameter is a separate branch with two columns: 
+parameter name and parameter value.
+Editor is populated with default values of parameters, if this in not a case 'None' values are used. (If macro execution settings 
+were restored e.g. from favourites list, editor is populated with stored values). Values become editable either by double-clicking on them, 
+or by pressing F2 button when value is selected. This action opens default parameter editor (combobox with predefined values, spin box etc.). 
+
+In case of macros with single parameters only, tree has only a one level branch, and then tree representation looks more like a list 
+(because of hidden root node)
+
+.. figure:: /_static/macros/macroparameterseditor01.png
+  :align: center
+
+In case of macros which contain repeat parameters, concept of tree is more visible.  
+ 
+.. figure:: /_static/macros/macroparameterseditor02.png
+  :align: center
+  
+- adding new parameter repetition
+
+First select parameter node and if its maximum number of repetition is not exceeded, button with '+' sign appears enabled. 
+After pressing this button child branch with new repetition appears in tree editor.   
+
+.. figure:: /_static/macros/macroparameterseditor03.png
+  :align: center
+  
+- modifying repetition order
+
+First select repetition node (with #<number> text), and buttons with arrows becomes enable (if it is feasible to change order)
+
+.. figure:: /_static/macros/macroparameterseditor04.png
+  :align: center
+
+- removing parameter repetition
+
+First select repetition node (with #<number> text), and if it's minimum number of repetition is not reached, button with '-' sign appears enabled. 
+After pressing this button child branch disappears from tree editor. (see previous picture)
+
+.. figure:: /_static/macros/macroparameterseditor05.png
+  :align: center
+
+.. _editing_macro_parameters_custom:
+
+Using custom editors
+''''''''''''''''''''
+
+.. todo:: 
+	This chapter is not ready... Sorry for inconvenince. 
+
+.. _editing_favourites_list:
+
+Editing favourites list
+-----------------------
+  
+Once macro parameters are configured they can be easily stored in favourites list for later reuse.   
+
+- adding a favourite 
+
+Clicking in Add to favourites button (the one with yellow star), adds a new entry in favourite list, 
+with current macro and its current settings.
+
+- restoring a favourite
+
+To restore macro from favourites list just select it in the list and macro parameters editor will immediately populate with stored settings.
+
+- modifying favouites list
+
+First select favourite macro and buttons with arrows becomes enable (if it is feasible to change order)
+
+- removing a favourite
+
+First select favourite macro, button with '-' sign appears enabled. After pressing this button, previously selected macro disappears from the list.
\ No newline at end of file
diff --git a/doc/source/users/taurus/sardanaeditor.rst b/doc/source/users/taurus/sardanaeditor.rst
new file mode 100644
index 0000000..fe2e89a
--- /dev/null
+++ b/doc/source/users/taurus/sardanaeditor.rst
@@ -0,0 +1,15 @@
+.. currentmodule:: sardana.taurus.qt.qtgui.extra_sardana
+
+.. _sardanaeditor_ui:
+
+
+==========================
+Sardana Editor's interface
+==========================
+
+.. contents::
+
+.. todo:: 
+    Sardana Editor documentation to be written  
+
+ 
\ No newline at end of file
diff --git a/doc/source/users/taurus/sequencer.rst b/doc/source/users/taurus/sequencer.rst
new file mode 100644
index 0000000..6eca58d
--- /dev/null
+++ b/doc/source/users/taurus/sequencer.rst
@@ -0,0 +1,123 @@
+.. _sequencer_ui:
+
+==========================================
+Sequencer User's Interface
+==========================================
+
+
+.. contents::
+
+
+`Sequencer` provides an user-friendly interface to compose and execute sequences of macros. Sequence of macros allows execution 
+of ordered set of macros with just one trigger. It also allows using a concept of hooks (macros attached and executed in defined places of other macros).
+It is divided into 3 main areas: `actions bar`, `sequence editor` and `parameters editor`.
+`Sequence editor` allows you modifying sequences in many ways: appending new macros, changing macros locations and removing macros. 
+Graphical `parameters editor` (standard/custom) provides a clear way to set/modify macro execution settings(parameters). 
+Once sequence of macros is in execution phase, `Sequencer` informs user about its state with Door's state led and macros progress bars. 
+User has full control over sequence, with action buttons: Start, Stop, Pause, Resume. 
+If desirable, sequences can be permanently stored into a file and later on restored from there. 
+This functionality is provided thanks to action buttons: Save and Open a sequence.
+
+.. figure:: /_static/macros/sequencer01.png
+  :align: center
+
+
+.. _sequencer_stand-alone:
+
+Sequencer as a stand-alone application
+--------------------------------------
+
+You may also use *Sequencer* as a stand-alone application. In this case it appears embedded
+in window and some extra functionalities are provided.  
+You can launch the stand-alone *Sequencer* with the following command::
+
+    sequencer [options] [<macro_executor_dev_name> <door_dev_name>]
+	
+Options::
+ 
+  --taurus-log-level=LEVEL
+                        taurus log level. Allowed values are (case
+                        insensitive): critical, error, warning/warn, info,
+                        debug, trace
+                        
+  --taurus-polling-period=MILLISEC
+                        taurus global polling period in milliseconds
+                        
+  --taurus-serialization-mode=SERIAL
+                        taurus serialization mode. Allowed values are (case
+                        insensitive): serial, concurrent (default)
+  
+  --tango-host=TANGO_HOST
+                        Tango host name
+
+    
+The model list is optional and is a space-separated list of two device names: macro server and door.
+If not provided at the application startup, device names can be later on selected from Macro Configuration Dialog.   
+   
+Extra functionalities:
+
+- MacroConfigurationDialog
+
+.. todo:: 
+		This chapter in not ready... Sorry for inconvenience. 
+		 
+- CustomEditorsPathDialog
+ 
+.. todo:: 
+		This chapter in not ready... Sorry for inconvenience.
+		
+.. _editing_sequence:
+
+Editing sequence
+----------------
+
+Sequence is represented as a flat list of ordered macros, in this view each macro is represented as a new line with 4 columns: 
+Macro (macro name), Parameters (comma separated parameter values), Progress (macro progress bar) and Pause 
+(pause point before macro execution - not implemented yet). Macros which contain hooks, expand with branched macros. 
+Macro parameters values can be edited from `parameters editor`, to do so select one macro in sequence editor by clicking on it. 
+Selected macro becomes highlighted, and `parameters editor` populate with its current parameters values. 
+
+.. figure:: /_static/macros/sequenceeditor01.png
+  :align: center
+
+- adding a new macro 
+
+First select macro from macro combo box, and when you are sure to add it to the sequence, press '+' button. 
+To add macro as a hook of other macro, before adding it, please select its parent macro in the sequence, and then press '+' button.
+If no macro was selected as a parent, macro will be automatically appended at the end of the list.    
+   
+.. figure:: /_static/macros/sequenceeditor02.png
+  :align: center  
+  
+- reorganizing sequence
+
+Macros which are already part of a sequence, can be freely moved around, either in execution order or in hook place (if new macro accepts hooks).
+To move macro first select it in the sequence by single clicking on it (it will become highlighted). Then a set of buttons with arrows 
+become enabled. Clicking on them will cause selected macro changin its position in the sequence (either vertically - execution order or horizontal
+parent macro - hook macro relationship)
+
+.. figure:: /_static/macros/sequenceeditor03.png
+  :align: center
+  
+- remove macro
+
+Macros which are already part of a sequence, can be freely removed from it. To do so first select macro in a sequence by 
+single clicking on it (it will become highlighted). Then button with '-' becomes enabled. Clicking on it removes selected macro. 
+
+.. figure:: /_static/macros/sequenceeditor04.png
+  :align: center  
+
+- configuring hook execution place
+
+If macro is embedded as a hook in parent macro, please follow these instructions to configure its hook execution place. 
+First select macro in a sequence by single clicking on it (it will become highlighted). 
+Then using right mouse button open context menu, go to 'Hook places' sub-menu and select hook places which interest you 
+(you can select more than one). 
+   
+.. figure:: /_static/macros/sequenceeditor05_raw.png
+  :align: center 
+
+	
+Editing macro parameters
+------------------------
+To obtain information about editing macro parameters, please refer to the following link :ref:`Editing macro parameters <editing_macro_parameters>` 
\ No newline at end of file
diff --git a/setup.py b/setup.py
index d94528b..8b9dff5 100644
--- a/setup.py
+++ b/setup.py
@@ -374,9 +374,9 @@ def main():
 
     requires = [
         'PyTango (>=7.2.3)',
+        'itango (>=0.1.4)',
         'taurus (>= 3.6.0)',
         'lxml (>=2.1)',
-        'ipython (>=0.10, !=0.11)'
     ]
 
     scripts = [
diff --git a/src/sardana/macroserver/macro.py b/src/sardana/macroserver/macro.py
index 17e800c..34d6cb5 100644
--- a/src/sardana/macroserver/macro.py
+++ b/src/sardana/macroserver/macro.py
@@ -1051,20 +1051,27 @@ class Macro(Logger):
             # several parameters:
             self.execMacro('ascan', 'th', '0', '100', '10', '1.0')
             self.execMacro('mv', [[motor.getName(), '0']])
+            self.execMacro('mv', motor.getName(), '0') # backwards compatibility - see note
             self.execMacro('ascan', 'th', 0, 100, 10, 1.0)
             self.execMacro('mv', [[motor.getName(), 0]])
+            self.execMacro('mv', motor.getName(), 0) # backwards compatibility - see note
             th = self.getObj('th')
             self.execMacro('ascan', th, 0, 100, 10, 1.0)
-            self.execMacro('mv', [th, 0]])
+            self.execMacro('mv', [[th, 0]])
+            self.execMacro('mv', th, 0) # backwards compatibility - see note
 
             # a sequence of parameters:
             self.execMacro(['ascan', 'th', '0', '100', '10', '1.0')
             self.execMacro(['mv', [[motor.getName(), '0']]])
+            self.execMacro(['mv', motor.getName(), '0']) # backwards compatibility - see note
             self.execMacro(('ascan', 'th', 0, 100, 10, 1.0))
             self.execMacro(['mv', [[motor.getName(), 0]]])
+            self.execMacro(['mv', motor.getName(), 0]) # backwards compatibility - see note
             th = self.getObj('th')
             self.execMacro(['ascan', th, 0, 100, 10, 1.0])
             self.execMacro(['mv', [[th, 0]]])
+            self.execMacro(['mv', th, 0]) # backwards compatibility - see note
+
 
             # a space separated string of parameters (this is not compatible
             # with multiple or nested repeat parameters, furthermore the repeat
@@ -1072,6 +1079,13 @@ class Macro(Logger):
             self.execMacro('ascan th 0 100 10 1.0')
             self.execMacro('mv %s 0' % motor.getName())
 
+        .. note:: From Sardana 2.0 the repeat parameter values must be passed
+            as lists of items. An item of a repeat parameter containing more
+            than one member is a list. In case when a macro defines only one
+            repeat parameter and it is the last parameter, for the backwards
+            compatibility reasons, the plain list of items' members is allowed.
+
+
         :param pars: the command parameters as explained above
         :return:
             a sequence of two elements: the macro object and the result of
@@ -1108,20 +1122,26 @@ class Macro(Logger):
             # several parameters:
             self.execMacro('ascan', 'th', '0', '100', '10', '1.0')
             self.execMacro('mv', [[motor.getName(), '0']])
+            self.execMacro('mv', motor.getName(), '0') # backwards compatibility - see note
             self.execMacro('ascan', 'th', 0, 100, 10, 1.0)
             self.execMacro('mv', [[motor.getName(), 0]])
+            self.execMacro('mv', motor.getName(), 0) # backwards compatibility - see note
             th = self.getObj('th')
             self.execMacro('ascan', th, 0, 100, 10, 1.0)
-            self.execMacro('mv', [th, 0]])
+            self.execMacro('mv', [[th, 0]])
+            self.execMacro('mv', th, 0) # backwards compatibility - see note
 
             # a sequence of parameters:
             self.execMacro(['ascan', 'th', '0', '100', '10', '1.0')
             self.execMacro(['mv', [[motor.getName(), '0']]])
+            self.execMacro(['mv', motor.getName(), '0']) # backwards compatibility - see note
             self.execMacro(('ascan', 'th', 0, 100, 10, 1.0))
             self.execMacro(['mv', [[motor.getName(), 0]]])
+            self.execMacro(['mv', motor.getName(), 0]) # backwards compatibility - see note
             th = self.getObj('th')
             self.execMacro(['ascan', th, 0, 100, 10, 1.0])
             self.execMacro(['mv', [[th, 0]]])
+            self.execMacro(['mv', th, 0]) # backwards compatibility - see note
 
             # a space separated string of parameters (this is not compatible
             # with multiple or nested repeat parameters, furthermore the repeat
@@ -1129,11 +1149,18 @@ class Macro(Logger):
             self.execMacro('ascan th 0 100 10 1.0')
             self.execMacro('mv %s 0' % motor.getName())
 
+        .. note:: From Sardana 2.0 the repeat parameter values must be passed
+            as lists of items. An item of a repeat parameter containing more
+            than one member is a list. In case when a macro defines only one
+            repeat parameter and it is the last parameter, for the backwards
+            compatibility reasons, the plain list of items' members is allowed.
+
         :param args: the command parameters as explained above
         :param kwargs: keyword optional parameters for prepare
         :return:
             a sequence of two elements: the macro object and the result of
-            preparing the macro"""
+            preparing the macro
+        """
         # sync our log before calling the child macro prepare in order to avoid
         # mixed outputs between this macro and the child macro
         self.syncLog()
@@ -1190,20 +1217,26 @@ class Macro(Logger):
             # several parameters:
             self.execMacro('ascan', 'th', '0', '100', '10', '1.0')
             self.execMacro('mv', [[motor.getName(), '0']])
+            self.execMacro('mv', motor.getName(), '0') # backwards compatibility - see note
             self.execMacro('ascan', 'th', 0, 100, 10, 1.0)
             self.execMacro('mv', [[motor.getName(), 0]])
+            self.execMacro('mv', motor.getName(), 0) # backwards compatibility - see note
             th = self.getObj('th')
             self.execMacro('ascan', th, 0, 100, 10, 1.0)
             self.execMacro('mv', [th, 0]])
+            self.execMacro('mv', th, 0) # backwards compatibility - see note
 
             # a sequence of parameters:
             self.execMacro(['ascan', 'th', '0', '100', '10', '1.0')
             self.execMacro(['mv', [[motor.getName(), '0']]])
+            self.execMacro(['mv', motor.getName(), '0']) # backwards compatibility - see note
             self.execMacro(('ascan', 'th', 0, 100, 10, 1.0))
             self.execMacro(['mv', [[motor.getName(), 0]]])
+            self.execMacro(['mv', motor.getName(), 0]) # backwards compatibility - see note
             th = self.getObj('th')
             self.execMacro(['ascan', th, 0, 100, 10, 1.0])
             self.execMacro(['mv', [[th, 0]]])
+            self.execMacro(['mv', th, 0]) # backwards compatibility - see note
 
             # a space separated string of parameters (this is not compatible
             # with multiple or nested repeat parameters, furthermore the repeat
@@ -1211,9 +1244,16 @@ class Macro(Logger):
             self.execMacro('ascan th 0 100 10 1.0')
             self.execMacro('mv %s 0' % motor.getName())
 
+        .. note:: From Sardana 2.0 the repeat parameter values must be passed
+            as lists of items. An item of a repeat parameter containing more
+            than one member is a list. In case when a macro defines only one
+            repeat parameter and it is the last parameter, for the backwards
+            compatibility reasons, the plain list of items' members is allowed.
+
         :param pars: the command parameters as explained above
 
-        :return: a macro object"""
+        :return: a macro object
+        """
         # obtaining macro name
         macro_name = None
         arg0 = args[0]
diff --git a/src/sardana/macroserver/macros/demo.py b/src/sardana/macroserver/macros/demo.py
index 50536a2..6e8b8df 100644
--- a/src/sardana/macroserver/macros/demo.py
+++ b/src/sardana/macroserver/macros/demo.py
@@ -264,21 +264,21 @@ def sar_demo_hkl(self):
 
     self.print("Creating hkl controller", hkl_ctrl_name, "...")
     self.defctrl("DiffracE6C", hkl_ctrl_name,
-                 "mu=" + motor_names[0],  # motor role
-                 "omega=" + motor_names[1],
-                 "chi=" + motor_names[2],
-                 "phi=" + motor_names[3],
-                 "gamma=" + motor_names[4],
-                 "delta=" + motor_names[5],
-                 "h=" + pseudo_names[0],  # pseudo role
-                 "k=" + pseudo_names[1],
-                 "l=" + pseudo_names[2],
-                 "psi=" + pseudo_names[3],
-                 "q=" + pseudo_names[4],
-                 "alpha=" + pseudo_names[5],
-                 "qper=" + pseudo_names[6],
-                 "qpar=" + pseudo_names[7],
-                 "diffractometertype", "E6C")
+                 ["mu=" + motor_names[0],  # motor role
+                  "omega=" + motor_names[1],
+                  "chi=" + motor_names[2],
+                  "phi=" + motor_names[3],
+                  "gamma=" + motor_names[4],
+                  "delta=" + motor_names[5],
+                  "h=" + pseudo_names[0],  # pseudo role
+                  "k=" + pseudo_names[1],
+                  "l=" + pseudo_names[2],
+                  "psi=" + pseudo_names[3],
+                  "q=" + pseudo_names[4],
+                  "alpha=" + pseudo_names[5],
+                  "qper=" + pseudo_names[6],
+                  "qpar=" + pseudo_names[7],
+                  "diffractometertype", "E6C"])
 
     controllers = motor_ctrl_name, hkl_ctrl_name
     elements = pseudo_names + motor_names
diff --git a/src/sardana/macroserver/macros/examples/motion.py b/src/sardana/macroserver/macros/examples/motion.py
new file mode 100755
index 0000000..e1b2e1d
--- /dev/null
+++ b/src/sardana/macroserver/macros/examples/motion.py
@@ -0,0 +1,56 @@
+##############################################################################
+##
+## This file is part of Sardana
+##
+## http://www.sardana-controls.org/
+##
+## Copyright 2011 CELLS / ALBA Synchrotron, Bellaterra, Spain
+##
+## Sardana is free software: you can redistribute it and/or modify
+## it under the terms of the GNU Lesser General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## Sardana is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public License
+## along with Sardana.  If not, see <http://www.gnu.org/licenses/>.
+##
+##############################################################################
+
+"""This module contains macros that demonstrate the usage of motion"""
+
+__all__ = ["move_async"]
+
+__docformat__ = 'restructuredtext'
+
+from sardana.macroserver.macro import *
+
+
+class move_async(Macro):
+    """A macro that executes an asynchronous movement of a motor. The movement
+    can be cancelled by a Ctrl-C signal.
+
+    This macro is part of the examples package. It was written for
+    demonstration purposes"""
+
+    param_def = [['moveable', Type.Moveable, None, 'moveable to be moved'],
+                 ['pos', Type.Float, None, 'target position'],
+                 ]
+
+    def run(self, moveable, pos):
+        try:
+            motion = self.getMotion([moveable])
+            self.info('initial position: %s' % motion.readPosition())
+            _id = motion.startMove([pos])
+            # Do whatever here (while the moveable is moving)
+            self.info('state: %s' % motion.readState())
+            # End Do whatever here
+        finally:
+            motion.waitMove(id=_id)
+            # this line will not be printed in case of abort (Ctrl-C)
+            # due to https://sourceforge.net/p/sardana/tickets/9/
+            self.info('final position: %s' % motion.readPosition())
\ No newline at end of file
diff --git a/src/sardana/macroserver/macros/examples/parameters.py b/src/sardana/macroserver/macros/examples/parameters.py
index b164a1c..8704eca 100644
--- a/src/sardana/macroserver/macros/examples/parameters.py
+++ b/src/sardana/macroserver/macros/examples/parameters.py
@@ -208,7 +208,7 @@ class twice(Macro):
 
     # uncomment the following lines as necessary. Otherwise you may delete them
     param_def = [ [ "value", Type.Float, 23, "value to be doubled" ] ]
-    result_def = [ [ "result", Type.Float, 23, "the double of the given value" ] ]
+    result_def = [ [ "result", Type.Float, None, "the double of the given value" ] ]
     #hints = {}
     #env = (,)
     
@@ -219,4 +219,4 @@ class twice(Macro):
     def run(self, n):
         ret = 2*n
         self.setData({'in':n, 'out':ret})
-        return ret
\ No newline at end of file
+        return ret
diff --git a/src/sardana/macroserver/macros/hkl.py b/src/sardana/macroserver/macros/hkl.py
index afdb968..2cde50e 100644
--- a/src/sardana/macroserver/macros/hkl.py
+++ b/src/sardana/macroserver/macros/hkl.py
@@ -27,6 +27,7 @@ import numpy as np
 
 from sardana.macroserver.macro import *
 from sardana.macroserver.macros.scan import aNscan
+from sardana.macroserver.msexception import UnknownEnv
 
 from taurus.core.util.log import Logger
 
@@ -171,9 +172,6 @@ class _diffrac:
         if mat:
             return regx.sub(repl, ch)
 
-# TODO: Revrite this macro in order to use events instead of polling to obtain 
-# the position updates. See umv macro as an example
-# TODO: H, K, L parameters should be of type float and not string
 class br(Macro, _diffrac):
     """Move the diffractometer to the reciprocal space coordinates given by 
     H, K and L. 
@@ -187,13 +185,16 @@ class br(Macro, _diffrac):
         ['L', Type.String, None, "L value"],
         ['AnglesIndex', Type.Integer, -1, "Angles index"],
         ['FlagNotBlocking', Type.Integer,  0,
-         "If 1 not block. Return without finish movement"]
+         "If 1 not block. Return without finish movement"],
+        ['FlagPrinting', Type.Integer,  0,
+         "If 1 printing. Used by ubr"]
     ]
 
-    def prepare(self, H, K, L, AnglesIndex, FlagNotBlocking):
+    def prepare(self, H, K, L, AnglesIndex, FlagNotBlocking, FlagPrinting):
         _diffrac.prepare(self)
 
-    def run(self, H, K, L, AnglesIndex, FlagNotBlocking):
+    def run(self, H, K, L, AnglesIndex, FlagNotBlocking, FlagPrinting):
+        h_idx = 0; k_idx = 1; l_idx = 2
 
         if AnglesIndex != -1:
             sel_tr = AnglesIndex
@@ -205,43 +206,42 @@ class br(Macro, _diffrac):
         if H in hkl_labels or K in hkl_labels or L in hkl_labels:
             try:
                 q_vector = self.getEnv('Q')
-                q_dict = {}
-                q_dict["H"] = q_vector[0]
-                q_dict["K"] = q_vector[1]
-                q_dict["L"] = q_vector[2]
-
+            except UnknownEnv:
+                self.error("Environment Q not defined. Run wh to define it")
+                return
+            try:
                 if H in hkl_labels:
-                    H = float(q_dict[H])
+                    H = float(q_vector[h_idx])
                 if K in hkl_labels:
-                    K = float(q_dict[K])
+                    K = float(q_vector[k_idx])
                 if L in hkl_labels:
-                    L = float(q_dict[L])
+                    L = float(q_vector[l_idx])
             except:
-                self.error("Environment Q not defined. Run wh to define it")
+                self.error("Wrong format of Q vector")
                 return
-
         hkl_values = [float(H), float(K), float(L)]
 
         self.diffrac.write_attribute("computetrajectoriessim", hkl_values)
 
         angles_list = self.diffrac.trajectorylist[sel_tr]
 
-        i = 0
-        for angle in self.angle_names:
-            angle_dev = self.getDevice(self.angle_device_names[angle])
-            angle_dev.write_attribute("Position", angles_list[i])
-            i = i + 1
-            self.checkPoint()
-
-        self.checkPoint()
-
         if FlagNotBlocking == 0:
-            self.execMacro('_blockprintmove', 0)
+            cmd = "mv"
+            for name, angle in zip(self.angle_names, angles_list):
+                cmd = cmd + " " + str(self.angle_device_names[name])
+                cmd = cmd + " " + str(angle)
+            if FlagPrinting == 1:
+                cmd = "u" + cmd
+            self.execMacro(cmd)
+        else:
+            for name, angle in zip(self.angle_names, angles_list):
+                angle_dev = self.getObj(self.angle_device_names[name])
+                angle_dev.write_attribute("Position", angle)
+
+        self.setEnv('Q', [hkl_values[h_idx], hkl_values[k_idx],
+                          hkl_values[l_idx], self.diffrac.WaveLength])
 
-        self.setEnv('Q', [hkl_values[0], hkl_values[1],
-                          hkl_values[2], self.diffrac.WaveLength])
 
-# TODO: hh, kk, ll parameters should be of type float and not string
 class ubr(Macro, _diffrac):
     """Move the diffractometer to the reciprocal space coordinates given by 
     H, K and L und update.
@@ -258,20 +258,8 @@ class ubr(Macro, _diffrac):
         _diffrac.prepare(self)
 
     def run(self, hh, kk, ll, AnglesIndex):
-
-        hkl_labels = ["H", "K", "L"]
-
-        if hh in hkl_labels or kk in hkl_labels or ll in hkl_labels:  # Needs to be checked also here
-            try:
-                q_vector = self.getEnv('Q')
-            except:
-                self.error("Environment Q not defined. Run wh to define it")
-                return
-
         if ll != "Not set":
-            br, pars = self.createMacro("br", hh, kk, ll, AnglesIndex, 1)
-            self.runMacro(br)
-            self.execMacro('_blockprintmove', 1)
+            self.execMacro("br", hh, kk, ll, AnglesIndex, 0, 1)
         else:
             self.output("usage:  ubr H K L [Trajectory]")
 
diff --git a/src/sardana/macroserver/macros/standard.py b/src/sardana/macroserver/macros/standard.py
index c8c72d4..d41aee7 100644
--- a/src/sardana/macroserver/macros/standard.py
+++ b/src/sardana/macroserver/macros/standard.py
@@ -472,6 +472,7 @@ class umv(Macro):
             posObj.subscribeEvent(self.positionChanged, motor)
 
     def run(self, motor_pos_list):
+        self.print_pos = True
         self.execMacro('mv', motor_pos_list)
         self.finish()
  
@@ -632,7 +633,7 @@ class ct(Macro):
         state, data = self.mnt_grp.count(integ_time)
 
         names, counts = [], []
-        for ch_info in self.mnt_grp.getChannelsInfo():
+        for ch_info in self.mnt_grp.getChannelsEnabledInfo():
             names.append('  %s' % ch_info.label)
             ch_data = data.get(ch_info.full_name)
             if ch_info.shape > [1]:
diff --git a/src/sardana/macroserver/macros/test/macroexecutor.py b/src/sardana/macroserver/macros/test/macroexecutor.py
index bf01c5b..39e43ac 100644
--- a/src/sardana/macroserver/macros/test/macroexecutor.py
+++ b/src/sardana/macroserver/macros/test/macroexecutor.py
@@ -295,7 +295,11 @@ class MacroExecutorFactory(Singleton):
         # For the moment I implement it by calling an internal member of
         # TaurusManager
         from taurus.core import TaurusManager
-        scheme = TaurusManager()._get_scheme(door_name)
+        try:
+            scheme = TaurusManager()._get_scheme(door_name)
+        except AttributeError:
+            # TODO: For Taurus 4 compatibility
+            scheme = TaurusManager().getScheme(door_name)
         #======================================================================
 
         if scheme == 'tango':
diff --git a/src/sardana/macroserver/msmacromanager.py b/src/sardana/macroserver/msmacromanager.py
index cc99d9c..b867538 100644
--- a/src/sardana/macroserver/msmacromanager.py
+++ b/src/sardana/macroserver/msmacromanager.py
@@ -54,7 +54,8 @@ from sardana.sardanautils import is_pure_str, is_non_str_seq
 from sardana.macroserver.msmanager import MacroServerManager
 from sardana.macroserver.msmetamacro import MACRO_TEMPLATE, MacroLibrary, \
     MacroClass, MacroFunction
-from sardana.macroserver.msparameter import ParamDecoder
+from sardana.macroserver.msparameter import ParamDecoder, FlatParamDecoder, \
+    WrongParam
 from sardana.macroserver.macro import Macro, MacroFunc
 from sardana.macroserver.msexception import UnknownMacroLibrary, \
     LibraryError, UnknownMacro, MissingEnv, AbortException, StopException, \
@@ -125,13 +126,20 @@ def is_macro(macro, abs_file=None, logger=None):
         return False
     return True
 
-def recur_map(fun, data):
+def recur_map(fun, data, keep_none=False):
     """Recursive map. Similar to map, but maintains the list objects structure
+
+    :param fun: <callable> the same purpose as in map function
+    :param data: <object> the same purpose as in map function
+    :param keep_none: <bool> keep None elements without applying fun
     """
     if hasattr(data, "__iter__"):
-        return [recur_map(fun, elem) for elem in data]
+        return [recur_map(fun, elem, keep_none) for elem in data]
     else:
-        return fun(data)
+        if keep_none is True and data is None:
+            return data
+        else:
+            return fun(data)
 
 
 class MacroManager(MacroServerManager):
@@ -674,7 +682,24 @@ class MacroManager(MacroServerManager):
         macro_meta = self.getMacro(macro_name)
         params_def = macro_meta.get_parameter()
         type_manager = door.type_manager
-        out_par_list = ParamDecoder(type_manager, params_def, raw_params)
+        try:
+            out_par_list = ParamDecoder(type_manager, params_def, raw_params)
+        except WrongParam, out_e:
+            # only if raw params are passed as a list e.g. using macro API
+            # execMacro("mv", mot01, 0.0) and parameters definition allows to
+            # decode it from a flat list we give it a try
+            if (isinstance(raw_params, list) and
+                FlatParamDecoder.isPossible(params_def)):
+                self.debug("Trying flat parameter decoder due to: %s" % out_e)
+                try:
+                    out_par_list = FlatParamDecoder(type_manager, params_def,
+                                                    raw_params)
+                except WrongParam, in_e:
+                    msg = ("Either of: %s or %s made it impossible to decode"
+                           " parameters" % (out_e.message, in_e.message))
+                    raise WrongParam, msg
+            else:
+                raise out_e
         return macro_meta, raw_params, out_par_list
 
     def strMacroParamValues(self, par_list):
@@ -954,25 +979,37 @@ class MacroExecutor(Logger):
            1. several parameters:
              1.1 executor.prepareMacro('ascan', 'th', '0', '100', '10', '1.0')
                  executor.prepareMacro('mv', [['th', '0']])
+                 executor.prepareMacro('mv', 'th', '0') # backwards compatibility - see note
              1.2 executor.prepareMacro('ascan', 'th', 0, 100, 10, 1.0)
                  executor.prepareMacro('mv', [['th', 0]])
+                 executor.prepareMacro('mv', 'th', 0) # backwards compatibility - see note
              1.3 th = self.getObj('th');
                  executor.prepareMacro('ascan', th, 0, 100, 10, 1.0)
                  executor.prepareMacro('mv', [[th, 0]])
+                 executor.prepareMacro('mv', th, 0) # backwards compatibility - see note
            2. a sequence of parameters:
               2.1 executor.prepareMacro(['ascan', 'th', '0', '100', '10', '1.0')
                   executor.prepareMacro(['mv', [['th', '0']]])
+                  executor.prepareMacro(['mv', 'th', '0']) # backwards compatibility - see note
               2.2 executor.prepareMacro(('ascan', 'th', 0, 100, 10, 1.0))
                   executor.prepareMacro(['mv', [['th', 0]]])
+                  executor.prepareMacro(['mv', 'th', 0]) # backwards compatibility - see note
               2.3 th = self.getObj('th');
                   executor.prepareMacro(['ascan', th, 0, 100, 10, 1.0])
                   executor.prepareMacro(['mv', [[th, 0]]])
+                  executor.prepareMacro(['mv', th, 0]) # backwards compatibility - see note
            3. a space separated string of parameters (this is not compatible
               with multiple or nested repeat parameters, furthermore the repeat
               parameter must be the last one):
               executor.prepareMacro('ascan th 0 100 10 1.0')
               executor.prepareMacro('mv %s 0' % motor.getName())
 
+        .. note:: From Sardana 2.0 the repeat parameter values must be passed
+            as lists of items. An item of a repeat parameter containing more
+            than one member is a list. In case when a macro defines only one
+            repeat parameter and it is the last parameter, for the backwards
+            compatibility reasons, the plain list of items' members is allowed.
+
         :param pars: the command parameters as explained above
         :param opts: keyword optional parameters for prepare
         :return: a tuple of two elements: macro object, the result of preparing the macro
@@ -993,7 +1030,8 @@ class MacroExecutor(Logger):
         # or args = ('mv', [[mot01, 0], [mot02, 0]])
 
         # in case parameters were passed as objects cast them to strings
-        pars = recur_map(str, pars)
+        # but maintain None's to be able to discover missing params
+        pars = recur_map(str, pars, keep_none=True)
 
         meta_macro, _, macro_params = self._decodeMacroParameters(pars)
         macro_name = meta_macro.name
@@ -1210,7 +1248,7 @@ class MacroExecutor(Logger):
         except Exception, err:
             exc_info = sys.exc_info()
             exp_pars = {'type'      : err.__class__.__name__,
-                        'msg'       : err.args[0],
+                        'msg'       : str(err),
                         'args'      : err.args,
                         'traceback' : traceback.format_exc() }
             macro_exp = MacroServerException(exp_pars)
diff --git a/src/sardana/macroserver/msoptions.py b/src/sardana/macroserver/msoptions.py
index 0d3b099..def2573 100644
--- a/src/sardana/macroserver/msoptions.py
+++ b/src/sardana/macroserver/msoptions.py
@@ -44,6 +44,7 @@ class ViewOption(object):
         'ShowDial' : True,
         'ShowCtrlAxis' : False,
         'PosFormat': -1,
+        'OutputBlock': False
     }
 
     @classmethod
diff --git a/src/sardana/macroserver/msparameter.py b/src/sardana/macroserver/msparameter.py
index a888582..d608670 100644
--- a/src/sardana/macroserver/msparameter.py
+++ b/src/sardana/macroserver/msparameter.py
@@ -26,13 +26,15 @@
 """This module contains the definition of the macroserver parameters for
 macros"""
 
-__all__ = ["WrongParam", "MissingParam", "UnknownParamObj", "WrongParamType",
-           "TypeNames", "Type", "ParamType", "ParamRepeat", "ElementParamType",
-           "ElementParamInterface", "AttrParamType", "AbstractParamTypes",
-           "ParamDecoder"]
+__all__ = ["WrongParam", "MissingParam", "SupernumeraryParam",
+           "UnknownParamObj", "WrongParamType", "MissingRepeat",
+           "SupernumeraryRepeat", "TypeNames", "Type", "ParamType",
+           "ParamRepeat", "ElementParamType", "ElementParamInterface",
+           "AttrParamType", "AbstractParamTypes", "ParamDecoder"]
 
 __docformat__ = 'restructuredtext'
 
+from copy import deepcopy
 from lxml import etree
 
 from taurus.core.util.containers import CaselessDict
@@ -57,6 +59,13 @@ class MissingParam(WrongParam):
         self.type = 'Missing parameter'
 
 
+class SupernumeraryParam(WrongParam):
+
+    def __init__(self, *args):
+        WrongParam.__init__(self, *args)
+        self.type = 'Supernumerary parameter'
+
+
 class UnknownParamObj(WrongParam):
 
     def __init__(self, *args):
@@ -71,6 +80,20 @@ class WrongParamType(WrongParam):
         self.type = 'Unknown parameter type'
 
 
+class MissingRepeat(WrongParam):
+
+    def __init__(self, *args):
+        WrongParam.__init__(self, *args)
+        self.type = 'Missing repeat'
+
+
+class SupernumeraryRepeat(WrongParam):
+
+    def __init__(self, *args):
+        WrongParam.__init__(self, *args)
+        self.type = 'Supernumerary repeat'
+
+
 class TypeNames:
     """Class that holds the list of registered macro parameter types"""
 
@@ -321,7 +344,9 @@ class ParamDecoder:
         """Decode raw representation of parameters to parameters as passed
         to the prepare or run methods.
         """
-        raw_params = self.raw_params
+        # make a copy since in case of XML it could be necessary to modify
+        # the raw_params - filter out elements different than params
+        raw_params = deepcopy(self.raw_params)
         params_def = self.params_def
         # ignore other tags than "param" and "paramRepeat"
         # e.g. sequencer may create tags like "hookPlace"
@@ -331,6 +356,12 @@ class ParamDecoder:
                     raw_params.remove(raw_param)
 
         params = []
+        # check if too many parameters were passed
+        len_params_def = len(params_def)
+        if len(raw_params) > len_params_def:
+            msg = ("%r are supernumerary with respect to definition" %
+                   raw_params[len_params_def:])
+            raise SupernumeraryParam, msg
         # iterate over definition since missing values may just mean using
         # the default values
         for i, param_def in enumerate(params_def):
@@ -368,6 +399,9 @@ class ParamDecoder:
                     value = param_def['default_value']
                 if value is None:
                     raise MissingParam, "'%s' not specified" % name
+                else:
+                    # cast to sting to fulfill with ParamType API
+                    value = str(value)
                 param = param_type.getObj(value)
             except ValueError, e:
                 raise WrongParamType, e.message
@@ -402,11 +436,11 @@ class ParamDecoder:
         if min_rep and len_rep < min_rep:
             msg = 'Found %d repetitions of param %s, min is %d' % \
                   (len_rep, name, min_rep)
-            raise RuntimeError, msg
+            raise MissingRepeat, msg
         if  max_rep and len_rep > max_rep:
             msg = 'Found %d repetitions of param %s, max is %d' % \
                   (len_rep, name, max_rep)
-            raise RuntimeError, msg
+            raise SupernumeraryRepeat, msg
         for raw_repeat in raw_param_repeat:
             if len(param_type) > 1:
                 repeat = []
@@ -428,3 +462,120 @@ class ParamDecoder:
 
     def __getattr__(self, name):
         return getattr(self.params, name)
+
+
+class FlatParamDecoder:
+    """Parameter decoder useful for macros with only one repeat parameter
+    located at the very last place. It requires that the raw parameters are
+    passed as a flat list of strings.
+    """
+    def __init__(self, type_manager, params_def, raw_params):
+        self.type_manager = type_manager
+        self.params_def = params_def
+        self.raw_params = raw_params
+        self.params = None
+        if not self.isPossible(params_def):
+            msg = ("%s parameter definition is not compatible with"
+                   " FlatParamDecoder" % params_def)
+            raise AttributeError, msg
+        self.decode()
+
+    @staticmethod
+    def isPossible(params_def):
+        for param_def in params_def:
+            param_type = param_def["type"]
+            if isinstance(param_type, list):
+                if param_def != params_def[-1]:
+                    # repeat parameter is not the last one
+                    # it won't be possible to decode it
+                    return False
+                else:
+                    for sub_param_def in param_type:
+                        if isinstance(sub_param_def, list):
+                            # nested repeat parameter
+                            # it won't be possible to decode it
+                            return False
+        return True
+
+    def decode(self):
+        params_def = self.params_def
+        raw_params = self.raw_params
+        _, self.params = self.decodeNormal(raw_params, params_def)
+        return self.params
+
+    def decodeNormal(self, raw_params, params_def):
+        str_len = len(raw_params)
+        obj_list = []
+        str_idx = 0
+        for i, par_def in enumerate(params_def):
+            name = par_def['name']
+            type_class = par_def['type']
+            def_val = par_def['default_value']
+            if str_idx == str_len:
+                if def_val is None:
+                    if not isinstance(type_class, list):
+                        raise MissingParam, "'%s' not specified" % name
+                    elif isinstance(type_class, list):
+                        min_rep = par_def['min']
+                        if min_rep > 0:
+                            msg = "'%s' demands at least %d values" %\
+                                  (name, min_rep)
+                            raise WrongParam, msg
+                if not def_val is None:
+                    new_obj = def_val
+            else:
+                if isinstance(type_class, list):
+                    data = self.decodeRepeat(raw_params[str_idx:], par_def)
+                    dec_token, new_obj = data
+                else:
+                    type_manager = self.type_manager
+                    type_name = type_class
+                    type_class = type_manager.getTypeClass(type_name)
+                    par_type = type_manager.getTypeObj(type_name)
+                    par_str = raw_params[str_idx]
+                    try:
+                        val = par_type.getObj(par_str)
+                    except ValueError, e:
+                        raise WrongParamType, e.message
+                    except UnknownParamObj, e:
+                        raise WrongParam, e.message
+                    if val is None:
+                        msg = 'Could not create %s parameter "%s" for "%s"' % \
+                              (par_type.getName(), name, par_str)
+                        raise WrongParam, msg
+                    dec_token = 1
+                    new_obj = val
+                str_idx += dec_token
+            obj_list.append(new_obj)
+        return str_idx, obj_list
+
+    def decodeRepeat(self, raw_params, par_def):
+        name = par_def['name']
+        param_def = par_def['type']
+        min_rep = par_def['min']
+        max_rep = par_def['max']
+
+        dec_token = 0
+        obj_list = []
+        rep_nr = 0
+        while dec_token < len(raw_params):
+            if max_rep is not None and rep_nr == max_rep:
+                break
+            new_token, new_obj_list = self.decodeNormal(raw_params[dec_token:],
+                                                        param_def)
+            dec_token += new_token
+            if len(new_obj_list) == 1:
+                new_obj_list = new_obj_list[0]
+            obj_list.append(new_obj_list)
+            rep_nr += 1
+        if rep_nr < min_rep:
+            msg = 'Found %d repetitions of param %s, min is %d' % \
+                  (rep_nr, name, min_rep)
+            raise MissingRepeat, msg
+        return dec_token, obj_list
+
+    def getParamList(self):
+        return self.params
+
+    def __getattr__(self, name):
+        return getattr(self.params, name)
diff --git a/src/sardana/macroserver/recorders/output.py b/src/sardana/macroserver/recorders/output.py
index a25b898..b030f36 100644
--- a/src/sardana/macroserver/recorders/output.py
+++ b/src/sardana/macroserver/recorders/output.py
@@ -124,7 +124,7 @@ class JsonRecorder(DataRecorder):
 class OutputRecorder(DataRecorder):
 
     def __init__(self, stream, cols=None, number_fmt='%8.4f', col_width=8,
-                 col_sep='  ', **pars):
+                 col_sep='  ', output_block=False, **pars):
         DataRecorder.__init__(self, **pars)
         self._stream = stream
         if not number_fmt.startswith('%'):
@@ -140,6 +140,7 @@ class OutputRecorder(DataRecorder):
         else:
             cols = None
         self._columns = cols
+        self._output_block = output_block
 
     def _startRecordList(self, recordlist):
         starttime = recordlist.getEnvironValue('starttime').ctime()
@@ -259,7 +260,11 @@ class OutputRecorder(DataRecorder):
             cells.append(cell)
         scan_line = self._col_sep.join(cells)
 
-        self._stream.output(scan_line)
+        if self._output_block:
+            self._stream.outputBlock(scan_line)
+        else:
+            self._stream.output(scan_line)
+
         self._stream.flushOutput()
 
     def _addCustomData(self, value, name, **kwargs):
diff --git a/src/sardana/macroserver/scan/gscan.py b/src/sardana/macroserver/scan/gscan.py
index 8de7866..9ab29dc 100644
--- a/src/sardana/macroserver/scan/gscan.py
+++ b/src/sardana/macroserver/scan/gscan.py
@@ -370,14 +370,23 @@ class GScan(Logger):
 
     def _getOutputRecorder(self):
         cols = None
+        output_block = False
         try:
             cols = self.macro.getEnv('OutputCols')
         except InterruptException:
             raise
         except:
             pass
+
+        try:
+            output_block = self.macro.getViewOption('OutputBlock')
+        except InterruptException:
+            raise
+        except:
+            pass
+
         return self._rec_manager.getRecorderClass("OutputRecorder")(
-            self.macro, cols=cols, number_fmt='%g')
+            self.macro, cols=cols, number_fmt='%g', output_block=output_block)
 
     def _getFileRecorders(self):
         macro = self.macro
@@ -558,7 +567,7 @@ class GScan(Logger):
         instrument = master['instrument']
 
         #add channels from measurement group
-        channels_info = self.measurement_group.getChannelsInfo()
+        channels_info = self.measurement_group.getChannelsEnabledInfo()
         counters = []
         for ci in channels_info:
             instrument = ci.instrument or ''
@@ -592,7 +601,11 @@ class GScan(Logger):
                                 data_units=ci.unit)
             data_desc.append(column)
             counters.append(column.name)
-        counters.remove(master['full_name'])
+        try:
+            counters.remove(master['full_name'])
+        except ValueError:
+            # timer may be disabled
+            pass
         env['counters'] = counters
 
         for extra_column in self._extra_columns:
diff --git a/src/sardana/pool/pool.py b/src/sardana/pool/pool.py
index 9ef4f35..e4cdba1 100644
--- a/src/sardana/pool/pool.py
+++ b/src/sardana/pool/pool.py
@@ -35,7 +35,12 @@ __docformat__ = 'restructuredtext'
 import os.path
 import logging.handlers
 
-from taurus.core.taurusvalidator import AttributeNameValidator
+try:
+    from taurus.core.taurusvalidator import AttributeNameValidator as\
+        TangoAttributeNameValidator
+except ImportError:
+    #TODO: For Taurus 4 compatibility
+    from taurus.core.tango.tangovalidator import TangoAttributeNameValidator
 from taurus.core.util.containers import CaselessDict
 
 from sardana import InvalidId, ElementType, TYPE_ACQUIRABLE_ELEMENTS, \
@@ -515,7 +520,7 @@ class Pool(PoolContainer, PoolObject, SardanaElementManager, SardanaIDManager):
             if type(elem_id) is int:
                 self.pool.get_element(id=elem_id)
             else:
-                tg_attr_validator = AttributeNameValidator()
+                tg_attr_validator = TangoAttributeNameValidator()
                 params = tg_attr_validator.getParams(elem_id)
                 if params is None:
                     raise Exception("Invalid channel name %s" % elem_id)
diff --git a/src/sardana/pool/poolacquisition.py b/src/sardana/pool/poolacquisition.py
index 9833ce3..2ee1061 100644
--- a/src/sardana/pool/poolacquisition.py
+++ b/src/sardana/pool/poolacquisition.py
@@ -454,20 +454,18 @@ class Pool0DAcquisition(PoolAction):
                 return True
 
     def action_loop(self):
-        i = 0
-
         states, values = {}, {}
         for element in self._channels:
             states[element] = None
             values[element] = None
 
         nap = self._acq_sleep_time
-        while not (self._stopped or self._aborted):
+        while True:
             self.read_value(ret=values)
             for acquirable, value in values.items():
                 acquirable.put_value(value)
-
-            i += 1
+            if self._stopped or self._aborted:
+                break
             time.sleep(nap)
 
         with ActionContext(self):
diff --git a/src/sardana/pool/poolbasegroup.py b/src/sardana/pool/poolbasegroup.py
index 37ff0aa..8986730 100644
--- a/src/sardana/pool/poolbasegroup.py
+++ b/src/sardana/pool/poolbasegroup.py
@@ -30,7 +30,12 @@ __all__ = ["PoolBaseGroup"]
 
 __docformat__ = 'restructuredtext'
 
-from taurus.core.taurusvalidator import AttributeNameValidator
+try:
+    from taurus.core.taurusvalidator import AttributeNameValidator as\
+        TangoAttributeNameValidator
+except ImportError:
+    #TODO: For Taurus 4 compatibility
+    from taurus.core.tango.tangovalidator import TangoAttributeNameValidator
 
 from sardana import State, ElementType, TYPE_PHYSICAL_ELEMENTS
 from sardana.pool.poolexternal import PoolExternalObject
@@ -168,7 +173,7 @@ class PoolBaseGroup(PoolContainer):
             # a tango channel or non internal element (ex: ioregister or motor
             # in measurement group)
             if not internal:
-                validator = AttributeNameValidator()
+                validator = TangoAttributeNameValidator()
                 params = validator.getParams(user_element_id)
                 params['pool'] = self._get_pool()
                 user_element = PoolExternalObject(**params)
diff --git a/src/sardana/pool/poolcontrollers/HklPseudoMotorController.py b/src/sardana/pool/poolcontrollers/HklPseudoMotorController.py
index 0fd2162..ef3b85f 100644
--- a/src/sardana/pool/poolcontrollers/HklPseudoMotorController.py
+++ b/src/sardana/pool/poolcontrollers/HklPseudoMotorController.py
@@ -469,6 +469,9 @@ class DiffracBasis(PseudoMotorController):
             elif engine_name == "eulerians":
                 values = [pseudo_pos[8], pseudo_pos[9], pseudo_pos[10]]
 
+        # getWavelength updates wavelength in the library in case automatic
+        # energy update is set. Needed before computing trajectories.
+
         self.getWavelength()
 
         solutions = self._solutions(values, curr_physical_pos)
@@ -484,6 +487,9 @@ class DiffracBasis(PseudoMotorController):
         # physical values are not equal to the expected len of the
         # geometry axes.
         
+        # getWavelength updates wavelength in the library in case automatic
+        # energy update is set. Needed before computing trajectories.
+
         self.getWavelength()
             
 
@@ -748,6 +754,11 @@ class DiffracBasis(PseudoMotorController):
         #         (len(values),
         #          len(self.engine.pseudo_axis_names_get()),
         #          self.engine.name_get())
+        # getWavelength updates wavelength in the library in case automatic
+        # energy update is set. Needed before computing trajectories.
+     
+        self.getWavelength()
+            
         curr_physical_pos = self.geometry.axis_values_get(USER)
         solutions = self._solutions(values, curr_physical_pos)
         self.trajectorylist = [item.geometry_get().axis_values_get(USER)
@@ -960,9 +971,13 @@ class DiffracBasis(PseudoMotorController):
                 geometry.axis_values_set(values[6:], USER)
                 reflection.geometry_set(geometry)
 
-    def setLoadCrystal(self, value):  # value: complete path of the file with the crystal to set
+    def setLoadCrystal(self, value):
+        """Load crystal information from a file. Ignore wavelength information.
+
+        :param value: complete path of the file with the crystal to set
+        :type value: string
+        """
         # Read the file
-        
         with open(value, 'r') as crystal_file:
             self._loadcrystal = value
 
@@ -981,10 +996,6 @@ class DiffracBasis(PseudoMotorController):
                     # Remove all reflections from crystal (there should not be any ... but just in case)
                     for ref in self.sample.reflections_get():
                         self.sample.del_reflection(ref)
-                elif line.find("Wavelength") != -1:
-                    line = line.replace(" ", "")
-                    wavelength = float(line.split("Wavelength",1)[1]) # The value will be set after creating the new geometry with the reflections
-                    self.geometry.wavelength_set(wavelength, USER)
                 elif line.find("A") != -1 and line.find("B") != -1 and line.find("C") != -1:
                     par_line = line.split(" ")
                     avalue = float(par_line[1])
@@ -1323,7 +1334,10 @@ class DiffracBasis(PseudoMotorController):
         self._autoenergyupdate = value
 
     def setComputeHKL(self, value):
-              
+         
+        # getWavelength updates wavelength in the library in case automatic
+        # energy update is set. Needed before computing trajectories.
+     
         self.getWavelength()
             
 
diff --git a/src/sardana/pool/poolmeasurementgroup.py b/src/sardana/pool/poolmeasurementgroup.py
index 25cab6d..7e9269e 100644
--- a/src/sardana/pool/poolmeasurementgroup.py
+++ b/src/sardana/pool/poolmeasurementgroup.py
@@ -30,7 +30,12 @@ __all__ = ["PoolMeasurementGroup"]
 
 __docformat__ = 'restructuredtext'
 
-from taurus.core.taurusvalidator import AttributeNameValidator
+try:
+    from taurus.core.taurusvalidator import AttributeNameValidator as\
+        TangoAttributeNameValidator
+except ImportError:
+    #TODO: For Taurus 4 compatibility
+    from taurus.core.tango.tangovalidator import TangoAttributeNameValidator
 
 from sardana import State, ElementType, \
     TYPE_EXP_CHANNEL_ELEMENTS, TYPE_TIMERABLE_ELEMENTS
@@ -114,21 +119,9 @@ class PoolMeasurementGroup(PoolGroupElement):
         acq_name = "%s.Acquisition" % self._name
         return PoolAcquisition(self, acq_name)
 
-    def _calculate_element_state(self, elem, elem_state_info):
-        if elem.get_type() == ElementType.ZeroDExpChannel:
-            if elem_state_info[0] == State.Moving:
-                elem_state_info = State.On, elem_state_info[1]
-        return PoolGroupElement._calculate_element_state(self, elem,
-                                                         elem_state_info)
-
     def on_element_changed(self, evt_src, evt_type, evt_value):
         name = evt_type.name
         if name == 'state':
-            if evt_src.get_type() == ElementType.ZeroDExpChannel:
-                # 0D channels are "passive", which means they cannot contribute
-                # to set the measurement group into a moving state
-                if evt_value in (State.On, State.Moving):
-                    return
             state, status = self._calculate_states()
             self.set_state(state, propagate=2)
             self.set_status("\n".join(status))
@@ -368,7 +361,7 @@ class PoolMeasurementGroup(PoolGroupElement):
                 unit_data['channels'] = channels = {}
                 for ch_name, ch_data in u_data['channels'].items():
                     if external:
-                        validator = AttributeNameValidator()
+                        validator = TangoAttributeNameValidator()
                         params = validator.getParams(ch_data['full_name'])
                         params['pool'] = self.pool
                         channel = PoolExternalObject(**params)
diff --git a/src/sardana/pool/poolzerodexpchannel.py b/src/sardana/pool/poolzerodexpchannel.py
index 95da098..35c4168 100644
--- a/src/sardana/pool/poolzerodexpchannel.py
+++ b/src/sardana/pool/poolzerodexpchannel.py
@@ -80,14 +80,22 @@ class SumAccumulation(BaseAccumulation):
         self.sum = 0.0
 
     def update_value(self, value, timestamp):
-        self.sum += value
+        if not value is None:
+            self.sum += value
+            self.value = self.sum
 
 
 class AverageAccumulation(SumAccumulation):
 
+    def clear(self):
+        SumAccumulation.clear(self)
+        self.nb_valid_points = 0
+
     def update_value(self, value, timestamp):
         SumAccumulation.update_value(self, value, timestamp)
-        self.value = self.sum / self.nb_points
+        if not value is None:
+            self.nb_valid_points += 1
+            self.value = self.sum / self.nb_valid_points
 
 
 class IntegralAccumulation(BaseAccumulation):
@@ -152,7 +160,8 @@ class Value(SardanaAttribute):
     def _get_value(self):
         value = self._accumulation.value
         if value is None:
-            raise Exception("Value not available: no acquisition done so far!")
+            raise Exception("Value not available: no successful acquisition"
+                            " done so far!")
         return value
 
     def get_value_buffer(self):
diff --git a/src/sardana/release.py b/src/sardana/release.py
index 29fdf54..681a7b2 100644
--- a/src/sardana/release.py
+++ b/src/sardana/release.py
@@ -49,7 +49,7 @@ name = 'sardana'
 #: the new substring. We have to avoid using either dashes or underscores,
 #: because bdist_rpm does not accept dashes (an RPM) convention, and
 #: bdist_deb does not accept underscores (a Debian convention).
-version_info = (2, 0, 0, 'rc', 0)
+version_info = (2, 1, 0, 'rc', 0)
 version = '.'.join(map(str, version_info[:3]))
 revision = str(version_info[4])
 
diff --git a/src/sardana/requirements.py b/src/sardana/requirements.py
index f8e8de2..09db0e3 100644
--- a/src/sardana/requirements.py
+++ b/src/sardana/requirements.py
@@ -77,6 +77,9 @@ def check_requirements(exec_name=None):
         print "%s requires PyTango %s. Installed version is %s" % (exec_name, pytangover_str_, pytangover_str)
         sys.exit(-1)
 
+    # TODO: add itango as runtime dependency of spock
+    # now it is not possible because itango does not provide info about its version
+
     taurusver = None
     try:
         import taurus
diff --git a/src/sardana/spock/ipython_00_10/genutils.py b/src/sardana/spock/ipython_00_10/genutils.py
index 4f27ffc..e1ec926 100644
--- a/src/sardana/spock/ipython_00_10/genutils.py
+++ b/src/sardana/spock/ipython_00_10/genutils.py
@@ -59,7 +59,7 @@ import imp
 import IPython
 import IPython.genutils
 import PyTango
-import PyTango.ipython
+import itango
 
 from taurus.core.taurushelper import Factory
 from taurus.core.util.codecs import CodecFactory
@@ -78,6 +78,8 @@ requirements = {
     "IPython"     : ("0.10.0", "0.10.0"),
     "Python"      : ("2.6.0", "2.6.0"),
     "PyTango"     : ("7.1.2", "7.2.0"),
+    # for the moment just for reference since itango does not provide version
+    "itango"      : ("0.1.4", "0.1.4"),
     "taurus.core" : ("2.0.0", "2.1.0")
 }
 
@@ -193,8 +195,8 @@ def get_python_version_number():
 
 def get_ipython_dir():
     """Find the ipython local directory. Usually is <home>/.ipython"""
-    if hasattr(PyTango.ipython, "get_ipython_dir"):
-        return PyTango.ipython.get_ipython_dir()
+    if hasattr(itango, "get_ipython_dir"):
+        return itango.get_ipython_dir()
     
     if hasattr(IPython.iplib, 'get_ipython_dir'):
         # Starting from ipython 0.9 they hadded this method
@@ -215,8 +217,8 @@ def get_ipython_dir():
 
 def get_ipython_profiles():
     """Helper function to find all ipython profiles"""
-    if hasattr(PyTango.ipython, "get_ipython_profiles"):
-        return PyTango.ipython.get_ipython_profiles()
+    if hasattr(itango, "get_ipython_profiles"):
+        return itango.get_ipython_profiles()
 
     ret = []
     ipydir = get_ipython_dir()
@@ -510,6 +512,12 @@ def check_requirements():
             errMsg += "Current version is unknown (most surely too old)\n"
         errPyTango = True
 
+    # TODO: verify the version whenever itango starts to provide it
+    try:
+        import itango
+    except ImportError:
+        errMsg += "Spock needs itango version >= 0.1.4. No itango installation found\n"
+
     if currTaurusCore is None:
         errMsg += "Spock needs taurus.core version >= %s. No taurus.core installation found\n" % requirements["taurus.core"][0]
         errTaurusCore = True
@@ -550,7 +558,8 @@ def _get_dev(dev_type):
         return ret
     
     dev_obj_name = '%s_NAME' % dev_type
-    dev_name = ip.user_ns[dev_obj_name]
+    # TODO: For Taurus 4 compatibility
+    dev_name = "tango://%s" % ip.user_ns[dev_obj_name]
     factory = Factory()
     dev_obj = factory.getDevice(dev_name)
     ip.user_ns[dev_type] = PyTango.DeviceProxy(dev_name) 
@@ -956,7 +965,7 @@ def init_post_spock(ip):
     
 def init_spock(ip, macro_server, door):
     init_pre_spock(ip, macro_server, door)
-    PyTango.ipython.init_ipython(ip)
+    itango.init_ipython(ip)
     init_post_spock(ip)
 
 
diff --git a/src/sardana/spock/ipython_00_11/genutils.py b/src/sardana/spock/ipython_00_11/genutils.py
index 823bd79..49ad81d 100644
--- a/src/sardana/spock/ipython_00_11/genutils.py
+++ b/src/sardana/spock/ipython_00_11/genutils.py
@@ -88,6 +88,8 @@ requirements = {
     "IPython"     : ("0.11.0", "0.12.0"),
     "Python"      : ("2.6.0", "2.6.0"),
     "PyTango"     : ("7.2.0", "7.2.3"),
+    # for the moment just for reference since itango does not provide version
+    "itango"      : ("0.1.4", "0.1.4"),
     "taurus.core" : ("3.0.0", "3.0.0")
 }
 
@@ -471,6 +473,12 @@ def check_requirements():
             errMsg += "Current version is unknown (most surely too old)\n"
         errPyTango = True
 
+    # TODO: verify the version whenever itango starts to provide it
+    try:
+        import itango
+    except ImportError:
+        errMsg += "Spock needs itango version >= 0.1.4. No itango installation found\n"
+
     if currTaurusCore is None:
         errMsg += "Spock needs taurus.core version >= %s. No taurus.core installation found\n" % requirements["taurus.core"][0]
         errTaurusCore = True
@@ -519,7 +527,8 @@ def _get_dev(dev_type):
     if hasattr(spock_config, taurus_dev_var):
         taurus_dev = getattr(spock_config, taurus_dev_var)
     if taurus_dev is None:
-        dev_name = getattr(spock_config, dev_type + '_name')
+        # TODO: For Taurus 4 compatibility
+        dev_name = "tango://%s" % getattr(spock_config, dev_type + '_name')
         factory = Factory()
         taurus_dev = factory.getDevice(dev_name)
         import PyTango
@@ -593,19 +602,9 @@ def unexpose_variable(name):
     user_ns = get_shell().user_ns
     del user_ns[name]
 
-def create_spock_profile(userdir, dft_profile, profile, door_name=None):
-    """Create a profile file from a profile template file """
-    if not os.path.isdir(userdir):
-        ProfileDir.create_profile_dir(userdir)
-    p_dir = ProfileDir.create_profile_dir_by_name(userdir, profile)
+def _create_config_file(location, door_name=None):
     config_file_name = BaseIPythonApplication.config_file_name.default_value
-    abs_config_file_name = os.path.join(p_dir.location, config_file_name)
-    create_config = True
-    if os.path.isfile(abs_config_file_name):
-        create_config = ask_yes_no("Spock configuration file already exists. "\
-                                   "Do you wish to replace it?", default='y')
-    if not create_config:
-        return
+    abs_config_file_name = os.path.join(location, config_file_name)
 
     src_data = """\
 \"\"\"Settings for Spock session\"\"\"
@@ -617,7 +616,8 @@ def create_spock_profile(userdir, dft_profile, profile, door_name=None):
 # door_name = {door_name}
 #
 
-import PyTango.ipython
+import itango
+
 import sardana.spock.genutils
 from sardana.spock.config import Spock
 
@@ -636,7 +636,7 @@ config.IPKernelApp.pylab = 'inline'
     # Discover door name
     #
     if door_name is None:
-        door_name = get_device_from_user("Door", profile)
+        door_name = get_device_from_user("Door")
     else:
         full_door_name, door_name, _ = from_name_to_tango(door_name)
         door_name = full_door_name
@@ -650,7 +650,7 @@ config.IPKernelApp.pylab = 'inline'
                                 macroserver_name=ms_name,
                                 door_name=door_name)
 
-    sys.stdout.write('Storing %s in %s... ' % (config_file_name, p_dir.location))
+    sys.stdout.write('Storing %s in %s... ' % (config_file_name, location))
     sys.stdout.flush()
 
 
@@ -659,18 +659,49 @@ config.IPKernelApp.pylab = 'inline'
         f.close()
     sys.stdout.write(MSG_DONE + '\n')
 
-def check_for_upgrade(ipy_profile_file, ipythondir, session, profile):
-    # Check if the current profile is up to date with the spock version
+def create_spock_profile(userdir, profile, door_name=None):
+    """Create spock profile directory and configuration file from a template
+    file
+
+    :param userdir: directory where the spock profile will be created
+    :param profile: profile name
+    :param door_name: door name, if None, user will be asked for the door name
+    """
+
+    if not os.path.isdir(userdir):
+        ProfileDir.create_profile_dir(userdir)
+    p_dir = ProfileDir.create_profile_dir_by_name(userdir, profile)
+    ipy_profile_dir = p_dir.location
+
+    _create_config_file(ipy_profile_dir)
+
+def upgrade_spock_profile(ipy_profile_dir, door_name):
+    """Upgrade spock profile by recreating configuration file from scratch
+
+    :param ipy_profile_dir: directory with the spock profile
+    :param door_name: door name
+    """
+    _create_config_file(ipy_profile_dir, door_name)
+
+def check_for_upgrade(ipy_profile_dir):
+    """Check if the current profile is up to date with the spock version
+
+    :param ipy_profile_dir: directory with the spock profile
+    """
     spock_profile_ver_str = '0.0.0'
     door_name = None
 
+    config_file_name = BaseIPythonApplication.config_file_name.default_value
+    abs_config_file_name = os.path.join(ipy_profile_dir, config_file_name)
+
     # search for version and door inside the ipy_profile file
-    for i, line in enumerate(ipy_profile_file):
-        if i > 20 : break; # give up after 20 lines
-        if line.startswith('# spock_creation_version = '):
-            spock_profile_ver_str = line[line.index('=')+1:].strip()
-        if line.startswith('# door_name = '):
-            door_name = line[line.index('=')+1:].strip()
+    with file(abs_config_file_name, "r") as ipy_config_file:
+        for i, line in enumerate(ipy_config_file):
+            if i > 20 : break; # give up after 20 lines
+            if line.startswith('# spock_creation_version = '):
+                spock_profile_ver_str = line[line.index('=')+1:].strip()
+            if line.startswith('# door_name = '):
+                door_name = line[line.index('=')+1:].strip()
 
     # convert version from string to numbers
     spocklib_ver = translate_version_str2int(release.version)
@@ -695,7 +726,7 @@ def check_for_upgrade(ipy_profile_file, ipythondir, session, profile):
     prompt = 'Do you wish to upgrade now (warn: this will shutdown the current spock session) ([y]/n)? '
     r = raw_input(prompt) or 'y'
     if r.lower() == 'y':
-        create_spock_profile(ipythondir, session, profile, door_name)
+        upgrade_spock_profile(ipy_profile_dir, door_name)
         sys.exit(0)
 
 def get_args(argv):
@@ -729,7 +760,7 @@ def get_args(argv):
                      'one now ([y]/n)? ' % profile
             r = raw_input(prompt) or 'y'
         if r.lower() == 'y':
-            create_spock_profile(ipython_dir, session, profile)
+            create_spock_profile(ipython_dir, profile)
         else:
             sys.stdout.write('No spock door extension profile was created. Starting normal spock...\n')
             sys.stdout.flush()
@@ -895,7 +926,7 @@ object?   -> Details about 'object'. ?object also works, ?? prints more.
     # ------------------------------------
     i_app = config.BaseIPythonApplication
     extensions = getattr(i_app, 'extensions', [])
-    extensions.extend(["PyTango.ipython", "sardana.spock"])
+    extensions.extend(["itango", "sardana.spock"])
     i_app.extensions = extensions
 
     # ------------------------------------
@@ -1095,7 +1126,7 @@ def prepare_cmdline(argv=None):
 
     ipython_dir = get_ipython_dir()
     try:
-        ProfileDir.find_profile_dir_by_name(ipython_dir, profile)
+        pd = ProfileDir.find_profile_dir_by_name(ipython_dir, profile)
     except ProfileDirError:
         r = ''
         while not r in ('y', 'n'):
@@ -1103,7 +1134,7 @@ def prepare_cmdline(argv=None):
                      "one now ([y]/n)? " % profile
             r = raw_input(prompt) or 'y'
         if r.lower() == 'y':
-            create_spock_profile(ipython_dir, session, profile)
+            create_spock_profile(ipython_dir, profile)
         else:
             sys.stdout.write('No spock profile was created. '
                              'Starting ipython with default profile...\n')
@@ -1113,6 +1144,9 @@ def prepare_cmdline(argv=None):
                 if arg.startswith('--profile='):
                     argv.remove(arg)
             return
+    else:
+        ipy_profile_dir = pd.location # directory with the spock profile
+        check_for_upgrade(ipy_profile_dir)
 
     if append_profile:
         argv.append("--profile=" + profile)
diff --git a/src/sardana/spock/ipython_01_00/genutils.py b/src/sardana/spock/ipython_01_00/genutils.py
index 0ea510f..ccb6b10 100644
--- a/src/sardana/spock/ipython_01_00/genutils.py
+++ b/src/sardana/spock/ipython_01_00/genutils.py
@@ -95,6 +95,8 @@ requirements = {
     "IPython"     : ("0.11.0", "0.12.0"),
     "Python"      : ("2.6.0", "2.6.0"),
     "PyTango"     : ("7.2.0", "7.2.3"),
+    # for the moment just for reference since itango does not provide version
+    "itango"      : ("0.1.4", "0.1.4"),
     "taurus.core" : ("3.0.0", "3.0.0")
 }
 
@@ -478,6 +480,12 @@ def check_requirements():
             errMsg += "Current version is unknown (most surely too old)\n"
         errPyTango = True
 
+    # TODO: verify the version whenever itango starts to provide it
+    try:
+        import itango
+    except ImportError:
+        errMsg += "Spock needs itango version >= 0.1.4. No itango installation found\n"
+
     if currTaurusCore is None:
         errMsg += "Spock needs taurus.core version >= %s. No taurus.core installation found\n" % requirements["taurus.core"][0]
         errTaurusCore = True
@@ -526,7 +534,8 @@ def _get_dev(dev_type):
     if hasattr(spock_config, taurus_dev_var):
         taurus_dev = getattr(spock_config, taurus_dev_var)
     if taurus_dev is None:
-        dev_name = getattr(spock_config, dev_type + '_name')
+        # TODO: For Taurus 4 compatibility
+        dev_name = "tango://%s" % getattr(spock_config, dev_type + '_name')
         factory = Factory()
         taurus_dev = factory.getDevice(dev_name)
         import PyTango
@@ -600,11 +609,7 @@ def unexpose_variable(name):
     user_ns = get_shell().user_ns
     del user_ns[name]
 
-def create_spock_profile(userdir, dft_profile, profile, door_name=None):
-    """Create a profile file from a profile template file """
-    if not os.path.isdir(userdir):
-        ProfileDir.create_profile_dir(userdir)
-    p_dir = ProfileDir.create_profile_dir_by_name(userdir, profile)
+def _create_config_file(location, door_name=None):
     ###########################################################################
     # NOTE: BaseIPythonApplication.config_file_name.default_value should return
     # the config file name, but it returns an empty string instead (at least 
@@ -613,13 +618,7 @@ def create_spock_profile(userdir, dft_profile, profile, door_name=None):
     config_file_name = BaseIPythonApplication.config_file_name.default_value 
     config_file_name = config_file_name or 'ipython_config.py' 
     ###########################################################################
-    abs_config_file_name = os.path.join(p_dir.location, config_file_name)
-    create_config = True
-    if os.path.isfile(abs_config_file_name):
-        create_config = ask_yes_no("Spock configuration file already exists. "\
-                                   "Do you wish to replace it?", default='y')
-    if not create_config:
-        return
+    abs_config_file_name = os.path.join(location, config_file_name)
 
     src_data = """\
 \"\"\"Settings for Spock session\"\"\"
@@ -631,7 +630,8 @@ def create_spock_profile(userdir, dft_profile, profile, door_name=None):
 # door_name = {door_name}
 #
 
-import PyTango.ipython
+import itango
+
 import sardana.spock.genutils
 from sardana.spock.config import Spock
 
@@ -650,7 +650,7 @@ config.IPKernelApp.pylab = 'inline'
     # Discover door name
     #
     if door_name is None:
-        door_name = get_device_from_user("Door", profile)
+        door_name = get_device_from_user("Door" )
     else:
         full_door_name, door_name, _ = from_name_to_tango(door_name)
         door_name = full_door_name
@@ -664,7 +664,7 @@ config.IPKernelApp.pylab = 'inline'
                                 macroserver_name=ms_name,
                                 door_name=door_name)
 
-    sys.stdout.write('Storing %s in %s... ' % (config_file_name, p_dir.location))
+    sys.stdout.write('Storing %s in %s... ' % (config_file_name, location))
     sys.stdout.flush()
 
     with file(abs_config_file_name, "w") as f:
@@ -672,18 +672,57 @@ config.IPKernelApp.pylab = 'inline'
         f.close()
     sys.stdout.write(MSG_DONE + '\n')
 
-def check_for_upgrade(ipy_profile_file, ipythondir, session, profile):
-    # Check if the current profile is up to date with the spock version
+
+def create_spock_profile(userdir, profile, door_name=None):
+    """Create spock profile directory and configuration file from a template
+    file
+
+    :param userdir: directory where the spock profile will be created
+    :param profile: profile name
+    :param door_name: door name, if None, user will be asked for the door name
+    :"""
+    if not os.path.isdir(userdir):
+        ProfileDir.create_profile_dir(userdir)
+    p_dir = ProfileDir.create_profile_dir_by_name(userdir, profile)
+
+    ipy_profile_dir = p_dir.location
+
+    _create_config_file(ipy_profile_dir)
+
+def upgrade_spock_profile(ipy_profile_dir, door_name):
+    """Upgrade spock profile by recreating configuration file from scratch
+
+    :param ipy_profile_dir: directory with the spock profile
+    :param door_name: door name
+    """
+    _create_config_file(ipy_profile_dir, door_name)
+
+def check_for_upgrade(ipy_profile_dir):
+    """Check if the current profile is up to date with the spock version
+
+    :param ipy_profile_dir: directory with the spock profile
+    """
     spock_profile_ver_str = '0.0.0'
     door_name = None
 
+    ###########################################################################
+    # NOTE: BaseIPythonApplication.config_file_name.default_value should return
+    # the config file name, but it returns an empty string instead (at least 
+    # in some cases). For now, we give a hardcoded name if it is empty
+    # TODO: Check why this is the case
+    config_file_name = BaseIPythonApplication.config_file_name.default_value 
+    config_file_name = config_file_name or 'ipython_config.py'
+    ###########################################################################
+    abs_config_file_name = os.path.join(ipy_profile_dir, config_file_name)
+
     # search for version and door inside the ipy_profile file
-    for i, line in enumerate(ipy_profile_file):
-        if i > 20 : break; # give up after 20 lines
-        if line.startswith('# spock_creation_version = '):
-            spock_profile_ver_str = line[line.index('=')+1:].strip()
-        if line.startswith('# door_name = '):
-            door_name = line[line.index('=')+1:].strip()
+    with file(abs_config_file_name, "r") as ipy_config_file:
+        for i, line in enumerate(ipy_config_file):
+            if i > 20 : break; # give up after 20 lines
+            if line.startswith('# spock_creation_version = '):
+                spock_profile_ver_str = line[line.index('=')+1:].strip()
+            if line.startswith('# door_name = '):
+                door_name = line[line.index('=')+1:].strip()
 
     # convert version from string to numbers
     spocklib_ver = translate_version_str2int(release.version)
@@ -708,7 +747,7 @@ def check_for_upgrade(ipy_profile_file, ipythondir, session, profile):
     prompt = 'Do you wish to upgrade now (warn: this will shutdown the current spock session) ([y]/n)? '
     r = raw_input(prompt) or 'y'
     if r.lower() == 'y':
-        create_spock_profile(ipythondir, session, profile, door_name)
+        upgrade_spock_profile(ipy_profile_dir, door_name)
         sys.exit(0)
 
 def get_args(argv):
@@ -742,7 +781,7 @@ def get_args(argv):
                      'one now ([y]/n)? ' % profile
             r = raw_input(prompt) or 'y'
         if r.lower() == 'y':
-            create_spock_profile(ipython_dir, session, profile)
+            create_spock_profile(ipython_dir, profile)
         else:
             sys.stdout.write('No spock door extension profile was created. Starting normal spock...\n')
             sys.stdout.flush()
@@ -909,7 +948,7 @@ object?   -> Details about 'object'. ?object also works, ?? prints more.
     # ------------------------------------
     i_app = config.BaseIPythonApplication
     extensions = getattr(i_app, 'extensions', [])
-    extensions.extend(["PyTango.ipython", "sardana.spock"])
+    extensions.extend(["itango", "sardana.spock"])
     i_app.extensions = extensions
 
     # ------------------------------------
@@ -1103,7 +1142,7 @@ def prepare_cmdline(argv=None):
 
     ipython_dir = get_ipython_dir()
     try:
-        ProfileDir.find_profile_dir_by_name(ipython_dir, profile)
+        pd = ProfileDir.find_profile_dir_by_name(ipython_dir, profile)
     except ProfileDirError:
         r = ''
         while not r in ('y', 'n'):
@@ -1111,7 +1150,7 @@ def prepare_cmdline(argv=None):
                      "one now ([y]/n)? " % profile
             r = raw_input(prompt) or 'y'
         if r.lower() == 'y':
-            create_spock_profile(ipython_dir, session, profile)
+            create_spock_profile(ipython_dir, profile)
         else:
             sys.stdout.write('No spock profile was created. '
                              'Starting ipython with default profile...\n')
@@ -1121,6 +1160,9 @@ def prepare_cmdline(argv=None):
                 if arg.startswith('--profile='):
                     argv.remove(arg)
             return
+    else:
+        ipy_profile_dir = pd.location # directory with the spock profile
+        check_for_upgrade(ipy_profile_dir)
 
     if append_profile:
         argv.append("--profile=" + profile)
diff --git a/src/sardana/spock/magic.py b/src/sardana/spock/magic.py
index 325c8b8..e5ac0a3 100644
--- a/src/sardana/spock/magic.py
+++ b/src/sardana/spock/magic.py
@@ -31,7 +31,6 @@ __all__ = ['expconf', 'showscan', 'spsplot', 'debug_completer',
            'post_mortem', 'macrodata', 'edmac', 'spock_late_startup_hook',
            'spock_pre_prompt_hook']
 
-
 from .genutils import page, get_door, get_macro_server, ask_yes_no, arg_split
 from .genutils import MSG_DONE, MSG_FAILED
 from .genutils import get_ipapi
@@ -43,11 +42,14 @@ def expconf(self, parameter_s=''):
     try:
         from sardana.taurus.qt.qtgui.extra_sardana import ExpDescriptionEditor
     except:
-        print "Error importing ExpDescriptionEditor "\
+        print "Error importing ExpDescriptionEditor " \
               "(hint: is taurus extra_sardana installed?)"
         return
-    doorname = get_door().name()
-        
+    try:
+        doorname = get_door().name()
+    except TypeError:
+        # TODO: For Taurus 4 adaptation
+        doorname = get_door().fullname
     #===========================================================================
     ## ugly hack to avoid ipython/qt thread problems #e.g. see
     ## https://sourceforge.net/p/sardana/tickets/10/ 
@@ -55,14 +57,15 @@ def expconf(self, parameter_s=''):
     ## widget open after closing spock 
     ## @todo: investigate cause of segfaults when using launching qt widgets from ipython
     # 
-    #w = ExpDescriptionEditor(door=doorname)
-    #w.show() #launching it like this, produces the problem of https://sourceforge.net/p/sardana/tickets/10/
+    # w = ExpDescriptionEditor(door=doorname)
+    # w.show() #launching it like this, produces the problem of https://sourceforge.net/p/sardana/tickets/10/
     import subprocess
     import sys
+
     fname = sys.modules[ExpDescriptionEditor.__module__].__file__
     args = ['python', fname, doorname]
     subprocess.Popen(args)
-    #===========================================================================
+    # ===========================================================================
 
 
 def showscan(self, parameter_s=''):
@@ -122,6 +125,7 @@ def debug(self, parameter_s=''):
 def www(self, parameter_s=''):
     """What went wrong. Prints the error message from the last macro execution"""
     import PyTango
+
     door = get_door()
     try:
         last_macro = door.getLastRunningMacro()
@@ -139,6 +143,7 @@ def www(self, parameter_s=''):
                      stream=door.Error)
         door.writeln(str(e), stream=door.Error)
         import traceback
+
         traceback.print_exc()
 
 
@@ -156,7 +161,7 @@ def post_mortem(self, parameter_s='', from_www=False):
             msg = "\n".join(logger.read(cache=False).value)
         except:
             from_www = True
-            
+
     if from_www:
         msg = "------------------------------\n" \
               "Server is offline.\n" \
@@ -165,6 +170,7 @@ def post_mortem(self, parameter_s='', from_www=False):
         msg += "\n".join(logger.getLogBuffer())
     page(msg)
 
+
 def macrodata(self, parameter_s=''):
     """macrodata
     
@@ -173,10 +179,11 @@ def macrodata(self, parameter_s=''):
     macro_data = door.read_attribute("RecordData")
 
     from taurus.core.util.codecs import CodecFactory
+
     factory = CodecFactory()
-    data = factory.decode(macro_data.value)    
+    data = factory.decode(macro_data.value)
     return data
-    
+
 
 def edmac(self, parameter_s=''):
     """edmac <macro name> [<module>]
@@ -195,14 +202,27 @@ def edmac(self, parameter_s=''):
 
     if len(pars) == 1:
         macro_name = pars[0]
-        macro_info = ms.getMacroInfoObj(macro_name)
-        if macro_info is None:
-            print "Macro '%s' could not be found" % macro_name
-            return
-        macro_lib = macro_info.module
+        is_new_macro = False
     else:
+        is_new_macro = True
         macro_name, macro_lib = pars
 
+    macro_info_obj = ms.getMacroInfoObj(macro_name)
+    if not is_new_macro:
+        if macro_info_obj is None:
+            print "Macro '%s' could not be found" % macro_name
+            return
+        macro_lib = macro_info_obj.module
+
+    if is_new_macro:
+        if macro_info_obj is not None:
+            msg = ('Do you want to create macro "%s" in module "%s" that will'
+                   ' override the already existing macro in module "%s"'
+                    % (macro_name, macro_lib, macro_info_obj.module))
+            if not ask_yes_no(msg, 'y'):
+                print "Aborting edition..."
+                return
+
     macro_info = (macro_lib, macro_name)
     print 'Opening %s.%s...' % macro_info
 
@@ -240,7 +260,7 @@ def edmac(self, parameter_s=''):
     else:
         print "Discarding changes..."
 
-    #if os.path.exists(local_fname):
+    # if os.path.exists(local_fname):
     #    if ask_yes_no('Delete temporary file \'%s\'?' % local_fname, 'y'):
     #        os.remove(local_fname)
     #        bkp = '%s~' % local_fname
@@ -257,6 +277,7 @@ def spock_late_startup_hook(self):
         get_door().setConsoleReady(True)
     except:
         import traceback
+
         print "Exception in spock_late_startup_hook:"
         traceback.print_exc()
 
@@ -266,9 +287,10 @@ def spock_pre_prompt_hook(self):
         get_door().pre_prompt_hook(self)
     except:
         import traceback
+
         print "Exception in spock_pre_prompt_hook:"
         traceback.print_exc()
 
-#def spock_pre_runcode_hook(self):
+# def spock_pre_runcode_hook(self):
 #    print "spock_pre_runcode_hook"
 #    return None
diff --git a/src/sardana/spock/release.py b/src/sardana/spock/release.py
index 0888980..7d2d84c 100644
--- a/src/sardana/spock/release.py
+++ b/src/sardana/spock/release.py
@@ -39,7 +39,7 @@ name = 'spock'
 revision = '1'
 
 #version = '0.8.1.svn.r' + revision.rstrip('M')
-version = '2.0.0'
+version = '2.1.0'
 
 description = "An enhanced interactive Macro Server shell."
 
diff --git a/src/sardana/spock/spockms.py b/src/sardana/spock/spockms.py
index 3cd53f9..dd6378f 100755
--- a/src/sardana/spock/spockms.py
+++ b/src/sardana/spock/spockms.py
@@ -52,6 +52,12 @@ else:
     from sardana.taurus.core.tango.sardana.macroserver import BaseDoor, BaseMacroServer
     BaseGUIViewer = object
 
+try:
+    RUNNING_STATE = TaurusSWDevState.Running
+except RuntimeError:
+    # TODO: For Taurus 4 compatibility
+    from taurus.core import TaurusDevState
+    RUNNING_STATE = TaurusDevState.Ready
 
 class GUIViewer(BaseGUIViewer):
 
@@ -314,7 +320,7 @@ class SpockBaseDoor(BaseDoor):
 
     def _runMacro(self, xml, **kwargs):
         #kwargs like 'synch' are ignored in this re-implementation
-        if self._spock_state != TaurusSWDevState.Running:
+        if self._spock_state != RUNNING_STATE:
             print "Unable to run macro: No connection to door '%s'" % self.getSimpleName()
             raise Exception("Unable to run macro: No connection")
         if xml is None:
@@ -403,7 +409,7 @@ class SpockBaseDoor(BaseDoor):
 
     def _updateState(self, old_sw_state, new_sw_state, silent=False):
         user_ns = genutils.get_ipapi().user_ns
-        if new_sw_state == TaurusSWDevState.Running:
+        if new_sw_state == RUNNING_STATE:
             user_ns['DOOR_STATE'] = ""
         else:
             user_ns['DOOR_STATE'] = " (OFFLINE)"
@@ -414,9 +420,9 @@ class SpockBaseDoor(BaseDoor):
 
         ss = self._spock_state
         if ss is not None and ss != new_sw_state and not silent:
-            if ss == TaurusSWDevState.Running:
+            if ss == RUNNING_STATE:
                 self.write_asynch("\nConnection to door '%s' was lost.\n" % self.getSimpleName())
-            elif new_sw_state == TaurusSWDevState.Running:
+            elif new_sw_state == RUNNING_STATE:
                 self.write_asynch("\nConnection to the door (%s) has " \
                     "been restablished\n" % self.getSimpleName())
         self._spock_state = new_sw_state
diff --git a/src/sardana/taurus/core/tango/sardana/macroserver.py b/src/sardana/taurus/core/tango/sardana/macroserver.py
old mode 100644
new mode 100755
index d31459c..d4e9bc8
--- a/src/sardana/taurus/core/tango/sardana/macroserver.py
+++ b/src/sardana/taurus/core/tango/sardana/macroserver.py
@@ -281,6 +281,7 @@ class BaseDoor(MacroServerDevice):
     def __init__(self, name, **kw):
         self._log_attr = CaselessDict()
         self._block_lines = 0
+        self._in_block = False
         self._macro_server = None
         self._running_macros = None
         self._running_macro = None
@@ -296,7 +297,12 @@ class BaseDoor(MacroServerDevice):
         self.call__init__(MacroServerDevice, name, **kw)
 
         self._old_door_state = PyTango.DevState.UNKNOWN
-        self._old_sw_door_state = TaurusSWDevState.Uninitialized
+        try:
+            self._old_sw_door_state = TaurusSWDevState.Uninitialized
+        except RuntimeError:
+            #TODO: For Taurus 4 compatibility
+            from taurus.core import TaurusDevState
+            self._old_sw_door_state = TaurusDevState.Undefined 
 
         self.getStateObj().addListener(self.stateChanged)
 
@@ -542,7 +548,11 @@ class BaseDoor(MacroServerDevice):
 
     def stateChanged(self, s, t, v):
         self._old_door_state = self.getState()
-        self._old_sw_door_state = self.getSWState()
+        try:
+            self._old_sw_door_state = self.getSWState()
+        except:
+            # TODO: For Taurus 4 compatibility
+            self._old_sw_door_state = self.state
 
     def resultReceived(self, log_name, result):
         """Method invoked by the arrival of a change event on the Result attribute"""
@@ -644,14 +654,21 @@ class BaseDoor(MacroServerDevice):
         for line in output:
             if not self._debug:
                 if line == self.BlockStart:
+                    self._in_block = True
                     for i in xrange(self._block_lines):
                         o += '\x1b[2K\x1b[1A\x1b[2K'  #erase current line, up one line, erase current line
                     self._block_lines = 0
                     continue
                 elif line == self.BlockFinish:
+                    self._in_block = False
                     continue
+                else:
+                    if self._in_block:
+                        self._block_lines += 1
+                    else:
+                        self._block_lines = 0
             o += "%s\n" % line
-            self._block_lines += 1
+
         o += self.log_stop[log_name]
         self.write(o)
 
@@ -701,6 +718,7 @@ class MacroPath(object):
         self.rel_macro_path = [ osp.relpath for p in mp, self.base_macro_path ]
 
 
+
 class Environment(dict):
 
     def __init__(self, macro_server):
@@ -821,7 +839,9 @@ class BaseMacroServer(MacroServerDevice):
         return MacroInfo(from_json=element_info._data)
 
     def _createDeviceObject(self, element_info):
-        return Factory().getDevice(element_info.full_name)
+        # TODO: For Taurus 4 compatibility
+        name = "tango://%s" % element_info.full_name
+        return Factory().getDevice(name)
 
     def on_elements_changed(self, evt_src, evt_type, evt_value):
         try:
diff --git a/src/sardana/taurus/core/tango/sardana/motion.py b/src/sardana/taurus/core/tango/sardana/motion.py
index f183983..547f97f 100644
--- a/src/sardana/taurus/core/tango/sardana/motion.py
+++ b/src/sardana/taurus/core/tango/sardana/motion.py
@@ -151,7 +151,7 @@ class MotionGroup(BaseMotion):
         times = [ moveable.getLastMotionTime() for moveable in self.moveable_list ]
         return max(times)
 
-    def getTotalLastMotionTime():
+    def getTotalLastMotionTime(self):
         return self.__total_motion_time
 
     def startMove(self, pos_list, timeout=None):
diff --git a/src/sardana/taurus/core/tango/sardana/pool.py b/src/sardana/taurus/core/tango/sardana/pool.py
index 1194245..17f027b 100644
--- a/src/sardana/taurus/core/tango/sardana/pool.py
+++ b/src/sardana/taurus/core/tango/sardana/pool.py
@@ -38,6 +38,7 @@ __docformat__ = 'restructuredtext'
 import os
 import sys
 import time
+import copy
 import weakref
 import operator
 import traceback
@@ -48,7 +49,12 @@ from PyTango import DevState, AttrDataFormat, AttrQuality, DevFailed, \
 from taurus import Factory, Device
 from taurus.core.taurusbasetypes import TaurusEventType, TaurusSWDevState, \
     TaurusSerializationMode
-from taurus.core.taurusvalidator import AttributeNameValidator
+try:
+    from taurus.core.taurusvalidator import AttributeNameValidator as\
+        TangoAttributeNameValidator
+except ImportError:
+    #TODO: For Taurus 4 compatibility
+    from taurus.core.tango.tangovalidator import TangoAttributeNameValidator
 from taurus.core.util.log import Logger
 from taurus.core.util.singleton import Singleton
 from taurus.core.util.codecs import CodecFactory
@@ -1155,12 +1161,13 @@ class MGConfiguration(object):
         self.non_tango_channels = n_tg_chs = CaselessDict()
         self.cache = cache = {}
 
-        tg_attr_validator = AttributeNameValidator()
+        tg_attr_validator = TangoAttributeNameValidator()
         for channel_name, channel_data in self.channels.items():
             cache[channel_name] = None
             data_source = channel_data['source']
             #external = ctrl_name.startswith("__")
-            params = tg_attr_validator.getParams(data_source)
+            # TODO: For Taurus 4 compatibility
+            params = tg_attr_validator.getParams("tango://%s" % data_source)
             if params is None:
                 # Handle NON tango channel
                 n_tg_chs[channel_name] = channel_data
@@ -1249,17 +1256,42 @@ class MGConfiguration(object):
                 if ch_info.name.lower() == channel_name:
                     return d_name, a_name, ch_info
 
-    def getChannelsInfo(self):
+    def getChannelsInfo(self, only_enabled=False):
+        """Returns information about the channels present in the measurement
+        group in a form of dictionary, where key is a channel name and value is
+        a tuple of three elements:
+            - device name
+            - attribute name
+            - attribute information or None if there was an error trying to get
+              the information
+
+        :param only_enabled: flag to filter out disabled channels
+        :type only_enabled: bool
+        :return: dictionary with channels info
+        :rtype: dict<str, tuple<str, str, TangoChannelInfo>>
+        """
         self.prepare()
         ret = CaselessDict(self.tango_channels_info)
         ret.update(self.non_tango_channels)
+        for ch_name, (_, _, ch_info) in ret.items():
+            if only_enabled and not ch_info.enabled:
+                ret.pop(ch_name)
         return ret
 
-    def getChannelsInfoList(self):
-        channels_info = self.getChannelsInfo()
-        ret = len(channels_info) * [None]
+    def getChannelsInfoList(self, only_enabled=False):
+        """Returns information about the channels present in the measurement
+        group in a form of ordered, based on the channel index, list.
+
+        :param only_enabled: flag to filter out disabled channels
+        :type only_enabled: bool
+        :return: list with channels info
+        :rtype: list<TangoChannelInfo>
+        """
+        channels_info = self.getChannelsInfo(only_enabled=only_enabled)
+        ret = []
         for _, (_, _, ch_info) in channels_info.items():
-            ret[ch_info.index] = ch_info
+            ret.append(ch_info)
+        ret = sorted(ret, lambda x,y: cmp(x.index, y.index))
         return ret
 
     def getCountersInfoList(self):
@@ -1273,6 +1305,29 @@ class MGConfiguration(object):
             channels_info.pop(idx)
         return channels_info
 
+    def getTangoDevChannels(self, only_enabled=False):
+        """Returns Tango channels (attributes) that could be used to read
+        measurement group results in a form of dict where key is a device name
+        and value is a list with two elements:
+            - A device proxy or None if there was an error building it
+            - A dict where keys are attribute names and value is a reference to
+              a dict representing channel data as received in raw data
+
+        :param only_enabled: flag to filter out disabled channels
+        :type only_enabled: bool
+        :return: dict with Tango channels
+        :rtype: dict<str, list[DeviceProxy, CaselessDict<str, dict>]>
+        """
+        if not only_enabled:
+            return self.tango_dev_channels
+        tango_dev_channels = copy.deepcopy(self.tango_dev_channels)
+        for _, dev_data in tango_dev_channels.items():
+            _, attrs = dev_data
+            for attr_name, channel_data in attrs.items():
+                if not channel_data["enabled"]:
+                    attrs.pop(attr_name)
+        return tango_dev_channels
+
     def read(self, parallel=True):
         if parallel:
             return self._read_parallel()
@@ -1284,7 +1339,8 @@ class MGConfiguration(object):
         dev_replies = {}
 
         # deposit read requests
-        for _, dev_data in self.tango_dev_channels.items():
+        tango_dev_channels = self.getTangoDevChannels(only_enabled=True)
+        for _, dev_data in tango_dev_channels.items():
             dev, attrs = dev_data
             if dev is None:
                 continue
@@ -1314,7 +1370,8 @@ class MGConfiguration(object):
     def _read(self):
         self.prepare()
         ret = CaselessDict(self.cache)
-        for _, dev_data in self.tango_dev_channels.items():
+        tango_dev_channels = self.getTangoDevChannels(only_enabled=True)
+        for _, dev_data in tango_dev_channels.items():
             dev, attrs = dev_data
             try:
                 data = dev.read_attributes(attrs.keys())
@@ -1425,6 +1482,16 @@ class MeasurementGroup(PoolElement):
     def getChannelsInfo(self):
         return self.getConfiguration().getChannelsInfoList()
 
+    def getChannelsEnabledInfo(self):
+        """Returns information about **only enabled** channels present in the
+        measurement group in a form of ordered, based on the channel index,
+        list.
+
+        :return: list with channels info
+        :rtype: list<TangoChannelInfo>
+        """
+        return self.getConfiguration().getChannelsInfoList(only_enabled=True)
+
     def getCountersInfo(self):
         return self.getConfiguration().getCountersInfoList()
 
@@ -1588,7 +1655,9 @@ class Pool(TangoDevice, MoveableSource):
             kwargs['_pool_data'] = data
             kwargs['_pool_obj'] = self
             return klass(**kwargs)
-        obj = Factory().getDevice(element_info.full_name, _pool_obj=self,
+        # TODO: For Taurus 4 compatibility
+        fullname = "tango://%s" % element_info.full_name
+        obj = Factory().getDevice(fullname, _pool_obj=self,
                                   _pool_data=data)
         return obj
 
diff --git a/src/sardana/taurus/qt/qtcore/tango/sardana/macroserver.py b/src/sardana/taurus/qt/qtcore/tango/sardana/macroserver.py
index b0a780f..fbcb0bb 100644
--- a/src/sardana/taurus/qt/qtcore/tango/sardana/macroserver.py
+++ b/src/sardana/taurus/qt/qtcore/tango/sardana/macroserver.py
@@ -39,6 +39,19 @@ class QDoor(BaseDoor, Qt.QObject):
 
     __pyqtSignals__ = ["resultUpdated", "recordDataUpdated", "macroStatusUpdated"]
     __pyqtSignals__ += [ "%sUpdated" % l.lower() for l in BaseDoor.log_streams ]
+    # TODO: For Taurus 4 compatibility
+    try:
+        # sometimes we emit None hence the type is object
+        # (but most of the data are passed with type list)
+        resultUpdated = Qt.pyqtSignal(object)
+        recordDataUpdated = Qt.pyqtSignal(object)
+        errorUpdated = Qt.pyqtSignal(object)
+        warningUpdated = Qt.pyqtSignal(object)
+        infoUpdated = Qt.pyqtSignal(object)
+        outputUpdated = Qt.pyqtSignal(object)
+        debugUpdated = Qt.pyqtSignal(object)
+    except AttributeError:
+        pass
 
     def __init__(self, name, qt_parent=None, **kw):
         self.call__init__wo_kw(Qt.QObject, qt_parent)
@@ -47,12 +60,18 @@ class QDoor(BaseDoor, Qt.QObject):
     def resultReceived(self, log_name, result):
         res = BaseDoor.resultReceived(self, log_name, result)
         self.emit(Qt.SIGNAL("resultUpdated"), res)
+        # TODO: For Taurus 4 compatibility
+        if hasattr(self, "resultUpdated"):
+            self.resultUpdated.emit(res)
         return res
 
     def recordDataReceived(self, s, t, v):
         if t not in CHANGE_EVTS: return
         res = BaseDoor.recordDataReceived(self, s, t, v)
         self.emit(Qt.SIGNAL("recordDataUpdated"), res)
+        # TODO: For Taurus 4 compatibility
+        if hasattr(self, "recordDataUpdated"):
+            self.recordDataUpdated.emit(res)
         return res
 
     def macroStatusReceived(self, s, t, v):
@@ -63,11 +82,21 @@ class QDoor(BaseDoor, Qt.QObject):
             macro = self.getRunningMacro()
         if macro is None: return
         self.emit(Qt.SIGNAL("macroStatusUpdated"), (macro, res))
+        # TODO: For Taurus 4 compatibility
+        if hasattr(self, "macroStatusUpdated"):
+            self.macroStatusUpdated.emit(res)
         return res
 
     def logReceived(self, log_name, output):
         res = BaseDoor.logReceived(self, log_name, output)
-        self.emit(Qt.SIGNAL("%sUpdated" % log_name.lower()), output)
+        log_name = log_name.lower()
+        self.emit(Qt.SIGNAL("%sUpdated" % log_name), output)
+        # TODO: For Taurus 4 compatibility
+        try:
+            recordDataUpdated = getattr(self, "%sUpdated" % log_name)
+            recordDataUpdated.emit(output)
+        except AttributeError:
+            pass
         return res
 
 
diff --git a/src/sardana/taurus/qt/qtgui/extra_macroexecutor/common.py b/src/sardana/taurus/qt/qtgui/extra_macroexecutor/common.py
index 51bea8b..0b1bcb3 100644
--- a/src/sardana/taurus/qt/qtgui/extra_macroexecutor/common.py
+++ b/src/sardana/taurus/qt/qtgui/extra_macroexecutor/common.py
@@ -31,7 +31,7 @@ from taurus.core.taurusbasetypes import TaurusEventType
 from taurus.qt.qtgui.base import TaurusBaseWidget
 from taurus.qt.qtgui.input import TaurusAttrListComboBox
 from taurus.qt.qtgui.container import TaurusMainWindow
-from taurus.qt.qtgui.resource import getThemeIcon
+from taurus.qt.qtgui.resource import getThemeIcon, getIcon
 
 
 def str2bool(text):
@@ -188,11 +188,11 @@ class TaurusMacroConfigurationDialog(Qt.QDialog):
                 pass
             icon = None
             if state == PyTango.DevState.ON:
-                icon = Qt.QIcon(":/leds/images24/ledgreen.png")
+                icon = getIcon(":/leds/images24/ledgreen.png")
             elif state == PyTango.DevState.FAULT:
-                icon = Qt.QIcon(":/leds/images24/ledred.png")
+                icon = getIcon(":/leds/images24/ledred.png")
             elif state == None:
-                icon = Qt.QIcon(":/leds/images24/ledredoff.png")
+                icon = getIcon(":/leds/images24/ledredoff.png")
             ms_stateIcons.append((macroServer, icon))
         return ms_stateIcons
 
@@ -246,7 +246,7 @@ class MacroExecutionWindow(TaurusMainWindow):
         self._customMacroEditorPaths = ""
         self.registerConfigProperty("customMacroEditorPaths", "setCustomMacroEditorPaths", "customMacroEditorPaths")
         self._qDoor = None
-        self.setWindowIcon(Qt.QIcon(":/apps/preferences-system-session.svg"))
+        self.setWindowIcon(getIcon(":/apps/preferences-system-session.svg"))
         toolBar = self.basicTaurusToolbar()
         toolBar.setIconSize(Qt.QSize(24, 24))
         self.configureAction = self.createConfigureAction()
diff --git a/src/sardana/taurus/qt/qtgui/extra_macroexecutor/macrobutton.py b/src/sardana/taurus/qt/qtgui/extra_macroexecutor/macrobutton.py
index 6c5ded9..b35a718 100644
--- a/src/sardana/taurus/qt/qtgui/extra_macroexecutor/macrobutton.py
+++ b/src/sardana/taurus/qt/qtgui/extra_macroexecutor/macrobutton.py
@@ -255,17 +255,15 @@ class MacroButton(TaurusWidget):
         if self.door is None:
             return
 
-        # Thanks to gjover for the hint... :-D
-        #macro_cmd = self.macro_name + ' ' + ' '.join(self.macro_args)
-        self.macro_id = uuid.uuid1()
-        macro_cmd_xml = '<macro name="%s" id="%s">\n' % \
-                        (self.macro_name, self.macro_id)
-        for arg in self.macro_args:
-            macro_cmd_xml += '<param value="%s"/>\n' % arg
-        macro_cmd_xml += '</macro>'
+        # TODO: make macrobutton compatible with macros with advanced usage of
+        # repeat parameters e.g. multiple repeat parameters, nested repeat
+        # parameters, etc.
+        macro_cmd = self.macro_name + ' ' + ' '.join(self.macro_args)
         try:
-            #self.door.runMacro(macro_cmd)
-            self.door.runMacro(macro_cmd_xml)
+            self.door.runMacro(macro_cmd)
+            sec_xml = self.door.getRunningXML()
+            # get the id of the current running macro
+            self.macro_id = sec_xml[0].get("id")
         except Exception, e:
             self.ui.button.setChecked(False)
             raise e
diff --git a/src/sardana/taurus/qt/qtgui/extra_macroexecutor/macroexecutor.py b/src/sardana/taurus/qt/qtgui/extra_macroexecutor/macroexecutor.py
index 5b2e24d..baa0494 100644
--- a/src/sardana/taurus/qt/qtgui/extra_macroexecutor/macroexecutor.py
+++ b/src/sardana/taurus/qt/qtgui/extra_macroexecutor/macroexecutor.py
@@ -688,7 +688,11 @@ class TaurusMacroExecutorWidget(TaurusWidget):
 
     def checkDoorState(self):
         door = Device(self.doorName())
-        doorState = door.state()
+        try:
+            doorState = door.state()
+        except TypeError:
+            # TODO: For Taurus 4 adaptation
+            doorState = door.getState()
         if doorState == PyTango.DevState.RUNNING:
             self.playMacroAction.setEnabled(False)
             self.pauseMacroAction.setEnabled(True)
@@ -812,7 +816,12 @@ class TaurusMacroExecutorWidget(TaurusWidget):
             self.doorStateLed.setModel(None)
             return
         self.doorStateLed.setModel(self.doorName() + "/State")
-        doorState = Device(doorName).state()
+        door = Device(doorName)
+        try:
+            doorState = door.state()
+        except TypeError:
+            # TODO: For Taurus 4 adaptation
+            doorState = door.getState()
         if doorState == PyTango.DevState.ON:
             self.playMacroAction.setText("Start macro")
             self.playMacroAction.setToolTip("Start macro")
@@ -822,7 +831,11 @@ class TaurusMacroExecutorWidget(TaurusWidget):
 
     def onPlayMacro(self):
         door = Device(self.doorName())
-        doorState = door.state()
+        try:
+            doorState = door.state()
+        except TypeError:
+            # TODO: For Taurus 4 adaptation
+            doorState = door.getState()
         if doorState == PyTango.DevState.ON or doorState == PyTango.DevState.ALARM:
             self.setFocus()
             paramEditorModel = self.paramEditorModel()
@@ -845,7 +858,11 @@ class TaurusMacroExecutorWidget(TaurusWidget):
 
     def onStopMacro(self):
         door = Device(self.doorName())
-        doorState = door.state()
+        try:
+            doorState = door.state()
+        except TypeError:
+            # TODO: For Taurus 4 adaptation
+            doorState = door.getState()
 
         if doorState in (PyTango.DevState.RUNNING, PyTango.DevState.STANDBY):
             door.command_inout("StopMacro")
@@ -855,7 +872,11 @@ class TaurusMacroExecutorWidget(TaurusWidget):
 
     def onPauseMacro(self):
         door = Device(self.doorName())
-        doorState = door.state()
+        try:
+            doorState = door.state()
+        except TypeError:
+            # TODO: For Taurus 4 adaptation
+            doorState = door.getState()
 
         if doorState == PyTango.DevState.RUNNING:
             door.command_inout("PauseMacro")
diff --git a/src/sardana/taurus/qt/qtgui/extra_macroexecutor/sequenceeditor/model.py b/src/sardana/taurus/qt/qtgui/extra_macroexecutor/sequenceeditor/model.py
index 00ed7e5..5235c25 100644
--- a/src/sardana/taurus/qt/qtgui/extra_macroexecutor/sequenceeditor/model.py
+++ b/src/sardana/taurus/qt/qtgui/extra_macroexecutor/sequenceeditor/model.py
@@ -181,7 +181,7 @@ class MacroSequenceTreeModel(Qt.QAbstractItemModel):
                     index = index.parent()
                     node = self.nodeFromIndex(index)
                     if isinstance(node, macro.MacroNode):
-                        self.emit(Qt.SIGNAL("dataChanged(QModelIndex,QModelIndex)"), index, index.sibling(index.row(), self.columnCount(index)))
+                        self.emit(Qt.SIGNAL("dataChanged(QModelIndex,QModelIndex)"), index, index.sibling(index.row(), self.columnCount(index) - 1))
                         break
         elif index.column() == 2:
             progress = Qt.from_qvariant(value, float)
diff --git a/src/sardana/taurus/qt/qtgui/extra_macroexecutor/sequenceeditor/sequenceeditor.py b/src/sardana/taurus/qt/qtgui/extra_macroexecutor/sequenceeditor/sequenceeditor.py
index 7c2e554..e198ed1 100644
--- a/src/sardana/taurus/qt/qtgui/extra_macroexecutor/sequenceeditor/sequenceeditor.py
+++ b/src/sardana/taurus/qt/qtgui/extra_macroexecutor/sequenceeditor/sequenceeditor.py
@@ -460,7 +460,11 @@ class TaurusSequencerWidget(TaurusWidget):
         about the macro status does not reach the sequencer widget.'''
 
         door = Device(self.doorName())
-        doorState = door.state()
+        try:
+            doorState = door.state()
+        except TypeError:
+            # TODO: For Taurus 4 adaptation
+            doorState = door.getState()
         if doorState == PyTango.DevState.RUNNING:
             self.playSequenceAction.setEnabled(False)
             self.pauseSequenceAction.setEnabled(True)
@@ -604,7 +608,11 @@ class TaurusSequencerWidget(TaurusWidget):
 
     def onPlaySequence(self):
         door = Device(self.doorName())
-        doorState = door.state()
+        try:
+            doorState = door.state()
+        except TypeError:
+            # TODO: For Taurus 4 adaptation
+            doorState = door.getState()
         if doorState == PyTango.DevState.ON or doorState == PyTango.DevState.ALARM:
             first, last, ids = self.tree.prepareMacroIds()
             self.setFirstMacroId(first)
@@ -621,7 +629,11 @@ class TaurusSequencerWidget(TaurusWidget):
 
     def onStopSequence(self):
         door = Device(self.doorName())
-        doorState = door.state()
+        try:
+            doorState = door.state()
+        except TypeError:
+            # TODO: For Taurus 4 adaptation
+            doorState = door.getState()
         if doorState in (PyTango.DevState.RUNNING, PyTango.DevState.STANDBY):
             door.command_inout("StopMacro")
         else:
@@ -630,7 +642,11 @@ class TaurusSequencerWidget(TaurusWidget):
 
     def onPauseSequence(self):
         door = Device(self.doorName())
-        doorState = door.state()
+        try:
+            doorState = door.state()
+        except TypeError:
+            # TODO: For Taurus 4 adaptation
+            doorState = door.getState()
         if doorState == PyTango.DevState.RUNNING:
             door.command_inout("PauseMacro")
         else:
@@ -707,7 +723,12 @@ class TaurusSequencerWidget(TaurusWidget):
             self.doorStateLed.setModel(None)
             return
         self.doorStateLed.setModel(self.doorName() + "/State")
-        doorState = Device(doorName).state()
+        door = Device(doorName)
+        try:
+            doorState = door.state()
+        except TypeError:
+            # TODO: For Taurus 4 adaptation
+            doorState = door.getState()
         if doorState == PyTango.DevState.ON:
             self.playSequenceAction.setText("Start sequence")
             self.playSequenceAction.setToolTip("Start sequence")
diff --git a/src/sardana/taurus/qt/qtgui/extra_pool/poolchannel.py b/src/sardana/taurus/qt/qtgui/extra_pool/poolchannel.py
index acbc0e2..042b244 100644
--- a/src/sardana/taurus/qt/qtgui/extra_pool/poolchannel.py
+++ b/src/sardana/taurus/qt/qtgui/extra_pool/poolchannel.py
@@ -59,7 +59,7 @@ class PoolChannelTV(TaurusValue):
     '''
     def __init__(self, parent=None, designMode=False):
         TaurusValue.__init__(self, parent=parent, designMode=designMode)
-        self.setLabelWidgetClass("LabelWidgetDragsDeviceAndAttribute")
+        self.setLabelWidgetClass(LabelWidgetDragsDeviceAndAttribute)
         self.setLabelConfig('dev_alias')
 
     def getDefaultExtraWidgetClass(self):
diff --git a/src/sardana/taurus/qt/qtgui/extra_pool/poolioregister.py b/src/sardana/taurus/qt/qtgui/extra_pool/poolioregister.py
index 97d89b5..e2d8bf8 100644
--- a/src/sardana/taurus/qt/qtgui/extra_pool/poolioregister.py
+++ b/src/sardana/taurus/qt/qtgui/extra_pool/poolioregister.py
@@ -127,10 +127,10 @@ class PoolIORegisterTV(TaurusValue):
     '''
     def __init__(self, parent=None, designMode=False):
         TaurusValue.__init__(self, parent=parent, designMode=designMode)
-        self.setLabelWidgetClass("LabelWidgetDragsDeviceAndAttribute")
+        self.setLabelWidgetClass(LabelWidgetDragsDeviceAndAttribute)
         self.setLabelConfig('dev_alias')
-        self.setReadWidgetClass('PoolIORegisterReadWidget')
-        self.setWriteWidgetClass('PoolIORegisterWriteWidget')
+        self.setReadWidgetClass(PoolIORegisterReadWidget)
+        self.setWriteWidgetClass(PoolIORegisterWriteWidget)
         self.ioreg_dev = None
 
     def setModel(self, model):
diff --git a/src/sardana/taurus/qt/qtgui/extra_pool/poolmotor.py b/src/sardana/taurus/qt/qtgui/extra_pool/poolmotor.py
index c05853a..a059a3e 100644
--- a/src/sardana/taurus/qt/qtgui/extra_pool/poolmotor.py
+++ b/src/sardana/taurus/qt/qtgui/extra_pool/poolmotor.py
@@ -33,7 +33,12 @@ from taurus.external.qt import Qt
 import taurus
 from taurus.core.util.colors import DEVICE_STATE_PALETTE
 from taurus.core.taurusbasetypes import TaurusEventType
-from taurus.core.taurusvalidator import DeviceNameValidator
+try:
+    from taurus.core.taurusvalidator import DeviceNameValidator as \
+        TangoDeviceNameValidator
+except ImportError:
+    # TODO: For Taurus 4 adaptation
+    from taurus.core.tango.tangovalidator import TangoDeviceNameValidator
 import taurus.qt.qtcore.mimetypes
 from taurus.qt.qtgui.base import TaurusBaseWritableWidget
 from taurus.qt.qtgui.compact import TaurusReadWriteSwitcher
@@ -300,6 +305,7 @@ class PoolMotorSlim(TaurusWidget, PoolMotorClient):
         #self.call__init__(TaurusBaseWidget, str(self.objectName()), designMode=designMode)
         PoolMotorClient.__init__(self)
         self.loadUi()
+        self.recheckTaurusParent()
 
         self.show_context_menu = True
 
@@ -647,7 +653,9 @@ class PoolMotorSlim(TaurusWidget, PoolMotorClient):
         # DUE TO A BUG IN TAUGROUPBOX, WE NEED THE FULL MODEL NAME
         try:
             # In case the model is an attribute of a motor, get the device name
-            if not DeviceNameValidator().isValid(model):
+            # TODO: When sardana is moved to Taurus 4 replace this line by
+            # taurushelper.isValidName(model, [TaurusElementType.Device])
+            if not TangoDeviceNameValidator().isValid(model):
                 model = model.rpartition('/')[0]
             model = taurus.Factory().getDevice(model).getFullName()
             self.setMotor(model)
@@ -836,7 +844,6 @@ class PoolMotorTVLabelWidget(TaurusWidget):
         self.lbl_alias.taurusValueBuddy = self.taurusValueBuddy
         self.lbl_alias.setModel(model)
         TaurusWidget.setModel(self, model + '/Status')
-
         self.connect(self.taurusValueBuddy(), Qt.SIGNAL('expertViewChanged(bool)'), self.setExpertView)
         # Handle Power ON/OFF
         self.connect(self.btn_poweron, Qt.SIGNAL('clicked()'), self.setPowerOn)
@@ -881,10 +888,10 @@ class PoolMotorTVLabelWidget(TaurusWidget):
         event.accept()
 
     def mouseMoveEvent(self, event):
-        model = self.lbl_alias.getModelName()
+        model = self.taurusValueBuddy().getModelObj()
         mimeData = Qt.QMimeData()
         mimeData.setText(self.lbl_alias.text())
-        dev_name = model.rpartition('/')[0]
+        dev_name = model.getFullName()
         attr_name = dev_name + '/Position'
         mimeData.setData(TAURUS_DEV_MIME_TYPE, dev_name)
         mimeData.setData(TAURUS_ATTR_MIME_TYPE, attr_name)
@@ -1032,9 +1039,14 @@ class PoolMotorTVReadWidget(TaurusWidget):
 #                  WRITE WIDGET                  #
 ##################################################
 class PoolMotorTVWriteWidget(TaurusWidget):
-    
+
     layoutAlignment = Qt.Qt.AlignTop
-    
+    try:
+        # TODO: For Taurus 4 compatibility
+        applied = Qt.pyqtSignal()
+    except AttributeError:
+        pass
+
     def __init__(self, parent=None, designMode=False):
         TaurusWidget.__init__(self, parent, designMode)
         self.setLayout(Qt.QGridLayout())
@@ -1141,7 +1153,11 @@ class PoolMotorTVWriteWidget(TaurusWidget):
         self.btn_to_pos_press.setVisible(False)
 
         # IN EXPERT VIEW, WE HAVE TO FORWARD THE ''editingFinished()' SIGNAL FROM TaurusValueLineEdit TO Switcher
-        self.connect(self.le_write_absolute, Qt.SIGNAL(TaurusBaseWritableWidget.appliedSignalSignature), self.emitEditingFinished)
+        try:
+            self.connect(self.le_write_absolute, Qt.SIGNAL(TaurusBaseWritableWidget.appliedSignalSignature), self.emitEditingFinished)
+        except AttributeError:
+            # TODO: For Taurus 4 adaptation
+            self.le_write_absolute.applied.connect(self.emitEditingFinished)
         self.connect(self.btn_step_down, Qt.SIGNAL("clicked()"), self.emitEditingFinished)
         self.connect(self.btn_step_up, Qt.SIGNAL("clicked()"), self.emitEditingFinished)
         self.connect(self.btn_to_neg, Qt.SIGNAL("clicked()"), self.emitEditingFinished)
@@ -1262,7 +1278,11 @@ class PoolMotorTVWriteWidget(TaurusWidget):
         TaurusWidget.keyPressEvent(self, key_event)
 
     def emitEditingFinished(self):
-        self.emit(Qt.SIGNAL(TaurusBaseWritableWidget.appliedSignalSignature))
+        try:
+            self.emit(Qt.SIGNAL(TaurusBaseWritableWidget.appliedSignalSignature))
+        except AttributeError:
+            # TODO: For Taurus 4 adaptation
+            self.applied.emit()
 
 
 ##################################################
@@ -1296,10 +1316,10 @@ class PoolMotorTV(TaurusValue):
     '''
     def __init__(self, parent=None, designMode=False):
         TaurusValue.__init__(self, parent=parent, designMode=designMode)
-        self.setLabelWidgetClass('PoolMotorTVLabelWidget')
-        self.setReadWidgetClass('PoolMotorTVReadWidget')
-        self.setWriteWidgetClass('PoolMotorTVWriteWidget')
-        self.setUnitsWidgetClass('PoolMotorTVUnitsWidget')
+        self.setLabelWidgetClass(PoolMotorTVLabelWidget)
+        self.setReadWidgetClass(PoolMotorTVReadWidget)
+        self.setWriteWidgetClass(PoolMotorTVWriteWidget)
+        self.setUnitsWidgetClass(PoolMotorTVUnitsWidget)
 
         self.setLabelConfig('dev_alias')
 
@@ -1343,7 +1363,6 @@ class PoolMotorTV(TaurusValue):
             if model == '' or model is None:
                 self.motor_dev = None
                 return
-
             self.motor_dev = taurus.Device(model)
 
             # CONFIGURE A LISTENER IN ORDER TO UPDATE LIMIT SWITCHES STATES
@@ -1524,7 +1543,6 @@ def main():
     import taurus.qt.qtgui.application
     import taurus.core.util.argparse
     from taurus.qt.qtgui.panel import TaurusForm
-
     parser = taurus.core.util.argparse.get_taurus_parser()
     parser.usage = "%prog [options] [<motor1> [<motor2>] ...]"
 
@@ -1548,7 +1566,7 @@ def main():
 
     # 1) Test PoolMotorSlim motor widget
     form_pms = TaurusForm()
-    pms_widget_class = 'taurus.qt.qtgui.extra_pool.PoolMotorSlim'
+    pms_widget_class = 'sardana.taurus.qt.qtgui.extra_pool.PoolMotorSlim'
     pms_tgclass_map = {'SimuMotor':(pms_widget_class, (), {}),
                        'Motor':(pms_widget_class, (), {}),
                        'PseudoMotor':(pms_widget_class, (), {})}
@@ -1560,7 +1578,7 @@ def main():
     # 2) Test PoolMotorTV motor widget
     form_tv = TaurusForm()
     form_tv.setModifiableByUser(True)
-    tv_widget_class = 'taurus.qt.qtgui.extra_pool.PoolMotorTV'
+    tv_widget_class = 'sardana.taurus.qt.qtgui.extra_pool.PoolMotorTV'
     tv_tgclass_map = {'SimuMotor':(tv_widget_class, (), {}),
                       'Motor':(tv_widget_class, (), {}),
                       'PseudoMotor':(tv_widget_class, (), {})}
diff --git a/src/sardana/taurus/qt/qtgui/extra_pool/ui/PoolMotorSlim.ui b/src/sardana/taurus/qt/qtgui/extra_pool/ui/PoolMotorSlim.ui
index 6c6141b..9233390 100644
--- a/src/sardana/taurus/qt/qtgui/extra_pool/ui/PoolMotorSlim.ui
+++ b/src/sardana/taurus/qt/qtgui/extra_pool/ui/PoolMotorSlim.ui
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
 <ui version="4.0">
  <class>PoolMotorSlim</class>
  <widget class="TaurusWidget" name="PoolMotorSlim">
@@ -5,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>487</width>
-    <height>61</height>
+    <width>549</width>
+    <height>212</height>
    </rect>
   </property>
   <property name="windowTitle">
@@ -22,12 +23,12 @@
    <item row="0" column="0">
     <widget class="TaurusGroupBox" name="motorGroupBox">
      <property name="sizePolicy">
-      <sizepolicy vsizetype="Fixed" hsizetype="Preferred">
+      <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
        <horstretch>0</horstretch>
        <verstretch>0</verstretch>
       </sizepolicy>
      </property>
-     <property name="showText" stdset="0">
+     <property name="showText">
       <bool>false</bool>
      </property>
      <layout class="QGridLayout" name="gridLayout">
@@ -37,13 +38,19 @@
       <property name="spacing">
        <number>0</number>
       </property>
-      <item row="0" column="0">
-       <widget class="QWidget" native="1" name="taurusValueContainer">
-        <property name="sizePolicy">
-         <sizepolicy vsizetype="Preferred" hsizetype="Expanding">
-          <horstretch>0</horstretch>
-          <verstretch>0</verstretch>
-         </sizepolicy>
+      <item row="0" column="2">
+       <widget class="QPushButton" name="btnStop">
+        <property name="maximumSize">
+         <size>
+          <width>30</width>
+          <height>16777215</height>
+         </size>
+        </property>
+        <property name="toolTip">
+         <string>Stops the motor</string>
+        </property>
+        <property name="text">
+         <string>S</string>
         </property>
        </widget>
       </item>
@@ -55,7 +62,7 @@
         <item>
          <widget class="QPushButton" name="btnMin">
           <property name="sizePolicy">
-           <sizepolicy vsizetype="Maximum" hsizetype="Fixed">
+           <sizepolicy hsizetype="Fixed" vsizetype="Maximum">
             <horstretch>0</horstretch>
             <verstretch>0</verstretch>
            </sizepolicy>
@@ -83,7 +90,7 @@
         <item>
          <widget class="QPushButton" name="btnGoToNeg">
           <property name="sizePolicy">
-           <sizepolicy vsizetype="Maximum" hsizetype="Fixed">
+           <sizepolicy hsizetype="Fixed" vsizetype="Maximum">
             <horstretch>0</horstretch>
             <verstretch>0</verstretch>
            </sizepolicy>
@@ -111,7 +118,7 @@
         <item>
          <widget class="QPushButton" name="btnGoToNegPress">
           <property name="sizePolicy">
-           <sizepolicy vsizetype="Maximum" hsizetype="Fixed">
+           <sizepolicy hsizetype="Fixed" vsizetype="Maximum">
             <horstretch>0</horstretch>
             <verstretch>0</verstretch>
            </sizepolicy>
@@ -126,14 +133,14 @@
            <string>Moves the motor towards negative limit while pressed</string>
           </property>
           <property name="text">
-           <string>«</string>
+           <string>«</string>
           </property>
          </widget>
         </item>
         <item>
          <widget class="QPushButton" name="btnGoToNegInc">
           <property name="sizePolicy">
-           <sizepolicy vsizetype="Maximum" hsizetype="Fixed">
+           <sizepolicy hsizetype="Fixed" vsizetype="Maximum">
             <horstretch>0</horstretch>
             <verstretch>0</verstretch>
            </sizepolicy>
@@ -171,7 +178,7 @@
         <item>
          <widget class="QPushButton" name="btnGoToPosInc">
           <property name="sizePolicy">
-           <sizepolicy vsizetype="Fixed" hsizetype="Fixed">
+           <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
             <horstretch>0</horstretch>
             <verstretch>0</verstretch>
            </sizepolicy>
@@ -193,7 +200,7 @@
         <item>
          <widget class="QPushButton" name="btnGoToPosPress">
           <property name="sizePolicy">
-           <sizepolicy vsizetype="Fixed" hsizetype="Fixed">
+           <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
             <horstretch>0</horstretch>
             <verstretch>0</verstretch>
            </sizepolicy>
@@ -208,14 +215,14 @@
            <string>Moves the motor towards positive limit while pressed</string>
           </property>
           <property name="text">
-           <string>»</string>
+           <string>»</string>
           </property>
          </widget>
         </item>
         <item>
          <widget class="QPushButton" name="btnGoToPos">
           <property name="sizePolicy">
-           <sizepolicy vsizetype="Fixed" hsizetype="Fixed">
+           <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
             <horstretch>0</horstretch>
             <verstretch>0</verstretch>
            </sizepolicy>
@@ -237,7 +244,7 @@
         <item>
          <widget class="QPushButton" name="btnMax">
           <property name="sizePolicy">
-           <sizepolicy vsizetype="Fixed" hsizetype="Fixed">
+           <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
             <horstretch>0</horstretch>
             <verstretch>0</verstretch>
            </sizepolicy>
@@ -261,8 +268,18 @@
         </item>
        </layout>
       </item>
-      <item row="0" column="2">
-       <widget class="QPushButton" name="btnStop">
+      <item row="0" column="0">
+       <widget class="QWidget" name="taurusValueContainer" native="true">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="4">
+       <widget class="TaurusLauncherButton" name="btnCfg">
         <property name="maximumSize">
          <size>
           <width>30</width>
@@ -270,31 +287,25 @@
          </size>
         </property>
         <property name="toolTip">
-         <string>Stops the motor</string>
+         <string>Configures the motor</string>
         </property>
         <property name="text">
-         <string>S</string>
+         <string>Cfg</string>
         </property>
        </widget>
       </item>
-      <item row="0" column="3">
-       <widget class="QPushButton" name="btnHome">
-        <property name="maximumSize">
-         <size>
-          <width>30</width>
-          <height>16777215</height>
-         </size>
-        </property>
-        <property name="toolTip">
-         <string>Goes Home</string>
+      <item row="1" column="0" colspan="5">
+       <widget class="TaurusLabel" name="lblStatus">
+        <property name="model">
+         <string>/Status</string>
         </property>
-        <property name="text">
-         <string>H</string>
+        <property name="useParentModel">
+         <bool>true</bool>
         </property>
        </widget>
       </item>
-      <item row="0" column="4">
-       <widget class="TaurusLauncherButton" name="btnCfg">
+      <item row="0" column="3">
+       <widget class="QPushButton" name="btnHome">
         <property name="maximumSize">
          <size>
           <width>30</width>
@@ -302,47 +313,10 @@
          </size>
         </property>
         <property name="toolTip">
-         <string>Configures the motor</string>
+         <string>Goes Home</string>
         </property>
         <property name="text">
-         <string>Cfg</string>
-        </property>
-       </widget>
-      </item>
-      <item row="1" column="0" colspan="5">
-       <widget class="TaurusValueLabel" name="lblStatus">
-        <property name="sizePolicy">
-         <sizepolicy vsizetype="Fixed" hsizetype="Expanding">
-          <horstretch>0</horstretch>
-          <verstretch>0</verstretch>
-         </sizepolicy>
-        </property>
-        <property name="font">
-         <font>
-          <pointsize>7</pointsize>
-         </font>
-        </property>
-        <property name="styleSheet">
-         <string notr="true">TauValueLabel {
-            border-style: outset;
-            border-width: 2px;
-            border-color: rgba(255,255,255,128);
-            background-color: transparent; color:black; }</string>
-        </property>
-        <property name="frameShape">
-         <enum>QFrame::StyledPanel</enum>
-        </property>
-        <property name="lineWidth">
-         <number>0</number>
-        </property>
-        <property name="model" stdset="0">
-         <string>/Status</string>
-        </property>
-        <property name="useParentModel" stdset="0">
-         <bool>true</bool>
-        </property>
-        <property name="showQuality" stdset="0">
-         <bool>false</bool>
+         <string>H</string>
         </property>
        </widget>
       </item>
@@ -353,28 +327,28 @@
  </widget>
  <customwidgets>
   <customwidget>
-   <class>TaurusWidget</class>
-   <extends>QWidget</extends>
-   <header>taurus.qt.qtgui.container</header>
-  </customwidget>
-  <customwidget>
    <class>TaurusLauncherButton</class>
    <extends>QPushButton</extends>
    <header>taurus.qt.qtgui.button</header>
   </customwidget>
   <customwidget>
-   <class>TaurusGroupBox</class>
-   <extends>QGroupBox</extends>
+   <class>TaurusWidget</class>
+   <extends>QWidget</extends>
    <header>taurus.qt.qtgui.container</header>
    <container>1</container>
   </customwidget>
   <customwidget>
-   <class>TaurusValueLabel</class>
+   <class>TaurusLabel</class>
    <extends>QLabel</extends>
    <header>taurus.qt.qtgui.display</header>
   </customwidget>
+  <customwidget>
+   <class>TaurusGroupBox</class>
+   <extends>QGroupBox</extends>
+   <header>taurus.qt.qtgui.container</header>
+   <container>1</container>
+  </customwidget>
  </customwidgets>
  <resources/>
  <connections/>
 </ui>
-
diff --git a/src/sardana/taurus/qt/qtgui/extra_sardana/expdescription.py b/src/sardana/taurus/qt/qtgui/extra_sardana/expdescription.py
index 3e90c8b..1795871 100644
--- a/src/sardana/taurus/qt/qtgui/extra_sardana/expdescription.py
+++ b/src/sardana/taurus/qt/qtgui/extra_sardana/expdescription.py
@@ -98,7 +98,12 @@ class ExpDescriptionEditor(Qt.QWidget, TaurusBaseWidget):
         self.connect(self.ui.filenameLE, Qt.SIGNAL('textEdited (QString)'), self.onFilenameLEEdited)
         self.connect(self.ui.channelEditor.getQModel(), Qt.SIGNAL('dataChanged (QModelIndex, QModelIndex)'), self._updateButtonBox)
         self.connect(self.ui.channelEditor.getQModel(), Qt.SIGNAL('modelReset ()'), self._updateButtonBox)
-        self.connect(self.ui.preScanList, Qt.SIGNAL('dataChanged'), self.onPreScanSnapshotChanged)
+        preScanList = self.ui.preScanList
+        self.connect(preScanList, Qt.SIGNAL('dataChanged'),
+                     self.onPreScanSnapshotChanged)
+        #TODO: For Taurus 4 compatibility
+        if hasattr(preScanList, "dataChangedSignal"):
+            preScanList.dataChangedSignal.connect(self.onPreScanSnapshotChanged)
         self.connect(self.ui.choosePathBT, Qt.SIGNAL('clicked ()'), self.onChooseScanDirButtonClicked)
         
         self.__plotManager = None
@@ -210,8 +215,12 @@ class ExpDescriptionEditor(Qt.QWidget, TaurusBaseWidget):
 
         #set the system snapshot list
         psl = self._localConfig.get('PreScanSnapshot')  #I get it before clearing because clear() changes the _localConfig
+        # TODO: For Taurus 4 compatibility
+        psl_fullname = []
+        for name, display in psl:
+            psl_fullname.append(("tango://%s" % name, display))
         self.ui.preScanList.clear()
-        self.ui.preScanList.addModels(psl)
+        self.ui.preScanList.addModels(psl_fullname)
 
         #other settings
         self.ui.filenameLE.setText(", ".join(self._localConfig['ScanFile']))
@@ -360,9 +369,11 @@ class ExpDescriptionEditor(Qt.QWidget, TaurusBaseWidget):
         for e in items:
             nfo = ms.getElementInfo(e.src)
             if nfo is None:
-                preScanList.append((e.src, e.display))
+                full_name = e.src; display = e.display
             else:
-                preScanList.append((nfo.full_name, nfo.name))
+                full_name = nfo.full_name; display = nfo.name
+            # TODO: For Taurus 4 compatibility
+            preScanList.append((full_name.lstrip("tango://"), display))
         self._localConfig['PreScanSnapshot'] = preScanList
         self._setDirty(True)
         
diff --git a/src/sardana/taurus/qt/qtgui/extra_sardana/measurementgroup.py b/src/sardana/taurus/qt/qtgui/extra_sardana/measurementgroup.py
index 23fb8df..eca78d8 100644
--- a/src/sardana/taurus/qt/qtgui/extra_sardana/measurementgroup.py
+++ b/src/sardana/taurus/qt/qtgui/extra_sardana/measurementgroup.py
@@ -888,9 +888,27 @@ class MntGrpChannelEditor(TaurusBaseTableWidget):
         tableView.setItemDelegate(self._delegate)
         tableView.setSortingEnabled(False)
         self.connect(self._editorBar, Qt.SIGNAL("addTriggered"), self.addChannel)
+        #TODO: For Taurus 4 compatibility
+        if hasattr(self._editorBar, "addTriggered"):
+            self._editorBar.addTriggered.connect(self.addChannel)
         self.connect(self._editorBar, Qt.SIGNAL("removeTriggered"), self.removeChannels)
+        #TODO: For Taurus 4 compatibility
+        if hasattr(self._editorBar, "removeTriggered"):
+            self._editorBar.removeTriggered.connect(self.removeChannels)
         self.connect(self._editorBar, Qt.SIGNAL("moveUpTriggered"), self.moveUpChannel)
+        #TODO: For Taurus 4 compatibility
+        if hasattr(self._editorBar, "moveUpTriggered"):
+            self._editorBar.moveUpTriggered.connect(self.moveUpChannel)
         self.connect(self._editorBar, Qt.SIGNAL("moveDownTriggered"), self.moveDownChannel)
+        #TODO: For Taurus 4 compatibility
+        if hasattr(self._editorBar, "moveDownTriggered"):
+            self._editorBar.moveDownTriggered.connect(self.moveDownChannel)
+        self.connect(self._editorBar, Qt.SIGNAL("moveTopTriggered"), self.moveTopChannel)
+        if hasattr(self._editorBar, "moveTopTriggered"):
+            self._editorBar.moveTopTriggered.connect(self.moveTopChannel)
+        self.connect(self._editorBar, Qt.SIGNAL("moveBottomTriggered"), self.moveBottomChannel)
+        if hasattr(self._editorBar, "moveBottomTriggered"):
+            self._editorBar.moveBottomTriggered.connect(self.moveBottomChannel)
         return tableView
 
     def createToolArea(self):
@@ -933,17 +951,48 @@ class MntGrpChannelEditor(TaurusBaseTableWidget):
         chnames = [ch.itemData()[0] for ch in channels]
         self.getQModel().removeChannels(chnames)
 
+    def _getSelectedChannel(self):
+        channels = self.selectedItems()
+        if len(channels) != 1:
+            return None
+        return channels[0]
+
+    def moveBottomChannel(self):
+        channel = self._getSelectedChannel()
+        if channel is None:
+            return
+        row = channel.row()
+        parent = channel.parent()
+        if row >= parent.childCount() - 1:
+            return
+        else:
+            # TODO: optimize it if necessary. Instead of moving one by one,
+            # try to remove the item from the list and insert it at the bottom.
+            self.moveDownChannel()
+            return self.moveBottomChannel()
+
+    def moveTopChannel(self):
+        channel = self._getSelectedChannel()
+        if channel is None:
+            return
+        row = channel.row()
+        if row < 1:
+            return
+        else:
+            # TODO: optimize it if necessary. Instead of moving one by one,
+            # try to remove the item from the list and insert it at the top.
+            self.moveUpChannel()
+            return self.moveTopChannel()
+
     def moveUpChannel(self, channel=None):
         if channel is None:
-            channels = self.selectedItems()
-            if len(channels) != 1:
+            channel = self._getSelectedChannel()
+            if channel is None:
                 return
-            channel = channels[0]
         parent = channel.parent()
         row = channel.row()
         if row < 1:
             return
-
         model = self.getQModel()
         model.swapChannels(parent, row, row - 1)
         idx = model.index(row - 1, 0)
@@ -951,10 +1000,9 @@ class MntGrpChannelEditor(TaurusBaseTableWidget):
 
     def moveDownChannel(self, channel=None):
         if channel is None:
-            channels = self.selectedItems()
-            if len(channels) != 1:
+            channel = self._getSelectedChannel()
+            if channel is None:
                 return
-            channel = channels[0]
         parent = channel.parent()
         row = channel.row()
         if row >= parent.childCount() - 1:

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/sardana.git



More information about the debian-science-commits mailing list