1 // Copyright (C) 2009-2014 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "BL_JobsManager_QT.hxx"
21 #include "BL_GenericGui.hxx"
26 // To tokenize a string
27 static void Tokenize(const std::string& str, std::vector<std::string>& tokens, const std::string& delimiters = " ");
29 BL::JobManagerEvent::JobManagerEvent(const std::string & action_i,
30 const std::string & event_name_i,
31 const std::string & job_name_i,
32 const std::string & data_i) : QEvent(QEvent::User)
35 event_name = event_name_i;
36 job_name = job_name_i;
40 BL::JobManagerEvent::~JobManagerEvent() {}
42 BL::JobsManager_QT::JobsManager_QT(QWidget * parent, BL::GenericGui * main_gui, BL::SALOMEServices * salome_services) :
43 QDockWidget(parent), BL::JobsManager(salome_services)
45 DEBTRACE("Creating BL::JobsManager_QT");
48 _model_manager = NULL;
52 QWidget * main_widget = new QWidget(this);
54 _load_jobs = new QPushButton("Load Jobs");
55 _save_jobs = new QPushButton("Save Jobs");
56 connect(_load_jobs, SIGNAL(clicked()), this, SLOT(load_jobs_button()));
57 connect(_save_jobs, SIGNAL(clicked()), this, SLOT(save_jobs_button()));
59 _auto_refresh_jobs = new QPushButton("Auto Refresh: no");
60 _timer = new QTimer(this);
62 connect(_timer, SIGNAL(timeout()), this, SLOT(RefreshJobs()));
64 // Menu for auto refresh
65 QMenu * refresh_menu = new QMenu(this);
66 refresh_menu->addAction("No", this, SLOT(no_auto_refresh()));
67 refresh_menu->addAction("10 seconds", this, SLOT(ten_seconds_refresh()));
68 refresh_menu->addAction("30 seconds", this, SLOT(thirty_seconds_refresh()));
69 refresh_menu->addAction("1 minute", this, SLOT(one_minute_refresh()));
70 refresh_menu->addAction("5 minutes", this, SLOT(five_minutes_refresh()));
71 refresh_menu->addAction("30 minutes", this, SLOT(thirty_minutes_refresh()));
72 refresh_menu->addAction("1 hour", this, SLOT(one_hour_refresh()));
73 _auto_refresh_jobs->setMenu(refresh_menu);
75 QHBoxLayout * button_layout = new QHBoxLayout();
76 button_layout->addWidget(_load_jobs);
77 button_layout->addWidget(_save_jobs);
78 button_layout->addWidget(_auto_refresh_jobs);
80 QGroupBox * message_box = new QGroupBox("Messages");
81 _log = new QTextEdit(this);
82 _log->setReadOnly(true);
83 QVBoxLayout * message_box_layout = new QVBoxLayout(message_box);
84 message_box_layout->addWidget(_log);
85 message_box->setLayout(message_box_layout);
87 QVBoxLayout * mainLayout = new QVBoxLayout();
88 mainLayout->addLayout(button_layout);
89 mainLayout->addWidget(message_box);
90 main_widget->setLayout(mainLayout);
92 QScrollArea * scroll_widget = new QScrollArea(this);
93 scroll_widget->setWidget(main_widget);
94 scroll_widget->setWidgetResizable(true);
95 setWidget(scroll_widget);
96 setWindowTitle("Job Manager");
97 setObjectName("JobManagerDockWidget");
100 BL::JobsManager_QT::~JobsManager_QT()
102 DEBTRACE("Destroying BL::JobsManager_QT");
106 BL::JobsManager_QT::set_model_manager(BL::QModelManager * model_manager)
108 _model_manager = model_manager;
112 BL::JobsManager_QT::load_jobs_button()
114 DEBTRACE("load_jobs");
115 QString jobs_file = QFileDialog::getOpenFileName(this,
116 tr("Choose an xml jobs file"), "",
117 tr("xml (*.xml);;All Files (*)"));
120 write_normal_text("Load jobs action cancelled\n");
123 load_jobs(jobs_file.toStdString());
127 BL::JobsManager_QT::save_jobs_button()
129 DEBTRACE("save_jobs");
130 QFileDialog dialog(this, "Save jobs file");
132 filters << "XML files (*.xml)"
134 dialog.setFileMode(QFileDialog::AnyFile);
135 dialog.setFilters(filters);
136 dialog.selectFilter("(*.xml)");
137 dialog.setDefaultSuffix("xml");
138 dialog.setConfirmOverwrite(true);
139 dialog.setAcceptMode(QFileDialog::AcceptSave);
140 QString jobs_file("");
141 QStringList fileNames;
143 if (bool ret = dialog.exec())
145 DEBTRACE(ret << " " << dialog.confirmOverwrite());
146 fileNames = dialog.selectedFiles();
147 if (!fileNames.isEmpty())
148 jobs_file= fileNames.first();
152 write_normal_text("Save jobs action cancelled\n");
155 save_jobs(jobs_file.toStdString());
159 BL::JobsManager_QT::RefreshJobs()
165 BL::JobsManager_QT::no_auto_refresh()
167 _auto_refresh_jobs->setText("Auto Refresh: no");
172 BL::JobsManager_QT::ten_seconds_refresh()
174 _auto_refresh_jobs->setText("Auto Refresh: 10s");
176 _timer->start(10 * 1000);
180 BL::JobsManager_QT::thirty_seconds_refresh()
182 _auto_refresh_jobs->setText("Auto Refresh: 30s");
184 _timer->start(30 * 1000);
188 BL::JobsManager_QT::one_minute_refresh()
190 _auto_refresh_jobs->setText("Auto Refresh: 1min");
192 _timer->start(1 * 60 * 1000);
196 BL::JobsManager_QT::five_minutes_refresh()
198 _auto_refresh_jobs->setText("Auto Refresh: 5min");
200 _timer->start(5 * 60 * 1000);
204 BL::JobsManager_QT::thirty_minutes_refresh()
206 _auto_refresh_jobs->setText("Auto Refresh: 30min");
208 _timer->start(30 * 60 * 1000);
212 BL::JobsManager_QT::one_hour_refresh()
214 _auto_refresh_jobs->setText("Auto Refresh: 1hour");
216 _timer->start(1 * 60 * 60 * 1000);
220 BL::JobsManager_QT::restart_job(const std::string & name)
222 DEBTRACE("Restart job with name: " << name);
223 BL::CreateJobWizard wizard(this, _salome_services);
226 wizard.job_name = name;
227 wizard.start_job = true;
228 _main_gui->delete_job_internal();
229 create_job_with_wizard(wizard);
233 BL::JobsManager_QT::edit_clone_job(const std::string & name)
235 BL::CreateJobWizard wizard(this, _salome_services);
239 // Check if the job has the same name
240 if (name == wizard.job_name)
242 DEBTRACE("Job " << name << " has been edited");
243 _main_gui->delete_job_internal();
246 if (wizard.job_name != "")
248 create_job_with_wizard(wizard);
252 DEBTRACE("User cancel Create Job Wizard");
257 BL::JobsManager_QT::create_job()
259 BL::CreateJobWizard wizard(this, _salome_services);
261 if (wizard.job_name != "")
263 create_job_with_wizard(wizard);
267 DEBTRACE("User cancel Create Job Wizard");
272 BL::JobsManager_QT::create_job_with_wizard(BL::CreateJobWizard & wizard)
274 BL::Job * new_job = createJob(wizard.job_name);
275 if (wizard.yacs_file != "")
278 new_job->setType(BL::Job::YACS_SCHEMA);
279 new_job->setJobFile(wizard.yacs_file);
280 new_job->setDumpYACSState(wizard.dump_yacs_state);
282 else if (wizard.command != "")
285 new_job->setType(BL::Job::COMMAND);
286 new_job->setJobFile(wizard.command);
288 else if (wizard.python_salome_file != "")
291 new_job->setType(BL::Job::PYTHON_SALOME);
292 new_job->setJobFile(wizard.python_salome_file);
296 new_job->setEnvFile(wizard.env_file);
297 BL::Job::BatchParam param;
300 if (wizard.coorm_batch_directory != "")
302 param.batch_directory = wizard.coorm_batch_directory;
304 else if (wizard.batch_directory != "")
306 param.batch_directory = wizard.batch_directory;
309 param.maximum_duration = wizard.maximum_duration;
310 param.mem_limit = wizard.mem_limit;
311 param.mem_req_type = wizard.mem_req_type;
312 param.nb_proc = wizard.nb_proc;
313 param.exclusive = wizard.exclusive;
315 // Parameters for COORM
316 param.launcher_file = wizard.launcher_file;
317 param.launcher_args = wizard.launcher_args;
319 new_job->setBatchParameters(param);
320 BL::Job::FilesParam files_params;
321 files_params.result_directory = wizard.result_directory;
322 files_params.input_files_list = wizard.input_files_list;
323 files_params.output_files_list = wizard.output_files_list;
324 new_job->setFilesParameters(files_params);
325 new_job->setResource(wizard.resource_choosed);
326 new_job->setBatchQueue(wizard.batch_queue);
327 new_job->setLoadLevelerJobType(wizard.ll_jobtype);
330 addJobToLauncher(wizard.job_name);
331 emit new_job_added(QString::fromStdString(wizard.job_name));
332 QStandardItemModel * model = _model_manager->getModel();
333 QList<QStandardItem *> item_list = model->findItems(QString::fromStdString(wizard.job_name));
334 QStandardItem * job_state_item = model->item(item_list.at(0)->row(), 2);
335 _main_gui->_jobs_table->selectRow(item_list.at(0)->row());
336 if (wizard.start_job)
337 start_job(wizard.job_name);
341 BL::JobsManager_QT::delete_job(QString job_name)
343 BL::JobsManager::removeJob(job_name.toStdString());
344 _model_manager->delete_job(job_name);
345 _main_gui->_job_tab->reset(job_name);
349 BL::JobsManager_QT::sendEvent(const std::string & action,
350 const std::string & event_name,
351 const std::string & job_name,
352 const std::string & data)
354 DEBTRACE("sendEvent BL::JobsManager_QT");
356 // Sending a QEvent to go back to main thread
357 BL::JobManagerEvent * event = new JobManagerEvent(action, event_name, job_name, data);
358 QApplication::postEvent(this, event);
362 BL::JobsManager_QT::event(QEvent * e)
364 QDockWidget::event(e);
365 JobManagerEvent * event = dynamic_cast<JobManagerEvent*>(e);
366 if (!event) return false;
368 DEBTRACE("BL::JobsManager_QT Receiving event : "
369 << event->action << " "
370 << event->event_name << " "
371 << event->job_name << " "
374 if (event->action == "create_job")
376 if (event->event_name == "Ok")
378 QString str((event->job_name).c_str());
379 write_normal_text("Job " + str + " created\n");
383 QString str((event->job_name).c_str());
384 write_error_text("Error in creating job: " + str + "\n");
385 write_error_text("*** ");
386 write_error_text((event->data).c_str());
387 write_error_text(" ***\n");
390 else if (event->action == "start_job")
392 if (event->event_name == "Ok")
394 QString str((event->job_name).c_str());
395 write_normal_text("Job " + str + " queued\n");
399 QString str((event->job_name).c_str());
400 write_error_text("Error in starting job: " + str + "\n");
401 write_error_text("*** ");
402 write_error_text((event->data).c_str());
403 write_error_text(" ***\n");
405 emit job_state_changed(QString((event->job_name).c_str()));
407 else if (event->action == "refresh_job")
409 if (event->event_name == "Ok")
411 QString name((event->job_name).c_str());
412 QString state((event->data).c_str());
413 state = state.toLower();
414 write_normal_text("Job " + name + " new state is " + state + "\n");
415 emit job_state_changed(QString((event->job_name).c_str()));
419 QString str((event->job_name).c_str());
420 write_error_text("Error in refreshing job: " + str + "\n");
421 write_error_text("*** ");
422 write_error_text((event->data).c_str());
423 write_error_text(" ***\n");
426 else if (event->action == "delete_job")
428 if (event->event_name == "Ok")
430 QString str((event->job_name).c_str());
431 write_normal_text("Job " + str + " deleted\n");
435 QString str((event->job_name).c_str());
436 write_error_text("Warning delete job: " + str + " maybe not complete, exception catch in SALOME Launcher service\n");
437 write_error_text("*** ");
438 write_error_text((event->data).c_str());
439 write_error_text(" ***\n");
442 else if (event->action == "get_results_job")
444 if (event->event_name == "Ok")
446 QString str((event->job_name).c_str());
447 write_normal_text("Results of Job " + str + " are get\n");
451 QString str((event->job_name).c_str());
452 write_error_text("Warning for results of job: " + str + " maybe not complete, exception catch in SALOME Launcher service\n");
453 write_error_text("*** ");
454 write_error_text((event->data).c_str());
455 write_error_text(" ***\n");
458 else if (event->action == "stop_job")
460 if (event->event_name == "Ok")
462 QString str((event->job_name).c_str());
463 write_normal_text("Job " + str + " is stopped\n");
467 QString str((event->job_name).c_str());
468 write_error_text("Error when trying to stop job: " + str + "\n");
469 write_error_text("*** ");
470 write_error_text((event->data).c_str());
471 write_error_text(" ***\n");
474 else if (event->action == "get_assigned_hostnames")
476 if (event->event_name == "Ok")
478 QString str((event->job_name).c_str());
480 vector<string> hostnames;
482 Tokenize(event->data, hostnames, "+");
484 vector<string>::iterator it;
486 write_normal_text("Job " + str + " assigned hostnames are :\n");
488 for (it = hostnames.begin(); it < hostnames.end(); it++)
490 vector<string> hostname;
491 Tokenize(*it, hostname, ".");
492 QString assigned_hostname(hostname[0].c_str());
493 write_normal_text("+ " + assigned_hostname + "\n");
498 // Do nothing in case the batch manager does not support this
501 else if (event->action == "save_jobs")
503 if (event->event_name == "Error")
505 write_error_text("Error in saving jobs: \n");
506 write_error_text("*** ");
507 write_error_text((event->data).c_str());
508 write_error_text(" ***\n");
512 QString str((event->data).c_str());
513 write_normal_text("Jobs saved in file " + str + "\n");
516 else if (event->action == "load_jobs")
518 if (event->event_name == "Error")
520 write_error_text("Error in loading jobs: \n");
521 write_error_text("*** ");
522 write_error_text((event->data).c_str());
523 write_error_text(" ***\n");
527 QString str((event->data).c_str());
528 write_normal_text("Jobs loaded from file " + str + "\n");
531 else if (event->action == "add_job")
533 if (event->event_name == "Ok")
535 QString str((event->job_name).c_str());
536 write_normal_text("New job added " + str + "\n");
537 emit new_job_added(str);
540 else if (event->action == "to_remove_job")
542 if (event->event_name == "Ok")
543 _main_gui->delete_job_external((event->job_name).c_str());
547 QString str((event->action).c_str());
548 write_error_text("Unknown type of event received:" + str + "\n");
554 BL::JobsManager_QT::write_normal_text(const QString & text)
556 _log->setReadOnly(false);
557 QTextCursor cursor = _log->textCursor();
558 QTextCharFormat text_format;
559 text_format.setForeground(Qt::darkBlue);
560 cursor.insertText(text, text_format);
561 _log->setTextCursor(cursor);
562 _log->setReadOnly(true);
566 BL::JobsManager_QT::write_error_text(const QString & text)
568 _log->setReadOnly(false);
569 QTextCursor cursor = _log->textCursor();
570 QTextCharFormat text_format;
571 text_format.setForeground(Qt::red);
572 cursor.insertText(text, text_format);
573 _log->setTextCursor(cursor);
574 _log->setReadOnly(true);
577 // To tokenize a string
578 void Tokenize(const std::string& str, std::vector<std::string>& tokens, const std::string& delimiters)
580 // Skip delimiters at beginning.
581 string::size_type lastPos = str.find_first_not_of(delimiters, 0);
582 // Find first "non-delimiter".
583 string::size_type pos = str.find_first_of(delimiters, lastPos);
585 while (string::npos != pos || string::npos != lastPos)
587 // Found a token, add it to the vector.
588 tokens.push_back(str.substr(lastPos, pos - lastPos));
589 // Skip delimiters. Note the "not_of"
590 lastPos = str.find_first_not_of(delimiters, pos);
591 // Find next "non-delimiter"
592 pos = str.find_first_of(delimiters, lastPos);