Salome HOME
Initial commit
[modules/jobmanager.git] / src / genericgui / BL_CreateJobWizard.cxx
1 //  Copyright (C) 2009 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
22 BL::CreateJobWizard::CreateJobWizard(BL::JobsManager_QT * jobs_manager, BL::SALOMEServices * salome_services)
23 {
24   DEBTRACE("Creating BL::CreateJobWizard");
25   BL_ASSERT(jobs_manager);
26   BL_ASSERT(salome_services);
27   _jobs_manager = jobs_manager;
28
29   job_name = "";
30   yacs_file = "";
31   command = "";
32   batch_directory = "";
33   expected_during_time = "";
34   expected_memory = "";
35   nb_proc = 1;
36
37   result_directory = "";
38
39   machine_choosed = "";
40
41   start_job = false;
42
43   setOptions(QWizard::IndependentPages | QWizard::NoBackButtonOnStartPage);
44
45   setPage(Page_JobName, new BL::CreateJobWizard::JobNamePage(this, _jobs_manager));
46   setPage(Page_YACSSchema, new BL::YACSSchemaPage(this));
47   setPage(Page_BatchParameters, new BL::BatchParametersPage(this));
48   setPage(Page_Files, new BL::FilesPage(this));
49   setPage(Page_Command_Main_Definitions, new BL::CreateJobWizard::CommandMainPage(this));
50   setPage(Page_Machine, new BL::MachinePage(this, salome_services));
51   setPage(Page_Conclusion, new BL::CreateJobWizard::ConclusionPage(this));
52
53   setWindowTitle("Create Job Wizard");
54   connect(this, SIGNAL(finished(int)), this, SLOT(end(int)));
55 }
56
57 BL::CreateJobWizard::~CreateJobWizard()
58 {
59   DEBTRACE("Destroying BL::CreateJobWizard");
60 }
61
62 void
63 BL::CreateJobWizard::setFilesList(QListWidget * input_files_list, QListWidget * output_files_list)
64 {
65   _input_files_list = input_files_list;
66   _output_files_list = output_files_list;
67 }
68
69 void
70 BL::CreateJobWizard::end(int result)
71 {
72   DEBTRACE("End of BL::CreateJobWizard");
73   if (result)
74   {
75     // Job Name Panel
76     QString f_job_name = field("job_name").toString();
77     job_name = f_job_name.toStdString();
78
79     // YACS Schema Panel
80     QString f_yacs_file = field("yacs_file").toString();
81     yacs_file = f_yacs_file.toStdString();
82     
83     // Command Panel
84     QString f_command = field("command").toString();
85     command = f_command.toStdString();
86     
87     // Batch Panel
88     QString f_batch_directory = field("batch_directory").toString();
89     batch_directory = f_batch_directory.toStdString();
90
91     QString time_hour;
92     QString time_min;
93     if (field("during_time_hour").toInt() < 10)
94       time_hour = "0" + field("during_time_hour").toString();
95     else
96       time_hour = field("during_time_hour").toString();
97     if (field("during_time_min").toInt() < 10)
98       time_min = "0" + field("during_time_min").toString();
99     else
100       time_min = field("during_time_min").toString();
101     expected_during_time = time_hour.toStdString() + ":" + time_min.toStdString() + ":00";
102
103     QString mem = field("mem_value").toString();
104     int mem_type_i = field("mem_type").toInt();
105     QString mem_type("gb");
106     if (mem_type_i == 0)
107       mem_type = "mb";
108     expected_memory = mem.toStdString() + mem_type.toStdString();
109
110     nb_proc = field("proc_value").toInt();
111
112     // Files Panel
113     QString f_result_directory = field("result_directory").toString();
114     result_directory = f_result_directory.toStdString();
115     for (int i = 0; i < _input_files_list->count(); ++i)
116     {
117       QListWidgetItem * item = _input_files_list->item(i);
118       QString item_text = item->text();
119       input_files_list.push_back(item_text.toStdString());
120     }
121     for (int i = 0; i < _output_files_list->count(); ++i)
122     {
123       QListWidgetItem * item = _output_files_list->item(i);
124       QString item_text = item->text();
125       output_files_list.push_back(item_text.toStdString());
126     }
127
128     // Machine list
129     QString f_machine_choosed = field("machine_choosed").toString();
130     machine_choosed = f_machine_choosed.toStdString(); 
131
132     start_job = field("start_job").toBool();
133   }
134 }
135
136 // Job Name Page
137 BL::CreateJobWizard::JobNamePage::JobNamePage(QWidget * parent, BL::JobsManager_QT * jobs_manager)
138 : QWizardPage(parent)
139 {
140   _jobs_manager = jobs_manager;
141   setTitle("Create a new job");
142
143   QLabel *label = new QLabel("Enter Job name, you cannot add two jobs with the same name");
144   label->setWordWrap(true);
145   QLabel * nameLabel = new QLabel("Job Name:");
146   QLineEdit * _nameLineEdit = new QLineEdit(this);
147   registerField("job_name", _nameLineEdit);
148
149   QLabel * label_type = new QLabel("Choose type of batch job:");
150   QGroupBox *groupBox = new QGroupBox();
151   _yacs_schema_button = new QRadioButton(tr("YACS Schema"));
152   _yacs_schema_button->setChecked(true);
153   QRadioButton *radio2 = new QRadioButton(tr("Command"));
154   QVBoxLayout *vbox = new QVBoxLayout;
155   vbox->addWidget(_yacs_schema_button);
156   vbox->addWidget(radio2);
157   vbox->addStretch(1);
158   groupBox->setLayout(vbox);
159
160   // Layouts
161   QVBoxLayout * main_layout = new QVBoxLayout;
162   main_layout->addWidget(label);
163   QGridLayout *layout = new QGridLayout;
164   layout->addWidget(nameLabel, 0, 0);
165   layout->addWidget(_nameLineEdit, 0, 1);
166   main_layout->insertLayout(-1, layout);
167   layout->addWidget(label_type, 2, 0);
168   layout->addWidget(groupBox, 3, 0, 1, -1);
169   setLayout(main_layout);
170 }
171
172 BL::CreateJobWizard::JobNamePage::~JobNamePage()
173 {}
174
175 bool
176 BL::CreateJobWizard::JobNamePage::validatePage()
177 {
178   DEBTRACE("Calling validatePage of BL::CreateJobWizard::JobNamePage");
179   bool return_value;
180   QString job_name = field("job_name").toString();
181
182   // Check if job name is empty
183   if (job_name == "")
184   {
185     QMessageBox::warning(NULL, "Job Name Error", "Job name entered is empty, enter a job name or cancel the wizard");
186     return_value = false;
187   }
188
189   // Check if job name already exists
190   else {
191     if (_jobs_manager->job_already_exist(job_name.toStdString()) == false)
192     {
193       return_value = true;
194     }
195     else
196     {
197       QMessageBox::critical(NULL, "Job Name Error", "Job name entered is already used");
198       QString value("");
199       setField("job_name", value);
200       return_value = false;
201     }
202   }
203
204   return return_value;
205 }
206
207 int 
208 BL::CreateJobWizard::JobNamePage::nextId() const
209 {
210   if (_yacs_schema_button->isChecked()) 
211   {
212     return BL::CreateJobWizard::Page_YACSSchema;
213   } 
214   else 
215   {
216     return BL::CreateJobWizard::Page_Command_Main_Definitions;
217   }
218 }
219
220 BL::YACSSchemaPage::YACSSchemaPage(QWidget * parent)
221 : QWizardPage(parent)
222 {
223   setTitle("Choose YACS Schema");
224
225   QLabel *label = new QLabel("In this step you have to choose what YACS Schema you want to execute");
226   label->setWordWrap(true);
227
228   _yacs_file_button = new QPushButton(tr("Choose YACS Schema file"));
229   _yacs_file_button->show();
230   connect(_yacs_file_button, SIGNAL(clicked()), this, SLOT(choose_file()));
231
232   _yacs_file_text = new QLineEdit(this);
233   _yacs_file_text->setText("");
234   registerField("yacs_file", _yacs_file_text);
235   _yacs_file_text->setReadOnly(true);
236
237   QVBoxLayout * main_layout = new QVBoxLayout;
238   main_layout->addWidget(label);
239   QGridLayout *layout = new QGridLayout;
240   layout->addWidget(_yacs_file_button, 0, 0);
241   layout->addWidget(_yacs_file_text, 0, 1);
242   main_layout->insertLayout(-1, layout);
243   setLayout(main_layout);
244 };
245
246 BL::YACSSchemaPage::~YACSSchemaPage()
247 {}
248
249 bool
250 BL::YACSSchemaPage::validatePage()
251 {
252   bool return_value;
253   QString yacs_file = field("yacs_file").toString();
254   if (yacs_file != "")
255   {
256     return_value = true;
257   }
258   else
259   {
260     QMessageBox::warning(NULL, "YACS File Error", "Please choose a YACS File");
261     return_value = false;
262   }
263   return return_value;
264 }
265
266 void
267 BL::YACSSchemaPage::choose_file()
268 {
269   QString yacs_file = QFileDialog::getOpenFileName(this,
270                                                    tr("Open YACS files"), "",
271                                                    tr("XML (*.xml);;All Files (*)"));
272   _yacs_file_text->setReadOnly(false);
273   _yacs_file_text->setText(yacs_file);
274   _yacs_file_text->setReadOnly(true);
275 }
276
277 int 
278 BL::YACSSchemaPage::nextId() const
279 {
280   return BL::CreateJobWizard::Page_BatchParameters;
281 }
282
283 BL::CreateJobWizard::CommandMainPage::CommandMainPage(QWidget * parent)
284 : QWizardPage(parent)
285 {
286   setTitle("Define command job");
287   QLabel *label = new QLabel("Enter the command that will be executed into the resource");
288   label->setWordWrap(true);
289
290   // command
291   QLabel * label_command = new QLabel("Command: ");
292   QLineEdit * line_command = new QLineEdit(this);
293   registerField("command", line_command);
294
295   QGridLayout *layout = new QGridLayout;
296   layout->addWidget(label_command, 0, 0);
297   layout->addWidget(line_command, 0, 1);
298
299   QVBoxLayout * main_layout = new QVBoxLayout;
300   main_layout->addWidget(label);
301   main_layout->insertLayout(-1, layout);
302   setLayout(main_layout);
303 };
304
305 BL::CreateJobWizard::CommandMainPage::~CommandMainPage()
306 {}
307
308 bool
309 BL::CreateJobWizard::CommandMainPage::validatePage()
310 {
311   QString command = field("command").toString();
312   if (command == "")
313   {
314     QMessageBox::warning(NULL, "Command Error", "Please enter a command");
315     return false;
316   }
317
318   return true;
319 }
320
321 int 
322 BL::CreateJobWizard::CommandMainPage::nextId() const
323 {
324   return BL::CreateJobWizard::Page_BatchParameters;
325 }
326
327 BL::BatchParametersPage::BatchParametersPage(QWidget * parent)
328 : QWizardPage(parent)
329 {
330   setTitle("Enter Batch Parameters");
331
332   QLabel *label = new QLabel("In this step you define the parameters of your job");
333   label->setWordWrap(true);
334   QVBoxLayout * main_layout = new QVBoxLayout;
335   main_layout->addWidget(label);
336
337   // batch_directory
338   QLabel * label_directory = new QLabel("Batch directory: ");
339   QLineEdit * line_directory = new QLineEdit(this);
340   registerField("batch_directory", line_directory);
341
342   // exected during time
343   QLabel * label_during_time = new QLabel("Expected during time: ");
344   QSpinBox * spin_during_time_hour = new QSpinBox(this);
345   QLabel * label_during_time_hour = new QLabel("Hours");
346   spin_during_time_hour->setMinimum(0);
347   spin_during_time_hour->setMaximum(1000000);
348   registerField("during_time_hour", spin_during_time_hour);
349   QSpinBox * spin_during_time_min = new QSpinBox(this);
350   QLabel * label_during_time_min = new QLabel("Minutes");
351   spin_during_time_min->setMinimum(0);
352   spin_during_time_min->setMaximum(59);
353   registerField("during_time_min", spin_during_time_min);
354
355   // memory
356   QLabel * label_memory = new QLabel("Memory per nodes expected: ");
357   QSpinBox * spin_memory = new QSpinBox(this);
358   spin_memory->setMinimum(0);
359   spin_memory->setMaximum(1000000);
360   registerField("mem_value", spin_memory);
361   QComboBox * combo_memory = new QComboBox(this);
362   combo_memory->addItem("MB");
363   combo_memory->addItem("GB");
364   combo_memory->setCurrentIndex(1);
365   registerField("mem_type", combo_memory);
366
367   // proc
368   QLabel * label_proc = new QLabel("Number of proc expected: ");
369   QSpinBox * spin_proc = new QSpinBox(this);
370   spin_proc->setMinimum(1);
371   spin_proc->setMaximum(1000000);
372   registerField("proc_value", spin_proc);
373
374   QGridLayout *layout = new QGridLayout;
375   layout->addWidget(label_directory, 0, 0);
376   layout->addWidget(line_directory, 0, 1, 1, -1);
377   layout->addWidget(label_during_time, 1, 0);
378   layout->addWidget(spin_during_time_hour, 1, 1);
379   layout->addWidget(label_during_time_hour, 1, 2);
380   layout->addWidget(spin_during_time_min, 1, 3);
381   layout->addWidget(label_during_time_min, 1, 4);
382   layout->addWidget(label_memory, 2, 0);
383   layout->addWidget(spin_memory, 2, 1);
384   layout->addWidget(combo_memory, 2, 2);
385   layout->addWidget(label_proc, 3, 0);
386   layout->addWidget(spin_proc, 3, 1);
387
388   main_layout->insertLayout(-1, layout);
389
390   setLayout(main_layout);
391 };
392
393 BL::BatchParametersPage::~BatchParametersPage()
394 {}
395
396 bool
397 BL::BatchParametersPage::validatePage()
398 {
399   QString batch_directory = field("batch_directory").toString();
400   if (batch_directory == "")
401   {
402     QMessageBox::warning(NULL, "Batch Directory Error", "Please enter a batch directory");
403     return false;
404   }
405
406   int time_hour = field("during_time_hour").toInt();
407   int time_min = field("during_time_min").toInt();
408   if (time_hour == 0 and time_min == 0)
409   {
410     QMessageBox::warning(NULL, "Time Error", "Please enter an expected during time");
411     return false;
412   }
413
414   int mem = field("mem_value").toInt();
415   if (mem == 0)
416   {
417     QMessageBox::warning(NULL, "Memory Error", "Please enter an expected memory");
418     return false;
419   }
420
421   return true;
422 }
423
424 int 
425 BL::BatchParametersPage::nextId() const
426 {
427   return BL::CreateJobWizard::Page_Files;
428 }
429
430 BL::FilesPage::FilesPage(BL::CreateJobWizard * parent)
431 : QWizardPage(parent)
432 {
433   setTitle("Enter Input and Output Files");
434
435   QLabel * main_label = new QLabel("In this step you define input and output files of your job");
436   main_label->setWordWrap(true);
437
438   // input_files
439   QGroupBox * input_group_box = new QGroupBox("Input Files");
440   _input_files_button = new QPushButton("Add input files");
441   _input_files_button->show();
442   connect(_input_files_button, SIGNAL(clicked()), this, SLOT(choose_input_files()));
443   _remove_input_files_button = new QPushButton("Remove input files");
444   _remove_input_files_button->show();
445   _remove_input_files_button->setEnabled(false);
446   connect(_remove_input_files_button, SIGNAL(clicked()), this, SLOT(remove_input_files()));
447   _input_files_list = new QListWidget();
448   _input_files_list->setSelectionMode(QAbstractItemView::MultiSelection);
449   connect(_input_files_list, SIGNAL(itemSelectionChanged()), this, SLOT(input_itemSelectionChanged()));
450
451   QGridLayout * input_box = new QGridLayout;
452   input_box->addWidget(_input_files_button, 0, 0);
453   input_box->addWidget(_remove_input_files_button, 0, 1);
454   input_box->addWidget(_input_files_list, 1, 0, 1, -1);
455   input_group_box->setLayout(input_box);
456
457   // output_files
458   QGroupBox * output_group_box = new QGroupBox("Output Files");
459   _output_files_button = new QPushButton("Add output file");
460   _output_files_button->show();
461   connect(_output_files_button, SIGNAL(clicked()), this, SLOT(add_output_file()));
462   _remove_output_files_button = new QPushButton("Remove output files");
463   _remove_output_files_button->show();
464   _remove_output_files_button->setEnabled(false);
465   connect(_remove_output_files_button, SIGNAL(clicked()), this, SLOT(remove_output_files()));
466   _output_files_list = new QListWidget();
467   _output_files_list->setSelectionMode(QAbstractItemView::MultiSelection);
468   _output_files_list->setEditTriggers(QAbstractItemView::DoubleClicked);
469   connect(_output_files_list, SIGNAL(itemSelectionChanged()), this, SLOT(output_itemSelectionChanged()));
470
471   // Results Directory
472   QLabel * label_result_directory = new QLabel("Result directory: ");
473   QLineEdit * result_directory = new QLineEdit(this);
474   registerField("result_directory", result_directory);
475
476   QGridLayout * output_box = new QGridLayout;
477   output_box->addWidget(_output_files_button, 0, 0);
478   output_box->addWidget(_remove_output_files_button, 0, 1);
479   output_box->addWidget(_output_files_list, 1, 0, 1, -1);
480   output_box->addWidget(label_result_directory, 2, 0);
481   output_box->addWidget(result_directory, 2, 1, 1, -1);
482   output_group_box->setLayout(output_box);
483
484   QVBoxLayout * main_layout = new QVBoxLayout;
485   main_layout->addWidget(main_label);
486   main_layout->addWidget(input_group_box);
487   main_layout->addWidget(output_group_box);
488   setLayout(main_layout);
489
490   parent->setFilesList(_input_files_list, _output_files_list);
491 };
492
493 BL::FilesPage::~FilesPage()
494 {}
495
496 bool
497 BL::FilesPage::validatePage()
498 {
499   QString result_directory = field("result_directory").toString();
500   
501   for (int i = 0; i < _output_files_list->count(); ++i)
502   {
503     QListWidgetItem * item = _output_files_list->item(i);
504     if (item->text() == "TO EDIT!")
505     {
506       QMessageBox::warning(NULL, "Ouput Files Error", "Some output files are not defined !");
507       return false;
508     }
509   }
510
511   if (result_directory == "" and _output_files_list->count() != 0)
512   {
513     QMessageBox::warning(NULL, "Result Directory Error", "Please enter a result directory or remove output files");
514     return false;
515   }
516
517   if (result_directory != "" and _output_files_list->count() == 0)
518   {
519     QMessageBox::warning(NULL, "Result Error", "Please add output files or erase result directory");
520     return false;
521   }
522
523   return true;
524 }
525
526 void
527 BL::FilesPage::choose_input_files()
528 {
529   QStringList files = QFileDialog::getOpenFileNames(this,
530                                               tr("Add input files"), "",
531                                               tr("All Files (*)"));
532   for (int i = 0; i < files.size(); ++i) 
533   {
534     if (_input_files_list->findItems(files.at(i), Qt::MatchFixedString).size() == 0)
535       _input_files_list->addItem(files.at(i));
536   }
537 }
538
539 void 
540 BL::FilesPage::remove_input_files()
541 {
542   QList<QListWidgetItem *> list = _input_files_list->selectedItems();
543   for (int i = 0; i < list.size(); ++i)
544   {
545     int row = _input_files_list->row( list.at(i) );
546     delete _input_files_list->takeItem(row);
547   }
548 }
549
550 void 
551 BL::FilesPage::input_itemSelectionChanged()
552 {
553   if (_input_files_list->selectedItems().size() > 0)
554     _remove_input_files_button->setEnabled(true);
555   else
556     _remove_input_files_button->setEnabled(false);
557 }
558
559 void
560 BL::FilesPage::add_output_file()
561 {
562   QListWidgetItem * new_item = new QListWidgetItem("TO EDIT!");
563   new_item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEditable|Qt::ItemIsUserCheckable|Qt::ItemIsEnabled);
564   _output_files_list->addItem(new_item);
565 }
566
567 void 
568 BL::FilesPage::remove_output_files()
569 {
570   QList<QListWidgetItem *> list = _output_files_list->selectedItems();
571   for (int i = 0; i < list.size(); ++i)
572   {
573     int row = _output_files_list->row( list.at(i) );
574     delete _output_files_list->takeItem(row);
575   }
576 }
577
578 void 
579 BL::FilesPage::output_itemSelectionChanged()
580 {
581   if (_output_files_list->selectedItems().size() > 0)
582     _remove_output_files_button->setEnabled(true);
583   else
584     _remove_output_files_button->setEnabled(false);
585 }
586
587 int 
588 BL::FilesPage::nextId() const
589 {
590   return BL::CreateJobWizard::Page_Machine;
591 }
592
593 BL::CreateJobWizard::ConclusionPage::ConclusionPage(QWidget * parent)
594 : QWizardPage(parent)
595 {
596   setTitle("Job definition is finished");
597   QCheckBox * check_box =  new QCheckBox("Start job after creation");
598   registerField("start_job", check_box);
599   QVBoxLayout * main_layout = new QVBoxLayout;
600   main_layout->addWidget(check_box);
601   setLayout(main_layout);
602 };
603
604 BL::CreateJobWizard::ConclusionPage::~ConclusionPage()
605 {}
606
607 bool
608 BL::CreateJobWizard::ConclusionPage::validatePage()
609 {
610   return true;
611 }
612
613 int 
614 BL::CreateJobWizard::ConclusionPage::nextId() const
615 {
616   return -1;
617 }
618
619 BL::MachinePage::MachinePage(BL::CreateJobWizard * parent, BL::SALOMEServices * salome_services)
620 : QWizardPage(parent)
621 {
622   _salome_services = salome_services;
623   setTitle("Select a Machine");
624
625   QLabel * main_label = new QLabel("In this step you select the machine of your job");
626   main_label->setWordWrap(true);
627
628   // input_Machine
629   QGroupBox * machine_group_box = new QGroupBox("Machine List");
630   _machine_list = new QListWidget();
631   _machine_list->setSelectionMode(QAbstractItemView::SingleSelection);
632   std::list<std::string> machine_list = _salome_services->getMachineList();
633   std::list<std::string>::iterator it;
634   for (it = machine_list.begin(); it != machine_list.end(); it++)
635   {
636     std::string machine = *it;
637     _machine_list->addItem(QString(machine.c_str()));
638   }
639   connect(_machine_list, SIGNAL(itemSelectionChanged()), this, SLOT(machine_itemSelectionChanged()));
640   QVBoxLayout * machine_list_layout = new QVBoxLayout();
641   machine_list_layout->addWidget(_machine_list);
642   machine_group_box->setLayout(machine_list_layout);
643
644   QLabel * machine_label = new QLabel("Machine selected: ");
645   _machine_choosed = new QLineEdit();
646   _machine_choosed->setText("");
647   _machine_choosed->setReadOnly(true);
648   registerField("machine_choosed", _machine_choosed);
649
650   QGridLayout * main_layout = new QGridLayout;
651   main_layout->addWidget(machine_group_box, 0, 0, 1, -1);
652   main_layout->addWidget(machine_label, 1, 0);
653   main_layout->addWidget(_machine_choosed, 1, 1);
654   setLayout(main_layout);
655 };
656
657 BL::MachinePage::~MachinePage()
658 {}
659
660 bool
661 BL::MachinePage::validatePage()
662 {
663   QString machine_choosed = field("machine_choosed").toString();
664   if (machine_choosed == "")
665   {
666     QMessageBox::warning(NULL, "Machine Error", "Please choose a machine");
667     return false;
668   }
669   return true;
670 }
671
672 void 
673 BL::MachinePage::machine_itemSelectionChanged()
674 {
675   _machine_choosed->setReadOnly(false);
676   QList<QListWidgetItem *> list = _machine_list->selectedItems();
677   QListWidgetItem * item = list.at(0);
678   _machine_choosed->setText(item->text());
679   _machine_choosed->setReadOnly(true);
680 }
681
682 int 
683 BL::MachinePage::nextId() const
684 {
685   return BL::CreateJobWizard::Page_Conclusion;
686 }