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