1 // Copyright (C) 2016-2022 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Author : Anthony Geay (EDF R&D)
22 #include "YDFXGUISeqInit.hxx"
29 #include <QPushButton>
30 #include <QScrollArea>
31 #include <QHBoxLayout>
32 #include <QFileDialog>
33 #include <QApplication>
36 #include "PythonCppUtils.hxx"
38 #include "YDFXGUIWrap.hxx"
39 #include "YDFXGUIPyThreadSaver.hxx"
41 #include "YACSEvalPort.hxx"
42 #include "YACSEvalSeqAny.hxx"
47 const char YDFXGUIStatus::OK_STR[]="OK !";
49 ////////////////////////////
51 void YDFXGUIDoubleVectHolder::applyOnInput(YACSEvalInputPort *inp) const
53 YACSEvalSeqAny *val(new YACSEvalSeqAnyDouble(_vect));
54 inp->setSequenceOfValuesToEval(val);
58 ////////////////////////////
60 YDFXGUISeqSetterP::YDFXGUISeqSetterP(QWidget *parent):QPushButton(parent),_isIn(false)
63 connect(this,SIGNAL(clicked()),this,SLOT(selectAFile()));
66 void YDFXGUISeqSetterP::loadState(const QString& state)
69 setToolTip(_fileName);
72 QString YDFXGUISeqSetterP::saveState() const
77 bool YDFXGUISeqSetterP::executeScript(int& sz)
79 QObject *zeBoss(parent()->parent());
80 YDFXGUISeqLine *zeBossc(qobject_cast<YDFXGUISeqLine *>(zeBoss));
84 if(_fileName.isEmpty())
86 Q_EMIT problemDetected(QString("For \"%1\" : no file defined !").arg(zeBossc->getName()));
89 QFile file(_fileName);
90 if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
96 QByteArray line(file.readLine());
97 QString line2(line.data());
99 double v(line2.toDouble(&isOK));
102 Q_EMIT problemDetected(QString("For \"%1\" : At line %2 it is not a float !").arg(zeBossc->getName()).arg(i));
112 void YDFXGUISeqSetterP::enterEvent(QEvent *event)
118 void YDFXGUISeqSetterP::leaveEvent(QEvent *event)
124 void YDFXGUISeqSetterP::paintEvent(QPaintEvent *event)
126 if(_isIn || _fileName.isEmpty())
128 QPushButton::paintEvent(event);
131 QFileInfo fi(_fileName);
132 QString txt(fi.fileName());
133 QRect refRect(rect());
136 QSize refRect2(fm.boundingRect(txt).size());
138 QPainter painter(this);
139 painter.drawText(QPoint((refRect.width()-refRect2.width())/2,
140 refRect.height()/2+refRect2.height()/2-fm.descent()),txt);
143 void YDFXGUISeqSetterP::selectAFile()
145 QFileDialog fd(this,QString("Select a file containing list of floats."));
146 fd.setFileMode(QFileDialog::ExistingFile);
149 QStringList files(fd.selectedFiles());
154 setToolTip(_fileName);
159 ////////////////////////////
161 void YDFXGUISeqSetterT::loadState(const QString& state)
166 QString YDFXGUISeqSetterT::saveState() const
168 return toPlainText();
171 bool YDFXGUISeqSetterT::executeScript(int& sz)
173 QObject *zeBoss(parent()->parent());
174 YDFXGUISeqLine *zeBossc(qobject_cast<YDFXGUISeqLine *>(zeBoss));
178 std::string name(zeBossc->getName().toStdString());
180 static const char TMP_FILENAME[]="/tmp/TMP";
181 std::string txt(toPlainText().toStdString());
182 YDFXGUIPyThreadSaver::SaveContext(QApplication::instance()->thread());
185 AutoPyRef code(Py_CompileString(txt.c_str(),TMP_FILENAME, Py_file_input));
186 if(code.get() == NULL)
188 Q_EMIT problemDetected(QString("For \"%1\" : python code is invalid !").arg(zeBossc->getName()));
191 AutoPyRef context(PyDict_New());
192 PyDict_SetItemString( context, "__builtins__", PyEval_GetBuiltins() );
193 AutoPyRef res(PyEval_EvalCode(code.get(), context, context));
194 PyObject *item(PyDict_GetItemString(context,name.c_str()));
198 Q_EMIT problemDetected(QString("For \"%1\" : Py var %1 is not defined !").arg(zeBossc->getName()));
201 if(!PyList_Check(item))
203 Q_EMIT problemDetected(QString("For \"%1\" : Py var %1 must be a list !").arg(zeBossc->getName()));
206 sz=PyList_Size(item);
207 _vect.clear() ; _vect.resize(sz);
208 for(int i=0;i<sz;i++)
210 PyObject *val(PyList_GetItem(item,i));
211 if(!PyFloat_Check(val))
213 Q_EMIT problemDetected(QString("For \"%1\" : At pos %2 of python list, it is not a float !").arg(zeBossc->getName()).arg(i));
216 _vect[i]=PyFloat_AS_DOUBLE(val);
222 ////////////////////////////
224 YDFXGUICombo::YDFXGUICombo(QWidget *parent):QComboBox(parent),_isIn(false)
226 setFocusPolicy(Qt::TabFocus);
229 QString YDFXGUICombo::getName()
232 YDFXGUISeqLine *parentc(qobject_cast<YDFXGUISeqLine *>(parent()));
234 ret=parentc->getName();
238 void YDFXGUICombo::enterEvent(QEvent *event)
244 void YDFXGUICombo::leaveEvent(QEvent *event)
250 void YDFXGUICombo::paintEvent(QPaintEvent *event)
254 QComboBox::paintEvent(event);
257 QRect refRect(rect());
261 QSize refRect2(fm.boundingRect(getName()).size());
262 QPainter painter(this);
264 QPen pen(painter.pen());
265 pen.setColor(Qt::red);
267 painter.drawText(QPoint((refRect.width()-refRect2.width())/2,refRect.height()/2+refRect2.height()/2-fm.descent()),getName());
270 ////////////////////////////
272 YDFXGUISeqSetter::YDFXGUISeqSetter(QWidget *parent, const QString& name):QWidget(parent),_textEdit(0),_push(0),_curType(0)
274 QVBoxLayout *verticalLayout(new QVBoxLayout(this));
275 _textEdit=new YDFXGUISeqSetterT(this); verticalLayout->addWidget(_textEdit);
276 _push=new YDFXGUISeqSetterP(this); verticalLayout->addWidget(_push);
277 _textEdit->setText(QString("import math\n%1=[math.sqrt(float(elt)+0.) for elt in range(4)]").arg(name));
282 int YDFXGUISeqSetter::loadState(const QString& state)
284 if(state.isEmpty() || state.size()<3)
286 QString sw(state.mid(0,3));
289 _push->loadState(state.mid(3));
295 _textEdit->loadState(state.mid(3));
301 QString YDFXGUISeqSetter::saveState() const
303 YDFXGUISeqLine *parentc(qobject_cast<YDFXGUISeqLine *>(parent()));
306 int pos(parentc->getPositionOfCombo());
310 ret+=_push->saveState();
316 ret+=_textEdit->saveState();
322 QSize YDFXGUISeqSetter::sizeHint() const
324 QSize sz,sz2(QWidget::sizeHint());
326 sz=_push->sizeHint();
328 sz=_textEdit->sizeHint();
329 sz.rwidth()+=sz2.rwidth();
330 sz.rheight()+=sz2.rheight();
334 QSize YDFXGUISeqSetter::minimumSizeHint() const
336 QSize sz,sz2(QWidget::minimumSizeHint());
338 sz=_push->minimumSizeHint();
340 sz=_textEdit->minimumSizeHint();
341 sz.rwidth()+=sz2.rwidth();
342 sz.rheight()+=sz2.rheight();
346 bool YDFXGUISeqSetter::checkOK(int& sz)
349 return _push->executeScript(sz);
351 return _textEdit->executeScript(sz);
354 void YDFXGUISeqSetter::applyOnInput(YACSEvalInputPort *inp)
357 _push->applyOnInput(inp);
359 _textEdit->applyOnInput(inp);
362 void YDFXGUISeqSetter::typeOfAssignmentChanged(int newType)
369 disconnect(_textEdit,SIGNAL(problemDetected(const QString&)),this,SIGNAL(problemDetected(const QString&)));
370 connect(_push,SIGNAL(problemDetected(const QString&)),this,SIGNAL(problemDetected(const QString&)));
376 disconnect(_push,SIGNAL(problemDetected(const QString&)),this,SIGNAL(problemDetected(const QString&)));
377 connect(_textEdit,SIGNAL(problemDetected(const QString&)),this,SIGNAL(problemDetected(const QString&)));
381 ////////////////////////////
383 YDFXGUISeqLine::YDFXGUISeqLine(QWidget *parent, YACSEvalInputPort *inp):_combo(0),_setter(0),_inp(inp)
385 QHBoxLayout *horizontalLayout(new QHBoxLayout(this));
386 _combo=new YDFXGUICombo(this);
387 _combo->insertItem(0,QString("%1 from file").arg(getName()));
388 _combo->insertItem(1,QString("%1 from PyScript").arg(getName()));
389 horizontalLayout->addWidget(_combo);
390 _setter=new YDFXGUISeqSetter(this,getName());
391 connect(_combo,SIGNAL(currentIndexChanged(int)),this,SLOT(typeOfAssignmentChanged(int)));
392 horizontalLayout->addWidget(_setter);
393 _combo->setCurrentIndex(0);
394 Q_EMIT _combo->currentIndexChanged(0);//to be sure to sync widgets
397 void YDFXGUISeqLine::loadState(const QMap<QString,QString>& state)
399 QString name(getName());
400 QMap<QString,QString>::const_iterator it(state.find(name));
403 int pos(_setter->loadState(it.value()));
404 _combo->setCurrentIndex(pos);
407 void YDFXGUISeqLine::saveState(QMap<QString,QString>& state) const
409 state[getName()]=_setter->saveState();
412 QString YDFXGUISeqLine::getName() const
414 return QString(_inp->getName().c_str());
417 int YDFXGUISeqLine::getPositionOfCombo() const
419 return _combo->currentIndex();
422 bool YDFXGUISeqLine::checkOK(int& sz)
424 return _setter->checkOK(sz);
427 void YDFXGUISeqLine::connectToStatus(YDFXGUIStatus *status)
429 connect(_setter,SIGNAL(problemDetected(const QString&)),status,SLOT(displayInfo(const QString&)));
432 void YDFXGUISeqLine::applyOnInput()
434 _setter->applyOnInput(_inp);
437 void YDFXGUISeqLine::typeOfAssignmentChanged(int newType)
439 _setter->typeOfAssignmentChanged(newType);
440 _setter->updateGeometry();
444 ////////////////////////////
446 YDFXGUIStatus::YDFXGUIStatus(QWidget *parent):QWidget(parent)
450 void YDFXGUIStatus::paintEvent(QPaintEvent *event)
452 QRect refRect(rect());
455 QSize refRect2(fm.boundingRect(_text).size());
457 QPainter painter(this);
458 QPen pen(painter.pen());
459 pen.setColor(_text==OK_STR?Qt::green:Qt::red);
461 painter.drawText(QPoint((refRect.width()-refRect2.width())/2,
462 refRect.height()/2+refRect2.height()/2-fm.descent()),_text);
465 QSize YDFXGUIStatus::sizeHint() const
469 QSize ret(fm.boundingRect(_text).size());
473 QSize YDFXGUIStatus::minimumSizeHint() const
478 void YDFXGUIStatus::declareOK(bool isOK)
487 void YDFXGUIStatus::displayInfo(const QString& txt)
494 ////////////////////////////
496 YDFXGUISeqInitEff::YDFXGUISeqInitEff(QWidget *parent, YACSEvalYFXWrap *efx):QWidget(parent)
498 QVBoxLayout *verticalLayout(new QVBoxLayout(this));
499 std::vector< YACSEvalInputPort * > inputs(efx->getFreeInputPorts());
500 foreach(YACSEvalInputPort *input,inputs)
502 if(!input->isRandomVar())
504 YDFXGUISeqLine *line(new YDFXGUISeqLine(this,input));
505 verticalLayout->addWidget(line);
506 _lines.push_back(line);
510 void YDFXGUISeqInitEff::loadState(const QMap<QString,QString>& state)
512 foreach(YDFXGUISeqLine *line,_lines)
513 line->loadState(state);
516 QMap<QString,QString> YDFXGUISeqInitEff::saveState() const
518 QMap<QString,QString> ret;
519 foreach(YDFXGUISeqLine *line,_lines)
520 line->saveState(ret);
524 void YDFXGUISeqInitEff::connectToStatus(YDFXGUIStatus *status)
526 foreach(YDFXGUISeqLine *line,_lines)
528 line->connectToStatus(status);
532 void YDFXGUISeqInitEff::assignButtonClicked()
535 bool verdict(checkConsistency(sz));
536 Q_EMIT configurationIsOK(verdict);
539 void YDFXGUISeqInitEff::applyOnEFX()
541 foreach(YDFXGUISeqLine *line,_lines)
542 line->applyOnInput();
545 bool YDFXGUISeqInitEff::checkConsistency(int& sz)
547 int refSz(std::numeric_limits<int>::max());
548 foreach(YDFXGUISeqLine *line,_lines)
551 if(!line->checkOK(locSz))
553 if(refSz==std::numeric_limits<int>::max())
557 Q_EMIT line->setter()->problemDetected(QString("Var %1 does not have the same number of elts than others !").arg(line->getName()));
565 ////////////////////////////
567 YDFXGUISeqInit::YDFXGUISeqInit(QWidget *parent, YACSEvalYFXWrap *efx):QWidget(parent),_zeWidget(0)
569 QVBoxLayout *verticalLayout(new QVBoxLayout(this));
570 QFrame *frame(new QFrame(this));
571 frame->setFrameStyle(QFrame::Panel | QFrame::Sunken);
572 verticalLayout->addWidget(frame);
573 QHBoxLayout *horizontalLayout2(new QHBoxLayout(frame));
574 QScrollArea *sa(new QScrollArea(frame));
575 horizontalLayout2->addWidget(sa);
576 _zeWidget=new YDFXGUISeqInitEff(sa,efx);
577 sa->setWidgetResizable(true);
578 sa->setWidget(_zeWidget);
580 QHBoxLayout *horizontalLayout(new QHBoxLayout);
581 QSpacerItem *si(new QSpacerItem(40,20,QSizePolicy::Expanding,QSizePolicy::Minimum));
582 YDFXGUIStatus *statusInfo(new YDFXGUIStatus(this));
583 _zeWidget->connectToStatus(statusInfo);
584 connect(_zeWidget,SIGNAL(configurationIsOK(bool)),statusInfo,SLOT(declareOK(bool)));
585 QPushButton *button(new QPushButton(this));
586 button->setText("Check");
587 QPushButton *button2(new QPushButton(this));
588 button2->setText("Assign !");
589 connect(_zeWidget,SIGNAL(configurationIsOK(bool)),button2,SLOT(setEnabled(bool)));
590 connect(button2,SIGNAL(clicked(bool)),_zeWidget,SLOT(applyOnEFX()));
591 connect(button2,SIGNAL(clicked(bool)),this,SIGNAL(assignButtonClicked()));
592 horizontalLayout->addWidget(statusInfo);
593 horizontalLayout->addItem(si);
594 horizontalLayout->addWidget(button);
595 horizontalLayout->addWidget(button2);
596 connect(button,SIGNAL(pressed()),_zeWidget,SLOT(assignButtonClicked()));
597 button2->setEnabled(false);
599 verticalLayout->addLayout(horizontalLayout);
602 void YDFXGUISeqInit::loadState(const QMap<QString,QString>& state)
604 _zeWidget->loadState(state);
607 QMap<QString,QString> YDFXGUISeqInit::saveState() const
609 return _zeWidget->saveState();