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