Salome HOME
2fe128e23672d00a9709e2e8ab12547cfdf7a10c
[modules/jobmanager.git] / src / genericgui / BL_CreateJobWizard.cxx
1 // Copyright (C) 2009-2014  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
20 #include "BL_CreateJobWizard.hxx"
21 #include "BL_JobsManager_QT.hxx"
22 #ifndef WNT
23 #include <unistd.h>
24 #include <pwd.h>
25 #endif
26 #include <sys/types.h>
27 #include <stdlib.h>
28 #include <time.h>
29
30 #include <ui_ResourceRequirementsWizardPage.h>
31 #include <ui_FilesWizardPage.h>
32 #include <ui_AdvancedParametersWizardPage.h>
33
34 #ifdef WNT
35 #undef ERROR
36 #endif
37
38 using namespace std;
39 using namespace BL;
40
41 BL::CreateJobWizard::CreateJobWizard(BL::JobsManager_QT * jobs_manager, BL::SALOMEServices * salome_services)
42 {
43   DEBTRACE("Creating BL::CreateJobWizard");
44   BL_ASSERT(jobs_manager);
45   BL_ASSERT(salome_services);
46   _jobs_manager = jobs_manager;
47   _salome_services = salome_services;
48
49   job_name = "";
50   yacs_file = "";
51   command = "";
52   python_salome_file = "";
53   env_file = "";
54   batch_directory = "";
55
56   // For COORM
57   coorm_batch_directory = "";
58
59   maximum_duration = "";
60   mem_limit = 0;
61   mem_req_type = BL::Job::MEM_PER_NODE;
62   nb_proc = 1;
63
64   // Parameters for COORM
65   launcher_file = "";
66   launcher_args = "";
67
68   result_directory = "";
69
70   resource_choosed = "";
71   batch_queue = "";
72
73   start_job = false;
74   dump_yacs_state = -1;
75   ll_jobtype = "";
76
77   setOptions(QWizard::NoBackButtonOnStartPage);
78
79   // Common pages
80   _job_name_page = new BL::JobNamePage(this, _jobs_manager);
81   _batch_parameters_page = new BL::BatchParametersPage(this, salome_services);
82
83   setPage(Page_JobName, _job_name_page);
84   setPage(Page_BatchParameters, _batch_parameters_page);
85
86   // For COORM
87   setPage(Page_COORM_BatchParameters, new BL::COORM_BatchParametersPage(this, salome_services));
88
89   setPage(Page_Files, new BL::FilesPage(this, salome_services));
90   setPage(Page_Resource, new BL::ResourcePage(this, salome_services));
91   setPage(Page_Advanced, new BL::AdvancedParametersPage(this));
92   setPage(Page_Conclusion, new BL::ConclusionPage(this));
93
94   // Specific pages
95   setPage(Page_YACSSchema, new BL::YACSSchemaPage(this));
96   setPage(Page_Command_Main_Definitions, new BL::CommandMainPage(this));
97   setPage(Page_PythonSalome_Main_Definitions, new BL::PythonSalomeMainPage(this));
98
99   setWindowTitle("Create Job Wizard");
100   connect(this, SIGNAL(finished(int)), this, SLOT(end(int)));
101 }
102
103 BL::CreateJobWizard::~CreateJobWizard()
104 {
105   DEBTRACE("Destroying BL::CreateJobWizard");
106 }
107
108 void
109 BL::CreateJobWizard::clone(const std::string & name)
110 {
111   if (_jobs_manager->job_already_exist(name) == true)
112   {
113     BL::Job * job = _jobs_manager->getJob(name);
114
115     // We can only edit a job in CREATED, ERROR, FAILED and NOT_CREATED
116     if (job->getState() == BL::Job::CREATED ||
117         job->getState() == BL::Job::ERROR   ||
118         job->getState() == BL::Job::FAILED  ||
119         job->getState() == BL::Job::NOT_CREATED)
120     { 
121       setField("job_name", QString(name.c_str()));
122       _job_name_page->_check_name = false;
123     }
124
125     if (job->getType() == BL::Job::YACS_SCHEMA)
126     {
127       setField("yacs_file", QString(job->getJobFile().c_str()));
128       _job_name_page->_yacs_schema_button->click();
129       setField("env_yacs_file", QString(job->getEnvFile().c_str()));
130       if (job->getDumpYACSState() != -1)
131       {
132         QString value;
133         value.setNum(job->getDumpYACSState());
134         setField("dump_yacs_state", value);
135       }
136     }
137     else if (job->getType() == BL::Job::COMMAND)
138     {
139       setField("command", QString(job->getJobFile().c_str()));
140       _job_name_page->_command_button->click();
141       setField("env_command_file", QString(job->getEnvFile().c_str()));
142     }
143     else if (job->getType() == BL::Job::PYTHON_SALOME)
144     {
145       setField("PythonSalome", QString(job->getJobFile().c_str()));
146       _job_name_page->_python_salome_button->click();
147       setField("env_PythonSalome_file", QString(job->getEnvFile().c_str()));
148     }
149
150
151         // For COORM
152     BL::Job::BatchParam batch_params = job->getBatchParameters();
153         BL::ResourceDescr resource_descr = _salome_services->getResourceDescr(job->getResource().c_str());
154         std::string batch = resource_descr.batch.c_str();
155         if (batch == "coorm")
156         {
157                 setField("coorm_batch_directory", QString(batch_params.batch_directory.c_str()));
158                 setField("launcher_file", QString(batch_params.launcher_file.c_str()));
159                 setField("launcher_args", QString(batch_params.launcher_args.c_str()));
160         }
161         else
162         {
163                 setField("batch_directory", QString(batch_params.batch_directory.c_str()));
164         }
165
166     QString proc_value;
167     proc_value.setNum(batch_params.nb_proc);
168     setField("proc_value", proc_value);
169
170     setField("exclusive", batch_params.exclusive);
171
172     if (batch_params.maximum_duration == "")
173     {
174       setField("duration_hour", 0);
175       setField("duration_min", 0);
176     }
177     else
178     {
179       std::size_t pos = batch_params.maximum_duration.find(":");
180       std::string hour_str = batch_params.maximum_duration.substr(0, pos);
181       int hour; 
182       std::istringstream iss_hour(hour_str);
183       iss_hour >> hour;
184       setField("duration_hour", hour);
185
186       std::string min_str = batch_params.maximum_duration.substr(pos + 1, batch_params.maximum_duration.npos);
187       int min; 
188       std::istringstream iss_min(min_str);
189       iss_min >> min;
190       setField("duration_min", min);
191     }
192
193     unsigned long long mem_mb = batch_params.mem_limit;
194     if (mem_mb % 1024 == 0)
195     {
196       setField("mem_value", mem_mb / 1024);
197       _batch_parameters_page->setMemUnit(BatchParametersPage::GB);
198     }
199     else
200     {
201       setField("mem_value", mem_mb);
202       _batch_parameters_page->setMemUnit(BatchParametersPage::MB);
203     }
204     _batch_parameters_page->setMemReqType(batch_params.mem_req_type);
205
206     BL::Job::FilesParam files_params = job->getFilesParameters();
207
208     std::list<std::string>::iterator it = files_params.input_files_list.begin();
209     for (; it != files_params.input_files_list.end(); it++)
210       _input_files_list->addItem(QString((*it).c_str()));
211     it = files_params.output_files_list.begin();
212     for (; it != files_params.output_files_list.end(); it++)
213       _output_files_list->addItem(QString((*it).c_str()));
214
215     setField("result_directory", QString(files_params.result_directory.c_str()));
216     setField("resource_choosed", QString(job->getResource().c_str()));
217     setField("batch_queue", QString(job->getBatchQueue().c_str()));
218     setField("ll_jobtype", QString(job->getLoadLevelerJobType().c_str()));
219     setField("wckey", QString(job->getWCKey().c_str()));
220   }
221 }
222
223 void
224 BL::CreateJobWizard::setFilesList(QListWidget * input_files_list, QListWidget * output_files_list)
225 {
226   _input_files_list = input_files_list;
227   _output_files_list = output_files_list;
228 }
229
230 void
231 BL::CreateJobWizard::end(int result)
232 {
233   DEBTRACE("End of BL::CreateJobWizard");
234   if (result)
235   {
236     // Job Name Panel
237     QString f_job_name = field("job_name").toString();
238     job_name = f_job_name.trimmed().toUtf8().constData();
239
240     // YACS Schema Panel
241     QString f_yacs_file = field("yacs_file").toString();
242     yacs_file = f_yacs_file.trimmed().toUtf8().constData();
243     dump_yacs_state = field("dump_yacs_state").toInt();
244
245     // Command Panel
246     QString f_command = field("command").toString();
247     command = f_command.trimmed().toUtf8().constData();
248
249     // Command Panel
250     QString f_python_salome_file = field("PythonSalome").toString();
251     python_salome_file = f_python_salome_file.trimmed().toUtf8().constData();
252
253     QString f_env_file;
254     if (yacs_file != "")
255       f_env_file = field("env_yacs_file").toString();
256     else if (command != "")
257       f_env_file = field("env_command_file").toString();
258     else if (python_salome_file != "")
259       f_env_file = field("env_PythonSalome_file").toString();
260     env_file = f_env_file.trimmed().toUtf8().constData();
261
262     // Batch Panel
263     QString f_batch_directory = field("batch_directory").toString();
264     batch_directory = f_batch_directory.trimmed().toUtf8().constData();
265
266     // For COORM
267     QString f_coorm_batch_directory = field("coorm_batch_directory").toString();
268     coorm_batch_directory = f_coorm_batch_directory.toUtf8().constData();
269
270         // For COORM
271     QString f_launcher_file = field("launcher_file").toString();
272     launcher_file = f_launcher_file.toUtf8().constData();
273     QString f_launcher_args = field("launcher_args").toString();
274     launcher_args = f_launcher_args.toUtf8().constData();
275
276     QString time_hour;
277     QString time_min;
278     if(field("duration_hour").toInt() == 0 && field("duration_min").toInt() == 0)
279     {
280       maximum_duration = "";
281     }
282     else
283     {
284       if (field("duration_hour").toInt() < 10)
285         time_hour = "0" + field("duration_hour").toString().trimmed();
286       else
287         time_hour = field("duration_hour").toString().trimmed();
288       if (field("duration_min").toInt() < 10)
289         time_min = "0" + field("duration_min").toString().trimmed();
290       else
291         time_min = field("duration_min").toString().trimmed();
292       maximum_duration = time_hour.toStdString() + ":" + time_min.toStdString();
293     }
294
295     unsigned long mem = field("mem_value").toULongLong();
296     BatchParametersPage::MemUnit mem_unit = _batch_parameters_page->getMemUnit();
297     switch (mem_unit)
298     {
299     case BatchParametersPage::MB:
300       mem_limit = mem;
301       break;
302     case BatchParametersPage::GB:
303       mem_limit = mem * 1024;
304       break;
305     default:
306       throw Exception("Invalid memory unit");
307     }
308     mem_req_type = _batch_parameters_page->getMemReqType();
309
310     nb_proc = field("proc_value").toInt();
311     exclusive = field("exclusive").toBool();
312
313     // Files Panel
314     QString f_result_directory = field("result_directory").toString();
315     result_directory = f_result_directory.trimmed().toUtf8().constData();
316     for (int i = 0; i < _input_files_list->count(); ++i)
317     {
318       QListWidgetItem * item = _input_files_list->item(i);
319       QString item_text = item->text();
320       input_files_list.push_back(item_text.trimmed().toUtf8().constData());
321     }
322     for (int i = 0; i < _output_files_list->count(); ++i)
323     {
324       QListWidgetItem * item = _output_files_list->item(i);
325       QString item_text = item->text();
326       output_files_list.push_back(item_text.trimmed().toUtf8().constData());
327     }
328
329     // Resource list
330     QString f_resource_choosed = field("resource_choosed").toString();
331     resource_choosed = f_resource_choosed.trimmed().toUtf8().constData();
332
333     // Batch Queue
334     QString f_batch_queue = field("batch_queue").toString();
335     batch_queue = f_batch_queue.trimmed().toUtf8().constData();
336
337     // LoadLeveler JobType
338     BL::ResourceDescr resource_descr = _salome_services->getResourceDescr(resource_choosed);
339     std::string batch = resource_descr.batch.c_str();
340     if (batch == "ll")
341     {
342       QString f_ll_jobtype = field("ll_jobtype").toString();
343       ll_jobtype = f_ll_jobtype.trimmed().toStdString();
344     }
345     else
346     {
347       ll_jobtype = "";
348     }
349
350     // WC Key
351     QString f_wckey = field("wckey").toString();
352     wckey = f_wckey.trimmed().toUtf8().constData();
353
354     start_job = field("start_job").toBool();
355   }
356 }
357
358 // Job Name Page
359 BL::JobNamePage::JobNamePage(QWidget * parent, BL::JobsManager_QT * jobs_manager)
360 : QWizardPage(parent)
361 {
362   _jobs_manager = jobs_manager;
363   _check_name = true;
364   setTitle("Create a new job");
365
366   QLabel *label = new QLabel("Enter Job name, you cannot add two jobs with the same name");
367   label->setWordWrap(true);
368   QLabel * nameLabel = new QLabel("Job Name:");
369   QLineEdit * _nameLineEdit = new QLineEdit(this);
370   registerField("job_name", _nameLineEdit);
371
372   QLabel * label_type = new QLabel("Choose type of batch job:");
373   QGroupBox *groupBox = new QGroupBox("Type of job");
374   _yacs_schema_button = new QRadioButton(tr("YACS Schema"));
375   _yacs_schema_button->setChecked(true);
376   _command_button = new QRadioButton(tr("Command"));
377   _python_salome_button = new QRadioButton(tr("Python script in SALOME"));
378   QVBoxLayout *vbox = new QVBoxLayout;
379   vbox->addWidget(_yacs_schema_button);
380   vbox->addWidget(_command_button);
381   vbox->addWidget(_python_salome_button);
382   vbox->addStretch(1);
383   groupBox->setLayout(vbox);
384
385   QGroupBox * explanationBox = new QGroupBox("Explanation");
386   QVBoxLayout *explanationvbox = new QVBoxLayout;
387   _explanation = new QLabel();
388   _explanation->setWordWrap(true);
389   explanationvbox->addWidget(_explanation);
390   explanationvbox->addStretch(1);
391   explanationBox->setLayout(explanationvbox);
392
393   // Layouts
394   QVBoxLayout * main_layout = new QVBoxLayout;
395   main_layout->addWidget(label);
396   QGridLayout *layout = new QGridLayout;
397   layout->addWidget(nameLabel, 0, 0);
398   layout->addWidget(_nameLineEdit, 0, 1);
399   main_layout->insertLayout(-1, layout);
400   layout->addWidget(label_type, 2, 0);
401   layout->addWidget(groupBox, 3, 0, 1, -1);
402   layout->addWidget(explanationBox, 4, 0, 1, -1);
403   setLayout(main_layout);
404
405   connect(_yacs_schema_button, SIGNAL(clicked(bool)), this, SLOT(yacs_schema_button(bool)));
406   connect(_command_button, SIGNAL(clicked(bool)), this, SLOT(command_button(bool)));
407   connect(_python_salome_button, SIGNAL(clicked(bool)), this, SLOT(python_salome_button(bool)));
408
409   // Default button
410   yacs_schema_button(true);
411 }
412
413 BL::JobNamePage::~JobNamePage()
414 {}
415
416 void
417 BL::JobNamePage::yacs_schema_button(bool checked)
418 {
419   if (checked)
420   {
421     _explanation->setText("This job permits to launch a YACS schema into a SALOME application");
422     setField("exclusive", true);
423   }
424 }
425
426 void
427 BL::JobNamePage::command_button(bool checked)
428 {
429   if (checked)
430   {
431     _explanation->setText("This job permits to launch a script into a distributed resource. This script is not launched into a SALOME application");
432     setField("exclusive", false);
433   }
434 }
435
436 void
437 BL::JobNamePage::python_salome_button(bool checked)
438 {
439   if (checked)
440   {
441     _explanation->setText("This job permits to launch a python script into a SALOME application");
442     setField("exclusive", true);
443   }
444 }
445
446 bool
447 BL::JobNamePage::validatePage()
448 {
449   DEBTRACE("Calling validatePage of BL::JobNamePage");
450   bool return_value;
451   QString job_name = field("job_name").toString();
452
453   // Check if job name is empty
454   if (job_name == "")
455   {
456     QMessageBox::warning(NULL, "Job Name Error", "Job name entered is empty, enter a job name or cancel the wizard");
457     return_value = false;
458   }
459
460   // Check if job name already exists
461   else {
462     if (_jobs_manager->job_already_exist(job_name.toUtf8().constData()) == false || _check_name == false)
463     {
464       return_value = true;
465     }
466     else
467     {
468       QMessageBox::critical(NULL, "Job Name Error", "Job name entered is already used");
469       QString value("");
470       setField("job_name", value);
471       return_value = false;
472     }
473   }
474
475   return return_value;
476 }
477
478 int
479 BL::JobNamePage::nextId() const
480 {
481   if (_yacs_schema_button->isChecked())
482   {
483     return BL::CreateJobWizard::Page_YACSSchema;
484   } 
485   else if (_command_button->isChecked())
486   {
487     return BL::CreateJobWizard::Page_Command_Main_Definitions;
488   }
489   else
490   {
491     return BL::CreateJobWizard::Page_PythonSalome_Main_Definitions;
492   }
493 }
494
495 BL::YACSSchemaPage::YACSSchemaPage(QWidget * parent)
496 : QWizardPage(parent)
497 {
498   setTitle("Configure YACS Execution");
499
500   QLabel *label = new QLabel("In this step you have to configure your YACS execution");
501   label->setWordWrap(true);
502
503   QGroupBox * files_param_box = new QGroupBox("YACS job files");
504   QPushButton * yacs_file_button = new QPushButton(tr("Choose YACS Schema file"));
505   connect(yacs_file_button, SIGNAL(clicked()), this, SLOT(choose_file()));
506   _yacs_file_text = new QLineEdit(this);
507   _yacs_file_text->setText("");
508   registerField("yacs_file", _yacs_file_text);
509   _yacs_file_text->setReadOnly(true);
510   QPushButton * command_env_file_button = new QPushButton(tr("Choose an environnement file"));
511   connect(command_env_file_button, SIGNAL(clicked()), this, SLOT(choose_env_file()));
512   _line_env_file = new QLineEdit(this);
513   registerField("env_yacs_file", _line_env_file);
514   _line_env_file->setReadOnly(true);
515   QGridLayout * files_layout = new QGridLayout;
516   files_layout->addWidget(yacs_file_button, 0, 0);
517   files_layout->addWidget(_yacs_file_text, 0, 1);
518   files_layout->addWidget(command_env_file_button, 1, 0);
519   files_layout->addWidget(_line_env_file, 1, 1);
520   files_param_box->setLayout(files_layout);
521
522   QGroupBox * spec_param_box = new QGroupBox("YACS specific parameters");
523   QLabel * label_dump =  new QLabel("Dump YACS state each secs (0 disable this feature)");
524   QLabel * label_dump_warning = new QLabel("(WARNING: can only be used with SALOME >= 6.3.0)");
525   QSpinBox * spin_dump = new QSpinBox(this);
526   spin_dump->setMinimum(0);
527   spin_dump->setMaximum(1000000);
528   registerField("dump_yacs_state", spin_dump);
529   QGridLayout * specific_layout = new QGridLayout;
530   specific_layout->addWidget(label_dump, 0, 0);
531   specific_layout->addWidget(spin_dump, 0, 1);
532   specific_layout->addWidget(label_dump_warning, 1, 0);
533   spec_param_box->setLayout(specific_layout);
534
535   QVBoxLayout * main_layout = new QVBoxLayout;
536   main_layout->addWidget(label);
537   main_layout->addWidget(files_param_box);
538   main_layout->addWidget(spec_param_box);
539
540   setLayout(main_layout);
541 };
542
543 BL::YACSSchemaPage::~YACSSchemaPage()
544 {}
545
546 bool
547 BL::YACSSchemaPage::validatePage()
548 {
549   bool return_value;
550   QString yacs_file = field("yacs_file").toString();
551   if (yacs_file != "")
552   {
553     return_value = true;
554   }
555   else
556   {
557     QMessageBox::warning(NULL, "YACS File Error", "Please choose a YACS File");
558     return_value = false;
559   }
560   return return_value;
561 }
562
563 void
564 BL::YACSSchemaPage::choose_file()
565 {
566   QString yacs_file = QFileDialog::getOpenFileName(this,
567                                                    tr("Open YACS files"), "",
568                                                    tr("XML (*.xml);;All Files (*)"));
569   _yacs_file_text->setReadOnly(false);
570   _yacs_file_text->setText(yacs_file);
571   _yacs_file_text->setReadOnly(true);
572 }
573
574 void
575 BL::YACSSchemaPage::choose_env_file()
576 {
577   QString env_file = QFileDialog::getOpenFileName(this,
578                                                   tr("Open environnement file"), "",
579                                                   tr("sh (*.sh);;All Files (*)"));
580   _line_env_file->setReadOnly(false);
581   _line_env_file->setText(env_file);
582   _line_env_file->setReadOnly(true);
583 }
584
585
586 int 
587 BL::YACSSchemaPage::nextId() const
588 {
589   return BL::CreateJobWizard::Page_Resource;
590 }
591
592 BL::CommandMainPage::CommandMainPage(QWidget * parent)
593 : QWizardPage(parent)
594 {
595   setTitle("Define command job");
596   QLabel *label = new QLabel("Enter the command that will be executed into the resource");
597   label->setWordWrap(true);
598
599   // command
600   QPushButton * command_file_button = new QPushButton(tr("Choose a command file"));
601   connect(command_file_button, SIGNAL(clicked()), this, SLOT(choose_command_file()));
602   _line_command = new QLineEdit(this);
603   registerField("command", _line_command);
604   _line_command->setReadOnly(true);
605
606   QPushButton * command_env_file_button = new QPushButton(tr("Choose an environnement file"));
607   connect(command_env_file_button, SIGNAL(clicked()), this, SLOT(choose_env_file()));
608   _line_env_file = new QLineEdit(this);
609   registerField("env_command_file", _line_env_file);
610   _line_env_file->setReadOnly(true);
611
612   QGridLayout *layout = new QGridLayout;
613   layout->addWidget(command_file_button, 0, 0);
614   layout->addWidget(_line_command, 0, 1);
615   layout->addWidget(command_env_file_button, 1, 0);
616   layout->addWidget(_line_env_file, 1, 1);
617
618   QVBoxLayout * main_layout = new QVBoxLayout;
619   main_layout->addWidget(label);
620   main_layout->insertLayout(-1, layout);
621   setLayout(main_layout);
622 };
623
624 BL::CommandMainPage::~CommandMainPage()
625 {}
626
627 void
628 BL::CommandMainPage::choose_command_file()
629 {
630   QString command_file = QFileDialog::getOpenFileName(this,
631                                                       tr("Open command file"), "",
632                                                       tr("sh (*.sh);;All Files (*)"));
633   _line_command->setReadOnly(false);
634   _line_command->setText(command_file);
635   _line_command->setReadOnly(true);
636 }
637
638 void
639 BL::CommandMainPage::choose_env_file()
640 {
641   QString env_file = QFileDialog::getOpenFileName(this,
642                                                   tr("Open environnement file"), "",
643                                                   tr("sh (*.sh);;All Files (*)"));
644   _line_env_file->setReadOnly(false);
645   _line_env_file->setText(env_file);
646   _line_env_file->setReadOnly(true);
647 }
648
649 bool
650 BL::CommandMainPage::validatePage()
651 {
652   QString command = field("command").toString();
653   if (command == "")
654   {
655     QMessageBox::warning(NULL, "Command Error", "Please enter a command");
656     return false;
657   }
658
659   return true;
660 }
661
662 int 
663 BL::CommandMainPage::nextId() const
664 {
665   return BL::CreateJobWizard::Page_Resource;
666 }
667
668 BatchParametersPage::BatchParametersPage(QWidget * parent, SALOMEServices * salome_services)
669 : QWizardPage(parent),
670   ui(new Ui::ResourceRequirementsWizardPage),
671   _salome_services(salome_services),
672   resource_choosed()
673 {
674   ui->setupUi(this);
675
676   registerField("duration_hour", ui->spin_duration_hour);
677   registerField("duration_min", ui->spin_duration_min);
678   registerField("mem_value", ui->spin_memory);
679   registerField("proc_value", ui->spin_proc);
680   registerField("exclusive", ui->check_exclusive);
681
682   ui->combo_memory_unit->insertItem(ui->combo_memory_unit->count(), "MB", MB);
683   ui->combo_memory_unit->insertItem(ui->combo_memory_unit->count(), "GB", GB);
684   setMemUnit(GB);
685
686   ui->combo_memory_req_type->insertItem(ui->combo_memory_req_type->count(),
687                                         "per node", Job::MEM_PER_NODE);
688   ui->combo_memory_req_type->insertItem(ui->combo_memory_req_type->count(),
689                                         "per core", Job::MEM_PER_CPU);
690 };
691
692 BatchParametersPage::~BatchParametersPage()
693 {
694   delete ui;
695 }
696
697 void
698 BatchParametersPage::initializePage()
699 {
700   string f_resource_choosed = field("resource_choosed").toString().toUtf8().constData();
701   if (f_resource_choosed != resource_choosed)
702   {
703     resource_choosed = f_resource_choosed;
704     // If choosed resource has a SLURM batch manager, activate option "memory per cpu"
705     ResourceDescr resource_descr = _salome_services->getResourceDescr(resource_choosed);
706     if (resource_descr.batch == "slurm")
707     {
708       ui->combo_memory_req_type->setEnabled(true);
709     }
710     else
711     {
712       ui->combo_memory_req_type->setEnabled(false);
713       setMemReqType(Job::MEM_PER_NODE);
714     }
715   }
716 }
717
718 BatchParametersPage::MemUnit
719 BatchParametersPage::getMemUnit() const
720 {
721   int idx = ui->combo_memory_unit->currentIndex();
722   return (MemUnit)(ui->combo_memory_unit->itemData(idx).toInt());
723 }
724
725 void
726 BatchParametersPage::setMemUnit(MemUnit mem_unit)
727 {
728   ui->combo_memory_unit->setCurrentIndex(ui->combo_memory_unit->findData(mem_unit));
729 }
730
731 Job::MemReqType
732 BatchParametersPage::getMemReqType() const
733 {
734   int idx = ui->combo_memory_req_type->currentIndex();
735   return (Job::MemReqType)(ui->combo_memory_req_type->itemData(idx).toInt());
736 }
737
738 void
739 BatchParametersPage::setMemReqType(Job::MemReqType mem_req_type)
740 {
741   ui->combo_memory_req_type->setCurrentIndex(ui->combo_memory_req_type->findData(mem_req_type));
742 }
743
744 void
745 BatchParametersPage::cleanupPage()
746 {
747 }
748
749 int 
750 BatchParametersPage::nextId() const
751 {
752   return CreateJobWizard::Page_Files;
753 }
754
755 BL::COORM_BatchParametersPage::COORM_BatchParametersPage(QWidget * parent, BL::SALOMEServices * salome_services)
756 : QWizardPage(parent)
757 {
758   setTitle("Enter COORM Parameters");
759   resource_choosed = "";
760
761   _salome_services = salome_services;
762
763   QLabel *label = new QLabel("In this step you define the parameters for COORM");
764   label->setWordWrap(true);
765   QVBoxLayout * main_layout = new QVBoxLayout;
766   main_layout->addWidget(label);
767
768   // coorm_batch_directory
769   QLabel * label_directory = new QLabel("Remote work directory: ");
770   QLineEdit * line_directory = new QLineEdit(this);
771   registerField("coorm_batch_directory", line_directory);
772
773   // launcher_file
774   QPushButton * launcher_file_button = new QPushButton(tr("Choose a launcher file"));
775   connect(launcher_file_button, SIGNAL(clicked()), this, SLOT(choose_launcher_file()));
776   _launcher_file_text = new QLineEdit(this);
777   _launcher_file_text->setText("");
778   registerField("launcher_file", _launcher_file_text);
779   _launcher_file_text->setReadOnly(true);
780
781   // launcher_args
782   QLabel * launcher_args_label = new QLabel("Launcher args:");
783   QLineEdit * launcher_args_text = new QLineEdit(this);
784   registerField("launcher_args", launcher_args_text);
785
786   QGridLayout * layout = new QGridLayout;
787   layout->addWidget(label_directory, 0, 0);
788   layout->addWidget(line_directory, 0, 1);
789   layout->addWidget(launcher_file_button, 1, 0);
790   layout->addWidget(_launcher_file_text, 1, 1);
791   layout->addWidget(launcher_args_label, 2, 0);
792   layout->addWidget(launcher_args_text, 2, 1);
793
794   main_layout->insertLayout(-1, layout);
795
796   setLayout(main_layout);
797 };
798
799 BL::COORM_BatchParametersPage::~COORM_BatchParametersPage()
800 {}
801
802 bool
803 BL::COORM_BatchParametersPage::validatePage()
804 {
805   QString coorm_batch_directory = field("coorm_batch_directory").toString();
806   if (coorm_batch_directory == "")
807   {
808     QMessageBox::warning(NULL, "Batch Directory Error", "Please enter a batch directory");
809     return false;
810   }
811
812   QString launcher_file = field("launcher_file").toString();
813   if (launcher_file == "")
814   {
815     QMessageBox::warning(NULL, "Launcher File Error", "Please enter a launcher file");
816     return false;
817   }
818
819   return true;
820 }
821
822 int
823 BL::COORM_BatchParametersPage::nextId() const
824 {
825   return BL::CreateJobWizard::Page_Files;
826 }
827
828 void
829 BL::COORM_BatchParametersPage::choose_launcher_file()
830 {
831   QString launcher_file = QFileDialog::getOpenFileName(this,
832                                                    tr("Open launcher files"), "",
833                                                    tr("Py (*.py);;All Files (*)"));
834   _launcher_file_text->setReadOnly(false);
835   _launcher_file_text->setText(launcher_file);
836   _launcher_file_text->setReadOnly(true);
837 }
838
839 void BL::COORM_BatchParametersPage::cleanupPage()
840 {}
841
842 void
843 BL::COORM_BatchParametersPage::initializePage()
844 {
845   QString f_resource_choosed = field("resource_choosed").toString();
846   if (f_resource_choosed != resource_choosed)
847   {
848     resource_choosed = f_resource_choosed;
849     // If choosed resource has a working_directory set
850     // Generates a default remote working directory
851     BL::ResourceDescr resource_descr = _salome_services->getResourceDescr(resource_choosed.toUtf8().constData());
852     QString res_work_dir = resource_descr.working_directory.c_str();
853     if (res_work_dir != "")
854     {
855       time_t rawtime;
856       time(&rawtime);
857       std::string launch_date = ctime(&rawtime);
858       for (int i = 0; i < launch_date.size(); i++)
859         if (launch_date[i] == '/' ||
860             launch_date[i] == '-' ||
861             launch_date[i] == ':' ||
862             launch_date[i] == ' ')
863           launch_date[i] = '_';
864       launch_date.erase(--launch_date.end()); // Last caracter is a \n
865       QString date = launch_date.c_str();
866       setField("coorm_batch_directory", res_work_dir + "/" + date);
867     }
868   }
869 }
870
871 FilesPage::FilesPage(CreateJobWizard * parent, SALOMEServices * salome_services)
872 : QWizardPage(parent),
873   ui(new Ui::FilesWizardPage)
874 {
875   ui->setupUi(this);
876
877   resource_choosed = "";
878   _salome_services = salome_services;
879
880   connect(ui->add_input_files_button, SIGNAL(clicked()), this, SLOT(choose_input_files()));
881   connect(ui->remove_input_files_button, SIGNAL(clicked()), this, SLOT(remove_input_files()));
882   connect(ui->input_files_list, SIGNAL(itemSelectionChanged()), this, SLOT(input_itemSelectionChanged()));
883   connect(ui->add_output_files_button, SIGNAL(clicked()), this, SLOT(add_output_file()));
884   connect(ui->remove_output_files_button, SIGNAL(clicked()), this, SLOT(remove_output_files()));
885   connect(ui->output_files_list, SIGNAL(itemSelectionChanged()), this, SLOT(output_itemSelectionChanged()));
886   connect(ui->button_choose_result_dir, SIGNAL(clicked()), this, SLOT(choose_local_directory()));
887
888   registerField("batch_directory", ui->line_remote_working_dir);
889   registerField("result_directory", ui->line_result_dir);
890
891   // Default result directory is home directory (if we found it)
892   // First try -> HOME
893 #ifdef WNT
894   ui->line_result_dir->setText(getenv("HOME"));
895 #else
896   if (getenv("HOME"))
897     ui->line_result_dir->setText(getenv("HOME"));
898   else {
899     // Second try -> getpwuid
900     struct passwd * pass_struct = getpwuid(getuid());
901     if (pass_struct)
902       ui->line_result_dir->setText(pass_struct->pw_dir);
903   }
904 #endif
905
906   parent->setFilesList(ui->input_files_list, ui->output_files_list);
907
908   // Check for warning messages
909   ui->label_warning_icon->setPixmap(QIcon::fromTheme("dialog-error").pixmap(16, 16));
910   connect(ui->line_remote_working_dir, SIGNAL(textChanged(const QString &)), this, SIGNAL(completeChanged()));
911   connect(ui->line_result_dir, SIGNAL(textChanged(const QString &)), this, SIGNAL(completeChanged()));
912 };
913
914 FilesPage::~FilesPage()
915 {
916   delete ui;
917 }
918
919 void
920 FilesPage::initializePage()
921 {
922   QString f_resource_choosed = field("resource_choosed").toString();
923   if (f_resource_choosed != resource_choosed)
924   {
925     resource_choosed = f_resource_choosed;
926     // If choosed resource has a working_directory set
927     // Generates a default remote working directory
928     BL::ResourceDescr resource_descr = _salome_services->getResourceDescr(resource_choosed.toUtf8().constData());
929     QString res_work_dir = resource_descr.working_directory.c_str();
930     if (res_work_dir != "")
931     {
932       time_t rawtime;
933       time(&rawtime);
934       std::string launch_date = ctime(&rawtime);
935       for (int i = 0; i < launch_date.size(); i++)
936         if (launch_date[i] == '/' ||
937             launch_date[i] == '-' ||
938             launch_date[i] == ':' ||
939             launch_date[i] == ' ')
940           launch_date[i] = '_';
941       launch_date.erase(--launch_date.end()); // Last caracter is a \n
942       QString date = launch_date.c_str();
943       setField("batch_directory", res_work_dir + "/" + date);
944     }
945   }
946 }
947
948 bool
949 FilesPage::isComplete() const
950 {
951   QString warn_msg;
952   if (field("batch_directory").toString().isEmpty())
953     warn_msg = "Remote working directory is mandatory.";
954   if (field("result_directory").toString().isEmpty() && ui->output_files_list->count() != 0)
955   {
956     if (!warn_msg.isEmpty()) warn_msg += "\n";
957     warn_msg += "Result directory is mandatory if there are output files.";
958   }
959
960   ui->label_warning_text->setText(warn_msg);
961   if (warn_msg.isEmpty())
962   {
963     ui->label_warning_icon->hide();
964     return true;
965   }
966   else
967   {
968     ui->label_warning_icon->show();
969     return false;
970   }
971 }
972
973 void
974 FilesPage::choose_input_files()
975 {
976   QStringList files = QFileDialog::getOpenFileNames(this,
977                                                     tr("Add input files"), "",
978                                                     tr("All Files (*)"));
979   for (int i = 0; i < files.size(); ++i) 
980   {
981     if (ui->input_files_list->findItems(files.at(i), Qt::MatchFixedString).size() == 0)
982       ui->input_files_list->addItem(files.at(i));
983   }
984 }
985
986 void
987 FilesPage::choose_local_directory()
988 {
989   QString dir = QFileDialog::getExistingDirectory(this, tr("Choose local result directory"),
990                                                  "",
991                                                  QFileDialog::ShowDirsOnly
992                                                  | QFileDialog::DontResolveSymlinks);
993
994   if (dir != "")
995     ui->line_result_dir->setText(dir);
996 }
997
998 void 
999 FilesPage::remove_input_files()
1000 {
1001   QList<QListWidgetItem *> list = ui->input_files_list->selectedItems();
1002   for (int i = 0; i < list.size(); ++i)
1003   {
1004     int row = ui->input_files_list->row( list.at(i) );
1005     delete ui->input_files_list->takeItem(row);
1006   }
1007 }
1008
1009 void 
1010 FilesPage::input_itemSelectionChanged()
1011 {
1012   if (ui->input_files_list->selectedItems().size() > 0)
1013     ui->remove_input_files_button->setEnabled(true);
1014   else
1015     ui->remove_input_files_button->setEnabled(false);
1016 }
1017
1018 void
1019 FilesPage::add_output_file()
1020 {
1021   QListWidgetItem * new_item = new QListWidgetItem("TO EDIT!");
1022   new_item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEditable|Qt::ItemIsUserCheckable|Qt::ItemIsEnabled);
1023   ui->output_files_list->addItem(new_item);
1024   emit completeChanged();
1025 }
1026
1027 void 
1028 FilesPage::remove_output_files()
1029 {
1030   QList<QListWidgetItem *> list = ui->output_files_list->selectedItems();
1031   for (int i = 0; i < list.size(); ++i)
1032   {
1033     int row = ui->output_files_list->row( list.at(i) );
1034     delete ui->output_files_list->takeItem(row);
1035   }
1036   emit completeChanged();
1037 }
1038
1039 void 
1040 FilesPage::output_itemSelectionChanged()
1041 {
1042   if (ui->output_files_list->selectedItems().size() > 0)
1043     ui->remove_output_files_button->setEnabled(true);
1044   else
1045     ui->remove_output_files_button->setEnabled(false);
1046 }
1047
1048 int 
1049 FilesPage::nextId() const
1050 {
1051   return BL::CreateJobWizard::Page_Advanced;
1052 }
1053
1054 BL::ConclusionPage::ConclusionPage(QWidget * parent)
1055 : QWizardPage(parent)
1056 {
1057   setTitle("Job definition is finished");
1058   QCheckBox * check_box =  new QCheckBox("Start job after creation");
1059   registerField("start_job", check_box);
1060   QVBoxLayout * main_layout = new QVBoxLayout;
1061   main_layout->addWidget(check_box);
1062   setLayout(main_layout);
1063 };
1064
1065 BL::ConclusionPage::~ConclusionPage()
1066 {}
1067
1068 bool
1069 BL::ConclusionPage::validatePage()
1070 {
1071   return true;
1072 }
1073
1074 int 
1075 BL::ConclusionPage::nextId() const
1076 {
1077   return -1;
1078 }
1079
1080 BL::ResourcePage::ResourcePage(BL::CreateJobWizard * parent, BL::SALOMEServices * salome_services)
1081 : QWizardPage(parent)
1082 {
1083   _salome_services = salome_services;
1084   setTitle("Select a Resource");
1085
1086   QLabel * main_label = new QLabel("In this step you select the resource of your job");
1087   main_label->setWordWrap(true);
1088
1089   // input_Resource
1090   QGroupBox * resource_group_box = new QGroupBox("Resource List");
1091   _resource_list = new JM::ResourceCatalog(this, _salome_services, true);
1092   connect(_resource_list->getQListWidget(), SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(itemSelected(QListWidgetItem*)));
1093
1094   QVBoxLayout * resource_list_layout = new QVBoxLayout();
1095   resource_list_layout->addWidget(_resource_list);
1096   resource_group_box->setLayout(resource_list_layout);
1097
1098   QLabel * resource_label = new QLabel("Resource selected: ");
1099   _resource_choosed = new QLineEdit();
1100   _resource_choosed->setText("");
1101   _resource_choosed->setReadOnly(true);
1102   registerField("resource_choosed", _resource_choosed);
1103
1104   QLabel * bqLabel = new QLabel("Batch Queue (could be optional):");
1105   QLineEdit * _bqLineEdit = new QLineEdit(this);
1106   registerField("batch_queue", _bqLineEdit);
1107
1108   _ll_label = new QLabel("LoadLeveler JobType:", this);
1109   _ll_value = new QLineEdit(this);
1110   registerField("ll_jobtype", _ll_value);
1111   _ll_label->hide();
1112   _ll_value->hide();
1113
1114   _main_layout = new QGridLayout;
1115   _main_layout->addWidget(resource_group_box, 0, 0, 1, -1);
1116   _main_layout->addWidget(resource_label, 1, 0);
1117   _main_layout->addWidget(_resource_choosed, 1, 1);
1118   _main_layout->addWidget(bqLabel, 2, 0);
1119   _main_layout->addWidget(_bqLineEdit, 2, 1);
1120   setLayout(_main_layout);
1121
1122 };
1123
1124 BL::ResourcePage::~ResourcePage()
1125 {}
1126
1127 void
1128 BL::ResourcePage::initializePage()
1129 {
1130   if (field("ll_jobtype").toString() != "")
1131   {
1132     _main_layout->addWidget(_ll_label, 3, 0);
1133     _main_layout->addWidget(_ll_value, 3, 1);
1134     _ll_label->show();
1135     _ll_value->show();
1136   }
1137
1138   // Initialize resource_choosed with first resource in resource list
1139   if (field("resource_choosed").toString() == "")
1140   {
1141     std::list<std::string> resource_list = _salome_services->getResourceList(true);
1142     std::list<std::string>::iterator it = resource_list.begin();
1143     if (it != resource_list.end())
1144     {
1145       QString first_resource((*it).c_str());
1146       setField("resource_choosed", first_resource);
1147     }
1148   }
1149 }
1150
1151 bool
1152 BL::ResourcePage::validatePage()
1153 {
1154   QString resource_choosed = field("resource_choosed").toString();
1155   if (resource_choosed == "")
1156   {
1157     QMessageBox::warning(NULL, "Resource Error", "Please choose a resource");
1158     return false;
1159   }
1160
1161   BL::ResourceDescr resource_descr = _salome_services->getResourceDescr(resource_choosed.toUtf8().constData());
1162   std::string batch = resource_descr.batch.c_str();
1163   if (batch == "ll")
1164   {
1165     QString ll_jobtype = field("ll_jobtype").toString();
1166     if (ll_jobtype == "")
1167     {
1168       QMessageBox::warning(NULL, "LoadLeveler Error", "Please define a LoadLeveler JobType");
1169       return false;
1170     }
1171   }
1172   return true;
1173 }
1174
1175 void 
1176 BL::ResourcePage::itemSelected(QListWidgetItem * item)
1177 {
1178   _resource_choosed->setReadOnly(false);
1179   _resource_choosed->setText(item->text());
1180   _resource_choosed->setReadOnly(true);
1181
1182   //Specific parameters for LoadLeveler
1183   BL::ResourceDescr resource_descr = _salome_services->getResourceDescr(item->text().toUtf8().constData());
1184   std::string batch = resource_descr.batch.c_str();
1185   if (batch == "ll")
1186   {
1187     _main_layout->addWidget(_ll_label, 3, 0);
1188     _main_layout->addWidget(_ll_value, 3, 1);
1189     _ll_label->show();
1190     _ll_value->show();
1191   }
1192   else
1193   {
1194     _main_layout->removeWidget(_ll_value);
1195     _main_layout->removeWidget(_ll_label);
1196     _ll_label->hide();
1197     _ll_value->hide();
1198   }
1199 }
1200
1201 int 
1202 BL::ResourcePage::nextId() const
1203 {
1204   BL::ResourceDescr resource_descr = _salome_services->getResourceDescr(_resource_choosed->text().toUtf8().constData());
1205   std::string batch = resource_descr.batch.c_str();
1206   if (batch == "coorm")
1207   {
1208           return BL::CreateJobWizard::Page_COORM_BatchParameters;
1209   }
1210   else
1211   {
1212           return BL::CreateJobWizard::Page_BatchParameters;
1213   }
1214 }
1215
1216 BL::PythonSalomeMainPage::PythonSalomeMainPage(QWidget * parent)
1217 : QWizardPage(parent)
1218 {
1219   setTitle("Define a Python script in SALOME job");
1220   QLabel *label = new QLabel("Enter the Python script that will be executed into the resource");
1221   label->setWordWrap(true);
1222
1223   // PythonSalome
1224   QPushButton * PythonSalome_file_button = new QPushButton(tr("Choose a Python file"));
1225   connect(PythonSalome_file_button, SIGNAL(clicked()), this, SLOT(choose_PythonSalome_file()));
1226   _line_PythonSalome = new QLineEdit(this);
1227   registerField("PythonSalome", _line_PythonSalome);
1228   _line_PythonSalome->setReadOnly(true);
1229
1230   QPushButton * PythonSalome_env_file_button = new QPushButton(tr("Choose an environnement file"));
1231   connect(PythonSalome_env_file_button, SIGNAL(clicked()), this, SLOT(choose_env_file()));
1232   _line_env_file = new QLineEdit(this);
1233   registerField("env_PythonSalome_file", _line_env_file);
1234   _line_env_file->setReadOnly(true);
1235
1236   QGridLayout *layout = new QGridLayout;
1237   layout->addWidget(PythonSalome_file_button, 0, 0);
1238   layout->addWidget(_line_PythonSalome, 0, 1);
1239   layout->addWidget(PythonSalome_env_file_button, 1, 0);
1240   layout->addWidget(_line_env_file, 1, 1);
1241
1242   QVBoxLayout * main_layout = new QVBoxLayout;
1243   main_layout->addWidget(label);
1244   main_layout->insertLayout(-1, layout);
1245   setLayout(main_layout);
1246 };
1247
1248 BL::PythonSalomeMainPage::~PythonSalomeMainPage()
1249 {}
1250
1251 void
1252 BL::PythonSalomeMainPage::choose_PythonSalome_file()
1253 {
1254   QString PythonSalome_file = QFileDialog::getOpenFileName(this,
1255                                                       tr("Open Python script file"), "",
1256                                                       tr("py (*.py);;All Files (*)"));
1257   _line_PythonSalome->setReadOnly(false);
1258   _line_PythonSalome->setText(PythonSalome_file);
1259   _line_PythonSalome->setReadOnly(true);
1260 }
1261
1262 void
1263 BL::PythonSalomeMainPage::choose_env_file()
1264 {
1265   QString env_file = QFileDialog::getOpenFileName(this,
1266                                                       tr("Open environnement file"), "",
1267                                                       tr("sh (*.sh);;All Files (*)"));
1268   _line_env_file->setReadOnly(false);
1269   _line_env_file->setText(env_file);
1270   _line_env_file->setReadOnly(true);
1271 }
1272
1273 bool
1274 BL::PythonSalomeMainPage::validatePage()
1275 {
1276   QString PythonSalome = field("PythonSalome").toString();
1277   if (PythonSalome == "")
1278   {
1279     QMessageBox::warning(NULL, "Python script in SALOME Error", "Please enter a Python script");
1280     return false;
1281   }
1282
1283   return true;
1284 }
1285
1286 int 
1287 BL::PythonSalomeMainPage::nextId() const
1288 {
1289   return BL::CreateJobWizard::Page_Resource;
1290 }
1291
1292
1293
1294 AdvancedParametersPage::AdvancedParametersPage(CreateJobWizard * parent)
1295 : QWizardPage(parent),
1296   ui(new Ui::AdvancedParametersWizardPage)
1297 {
1298   ui->setupUi(this);
1299   registerField("wckey", ui->line_wckey);
1300 };
1301
1302 AdvancedParametersPage::~AdvancedParametersPage()
1303 {
1304   delete ui;
1305 }
1306
1307 int
1308 AdvancedParametersPage::nextId() const
1309 {
1310   return BL::CreateJobWizard::Page_Conclusion;
1311 }