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