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