Salome HOME
GUI of YDFX is in for uncertainties and parametric users.
[modules/yacs.git] / src / ydfx_gui / YDFXGUIPortsSelector.cxx
1 // Copyright (C) 2016  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (EDF R&D)
20
21 #include "YDFXGUIPortsSelector.hxx"
22 #include "YDFXGUIPortsValidator.hxx"
23
24 #include "YACSEvalPort.hxx"
25 #include "YACSEvalSeqAny.hxx"
26
27 #include <QLabel>
28 #include <QPainter>
29 #include <QLineEdit>
30 #include <QClipboard>
31 #include <QHeaderView>
32 #include <QVBoxLayout>
33 #include <QHBoxLayout>
34 #include <QPaintEvent>
35 #include <QApplication>
36 #include <QSplitter>
37
38 #include <string>
39 #include <iostream>
40 #include <limits>
41 #include <cmath>
42
43 const int MyWidgetPainter::SZ_OF_PEN_RECT=2;
44 const int MyWidgetPainter::PADLOCK_X=130;
45 const int MyWidgetPainter::PADLOCK_Y=206;
46 const int MyWidgetPainter::DICE_X=225;
47 const int MyWidgetPainter::DICE_Y=225;
48 const int HoverLabel::PT_SZ_ON_HOVER=8;
49 const int OutputLabel::PEN_SZ_CIRCLED=5;
50
51 void MyWidgetPainter::drawPadlock(QWidget *wid) const
52 {
53   static const int STRT_BASEY=86,H_CHORD=18;
54   const float RATIO(float(PADLOCK_Y)/float(PADLOCK_X));
55   QPainter painter(wid);
56   int width(wid->width()),height(wid->height());
57   if(float(height)>RATIO*float(width))
58     painter.setViewport(0,int(height-RATIO*float(width))/2,width,width*RATIO);
59   else
60     painter.setViewport((float(width)-height/RATIO)/2,0,height/RATIO,height);//width-height/RATIO
61   painter.setRenderHint(QPainter::Antialiasing,true);
62   painter.setWindow(0,-STRT_BASEY,PADLOCK_X,PADLOCK_Y);
63   painter.setPen(QPen(Qt::black,SZ_OF_PEN_RECT,Qt::SolidLine,Qt::SquareCap));
64   
65   float radius=PADLOCK_X*PADLOCK_X/(8*H_CHORD)+H_CHORD/2;
66   float startAngle=acos(PADLOCK_X/(2.*radius))/M_PI*180*16;
67   float spanAngle=2*asin(PADLOCK_X/(2*radius))/M_PI*180*16;
68   
69   //
70   QColor darkYellow(194,170,99),brightYellow(255,250,219),zeYellow(255,212,80);
71   QBrush brush(painter.brush());
72   QLinearGradient grad(0,0,PADLOCK_X,0);
73   grad.setColorAt(0.,darkYellow);
74   grad.setColorAt(0.8,brightYellow);
75   grad.setColorAt(1.,zeYellow);
76   painter.setBrush(grad);
77   //painter.setCompositionMode(QPainter::CompositionMode_DestinationOver);// SourceOver by default
78   painter.drawRect(QRect(SZ_OF_PEN_RECT,SZ_OF_PEN_RECT,PADLOCK_X-2*SZ_OF_PEN_RECT,PADLOCK_Y-STRT_BASEY-2*SZ_OF_PEN_RECT));
79   //
80   painter.setBrush(brush);
81   painter.drawRect(QRect(0+SZ_OF_PEN_RECT/2,0+SZ_OF_PEN_RECT/2,PADLOCK_X-SZ_OF_PEN_RECT,PADLOCK_Y-STRT_BASEY-SZ_OF_PEN_RECT));
82   QTransform t,t2;
83   t.translate(0,-(STRT_BASEY+H_CHORD)) ; t.rotate(180) ; t.translate(-PADLOCK_X,-STRT_BASEY-2*H_CHORD);
84   painter.setWorldTransform(t);
85   painter.drawChord(QRect(-(radius-PADLOCK_X/2),0,2*radius,2*radius),180*16-startAngle,-spanAngle);
86   painter.setWorldTransform(t2);
87   //
88   painter.drawLine(6,0,6,-24); painter.drawLine(25,0,25,-24);
89   //painter.drawLine(103,0,103,-24); painter.drawLine(122,0,122,-24);
90   const int r1(39),r2(58);//78==103-25 116==122-6
91   const int center[2]={64,-24};
92   float p1x=cos((180.-_angle)/180.*M_PI)*r1+center[0];
93   float p1y=-sin((180.-_angle)/180.*M_PI)*r1+center[1];
94   float p2x=cos((180.-_angle)/180.*M_PI)*r2+center[0];
95   float p2y=-sin((180.-_angle)/180.*M_PI)*r2+center[1];
96   painter.drawArc(QRect(25,-63,2*r1,2*r1),180*16,-_angle*16);
97   painter.drawArc(QRect(6,-82,2*r2,2*r2),180*16,-_angle*16);
98   painter.drawLine(p1x,p1y,p2x,p2y);
99 }
100
101 void MyWidgetPainter::drawDice(QWidget *wid) const
102 {
103   QPainter painter(wid);
104   int width(wid->width()),height(wid->height());
105   if(height>width)
106     painter.setViewport(0,(height-width)/2,width,width);
107   else
108     painter.setViewport((width-height)/2,0,height,height);
109   painter.setRenderHint(QPainter::Antialiasing,true);
110   painter.setWindow(0,0,DICE_X,DICE_Y);
111   const QPoint face0[4]={QPoint(22,35),QPoint(113,110),QPoint(90,224),QPoint(0,148)};
112   const QPoint face1[4]={QPoint(113,110),QPoint(224,73),QPoint(196,185),QPoint(90,224)};
113   const QPoint face2[4]={QPoint(22,35),QPoint(113,110),QPoint(224,73),QPoint(126,0)};
114   QLinearGradient grad(0,0,PADLOCK_X,0);
115   QColor red0(154,18,20),red1(87,11,13),red2(205,25,24);
116   painter.setBrush(QBrush(red0)); painter.drawPolygon(face0,4);
117   painter.setBrush(QBrush(red1)); painter.drawPolygon(face1,4);
118   painter.setBrush(QBrush(red2)); painter.drawPolygon(face2,4);
119   //32x16 rot=12*16
120   QColor grey(209,209,209);
121   painter.setBrush(grey);
122   //
123   const int NB_POINTS=14;
124   const float refs[NB_POINTS*2]={50,29,76,48,104,70,112,10,140,29,168,50,
125                                  33,57,53,114,72,171,21,127,87,103,
126                                  109,192,148,145,186,102
127   };
128   const int angles[NB_POINTS]={12,12,12,12,12,12,72,72,72,72,72,-47,-47,-47};
129   for(int i=0;i<NB_POINTS;i++)
130     {
131       QTransform t;
132       float angle(angles[i]);
133       float angler(-angle/180*M_PI);
134       float refX(refs[2*i]),refY(refs[2*i+1]);
135       t.rotate(angle) ; t.translate((cos(angler)*refX-sin(angler)*refY),(sin(angler)*refX+cos(angler)*refY));
136       painter.setWorldTransform(t);
137       painter.drawEllipse(0,0,32,16);
138     }
139 }
140
141 void MyWidgetPainter::changeAngle()
142 {
143   const int resolution(5);
144   _angle=(((_angle-120)+resolution)%60)+120;
145 }
146
147 void MyWidgetPainter::paintDataCommonPart(QPaintEvent *event, const QString& text)
148 {
149   int width0(getWidget()->width()),height0(getWidget()->height());
150   QRect refRect(0,0,width0,height0);
151   QPainter painter(getWidget());
152   //const QRect& refRect(event->rect());//getWidget()->frameGeometry()
153   QRect refRect2(refRect);//event->rect());
154   painter.setPen(QPen(Qt::red,SZ_OF_PEN_RECT,Qt::SolidLine,Qt::RoundCap));
155   refRect2.translate(SZ_OF_PEN_RECT,SZ_OF_PEN_RECT);
156   refRect2.setWidth(refRect2.width()-2*SZ_OF_PEN_RECT);;
157   refRect2.setHeight(refRect2.height()-2*SZ_OF_PEN_RECT);
158   painter.drawRect(refRect2);
159   painter.setPen(QPen(Qt::black,10,Qt::SolidLine,Qt::RoundCap));
160   QRect rect(painter.boundingRect(refRect,Qt::AlignTop,text));//Qt::AlignCenter
161   const QFont& ft(getWidget()->font());
162   QFontMetrics fm(ft);
163   painter.drawText(QPoint(refRect.x()+SZ_OF_PEN_RECT+refRect2.width()/2-rect.width()/2,
164                           refRect.y()+refRect.height()/2+rect.height()/2-fm.descent()),text);
165 }
166
167 template<class FontBrushSetGet>
168 void MyWidgetPainterNoFocus::prepareFontAndBrush(FontBrushSetGet *fbsg)
169 {
170   QFont ft(fbsg->font());
171   ft.setBold(true);
172   fbsg->setFont(ft);
173 }
174
175 void MyWidgetPainterNoFocus::paintEvent(QPaintEvent *event)
176 {
177   prepareFontAndBrush(getWidget());
178   if(!getWidget()->isRandom())
179     {
180       if(getWidget()->text().isEmpty())
181         drawPadlock(getWidget());
182       else
183         paintDataCommonPart(event,getWidget()->text());
184     }
185   else
186     drawDice(getWidget());
187 }
188
189 QSize MyWidgetPainterNoFocus::sizeHint() const
190 {
191   if(!getWidget()->isRandom())
192     {
193       if(getWidget()->text().isEmpty())
194         return QSize(PADLOCK_X/6,PADLOCK_Y/6);
195       else
196         {
197           QPixmap px(1000,1000);
198           QPainter painter(&px);
199           painter.setPen(QPen(Qt::black,5,Qt::SolidLine,Qt::RoundCap));
200           prepareFontAndBrush(&painter);
201           QRect rect(painter.boundingRect(QRect(),Qt::AlignTop,getWidget()->text()));
202           return QSize(rect.width()+2*SZ_OF_PEN_RECT,rect.height()+2*SZ_OF_PEN_RECT);
203         }
204     }
205   else
206     return QSize(DICE_X/5,DICE_Y/5);
207 }
208
209 void MyWidgetPainterNoFocus::appendLetter(const QString& letter)
210 {
211 }
212
213 void MyWidgetPainterNoFocus::supprLetter()
214 {
215 }
216
217 template<class FontBrushSetGet>
218 void MyWidgetPainterFocus::prepareFontAndBrush(FontBrushSetGet *fbsg)
219 {
220   QFont ft(fbsg->font());
221   ft.setBold(false);
222   fbsg->setFont(ft);
223 }
224
225 void MyWidgetPainterFocus::paintEvent(QPaintEvent *event)
226 {
227   prepareFontAndBrush(getWidget());
228   paintDataCommonPart(event,_textEntered);
229 }
230
231 QSize MyWidgetPainterFocus::sizeHint() const
232 {
233   QPixmap px(1000,1000);
234   QPainter painter(&px);
235   painter.setPen(QPen(Qt::black,5,Qt::SolidLine,Qt::RoundCap));
236   prepareFontAndBrush(&painter);
237   QRect rect(painter.boundingRect(QRect(),Qt::AlignTop,_textEntered));
238   return QSize(rect.width(),rect.height());
239 }
240
241 void MyWidgetPainterFocus::appendLetter(const QString& letter)
242 {
243   _textEntered+=letter;
244   getWidget()->updateGeometry();
245   getWidget()->update();
246 }
247
248 void MyWidgetPainterFocus::supprLetter()
249 {
250   _textEntered.chop(1);
251   getWidget()->updateGeometry();
252   getWidget()->update();
253 }
254
255 /////////////
256
257 YDFXGUIInputPortValueEditor::YDFXGUIInputPortValueEditor(YACSEvalInputPort *inp):_inp(inp),_zePainter(new MyWidgetPainterNoFocus(this)),_valid(0)
258 {
259   _valid=BuildValidatorFromPort(this,_inp);
260   QString txt(text());
261   setText(txt);
262   setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum);//Fixed
263   setFocusPolicy(Qt::ClickFocus);
264 }
265
266 YDFXGUIInputPortValueEditor::~YDFXGUIInputPortValueEditor()
267 {
268   delete _zePainter;
269 }
270
271 QString YDFXGUIInputPortValueEditor::text() const
272 {
273   QString txt;
274   if(_inp->hasDefaultValueDefined())
275     {
276       YACSEvalAny *val(_inp->getDefaultValueDefined());
277       txt=BuidStringFromAny(val);
278       delete val;
279     }
280   return txt;
281 }
282
283 void YDFXGUIInputPortValueEditor::setText(const QString& text)
284 {
285   bool wasKO(!_inp->hasDefaultValueDefined());
286   YACSEvalAny *val(BuildAnyFromString(text,_inp));
287   _inp->setDefaultValue(val);
288   QString text2(BuidStringFromAny(val));
289   delete val;
290   QString toolTipText(QString("Default = %1").arg(text2));
291   if(text.isNull())
292     toolTipText="No default set !";
293   setToolTip(toolTipText);
294   if(text.isEmpty())
295     {
296       connect(this,SIGNAL(changeLook()),this,SLOT(applyModificationOfLook()));
297     }
298   else
299     {
300       if(wasKO)
301         {
302           emit statusChanged();
303           disconnect(this,SIGNAL(changeLook()),this,SLOT(applyModificationOfLook()));
304         }
305     }
306 }
307
308 void YDFXGUIInputPortValueEditor::paintEvent(QPaintEvent *event)
309 {
310   _zePainter->paintEvent(event);
311 }
312
313 void YDFXGUIInputPortValueEditor::mousePressEvent(QMouseEvent *event)
314 {
315   delete _zePainter;
316   _zePainter=new MyWidgetPainterFocus(this);
317   updateGeometry();
318   update();
319 }
320
321 void YDFXGUIInputPortValueEditor::mouseReleaseEvent(QMouseEvent *event)
322 {
323   QClipboard *cb(QApplication::clipboard());
324   if(event->button()==Qt::MidButton && cb->supportsSelection())
325     {
326       QString text(cb->text(QClipboard::Selection));
327       int pos;
328       if(_valid->validate(text,pos)==QValidator::Acceptable)
329         {
330           delete _zePainter;
331           _zePainter=new MyWidgetPainterNoFocus(this);
332           setText(text);
333           update();
334         }
335     }
336 }
337
338 void YDFXGUIInputPortValueEditor::keyPressEvent(QKeyEvent *event)
339 {
340   int ekey(event->key());
341   if(ekey==Qt::Key_Return || ekey==Qt::Key_Enter)
342     {
343       clearFocus();
344       return ;
345     }
346   if(ekey==Qt::Key_Escape)
347     {
348       delete _zePainter;
349       _zePainter=new MyWidgetPainterNoFocus(this);
350       clearFocus();
351       return ;
352     }
353   if(ekey==Qt::Key_Backspace)
354     {
355       _zePainter->supprLetter();
356       return ;
357     }
358   if((ekey>=Qt::Key_Exclam && ekey<=Qt::Key_Z))
359     {
360       QString st(event->text());
361       _zePainter->appendLetter(st);
362     }
363 }
364
365 void YDFXGUIInputPortValueEditor::focusOutEvent(QFocusEvent * event)
366 {
367   MyWidgetPainterFocus *zePainter(dynamic_cast<MyWidgetPainterFocus *>(_zePainter));
368   if(zePainter)
369     {
370       int pos;
371       QString zeSt(zePainter->getText());
372       delete _zePainter;
373       _zePainter=new MyWidgetPainterNoFocus(this);
374       if(_valid->validate(zeSt,pos)==QValidator::Acceptable)
375         setText(zeSt);
376     }
377   updateGeometry();
378   update();
379 }
380
381 QSize YDFXGUIInputPortValueEditor::sizeHint() const
382 {
383   return _zePainter->sizeHint();
384 }
385
386 QSize YDFXGUIInputPortValueEditor::minimumSizeHint() const
387 {
388   return _zePainter->sizeHint();
389 }
390
391 bool YDFXGUIInputPortValueEditor::isOK() const
392 {
393   return IsOK(_inp);
394 }
395
396 bool YDFXGUIInputPortValueEditor::IsOK(YACSEvalInputPort *inp)
397 {
398   return inp->isRandomVar() || inp->hasDefaultValueDefined();
399 }
400
401 bool YDFXGUIInputPortValueEditor::isRandom() const
402 {
403   return _inp->isRandomVar();
404 }
405
406 bool YDFXGUIInputPortValueEditor::toggleRandom()
407 {
408   bool oldOK(isOK());
409   bool oldStatus(_inp->isRandomVar());
410   _inp->declareRandomnessStatus(!oldStatus);
411   emit statusChanged(); // always emit because this even if newOK and oldOK are the same the upon status can changed !
412   updateGeometry();
413   update();
414   return _inp->isRandomVar();
415 }
416
417 void YDFXGUIInputPortValueEditor::applyModificationOfLook()
418 {
419   _zePainter->changeAngle();
420   if(!isOK())
421     this->update();
422 }
423
424 //////////////////
425
426 HoverLabel::HoverLabel(QWidget *parent):QLabel(parent),_isin(false),_isPressed(false)
427 {
428   //setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed);
429   setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
430 }
431
432 void HoverLabel::mousePressEvent(QMouseEvent *event)
433 {
434   if(event->button()==Qt::LeftButton)
435     {
436       _isPressed=true;
437       pressOccured();
438       updateGeometry();
439       update();
440     }
441 }
442
443 void HoverLabel::mouseReleaseEvent(QMouseEvent *event)
444 {
445   if(event->button()==Qt::LeftButton)
446     {
447       _isPressed=false;
448       updateGeometry();
449       update();
450     }
451 }
452
453 void HoverLabel::enterEvent(QEvent *event)
454 {
455   _isin=true;
456   updateGeometry();
457   update();
458 }
459
460 void HoverLabel::leaveEvent(QEvent *event)
461 {
462   _isin=false;
463   updateGeometry();
464   update();
465 }
466
467 void HoverLabel::paintEvent(QPaintEvent *event)
468 {
469   if(!_isin)
470     return paintIfNotOn(event);
471   //
472   QPainter painter(this);
473   QFont ft(painter.font());
474   AssignFontOnHover(ft);
475   painter.setFont(ft);
476   QFontMetrics fm(ft);
477   QPalette pal(QApplication::palette("QPushButton"));
478   QRect refRect(rect());
479   std::vector<ColoredString> sts(textForEmulatedPushButton());
480   QRect rect3(painter.boundingRect(refRect,Qt::AlignTop,sts[0].str()));
481   int deltaY((refRect.height()-sts.size()*rect3.height())/(sts.size()+1));
482   QBrush b0(pal.color(_isPressed?QPalette::Dark:QPalette::Button));
483   painter.setBrush(b0);
484   painter.setPen(QPen(pal.color(QPalette::Highlight),1,Qt::SolidLine,Qt::SquareCap));
485   painter.drawRoundedRect(QRect(0,0,refRect.width()-1,refRect.height()-1),3,3);
486   painter.setBrush(QBrush());
487   painter.setPen(QPen(pal.color(QPalette::Shadow),1,Qt::SolidLine,Qt::SquareCap));
488   painter.drawRoundedRect(QRect(1,1,refRect.width()-3,refRect.height()-3),3,3);
489   painter.setPen(QPen(pal.color(QPalette::Dark),1,Qt::SolidLine,Qt::SquareCap));
490   painter.drawRoundedRect(QRect(2,2,refRect.width()-5,refRect.height()-5),5,5);
491   painter.setPen(QPen(pal.color(QPalette::Midlight),1,Qt::SolidLine,Qt::SquareCap));
492   painter.drawRoundedRect(QRect(3,3,refRect.width()-7,refRect.height()-7),3,3);
493   painter.setPen(QPen(pal.color(QPalette::Light),1,Qt::SolidLine,Qt::SquareCap));
494   painter.drawRoundedRect(QRect(4,4,refRect.width()-9,refRect.height()-9),3,3);
495   //QPalette::Button QPalette::ButtonText
496   painter.setPen(QPen(pal.color(QPalette::ButtonText),2,Qt::SolidLine,Qt::SquareCap));
497   int posY(deltaY);
498   foreach(ColoredString st,sts)
499     {
500       QRect rect2(painter.boundingRect(refRect,Qt::AlignTop,st.str()));
501       QPen pen(painter.pen());
502       QPen pen2(pen);
503       pen2.setColor(st.color());
504       painter.setPen(pen2);
505       painter.drawText(QPoint((refRect.width()-rect2.width())/2,posY+rect2.height()-fm.descent()),st.str());
506       painter.setPen(pen);
507       posY+=deltaY+rect2.height();
508     }
509 }
510
511 QSize HoverLabel::sizeHint() const
512 {
513   if(!_isin)
514     return sizeHintNotHovered();
515   else
516     {
517       QFont ft(font());
518       AssignFontOnHover(ft);
519       QFontMetrics fm(ft);
520       std::vector<ColoredString> sts(textForEmulatedPushButton());
521       int h(0),w(0);
522       foreach(ColoredString st,sts)
523         {
524           QSize elt(fm.boundingRect(st.str()).size());
525           h+=elt.height();
526           w=std::max(w,elt.width());
527         }
528       QSize ret;
529       ret.setHeight(h); ret.setWidth(w);//3*PT_SZ_ON_HOVER
530       return ret;
531     }
532 }
533
534 void HoverLabel::AssignFontOnHover(QFont& ft)
535 {
536   ft.setBold(true);
537   ft.setItalic(true);
538   ft.setPointSize(PT_SZ_ON_HOVER);
539 }
540
541 //////////////////
542
543 InputLabel::InputLabel(YACSEvalInputPort *inp, QWidget *parent):HoverLabel(parent),_inp(inp)
544 {
545   AssignTextAndTooltip(this,_inp);
546 }
547
548 QSize InputLabel::sizeHintNotHovered() const
549 {
550   return QLabel::sizeHint();
551 }
552
553 void InputLabel::paintIfNotOn(QPaintEvent *event)
554 {
555   QLabel::paintEvent(event);
556 }
557
558 void InputLabel::pressOccured()
559 {
560   emit randomnessStatusChanged();
561 }
562
563 std::vector<ColoredString> InputLabel::textForEmulatedPushButton() const
564 {
565   std::vector<ColoredString> ret;
566   if(!_inp->isRandomVar())
567     ret.push_back(QString(" Parametrize %1 ").arg(text()));
568   else
569     ret.push_back(QString(" Unparametrize %1 ").arg(text()));
570   return ret;
571 }
572
573 void InputLabel::AssignTextAndTooltip(QLabel *wid, YACSEvalInputPort *port)
574 {
575   QString txt(port->getName().c_str());
576   wid->setText(txt);
577   wid->setToolTip(QString("%1 (%2)").arg(txt).arg(QString(port->getTypeOfData().c_str())));
578 }
579
580 //////////////////
581
582 InputLabelNonToggle::InputLabelNonToggle(YDFXGUIInputPortValueEditor *wid, QWidget *parent):QLabel(parent),_wid(wid)
583 {
584   setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
585   InputLabel::AssignTextAndTooltip(this,_wid->getPort());
586 }
587
588 //////////////////
589
590 OutputLabel::OutputLabel(YACSEvalOutputPort *outp, QWidget *parent):HoverLabel(parent),_outp(outp)
591 {
592   QString txt(_outp->getName().c_str());
593   setText(txt);
594   setToolTip(txt);
595 }
596
597 bool OutputLabel::isQOfInt() const
598 {
599   return _outp->isQOfInterest();
600 }
601
602 QSize OutputLabel::sizeHintNotHovered() const
603 {
604   if(!isQOfInt())
605     return QLabel::sizeHint();
606   const QFont& ft(font());
607   QFontMetrics fm(ft);
608   QString txt(text());
609   QPointF pts[7];
610   ComputePointsToCircle(txt,rect(),font(),pts);
611   QPainterPath path;
612   path.moveTo(pts[0]);
613   path.cubicTo(pts[1],pts[2],pts[3]);
614   path.cubicTo(pts[4],pts[5],pts[6]);
615   QSize ret(path.boundingRect().toRect().size());
616   int& rh(ret.rheight()),&rw(ret.rwidth());
617   rh+=2*PEN_SZ_CIRCLED; rw+=2*PEN_SZ_CIRCLED; 
618   return ret;
619 }
620
621 void OutputLabel::paintIfNotOn(QPaintEvent *event)
622 {
623   QLabel::paintEvent(event);
624   if(!isQOfInt())
625     return ;
626   QString txt(text());
627   //
628   const QFont& ft(font());
629   QFontMetrics fm(ft);
630   QPainter painter(this);
631   //
632   QPointF pts[7];
633   ComputePointsToCircle(txt,rect(),font(),pts);
634   //
635   QPainterPath path;
636   path.moveTo(pts[0]);
637   path.cubicTo(pts[1],pts[2],pts[3]);
638   path.cubicTo(pts[4],pts[5],pts[6]);
639   QPen pen(painter.pen());
640   pen.setColor(Qt::green); pen.setWidth(PEN_SZ_CIRCLED);
641   painter.strokePath(path,pen);
642 }
643
644 void OutputLabel::pressOccured()
645 {
646   bool oldStatus(_outp->isQOfInterest());
647   _outp->setQOfInterestStatus(!oldStatus);
648   emit clicked();
649 }
650
651 std::vector<ColoredString> OutputLabel::textForEmulatedPushButton() const
652 {
653   std::vector<ColoredString> ret;
654   if(!isQOfInt())
655     {
656       ret.push_back(QString("Make"));
657       ColoredString elt(QString("%1").arg(_outp->getName().c_str()));
658       elt.setColor(Qt::red);
659       ret.push_back(elt);
660     }
661   else
662     {
663       ret.push_back(QString("No more"));
664       ColoredString elt(QString("%1").arg(_outp->getName().c_str()));
665       elt.setColor(Qt::red);
666       ret.push_back(elt);
667       ret.push_back(QString("as"));
668     }
669   ret.push_back(QString("quantity"));
670   ret.push_back(QString("of"));
671   ret.push_back(QString("interest"));
672   return ret;
673 }
674
675 QSize OutputLabel::minimumSizeHint() const
676 {
677   return sizeHint();
678 }
679
680 void OutputLabel::ComputePointsToCircle(const QString& txt, const QRect& refRect, const QFont& font, QPointF pts[8])
681 {
682   QFontMetrics fm(font);
683   QSize rect2(fm.boundingRect(txt).size());
684   QPointF refPt(refRect.width()/2,refRect.height()/2+fm.descent());
685   for(int i=0;i<7;i++)
686     pts[i]=refPt;
687   qreal& p0x(pts[0].rx()),&p0y(pts[0].ry()),&p1x(pts[1].rx()),&p1y(pts[1].ry()),&p2x(pts[2].rx()),&p2y(pts[2].ry()),&p3x(pts[3].rx()),&p3y(pts[3].ry());
688   p0x+=rect2.width()/2.; p0y-=rect2.height();
689   p1x+=rect2.width(); p1y-=1.2*rect2.height()/2.;
690   p2x+=rect2.width(); p2y+=1.2*rect2.height();
691   p3y+=1.2*rect2.height();
692   qreal &p4x(pts[4].rx()),&p4y(pts[4].ry()),&p5x(pts[5].rx()),&p5y(pts[5].ry()),&p6x(pts[6].rx()),&p6y(pts[6].ry());
693   p4x-=1.1*rect2.width(); p4y+=1.2*rect2.height();
694   p5x-=rect2.width(); p5y-=1.3*rect2.height()/2.;
695   p6x+=rect2.width()/2.; p6y-=1.4*rect2.height();
696 }
697
698 /////////////
699
700 void YDFXGUIOKCls::initOK()
701 {
702   _isOK=isOK();
703 }
704
705 //////////////////
706
707 void YDFXGUIGatherPorts::somebodyChangedStatus()
708 {
709   bool newStatus(isOK());
710   if(newStatus!=wasOK())
711     {
712       updateGeometry();
713       update();
714       setWasOKStatus(newStatus);
715     }
716   emit theGlobalStatusChanged(newStatus);// emit signal always because of input ports and sequences definitions.
717 }
718
719 //////////////////
720
721 YDFXGUIInputPortsSelector::YDFXGUIInputPortsSelector(YACSEvalYFXWrap *efx, QWidget *parent):YDFXGUIGatherPorts(parent),_timerId(-1)
722 {
723   _inps=efx->getFreeInputPorts();
724   fillWidget();
725   initOK();
726 }
727
728 bool YDFXGUIInputPortsSelector::isOK() const
729 {
730   const QObjectList &children(this->children());
731   int nbOfRandom(0);
732   foreach(QObject *child,children)
733     {
734       YDFXGUIInputPortValueEditor *childc(qobject_cast<YDFXGUIInputPortValueEditor *>(child));
735       if(childc)
736         {
737           if(!childc->isOK())
738             return false;
739           if(childc->isRandom())
740             nbOfRandom++;
741         }
742     }
743   return nbOfRandom>=1;
744 }
745
746 bool YDFXGUIInputPortsSelector::areSeqWellDefined() const
747 {
748   const QObjectList &children(this->children());
749   int nbOfRandom(0),refSz(std::numeric_limits<int>::max());
750   foreach(QObject *child,children)
751     {
752       YDFXGUIInputPortValueEditor *childc(qobject_cast<YDFXGUIInputPortValueEditor *>(child));
753       if(!childc)
754         continue;
755       if(!childc->isOK())
756         return false;
757       if(!childc->isRandom())
758         continue;
759       YACSEvalInputPort *port(childc->getPort());
760       YACSEvalSeqAny *seq(port->getSequenceOfValuesToEval());
761       if(!seq)
762         return false;
763       if(nbOfRandom==0)
764         refSz=seq->size();
765       if(refSz!=seq->size())
766         return false;
767       nbOfRandom++;
768     }
769   return nbOfRandom>=1;
770 }
771
772 void YDFXGUIInputPortsSelector::fillWidget()
773 {
774   QVBoxLayout *mainLayout(new QVBoxLayout);
775   for(std::vector< YACSEvalInputPort * >::const_iterator it=_inps.begin();it!=_inps.end();it++)
776     {
777       QHBoxLayout *lineLayout(new QHBoxLayout);
778       YDFXGUIInputPortValueEditor *elt1(new YDFXGUIInputPortValueEditor(*it));
779       QLabel *elt0(0);
780       if((*it)->getTypeOfData()==YACSEvalAnyDouble::TYPE_REPR)
781         {
782           InputLabel *elt0c(new InputLabel(*it,this));
783           elt0=elt0c;
784           connect(elt0c,SIGNAL(randomnessStatusChanged()),elt1,SLOT(toggleRandom()));
785         }
786       else
787         elt0=new InputLabelNonToggle(elt1,this);
788       lineLayout->addWidget(elt0);
789       connect(elt1,SIGNAL(statusChanged()),this,SLOT(somebodyChangedStatus()));
790       lineLayout->addWidget(elt1);
791       mainLayout->addLayout(lineLayout);
792     }
793   this->setLayout(mainLayout);
794 }
795
796 YDFXGUIInputPortsSelector::~YDFXGUIInputPortsSelector()
797 {
798   if(_timerId!=-1)
799     killTimer(_timerId);
800 }
801
802 void YDFXGUIInputPortsSelector::showEvent(QShowEvent *e)
803 {
804   _timerId=startTimer(100);
805 }
806
807 void YDFXGUIInputPortsSelector::timerEvent(QTimerEvent *e)
808 {
809   if(e->timerId()==_timerId)
810     {
811       const QObjectList &children(this->children());
812       foreach(QObject *child,children)
813         {
814           YDFXGUIInputPortValueEditor *childc(qobject_cast<YDFXGUIInputPortValueEditor *>(child));
815           if(childc)
816             {
817               emit childc->changeLook();
818             }
819         }
820     }
821 }
822
823 void YDFXGUIInputPortsSelector::DrawWarningSign(QPainter& painter, int width0, int height0)
824 {
825   const int SZP(12);
826   static const int WARN_Y=176,WARN_X=200;
827   const float RATIO(float(WARN_X)/float(WARN_Y));
828   //QPen(QColor(255,203,189)
829   if(float(width0)>RATIO*float(height0))
830     painter.setViewport(int(width0-RATIO*float(height0))/2,0,height0*RATIO,height0);
831   else
832     painter.setViewport(0,(float(height0)-width0/RATIO)/2,width0,width0/RATIO);//width-height/RATIO
833   painter.setRenderHint(QPainter::Antialiasing,true);
834   painter.setWindow(0,0,WARN_X,WARN_Y);
835   //
836   painter.setPen(QPen(QColor(255,203,189),SZP,Qt::SolidLine,Qt::RoundCap));
837   painter.drawLine(QPoint(100,13),QPoint(11,164));
838   painter.drawLine(QPoint(11,164),QPoint(185,164));
839   painter.drawLine(QPoint(185,164),QPoint(100,13));
840   QColor lightBlack(200,200,200);
841   painter.setBrush(QBrush(lightBlack));
842   painter.setPen(QPen(lightBlack,2,Qt::SolidLine,Qt::RoundCap));
843   painter.drawEllipse(87,47,24,24);
844   painter.drawEllipse(93,105,12,12);
845   painter.drawEllipse(90,129,18,18);
846   const QPoint points[4]={QPoint(87,59),QPoint(93,111),QPoint(105,111),QPoint(111,59)};
847   painter.drawPolygon(points,4);
848 }
849
850 void YDFXGUIInputPortsSelector::paintEvent(QPaintEvent *e)
851 {
852   QPainter painter(this);
853   const int SZP(12);
854   int width0(width()),height0(height());
855   //
856   QRect refRect(0,0,width0,height0);
857   painter.eraseRect(refRect);
858   if(!isOK())
859     DrawWarningSign(painter,width0,height0);
860 }
861
862 /////////////
863
864 YDFXGUIOutputPortsSelector::YDFXGUIOutputPortsSelector(YACSEvalYFXWrap *efx, QWidget *parent):YDFXGUIGatherPorts(parent)
865 {
866   _outps=efx->getFreeOutputPorts();
867   fillWidget();
868   initOK();
869 }
870
871 void YDFXGUIOutputPortsSelector::fillWidget()
872 {
873   QVBoxLayout *mainLayout(new QVBoxLayout);
874   for(std::vector< YACSEvalOutputPort * >::const_iterator it=_outps.begin();it!=_outps.end();it++)
875     {
876       if((*it)->getTypeOfData()==YACSEvalAnyDouble::TYPE_REPR)
877         {
878           OutputLabel *elt1(new OutputLabel(*it,this));
879           mainLayout->addWidget(elt1);
880           connect(elt1,SIGNAL(clicked()),this,SLOT(somebodyChangedStatus()));
881         }
882     }
883   this->setLayout(mainLayout);
884 }
885
886 void YDFXGUIOutputPortsSelector::paintEvent(QPaintEvent *e)
887 {
888   if(isOK())
889     {
890       QWidget::paintEvent(e);
891       return ;
892     }
893   QPainter painter(this);
894   YDFXGUIInputPortsSelector::DrawWarningSign(painter,width(),height());
895 }
896
897 bool YDFXGUIOutputPortsSelector::isOK() const
898 {
899   int nbOfOutputsQOI(0);
900   foreach(QObject *child,children())
901     {
902       OutputLabel *childc(qobject_cast<OutputLabel *>(child));
903       if(!childc)
904         continue;
905       if(childc->isQOfInt())
906         nbOfOutputsQOI++;
907     }
908   return nbOfOutputsQOI>=1;
909 }
910
911 /////////////
912
913 QScrollArea *YDFXGUIAbstractPorts::setupWidgets(const QString& title, QWidget *zeWidget)
914 {
915   QHBoxLayout *mainLayout(new QHBoxLayout(this));
916   QGroupBox *gb(new QGroupBox(title,this));
917   QVBoxLayout *vbox(new QVBoxLayout);
918   QVBoxLayout *vbox2(new QVBoxLayout);
919   QFrame *frame(new QFrame(this));
920   frame->setFrameStyle(QFrame::Panel | QFrame::Sunken);
921   vbox->addWidget(frame);
922   gb->setLayout(vbox);
923   QScrollArea *sa(new QScrollArea(this));
924   sa->setWidgetResizable(true);
925   sa->setWidget(zeWidget);
926   vbox2->addWidget(sa);
927   frame->setLayout(vbox2);
928   mainLayout->addWidget(gb);
929   this->setLayout(mainLayout);
930   return sa;
931 }
932
933 /////////////
934
935 YDFXGUIInputPorts::YDFXGUIInputPorts(YACSEvalYFXWrap *efx, QWidget *parent):YDFXGUIAbstractPorts(efx,parent),_inputsSelector(new YDFXGUIInputPortsSelector(efx,this))
936 {
937   QScrollArea *sa(setupWidgets("Inputs",_inputsSelector));
938   connect(efx,SIGNAL(lockSignal(bool)),_inputsSelector,SLOT(setDisabled(bool)));
939   sa->setMinimumWidth(320);
940   sa->setMinimumHeight(360);
941 }
942
943 /////////////
944
945 YDFXGUIOutputPorts::YDFXGUIOutputPorts(YACSEvalYFXWrap *efx, QWidget *parent):YDFXGUIAbstractPorts(efx,parent),_outputsSelector(new YDFXGUIOutputPortsSelector(efx,this))
946 {
947   QScrollArea *sa(setupWidgets("Outputs",_outputsSelector));
948   connect(efx,SIGNAL(lockSignal(bool)),_outputsSelector,SLOT(setDisabled(bool)));
949   sa->setMinimumWidth(100);
950 }
951 /////////////
952
953 YDFXGUIAllPorts::YDFXGUIAllPorts(YACSEvalYFXWrap *efx, QWidget *parent):QWidget(parent),_in(new YDFXGUIInputPorts(efx,this)),_out(new YDFXGUIOutputPorts(efx,this))
954 {
955   QVBoxLayout *mainLayout(new QVBoxLayout(this));
956   QSplitter *sp(new QSplitter(Qt::Horizontal,this));
957   sp->addWidget(_in); sp->setStretchFactor(0,3);
958   sp->addWidget(_out); sp->setStretchFactor(1,1);
959   mainLayout->addWidget(sp);
960   connect(_in->getPortsManager(),SIGNAL(theGlobalStatusChanged(bool)),this,SLOT(somethingChangedInPorts(bool)));
961   connect(_out->getPortsManager(),SIGNAL(theGlobalStatusChanged(bool)),this,SLOT(somethingChangedInPorts(bool)));
962 }
963
964 bool YDFXGUIAllPorts::isOK() const
965 {
966   return _in->getPortsManager()->isOK() && _out->getPortsManager()->isOK();
967 }
968
969 void YDFXGUIAllPorts::somethingChangedInPorts(bool status)
970 {
971   bool step1(_in->isOK() && _out->isOK());
972   if(!step1)
973     {
974       emit sequencesCanBeDefinedSignal(false);
975       emit canBeExecutedSignal(false);
976       return ;
977     }
978   emit sequencesCanBeDefinedSignal(true);
979   emit canBeExecutedSignal(_in->areSeqWellDefined());
980 }