New directory tree, with preprocessor/ inside interpretor/.
[Faustine.git] / interpretor / preprocessor / faust-0.9.47mr3 / architecture / gui / faustqt.h
diff --git a/interpretor/preprocessor/faust-0.9.47mr3/architecture/gui/faustqt.h b/interpretor/preprocessor/faust-0.9.47mr3/architecture/gui/faustqt.h
new file mode 100644 (file)
index 0000000..46aab5b
--- /dev/null
@@ -0,0 +1,1753 @@
+/************************************************************************\r
+ ************************************************************************\r
+    FAUST Architecture File\r
+       Copyright (C) 2003-2011 GRAME, Centre National de Creation Musicale\r
+    ---------------------------------------------------------------------\r
+    This Architecture section is free software; you can redistribute it\r
+    and/or modify it under the terms of the GNU General Public License\r
+       as published by the Free Software Foundation; either version 3 of\r
+       the License, or (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+       along with this program; If not, see <http://www.gnu.org/licenses/>.\r
+\r
+ ************************************************************************\r
+ ************************************************************************/\r
+#ifndef __faustqt__\r
+#define __faustqt__\r
+\r
+#include <cassert>\r
+#include <cmath>\r
+#include <fstream>\r
+#include <iostream>\r
+#include <list>\r
+#include <map>\r
+#include <set>\r
+#include <vector>\r
+#include <stack>\r
+\r
+#include <QApplication>\r
+#include <QCheckBox>\r
+#include <QColormap>\r
+#include <QDial>\r
+#include <QDoubleSpinBox>\r
+#include <QGroupBox>\r
+#include <QHBoxLayout>\r
+#include <QLayout>\r
+#include <QMouseEvent>\r
+#include <QObject>\r
+#include <QPainter>\r
+#include <QProgressBar>\r
+#include <QPushButton>\r
+#include <QRadialGradient>\r
+#include <QSlider>\r
+#include <QStyle>\r
+#include <QTabWidget>\r
+#include <QTimer>\r
+#include <QToolTip>\r
+#include <QVBoxLayout>\r
+#include <QWheelEvent>\r
+#include <QWidget>\r
+#include <QtGui>\r
+\r
+#include "GUI.h"\r
+\r
+//----------------------------------\r
+\r
+// for compatibility\r
+#define minValue minimum\r
+#define maxValue maximum\r
+\r
+\r
+using namespace std;\r
+\r
+\r
+//==============================BEGIN QSYNTHKNOB=====================================\r
+//\r
+//   qsynthknob and qsynthDialVokiStyle borrowed from qsynth-0.3.3 by Rui Nuno Capela\r
+//   This widget is based on a design by Thorsten Wilms,\r
+//   implemented by Chris Cannam in Rosegarden,\r
+//   adapted for QSynth by Pedro Lopez-Cabanillas,\r
+//   improved for Qt4 by David Garcia Garzon.\r
+//\r
+\r
+#define DIAL_MIN      (0.25 * M_PI)\r
+#define DIAL_MAX      (1.75 * M_PI)\r
+#define DIAL_RANGE    (DIAL_MAX - DIAL_MIN)\r
+\r
+class qsynthDialVokiStyle : public QCommonStyle\r
+{\r
+public:\r
+       qsynthDialVokiStyle() {};\r
+       virtual ~qsynthDialVokiStyle() {};\r
+\r
+    virtual void drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, const QWidget *widget = 0) const\r
+       {\r
+               if (cc != QStyle::CC_Dial)\r
+               {\r
+                       QCommonStyle::drawComplexControl(cc, opt, p, widget);\r
+                       return;\r
+               }\r
+\r
+               const QStyleOptionSlider *dial = qstyleoption_cast<const QStyleOptionSlider *>(opt);\r
+               if (dial == NULL)\r
+                       return;\r
+\r
+               double angle = DIAL_MIN // offset\r
+                       + (DIAL_RANGE *\r
+                               (double(dial->sliderValue - dial->minimum) /\r
+                               (double(dial->maximum - dial->minimum))));\r
+               int degrees = int(angle * 180.0 / M_PI);\r
+               int side = dial->rect.width() < dial->rect.height() ? dial->rect.width() : dial->rect.height();\r
+               int xcenter = dial->rect.width() / 2;\r
+               int ycenter = dial->rect.height() / 2;\r
+               int notchWidth   = 1 + side / 400;\r
+               int pointerWidth = 2 + side / 30;\r
+               int scaleShadowWidth = 1 + side / 100;\r
+               int knobBorderWidth = 0;\r
+               int ns = dial->tickInterval;\r
+               int numTicks = 1 + (dial->maximum + ns - dial->minimum) / ns;\r
+               int indent = int(0.15 * side) + 2;\r
+               int knobWidth = side - 2 * indent;\r
+               int shineFocus = knobWidth / 4;\r
+               int shineCenter = knobWidth / 5;\r
+               int shineExtension = shineCenter * 4;\r
+               int shadowShift = shineCenter * 2;\r
+               int meterWidth = side - 2 * scaleShadowWidth;\r
+\r
+               QPalette pal = opt->palette;\r
+               QColor knobColor = pal.mid().color();\r
+               QColor borderColor = knobColor.light();\r
+               QColor meterColor = (dial->state & State_Enabled) ?\r
+                            QColor("orange") : pal.mid().color();\r
+                         // pal.highlight().color() : pal.mid().color();\r
+               QColor background = pal.window().color();\r
+\r
+               p->save();\r
+               p->setRenderHint(QPainter::Antialiasing, true);\r
+\r
+               // The bright metering bit...\r
+\r
+               QConicalGradient meterShadow(xcenter, ycenter, -90);\r
+               meterShadow.setColorAt(0, meterColor.dark());\r
+               meterShadow.setColorAt(0.5, meterColor);\r
+               meterShadow.setColorAt(1.0, meterColor.light().light());\r
+               p->setBrush(meterShadow);\r
+               p->setPen(Qt::transparent);\r
+               p->drawPie(xcenter - meterWidth / 2, ycenter - meterWidth / 2,\r
+                       meterWidth, meterWidth, (180 + 45) * 16, -(degrees - 45) * 16);\r
+\r
+               // Knob projected shadow\r
+               QRadialGradient projectionGradient(\r
+                       xcenter + shineCenter, ycenter + shineCenter,\r
+                       shineExtension, xcenter + shadowShift, ycenter + shadowShift);\r
+               projectionGradient.setColorAt(0, QColor(  0, 0, 0, 100));\r
+               projectionGradient.setColorAt(1, QColor(200, 0, 0,  10));\r
+               QBrush shadowBrush(projectionGradient);\r
+               p->setBrush(shadowBrush);\r
+               p->drawEllipse(xcenter - shadowShift, ycenter - shadowShift,\r
+                       knobWidth, knobWidth);\r
+\r
+               // Knob body and face...\r
+\r
+               QPen pen;\r
+               pen.setColor(knobColor);\r
+               pen.setWidth(knobBorderWidth);\r
+               p->setPen(pen);\r
+\r
+               QRadialGradient gradient(\r
+                       xcenter - shineCenter, ycenter - shineCenter,\r
+                       shineExtension, xcenter - shineFocus, ycenter - shineFocus);\r
+               gradient.setColorAt(0.2, knobColor.light().light());\r
+               gradient.setColorAt(0.5, knobColor);\r
+               gradient.setColorAt(1.0, knobColor.dark(150));\r
+               QBrush knobBrush(gradient);\r
+               p->setBrush(knobBrush);\r
+               p->drawEllipse(xcenter - knobWidth / 2, ycenter - knobWidth / 2,\r
+                       knobWidth, knobWidth);\r
+\r
+               // Tick notches...\r
+\r
+               p->setBrush(Qt::NoBrush);\r
+\r
+               if (dial->subControls & QStyle::SC_DialTickmarks)\r
+               {\r
+                       pen.setColor(pal.dark().color());\r
+                       pen.setWidth(notchWidth);\r
+                       p->setPen(pen);\r
+                       double hyp = double(side - scaleShadowWidth) / 2.0;\r
+                       double len = hyp / 4;\r
+                       for (int i = 0; i < numTicks; ++i) {\r
+                               int div = numTicks;\r
+                               if (div > 1) --div;\r
+                               bool internal = (i != 0 && i != numTicks - 1);\r
+                               double angle = DIAL_MIN\r
+                                       + (DIAL_MAX - DIAL_MIN) * i / div;\r
+                               double dir = (internal ? -1 : len);\r
+                               double sinAngle = sin(angle);\r
+                               double cosAngle = cos(angle);\r
+                               double x0 = xcenter - (hyp - len) * sinAngle;\r
+                               double y0 = ycenter + (hyp - len) * cosAngle;\r
+                               double x1 = xcenter - (hyp + dir) * sinAngle;\r
+                               double y1 = ycenter + (hyp + dir) * cosAngle;\r
+                               p->drawLine(QLineF(x0, y0, x1, y1));\r
+                       }\r
+               }\r
+\r
+               // Shadowing...\r
+\r
+               // Knob shadow...\r
+               if (knobBorderWidth > 0) {\r
+                       QLinearGradient inShadow(xcenter - side / 4, ycenter - side / 4,\r
+                               xcenter + side / 4, ycenter + side / 4);\r
+                       inShadow.setColorAt(0.0, borderColor.light());\r
+                       inShadow.setColorAt(1.0, borderColor.dark());\r
+                       p->setPen(QPen(QBrush(inShadow), knobBorderWidth * 7 / 8));\r
+                       p->drawEllipse(xcenter - side / 2 + indent,\r
+                               ycenter - side / 2 + indent,\r
+                               side - 2 * indent, side - 2 * indent);\r
+               }\r
+\r
+               // Scale shadow...\r
+               QLinearGradient outShadow(xcenter - side / 3, ycenter - side / 3,\r
+                       xcenter + side / 3, ycenter + side / 3);\r
+               outShadow.setColorAt(0.0, background.dark().dark());\r
+               outShadow.setColorAt(1.0, background.light().light());\r
+               p->setPen(QPen(QBrush(outShadow), scaleShadowWidth));\r
+               p->drawArc(xcenter - side / 2 + scaleShadowWidth / 2,\r
+                       ycenter - side / 2 + scaleShadowWidth / 2,\r
+                       side - scaleShadowWidth, side - scaleShadowWidth, -45 * 16, 270 * 16);\r
+\r
+               // Pointer notch...\r
+\r
+               double hyp = double(side) / 2.0;\r
+               double len = hyp - indent - 1;\r
+\r
+               double x = xcenter - len * sin(angle);\r
+               double y = ycenter + len * cos(angle);\r
+\r
+               QColor pointerColor = pal.dark().color();\r
+               pen.setColor((dial->state & State_Enabled) ? pointerColor.dark(140) : pointerColor);\r
+               pen.setWidth(pointerWidth + 2);\r
+               p->setPen(pen);\r
+               p->drawLine(QLineF(xcenter, ycenter, x, y));\r
+               pen.setColor((dial->state & State_Enabled) ? pointerColor.light() : pointerColor.light(140));\r
+               pen.setWidth(pointerWidth);\r
+               p->setPen(pen);\r
+               p->drawLine(QLineF(xcenter - 1, ycenter - 1, x - 1, y - 1));\r
+\r
+               // done\r
+               p->restore();\r
+       }\r
+\r
+};\r
+//\r
+//===============================END QSYNTHKNOB======================================\r
+\r
+\r
+//==============================BEGIN DISPLAYS===================================\r
+//\r
+// This section constains displays, passive QT widgets that displays values in\r
+// different ways, in particular bargraphs\r
+//\r
+\r
+/**\r
+ * An abstract widget that display a value in a range\r
+ */\r
+class AbstractDisplay : public QWidget\r
+{\r
+    protected :\r
+        float           fMin;\r
+        float           fMax;\r
+        float           fValue;\r
+\r
+    public:\r
+\r
+        AbstractDisplay (float lo, float hi) : fMin(lo), fMax(hi), fValue(lo)\r
+        {\r
+        }\r
+\r
+        /**\r
+         * set the range of displayed values\r
+         */\r
+        virtual void setRange(float lo, float hi)\r
+        {\r
+            fMin = lo;\r
+            fMax = hi;\r
+        }\r
+\r
+        /**\r
+         * set the value to be displayed\r
+         */\r
+        virtual void setValue(float v)\r
+        {\r
+            if (v < fMin)       v = fMin;\r
+            else if (v > fMax)  v = fMax;\r
+\r
+            if (v != fValue) {\r
+                fValue = v;\r
+                update();\r
+            }\r
+        }\r
+};\r
+\r
+\r
+/**\r
+ * Displays dB values using a scale of colors\r
+ */\r
+class dbAbstractDisplay : public AbstractDisplay\r
+{\r
+    protected :\r
+\r
+        float           fScaleMin;\r
+        float           fScaleMax;\r
+        vector<int>     fLevel;\r
+        vector<QBrush>  fBrush;\r
+\r
+\r
+        /**\r
+        * Convert a dB value into a scale between 0 and 1 (following IEC standard ?)\r
+        */\r
+        float dB2Scale ( float dB ) const\r
+        {\r
+            float fScale = 1.0f;\r
+\r
+            /*if (dB < -70.0f)\r
+                fScale = 0.0f;\r
+            else*/ if (dB < -60.0f)\r
+                fScale = (dB + 70.0f) * 0.0025f;\r
+            else if (dB < -50.0f)\r
+                fScale = (dB + 60.0f) * 0.005f + 0.025f;\r
+            else if (dB < -40.0)\r
+                fScale = (dB + 50.0f) * 0.0075f + 0.075f;\r
+            else if (dB < -30.0f)\r
+                fScale = (dB + 40.0f) * 0.015f + 0.15f;\r
+            else if (dB < -20.0f)\r
+                fScale = (dB + 30.0f) * 0.02f + 0.3f;\r
+            else if (dB < -0.001f || dB > 0.001f)  /* if (dB < 0.0f) */\r
+                fScale = (dB + 20.0f) * 0.025f + 0.5f;\r
+\r
+            return fScale;\r
+        }\r
+\r
+\r
+        /**\r
+         * Create the scale of colors used to paint the bargraph in relation to the levels\r
+         * The parameter x indicates the direction of the gradient. x=1 means an horizontal\r
+         * gradient typically used by a vertical bargraph, and x=0 a vertical gradient.\r
+         */\r
+        void initLevelsColors(int x)\r
+        {\r
+            int alpha = 200;\r
+            { // level until -10 dB\r
+                QColor c(40, 160, 40, alpha);\r
+                QLinearGradient g(0,0,x,1-x);\r
+                g.setCoordinateMode(QGradient::ObjectBoundingMode);\r
+                g.setColorAt(0.0,   c.lighter());\r
+                g.setColorAt(0.2,   c);\r
+                g.setColorAt(0.8,   c);\r
+                g.setColorAt(0.9,   c.darker(120));\r
+\r
+                fLevel.push_back(-10);\r
+                fBrush.push_back(QBrush(g));\r
+            }\r
+\r
+            { // level until -6 dB\r
+                QColor c(160, 220, 20, alpha);\r
+                QLinearGradient g(0,0,x,1-x);\r
+                g.setCoordinateMode(QGradient::ObjectBoundingMode);\r
+                g.setColorAt(0.0,   c.lighter());\r
+                g.setColorAt(0.2,   c);\r
+                g.setColorAt(0.8,   c);\r
+                g.setColorAt(0.9,   c.darker(120));\r
+\r
+                fLevel.push_back(-6);\r
+                fBrush.push_back(QBrush(g));\r
+            }\r
+\r
+            { // level until -3 dB\r
+                QColor c(220, 220, 20, alpha);\r
+                QLinearGradient g(0,0,x,1-x);\r
+                g.setCoordinateMode(QGradient::ObjectBoundingMode);\r
+                g.setColorAt(0.0,   c.lighter());\r
+                g.setColorAt(0.2,   c);\r
+                g.setColorAt(0.8,   c);\r
+                g.setColorAt(0.9,   c.darker(120));\r
+\r
+                fLevel.push_back(-3);\r
+                fBrush.push_back(QBrush(g));\r
+            }\r
+\r
+            { // level until -0 dB\r
+                QColor c(240, 160, 20, alpha);\r
+                QLinearGradient g(0,0,x,1-x);\r
+                g.setCoordinateMode(QGradient::ObjectBoundingMode);\r
+                g.setColorAt(0.0,   c.lighter());\r
+                g.setColorAt(0.2,   c);\r
+                g.setColorAt(0.8,   c);\r
+                g.setColorAt(0.9,   c.darker(120));\r
+\r
+                fLevel.push_back(0);\r
+                fBrush.push_back(QBrush(g));\r
+            }\r
+\r
+            { // until 10 dB (and over because last one)\r
+                QColor c(240,  0, 20, alpha);   // ColorOver\r
+                QLinearGradient g(0,0,x,1-x);\r
+                g.setCoordinateMode(QGradient::ObjectBoundingMode);\r
+                g.setColorAt(0.0,   c.lighter());\r
+                g.setColorAt(0.2,   c);\r
+                g.setColorAt(0.8,   c);\r
+                g.setColorAt(0.9,   c.darker(120));\r
+\r
+                fLevel.push_back(+10);\r
+                fBrush.push_back(QBrush(g));\r
+            }\r
+\r
+        }\r
+\r
+    public:\r
+\r
+        dbAbstractDisplay(float lo, float hi) : AbstractDisplay(lo,hi)\r
+        {\r
+        }\r
+\r
+        /**\r
+         * set the range of displayed values\r
+         */\r
+        virtual void setRange(float lo, float hi)\r
+        {\r
+            AbstractDisplay::setRange(lo, hi);\r
+            fScaleMin = dB2Scale(fMin);\r
+            fScaleMax = dB2Scale(fMax);\r
+        }\r
+};\r
+\r
+\r
+/**\r
+ * Small rectangular LED display which color changes with the level in dB\r
+ */\r
+class dbLED : public dbAbstractDisplay\r
+{\r
+    protected:\r
+\r
+        /**\r
+         * Draw the LED using a color depending of its value in dB\r
+         */\r
+        virtual void paintEvent ( QPaintEvent *)\r
+        {\r
+            QPainter painter(this);\r
+            painter.drawRect(rect());\r
+\r
+            if (fValue <= fLevel[0]) {\r
+\r
+                // interpolate the first color on the alpha channel\r
+                QColor c(40, 160, 40) ;\r
+                float a = (fValue-fMin)/(fLevel[0]-fMin);\r
+                c.setAlphaF(a);\r
+                painter.fillRect(rect(), c);\r
+\r
+            } else {\r
+\r
+                // find the minimal level > value\r
+                int l = fLevel.size()-1; while (fValue < fLevel[l] && l > 0) l--;\r
+                painter.fillRect(rect(), fBrush[l]);\r
+            }\r
+        }\r
+\r
+    public:\r
+\r
+        dbLED(float lo, float hi) : dbAbstractDisplay(lo,hi)\r
+        {\r
+            setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);\r
+            initLevelsColors(1);\r
+       }\r
+\r
+        virtual QSize sizeHint () const\r
+        {\r
+            return QSize(16, 8);\r
+        }\r
+};\r
+/**\r
+ * Small rectangular LED display which intensity (alpha channel) changes according to the value\r
+ */\r
+class LED : public AbstractDisplay\r
+{\r
+    QColor  fColor;\r
+\r
+    protected:\r
+\r
+        /**\r
+         * Draw the LED using a transparency depending of its value\r
+         */\r
+        virtual void paintEvent ( QPaintEvent *)\r
+        {\r
+            QPainter painter(this);\r
+            painter.drawRect(rect());\r
+            // interpolate the first color on the alpha channel\r
+            QColor c = fColor ;\r
+            float a = (fValue-fMin)/(fMax-fMin);\r
+            c.setAlphaF(a);\r
+            painter.fillRect(rect(), c);\r
+        }\r
+\r
+    public:\r
+\r
+        LED(float lo, float hi) : AbstractDisplay(lo,hi), fColor("yellow")\r
+        {\r
+            setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);\r
+       }\r
+\r
+        virtual QSize sizeHint () const\r
+        {\r
+            return QSize(16, 8);\r
+        }\r
+};\r
+\r
+\r
+\r
+/**\r
+ * A simple bargraph that detect automatically its direction\r
+ */\r
+class linBargraph : public AbstractDisplay\r
+{\r
+    protected :\r
+        QBrush  fBrush;\r
+\r
+        /**\r
+         * No scale implemented yet\r
+         */\r
+        void paintScale(QPainter* painter) const\r
+        {\r
+            painter->drawRect(0,0,width(),height());\r
+        }\r
+\r
+        /**\r
+         * The length of the rectangle is proportional to the value\r
+         */\r
+        void paintContent (QPainter* painter) const\r
+        {\r
+            int     w = width();\r
+            int     h = height();\r
+            float   v = (fValue-fMin)/(fMax-fMin);\r
+\r
+            if (h>w) {\r
+                // draw vertical rectangle\r
+                painter->fillRect(0,(1-v)*h,w, v*h, fBrush);\r
+            } else {\r
+                // draw horizontal rectangle\r
+                painter->fillRect(0, 0, h, v*w, fBrush);\r
+            }\r
+\r
+        }\r
+\r
+        virtual void paintEvent ( QPaintEvent *)\r
+        {\r
+            QPainter painter(this);\r
+            paintContent(&painter);\r
+            paintScale(&painter);\r
+        }\r
+\r
+    public:\r
+\r
+        linBargraph(float lo, float hi) : AbstractDisplay(lo,hi)\r
+        {\r
+            // compute the brush that will be used to\r
+            // paint the value\r
+            QColor c(0xffa500);                 // orange\r
+            int x = int(height() < width());    // gradient direction\r
+            QLinearGradient g(0,0,x,1-x);\r
+            g.setCoordinateMode(QGradient::ObjectBoundingMode);\r
+            g.setColorAt(0.0,   c.lighter());\r
+            g.setColorAt(0.2,   c);\r
+            g.setColorAt(0.8,   c);\r
+            g.setColorAt(0.9,   c.darker(120));\r
+            fBrush = QBrush(g);\r
+        }\r
+};\r
+\r
+\r
+/**\r
+ * A simple vertical bargraph\r
+ */\r
+class linVerticalBargraph : public linBargraph\r
+{\r
+    public:\r
+\r
+        linVerticalBargraph(float lo, float hi) : linBargraph(lo,hi)\r
+        {\r
+            setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);\r
+        }\r
+\r
+        virtual QSize sizeHint () const\r
+        {\r
+            return QSize(16, 128);\r
+        }\r
+};\r
+\r
+\r
+\r
+/**\r
+ * A simple horizontal bargraph\r
+ */\r
+class linHorizontalBargraph : public linBargraph\r
+{\r
+    public:\r
+\r
+        linHorizontalBargraph(float lo, float hi) : linBargraph(lo,hi)\r
+        {\r
+            setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);\r
+        }\r
+\r
+        virtual QSize sizeHint () const\r
+        {\r
+            return QSize(128, 16);\r
+        }\r
+};\r
+\r
+\r
+\r
+\r
+/**\r
+ * A dB Bargraph with a scale of colors\r
+ */\r
+class dbBargraph : public dbAbstractDisplay\r
+{\r
+    QBrush  fBackColor;\r
+\r
+    protected :\r
+\r
+        // These two abstract methods are implemented\r
+        // according to the vertical or horizontal direction\r
+        // in dbVerticalBargraph and dbHorizontalBargraph\r
+        virtual void paintMark(QPainter* painter, float v) const = 0;\r
+        virtual int paintSegment (QPainter* painter, int pos, float v, const QBrush& b) const = 0;\r
+\r
+        /**\r
+         * Draw the logarithmic scale\r
+         */\r
+        void paintScale(QPainter* painter) const\r
+        {\r
+            painter->fillRect(0,0,width(),height(), fBackColor);\r
+            painter->save();\r
+            painter->setPen(QColor(0x6699aa)); //0xffa500));\r
+            for (float v = -10; v > fMin; v -= 10) paintMark(painter, v);\r
+            for (float v = -6; v < fMax; v += 3) paintMark(painter, v);\r
+            painter->restore();\r
+        }\r
+\r
+\r
+        /**\r
+         * Draw the content using colored segments\r
+         */\r
+        void paintContent (QPainter* painter) const\r
+        {\r
+            int   l = fLevel.size();\r
+\r
+            float   p = -1;   // fake value indicates to start from border\r
+            int     n = 0;\r
+            // paint all the full segments < fValue\r
+            for (n=0; (n < l) && (fValue > fLevel[n]); n++) {\r
+                p = paintSegment(painter, p, fLevel[n], fBrush[n]);\r
+            }\r
+            // paint the last segment\r
+            if (n == l) n = n-1;\r
+            p=paintSegment(painter, p, fValue, fBrush[n]);\r
+\r
+            painter->drawRect(0,0,width(),height());\r
+       }\r
+\r
+\r
+        virtual void paintEvent ( QPaintEvent *)\r
+        {\r
+            QPainter painter(this);\r
+            paintScale(&painter);\r
+            paintContent(&painter);\r
+        }\r
+\r
+    public:\r
+\r
+        dbBargraph(float lo, float hi) : dbAbstractDisplay(lo,hi)\r
+        {\r
+\r
+            QFont f = this->font();\r
+            f.setPointSize(6);\r
+            this->setFont(f);\r
+\r
+            fBackColor = QBrush(QColor(20,20,20));\r
+        }\r
+};\r
+\r
+\r
+/**\r
+ * Vertical dB Bargraph\r
+ */\r
+class dbVerticalBargraph : public dbBargraph\r
+{\r
+    protected:\r
+        /**\r
+         * Convert a dB value into a vertical position\r
+         */\r
+        float dB2y (float dB) const\r
+        {\r
+            float s0 = fScaleMin;\r
+            float s1 = fScaleMax;\r
+            float sx = dB2Scale(dB);\r
+            int    h = height();\r
+\r
+            return h - h*(s0-sx)/(s0-s1);\r
+        }\r
+\r
+        /**\r
+         * Paint a vertical graduation mark\r
+         */\r
+        virtual void paintMark(QPainter* painter, float v) const\r
+        {\r
+            int n = 10;\r
+            int y = dB2y(v);\r
+            QRect r(0,y-n,width()-1,2*n);\r
+            if (v > 0.0) {\r
+                painter->drawText(r, Qt::AlignRight|Qt::AlignVCenter, QString::number(v).prepend('+'));\r
+            } else {\r
+                painter->drawText(r, Qt::AlignRight|Qt::AlignVCenter, QString::number(v));\r
+            }\r
+        }\r
+\r
+        /**\r
+         * Paint a color segment\r
+         */\r
+        virtual int paintSegment (QPainter* painter, int pos, float v, const QBrush& b) const\r
+        {\r
+            if (pos == -1) pos = height();\r
+            float y = dB2y(v);\r
+            painter->fillRect(0, y, width(), pos-y+1, b);\r
+            return y;\r
+        }\r
+\r
+\r
+    public:\r
+\r
+        dbVerticalBargraph(float lo, float hi) : dbBargraph(lo,hi)\r
+        {\r
+            setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);\r
+            initLevelsColors(1);\r
+        }\r
+\r
+        virtual QSize sizeHint () const\r
+        {\r
+            return QSize(18, 256);\r
+        }\r
+};\r
+\r
+/**\r
+ * Horizontal dB Bargraph\r
+ */\r
+class dbHorizontalBargraph : public dbBargraph\r
+{\r
+\r
+    protected:\r
+\r
+        /**\r
+         * Convert a dB value into an horizontal position\r
+         */\r
+        float dB2x (float dB) const\r
+        {\r
+            float s0 = fScaleMin;\r
+            float s1 = fScaleMax;\r
+            float sx = dB2Scale(dB);\r
+            int    w = width();\r
+\r
+            return w - w*(s1-sx)/(s1-s0);\r
+        }\r
+\r
+        /**\r
+         * Paint an horizontal graduation mark\r
+         */\r
+        void paintMark(QPainter* painter, float v) const\r
+        {\r
+            int n = 10;\r
+            int x = dB2x(v);\r
+            QRect r(x-n,0,2*n, height());\r
+            painter->drawText(r, Qt::AlignHCenter|Qt::AlignVCenter, QString::number(v));\r
+        }\r
+\r
+        /**\r
+         * Paint a horizontal color segment\r
+         */\r
+        int paintSegment (QPainter* painter, int pos, float v, const QBrush& b) const\r
+        {\r
+            if (pos == -1) pos = 0;\r
+            float x = dB2x(v);\r
+            painter->fillRect(pos, 0, x-pos, height(), b);\r
+            return x;\r
+        }\r
+\r
+\r
+    public:\r
+\r
+        dbHorizontalBargraph(float lo, float hi) : dbBargraph(lo,hi)\r
+        {\r
+            setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);\r
+            initLevelsColors(0);\r
+        }\r
+\r
+        virtual QSize sizeHint () const\r
+        {\r
+            return QSize(256, 18);\r
+        }\r
+\r
+};\r
+\r
+//\r
+//===============================END DISPLAYS====================================\r
+\r
+//============================= BEGIN GROUP LABEL METADATA===========================\r
+// Unlike widget's label, metadata inside group's label are not extracted directly by\r
+// the Faust compiler. Therefore they must be extracted within the architecture file\r
+//-----------------------------------------------------------------------------------\r
+//\r
+\r
+/**\r
+ * rmWhiteSpaces(): Remove the leading and trailing white spaces of a string\r
+ * (but not those in the middle of the string)\r
+ */\r
+static string rmWhiteSpaces(const string& s)\r
+{\r
+    size_t i = s.find_first_not_of(" \t");\r
+    size_t j = s.find_last_not_of(" \t");\r
+       if ( (i != string::npos) && (j != string::npos) ) {\r
+               return s.substr(i, 1+j-i);\r
+       } else {\r
+               return "";\r
+       }\r
+}\r
+\r
+/**\r
+ * Extracts metdata from a label : 'vol [unit: dB]' -> 'vol' + metadata(unit=dB)\r
+ */\r
+static void extractMetadata(const string& fulllabel, string& label, map<string, string>& metadata)\r
+{\r
+    enum {kLabel, kEscape1, kEscape2, kEscape3, kKey, kValue};\r
+    int state = kLabel; int deep = 0;\r
+    string key, value;\r
+\r
+    for (unsigned int i=0; i < fulllabel.size(); i++) {\r
+        char c = fulllabel[i];\r
+        switch (state) {\r
+            case kLabel :\r
+                assert (deep == 0);\r
+                switch (c) {\r
+                    case '\\' : state = kEscape1; break;\r
+                    case '[' : state = kKey; deep++; break;\r
+                    default : label += c;\r
+                }\r
+                break;\r
+\r
+            case kEscape1 :\r
+                label += c;\r
+                state = kLabel;\r
+                break;\r
+\r
+            case kEscape2 :\r
+                key += c;\r
+                state = kKey;\r
+                break;\r
+\r
+            case kEscape3 :\r
+                value += c;\r
+                state = kValue;\r
+                break;\r
+\r
+            case kKey :\r
+                assert (deep > 0);\r
+                switch (c) {\r
+                    case '\\' :  state = kEscape2;\r
+                                break;\r
+\r
+                    case '[' :  deep++;\r
+                                key += c;\r
+                                break;\r
+\r
+                    case ':' :  if (deep == 1) {\r
+                                    state = kValue;\r
+                                } else {\r
+                                    key += c;\r
+                                }\r
+                                break;\r
+                    case ']' :  deep--;\r
+                                if (deep < 1) {\r
+                                    metadata[rmWhiteSpaces(key)] = "";\r
+                                    state = kLabel;\r
+                                    key="";\r
+                                    value="";\r
+                                } else {\r
+                                    key += c;\r
+                                }\r
+                                break;\r
+                    default :   key += c;\r
+                }\r
+                break;\r
+\r
+            case kValue :\r
+                assert (deep > 0);\r
+                switch (c) {\r
+                    case '\\' : state = kEscape3;\r
+                                break;\r
+\r
+                    case '[' :  deep++;\r
+                                value += c;\r
+                                break;\r
+\r
+                    case ']' :  deep--;\r
+                                if (deep < 1) {\r
+                                    metadata[rmWhiteSpaces(key)]=rmWhiteSpaces(value);\r
+                                    state = kLabel;\r
+                                    key="";\r
+                                    value="";\r
+                                } else {\r
+                                    value += c;\r
+                                }\r
+                                break;\r
+                    default :   value += c;\r
+                }\r
+                break;\r
+\r
+            default :\r
+                cerr << "ERROR unrecognized state " << state << endl;\r
+        }\r
+    }\r
+    label = rmWhiteSpaces(label);\r
+}\r
+//\r
+//============================= END GROUP LABEL METADATA===========================\r
+\r
+\r
+/******************************************************************************\r
+*******************************************************************************\r
+\r
+                                                       IMPLEMENTATION OF GUI ITEMS\r
+                                                          (QT 4.3 for FAUST)\r
+\r
+*******************************************************************************\r
+*******************************************************************************/\r
+\r
+\r
+class uiButton : public QObject, public uiItem\r
+{\r
+    Q_OBJECT\r
+\r
+ public :\r
+       QAbstractButton*        fButton;\r
+\r
+       uiButton (GUI* ui, float* zone, QAbstractButton* b) : uiItem(ui, zone), fButton(b) {}\r
+\r
+\r
+       virtual void reflectZone()\r
+       {\r
+               float v = *fZone;\r
+               fCache = v;\r
+               fButton->setDown( v > 0.0 );\r
+       }\r
+\r
+ public slots :\r
+       void pressed()          { modifyZone(1.0); }\r
+       void released()         { modifyZone(0.0); }\r
+};\r
+\r
+\r
+class uiCheckButton : public QObject, public uiItem\r
+{\r
+    Q_OBJECT\r
+\r
+ public :\r
+       QCheckBox*      fCheckBox;\r
+\r
+       uiCheckButton (GUI* ui, float* zone, QCheckBox* b) : uiItem(ui, zone), fCheckBox(b) {}\r
+\r
+       virtual void reflectZone()\r
+       {\r
+               float v = *fZone;\r
+               fCache = v;\r
+               fCheckBox->setCheckState( (v < 0.5) ? Qt::Unchecked : Qt::Checked );\r
+       }\r
+\r
+ public slots :\r
+       void setState(int v)            { modifyZone(float(v>0)); }\r
+};\r
+\r
+\r
+class uiSlider : public QObject, public uiItem\r
+{\r
+    Q_OBJECT\r
+\r
+       int             faust2qt(float x)       { return int(0.5 + (x-fMin)/fStep); }\r
+       float   qt2faust (int v)        { return fMin + v*fStep; }\r
+       int             optimalTick()           {\r
+                               float x=fStep;\r
+                               while((fMax-fMin)/x > 50) x*=10;\r
+                               while((fMax-fMin)/x < 10) x/=2;\r
+                               return faust2qt(fMin+x);\r
+                       }\r
+\r
+ public :\r
+       QSlider*        fSlider;\r
+       float           fCur;\r
+       float           fMin;\r
+       float           fMax;\r
+       float           fStep;\r
+\r
+       uiSlider (GUI* ui, float* zone, QSlider* slider, float cur, float lo, float hi, float step)\r
+               : uiItem(ui, zone), fSlider(slider), fCur(cur), fMin(lo), fMax(hi), fStep(step)\r
+       {\r
+               fSlider->setMinimum(0);\r
+               fSlider->setMaximum(faust2qt(fMax));\r
+               fSlider->setValue(faust2qt(fCur));\r
+               fSlider->setTickInterval(optimalTick());\r
+               *fZone = fCur;\r
+       }\r
+\r
+       virtual void reflectZone()\r
+       {\r
+               float   v = *fZone;\r
+               fCache = v;\r
+               fSlider->setValue(faust2qt(v));\r
+       }\r
+\r
+ public slots :\r
+       void setValue(int v)            { modifyZone(qt2faust(v)); }\r
+};\r
+\r
+\r
+class uiKnob : public QObject, public uiItem\r
+{\r
+    Q_OBJECT\r
+\r
+       int             faust2qt(float x)       { return int(0.5 + (x-fMin)/fStep); }\r
+       float   qt2faust (int v)        { return fMin + v*fStep; }\r
+       int             optimalTick()           {\r
+                               float x=fStep;\r
+                               while((fMax-fMin)/x > 50) x*=10;\r
+                               while((fMax-fMin)/x < 10) x/=2;\r
+                               return faust2qt(fMin+x);\r
+                       }\r
+\r
+ public :\r
+       QAbstractSlider*        fSlider;\r
+       float                           fCur;\r
+       float                           fMin;\r
+       float                           fMax;\r
+       float                           fStep;\r
+\r
+       uiKnob (GUI* ui, float* zone, QAbstractSlider* slider, float cur, float lo, float hi, float step)\r
+               : uiItem(ui, zone), fSlider(slider), fCur(cur), fMin(lo), fMax(hi), fStep(step)\r
+       {\r
+               fSlider->setMinimum(0);\r
+               fSlider->setMaximum(faust2qt(fMax));\r
+               fSlider->setValue(faust2qt(fCur));\r
+               //fSlider->setTickInterval(optimalTick());\r
+               *fZone = fCur;\r
+       }\r
+\r
+       virtual void reflectZone()\r
+       {\r
+               float   v = *fZone;\r
+               fCache = v;\r
+               fSlider->setValue(faust2qt(v));\r
+       }\r
+\r
+ public slots :\r
+       void setValue(int v)            { modifyZone(qt2faust(v)); }\r
+};\r
+\r
+\r
+class uiBargraph : public QObject, public uiItem\r
+{\r
+    Q_OBJECT\r
+\r
+    int     faust2qt(float x)   { return int(0.5 + (x-fMin)/(fMax-fMin)*fStep); }\r
+\r
+ public :\r
+    QProgressBar*   fBar;\r
+    float           fMin;\r
+    float           fMax;\r
+    int             fStep;\r
+\r
+    uiBargraph (GUI* ui, float* zone, QProgressBar* bar, float lo, float hi)\r
+        : uiItem(ui, zone), fBar(bar), fMin(lo), fMax(hi), fStep(1024)\r
+    {\r
+        fBar->setRange(0, fStep);\r
+        fBar->setValue(0);\r
+        *fZone = 0;\r
+    }\r
+\r
+    virtual void reflectZone()\r
+    {\r
+        float   v = *fZone;\r
+        fCache = v;\r
+        int x = faust2qt(v);\r
+        //std::cout << "update *" << fBar << " = " << x << std::endl;\r
+        fBar->setValue(x);\r
+    }\r
+};\r
+\r
+\r
+class uiBargraph2 : public QObject, public uiItem\r
+{\r
+    Q_OBJECT\r
+\r
+ public :\r
+    AbstractDisplay*   fBar;\r
+\r
+    uiBargraph2 (GUI* ui, float* zone, AbstractDisplay* bar, float lo, float hi)\r
+        : uiItem(ui, zone), fBar(bar)\r
+    {\r
+        fBar->setRange(lo, hi);\r
+        fBar->setValue(lo);\r
+        *fZone = lo;\r
+    }\r
+\r
+    virtual void reflectZone()\r
+    {\r
+        float   v = *fZone;\r
+        fCache = v;\r
+        fBar->setValue(v);\r
+    }\r
+};\r
+\r
+\r
+\r
+class uiNumEntry : public QObject, public uiItem\r
+{\r
+    Q_OBJECT\r
+\r
+ public :\r
+       QDoubleSpinBox*         fNumEntry;\r
+       float                           fCur;\r
+       float                           fMin;\r
+       float                           fMax;\r
+       float                           fStep;\r
+       int                                     fDecimals;\r
+\r
+       uiNumEntry (GUI* ui, float* zone, QDoubleSpinBox* numEntry, float cur, float lo, float hi, float step)\r
+               : uiItem(ui, zone), fNumEntry(numEntry), fCur(cur), fMin(lo), fMax(hi), fStep(step)\r
+       {\r
+               fDecimals = (fStep >= 1.0) ? 0 : int(0.5+log10(1.0/fStep));\r
+\r
+               fNumEntry->setMinimum(fMin);\r
+               fNumEntry->setMaximum(fMax);\r
+               fNumEntry->setSingleStep(fStep);\r
+               fNumEntry->setDecimals(fDecimals);\r
+               fNumEntry->setValue(fCur);\r
+               *fZone = fCur;\r
+       }\r
+\r
+\r
+       virtual void reflectZone()\r
+       {\r
+               float   v = *fZone;\r
+               fCache = v;\r
+               fNumEntry->setValue(v);\r
+       }\r
+\r
+ public slots :\r
+       void setValue(double v)         {\r
+               modifyZone(float(v));\r
+       }\r
+};\r
+\r
+\r
+\r
+\r
+/******************************************************************************\r
+*******************************************************************************\r
+\r
+                                               IMPLEMENTATION OF THE USER INTERFACE\r
+                                                          (QT 4.3 for FAUST)\r
+\r
+*******************************************************************************\r
+*******************************************************************************/\r
+\r
+\r
+class QTGUI : public QObject, public GUI\r
+{\r
+    Q_OBJECT\r
+       QApplication            fAppl;\r
+       QTimer*                         fTimer;\r
+       QStyle*                         fStyle;\r
+       string                          gGroupTooltip;\r
+       stack<QWidget* >        fGroupStack;\r
+\r
+    map<float*, float>           fGuiSize;       // map widget zone with widget size coef\r
+    map<float*, string>          fTooltip;       // map widget zone with tooltip strings\r
+    map<float*, string>          fUnit;          // map widget zone to unit string (i.e. "dB")\r
+    set<float*>                  fKnobSet;       // set of widget zone to be knobs\r
+    set<float*>                  fLedSet;        // set of widget zone to be LEDs\r
+\r
+\r
+    /**\r
+    * Format tooltip string by replacing some white spaces by\r
+       * return characters so that line width doesn't exceed n.\r
+       * Limitation : long words exceeding n are not cut\r
+    */\r
+       virtual string formatTooltip(int n, const string& tt)\r
+       {\r
+               string  ss = tt;        // ss string we are going to format\r
+               int     lws = 0;        // last white space encountered\r
+               int     lri = 0;        // last return inserted\r
+               for (int i=0; i< (int)tt.size(); i++) {\r
+                       if (tt[i] == ' ') lws = i;\r
+                       if (((i-lri) >= n) && (lws > lri)) {\r
+                               // insert return here\r
+                               ss[lws] = '\n';\r
+                               lri = lws;\r
+                       }\r
+               }\r
+               return ss;\r
+       }\r
+\r
+\r
+    /**\r
+    * Analyses the widget zone metadata declarations and takes\r
+    * appropriate actions\r
+    */\r
+    virtual void declare(float* zone, const char* key, const char* value)\r
+    {\r
+               if (zone == 0) {\r
+                       // special zone 0 means group metadata\r
+                       if (strcmp(key,"tooltip")==0) {\r
+                               // only group tooltip are currently implemented\r
+                               gGroupTooltip = formatTooltip(30, value);\r
+                       }\r
+               } else {\r
+                       if (strcmp(key,"size")==0) {\r
+                               fGuiSize[zone]=atof(value);\r
+                       }\r
+                       else if (strcmp(key,"tooltip")==0) {\r
+                               fTooltip[zone] = formatTooltip(30, value) ;\r
+                       }\r
+                       else if (strcmp(key,"unit")==0) {\r
+                               fUnit[zone] = value ;\r
+                       }\r
+                       else if (strcmp(key,"style")==0) {\r
+                       // else if ((strcmp(key,"style")==0) || (strcmp(key,"type")==0)) {\r
+                               if (strcmp(value,"knob") == 0) {\r
+                                       fKnobSet.insert(zone);\r
+                               } else if (strcmp(value,"led") == 0) {\r
+                                       fLedSet.insert(zone);\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       bool isTabContext()\r
+       {\r
+               return fGroupStack.empty() || ((!fGroupStack.empty()) && (dynamic_cast<QTabWidget*>(fGroupStack.top()) != 0));\r
+       }\r
+\r
+       void insert(const char* label, QWidget* widget)\r
+       {\r
+               if (fStyle) widget->setStyle(fStyle);\r
+               if (!fGroupStack.empty()) {\r
+                       QWidget* mother = fGroupStack.top();\r
+                       QTabWidget*     tab = dynamic_cast<QTabWidget*>(mother);\r
+                       if (tab) {\r
+                               tab->addTab(widget,label);\r
+                       } else {\r
+                               widget->setParent(mother);\r
+                               mother->layout()->addWidget(widget);\r
+                       }\r
+               }\r
+       }\r
+\r
+    /**\r
+    * Analyses a full label and activates the relevant options. returns a simplified\r
+    * label (without options) and an amount of stack adjustement (in case additional\r
+    * containers were pushed on the stack).\r
+    */\r
+\r
+    int checkLabelOptions(QWidget* widget, const string& fullLabel, string& simplifiedLabel)\r
+    {\r
+        map<string, string> metadata;\r
+        extractMetadata(fullLabel, simplifiedLabel, metadata);\r
+\r
+        if (metadata.count("tooltip")) {\r
+            widget->setToolTip(metadata["tooltip"].c_str());\r
+        }\r
+        if (metadata["option"] == "detachable") {\r
+            //openHandleBox(simplifiedLabel.c_str());\r
+            return 1;\r
+        }\r
+\r
+        // no adjustement of the stack needed\r
+        return 0;\r
+    }\r
+\r
+    /**\r
+    * Check if a tooltip is associated to a zone and add it to the corresponding widget\r
+    */\r
+    void checkForTooltip(float* zone, QWidget* widget)\r
+    {\r
+        if (fTooltip.count(zone)) {\r
+            widget->setToolTip(fTooltip[zone].c_str());\r
+        }\r
+    }\r
+\r
+    /**\r
+    * Check if a knob is required\r
+    */\r
+    bool isKnob(float* zone)\r
+    {\r
+        return fKnobSet.count(zone) > 0;\r
+    }\r
+\r
+       void openBox(const char* fulllabel, QLayout* layout)\r
+       {\r
+               map<string, string> metadata;\r
+        string label;\r
+        extractMetadata(fulllabel, label, metadata);\r
+               layout->setMargin(5);\r
+               QWidget* box;\r
+\r
+        if (isTabContext()) {\r
+                       box = new QWidget();\r
+            // set background color\r
+            QPalette pal = box->palette();\r
+            pal.setColor(box->backgroundRole(), QColor::fromRgb(150, 150, 150) );\r
+            box->setPalette(pal);\r
+\r
+               } else  if (label.size()>0) {\r
+                       QGroupBox* group = new QGroupBox();\r
+                       group->setTitle(label.c_str());\r
+                       box = group;\r
+               } else {\r
+                       // no label here we use simple widget\r
+                       layout->setMargin(0);\r
+                       box = new QWidget();\r
+               }\r
+\r
+        box->setLayout(layout);\r
+/*        if (metadata.count("tooltip")) {\r
+            box->setToolTip(metadata["tooltip"].c_str());\r
+        }*/\r
+        if (gGroupTooltip != string()) {\r
+                       box->setToolTip(gGroupTooltip.c_str());\r
+                       gGroupTooltip = string();\r
+               }\r
+        insert(label.c_str(), box);\r
+        fGroupStack.push(box);\r
+    }\r
+\r
+       void openTab(const char* label)\r
+       {\r
+               QTabWidget* group = new QTabWidget();\r
+               if (fStyle) group->setStyle(fStyle);\r
+               insert(label, group);\r
+               fGroupStack.push(group);\r
+       }\r
+\r
+\r
+  public slots :\r
+       void update()           {\r
+        //std::cout << '.' << std::endl;\r
+               updateAllZones();\r
+       }\r
+\r
+  public:\r
+\r
+       QTGUI(int argc, char* argv[], QStyle* style = 0) : fAppl(argc, argv), fTimer(0), fStyle(style){\r
+        //fGroupStack.push(new QMainWindow());\r
+    }\r
+\r
+       virtual ~QTGUI() {}\r
+\r
+       virtual void run()\r
+       {\r
+               if (fTimer == 0) {\r
+                       fTimer = new QTimer(this);\r
+               QObject::connect(fTimer, SIGNAL(timeout()), this, SLOT(update()));\r
+               fTimer->start(100);\r
+               }\r
+#if 1\r
+        fAppl.setStyleSheet(\r
+\r
+// BUTTONS\r
+                        "QPushButton {"\r
+                                    "background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1,"\r
+                                                                    "stop: 0 #B0B0B0, stop: 1 #404040);"\r
+                                    "border: 2px solid grey;"\r
+                                    "border-radius: 6px;"\r
+                                    "margin-top: 1ex;"\r
+                                 "}"\r
+\r
+                 "QPushButton:hover {"\r
+                                    "border: 2px solid orange;"\r
+                                 "}"\r
+\r
+                 "QPushButton:pressed {"\r
+                                    //"border: 1px solid orange;"\r
+                                    "background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,"\r
+                                                                        "stop: 0 #404040, stop: 1 #B0B0B0);"\r
+                                 "}"\r
+// GROUPS\r
+                       "QGroupBox {"\r
+                                    "background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1,"\r
+                                                                    "stop: 0 #A0A0A0, stop: 1 #202020);"\r
+                                    "border: 2px solid gray;"\r
+                                    "border-radius: 5px;"\r
+                                    "margin-top: 1ex;"\r
+                                    "font-size:7pt;"\r
+                                    "font-weight:bold;"\r
+                                  //"color: dark grey;"\r
+                                    "color: white;"\r
+                                 "}"\r
+\r
+                "QGroupBox::title {"\r
+                                    "subcontrol-origin: margin;"\r
+                                    "subcontrol-position: top center;" /* position at the top center */\r
+                                    "padding: 0 5px;"\r
+                                 "}"\r
+// SLIDERS\r
+                    // horizontal sliders\r
+                    "QSlider::groove:vertical {"\r
+                        "background: red;"\r
+                        "position: absolute;" /* absolutely position 4px from the left and right of the widget. setting margins on the widget should work too... */\r
+                        "left: 13px; right: 13px;"\r
+                    "}"\r
+\r
+                    "QSlider::handle:vertical {"\r
+                        "height: 40px;"\r
+                        "width: 30px;"\r
+                        "background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,"\r
+                                                          "stop: 0 #AAAAAA, stop : 0.05 #0A0A0A, stop: 0.3 #101010, stop : 0.90 #AAAAAA, stop: 0.91 #000000);"\r
+                        "margin: 0 -5px; /* expand outside the groove */"\r
+                        "border-radius: 5px;"\r
+                    "}"\r
+\r
+                    "QSlider::add-page:vertical {"\r
+                        "background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0,"\r
+                                                          "stop: 0 yellow, stop : 0.5 orange);"\r
+                    "}"\r
+\r
+                    "QSlider::sub-page:vertical {"\r
+                        "background: grey;"\r
+                    "}"\r
+\r
+                    // horizontal sliders\r
+\r
+                    "QSlider::groove:horizontal {"\r
+                        "background: red;"\r
+                        "position: absolute;" /* absolutely position 4px from the left and right of the widget. setting margins on the widget should work too... */\r
+                        "top: 14px; bottom: 14px;"\r
+                    "}"\r
+\r
+                    "QSlider::handle:horizontal {"\r
+                        "width: 40px;"\r
+                        "background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0,"\r
+                                                          "stop: 0 #AAAAAA, stop : 0.05 #0A0A0A, stop: 0.3 #101010, stop : 0.90 #AAAAAA, stop: 0.91 #000000);"\r
+                        "margin: -5px 0; /* expand outside the groove */"\r
+                        "border-radius: 5px;"\r
+                    "}"\r
+\r
+                    "QSlider::sub-page:horizontal {"\r
+                        "background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,"\r
+                                                          "stop: 0 yellow, stop : 0.5 orange);"\r
+                    "}"\r
+\r
+                    "QSlider::add-page:horizontal {"\r
+                        "background: grey;"\r
+                    "}"\r
+\r
+// TABS\r
+                    //TabWidget and TabBar\r
+                    "QTabWidget::pane {" /* The tab widget frame */\r
+                        //"border-top: 2px solid #C2C7CB;"\r
+                        "border-top: 2px solid orange;"\r
+                        "background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,"\r
+                                                        "stop: 0 #A0A0A0, stop: 1 #202020);"\r
+                    "}"\r
+\r
+                    "QTabWidget::tab-bar {"\r
+                        "left: 5px;" /* move to the right by 5px */\r
+                    "}"\r
+\r
+                    /* Style the tab using the tab sub-control. Note that\r
+                        it reads QTabBar _not_ QTabWidget */\r
+                    "QTabBar::tab {"\r
+                        "background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,"\r
+                                                    "stop: 0 #909090, stop: 0.4 #888888,"\r
+                                                    "stop: 0.5 #808080, stop: 1.0 #909090);"\r
+                        "border: 2px solid #808080;"\r
+                        //"border-bottom-color: #C2C7CB;" /* same as the pane color */\r
+                        "border-bottom-color: orange;" /* same as the pane color */\r
+                        "border-top-left-radius: 4px;"\r
+                        "border-top-right-radius: 4px;"\r
+                        "min-width: 8ex;"\r
+                        "padding: 2px;"\r
+                    "}"\r
+\r
+                    "QTabBar::tab:selected, QTabBar::tab:hover {"\r
+                        "background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,"\r
+                                                    "stop: 0 #D0D0D0, stop: 0.4 #A0A0A0,"\r
+                                                    "stop: 0.5 #808080, stop: 1.0 #A0A0A0);"\r
+                                                    //"stop: 0.5 #A0A0A0, stop: 1.0 #C0C0C0);"\r
+                                                    //"stop: 0 #fafafa, stop: 0.4 #f4f4f4,"\r
+                                                    //"stop: 0.5 #e7e7e7, stop: 1.0 #fafafa);"\r
+                        //"border-bottom-color: orange;" /* same as the pane color */\r
+                    "}"\r
+\r
+                    "QTabBar::tab:selected {"\r
+                        "border-color: orange;"\r
+                        "border-bottom-color: #A0A0A0;" /* same as pane color */\r
+                    "}"\r
+\r
+                    "QTabBar::tab:!selected {"\r
+                    "    margin-top: 2px;" /* make non-selected tabs look smaller */\r
+                    "}"\r
+                            );\r
+#endif\r
+               fAppl.exec();\r
+               stop();\r
+\r
+       }\r
+\r
+\r
+       // ------------------------- Groups -----------------------------------\r
+\r
+       virtual void openHorizontalBox(const char* label) { \r
+               openBox(label, new QHBoxLayout());\r
+       }\r
+\r
+       virtual void openVerticalBox(const char* label)         {\r
+        openBox(label, new QVBoxLayout());\r
+    }\r
+\r
+    virtual void openFrameBox(const char* )            { }\r
+       virtual void openTabBox(const char* label)              { \r
+               openTab(label);\r
+       }\r
+\r
+       virtual void closeBox()\r
+       {\r
+               QWidget* group = fGroupStack.top();\r
+               fGroupStack.pop();\r
+               if (fGroupStack.empty()) { group->show(); }\r
+       }\r
+\r
+       // ------------------------- active widgets -----------------------------------\r
+\r
+       virtual void addButton(const char* label , float* zone)\r
+       {\r
+               QAbstractButton*        w = new QPushButton(label);\r
+               uiButton*                       c = new uiButton(this, zone, w);\r
+\r
+               insert(label, w);\r
+               QObject::connect(w, SIGNAL(pressed()), c, SLOT(pressed()));\r
+               QObject::connect(w, SIGNAL(released()), c, SLOT(released()));\r
+        checkForTooltip(zone, w);\r
+       }\r
+\r
+    virtual void addToggleButton(const char* , float* )\r
+    {}\r
+\r
+       virtual void addCheckButton(const char* label , float* zone)\r
+       {\r
+               QCheckBox*      w = new QCheckBox(label);\r
+               uiCheckButton*  c = new uiCheckButton(this, zone, w);\r
+\r
+               insert(label, w);\r
+               QObject::connect(w, SIGNAL(stateChanged(int)), c, SLOT(setState(int)));\r
+        checkForTooltip(zone, w);\r
+       }\r
+\r
+    virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step)\r
+    {\r
+        if (isKnob(zone)) {\r
+            addVerticalKnob(label, zone, init, min, max, step);\r
+            return;\r
+        }\r
+        //insert(label, new QDoubleSpinBox());\r
+        if (label && label[0]) openVerticalBox(label);\r
+        QDoubleSpinBox*     w = new QDoubleSpinBox();\r
+        uiNumEntry*         c = new uiNumEntry(this, zone, w, init, min, max, step);\r
+        insert(label, w);\r
+        w->setSuffix(fUnit[zone].c_str());\r
+        QObject::connect(w, SIGNAL(valueChanged(double)), c, SLOT(setValue(double)));\r
+        if (label && label[0]) closeBox();\r
+        checkForTooltip(zone, w);\r
+    }\r
+\r
+    // special num entry without buttons\r
+    virtual void addNumDisplay(const char* label, float* zone, float init, float min, float max, float step)\r
+    {\r
+        //insert(label, new QDoubleSpinBox());\r
+        if (label && label[0]) openVerticalBox(label);\r
+        QDoubleSpinBox*     w = new QDoubleSpinBox();\r
+        w->setAlignment(Qt::AlignHCenter);\r
+#if 1\r
+        w->setStyleSheet(\r
+                  "QDoubleSpinBox {"\r
+                                    "border: 2px solid orange;"\r
+                                    "border-radius: 5px;"\r
+                                 "}"\r
+        );\r
+#endif\r
+        uiNumEntry*         c = new uiNumEntry(this, zone, w, init, min, max, step);\r
+        insert(label, w);\r
+        w->setButtonSymbols(QAbstractSpinBox::NoButtons);\r
+        w->setSuffix(fUnit[zone].c_str());\r
+        QObject::connect(w, SIGNAL(valueChanged(double)), c, SLOT(setValue(double)));\r
+        if (label && label[0]) closeBox();\r
+        checkForTooltip(zone, w);\r
+    }\r
+\r
+\r
+       //////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+       //\r
+       // KNOBS\r
+       //\r
+       //////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+\r
+       virtual void addVerticalKnob(const char* label , float* zone, float init, float min, float max, float step)\r
+       {\r
+               openVerticalBox(label);\r
+               QAbstractSlider*        w = new QDial(); //qsynthKnob();\r
+               uiKnob* c = new uiKnob(this, zone, w, init, min, max, step);\r
+               insert(label, w);\r
+               w->setStyle(new qsynthDialVokiStyle());\r
+               QObject::connect(w, SIGNAL(valueChanged(int)), c, SLOT(setValue(int)));\r
+               addNumDisplay(0, zone, init, min, max, step);\r
+\r
+        // compute the size of the knob+display\r
+        int width  = int(64*pow(2,fGuiSize[zone]));\r
+        int height = int(100*pow(2,fGuiSize[zone]));\r
+        fGroupStack.top()->setMinimumSize(width,height);\r
+        fGroupStack.top()->setMaximumSize(width,height);\r
+\r
+               closeBox();\r
+        checkForTooltip(zone, w);\r
+       }\r
+\r
+       virtual void addHorizontalKnob(const char* label , float* zone, float init, float min, float max, float step)\r
+       {\r
+               openHorizontalBox(label);\r
+               QAbstractSlider*        w = new QDial(); //new qsynthKnob();\r
+               uiKnob* c = new uiKnob(this, zone, w, init, min, max, step);\r
+               insert(label, w);\r
+               w->setStyle(new qsynthDialVokiStyle());\r
+               QObject::connect(w, SIGNAL(valueChanged(int)), c, SLOT(setValue(int)));\r
+               addNumDisplay(0, zone, init, min, max, step);\r
+               closeBox();\r
+        checkForTooltip(zone, w);\r
+       }\r
+\r
+       //////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+       //\r
+       // SLIDERS\r
+       //\r
+       //////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+\r
+       virtual void addVerticalSlider(const char* label , float* zone, float init, float min, float max, float step)\r
+       {\r
+               if (isKnob(zone)) {\r
+                       addVerticalKnob(label, zone, init, min, max, step);\r
+                       return;\r
+               }\r
+               openVerticalBox(label);\r
+               QSlider*        w = new QSlider(Qt::Vertical);\r
+        w->setMinimumHeight(160);\r
+        w->setMinimumWidth(34);\r
+               //w->setTickPosition(QSlider::TicksBothSides);\r
+               uiSlider*       c = new uiSlider(this, zone, w, init, min, max, step);\r
+               insert(label, w);\r
+               QObject::connect(w, SIGNAL(valueChanged(int)), c, SLOT(setValue(int)));\r
+               addNumDisplay(0, zone, init, min, max, step);\r
+               closeBox();\r
+        checkForTooltip(zone, w);\r
+       }\r
+\r
+       virtual void addHorizontalSlider(const char* label , float* zone, float init, float min, float max, float step)\r
+       {\r
+               if (isKnob(zone)) {\r
+                       addHorizontalKnob(label, zone, init, min, max, step);\r
+                       return;\r
+               }\r
+               openHorizontalBox(label);\r
+               QSlider*        w = new QSlider(Qt::Horizontal);\r
+        w->setMinimumHeight(34);\r
+        w->setMinimumWidth(160);\r
+               //w->setTickPosition(QSlider::TicksBothSides);\r
+               uiSlider*       c = new uiSlider(this, zone, w, init, min, max, step);\r
+               insert(label, w);\r
+               QObject::connect(w, SIGNAL(valueChanged(int)), c, SLOT(setValue(int)));\r
+               addNumDisplay(0, zone, init, min, max, step);\r
+               closeBox();\r
+        checkForTooltip(zone, w);\r
+       }\r
+\r
+       // ------------------------- passive widgets -----------------------------------\r
+\r
+    virtual void addNumDisplay(const char*, float*, int)\r
+    {}\r
+\r
+       virtual void addTextDisplay(const char*, float*, const char* [], float, float)\r
+    {}\r
+\r
+    virtual void addHorizontalBargraph(const char* label , float* zone, float min, float max)\r
+    {\r
+        AbstractDisplay*  bargraph;\r
+        openVerticalBox(label);\r
+        bool db = (fUnit[zone] == "dB");\r
+\r
+        if (fLedSet.count(zone)) {\r
+            if (db) {\r
+                bargraph = new dbLED(min, max);\r
+            } else {\r
+                bargraph = new LED(min,max);\r
+            }\r
+        } else {\r
+            if (db) {\r
+                bargraph = new dbHorizontalBargraph(min, max);\r
+            } else {\r
+                bargraph = new linHorizontalBargraph(min, max);\r
+            }\r
+        }\r
+\r
+        new uiBargraph2(this, zone, bargraph, min, max);\r
+        insert(label, bargraph);\r
+        closeBox();\r
+        checkForTooltip(zone, bargraph);\r
+    }\r
+\r
+    virtual void addVerticalBargraph(const char* label , float* zone, float min, float max)\r
+    {\r
+        AbstractDisplay*  bargraph;\r
+        openVerticalBox(label);\r
+        bool db = (fUnit[zone] == "dB");\r
+\r
+        if (fLedSet.count(zone)) {\r
+            if (db) {\r
+                bargraph = new dbLED(min, max);\r
+            } else {\r
+                bargraph = new LED(min,max);\r
+            }\r
+        } else {\r
+            if (db) {\r
+                bargraph = new dbVerticalBargraph(min, max);\r
+            } else {\r
+                bargraph = new linVerticalBargraph(min, max);\r
+            }\r
+        }\r
+        new uiBargraph2(this, zone, bargraph, min, max);\r
+        insert(label, bargraph);\r
+        closeBox();\r
+        checkForTooltip(zone, bargraph);\r
+    }\r
+\r
+};\r
+\r
+#endif\r