Salome HOME
6ff0fe2dd004ccb47cd50992e347fb98c739bfee
[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
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().toUtf8().constData();
236
237     // YACS Schema Panel
238     QString f_yacs_file = field("yacs_file").toString();
239     yacs_file = f_yacs_file.trimmed().toUtf8().constData();
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().toUtf8().constData();
245
246     // Command Panel
247     QString f_python_salome_file = field("PythonSalome").toString();
248     python_salome_file = f_python_salome_file.trimmed().toUtf8().constData();
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().toUtf8().constData();
258
259     // Batch Panel
260     QString f_batch_directory = field("batch_directory").toString();
261     batch_directory = f_batch_directory.trimmed().toUtf8().constData();
262
263     // For COORM
264     QString f_coorm_batch_directory = field("coorm_batch_directory").toString();
265     coorm_batch_directory = f_coorm_batch_directory.toUtf8().constData();
266
267         // For COORM
268     QString f_launcher_file = field("launcher_file").toString();
269     launcher_file = f_launcher_file.toUtf8().constData();
270     QString f_launcher_args = field("launcher_args").toString();
271     launcher_args = f_launcher_args.toUtf8().constData();
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().toUtf8().constData();
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().toUtf8().constData());
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().toUtf8().constData());
324     }
325
326     // Resource list
327     QString f_resource_choosed = field("resource_choosed").toString();
328     resource_choosed = f_resource_choosed.trimmed().toUtf8().constData();
329
330     // Batch Queue
331     QString f_batch_queue = field("batch_queue").toString();
332     batch_queue = f_batch_queue.trimmed().toUtf8().constData();
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.toUtf8().constData()) == 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
685 BatchParametersPage::~BatchParametersPage()
686 {
687   delete ui;
688 }
689
690 void
691 BatchParametersPage::initializePage()
692 {
693   string f_resource_choosed = field("resource_choosed").toString().toUtf8().constData();
694   if (f_resource_choosed != resource_choosed)
695   {
696     resource_choosed = f_resource_choosed;
697     // If choosed resource has a SLURM batch manager, activate option "memory per cpu"
698     ResourceDescr resource_descr = _salome_services->getResourceDescr(resource_choosed);
699     if (resource_descr.batch == "slurm")
700     {
701       ui->combo_memory_req_type->setEnabled(true);
702     }
703     else
704     {
705       ui->combo_memory_req_type->setEnabled(false);
706       setMemReqType(Job::MEM_PER_NODE);
707     }
708   }
709 }
710
711 BatchParametersPage::MemUnit
712 BatchParametersPage::getMemUnit() const
713 {
714   int idx = ui->combo_memory_unit->currentIndex();
715   return (MemUnit)(ui->combo_memory_unit->itemData(idx).toInt());
716 }
717
718 void
719 BatchParametersPage::setMemUnit(MemUnit mem_unit)
720 {
721   ui->combo_memory_unit->setCurrentIndex(ui->combo_memory_unit->findData(mem_unit));
722 }
723
724 Job::MemReqType
725 BatchParametersPage::getMemReqType() const
726 {
727   int idx = ui->combo_memory_req_type->currentIndex();
728   return (Job::MemReqType)(ui->combo_memory_req_type->itemData(idx).toInt());
729 }
730
731 void
732 BatchParametersPage::setMemReqType(Job::MemReqType mem_req_type)
733 {
734   ui->combo_memory_req_type->setCurrentIndex(ui->combo_memory_req_type->findData(mem_req_type));
735 }
736
737 void
738 BatchParametersPage::cleanupPage()
739 {
740 }
741
742 int 
743 BatchParametersPage::nextId() const
744 {
745   return CreateJobWizard::Page_Files;
746 }
747
748 BL::COORM_BatchParametersPage::COORM_BatchParametersPage(QWidget * parent, BL::SALOMEServices * salome_services)
749 : QWizardPage(parent)
750 {
751   setTitle("Enter COORM Parameters");
752   resource_choosed = "";
753
754   _salome_services = salome_services;
755
756   QLabel *label = new QLabel("In this step you define the parameters for COORM");
757   label->setWordWrap(true);
758   QVBoxLayout * main_layout = new QVBoxLayout;
759   main_layout->addWidget(label);
760
761   // coorm_batch_directory
762   QLabel * label_directory = new QLabel("Remote work directory: ");
763   QLineEdit * line_directory = new QLineEdit(this);
764   registerField("coorm_batch_directory", line_directory);
765
766   // launcher_file
767   QPushButton * launcher_file_button = new QPushButton(tr("Choose a launcher file"));
768   connect(launcher_file_button, SIGNAL(clicked()), this, SLOT(choose_launcher_file()));
769   _launcher_file_text = new QLineEdit(this);
770   _launcher_file_text->setText("");
771   registerField("launcher_file", _launcher_file_text);
772   _launcher_file_text->setReadOnly(true);
773
774   // launcher_args
775   QLabel * launcher_args_label = new QLabel("Launcher args:");
776   QLineEdit * launcher_args_text = new QLineEdit(this);
777   registerField("launcher_args", launcher_args_text);
778
779   QGridLayout * layout = new QGridLayout;
780   layout->addWidget(label_directory, 0, 0);
781   layout->addWidget(line_directory, 0, 1);
782   layout->addWidget(launcher_file_button, 1, 0);
783   layout->addWidget(_launcher_file_text, 1, 1);
784   layout->addWidget(launcher_args_label, 2, 0);
785   layout->addWidget(launcher_args_text, 2, 1);
786
787   main_layout->insertLayout(-1, layout);
788
789   setLayout(main_layout);
790 };
791
792 BL::COORM_BatchParametersPage::~COORM_BatchParametersPage()
793 {}
794
795 bool
796 BL::COORM_BatchParametersPage::validatePage()
797 {
798   QString coorm_batch_directory = field("coorm_batch_directory").toString();
799   if (coorm_batch_directory == "")
800   {
801     QMessageBox::warning(NULL, "Batch Directory Error", "Please enter a batch directory");
802     return false;
803   }
804
805   QString launcher_file = field("launcher_file").toString();
806   if (launcher_file == "")
807   {
808     QMessageBox::warning(NULL, "Launcher File Error", "Please enter a launcher file");
809     return false;
810   }
811
812   return true;
813 }
814
815 int
816 BL::COORM_BatchParametersPage::nextId() const
817 {
818   return BL::CreateJobWizard::Page_Files;
819 }
820
821 void
822 BL::COORM_BatchParametersPage::choose_launcher_file()
823 {
824   QString launcher_file = QFileDialog::getOpenFileName(this,
825                                                    tr("Open launcher files"), "",
826                                                    tr("Py (*.py);;All Files (*)"));
827   _launcher_file_text->setReadOnly(false);
828   _launcher_file_text->setText(launcher_file);
829   _launcher_file_text->setReadOnly(true);
830 }
831
832 void BL::COORM_BatchParametersPage::cleanupPage()
833 {}
834
835 void
836 BL::COORM_BatchParametersPage::initializePage()
837 {
838   QString f_resource_choosed = field("resource_choosed").toString();
839   if (f_resource_choosed != resource_choosed)
840   {
841     resource_choosed = f_resource_choosed;
842     // If choosed resource has a working_directory set
843     // Generates a default remote working directory
844     BL::ResourceDescr resource_descr = _salome_services->getResourceDescr(resource_choosed.toUtf8().constData());
845     QString res_work_dir = resource_descr.working_directory.c_str();
846     if (res_work_dir != "")
847     {
848       time_t rawtime;
849       time(&rawtime);
850       std::string launch_date = ctime(&rawtime);
851       for (int i = 0; i < launch_date.size(); i++)
852         if (launch_date[i] == '/' ||
853             launch_date[i] == '-' ||
854             launch_date[i] == ':' ||
855             launch_date[i] == ' ')
856           launch_date[i] = '_';
857       launch_date.erase(--launch_date.end()); // Last caracter is a \n
858       QString date = launch_date.c_str();
859       setField("coorm_batch_directory", res_work_dir + "/" + date);
860     }
861   }
862 }
863
864 FilesPage::FilesPage(CreateJobWizard * parent, SALOMEServices * salome_services)
865 : QWizardPage(parent),
866   ui(new Ui::FilesWizardPage)
867 {
868   ui->setupUi(this);
869
870   resource_choosed = "";
871   _salome_services = salome_services;
872
873   connect(ui->add_input_files_button, SIGNAL(clicked()), this, SLOT(choose_input_files()));
874   connect(ui->remove_input_files_button, SIGNAL(clicked()), this, SLOT(remove_input_files()));
875   connect(ui->input_files_list, SIGNAL(itemSelectionChanged()), this, SLOT(input_itemSelectionChanged()));
876   connect(ui->add_output_files_button, SIGNAL(clicked()), this, SLOT(add_output_file()));
877   connect(ui->remove_output_files_button, SIGNAL(clicked()), this, SLOT(remove_output_files()));
878   connect(ui->output_files_list, SIGNAL(itemSelectionChanged()), this, SLOT(output_itemSelectionChanged()));
879   connect(ui->button_choose_result_dir, SIGNAL(clicked()), this, SLOT(choose_local_directory()));
880
881   registerField("batch_directory", ui->line_remote_working_dir);
882   registerField("result_directory", ui->line_result_dir);
883
884   // Default result directory is home directory (if we found it)
885   // First try -> HOME
886 #ifdef WNT
887   ui->line_result_dir->setText(getenv("HOME"));
888 #else
889   if (getenv("HOME"))
890     ui->line_result_dir->setText(getenv("HOME"));
891   else {
892     // Second try -> getpwuid
893     struct passwd * pass_struct = getpwuid(getuid());
894     if (pass_struct)
895       ui->line_result_dir->setText(pass_struct->pw_dir);
896   }
897 #endif
898
899   parent->setFilesList(ui->input_files_list, ui->output_files_list);
900
901   // Check for warning messages
902   ui->label_warning_icon->setPixmap(QIcon::fromTheme("dialog-error").pixmap(16, 16));
903   connect(ui->line_remote_working_dir, SIGNAL(textChanged(const QString &)), this, SIGNAL(completeChanged()));
904   connect(ui->line_result_dir, SIGNAL(textChanged(const QString &)), this, SIGNAL(completeChanged()));
905 };
906
907 FilesPage::~FilesPage()
908 {
909   delete ui;
910 }
911
912 void
913 FilesPage::initializePage()
914 {
915   QString f_resource_choosed = field("resource_choosed").toString();
916   if (f_resource_choosed != resource_choosed)
917   {
918     resource_choosed = f_resource_choosed;
919     // If choosed resource has a working_directory set
920     // Generates a default remote working directory
921     BL::ResourceDescr resource_descr = _salome_services->getResourceDescr(resource_choosed.toUtf8().constData());
922     QString res_work_dir = resource_descr.working_directory.c_str();
923     if (res_work_dir != "")
924     {
925       time_t rawtime;
926       time(&rawtime);
927       std::string launch_date = ctime(&rawtime);
928       for (int i = 0; i < launch_date.size(); i++)
929         if (launch_date[i] == '/' ||
930             launch_date[i] == '-' ||
931             launch_date[i] == ':' ||
932             launch_date[i] == ' ')
933           launch_date[i] = '_';
934       launch_date.erase(--launch_date.end()); // Last caracter is a \n
935       QString date = launch_date.c_str();
936       setField("batch_directory", res_work_dir + "/" + date);
937     }
938   }
939 }
940
941 bool
942 FilesPage::isComplete() const
943 {
944   QString warn_msg;
945   if (field("batch_directory").toString().isEmpty())
946     warn_msg = "Remote working directory is mandatory.";
947   if (field("result_directory").toString().isEmpty() && ui->output_files_list->count() != 0)
948   {
949     if (!warn_msg.isEmpty()) warn_msg += "\n";
950     warn_msg += "Result directory is mandatory if there are output files.";
951   }
952
953   ui->label_warning_text->setText(warn_msg);
954   if (warn_msg.isEmpty())
955   {
956     ui->label_warning_icon->hide();
957     return true;
958   }
959   else
960   {
961     ui->label_warning_icon->show();
962     return false;
963   }
964 }
965
966 void
967 FilesPage::choose_input_files()
968 {
969   QStringList files = QFileDialog::getOpenFileNames(this,
970                                                     tr("Add input files"), "",
971                                                     tr("All Files (*)"));
972   for (int i = 0; i < files.size(); ++i) 
973   {
974     if (ui->input_files_list->findItems(files.at(i), Qt::MatchFixedString).size() == 0)
975       ui->input_files_list->addItem(files.at(i));
976   }
977 }
978
979 void
980 FilesPage::choose_local_directory()
981 {
982   QString dir = QFileDialog::getExistingDirectory(this, tr("Choose local result directory"),
983                                                  "",
984                                                  QFileDialog::ShowDirsOnly
985                                                  | QFileDialog::DontResolveSymlinks);
986
987   if (dir != "")
988     ui->line_result_dir->setText(dir);
989 }
990
991 void 
992 FilesPage::remove_input_files()
993 {
994   QList<QListWidgetItem *> list = ui->input_files_list->selectedItems();
995   for (int i = 0; i < list.size(); ++i)
996   {
997     int row = ui->input_files_list->row( list.at(i) );
998     delete ui->input_files_list->takeItem(row);
999   }
1000 }
1001
1002 void 
1003 FilesPage::input_itemSelectionChanged()
1004 {
1005   if (ui->input_files_list->selectedItems().size() > 0)
1006     ui->remove_input_files_button->setEnabled(true);
1007   else
1008     ui->remove_input_files_button->setEnabled(false);
1009 }
1010
1011 void
1012 FilesPage::add_output_file()
1013 {
1014   QListWidgetItem * new_item = new QListWidgetItem("TO EDIT!");
1015   new_item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEditable|Qt::ItemIsUserCheckable|Qt::ItemIsEnabled);
1016   ui->output_files_list->addItem(new_item);
1017   emit completeChanged();
1018 }
1019
1020 void 
1021 FilesPage::remove_output_files()
1022 {
1023   QList<QListWidgetItem *> list = ui->output_files_list->selectedItems();
1024   for (int i = 0; i < list.size(); ++i)
1025   {
1026     int row = ui->output_files_list->row( list.at(i) );
1027     delete ui->output_files_list->takeItem(row);
1028   }
1029   emit completeChanged();
1030 }
1031
1032 void 
1033 FilesPage::output_itemSelectionChanged()
1034 {
1035   if (ui->output_files_list->selectedItems().size() > 0)
1036     ui->remove_output_files_button->setEnabled(true);
1037   else
1038     ui->remove_output_files_button->setEnabled(false);
1039 }
1040
1041 int 
1042 FilesPage::nextId() const
1043 {
1044   return BL::CreateJobWizard::Page_Conclusion;
1045 }
1046
1047 BL::ConclusionPage::ConclusionPage(QWidget * parent)
1048 : QWizardPage(parent)
1049 {
1050   setTitle("Job definition is finished");
1051   QCheckBox * check_box =  new QCheckBox("Start job after creation");
1052   registerField("start_job", check_box);
1053   QVBoxLayout * main_layout = new QVBoxLayout;
1054   main_layout->addWidget(check_box);
1055   setLayout(main_layout);
1056 };
1057
1058 BL::ConclusionPage::~ConclusionPage()
1059 {}
1060
1061 bool
1062 BL::ConclusionPage::validatePage()
1063 {
1064   return true;
1065 }
1066
1067 int 
1068 BL::ConclusionPage::nextId() const
1069 {
1070   return -1;
1071 }
1072
1073 BL::ResourcePage::ResourcePage(BL::CreateJobWizard * parent, BL::SALOMEServices * salome_services)
1074 : QWizardPage(parent)
1075 {
1076   _salome_services = salome_services;
1077   setTitle("Select a Resource");
1078
1079   QLabel * main_label = new QLabel("In this step you select the resource of your job");
1080   main_label->setWordWrap(true);
1081
1082   // input_Resource
1083   QGroupBox * resource_group_box = new QGroupBox("Resource List");
1084   _resource_list = new JM::ResourceCatalog(this, _salome_services, true);
1085   connect(_resource_list->getQListWidget(), SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(itemSelected(QListWidgetItem*)));
1086
1087   QVBoxLayout * resource_list_layout = new QVBoxLayout();
1088   resource_list_layout->addWidget(_resource_list);
1089   resource_group_box->setLayout(resource_list_layout);
1090
1091   QLabel * resource_label = new QLabel("Resource selected: ");
1092   _resource_choosed = new QLineEdit();
1093   _resource_choosed->setText("");
1094   _resource_choosed->setReadOnly(true);
1095   registerField("resource_choosed", _resource_choosed);
1096
1097   QLabel * bqLabel = new QLabel("Batch Queue (could be optional):");
1098   QLineEdit * _bqLineEdit = new QLineEdit(this);
1099   registerField("batch_queue", _bqLineEdit);
1100
1101   _ll_label = new QLabel("LoadLeveler JobType:", this);
1102   _ll_value = new QLineEdit(this);
1103   registerField("ll_jobtype", _ll_value);
1104   _ll_label->hide();
1105   _ll_value->hide();
1106
1107   _main_layout = new QGridLayout;
1108   _main_layout->addWidget(resource_group_box, 0, 0, 1, -1);
1109   _main_layout->addWidget(resource_label, 1, 0);
1110   _main_layout->addWidget(_resource_choosed, 1, 1);
1111   _main_layout->addWidget(bqLabel, 2, 0);
1112   _main_layout->addWidget(_bqLineEdit, 2, 1);
1113   setLayout(_main_layout);
1114
1115 };
1116
1117 BL::ResourcePage::~ResourcePage()
1118 {}
1119
1120 void
1121 BL::ResourcePage::initializePage()
1122 {
1123   if (field("ll_jobtype").toString() != "")
1124   {
1125     _main_layout->addWidget(_ll_label, 3, 0);
1126     _main_layout->addWidget(_ll_value, 3, 1);
1127     _ll_label->show();
1128     _ll_value->show();
1129   }
1130
1131   // Initialize resource_choosed with first resource in resource list
1132   if (field("resource_choosed").toString() == "")
1133   {
1134     std::list<std::string> resource_list = _salome_services->getResourceList(true);
1135     std::list<std::string>::iterator it = resource_list.begin();
1136     if (it != resource_list.end())
1137     {
1138       QString first_resource((*it).c_str());
1139       setField("resource_choosed", first_resource);
1140     }
1141   }
1142 }
1143
1144 bool
1145 BL::ResourcePage::validatePage()
1146 {
1147   QString resource_choosed = field("resource_choosed").toString();
1148   if (resource_choosed == "")
1149   {
1150     QMessageBox::warning(NULL, "Resource Error", "Please choose a resource");
1151     return false;
1152   }
1153
1154   BL::ResourceDescr resource_descr = _salome_services->getResourceDescr(resource_choosed.toUtf8().constData());
1155   std::string batch = resource_descr.batch.c_str();
1156   if (batch == "ll")
1157   {
1158     QString ll_jobtype = field("ll_jobtype").toString();
1159     if (ll_jobtype == "")
1160     {
1161       QMessageBox::warning(NULL, "LoadLeveler Error", "Please define a LoadLeveler JobType");
1162       return false;
1163     }
1164   }
1165   return true;
1166 }
1167
1168 void 
1169 BL::ResourcePage::itemSelected(QListWidgetItem * item)
1170 {
1171   _resource_choosed->setReadOnly(false);
1172   _resource_choosed->setText(item->text());
1173   _resource_choosed->setReadOnly(true);
1174
1175   //Specific parameters for LoadLeveler
1176   BL::ResourceDescr resource_descr = _salome_services->getResourceDescr(item->text().toUtf8().constData());
1177   std::string batch = resource_descr.batch.c_str();
1178   if (batch == "ll")
1179   {
1180     _main_layout->addWidget(_ll_label, 3, 0);
1181     _main_layout->addWidget(_ll_value, 3, 1);
1182     _ll_label->show();
1183     _ll_value->show();
1184   }
1185   else
1186   {
1187     _main_layout->removeWidget(_ll_value);
1188     _main_layout->removeWidget(_ll_label);
1189     _ll_label->hide();
1190     _ll_value->hide();
1191   }
1192 }
1193
1194 int 
1195 BL::ResourcePage::nextId() const
1196 {
1197   BL::ResourceDescr resource_descr = _salome_services->getResourceDescr(_resource_choosed->text().toUtf8().constData());
1198   std::string batch = resource_descr.batch.c_str();
1199   if (batch == "coorm")
1200   {
1201           return BL::CreateJobWizard::Page_COORM_BatchParameters;
1202   }
1203   else
1204   {
1205           return BL::CreateJobWizard::Page_BatchParameters;
1206   }
1207 }
1208
1209 BL::PythonSalomeMainPage::PythonSalomeMainPage(QWidget * parent)
1210 : QWizardPage(parent)
1211 {
1212   setTitle("Define a Python script in SALOME job");
1213   QLabel *label = new QLabel("Enter the Python script that will be executed into the resource");
1214   label->setWordWrap(true);
1215
1216   // PythonSalome
1217   QPushButton * PythonSalome_file_button = new QPushButton(tr("Choose a Python file"));
1218   connect(PythonSalome_file_button, SIGNAL(clicked()), this, SLOT(choose_PythonSalome_file()));
1219   _line_PythonSalome = new QLineEdit(this);
1220   registerField("PythonSalome", _line_PythonSalome);
1221   _line_PythonSalome->setReadOnly(true);
1222
1223   QPushButton * PythonSalome_env_file_button = new QPushButton(tr("Choose an environnement file"));
1224   connect(PythonSalome_env_file_button, SIGNAL(clicked()), this, SLOT(choose_env_file()));
1225   _line_env_file = new QLineEdit(this);
1226   registerField("env_PythonSalome_file", _line_env_file);
1227   _line_env_file->setReadOnly(true);
1228
1229   QGridLayout *layout = new QGridLayout;
1230   layout->addWidget(PythonSalome_file_button, 0, 0);
1231   layout->addWidget(_line_PythonSalome, 0, 1);
1232   layout->addWidget(PythonSalome_env_file_button, 1, 0);
1233   layout->addWidget(_line_env_file, 1, 1);
1234
1235   QVBoxLayout * main_layout = new QVBoxLayout;
1236   main_layout->addWidget(label);
1237   main_layout->insertLayout(-1, layout);
1238   setLayout(main_layout);
1239 };
1240
1241 BL::PythonSalomeMainPage::~PythonSalomeMainPage()
1242 {}
1243
1244 void
1245 BL::PythonSalomeMainPage::choose_PythonSalome_file()
1246 {
1247   QString PythonSalome_file = QFileDialog::getOpenFileName(this,
1248                                                       tr("Open Python script file"), "",
1249                                                       tr("py (*.py);;All Files (*)"));
1250   _line_PythonSalome->setReadOnly(false);
1251   _line_PythonSalome->setText(PythonSalome_file);
1252   _line_PythonSalome->setReadOnly(true);
1253 }
1254
1255 void
1256 BL::PythonSalomeMainPage::choose_env_file()
1257 {
1258   QString env_file = QFileDialog::getOpenFileName(this,
1259                                                       tr("Open environnement file"), "",
1260                                                       tr("sh (*.sh);;All Files (*)"));
1261   _line_env_file->setReadOnly(false);
1262   _line_env_file->setText(env_file);
1263   _line_env_file->setReadOnly(true);
1264 }
1265
1266 bool
1267 BL::PythonSalomeMainPage::validatePage()
1268 {
1269   QString PythonSalome = field("PythonSalome").toString();
1270   if (PythonSalome == "")
1271   {
1272     QMessageBox::warning(NULL, "Python script in SALOME Error", "Please enter a Python script");
1273     return false;
1274   }
1275
1276   return true;
1277 }
1278
1279 int 
1280 BL::PythonSalomeMainPage::nextId() const
1281 {
1282   return BL::CreateJobWizard::Page_Resource;
1283 }