Salome HOME
93391f8f4e1d4c20b3cdae32e70b6925f1ef616a
[modules/yacs.git] / src / ydfx_gui / YDFXGUIHostParametrizer.cxx
1 // Copyright (C) 2016-2023  CEA, EDF
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 "YDFXGUIHostParametrizer.hxx"
22
23 #include "YDFXGUIWrap.hxx"
24
25 #include "YACSEvalResource.hxx"
26
27 #include <QDialogButtonBox>
28 #include <QVBoxLayout>
29 #include <QHBoxLayout>
30 #include <QPushButton>
31 #include <QSettings>
32 #include <QComboBox>
33 #include <QGroupBox>
34 #include <QLineEdit>
35 #include <QLabel>
36
37 #include <iostream>
38
39 const char YDFXGUIHostParametrizer::MACHINE[]="machine/machine";
40
41 const char YDFXGUIBatchInfo::NBPROCS[]="machine/nbprocs";
42
43 const char YDFXGUIBatchInfo::REMOTEDIR[]="machine/remotedir";
44
45 const char YDFXGUIBatchInfo::LOCALDIR[]="machine/localdir";
46
47 const char YDFXGUIBatchInfo::WCKEY[]="machine/wckey";
48
49 const char YDFXGUIBatchInfo::MAXDUR[]="machine/maxdur";
50
51 YDFXGUIHostParametrizer::YDFXGUIHostParametrizer(QWidget *parent, YACSEvalYFXWrap *efx):QWidget(parent),_hostSelector(0),_clusterAdvInfo(0),_buttonBox(0),_efx(efx),_wasInteractive(true)
52 {
53   _efx->lockPortsForEvaluation();
54   YACSEvalListOfResources *res(_efx->giveResources());
55   std::vector<std::string> machines(res->getAllFittingMachines());
56   /////////////
57   QSizePolicy sizePolicy1(QSizePolicy::Minimum, QSizePolicy::Maximum);
58   sizePolicy1.setHorizontalStretch(0);
59   sizePolicy1.setVerticalStretch(0);
60   sizePolicy1.setHeightForWidth(sizePolicy().hasHeightForWidth());
61   QVBoxLayout *verticalLayout_3(new QVBoxLayout(this));
62   QHBoxLayout *horizontalLayout_2(new QHBoxLayout);
63   QLabel *label(new QLabel(this));
64   QSizePolicy sizePolicy2(QSizePolicy::Preferred, QSizePolicy::Maximum);
65   sizePolicy2.setHorizontalStretch(0);
66   sizePolicy2.setVerticalStretch(0);
67   sizePolicy2.setHeightForWidth(label->sizePolicy().hasHeightForWidth());
68   label->setText("Select machine");
69   horizontalLayout_2->addWidget(label);
70   _hostSelector=new QComboBox(this);
71   int i(0);
72   foreach(std::string mach,machines)
73     _hostSelector->insertItem(i++,mach.c_str());
74   connect(_hostSelector,SIGNAL(currentIndexChanged(const QString &)),this,SLOT(changeMachine(const QString &)));
75   sizePolicy2.setHeightForWidth(_hostSelector->sizePolicy().hasHeightForWidth());
76   horizontalLayout_2->addWidget(_hostSelector);
77   verticalLayout_3->addLayout(horizontalLayout_2,1);
78   //
79   _clusterAdvInfo=new YDFXGUIBatchInfo(this,_efx);
80   verticalLayout_3->addWidget(_clusterAdvInfo,1);
81   connect(_clusterAdvInfo,SIGNAL(statusOfEntryChanged(bool)),this,SLOT(clusterAdvParamStatusChanged(bool)));
82   //
83   QHBoxLayout *horizontalLayout_3(new QHBoxLayout);
84   _buttonBox=new QDialogButtonBox(this);
85   _buttonBox->setOrientation(Qt::Horizontal);
86   _buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
87   horizontalLayout_3->addWidget(_buttonBox,0);
88   verticalLayout_3->addLayout(horizontalLayout_3,0);
89   //
90   _hostSelector->setCurrentIndex(0);
91   {
92     YACSEvalListOfResources *res(_efx->giveResources());
93     _wasInteractive=res->isMachineInteractive(machines[0]);
94   }
95   this->changeMachine(QString(machines[0].c_str()));
96 }
97
98 void YDFXGUIHostParametrizer::loadFromSettings(const QSettings& settings)
99 {
100   if(!settings.contains(MACHINE))
101     return ;
102   QVariant v(settings.value(MACHINE));
103   QString vs(v.toString());
104   if(vs.isEmpty())
105     return ;
106   int id(_hostSelector->findText(vs));
107   if(id==-1)
108     return ;
109   _hostSelector->setCurrentIndex(id);
110   YACSEvalListOfResources *res(_efx->giveResources());
111   if(!res->isMachineInteractive(vs.toStdString()))
112     _clusterAdvInfo->loadFromSettings(settings);
113 }
114
115 void YDFXGUIHostParametrizer::learnSettings(QSettings& settings) const
116 {
117   settings.setValue(MACHINE,_hostSelector->currentText());
118   YACSEvalListOfResources *res(_efx->giveResources());
119   std::string selectedRes(_hostSelector->currentText().toStdString());
120   if(!res->isMachineInteractive(selectedRes))//res->isInteractive() does not work here if efx has no Resource (no containers !)
121     _clusterAdvInfo->learnSettings(settings);
122 }
123
124 void YDFXGUIHostParametrizer::applyToEFX()
125 {
126   YACSEvalListOfResources *res(_efx->giveResources());
127   std::string selectedRes(_hostSelector->currentText().toStdString());
128   res->setWantedMachine(selectedRes);
129   if(!res->isMachineInteractive(selectedRes))//res->isInteractive() does not work here if efx has no Resource (no containers !)
130     {
131       YACSEvalParamsForCluster& ps(res->getAddParamsForCluster());
132       _clusterAdvInfo->applyToParams(ps);
133     }
134   Q_EMIT readyForRunSignal(true);
135 }
136
137 QString YDFXGUIHostParametrizer::getNameOfHost()
138 {
139   return _hostSelector->currentText();
140 }
141
142 void YDFXGUIHostParametrizer::changeMachine(const QString& newMachineSelected)
143 {
144   YACSEvalListOfResources *res(_efx->giveResources());
145   bool isInterac(res->isMachineInteractive(newMachineSelected.toStdString()));
146   _clusterAdvInfo->setVisible(!isInterac);
147   QPushButton *ok(_buttonBox->button(QDialogButtonBox::Ok));
148   ok->setDisabled(!isInterac && !_clusterAdvInfo->isOK());
149   if(_wasInteractive!=isInterac)
150     {
151       Q_EMIT interactivityChanged(isInterac);
152       _wasInteractive=isInterac;
153     }
154 }
155
156 void YDFXGUIHostParametrizer::clusterAdvParamStatusChanged(bool newStatus)
157 {
158   QPushButton *ok(_buttonBox->button(QDialogButtonBox::Ok));
159   ok->setDisabled(!newStatus);
160 }
161
162 QValidator::State YDFXGUIDurationValidator::validate(QString &input, int &) const
163 {
164   QString input2(input.simplified());
165   input2.replace(' ',QString());
166   QStringList sp(input2.split(QChar(':')));
167   if(sp.size()>3)
168     return QValidator::Invalid;
169   QRegExp rx("\\d{1,2}");
170   if(sp.size()==1)
171     {
172       if(input2.isEmpty())
173         return QValidator::Intermediate;
174       if(!rx.exactMatch(input2))
175         return QValidator::Invalid;
176       return QValidator::Intermediate;
177     }
178   if(sp.size()==2 && sp[1].isEmpty())
179     {
180       if(sp[0].isEmpty())
181         return QValidator::Invalid;
182       return QValidator::Intermediate;
183     }
184   if(sp.size()==2)
185     sp.insert(0,QString("00"));
186   if(sp[2].isEmpty())
187     return QValidator::Intermediate;
188   int hms(0);
189   foreach(QString elt,sp)
190     {
191       if(!rx.exactMatch(elt))
192         return QValidator::Invalid;
193       bool isOK(false);
194       uint val(elt.toUInt(&isOK));
195       if(!isOK)
196         return QValidator::Invalid;
197       if(hms>1)
198         if(val>=60)
199           return QValidator::Invalid;
200       hms++;
201     }
202   return QValidator::Acceptable;
203 }
204  
205 YDFXGUIBatchInfo::YDFXGUIBatchInfo(QWidget *parent, YACSEvalYFXWrap *efx):QWidget(parent),_efx(efx),_nbProcs(0),_remoteDir(0),_localDir(0),_WCKey(0),_maxDuration(0),_wasOK(false)
206 {
207   QVBoxLayout *verticalLayout(new QVBoxLayout(this));
208   QGroupBox *gb(new QGroupBox(this));
209   gb->setTitle("Specific info for cluster");
210   verticalLayout->addWidget(gb);
211   QVBoxLayout *verticalLayout_1(new QVBoxLayout(gb));
212   QFrame *frame(new QFrame(gb));
213   verticalLayout_1->addWidget(frame);
214   frame->setFrameStyle(QFrame::Panel | QFrame::Sunken);
215   frame->setFrameShadow(QFrame::Raised);
216   QVBoxLayout *verticalLayout_2(new QVBoxLayout(frame));
217   QSpacerItem *verticalSpacer(new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding));
218   verticalLayout_2->addItem(verticalSpacer);
219   QHBoxLayout *horizontalLayout_3(0);
220   //
221   horizontalLayout_3=new QHBoxLayout;
222   QLabel *label_5(new QLabel(frame));
223   label_5->setText("Number of processes");
224   horizontalLayout_3->addWidget(label_5);
225   _nbProcs=new QLineEdit(frame);
226   QValidator *nbProcVal(new QIntValidator(1,10000,_nbProcs));
227   _nbProcs->setValidator(nbProcVal);
228   horizontalLayout_3->addWidget(_nbProcs);
229   verticalLayout_2->addLayout(horizontalLayout_3);
230   verticalSpacer=new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
231   verticalLayout_2->addItem(verticalSpacer);
232   connect(_nbProcs,SIGNAL(textChanged(const QString&)),this,SLOT(somethingChanged()));
233   //
234   horizontalLayout_3=new QHBoxLayout;
235   QLabel *label_2(new QLabel(frame));
236   label_2->setText("Remote dir");
237   horizontalLayout_3->addWidget(label_2);
238   _remoteDir=new QLineEdit(frame);
239   horizontalLayout_3->addWidget(_remoteDir);
240   verticalLayout_2->addLayout(horizontalLayout_3);
241   connect(_remoteDir,SIGNAL(textChanged(const QString&)),this,SLOT(somethingChanged()));
242   //
243   verticalSpacer=new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
244   verticalLayout_2->addItem(verticalSpacer);
245   //
246   horizontalLayout_3=new QHBoxLayout;
247   QLabel *label_3(new QLabel(frame));
248   label_3->setText("Local dir");
249   horizontalLayout_3->addWidget(label_3);
250   _localDir=new QLineEdit(frame);
251   horizontalLayout_3->addWidget(_localDir);
252   connect(_localDir,SIGNAL(textChanged(const QString&)),this,SLOT(somethingChanged()));
253   verticalLayout_2->addLayout(horizontalLayout_3);
254   verticalSpacer=new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
255   verticalLayout_2->addItem(verticalSpacer);
256   //
257   horizontalLayout_3=new QHBoxLayout;
258   QLabel *label_4(new QLabel(frame));
259   label_4->setText("Working Caracterization Key");
260   horizontalLayout_3->addWidget(label_4);
261   _WCKey=new QLineEdit(frame);
262   connect(_WCKey,SIGNAL(textChanged(const QString&)),this,SLOT(somethingChanged()));
263   horizontalLayout_3->addWidget(_WCKey);
264   verticalLayout_2->addLayout(horizontalLayout_3);
265   verticalSpacer=new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
266   verticalLayout_2->addItem(verticalSpacer);
267   //
268   horizontalLayout_3=new QHBoxLayout;
269   QLabel *label_6(new QLabel(frame));
270   label_6->setText("Max duration");
271   horizontalLayout_3->addWidget(label_6);
272   _maxDuration=new QLineEdit(frame);
273   QValidator *maxDurVal(new YDFXGUIDurationValidator(_maxDuration));
274   _maxDuration->setText("05:00");
275   _maxDuration->setValidator(maxDurVal);
276   connect(_maxDuration,SIGNAL(textChanged(const QString&)),this,SLOT(somethingChanged()));
277   horizontalLayout_3->addWidget(_maxDuration);
278   verticalLayout_2->addLayout(horizontalLayout_3);
279   verticalSpacer=new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
280   verticalLayout_2->addItem(verticalSpacer);
281 }
282
283 void YDFXGUIBatchInfo::showEvent(QShowEvent *event)
284 {
285   YDFXGUIHostParametrizer *parentc(qobject_cast<YDFXGUIHostParametrizer *>(parent()));
286   if(parentc)
287     {
288       QPushButton *ok(parentc->getDialogButtonBox()->button(QDialogButtonBox::Ok));
289       ok->setEnabled(isOK());
290     }
291   QWidget::showEvent(event);
292 }
293
294 bool YDFXGUIBatchInfo::isOK() const
295 {
296   bool ret1(!_nbProcs->text().isEmpty() && !_remoteDir->text().isEmpty() && !_localDir->text().isEmpty() && !_WCKey->text().isEmpty());
297   const QValidator *val(_maxDuration->validator());
298   int dummy;
299   QString st(_maxDuration->text());
300   QValidator::State sta(val->validate(st,dummy));
301   return ret1 && sta==QValidator::Acceptable;
302 }
303
304 void YDFXGUIBatchInfo::loadFromSettings(const QSettings& settings)
305 {
306   static const int NB=5;
307   const char *tab1[NB]={NBPROCS,REMOTEDIR,LOCALDIR,WCKEY,MAXDUR};
308   QLineEdit *tab2[NB]={_nbProcs,_remoteDir,_localDir,_WCKey,_maxDuration};
309   QString tab3[NB];
310   YACSEvalParamsForCluster* cp(0);
311   YACSEvalListOfResources *lr(_efx->giveResources());
312   if(lr)
313     {
314       std::vector<std::string> machines(lr->getAllChosenMachines());
315       if(machines.size()==1)
316         {
317           if(machines[0]==getNameOfHost().toStdString())
318             cp=&lr->getAddParamsForCluster();
319         }
320     }
321   if(cp)
322     {
323       tab3[0]=QString("%1").arg(cp->getNbProcs());
324       tab3[1]=cp->getRemoteWorkingDir().c_str();
325       tab3[2]=cp->getLocalWorkingDir().c_str();
326       tab3[3]=cp->getWCKey().c_str();
327       tab3[4]=cp->getMaxDuration().c_str();
328     }
329   for(int i=0;i<NB;i++)
330     {
331       const char *entry(tab1[i]);
332       QLineEdit *le(tab2[i]);
333       if(!tab3[1].isEmpty())
334         {
335           le->setText(tab3[i]);
336           continue;
337         }
338       //
339       if(!settings.contains(entry))
340         continue ;
341       QVariant v(settings.value(entry));
342       QString vs(v.toString());
343       if(vs.isEmpty())
344         return ;
345       le->setText(vs);
346     }
347   bool newOK(isOK());
348   _wasOK=newOK;
349   Q_EMIT statusOfEntryChanged(newOK);
350 }
351
352 void YDFXGUIBatchInfo::learnSettings(QSettings& settings) const
353 {
354   settings.setValue(NBPROCS,_nbProcs->text());
355   settings.setValue(REMOTEDIR,_remoteDir->text());
356   settings.setValue(LOCALDIR,_localDir->text());
357   settings.setValue(WCKEY,_WCKey->text());
358   settings.setValue(MAXDUR,_maxDuration->text());
359 }
360
361 void YDFXGUIBatchInfo::applyToParams(YACSEvalParamsForCluster& ps) const
362 {
363   QString nbProcs(_nbProcs->text());
364   ps.setNbProcs(nbProcs.toUInt());
365   ps.setRemoteWorkingDir(_remoteDir->text().toStdString());
366   ps.setLocalWorkingDir(_localDir->text().toStdString());
367   ps.setWCKey(_WCKey->text().toStdString());
368   ps.setMaxDuration(NormalizeDuration(_maxDuration->text()).toStdString());
369 }
370
371 QString YDFXGUIBatchInfo::getNameOfHost()
372 {
373   YDFXGUIHostParametrizer *parentc(qobject_cast<YDFXGUIHostParametrizer *>(parent()));
374   if(parentc)
375     return parentc->getNameOfHost();
376   else
377     return QString();
378 }
379
380 void YDFXGUIBatchInfo::somethingChanged()
381 {
382   Q_EMIT statusOfEntryChanged(isOK());
383 }
384
385 QString YDFXGUIBatchInfo::NormalizeDuration(const QString& txt)
386 {
387   QString input2(txt.simplified());
388   input2.replace(' ',QString());
389   QStringList sp(txt.split(QChar(':')));
390   QStringList ret;
391   foreach(QString elt,sp)
392     {
393       bool isOK(false);
394       uint val(elt.toUInt(&isOK));
395       if(!isOK)
396         {
397           ret << "00";
398           continue;
399         }
400       ret << QString("%1").arg(val,2,10,QChar('0'));
401     }
402   return ret.join(QChar(':'));
403 }
404