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