Merge branch 'master' of https://scm.cri.ensmp.fr/git/Faustine
[Faustine.git] / interpretor / faust-0.9.47mr3 / architecture / gui / faustqt.h
1 /************************************************************************
2 ************************************************************************
3 FAUST Architecture File
4 Copyright (C) 2003-2011 GRAME, Centre National de Creation Musicale
5 ---------------------------------------------------------------------
6 This Architecture section is free software; you can redistribute it
7 and/or modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 3 of
9 the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; If not, see <http://www.gnu.org/licenses/>.
18
19 ************************************************************************
20 ************************************************************************/
21 #ifndef __faustqt__
22 #define __faustqt__
23
24 #include <cassert>
25 #include <cmath>
26 #include <fstream>
27 #include <iostream>
28 #include <list>
29 #include <map>
30 #include <set>
31 #include <vector>
32 #include <stack>
33
34 #include <QApplication>
35 #include <QCheckBox>
36 #include <QColormap>
37 #include <QDial>
38 #include <QDoubleSpinBox>
39 #include <QGroupBox>
40 #include <QHBoxLayout>
41 #include <QLayout>
42 #include <QMouseEvent>
43 #include <QObject>
44 #include <QPainter>
45 #include <QProgressBar>
46 #include <QPushButton>
47 #include <QRadialGradient>
48 #include <QSlider>
49 #include <QStyle>
50 #include <QTabWidget>
51 #include <QTimer>
52 #include <QToolTip>
53 #include <QVBoxLayout>
54 #include <QWheelEvent>
55 #include <QWidget>
56 #include <QtGui>
57
58 #include "GUI.h"
59
60 //----------------------------------
61
62 // for compatibility
63 #define minValue minimum
64 #define maxValue maximum
65
66
67 using namespace std;
68
69
70 //==============================BEGIN QSYNTHKNOB=====================================
71 //
72 // qsynthknob and qsynthDialVokiStyle borrowed from qsynth-0.3.3 by Rui Nuno Capela
73 // This widget is based on a design by Thorsten Wilms,
74 // implemented by Chris Cannam in Rosegarden,
75 // adapted for QSynth by Pedro Lopez-Cabanillas,
76 // improved for Qt4 by David Garcia Garzon.
77 //
78
79 #define DIAL_MIN (0.25 * M_PI)
80 #define DIAL_MAX (1.75 * M_PI)
81 #define DIAL_RANGE (DIAL_MAX - DIAL_MIN)
82
83 class qsynthDialVokiStyle : public QCommonStyle
84 {
85 public:
86 qsynthDialVokiStyle() {};
87 virtual ~qsynthDialVokiStyle() {};
88
89 virtual void drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, const QWidget *widget = 0) const
90 {
91 if (cc != QStyle::CC_Dial)
92 {
93 QCommonStyle::drawComplexControl(cc, opt, p, widget);
94 return;
95 }
96
97 const QStyleOptionSlider *dial = qstyleoption_cast<const QStyleOptionSlider *>(opt);
98 if (dial == NULL)
99 return;
100
101 double angle = DIAL_MIN // offset
102 + (DIAL_RANGE *
103 (double(dial->sliderValue - dial->minimum) /
104 (double(dial->maximum - dial->minimum))));
105 int degrees = int(angle * 180.0 / M_PI);
106 int side = dial->rect.width() < dial->rect.height() ? dial->rect.width() : dial->rect.height();
107 int xcenter = dial->rect.width() / 2;
108 int ycenter = dial->rect.height() / 2;
109 int notchWidth = 1 + side / 400;
110 int pointerWidth = 2 + side / 30;
111 int scaleShadowWidth = 1 + side / 100;
112 int knobBorderWidth = 0;
113 int ns = dial->tickInterval;
114 int numTicks = 1 + (dial->maximum + ns - dial->minimum) / ns;
115 int indent = int(0.15 * side) + 2;
116 int knobWidth = side - 2 * indent;
117 int shineFocus = knobWidth / 4;
118 int shineCenter = knobWidth / 5;
119 int shineExtension = shineCenter * 4;
120 int shadowShift = shineCenter * 2;
121 int meterWidth = side - 2 * scaleShadowWidth;
122
123 QPalette pal = opt->palette;
124 QColor knobColor = pal.mid().color();
125 QColor borderColor = knobColor.light();
126 QColor meterColor = (dial->state & State_Enabled) ?
127 QColor("orange") : pal.mid().color();
128 // pal.highlight().color() : pal.mid().color();
129 QColor background = pal.window().color();
130
131 p->save();
132 p->setRenderHint(QPainter::Antialiasing, true);
133
134 // The bright metering bit...
135
136 QConicalGradient meterShadow(xcenter, ycenter, -90);
137 meterShadow.setColorAt(0, meterColor.dark());
138 meterShadow.setColorAt(0.5, meterColor);
139 meterShadow.setColorAt(1.0, meterColor.light().light());
140 p->setBrush(meterShadow);
141 p->setPen(Qt::transparent);
142 p->drawPie(xcenter - meterWidth / 2, ycenter - meterWidth / 2,
143 meterWidth, meterWidth, (180 + 45) * 16, -(degrees - 45) * 16);
144
145 // Knob projected shadow
146 QRadialGradient projectionGradient(
147 xcenter + shineCenter, ycenter + shineCenter,
148 shineExtension, xcenter + shadowShift, ycenter + shadowShift);
149 projectionGradient.setColorAt(0, QColor( 0, 0, 0, 100));
150 projectionGradient.setColorAt(1, QColor(200, 0, 0, 10));
151 QBrush shadowBrush(projectionGradient);
152 p->setBrush(shadowBrush);
153 p->drawEllipse(xcenter - shadowShift, ycenter - shadowShift,
154 knobWidth, knobWidth);
155
156 // Knob body and face...
157
158 QPen pen;
159 pen.setColor(knobColor);
160 pen.setWidth(knobBorderWidth);
161 p->setPen(pen);
162
163 QRadialGradient gradient(
164 xcenter - shineCenter, ycenter - shineCenter,
165 shineExtension, xcenter - shineFocus, ycenter - shineFocus);
166 gradient.setColorAt(0.2, knobColor.light().light());
167 gradient.setColorAt(0.5, knobColor);
168 gradient.setColorAt(1.0, knobColor.dark(150));
169 QBrush knobBrush(gradient);
170 p->setBrush(knobBrush);
171 p->drawEllipse(xcenter - knobWidth / 2, ycenter - knobWidth / 2,
172 knobWidth, knobWidth);
173
174 // Tick notches...
175
176 p->setBrush(Qt::NoBrush);
177
178 if (dial->subControls & QStyle::SC_DialTickmarks)
179 {
180 pen.setColor(pal.dark().color());
181 pen.setWidth(notchWidth);
182 p->setPen(pen);
183 double hyp = double(side - scaleShadowWidth) / 2.0;
184 double len = hyp / 4;
185 for (int i = 0; i < numTicks; ++i) {
186 int div = numTicks;
187 if (div > 1) --div;
188 bool internal = (i != 0 && i != numTicks - 1);
189 double angle = DIAL_MIN
190 + (DIAL_MAX - DIAL_MIN) * i / div;
191 double dir = (internal ? -1 : len);
192 double sinAngle = sin(angle);
193 double cosAngle = cos(angle);
194 double x0 = xcenter - (hyp - len) * sinAngle;
195 double y0 = ycenter + (hyp - len) * cosAngle;
196 double x1 = xcenter - (hyp + dir) * sinAngle;
197 double y1 = ycenter + (hyp + dir) * cosAngle;
198 p->drawLine(QLineF(x0, y0, x1, y1));
199 }
200 }
201
202 // Shadowing...
203
204 // Knob shadow...
205 if (knobBorderWidth > 0) {
206 QLinearGradient inShadow(xcenter - side / 4, ycenter - side / 4,
207 xcenter + side / 4, ycenter + side / 4);
208 inShadow.setColorAt(0.0, borderColor.light());
209 inShadow.setColorAt(1.0, borderColor.dark());
210 p->setPen(QPen(QBrush(inShadow), knobBorderWidth * 7 / 8));
211 p->drawEllipse(xcenter - side / 2 + indent,
212 ycenter - side / 2 + indent,
213 side - 2 * indent, side - 2 * indent);
214 }
215
216 // Scale shadow...
217 QLinearGradient outShadow(xcenter - side / 3, ycenter - side / 3,
218 xcenter + side / 3, ycenter + side / 3);
219 outShadow.setColorAt(0.0, background.dark().dark());
220 outShadow.setColorAt(1.0, background.light().light());
221 p->setPen(QPen(QBrush(outShadow), scaleShadowWidth));
222 p->drawArc(xcenter - side / 2 + scaleShadowWidth / 2,
223 ycenter - side / 2 + scaleShadowWidth / 2,
224 side - scaleShadowWidth, side - scaleShadowWidth, -45 * 16, 270 * 16);
225
226 // Pointer notch...
227
228 double hyp = double(side) / 2.0;
229 double len = hyp - indent - 1;
230
231 double x = xcenter - len * sin(angle);
232 double y = ycenter + len * cos(angle);
233
234 QColor pointerColor = pal.dark().color();
235 pen.setColor((dial->state & State_Enabled) ? pointerColor.dark(140) : pointerColor);
236 pen.setWidth(pointerWidth + 2);
237 p->setPen(pen);
238 p->drawLine(QLineF(xcenter, ycenter, x, y));
239 pen.setColor((dial->state & State_Enabled) ? pointerColor.light() : pointerColor.light(140));
240 pen.setWidth(pointerWidth);
241 p->setPen(pen);
242 p->drawLine(QLineF(xcenter - 1, ycenter - 1, x - 1, y - 1));
243
244 // done
245 p->restore();
246 }
247
248 };
249 //
250 //===============================END QSYNTHKNOB======================================
251
252
253 //==============================BEGIN DISPLAYS===================================
254 //
255 // This section constains displays, passive QT widgets that displays values in
256 // different ways, in particular bargraphs
257 //
258
259 /**
260 * An abstract widget that display a value in a range
261 */
262 class AbstractDisplay : public QWidget
263 {
264 protected :
265 float fMin;
266 float fMax;
267 float fValue;
268
269 public:
270
271 AbstractDisplay (float lo, float hi) : fMin(lo), fMax(hi), fValue(lo)
272 {
273 }
274
275 /**
276 * set the range of displayed values
277 */
278 virtual void setRange(float lo, float hi)
279 {
280 fMin = lo;
281 fMax = hi;
282 }
283
284 /**
285 * set the value to be displayed
286 */
287 virtual void setValue(float v)
288 {
289 if (v < fMin) v = fMin;
290 else if (v > fMax) v = fMax;
291
292 if (v != fValue) {
293 fValue = v;
294 update();
295 }
296 }
297 };
298
299
300 /**
301 * Displays dB values using a scale of colors
302 */
303 class dbAbstractDisplay : public AbstractDisplay
304 {
305 protected :
306
307 float fScaleMin;
308 float fScaleMax;
309 vector<int> fLevel;
310 vector<QBrush> fBrush;
311
312
313 /**
314 * Convert a dB value into a scale between 0 and 1 (following IEC standard ?)
315 */
316 float dB2Scale ( float dB ) const
317 {
318 float fScale = 1.0f;
319
320 /*if (dB < -70.0f)
321 fScale = 0.0f;
322 else*/ if (dB < -60.0f)
323 fScale = (dB + 70.0f) * 0.0025f;
324 else if (dB < -50.0f)
325 fScale = (dB + 60.0f) * 0.005f + 0.025f;
326 else if (dB < -40.0)
327 fScale = (dB + 50.0f) * 0.0075f + 0.075f;
328 else if (dB < -30.0f)
329 fScale = (dB + 40.0f) * 0.015f + 0.15f;
330 else if (dB < -20.0f)
331 fScale = (dB + 30.0f) * 0.02f + 0.3f;
332 else if (dB < -0.001f || dB > 0.001f) /* if (dB < 0.0f) */
333 fScale = (dB + 20.0f) * 0.025f + 0.5f;
334
335 return fScale;
336 }
337
338
339 /**
340 * Create the scale of colors used to paint the bargraph in relation to the levels
341 * The parameter x indicates the direction of the gradient. x=1 means an horizontal
342 * gradient typically used by a vertical bargraph, and x=0 a vertical gradient.
343 */
344 void initLevelsColors(int x)
345 {
346 int alpha = 200;
347 { // level until -10 dB
348 QColor c(40, 160, 40, alpha);
349 QLinearGradient g(0,0,x,1-x);
350 g.setCoordinateMode(QGradient::ObjectBoundingMode);
351 g.setColorAt(0.0, c.lighter());
352 g.setColorAt(0.2, c);
353 g.setColorAt(0.8, c);
354 g.setColorAt(0.9, c.darker(120));
355
356 fLevel.push_back(-10);
357 fBrush.push_back(QBrush(g));
358 }
359
360 { // level until -6 dB
361 QColor c(160, 220, 20, alpha);
362 QLinearGradient g(0,0,x,1-x);
363 g.setCoordinateMode(QGradient::ObjectBoundingMode);
364 g.setColorAt(0.0, c.lighter());
365 g.setColorAt(0.2, c);
366 g.setColorAt(0.8, c);
367 g.setColorAt(0.9, c.darker(120));
368
369 fLevel.push_back(-6);
370 fBrush.push_back(QBrush(g));
371 }
372
373 { // level until -3 dB
374 QColor c(220, 220, 20, alpha);
375 QLinearGradient g(0,0,x,1-x);
376 g.setCoordinateMode(QGradient::ObjectBoundingMode);
377 g.setColorAt(0.0, c.lighter());
378 g.setColorAt(0.2, c);
379 g.setColorAt(0.8, c);
380 g.setColorAt(0.9, c.darker(120));
381
382 fLevel.push_back(-3);
383 fBrush.push_back(QBrush(g));
384 }
385
386 { // level until -0 dB
387 QColor c(240, 160, 20, alpha);
388 QLinearGradient g(0,0,x,1-x);
389 g.setCoordinateMode(QGradient::ObjectBoundingMode);
390 g.setColorAt(0.0, c.lighter());
391 g.setColorAt(0.2, c);
392 g.setColorAt(0.8, c);
393 g.setColorAt(0.9, c.darker(120));
394
395 fLevel.push_back(0);
396 fBrush.push_back(QBrush(g));
397 }
398
399 { // until 10 dB (and over because last one)
400 QColor c(240, 0, 20, alpha); // ColorOver
401 QLinearGradient g(0,0,x,1-x);
402 g.setCoordinateMode(QGradient::ObjectBoundingMode);
403 g.setColorAt(0.0, c.lighter());
404 g.setColorAt(0.2, c);
405 g.setColorAt(0.8, c);
406 g.setColorAt(0.9, c.darker(120));
407
408 fLevel.push_back(+10);
409 fBrush.push_back(QBrush(g));
410 }
411
412 }
413
414 public:
415
416 dbAbstractDisplay(float lo, float hi) : AbstractDisplay(lo,hi)
417 {
418 }
419
420 /**
421 * set the range of displayed values
422 */
423 virtual void setRange(float lo, float hi)
424 {
425 AbstractDisplay::setRange(lo, hi);
426 fScaleMin = dB2Scale(fMin);
427 fScaleMax = dB2Scale(fMax);
428 }
429 };
430
431
432 /**
433 * Small rectangular LED display which color changes with the level in dB
434 */
435 class dbLED : public dbAbstractDisplay
436 {
437 protected:
438
439 /**
440 * Draw the LED using a color depending of its value in dB
441 */
442 virtual void paintEvent ( QPaintEvent *)
443 {
444 QPainter painter(this);
445 painter.drawRect(rect());
446
447 if (fValue <= fLevel[0]) {
448
449 // interpolate the first color on the alpha channel
450 QColor c(40, 160, 40) ;
451 float a = (fValue-fMin)/(fLevel[0]-fMin);
452 c.setAlphaF(a);
453 painter.fillRect(rect(), c);
454
455 } else {
456
457 // find the minimal level > value
458 int l = fLevel.size()-1; while (fValue < fLevel[l] && l > 0) l--;
459 painter.fillRect(rect(), fBrush[l]);
460 }
461 }
462
463 public:
464
465 dbLED(float lo, float hi) : dbAbstractDisplay(lo,hi)
466 {
467 setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
468 initLevelsColors(1);
469 }
470
471 virtual QSize sizeHint () const
472 {
473 return QSize(16, 8);
474 }
475 };
476 /**
477 * Small rectangular LED display which intensity (alpha channel) changes according to the value
478 */
479 class LED : public AbstractDisplay
480 {
481 QColor fColor;
482
483 protected:
484
485 /**
486 * Draw the LED using a transparency depending of its value
487 */
488 virtual void paintEvent ( QPaintEvent *)
489 {
490 QPainter painter(this);
491 painter.drawRect(rect());
492 // interpolate the first color on the alpha channel
493 QColor c = fColor ;
494 float a = (fValue-fMin)/(fMax-fMin);
495 c.setAlphaF(a);
496 painter.fillRect(rect(), c);
497 }
498
499 public:
500
501 LED(float lo, float hi) : AbstractDisplay(lo,hi), fColor("yellow")
502 {
503 setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
504 }
505
506 virtual QSize sizeHint () const
507 {
508 return QSize(16, 8);
509 }
510 };
511
512
513
514 /**
515 * A simple bargraph that detect automatically its direction
516 */
517 class linBargraph : public AbstractDisplay
518 {
519 protected :
520 QBrush fBrush;
521
522 /**
523 * No scale implemented yet
524 */
525 void paintScale(QPainter* painter) const
526 {
527 painter->drawRect(0,0,width(),height());
528 }
529
530 /**
531 * The length of the rectangle is proportional to the value
532 */
533 void paintContent (QPainter* painter) const
534 {
535 int w = width();
536 int h = height();
537 float v = (fValue-fMin)/(fMax-fMin);
538
539 if (h>w) {
540 // draw vertical rectangle
541 painter->fillRect(0,(1-v)*h,w, v*h, fBrush);
542 } else {
543 // draw horizontal rectangle
544 painter->fillRect(0, 0, h, v*w, fBrush);
545 }
546
547 }
548
549 virtual void paintEvent ( QPaintEvent *)
550 {
551 QPainter painter(this);
552 paintContent(&painter);
553 paintScale(&painter);
554 }
555
556 public:
557
558 linBargraph(float lo, float hi) : AbstractDisplay(lo,hi)
559 {
560 // compute the brush that will be used to
561 // paint the value
562 QColor c(0xffa500); // orange
563 int x = int(height() < width()); // gradient direction
564 QLinearGradient g(0,0,x,1-x);
565 g.setCoordinateMode(QGradient::ObjectBoundingMode);
566 g.setColorAt(0.0, c.lighter());
567 g.setColorAt(0.2, c);
568 g.setColorAt(0.8, c);
569 g.setColorAt(0.9, c.darker(120));
570 fBrush = QBrush(g);
571 }
572 };
573
574
575 /**
576 * A simple vertical bargraph
577 */
578 class linVerticalBargraph : public linBargraph
579 {
580 public:
581
582 linVerticalBargraph(float lo, float hi) : linBargraph(lo,hi)
583 {
584 setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
585 }
586
587 virtual QSize sizeHint () const
588 {
589 return QSize(16, 128);
590 }
591 };
592
593
594
595 /**
596 * A simple horizontal bargraph
597 */
598 class linHorizontalBargraph : public linBargraph
599 {
600 public:
601
602 linHorizontalBargraph(float lo, float hi) : linBargraph(lo,hi)
603 {
604 setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
605 }
606
607 virtual QSize sizeHint () const
608 {
609 return QSize(128, 16);
610 }
611 };
612
613
614
615
616 /**
617 * A dB Bargraph with a scale of colors
618 */
619 class dbBargraph : public dbAbstractDisplay
620 {
621 QBrush fBackColor;
622
623 protected :
624
625 // These two abstract methods are implemented
626 // according to the vertical or horizontal direction
627 // in dbVerticalBargraph and dbHorizontalBargraph
628 virtual void paintMark(QPainter* painter, float v) const = 0;
629 virtual int paintSegment (QPainter* painter, int pos, float v, const QBrush& b) const = 0;
630
631 /**
632 * Draw the logarithmic scale
633 */
634 void paintScale(QPainter* painter) const
635 {
636 painter->fillRect(0,0,width(),height(), fBackColor);
637 painter->save();
638 painter->setPen(QColor(0x6699aa)); //0xffa500));
639 for (float v = -10; v > fMin; v -= 10) paintMark(painter, v);
640 for (float v = -6; v < fMax; v += 3) paintMark(painter, v);
641 painter->restore();
642 }
643
644
645 /**
646 * Draw the content using colored segments
647 */
648 void paintContent (QPainter* painter) const
649 {
650 int l = fLevel.size();
651
652 float p = -1; // fake value indicates to start from border
653 int n = 0;
654 // paint all the full segments < fValue
655 for (n=0; (n < l) && (fValue > fLevel[n]); n++) {
656 p = paintSegment(painter, p, fLevel[n], fBrush[n]);
657 }
658 // paint the last segment
659 if (n == l) n = n-1;
660 p=paintSegment(painter, p, fValue, fBrush[n]);
661
662 painter->drawRect(0,0,width(),height());
663 }
664
665
666 virtual void paintEvent ( QPaintEvent *)
667 {
668 QPainter painter(this);
669 paintScale(&painter);
670 paintContent(&painter);
671 }
672
673 public:
674
675 dbBargraph(float lo, float hi) : dbAbstractDisplay(lo,hi)
676 {
677
678 QFont f = this->font();
679 f.setPointSize(6);
680 this->setFont(f);
681
682 fBackColor = QBrush(QColor(20,20,20));
683 }
684 };
685
686
687 /**
688 * Vertical dB Bargraph
689 */
690 class dbVerticalBargraph : public dbBargraph
691 {
692 protected:
693 /**
694 * Convert a dB value into a vertical position
695 */
696 float dB2y (float dB) const
697 {
698 float s0 = fScaleMin;
699 float s1 = fScaleMax;
700 float sx = dB2Scale(dB);
701 int h = height();
702
703 return h - h*(s0-sx)/(s0-s1);
704 }
705
706 /**
707 * Paint a vertical graduation mark
708 */
709 virtual void paintMark(QPainter* painter, float v) const
710 {
711 int n = 10;
712 int y = dB2y(v);
713 QRect r(0,y-n,width()-1,2*n);
714 if (v > 0.0) {
715 painter->drawText(r, Qt::AlignRight|Qt::AlignVCenter, QString::number(v).prepend('+'));
716 } else {
717 painter->drawText(r, Qt::AlignRight|Qt::AlignVCenter, QString::number(v));
718 }
719 }
720
721 /**
722 * Paint a color segment
723 */
724 virtual int paintSegment (QPainter* painter, int pos, float v, const QBrush& b) const
725 {
726 if (pos == -1) pos = height();
727 float y = dB2y(v);
728 painter->fillRect(0, y, width(), pos-y+1, b);
729 return y;
730 }
731
732
733 public:
734
735 dbVerticalBargraph(float lo, float hi) : dbBargraph(lo,hi)
736 {
737 setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
738 initLevelsColors(1);
739 }
740
741 virtual QSize sizeHint () const
742 {
743 return QSize(18, 256);
744 }
745 };
746
747 /**
748 * Horizontal dB Bargraph
749 */
750 class dbHorizontalBargraph : public dbBargraph
751 {
752
753 protected:
754
755 /**
756 * Convert a dB value into an horizontal position
757 */
758 float dB2x (float dB) const
759 {
760 float s0 = fScaleMin;
761 float s1 = fScaleMax;
762 float sx = dB2Scale(dB);
763 int w = width();
764
765 return w - w*(s1-sx)/(s1-s0);
766 }
767
768 /**
769 * Paint an horizontal graduation mark
770 */
771 void paintMark(QPainter* painter, float v) const
772 {
773 int n = 10;
774 int x = dB2x(v);
775 QRect r(x-n,0,2*n, height());
776 painter->drawText(r, Qt::AlignHCenter|Qt::AlignVCenter, QString::number(v));
777 }
778
779 /**
780 * Paint a horizontal color segment
781 */
782 int paintSegment (QPainter* painter, int pos, float v, const QBrush& b) const
783 {
784 if (pos == -1) pos = 0;
785 float x = dB2x(v);
786 painter->fillRect(pos, 0, x-pos, height(), b);
787 return x;
788 }
789
790
791 public:
792
793 dbHorizontalBargraph(float lo, float hi) : dbBargraph(lo,hi)
794 {
795 setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
796 initLevelsColors(0);
797 }
798
799 virtual QSize sizeHint () const
800 {
801 return QSize(256, 18);
802 }
803
804 };
805
806 //
807 //===============================END DISPLAYS====================================
808
809 //============================= BEGIN GROUP LABEL METADATA===========================
810 // Unlike widget's label, metadata inside group's label are not extracted directly by
811 // the Faust compiler. Therefore they must be extracted within the architecture file
812 //-----------------------------------------------------------------------------------
813 //
814
815 /**
816 * rmWhiteSpaces(): Remove the leading and trailing white spaces of a string
817 * (but not those in the middle of the string)
818 */
819 static string rmWhiteSpaces(const string& s)
820 {
821 size_t i = s.find_first_not_of(" \t");
822 size_t j = s.find_last_not_of(" \t");
823 if ( (i != string::npos) && (j != string::npos) ) {
824 return s.substr(i, 1+j-i);
825 } else {
826 return "";
827 }
828 }
829
830 /**
831 * Extracts metdata from a label : 'vol [unit: dB]' -> 'vol' + metadata(unit=dB)
832 */
833 static void extractMetadata(const string& fulllabel, string& label, map<string, string>& metadata)
834 {
835 enum {kLabel, kEscape1, kEscape2, kEscape3, kKey, kValue};
836 int state = kLabel; int deep = 0;
837 string key, value;
838
839 for (unsigned int i=0; i < fulllabel.size(); i++) {
840 char c = fulllabel[i];
841 switch (state) {
842 case kLabel :
843 assert (deep == 0);
844 switch (c) {
845 case '\\' : state = kEscape1; break;
846 case '[' : state = kKey; deep++; break;
847 default : label += c;
848 }
849 break;
850
851 case kEscape1 :
852 label += c;
853 state = kLabel;
854 break;
855
856 case kEscape2 :
857 key += c;
858 state = kKey;
859 break;
860
861 case kEscape3 :
862 value += c;
863 state = kValue;
864 break;
865
866 case kKey :
867 assert (deep > 0);
868 switch (c) {
869 case '\\' : state = kEscape2;
870 break;
871
872 case '[' : deep++;
873 key += c;
874 break;
875
876 case ':' : if (deep == 1) {
877 state = kValue;
878 } else {
879 key += c;
880 }
881 break;
882 case ']' : deep--;
883 if (deep < 1) {
884 metadata[rmWhiteSpaces(key)] = "";
885 state = kLabel;
886 key="";
887 value="";
888 } else {
889 key += c;
890 }
891 break;
892 default : key += c;
893 }
894 break;
895
896 case kValue :
897 assert (deep > 0);
898 switch (c) {
899 case '\\' : state = kEscape3;
900 break;
901
902 case '[' : deep++;
903 value += c;
904 break;
905
906 case ']' : deep--;
907 if (deep < 1) {
908 metadata[rmWhiteSpaces(key)]=rmWhiteSpaces(value);
909 state = kLabel;
910 key="";
911 value="";
912 } else {
913 value += c;
914 }
915 break;
916 default : value += c;
917 }
918 break;
919
920 default :
921 cerr << "ERROR unrecognized state " << state << endl;
922 }
923 }
924 label = rmWhiteSpaces(label);
925 }
926 //
927 //============================= END GROUP LABEL METADATA===========================
928
929
930 /******************************************************************************
931 *******************************************************************************
932
933 IMPLEMENTATION OF GUI ITEMS
934 (QT 4.3 for FAUST)
935
936 *******************************************************************************
937 *******************************************************************************/
938
939
940 class uiButton : public QObject, public uiItem
941 {
942 Q_OBJECT
943
944 public :
945 QAbstractButton* fButton;
946
947 uiButton (GUI* ui, float* zone, QAbstractButton* b) : uiItem(ui, zone), fButton(b) {}
948
949
950 virtual void reflectZone()
951 {
952 float v = *fZone;
953 fCache = v;
954 fButton->setDown( v > 0.0 );
955 }
956
957 public slots :
958 void pressed() { modifyZone(1.0); }
959 void released() { modifyZone(0.0); }
960 };
961
962
963 class uiCheckButton : public QObject, public uiItem
964 {
965 Q_OBJECT
966
967 public :
968 QCheckBox* fCheckBox;
969
970 uiCheckButton (GUI* ui, float* zone, QCheckBox* b) : uiItem(ui, zone), fCheckBox(b) {}
971
972 virtual void reflectZone()
973 {
974 float v = *fZone;
975 fCache = v;
976 fCheckBox->setCheckState( (v < 0.5) ? Qt::Unchecked : Qt::Checked );
977 }
978
979 public slots :
980 void setState(int v) { modifyZone(float(v>0)); }
981 };
982
983
984 class uiSlider : public QObject, public uiItem
985 {
986 Q_OBJECT
987
988 int faust2qt(float x) { return int(0.5 + (x-fMin)/fStep); }
989 float qt2faust (int v) { return fMin + v*fStep; }
990 int optimalTick() {
991 float x=fStep;
992 while((fMax-fMin)/x > 50) x*=10;
993 while((fMax-fMin)/x < 10) x/=2;
994 return faust2qt(fMin+x);
995 }
996
997 public :
998 QSlider* fSlider;
999 float fCur;
1000 float fMin;
1001 float fMax;
1002 float fStep;
1003
1004 uiSlider (GUI* ui, float* zone, QSlider* slider, float cur, float lo, float hi, float step)
1005 : uiItem(ui, zone), fSlider(slider), fCur(cur), fMin(lo), fMax(hi), fStep(step)
1006 {
1007 fSlider->setMinimum(0);
1008 fSlider->setMaximum(faust2qt(fMax));
1009 fSlider->setValue(faust2qt(fCur));
1010 fSlider->setTickInterval(optimalTick());
1011 *fZone = fCur;
1012 }
1013
1014 virtual void reflectZone()
1015 {
1016 float v = *fZone;
1017 fCache = v;
1018 fSlider->setValue(faust2qt(v));
1019 }
1020
1021 public slots :
1022 void setValue(int v) { modifyZone(qt2faust(v)); }
1023 };
1024
1025
1026 class uiKnob : public QObject, public uiItem
1027 {
1028 Q_OBJECT
1029
1030 int faust2qt(float x) { return int(0.5 + (x-fMin)/fStep); }
1031 float qt2faust (int v) { return fMin + v*fStep; }
1032 int optimalTick() {
1033 float x=fStep;
1034 while((fMax-fMin)/x > 50) x*=10;
1035 while((fMax-fMin)/x < 10) x/=2;
1036 return faust2qt(fMin+x);
1037 }
1038
1039 public :
1040 QAbstractSlider* fSlider;
1041 float fCur;
1042 float fMin;
1043 float fMax;
1044 float fStep;
1045
1046 uiKnob (GUI* ui, float* zone, QAbstractSlider* slider, float cur, float lo, float hi, float step)
1047 : uiItem(ui, zone), fSlider(slider), fCur(cur), fMin(lo), fMax(hi), fStep(step)
1048 {
1049 fSlider->setMinimum(0);
1050 fSlider->setMaximum(faust2qt(fMax));
1051 fSlider->setValue(faust2qt(fCur));
1052 //fSlider->setTickInterval(optimalTick());
1053 *fZone = fCur;
1054 }
1055
1056 virtual void reflectZone()
1057 {
1058 float v = *fZone;
1059 fCache = v;
1060 fSlider->setValue(faust2qt(v));
1061 }
1062
1063 public slots :
1064 void setValue(int v) { modifyZone(qt2faust(v)); }
1065 };
1066
1067
1068 class uiBargraph : public QObject, public uiItem
1069 {
1070 Q_OBJECT
1071
1072 int faust2qt(float x) { return int(0.5 + (x-fMin)/(fMax-fMin)*fStep); }
1073
1074 public :
1075 QProgressBar* fBar;
1076 float fMin;
1077 float fMax;
1078 int fStep;
1079
1080 uiBargraph (GUI* ui, float* zone, QProgressBar* bar, float lo, float hi)
1081 : uiItem(ui, zone), fBar(bar), fMin(lo), fMax(hi), fStep(1024)
1082 {
1083 fBar->setRange(0, fStep);
1084 fBar->setValue(0);
1085 *fZone = 0;
1086 }
1087
1088 virtual void reflectZone()
1089 {
1090 float v = *fZone;
1091 fCache = v;
1092 int x = faust2qt(v);
1093 //std::cout << "update *" << fBar << " = " << x << std::endl;
1094 fBar->setValue(x);
1095 }
1096 };
1097
1098
1099 class uiBargraph2 : public QObject, public uiItem
1100 {
1101 Q_OBJECT
1102
1103 public :
1104 AbstractDisplay* fBar;
1105
1106 uiBargraph2 (GUI* ui, float* zone, AbstractDisplay* bar, float lo, float hi)
1107 : uiItem(ui, zone), fBar(bar)
1108 {
1109 fBar->setRange(lo, hi);
1110 fBar->setValue(lo);
1111 *fZone = lo;
1112 }
1113
1114 virtual void reflectZone()
1115 {
1116 float v = *fZone;
1117 fCache = v;
1118 fBar->setValue(v);
1119 }
1120 };
1121
1122
1123
1124 class uiNumEntry : public QObject, public uiItem
1125 {
1126 Q_OBJECT
1127
1128 public :
1129 QDoubleSpinBox* fNumEntry;
1130 float fCur;
1131 float fMin;
1132 float fMax;
1133 float fStep;
1134 int fDecimals;
1135
1136 uiNumEntry (GUI* ui, float* zone, QDoubleSpinBox* numEntry, float cur, float lo, float hi, float step)
1137 : uiItem(ui, zone), fNumEntry(numEntry), fCur(cur), fMin(lo), fMax(hi), fStep(step)
1138 {
1139 fDecimals = (fStep >= 1.0) ? 0 : int(0.5+log10(1.0/fStep));
1140
1141 fNumEntry->setMinimum(fMin);
1142 fNumEntry->setMaximum(fMax);
1143 fNumEntry->setSingleStep(fStep);
1144 fNumEntry->setDecimals(fDecimals);
1145 fNumEntry->setValue(fCur);
1146 *fZone = fCur;
1147 }
1148
1149
1150 virtual void reflectZone()
1151 {
1152 float v = *fZone;
1153 fCache = v;
1154 fNumEntry->setValue(v);
1155 }
1156
1157 public slots :
1158 void setValue(double v) {
1159 modifyZone(float(v));
1160 }
1161 };
1162
1163
1164
1165
1166 /******************************************************************************
1167 *******************************************************************************
1168
1169 IMPLEMENTATION OF THE USER INTERFACE
1170 (QT 4.3 for FAUST)
1171
1172 *******************************************************************************
1173 *******************************************************************************/
1174
1175
1176 class QTGUI : public QObject, public GUI
1177 {
1178 Q_OBJECT
1179 QApplication fAppl;
1180 QTimer* fTimer;
1181 QStyle* fStyle;
1182 string gGroupTooltip;
1183 stack<QWidget* > fGroupStack;
1184
1185 map<float*, float> fGuiSize; // map widget zone with widget size coef
1186 map<float*, string> fTooltip; // map widget zone with tooltip strings
1187 map<float*, string> fUnit; // map widget zone to unit string (i.e. "dB")
1188 set<float*> fKnobSet; // set of widget zone to be knobs
1189 set<float*> fLedSet; // set of widget zone to be LEDs
1190
1191
1192 /**
1193 * Format tooltip string by replacing some white spaces by
1194 * return characters so that line width doesn't exceed n.
1195 * Limitation : long words exceeding n are not cut
1196 */
1197 virtual string formatTooltip(int n, const string& tt)
1198 {
1199 string ss = tt; // ss string we are going to format
1200 int lws = 0; // last white space encountered
1201 int lri = 0; // last return inserted
1202 for (int i=0; i< (int)tt.size(); i++) {
1203 if (tt[i] == ' ') lws = i;
1204 if (((i-lri) >= n) && (lws > lri)) {
1205 // insert return here
1206 ss[lws] = '\n';
1207 lri = lws;
1208 }
1209 }
1210 return ss;
1211 }
1212
1213
1214 /**
1215 * Analyses the widget zone metadata declarations and takes
1216 * appropriate actions
1217 */
1218 virtual void declare(float* zone, const char* key, const char* value)
1219 {
1220 if (zone == 0) {
1221 // special zone 0 means group metadata
1222 if (strcmp(key,"tooltip")==0) {
1223 // only group tooltip are currently implemented
1224 gGroupTooltip = formatTooltip(30, value);
1225 }
1226 } else {
1227 if (strcmp(key,"size")==0) {
1228 fGuiSize[zone]=atof(value);
1229 }
1230 else if (strcmp(key,"tooltip")==0) {
1231 fTooltip[zone] = formatTooltip(30, value) ;
1232 }
1233 else if (strcmp(key,"unit")==0) {
1234 fUnit[zone] = value ;
1235 }
1236 else if (strcmp(key,"style")==0) {
1237 // else if ((strcmp(key,"style")==0) || (strcmp(key,"type")==0)) {
1238 if (strcmp(value,"knob") == 0) {
1239 fKnobSet.insert(zone);
1240 } else if (strcmp(value,"led") == 0) {
1241 fLedSet.insert(zone);
1242 }
1243 }
1244 }
1245 }
1246
1247 bool isTabContext()
1248 {
1249 return fGroupStack.empty() || ((!fGroupStack.empty()) && (dynamic_cast<QTabWidget*>(fGroupStack.top()) != 0));
1250 }
1251
1252 void insert(const char* label, QWidget* widget)
1253 {
1254 if (fStyle) widget->setStyle(fStyle);
1255 if (!fGroupStack.empty()) {
1256 QWidget* mother = fGroupStack.top();
1257 QTabWidget* tab = dynamic_cast<QTabWidget*>(mother);
1258 if (tab) {
1259 tab->addTab(widget,label);
1260 } else {
1261 widget->setParent(mother);
1262 mother->layout()->addWidget(widget);
1263 }
1264 }
1265 }
1266
1267 /**
1268 * Analyses a full label and activates the relevant options. returns a simplified
1269 * label (without options) and an amount of stack adjustement (in case additional
1270 * containers were pushed on the stack).
1271 */
1272
1273 int checkLabelOptions(QWidget* widget, const string& fullLabel, string& simplifiedLabel)
1274 {
1275 map<string, string> metadata;
1276 extractMetadata(fullLabel, simplifiedLabel, metadata);
1277
1278 if (metadata.count("tooltip")) {
1279 widget->setToolTip(metadata["tooltip"].c_str());
1280 }
1281 if (metadata["option"] == "detachable") {
1282 //openHandleBox(simplifiedLabel.c_str());
1283 return 1;
1284 }
1285
1286 // no adjustement of the stack needed
1287 return 0;
1288 }
1289
1290 /**
1291 * Check if a tooltip is associated to a zone and add it to the corresponding widget
1292 */
1293 void checkForTooltip(float* zone, QWidget* widget)
1294 {
1295 if (fTooltip.count(zone)) {
1296 widget->setToolTip(fTooltip[zone].c_str());
1297 }
1298 }
1299
1300 /**
1301 * Check if a knob is required
1302 */
1303 bool isKnob(float* zone)
1304 {
1305 return fKnobSet.count(zone) > 0;
1306 }
1307
1308 void openBox(const char* fulllabel, QLayout* layout)
1309 {
1310 map<string, string> metadata;
1311 string label;
1312 extractMetadata(fulllabel, label, metadata);
1313 layout->setMargin(5);
1314 QWidget* box;
1315
1316 if (isTabContext()) {
1317 box = new QWidget();
1318 // set background color
1319 QPalette pal = box->palette();
1320 pal.setColor(box->backgroundRole(), QColor::fromRgb(150, 150, 150) );
1321 box->setPalette(pal);
1322
1323 } else if (label.size()>0) {
1324 QGroupBox* group = new QGroupBox();
1325 group->setTitle(label.c_str());
1326 box = group;
1327 } else {
1328 // no label here we use simple widget
1329 layout->setMargin(0);
1330 box = new QWidget();
1331 }
1332
1333 box->setLayout(layout);
1334 /* if (metadata.count("tooltip")) {
1335 box->setToolTip(metadata["tooltip"].c_str());
1336 }*/
1337 if (gGroupTooltip != string()) {
1338 box->setToolTip(gGroupTooltip.c_str());
1339 gGroupTooltip = string();
1340 }
1341 insert(label.c_str(), box);
1342 fGroupStack.push(box);
1343 }
1344
1345 void openTab(const char* label)
1346 {
1347 QTabWidget* group = new QTabWidget();
1348 if (fStyle) group->setStyle(fStyle);
1349 insert(label, group);
1350 fGroupStack.push(group);
1351 }
1352
1353
1354 public slots :
1355 void update() {
1356 //std::cout << '.' << std::endl;
1357 updateAllZones();
1358 }
1359
1360 public:
1361
1362 QTGUI(int argc, char* argv[], QStyle* style = 0) : fAppl(argc, argv), fTimer(0), fStyle(style){
1363 //fGroupStack.push(new QMainWindow());
1364 }
1365
1366 virtual ~QTGUI() {}
1367
1368 virtual void run()
1369 {
1370 if (fTimer == 0) {
1371 fTimer = new QTimer(this);
1372 QObject::connect(fTimer, SIGNAL(timeout()), this, SLOT(update()));
1373 fTimer->start(100);
1374 }
1375 #if 1
1376 fAppl.setStyleSheet(
1377
1378 // BUTTONS
1379 "QPushButton {"
1380 "background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1,"
1381 "stop: 0 #B0B0B0, stop: 1 #404040);"
1382 "border: 2px solid grey;"
1383 "border-radius: 6px;"
1384 "margin-top: 1ex;"
1385 "}"
1386
1387 "QPushButton:hover {"
1388 "border: 2px solid orange;"
1389 "}"
1390
1391 "QPushButton:pressed {"
1392 //"border: 1px solid orange;"
1393 "background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,"
1394 "stop: 0 #404040, stop: 1 #B0B0B0);"
1395 "}"
1396 // GROUPS
1397 "QGroupBox {"
1398 "background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1,"
1399 "stop: 0 #A0A0A0, stop: 1 #202020);"
1400 "border: 2px solid gray;"
1401 "border-radius: 5px;"
1402 "margin-top: 1ex;"
1403 "font-size:7pt;"
1404 "font-weight:bold;"
1405 //"color: dark grey;"
1406 "color: white;"
1407 "}"
1408
1409 "QGroupBox::title {"
1410 "subcontrol-origin: margin;"
1411 "subcontrol-position: top center;" /* position at the top center */
1412 "padding: 0 5px;"
1413 "}"
1414 // SLIDERS
1415 // horizontal sliders
1416 "QSlider::groove:vertical {"
1417 "background: red;"
1418 "position: absolute;" /* absolutely position 4px from the left and right of the widget. setting margins on the widget should work too... */
1419 "left: 13px; right: 13px;"
1420 "}"
1421
1422 "QSlider::handle:vertical {"
1423 "height: 40px;"
1424 "width: 30px;"
1425 "background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,"
1426 "stop: 0 #AAAAAA, stop : 0.05 #0A0A0A, stop: 0.3 #101010, stop : 0.90 #AAAAAA, stop: 0.91 #000000);"
1427 "margin: 0 -5px; /* expand outside the groove */"
1428 "border-radius: 5px;"
1429 "}"
1430
1431 "QSlider::add-page:vertical {"
1432 "background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0,"
1433 "stop: 0 yellow, stop : 0.5 orange);"
1434 "}"
1435
1436 "QSlider::sub-page:vertical {"
1437 "background: grey;"
1438 "}"
1439
1440 // horizontal sliders
1441
1442 "QSlider::groove:horizontal {"
1443 "background: red;"
1444 "position: absolute;" /* absolutely position 4px from the left and right of the widget. setting margins on the widget should work too... */
1445 "top: 14px; bottom: 14px;"
1446 "}"
1447
1448 "QSlider::handle:horizontal {"
1449 "width: 40px;"
1450 "background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0,"
1451 "stop: 0 #AAAAAA, stop : 0.05 #0A0A0A, stop: 0.3 #101010, stop : 0.90 #AAAAAA, stop: 0.91 #000000);"
1452 "margin: -5px 0; /* expand outside the groove */"
1453 "border-radius: 5px;"
1454 "}"
1455
1456 "QSlider::sub-page:horizontal {"
1457 "background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,"
1458 "stop: 0 yellow, stop : 0.5 orange);"
1459 "}"
1460
1461 "QSlider::add-page:horizontal {"
1462 "background: grey;"
1463 "}"
1464
1465 // TABS
1466 //TabWidget and TabBar
1467 "QTabWidget::pane {" /* The tab widget frame */
1468 //"border-top: 2px solid #C2C7CB;"
1469 "border-top: 2px solid orange;"
1470 "background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,"
1471 "stop: 0 #A0A0A0, stop: 1 #202020);"
1472 "}"
1473
1474 "QTabWidget::tab-bar {"
1475 "left: 5px;" /* move to the right by 5px */
1476 "}"
1477
1478 /* Style the tab using the tab sub-control. Note that
1479 it reads QTabBar _not_ QTabWidget */
1480 "QTabBar::tab {"
1481 "background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,"
1482 "stop: 0 #909090, stop: 0.4 #888888,"
1483 "stop: 0.5 #808080, stop: 1.0 #909090);"
1484 "border: 2px solid #808080;"
1485 //"border-bottom-color: #C2C7CB;" /* same as the pane color */
1486 "border-bottom-color: orange;" /* same as the pane color */
1487 "border-top-left-radius: 4px;"
1488 "border-top-right-radius: 4px;"
1489 "min-width: 8ex;"
1490 "padding: 2px;"
1491 "}"
1492
1493 "QTabBar::tab:selected, QTabBar::tab:hover {"
1494 "background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,"
1495 "stop: 0 #D0D0D0, stop: 0.4 #A0A0A0,"
1496 "stop: 0.5 #808080, stop: 1.0 #A0A0A0);"
1497 //"stop: 0.5 #A0A0A0, stop: 1.0 #C0C0C0);"
1498 //"stop: 0 #fafafa, stop: 0.4 #f4f4f4,"
1499 //"stop: 0.5 #e7e7e7, stop: 1.0 #fafafa);"
1500 //"border-bottom-color: orange;" /* same as the pane color */
1501 "}"
1502
1503 "QTabBar::tab:selected {"
1504 "border-color: orange;"
1505 "border-bottom-color: #A0A0A0;" /* same as pane color */
1506 "}"
1507
1508 "QTabBar::tab:!selected {"
1509 " margin-top: 2px;" /* make non-selected tabs look smaller */
1510 "}"
1511 );
1512 #endif
1513 fAppl.exec();
1514 stop();
1515
1516 }
1517
1518
1519 // ------------------------- Groups -----------------------------------
1520
1521 virtual void openHorizontalBox(const char* label) {
1522 openBox(label, new QHBoxLayout());
1523 }
1524
1525 virtual void openVerticalBox(const char* label) {
1526 openBox(label, new QVBoxLayout());
1527 }
1528
1529 virtual void openFrameBox(const char* ) { }
1530 virtual void openTabBox(const char* label) {
1531 openTab(label);
1532 }
1533
1534 virtual void closeBox()
1535 {
1536 QWidget* group = fGroupStack.top();
1537 fGroupStack.pop();
1538 if (fGroupStack.empty()) { group->show(); }
1539 }
1540
1541 // ------------------------- active widgets -----------------------------------
1542
1543 virtual void addButton(const char* label , float* zone)
1544 {
1545 QAbstractButton* w = new QPushButton(label);
1546 uiButton* c = new uiButton(this, zone, w);
1547
1548 insert(label, w);
1549 QObject::connect(w, SIGNAL(pressed()), c, SLOT(pressed()));
1550 QObject::connect(w, SIGNAL(released()), c, SLOT(released()));
1551 checkForTooltip(zone, w);
1552 }
1553
1554 virtual void addToggleButton(const char* , float* )
1555 {}
1556
1557 virtual void addCheckButton(const char* label , float* zone)
1558 {
1559 QCheckBox* w = new QCheckBox(label);
1560 uiCheckButton* c = new uiCheckButton(this, zone, w);
1561
1562 insert(label, w);
1563 QObject::connect(w, SIGNAL(stateChanged(int)), c, SLOT(setState(int)));
1564 checkForTooltip(zone, w);
1565 }
1566
1567 virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step)
1568 {
1569 if (isKnob(zone)) {
1570 addVerticalKnob(label, zone, init, min, max, step);
1571 return;
1572 }
1573 //insert(label, new QDoubleSpinBox());
1574 if (label && label[0]) openVerticalBox(label);
1575 QDoubleSpinBox* w = new QDoubleSpinBox();
1576 uiNumEntry* c = new uiNumEntry(this, zone, w, init, min, max, step);
1577 insert(label, w);
1578 w->setSuffix(fUnit[zone].c_str());
1579 QObject::connect(w, SIGNAL(valueChanged(double)), c, SLOT(setValue(double)));
1580 if (label && label[0]) closeBox();
1581 checkForTooltip(zone, w);
1582 }
1583
1584 // special num entry without buttons
1585 virtual void addNumDisplay(const char* label, float* zone, float init, float min, float max, float step)
1586 {
1587 //insert(label, new QDoubleSpinBox());
1588 if (label && label[0]) openVerticalBox(label);
1589 QDoubleSpinBox* w = new QDoubleSpinBox();
1590 w->setAlignment(Qt::AlignHCenter);
1591 #if 1
1592 w->setStyleSheet(
1593 "QDoubleSpinBox {"
1594 "border: 2px solid orange;"
1595 "border-radius: 5px;"
1596 "}"
1597 );
1598 #endif
1599 uiNumEntry* c = new uiNumEntry(this, zone, w, init, min, max, step);
1600 insert(label, w);
1601 w->setButtonSymbols(QAbstractSpinBox::NoButtons);
1602 w->setSuffix(fUnit[zone].c_str());
1603 QObject::connect(w, SIGNAL(valueChanged(double)), c, SLOT(setValue(double)));
1604 if (label && label[0]) closeBox();
1605 checkForTooltip(zone, w);
1606 }
1607
1608
1609 //////////////////////////////////////////////////////////////////////////////////////////////////////////
1610 //
1611 // KNOBS
1612 //
1613 //////////////////////////////////////////////////////////////////////////////////////////////////////////
1614
1615 virtual void addVerticalKnob(const char* label , float* zone, float init, float min, float max, float step)
1616 {
1617 openVerticalBox(label);
1618 QAbstractSlider* w = new QDial(); //qsynthKnob();
1619 uiKnob* c = new uiKnob(this, zone, w, init, min, max, step);
1620 insert(label, w);
1621 w->setStyle(new qsynthDialVokiStyle());
1622 QObject::connect(w, SIGNAL(valueChanged(int)), c, SLOT(setValue(int)));
1623 addNumDisplay(0, zone, init, min, max, step);
1624
1625 // compute the size of the knob+display
1626 int width = int(64*pow(2,fGuiSize[zone]));
1627 int height = int(100*pow(2,fGuiSize[zone]));
1628 fGroupStack.top()->setMinimumSize(width,height);
1629 fGroupStack.top()->setMaximumSize(width,height);
1630
1631 closeBox();
1632 checkForTooltip(zone, w);
1633 }
1634
1635 virtual void addHorizontalKnob(const char* label , float* zone, float init, float min, float max, float step)
1636 {
1637 openHorizontalBox(label);
1638 QAbstractSlider* w = new QDial(); //new qsynthKnob();
1639 uiKnob* c = new uiKnob(this, zone, w, init, min, max, step);
1640 insert(label, w);
1641 w->setStyle(new qsynthDialVokiStyle());
1642 QObject::connect(w, SIGNAL(valueChanged(int)), c, SLOT(setValue(int)));
1643 addNumDisplay(0, zone, init, min, max, step);
1644 closeBox();
1645 checkForTooltip(zone, w);
1646 }
1647
1648 //////////////////////////////////////////////////////////////////////////////////////////////////////////
1649 //
1650 // SLIDERS
1651 //
1652 //////////////////////////////////////////////////////////////////////////////////////////////////////////
1653
1654 virtual void addVerticalSlider(const char* label , float* zone, float init, float min, float max, float step)
1655 {
1656 if (isKnob(zone)) {
1657 addVerticalKnob(label, zone, init, min, max, step);
1658 return;
1659 }
1660 openVerticalBox(label);
1661 QSlider* w = new QSlider(Qt::Vertical);
1662 w->setMinimumHeight(160);
1663 w->setMinimumWidth(34);
1664 //w->setTickPosition(QSlider::TicksBothSides);
1665 uiSlider* c = new uiSlider(this, zone, w, init, min, max, step);
1666 insert(label, w);
1667 QObject::connect(w, SIGNAL(valueChanged(int)), c, SLOT(setValue(int)));
1668 addNumDisplay(0, zone, init, min, max, step);
1669 closeBox();
1670 checkForTooltip(zone, w);
1671 }
1672
1673 virtual void addHorizontalSlider(const char* label , float* zone, float init, float min, float max, float step)
1674 {
1675 if (isKnob(zone)) {
1676 addHorizontalKnob(label, zone, init, min, max, step);
1677 return;
1678 }
1679 openHorizontalBox(label);
1680 QSlider* w = new QSlider(Qt::Horizontal);
1681 w->setMinimumHeight(34);
1682 w->setMinimumWidth(160);
1683 //w->setTickPosition(QSlider::TicksBothSides);
1684 uiSlider* c = new uiSlider(this, zone, w, init, min, max, step);
1685 insert(label, w);
1686 QObject::connect(w, SIGNAL(valueChanged(int)), c, SLOT(setValue(int)));
1687 addNumDisplay(0, zone, init, min, max, step);
1688 closeBox();
1689 checkForTooltip(zone, w);
1690 }
1691
1692 // ------------------------- passive widgets -----------------------------------
1693
1694 virtual void addNumDisplay(const char*, float*, int)
1695 {}
1696
1697 virtual void addTextDisplay(const char*, float*, const char* [], float, float)
1698 {}
1699
1700 virtual void addHorizontalBargraph(const char* label , float* zone, float min, float max)
1701 {
1702 AbstractDisplay* bargraph;
1703 openVerticalBox(label);
1704 bool db = (fUnit[zone] == "dB");
1705
1706 if (fLedSet.count(zone)) {
1707 if (db) {
1708 bargraph = new dbLED(min, max);
1709 } else {
1710 bargraph = new LED(min,max);
1711 }
1712 } else {
1713 if (db) {
1714 bargraph = new dbHorizontalBargraph(min, max);
1715 } else {
1716 bargraph = new linHorizontalBargraph(min, max);
1717 }
1718 }
1719
1720 new uiBargraph2(this, zone, bargraph, min, max);
1721 insert(label, bargraph);
1722 closeBox();
1723 checkForTooltip(zone, bargraph);
1724 }
1725
1726 virtual void addVerticalBargraph(const char* label , float* zone, float min, float max)
1727 {
1728 AbstractDisplay* bargraph;
1729 openVerticalBox(label);
1730 bool db = (fUnit[zone] == "dB");
1731
1732 if (fLedSet.count(zone)) {
1733 if (db) {
1734 bargraph = new dbLED(min, max);
1735 } else {
1736 bargraph = new LED(min,max);
1737 }
1738 } else {
1739 if (db) {
1740 bargraph = new dbVerticalBargraph(min, max);
1741 } else {
1742 bargraph = new linVerticalBargraph(min, max);
1743 }
1744 }
1745 new uiBargraph2(this, zone, bargraph, min, max);
1746 insert(label, bargraph);
1747 closeBox();
1748 checkForTooltip(zone, bargraph);
1749 }
1750
1751 };
1752
1753 #endif