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