ARGoS 3
A parallel, multi-engine simulator for swarm robotics
qtopengl_lua_main_window.cpp
Go to the documentation of this file.
1
11#include "qtopengl_widget.h"
12
13#include <argos3/core/config.h>
14#include <argos3/core/wrappers/lua/lua_controller.h>
15#include <argos3/core/simulator/simulator.h>
16#include <argos3/core/simulator/space/space.h>
17#include <argos3/core/simulator/entity/composable_entity.h>
18#include <argos3/core/simulator/entity/controllable_entity.h>
19#include <argos3/core/wrappers/lua/lua_utility.h>
20
21#include <QApplication>
22#include <QDockWidget>
23#include <QFileDialog>
24#include <QHeaderView>
25#include <QMenu>
26#include <QMenuBar>
27#include <QMessageBox>
28#include <QProcess>
29#include <QSettings>
30#include <QStatusBar>
31#include <QTemporaryFile>
32#include <QTextStream>
33#include <QToolBar>
34#include <QTableWidget>
35#include <QTreeView>
36
37namespace argos {
38
39 /****************************************/
40 /****************************************/
41
42 static QString SCRIPT_TEMPLATE =
43 "-- Use Shift + Click to select a robot\n"
44 "-- When a robot is selected, its variables appear in this editor\n\n"
45 "-- Use Ctrl + Click (Cmd + Click on Mac) to move a selected robot to a different location\n\n\n\n"
46 "-- Put your global variables here\n\n\n\n"
47 "--[[ This function is executed every time you press the 'execute' button ]]\n"
48 "function init()\n"
49 " -- put your code here\n"
50 "end\n\n\n\n"
51 "--[[ This function is executed at each time step\n"
52 " It must contain the logic of your controller ]]\n"
53 "function step()\n"
54 " -- put your code here\n"
55 "end\n\n\n\n"
56 "--[[ This function is executed every time you press the 'reset'\n"
57 " button in the GUI. It is supposed to restore the state\n"
58 " of the controller to whatever it was right after init() was\n"
59 " called. The state of sensors and actuators is reset\n"
60 " automatically by ARGoS. ]]\n"
61 "function reset()\n"
62 " -- put your code here\n"
63 "end\n\n\n\n"
64 "--[[ This function is executed only once, when the robot is removed\n"
65 " from the simulation ]]\n"
66 "function destroy()\n"
67 " -- put your code here\n"
68 "end\n";
69
70 /****************************************/
71 /****************************************/
72
74 QMainWindow(pc_parent),
75 m_pcMainWindow(pc_parent),
76 m_pcStatusbar(NULL),
77 m_pcCodeEditor(NULL),
78 m_pcFindDialog(NULL),
79 m_pcLuaMessageTable(NULL) {
80 /* Add a status bar */
81 m_pcStatusbar = new QStatusBar(this);
82 setStatusBar(m_pcStatusbar);
83 /* Create the Lua message table */
84 CreateLuaMessageTable();
85 /* Populate list of Lua controllers */
86 PopulateLuaControllers();
87 /* Create the Lua state docks */
88 CreateLuaStateDocks();
89 /* Create editor */
90 CreateCodeEditor();
91 /* Create actions */
92 CreateFileActions();
93 CreateEditActions();
94 CreateCodeActions();
95 /* Set empty file */
96 SetCurrentFile("");
97 /* Read settings */
98 ReadSettings();
99 }
100
101 /****************************************/
102 /****************************************/
103
107
108 /****************************************/
109 /****************************************/
110
112 if(MaybeSave()) {
113 m_pcCodeEditor->setPlainText(SCRIPT_TEMPLATE);
114 SetCurrentFile("");
115 }
116 }
117
118 /****************************************/
119 /****************************************/
120
122 if(MaybeSave()) {
123 QString strNewFileName =
124 QFileDialog::getOpenFileName(this,
125 tr("Open File"),
126 "",
127 "Lua Files (*.lua)");
128 if (!strNewFileName.isEmpty()) {
129 OpenFile(strNewFileName);
130 }
131 }
132 }
133
134 /****************************************/
135 /****************************************/
136
138 QAction* pcAction = qobject_cast<QAction*>(sender());
139 if (pcAction) {
140 OpenFile(pcAction->data().toString());
141 }
142 }
143
144 /****************************************/
145 /****************************************/
146
148 if (m_strFileName.isEmpty()) {
149 return SaveAs();
150 } else {
151 return SaveFile(m_strFileName);
152 }
153 }
154
155 /****************************************/
156 /****************************************/
157
159 QString strNewFileName =
160 QFileDialog::getSaveFileName(this,
161 tr("Save File"),
162 "",
163 "Lua Files (*.lua)");
164 if (strNewFileName.isEmpty())
165 return false;
166 return SaveFile(strNewFileName);
167 }
168
169 /****************************************/
170 /****************************************/
171
172 static QString DetectLuaC() {
173 QProcess cLuaCompiler;
174 cLuaCompiler.start("luac", QStringList() << "-v");
175 /* First, try to execute luac */
176 if(!cLuaCompiler.waitForStarted()) {
177 /* luac is not installed */
178 return "";
179 }
180 /* luac is installed, but is it the right version? */
181 cLuaCompiler.waitForFinished();
182 if(QString(cLuaCompiler.readAllStandardOutput()).mid(4,3) == "5.2") {
183 return "luac";
184 }
185 cLuaCompiler.start("luac5.2", QStringList() << "-v");
186 if(!cLuaCompiler.waitForStarted()) {
187 /* luac52 is not installed */
188 return "";
189 }
190 else {
191 /* luac52 is installed */
192 cLuaCompiler.waitForFinished();
193 return "luac5.2";
194 }
195 }
196
198 /* Save script */
199 Save();
200 /* Change cursor */
201 QApplication::setOverrideCursor(Qt::WaitCursor);
202 /* Stop simulation */
203 m_pcMainWindow->SuspendExperiment();
204 /* Clear the message table */
205 m_pcLuaMessageTable->clearContents();
206 m_pcLuaMessageTable->setRowCount(1);
207 /* Create temporary file to contain the bytecode */
208 QTemporaryFile cByteCode;
209 if(! cByteCode.open()) {
210 SetMessage(0, "ALL", "Can't create bytecode file.");
211 QApplication::restoreOverrideCursor();
212 return;
213 }
214 /*
215 * Compile script
216 */
217 /* Check for luac 5.2 */
218 QString cLuaC = DetectLuaC();
219 if(cLuaC == "") {
220 /* luac 5.2 not found, fall back to sending the script directly to robots */
221 for(size_t i = 0; i < m_vecControllers.size(); ++i) {
222 m_vecControllers[i]->SetLuaScript(m_strFileName.toStdString());
223 }
224 }
225 else {
226 QProcess cLuaCompiler;
227 cLuaCompiler.start(cLuaC, QStringList() << "-o" << cByteCode.fileName() << m_strFileName);
228 if(! cLuaCompiler.waitForFinished()) {
229 SetMessage(0, "ALL", QString(cLuaCompiler.readAllStandardError()));
230 QApplication::restoreOverrideCursor();
231 return;
232 }
233 if(cLuaCompiler.exitCode() != 0) {
234 SetMessage(0, "ALL", QString(cLuaCompiler.readAllStandardError()));
235 QApplication::restoreOverrideCursor();
236 return;
237 }
238 SetMessage(0, "ALL", "Compilation successful.");
239 /* Set the script for all the robots */
240 for(size_t i = 0; i < m_vecControllers.size(); ++i) {
241 m_vecControllers[i]->SetLuaScript(cByteCode.fileName().toStdString());
242 }
243 }
244 /* Update Lua state if visible */
245 if(m_pcLuaVariableDock->isVisible()) {
246 static_cast<CQTOpenGLLuaStateTreeModel*>(m_pcLuaVariableTree->model())->SetLuaState(
247 m_vecControllers[m_unSelectedRobot]->GetLuaState());
248 }
249 if(m_pcLuaFunctionDock->isVisible()) {
250 static_cast<CQTOpenGLLuaStateTreeModel*>(m_pcLuaFunctionTree->model())->SetLuaState(
251 m_vecControllers[m_unSelectedRobot]->GetLuaState());
252 }
253 /* Resume simulation */
254 m_pcMainWindow->ResumeExperiment();
255 QApplication::restoreOverrideCursor();
256 statusBar()->showMessage(tr("Execution started"), 2000);
257 }
258
259 /****************************************/
260 /****************************************/
261
263 if(! m_pcFindDialog) {
264 m_pcFindDialog = new CQTOpenGLLuaFindDialog(this);
265 }
266 m_pcFindDialog->show();
267 }
268
269 /****************************************/
270 /****************************************/
271
273 setWindowModified(m_pcCodeEditor->document()->isModified());
274 }
275
276 /****************************************/
277 /****************************************/
278
279 bool CQTOpenGLLuaMainWindow::MaybeSave() {
280 if(m_pcCodeEditor->document()->isModified()) {
281 QMessageBox::StandardButton tReply;
282 tReply = QMessageBox::warning(this, tr("ARGoS v" ARGOS_VERSION "-" ARGOS_RELEASE " - Lua Editor"),
283 tr("The document has been modified.\n"
284 "Do you want to save your changes?"),
285 QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
286 if (tReply == QMessageBox::Save)
287 return Save();
288 else if (tReply == QMessageBox::Cancel)
289 return false;
290 }
291 return true;
292 }
293
294 /****************************************/
295 /****************************************/
296
297 void CQTOpenGLLuaMainWindow::PopulateLuaControllers() {
298 /* Get list of controllable entities */
299 CSpace& cSpace = CSimulator::GetInstance().GetSpace();
300 CSpace::TMapPerType& tControllables = cSpace.GetEntitiesByType("controller");
301 /* Go through them and keep a pointer to each Lua controller */
302 for(CSpace::TMapPerType::iterator it = tControllables.begin();
303 it != tControllables.end();
304 ++it) {
305 /* Try to convert the controller into a Lua controller */
306 CControllableEntity* pcControllable = any_cast<CControllableEntity*>(it->second);
307 CLuaController* pcLuaController = dynamic_cast<CLuaController*>(&(pcControllable->GetController()));
308 if(pcLuaController) {
309 /* Conversion succeeded, add to indices */
310 m_vecControllers.push_back(pcLuaController);
311 m_vecRobots.push_back(&pcControllable->GetParent());
312 }
313 else {
314 LOGERR << "[WARNING] Entity \""
315 << pcControllable->GetParent().GetId()
316 << "\" does not have a Lua controller associated"
317 << std::endl;
318 }
319 }
320 }
321
322 /****************************************/
323 /****************************************/
324
325 void CQTOpenGLLuaMainWindow::ReadSettings() {
326 QSettings cSettings;
327 cSettings.beginGroup("LuaEditor");
328 resize(cSettings.value("size", QSize(640,480)).toSize());
329 move(cSettings.value("position", QPoint(0,0)).toPoint());
330 cSettings.endGroup();
331 }
332
333 /****************************************/
334 /****************************************/
335
336 void CQTOpenGLLuaMainWindow::WriteSettings() {
337 QSettings cSettings;
338 cSettings.beginGroup("LuaEditor");
339 cSettings.setValue("size", size());
340 cSettings.setValue("position", pos());
341 cSettings.endGroup();
342 }
343
344 /****************************************/
345 /****************************************/
346
347 void CQTOpenGLLuaMainWindow::CreateCodeEditor() {
348 /* Create code editor */
349 m_pcCodeEditor = new CQTOpenGLLuaEditor(this);
350 setCentralWidget(m_pcCodeEditor);
351 m_pcCodeEditor->setPlainText(SCRIPT_TEMPLATE);
352 /* Connect stuff */
353 connect(m_pcCodeEditor->document(), SIGNAL(contentsChanged()),
354 this, SLOT(CodeModified()));
355 connect(&(m_pcMainWindow->GetOpenGLWidget()), SIGNAL(StepDone(int)),
356 this, SLOT(CheckLuaStatus(int)));
357 }
358
359 /****************************************/
360 /****************************************/
361
362 void CQTOpenGLLuaMainWindow::CreateLuaMessageTable() {
363 m_pcLuaMsgDock = new QDockWidget(tr("Messages"), this);
364 m_pcLuaMsgDock->setObjectName("LuaMessageDock");
365 m_pcLuaMsgDock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
366 m_pcLuaMsgDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea);
367 m_pcLuaMessageTable = new QTableWidget();
368 m_pcLuaMessageTable->setColumnCount(3);
369 QStringList listHeaders;
370 listHeaders << tr("Robot")
371 << tr("Line")
372 << tr("Message");
373 m_pcLuaMessageTable->setHorizontalHeaderLabels(listHeaders);
374 m_pcLuaMessageTable->horizontalHeader()->setStretchLastSection(true);
375 m_pcLuaMessageTable->setSelectionBehavior(QAbstractItemView::SelectRows);
376 m_pcLuaMessageTable->setSelectionMode(QAbstractItemView::SingleSelection);
377 m_pcLuaMsgDock->setWidget(m_pcLuaMessageTable);
378 addDockWidget(Qt::BottomDockWidgetArea, m_pcLuaMsgDock);
379 connect(m_pcLuaMessageTable, SIGNAL(itemSelectionChanged()),
380 this, SLOT(HandleMsgTableSelection()));
381 m_pcLuaMsgDock->hide();
382 }
383
384 /****************************************/
385 /****************************************/
386
387 void CQTOpenGLLuaMainWindow::CreateLuaStateDocks() {
388 /* Variable tree dock */
389 m_pcLuaVariableDock = new QDockWidget(tr("Variables"), this);
390 m_pcLuaVariableDock->setObjectName("LuaVariableDock");
391 m_pcLuaVariableDock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
392 m_pcLuaVariableDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea);
393 m_pcLuaVariableTree = new QTreeView();
394 m_pcLuaVariableDock->setWidget(m_pcLuaVariableTree);
395 addDockWidget(Qt::LeftDockWidgetArea, m_pcLuaVariableDock);
396 m_pcLuaVariableDock->hide();
397 /* Function tree dock */
398 m_pcLuaFunctionDock = new QDockWidget(tr("Functions"), this);
399 m_pcLuaFunctionDock->setObjectName("LuaFunctionDock");
400 m_pcLuaFunctionDock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
401 m_pcLuaFunctionDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea);
402 m_pcLuaFunctionTree = new QTreeView();
403 m_pcLuaFunctionDock->setWidget(m_pcLuaFunctionTree);
404 addDockWidget(Qt::LeftDockWidgetArea, m_pcLuaFunctionDock);
405 m_pcLuaFunctionDock->hide();
406 /* Connect stuff */
407 connect(&(m_pcMainWindow->GetOpenGLWidget()), SIGNAL(EntitySelected(CEntity*)),
408 this, SLOT(HandleEntitySelection(CEntity*)));
409 connect(&(m_pcMainWindow->GetOpenGLWidget()), SIGNAL(EntityDeselected(CEntity*)),
410 this, SLOT(HandleEntityDeselection(CEntity*)));
411 }
412
413 /****************************************/
414 /****************************************/
415
416 void CQTOpenGLLuaMainWindow::CreateFileActions() {
417 QIcon cFileNewIcon;
418 cFileNewIcon.addPixmap(QPixmap(m_pcMainWindow->GetIconDir() + "/new.png"));
419 m_pcFileNewAction = new QAction(cFileNewIcon, tr("&New"), this);
420 m_pcFileNewAction->setToolTip(tr("Create a new file"));
421 m_pcFileNewAction->setStatusTip(tr("Create a new file"));
422 m_pcFileNewAction->setShortcut(QKeySequence::New);
423 connect(m_pcFileNewAction, SIGNAL(triggered()),
424 this, SLOT(New()));
425 QIcon cFileOpenIcon;
426 cFileOpenIcon.addPixmap(QPixmap(m_pcMainWindow->GetIconDir() + "/open.png"));
427 m_pcFileOpenAction = new QAction(cFileOpenIcon, tr("&Open..."), this);
428 m_pcFileOpenAction->setToolTip(tr("Open a file"));
429 m_pcFileOpenAction->setStatusTip(tr("Open a file"));
430 m_pcFileOpenAction->setShortcut(QKeySequence::Open);
431 connect(m_pcFileOpenAction, SIGNAL(triggered()),
432 this, SLOT(Open()));
433 for (int i = 0; i < MAX_RECENT_FILES; ++i) {
434 m_pcFileOpenRecentAction[i] = new QAction(this);
435 m_pcFileOpenRecentAction[i]->setVisible(false);
436 connect(m_pcFileOpenRecentAction[i], SIGNAL(triggered()),
437 this, SLOT(OpenRecentFile()));
438 }
439 QIcon cFileSaveIcon;
440 cFileSaveIcon.addPixmap(QPixmap(m_pcMainWindow->GetIconDir() + "/save.png"));
441 m_pcFileSaveAction = new QAction(cFileSaveIcon, tr("&Save"), this);
442 m_pcFileSaveAction->setToolTip(tr("Save the current file"));
443 m_pcFileSaveAction->setStatusTip(tr("Save the current file"));
444 m_pcFileSaveAction->setShortcut(QKeySequence::Save);
445 connect(m_pcFileSaveAction, SIGNAL(triggered()),
446 this, SLOT(Save()));
447 QIcon cFileSaveAsIcon;
448 cFileSaveAsIcon.addPixmap(QPixmap(m_pcMainWindow->GetIconDir() + "/saveas.png"));
449 m_pcFileSaveAsAction = new QAction(cFileSaveAsIcon, tr("S&ave as..."), this);
450 m_pcFileSaveAsAction->setToolTip(tr("Save the current file under a new name"));
451 m_pcFileSaveAsAction->setStatusTip(tr("Save the current file under a new name"));
452 m_pcFileSaveAsAction->setShortcut(QKeySequence::SaveAs);
453 connect(m_pcFileSaveAsAction, SIGNAL(triggered()),
454 this, SLOT(SaveAs()));
455 QMenu* pcMenu = menuBar()->addMenu(tr("&File"));
456 pcMenu->addAction(m_pcFileNewAction);
457 pcMenu->addSeparator();
458 pcMenu->addAction(m_pcFileOpenAction);
459 pcMenu->addSeparator();
460 pcMenu->addAction(m_pcFileSaveAction);
461 pcMenu->addAction(m_pcFileSaveAsAction);
462 m_pcFileSeparateRecentAction = pcMenu->addSeparator();
463 for (int i = 0; i < MAX_RECENT_FILES; ++i) {
464 pcMenu->addAction(m_pcFileOpenRecentAction[i]);
465 }
466 QToolBar* pcToolBar = addToolBar(tr("File"));
467 pcToolBar->setObjectName("FileToolBar");
468 pcToolBar->setIconSize(QSize(32,32));
469 pcToolBar->addAction(m_pcFileNewAction);
470 pcToolBar->addAction(m_pcFileOpenAction);
471 pcToolBar->addAction(m_pcFileSaveAction);
472 UpdateRecentFiles();
473 }
474
475 /****************************************/
476 /****************************************/
477
478 void CQTOpenGLLuaMainWindow::CreateEditActions() {
479 QIcon cEditUndoIcon;
480 cEditUndoIcon.addPixmap(QPixmap(m_pcMainWindow->GetIconDir() + "/undo.png"));
481 m_pcEditUndoAction = new QAction(cEditUndoIcon, tr("&Undo"), this);
482 m_pcEditUndoAction->setToolTip(tr("Undo last operation"));
483 m_pcEditUndoAction->setStatusTip(tr("Undo last operation"));
484 m_pcEditUndoAction->setShortcut(QKeySequence::Undo);
485 connect(m_pcEditUndoAction, SIGNAL(triggered()),
486 m_pcCodeEditor, SLOT(undo()));
487 QIcon cEditRedoIcon;
488 cEditRedoIcon.addPixmap(QPixmap(m_pcMainWindow->GetIconDir() + "/redo.png"));
489 m_pcEditRedoAction = new QAction(cEditRedoIcon, tr("&Redo"), this);
490 m_pcEditRedoAction->setToolTip(tr("Redo last operation"));
491 m_pcEditRedoAction->setStatusTip(tr("Redo last operation"));
492 m_pcEditRedoAction->setShortcut(QKeySequence::Redo);
493 connect(m_pcEditRedoAction, SIGNAL(triggered()),
494 m_pcCodeEditor, SLOT(redo()));
495 QIcon cEditCopyIcon;
496 cEditCopyIcon.addPixmap(QPixmap(m_pcMainWindow->GetIconDir() + "/copy.png"));
497 m_pcEditCopyAction = new QAction(cEditCopyIcon, tr("&Copy"), this);
498 m_pcEditCopyAction->setToolTip(tr("Copy selected text into clipboard"));
499 m_pcEditCopyAction->setStatusTip(tr("Copy selected text into clipboard"));
500 m_pcEditCopyAction->setShortcut(QKeySequence::Copy);
501 connect(m_pcEditCopyAction, SIGNAL(triggered()),
502 m_pcCodeEditor, SLOT(copy()));
503 QIcon cEditCutIcon;
504 cEditCutIcon.addPixmap(QPixmap(m_pcMainWindow->GetIconDir() + "/cut.png"));
505 m_pcEditCutAction = new QAction(cEditCutIcon, tr("&Cut"), this);
506 m_pcEditCutAction->setToolTip(tr("Move selected text into clipboard"));
507 m_pcEditCutAction->setStatusTip(tr("Move selected text into clipboard"));
508 m_pcEditCutAction->setShortcut(QKeySequence::Cut);
509 connect(m_pcEditCutAction, SIGNAL(triggered()),
510 m_pcCodeEditor, SLOT(cut()));
511 QIcon cEditPasteIcon;
512 cEditPasteIcon.addPixmap(QPixmap(m_pcMainWindow->GetIconDir() + "/paste.png"));
513 m_pcEditPasteAction = new QAction(cEditPasteIcon, tr("&Paste"), this);
514 m_pcEditPasteAction->setToolTip(tr("Paste text from clipboard"));
515 m_pcEditPasteAction->setStatusTip(tr("Paste text from clipboard"));
516 m_pcEditPasteAction->setShortcut(QKeySequence::Paste);
517 connect(m_pcEditPasteAction, SIGNAL(triggered()),
518 m_pcCodeEditor, SLOT(paste()));
519 // QIcon cEditFindIcon;
520 // cEditFindIcon.addPixmap(QPixmap(m_pcMainWindow->GetIconDir() + "/find.png"));
521 // m_pcEditFindAction = new QAction(cEditFindIcon, tr("&Find/Replace"), this);
522 // m_pcEditFindAction->setToolTip(tr("Find/replace text"));
523 // m_pcEditFindAction->setStatusTip(tr("Find/replace text"));
524 // m_pcEditFindAction->setShortcut(QKeySequence::Find);
525 // connect(m_pcEditFindAction, SIGNAL(triggered()),
526 // this, SLOT(Find()));
527 QMenu* pcMenu = menuBar()->addMenu(tr("&Edit"));
528 pcMenu->addAction(m_pcEditUndoAction);
529 pcMenu->addAction(m_pcEditRedoAction);
530 pcMenu->addSeparator();
531 pcMenu->addAction(m_pcEditCopyAction);
532 pcMenu->addAction(m_pcEditCutAction);
533 pcMenu->addAction(m_pcEditPasteAction);
534 // pcMenu->addSeparator();
535 // pcMenu->addAction(m_pcEditFindAction);
536 QToolBar* pcToolBar = addToolBar(tr("Edit"));
537 pcToolBar->setObjectName("EditToolBar");
538 pcToolBar->setIconSize(QSize(32,32));
539 pcToolBar->addAction(m_pcEditUndoAction);
540 pcToolBar->addAction(m_pcEditRedoAction);
541 pcToolBar->addSeparator();
542 pcToolBar->addAction(m_pcEditCopyAction);
543 pcToolBar->addAction(m_pcEditCutAction);
544 pcToolBar->addAction(m_pcEditPasteAction);
545 // pcToolBar->addAction(m_pcEditFindAction);
546 }
547
548 /****************************************/
549 /****************************************/
550
551 void CQTOpenGLLuaMainWindow::CreateCodeActions() {
552 QIcon cCodeExecuteIcon;
553 cCodeExecuteIcon.addPixmap(QPixmap(m_pcMainWindow->GetIconDir() + "/execute.png"));
554 m_pcCodeExecuteAction = new QAction(cCodeExecuteIcon, tr("&Execute"), this);
555 m_pcCodeExecuteAction->setToolTip(tr("Execute code"));
556 m_pcCodeExecuteAction->setStatusTip(tr("Execute code"));
557 m_pcCodeExecuteAction->setShortcut(tr("Ctrl+E"));
558 connect(m_pcCodeExecuteAction, SIGNAL(triggered()),
559 this, SLOT(Execute()));
560 QMenu* pcMenu = menuBar()->addMenu(tr("&Code"));
561 pcMenu->addAction(m_pcCodeExecuteAction);
562 QToolBar* pcToolBar = addToolBar(tr("Code"));
563 pcToolBar->setObjectName("CodeToolBar");
564 pcToolBar->setIconSize(QSize(32,32));
565 pcToolBar->addAction(m_pcCodeExecuteAction);
566 }
567
568 /****************************************/
569 /****************************************/
570
571 void CQTOpenGLLuaMainWindow::OpenFile(const QString& str_path) {
572 QFile cFile(str_path);
573 if(! cFile.open(QFile::ReadOnly | QFile::Text)) {
574 QMessageBox::warning(this, tr("ARGoS v" ARGOS_VERSION "-" ARGOS_RELEASE " - Lua Editor"),
575 tr("Cannot read file %1:\n%2.")
576 .arg(str_path)
577 .arg(cFile.errorString()));
578 return;
579 }
580 QApplication::setOverrideCursor(Qt::WaitCursor);
581 m_pcCodeEditor->setPlainText(cFile.readAll());
582 QApplication::restoreOverrideCursor();
583 SetCurrentFile(str_path);
584 statusBar()->showMessage(tr("File loaded"), 2000);
585 }
586
587 /****************************************/
588 /****************************************/
589
590 bool CQTOpenGLLuaMainWindow::SaveFile(const QString& str_path) {
591 QFile cFile(str_path);
592 if(! cFile.open(QFile::WriteOnly | QFile::Text)) {
593 QMessageBox::warning(this, tr("ARGoS v" ARGOS_VERSION "-" ARGOS_RELEASE " - Lua Editor"),
594 tr("Cannot write file %1:\n%2.")
595 .arg(str_path)
596 .arg(cFile.errorString()));
597 return false;
598 }
599 QTextStream cOut(&cFile);
600 QApplication::setOverrideCursor(Qt::WaitCursor);
601 cOut << m_pcCodeEditor->toPlainText();
602 QApplication::restoreOverrideCursor();
603 SetCurrentFile(str_path);
604 statusBar()->showMessage(tr("File saved"), 2000);
605 return true;
606 }
607
608 /****************************************/
609 /****************************************/
610
611 void CQTOpenGLLuaMainWindow::SetCurrentFile(const QString& str_path) {
612 m_strFileName = str_path;
613 QString strShownName;
614 if(m_strFileName.isEmpty()) {
615 strShownName = "untitled";
616 }
617 else {
618 strShownName = StrippedFileName(m_strFileName);
619 }
620 setWindowTitle(tr("%1[*] - ARGoS v" ARGOS_VERSION "-" ARGOS_RELEASE " - Lua Editor").arg(strShownName));
621 if(!m_strFileName.isEmpty()) {
622 m_pcCodeEditor->document()->setModified(false);
623 setWindowModified(false);
624 QSettings cSettings;
625 cSettings.beginGroup("LuaEditor");
626 QStringList listFiles = cSettings.value("recent_files").toStringList();
627 listFiles.removeAll(m_strFileName);
628 listFiles.prepend(m_strFileName);
629 while(listFiles.size() > MAX_RECENT_FILES) {
630 listFiles.removeLast();
631 }
632 cSettings.setValue("recent_files", listFiles);
633 cSettings.endGroup();
634 UpdateRecentFiles();
635 }
636 else {
637 m_pcCodeEditor->document()->setModified(true);
638 setWindowModified(true);
639 }
640 }
641
642 /****************************************/
643 /****************************************/
644
646 int nRow = 0;
647 m_pcLuaMessageTable->clearContents();
648 m_pcLuaMessageTable->setRowCount(m_vecControllers.size());
649 for(size_t i = 0; i < m_vecControllers.size(); ++i) {
650 if(! m_vecControllers[i]->IsOK()) {
651 SetMessage(nRow,
652 QString::fromStdString(m_vecControllers[i]->GetId()),
653 QString::fromStdString(m_vecControllers[i]->GetErrorMessage()));
654 ++nRow;
655 }
656 }
657 m_pcLuaMessageTable->setRowCount(nRow);
658 if(nRow > 0) {
659 m_pcMainWindow->SuspendExperiment();
660 }
661 else {
662 m_pcLuaMsgDock->hide();
663 }
664 }
665
666 /****************************************/
667 /****************************************/
668
670 QList<QTableWidgetItem*> listSel = m_pcLuaMessageTable->selectedItems();
671 if(! listSel.empty()) {
672 int nLine = listSel[1]->data(Qt::DisplayRole).toInt();
673 QTextCursor cCursor = m_pcCodeEditor->textCursor();
674 int nCurLine = cCursor.blockNumber();
675 if(nCurLine < nLine) {
676 cCursor.movePosition(QTextCursor::NextBlock,
677 QTextCursor::MoveAnchor,
678 nLine - nCurLine - 1);
679 }
680 else if(nCurLine > nLine) {
681 cCursor.movePosition(QTextCursor::PreviousBlock,
682 QTextCursor::MoveAnchor,
683 nCurLine - nLine + 1);
684 }
685 cCursor.movePosition(QTextCursor::StartOfBlock);
686 m_pcCodeEditor->setTextCursor(cCursor);
687 m_pcCodeEditor->setFocus();
688 }
689 }
690
691 /****************************************/
692 /****************************************/
693
695 CComposableEntity* pcSelectedEntity = dynamic_cast<CComposableEntity*>(pc_entity);
696 if(pcSelectedEntity != NULL) {
697 bool bFound = false;
698 m_unSelectedRobot = 0;
699 while(!bFound && m_unSelectedRobot < m_vecRobots.size()) {
700 if(m_vecRobots[m_unSelectedRobot] == pcSelectedEntity) {
701 bFound = true;
702 }
703 else {
704 ++m_unSelectedRobot;
705 }
706 }
707 if(bFound &&
708 m_vecControllers[m_unSelectedRobot]->GetLuaState() != NULL) {
710 new CQTOpenGLLuaStateTreeVariableModel(m_vecControllers[m_unSelectedRobot]->GetLuaState(),
711 false,
712 m_pcLuaVariableTree);
713 pcVarModel->Refresh();
714 connect(&(m_pcMainWindow->GetOpenGLWidget()), SIGNAL(StepDone(int)),
715 pcVarModel, SLOT(Refresh(int)));
716 connect(m_pcMainWindow, SIGNAL(ExperimentReset()),
717 pcVarModel, SLOT(Refresh()));
718 connect(pcVarModel, SIGNAL(modelReset()),
719 this, SLOT(VariableTreeChanged()),
720 Qt::QueuedConnection);
721 m_pcLuaVariableTree->setModel(pcVarModel);
722 m_pcLuaVariableTree->setRootIndex(pcVarModel->index(0, 0));
723 m_pcLuaVariableTree->expandAll();
724 m_pcLuaVariableDock->show();
726 new CQTOpenGLLuaStateTreeFunctionModel(m_vecControllers[m_unSelectedRobot]->GetLuaState(),
727 true,
728 m_pcLuaFunctionTree);
729 pcFunModel->Refresh();
730 connect(&(m_pcMainWindow->GetOpenGLWidget()), SIGNAL(StepDone(int)),
731 pcFunModel, SLOT(Refresh(int)));
732 connect(m_pcMainWindow, SIGNAL(ExperimentReset()),
733 pcFunModel, SLOT(Refresh()));
734 connect(pcFunModel, SIGNAL(modelReset()),
735 this, SLOT(FunctionTreeChanged()),
736 Qt::QueuedConnection);
737 m_pcLuaFunctionTree->setModel(pcFunModel);
738 m_pcLuaFunctionTree->setRootIndex(pcFunModel->index(0, 0));
739 m_pcLuaFunctionTree->expandAll();
740 m_pcLuaFunctionDock->show();
741 }
742 }
743 }
744
745 /****************************************/
746 /****************************************/
747
749 disconnect(&(m_pcMainWindow->GetOpenGLWidget()), SIGNAL(StepDone(int)),
750 m_pcLuaVariableTree->model(), SLOT(Refresh(int)));
751 disconnect(m_pcMainWindow, SIGNAL(ExperimentReset()),
752 m_pcLuaVariableTree->model(), SLOT(Refresh()));
753 disconnect(m_pcLuaVariableTree->model(), SIGNAL(modelReset()),
754 this, SLOT(VariableTreeChanged()));
755 m_pcLuaVariableDock->hide();
756 delete m_pcLuaVariableTree->model();
757 m_pcLuaVariableTree->setModel(NULL);
758 disconnect(&(m_pcMainWindow->GetOpenGLWidget()), SIGNAL(StepDone(int)),
759 m_pcLuaFunctionTree->model(), SLOT(Refresh(int)));
760 disconnect(m_pcMainWindow, SIGNAL(ExperimentReset()),
761 m_pcLuaFunctionTree->model(), SLOT(Refresh()));
762 disconnect(m_pcLuaFunctionTree->model(), SIGNAL(modelReset()),
763 this, SLOT(FunctionTreeChanged()));
764 m_pcLuaFunctionDock->hide();
765 delete m_pcLuaFunctionTree->model();
766 m_pcLuaFunctionTree->setModel(NULL);
767 }
768
769 /****************************************/
770 /****************************************/
771
773 m_pcLuaVariableTree->setRootIndex(m_pcLuaVariableTree->model()->index(0, 0));
774 m_pcLuaVariableTree->expandAll();
775 }
776
777 /****************************************/
778 /****************************************/
779
781 m_pcLuaFunctionTree->setRootIndex(m_pcLuaFunctionTree->model()->index(0, 0));
782 m_pcLuaFunctionTree->expandAll();
783 }
784
785 /****************************************/
786 /****************************************/
787
788 void CQTOpenGLLuaMainWindow::UpdateRecentFiles() {
789 QSettings cSettings;
790 cSettings.beginGroup("LuaEditor");
791 QStringList listFiles = cSettings.value("recent_files").toStringList();
792 int nRecentFiles = qMin(listFiles.size(), (int)MAX_RECENT_FILES);
793 for(int i = 0; i < nRecentFiles; ++i) {
794 m_pcFileOpenRecentAction[i]->setText(tr("&%1 %2").arg(i+1).arg(StrippedFileName(listFiles[i])));
795 m_pcFileOpenRecentAction[i]->setData(listFiles[i]);
796 m_pcFileOpenRecentAction[i]->setVisible(true);
797 }
798 for(int i = nRecentFiles; i < MAX_RECENT_FILES; ++i) {
799 m_pcFileOpenRecentAction[i]->setVisible(false);
800 }
801 m_pcFileSeparateRecentAction->setVisible(nRecentFiles > 0);
802 cSettings.endGroup();
803 }
804
805 /****************************************/
806 /****************************************/
807
808 void CQTOpenGLLuaMainWindow::SetMessage(int n_row,
809 const QString& str_robot_id,
810 const QString& str_message) {
811 QStringList listFields = str_message.split(":",
812#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
813 Qt::KeepEmptyParts,
814#else
815 QString::KeepEmptyParts,
816#endif
817 Qt::CaseInsensitive);
818 m_pcLuaMessageTable->setItem(
819 n_row, 0,
820 new QTableWidgetItem(str_robot_id));
821 if(listFields.size() == 3) {
822 m_pcLuaMessageTable->setItem(
823 n_row, 1,
824 new QTableWidgetItem(listFields[1]));
825 m_pcLuaMessageTable->setItem(
826 n_row, 2,
827 new QTableWidgetItem(listFields[2]));
828 }
829 else if(listFields.size() == 4) {
830 m_pcLuaMessageTable->setItem(
831 n_row, 1,
832 new QTableWidgetItem(listFields[2]));
833 m_pcLuaMessageTable->setItem(
834 n_row, 2,
835 new QTableWidgetItem(listFields[3]));
836 }
837 else {
838 m_pcLuaMessageTable->setItem(
839 n_row, 2,
840 new QTableWidgetItem(str_message));
841 }
842 m_pcLuaMsgDock->show();
843 }
844
845 /****************************************/
846 /****************************************/
847
848 QString CQTOpenGLLuaMainWindow::StrippedFileName(const QString& str_path) {
849 return QFileInfo(str_path).fileName();
850 }
851
852 /****************************************/
853 /****************************************/
854
855 void CQTOpenGLLuaMainWindow::closeEvent(QCloseEvent* pc_event) {
856 pc_event->ignore();
857 }
858
859 /****************************************/
860 /****************************************/
861
862}
The namespace containing all the ARGoS related code.
Definition ci_actuator.h:12
CARGoSLog LOGERR(std::cerr, SLogColor(ARGOS_LOG_ATTRIBUTE_BRIGHT, ARGOS_LOG_COLOR_RED))
Definition argos_log.h:180
T * any_cast(CAny *pc_any)
Performs a cast on the any type to the desired type, when the any type is passed by non-const pointer...
Definition any.h:148
Basic class for an entity that contains other entities.
The basic entity type.
Definition entity.h:90
CSpace & GetSpace() const
Returns a reference to the simulated space.
Definition simulator.h:104
static CSimulator & GetInstance()
Returns the instance to the CSimulator class.
Definition simulator.cpp:78
std::map< std::string, CAny, std::less< std::string > > TMapPerType
A map of entities indexed by type description.
Definition space.h:56
TMapPerType & GetEntitiesByType(const std::string &str_type)
Returns a map containing all the objects of a given type.
Definition space.h:226
void HandleEntityDeselection(CEntity *pc_entity)
CQTOpenGLLuaMainWindow(CQTOpenGLMainWindow *pc_parent)
void HandleEntitySelection(CEntity *pc_entity)
virtual QModelIndex index(int n_row, int n_column, const QModelIndex &c_parent=QModelIndex()) const
CQTOpenGLWidget & GetOpenGLWidget()
void SuspendExperiment()
Suspends an experiment due to an error.
const QString & GetIconDir() const
void ResumeExperiment()
Resumes a suspended experiment.