ARGoS
3
A parallel, multi-engine simulator for swarm robotics
|
00001 00006 #include "qtopengl_lua_main_window.h" 00007 #include "qtopengl_lua_editor.h" 00008 #include "qtopengl_lua_find_dialog.h" 00009 #include "qtopengl_lua_statetree_model.h" 00010 #include "qtopengl_main_window.h" 00011 #include "qtopengl_widget.h" 00012 00013 #include <argos3/core/config.h> 00014 #include <argos3/core/wrappers/lua/lua_controller.h> 00015 #include <argos3/core/simulator/simulator.h> 00016 #include <argos3/core/simulator/space/space.h> 00017 #include <argos3/core/simulator/entity/composable_entity.h> 00018 #include <argos3/core/simulator/entity/controllable_entity.h> 00019 #include <argos3/core/wrappers/lua/lua_utility.h> 00020 00021 #include <QApplication> 00022 #include <QDockWidget> 00023 #include <QFileDialog> 00024 #include <QHeaderView> 00025 #include <QMenu> 00026 #include <QMenuBar> 00027 #include <QMessageBox> 00028 #include <QProcess> 00029 #include <QSettings> 00030 #include <QStatusBar> 00031 #include <QTemporaryFile> 00032 #include <QTextStream> 00033 #include <QToolBar> 00034 #include <QTableWidget> 00035 #include <QTreeView> 00036 00037 namespace argos { 00038 00039 /****************************************/ 00040 /****************************************/ 00041 00042 static QString SCRIPT_TEMPLATE = 00043 "-- Put your global variables here\n\n\n\n" 00044 "--[[ This function is executed every time you press the 'execute'\n" 00045 " button ]]\n" 00046 "function init()\n" 00047 " -- put your code here\n" 00048 "end\n\n\n\n" 00049 "--[[ This function is executed at each time step\n" 00050 " It must contain the logic of your controller ]]\n" 00051 "function step()\n" 00052 " -- put your code here\n" 00053 "end\n\n\n\n" 00054 "--[[ This function is executed every time you press the 'reset'\n" 00055 " button in the GUI. It is supposed to restore the state\n" 00056 " of the controller to whatever it was right after init() was\n" 00057 " called. The state of sensors and actuators is reset\n" 00058 " automatically by ARGoS. ]]\n" 00059 "function reset()\n" 00060 " -- put your code here\n" 00061 "end\n\n\n\n" 00062 "--[[ This function is executed only once, when the robot is removed\n" 00063 " from the simulation ]]\n" 00064 "function destroy()\n" 00065 " -- put your code here\n" 00066 "end\n"; 00067 00068 /****************************************/ 00069 /****************************************/ 00070 00071 CQTOpenGLLuaMainWindow::CQTOpenGLLuaMainWindow(CQTOpenGLMainWindow* pc_parent) : 00072 QMainWindow(pc_parent), 00073 m_pcMainWindow(pc_parent), 00074 m_pcStatusbar(NULL), 00075 m_pcCodeEditor(NULL), 00076 m_pcFindDialog(NULL), 00077 m_pcLuaMessageTable(NULL) { 00078 /* Add a status bar */ 00079 m_pcStatusbar = new QStatusBar(this); 00080 setStatusBar(m_pcStatusbar); 00081 /* Create the Lua message table */ 00082 CreateLuaMessageTable(); 00083 /* Populate list of Lua controllers */ 00084 PopulateLuaControllers(); 00085 /* Create the Lua state docks */ 00086 CreateLuaStateDocks(); 00087 /* Create editor */ 00088 CreateCodeEditor(); 00089 /* Create actions */ 00090 CreateFileActions(); 00091 CreateEditActions(); 00092 CreateCodeActions(); 00093 /* Set empty file */ 00094 SetCurrentFile(""); 00095 /* Read settings */ 00096 ReadSettings(); 00097 } 00098 00099 /****************************************/ 00100 /****************************************/ 00101 00102 CQTOpenGLLuaMainWindow::~CQTOpenGLLuaMainWindow() { 00103 WriteSettings(); 00104 } 00105 00106 /****************************************/ 00107 /****************************************/ 00108 00109 void CQTOpenGLLuaMainWindow::New() { 00110 if(MaybeSave()) { 00111 m_pcCodeEditor->setPlainText(SCRIPT_TEMPLATE); 00112 SetCurrentFile(""); 00113 } 00114 } 00115 00116 /****************************************/ 00117 /****************************************/ 00118 00119 void CQTOpenGLLuaMainWindow::Open() { 00120 if(MaybeSave()) { 00121 QString strNewFileName = 00122 QFileDialog::getOpenFileName(this, 00123 tr("Open File"), 00124 "", 00125 "Lua Files (*.lua)"); 00126 if (!strNewFileName.isEmpty()) { 00127 OpenFile(strNewFileName); 00128 } 00129 } 00130 } 00131 00132 /****************************************/ 00133 /****************************************/ 00134 00135 void CQTOpenGLLuaMainWindow::OpenRecentFile() { 00136 QAction* pcAction = qobject_cast<QAction*>(sender()); 00137 if (pcAction) { 00138 OpenFile(pcAction->data().toString()); 00139 } 00140 } 00141 00142 /****************************************/ 00143 /****************************************/ 00144 00145 bool CQTOpenGLLuaMainWindow::Save() { 00146 if (m_strFileName.isEmpty()) { 00147 return SaveAs(); 00148 } else { 00149 return SaveFile(m_strFileName); 00150 } 00151 } 00152 00153 /****************************************/ 00154 /****************************************/ 00155 00156 bool CQTOpenGLLuaMainWindow::SaveAs() { 00157 QString strNewFileName = 00158 QFileDialog::getSaveFileName(this, 00159 tr("Save File"), 00160 "", 00161 "Lua Files (*.lua)"); 00162 if (strNewFileName.isEmpty()) 00163 return false; 00164 return SaveFile(strNewFileName); 00165 } 00166 00167 /****************************************/ 00168 /****************************************/ 00169 00170 static QString DetectLuaC() { 00171 QProcess cLuaCompiler; 00172 cLuaCompiler.start("luac", QStringList() << "-v"); 00173 /* First, try to execute luac */ 00174 if(!cLuaCompiler.waitForStarted()) { 00175 /* luac is not installed */ 00176 return ""; 00177 } 00178 /* luac is installed, but is it the right version? */ 00179 cLuaCompiler.waitForFinished(); 00180 if(QString(cLuaCompiler.readAllStandardOutput()).mid(4,3) == "5.1") { 00181 return "luac"; 00182 } 00183 cLuaCompiler.start("luac5.1", QStringList() << "-v"); 00184 if(!cLuaCompiler.waitForStarted()) { 00185 /* luac51 is not installed */ 00186 return ""; 00187 } 00188 else { 00189 /* luac51 is installed */ 00190 cLuaCompiler.waitForFinished(); 00191 return "luac5.1"; 00192 } 00193 } 00194 00195 void CQTOpenGLLuaMainWindow::Execute() { 00196 /* Save script */ 00197 Save(); 00198 /* Change cursor */ 00199 QApplication::setOverrideCursor(Qt::WaitCursor); 00200 /* Stop simulation */ 00201 m_pcMainWindow->StopSimulation(); 00202 m_pcMainWindow->SimulationCanProceed(true); 00203 /* Clear the message table */ 00204 m_pcLuaMessageTable->clearContents(); 00205 m_pcLuaMessageTable->setRowCount(1); 00206 /* Create temporary file to contain the bytecode */ 00207 QTemporaryFile cByteCode; 00208 if(! cByteCode.open()) { 00209 SetMessage(0, "ALL", "Can't create bytecode file."); 00210 m_pcMainWindow->SimulationCanProceed(false); 00211 QApplication::restoreOverrideCursor(); 00212 return; 00213 } 00214 /* 00215 * Compile script 00216 */ 00217 /* Check for luac 5.1 */ 00218 QString cLuaC = DetectLuaC(); 00219 if(cLuaC == "") { 00220 /* luac 5.1 not found, fall back to sending the script directly to robots */ 00221 for(size_t i = 0; i < m_vecControllers.size(); ++i) { 00222 m_vecControllers[i]->SetLuaScript(m_strFileName.toStdString()); 00223 } 00224 } 00225 else { 00226 QProcess cLuaCompiler; 00227 cLuaCompiler.start(cLuaC, QStringList() << "-o" << cByteCode.fileName() << m_strFileName); 00228 if(! cLuaCompiler.waitForFinished()) { 00229 SetMessage(0, "ALL", QString(cLuaCompiler.readAllStandardError())); 00230 m_pcMainWindow->SimulationCanProceed(false); 00231 QApplication::restoreOverrideCursor(); 00232 return; 00233 } 00234 if(cLuaCompiler.exitCode() != 0) { 00235 SetMessage(0, "ALL", QString(cLuaCompiler.readAllStandardError())); 00236 m_pcMainWindow->SimulationCanProceed(false); 00237 QApplication::restoreOverrideCursor(); 00238 return; 00239 } 00240 SetMessage(0, "ALL", "Compilation successful."); 00241 /* Set the script for all the robots */ 00242 for(size_t i = 0; i < m_vecControllers.size(); ++i) { 00243 m_vecControllers[i]->SetLuaScript(cByteCode.fileName().toStdString()); 00244 } 00245 } 00246 /* Update Lua state if visible */ 00247 if(m_pcLuaVariableDock->isVisible()) { 00248 static_cast<CQTOpenGLLuaStateTreeModel*>(m_pcLuaVariableTree->model())->SetLuaState( 00249 m_vecControllers[m_unSelectedRobot]->GetLuaState()); 00250 } 00251 if(m_pcLuaFunctionDock->isVisible()) { 00252 static_cast<CQTOpenGLLuaStateTreeModel*>(m_pcLuaFunctionTree->model())->SetLuaState( 00253 m_vecControllers[m_unSelectedRobot]->GetLuaState()); 00254 } 00255 QApplication::restoreOverrideCursor(); 00256 statusBar()->showMessage(tr("Execution started"), 2000); 00257 } 00258 00259 /****************************************/ 00260 /****************************************/ 00261 00262 void CQTOpenGLLuaMainWindow::Find() { 00263 if(! m_pcFindDialog) { 00264 m_pcFindDialog = new CQTOpenGLLuaFindDialog(this); 00265 } 00266 m_pcFindDialog->show(); 00267 } 00268 00269 /****************************************/ 00270 /****************************************/ 00271 00272 void CQTOpenGLLuaMainWindow::CodeModified() { 00273 setWindowModified(m_pcCodeEditor->document()->isModified()); 00274 } 00275 00276 /****************************************/ 00277 /****************************************/ 00278 00279 bool CQTOpenGLLuaMainWindow::MaybeSave() { 00280 if(m_pcCodeEditor->document()->isModified()) { 00281 QMessageBox::StandardButton tReply; 00282 tReply = QMessageBox::warning(this, tr("ARGoS v" ARGOS_VERSION "-" ARGOS_RELEASE " - Lua Editor"), 00283 tr("The document has been modified.\n" 00284 "Do you want to save your changes?"), 00285 QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); 00286 if (tReply == QMessageBox::Save) 00287 return Save(); 00288 else if (tReply == QMessageBox::Cancel) 00289 return false; 00290 } 00291 return true; 00292 } 00293 00294 /****************************************/ 00295 /****************************************/ 00296 00297 void CQTOpenGLLuaMainWindow::PopulateLuaControllers() { 00298 /* Get list of controllable entities */ 00299 CSpace& cSpace = CSimulator::GetInstance().GetSpace(); 00300 CSpace::TMapPerType& tControllables = cSpace.GetEntitiesByType("controller"); 00301 /* Go through them and keep a pointer to each Lua controller */ 00302 for(CSpace::TMapPerType::iterator it = tControllables.begin(); 00303 it != tControllables.end(); 00304 ++it) { 00305 /* Try to convert the controller into a Lua controller */ 00306 CControllableEntity* pcControllable = any_cast<CControllableEntity*>(it->second); 00307 CLuaController* pcLuaController = dynamic_cast<CLuaController*>(&(pcControllable->GetController())); 00308 if(pcLuaController) { 00309 /* Conversion succeeded, add to indices */ 00310 m_vecControllers.push_back(pcLuaController); 00311 m_vecRobots.push_back(&pcControllable->GetParent()); 00312 } 00313 else { 00314 LOGERR << "[WARNING] Entity \"" 00315 << pcControllable->GetParent().GetId() 00316 << "\" does not have a Lua controller associated" 00317 << std::endl; 00318 } 00319 } 00320 } 00321 00322 /****************************************/ 00323 /****************************************/ 00324 00325 void CQTOpenGLLuaMainWindow::ReadSettings() { 00326 QSettings cSettings; 00327 cSettings.beginGroup("LuaEditor"); 00328 resize(cSettings.value("size", QSize(640,480)).toSize()); 00329 move(cSettings.value("position", QPoint(0,0)).toPoint()); 00330 cSettings.endGroup(); 00331 } 00332 00333 /****************************************/ 00334 /****************************************/ 00335 00336 void CQTOpenGLLuaMainWindow::WriteSettings() { 00337 QSettings cSettings; 00338 cSettings.beginGroup("LuaEditor"); 00339 cSettings.setValue("size", size()); 00340 cSettings.setValue("position", pos()); 00341 cSettings.endGroup(); 00342 } 00343 00344 /****************************************/ 00345 /****************************************/ 00346 00347 void CQTOpenGLLuaMainWindow::CreateCodeEditor() { 00348 /* Create code editor */ 00349 m_pcCodeEditor = new CQTOpenGLLuaEditor(this); 00350 setCentralWidget(m_pcCodeEditor); 00351 m_pcCodeEditor->setPlainText(SCRIPT_TEMPLATE); 00352 /* Connect stuff */ 00353 connect(m_pcCodeEditor->document(), SIGNAL(contentsChanged()), 00354 this, SLOT(CodeModified())); 00355 connect(&(m_pcMainWindow->GetOpenGLWidget()), SIGNAL(StepDone(int)), 00356 this, SLOT(CheckLuaStatus(int))); 00357 } 00358 00359 /****************************************/ 00360 /****************************************/ 00361 00362 void CQTOpenGLLuaMainWindow::CreateLuaMessageTable() { 00363 m_pcLuaMsgDock = new QDockWidget(tr("Messages"), this); 00364 m_pcLuaMsgDock->setObjectName("LuaMessageDock"); 00365 m_pcLuaMsgDock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable); 00366 m_pcLuaMsgDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea); 00367 m_pcLuaMessageTable = new QTableWidget(); 00368 m_pcLuaMessageTable->setColumnCount(3); 00369 QStringList listHeaders; 00370 listHeaders << tr("Robot") 00371 << tr("Line") 00372 << tr("Message"); 00373 m_pcLuaMessageTable->setHorizontalHeaderLabels(listHeaders); 00374 m_pcLuaMessageTable->horizontalHeader()->setStretchLastSection(true); 00375 m_pcLuaMessageTable->setSelectionBehavior(QAbstractItemView::SelectRows); 00376 m_pcLuaMessageTable->setSelectionMode(QAbstractItemView::SingleSelection); 00377 m_pcLuaMsgDock->setWidget(m_pcLuaMessageTable); 00378 addDockWidget(Qt::BottomDockWidgetArea, m_pcLuaMsgDock); 00379 connect(m_pcLuaMessageTable, SIGNAL(itemSelectionChanged()), 00380 this, SLOT(HandleMsgTableSelection())); 00381 m_pcLuaMsgDock->hide(); 00382 } 00383 00384 /****************************************/ 00385 /****************************************/ 00386 00387 void CQTOpenGLLuaMainWindow::CreateLuaStateDocks() { 00388 /* Variable tree dock */ 00389 m_pcLuaVariableDock = new QDockWidget(tr("Variables"), this); 00390 m_pcLuaVariableDock->setObjectName("LuaVariableDock"); 00391 m_pcLuaVariableDock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable); 00392 m_pcLuaVariableDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea); 00393 m_pcLuaVariableTree = new QTreeView(); 00394 m_pcLuaVariableDock->setWidget(m_pcLuaVariableTree); 00395 addDockWidget(Qt::LeftDockWidgetArea, m_pcLuaVariableDock); 00396 m_pcLuaVariableDock->hide(); 00397 /* Function tree dock */ 00398 m_pcLuaFunctionDock = new QDockWidget(tr("Functions"), this); 00399 m_pcLuaFunctionDock->setObjectName("LuaFunctionDock"); 00400 m_pcLuaFunctionDock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable); 00401 m_pcLuaFunctionDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea); 00402 m_pcLuaFunctionTree = new QTreeView(); 00403 m_pcLuaFunctionDock->setWidget(m_pcLuaFunctionTree); 00404 addDockWidget(Qt::LeftDockWidgetArea, m_pcLuaFunctionDock); 00405 m_pcLuaFunctionDock->hide(); 00406 /* Connect stuff */ 00407 connect(&(m_pcMainWindow->GetOpenGLWidget()), SIGNAL(EntitySelected(size_t)), 00408 this, SLOT(HandleEntitySelection(size_t))); 00409 connect(&(m_pcMainWindow->GetOpenGLWidget()), SIGNAL(EntityDeselected(size_t)), 00410 this, SLOT(HandleEntityDeselection(size_t))); 00411 } 00412 00413 /****************************************/ 00414 /****************************************/ 00415 00416 void CQTOpenGLLuaMainWindow::CreateFileActions() { 00417 QIcon cFileNewIcon; 00418 cFileNewIcon.addPixmap(QPixmap(m_pcMainWindow->GetIconDir() + "/new.png")); 00419 m_pcFileNewAction = new QAction(cFileNewIcon, tr("&New"), this); 00420 m_pcFileNewAction->setToolTip(tr("Create a new file")); 00421 m_pcFileNewAction->setStatusTip(tr("Create a new file")); 00422 m_pcFileNewAction->setShortcut(QKeySequence::New); 00423 connect(m_pcFileNewAction, SIGNAL(triggered()), 00424 this, SLOT(New())); 00425 QIcon cFileOpenIcon; 00426 cFileOpenIcon.addPixmap(QPixmap(m_pcMainWindow->GetIconDir() + "/open.png")); 00427 m_pcFileOpenAction = new QAction(cFileOpenIcon, tr("&Open..."), this); 00428 m_pcFileOpenAction->setToolTip(tr("Open a file")); 00429 m_pcFileOpenAction->setStatusTip(tr("Open a file")); 00430 m_pcFileOpenAction->setShortcut(QKeySequence::Open); 00431 connect(m_pcFileOpenAction, SIGNAL(triggered()), 00432 this, SLOT(Open())); 00433 for (int i = 0; i < MAX_RECENT_FILES; ++i) { 00434 m_pcFileOpenRecentAction[i] = new QAction(this); 00435 m_pcFileOpenRecentAction[i]->setVisible(false); 00436 connect(m_pcFileOpenRecentAction[i], SIGNAL(triggered()), 00437 this, SLOT(OpenRecentFile())); 00438 } 00439 QIcon cFileSaveIcon; 00440 cFileSaveIcon.addPixmap(QPixmap(m_pcMainWindow->GetIconDir() + "/save.png")); 00441 m_pcFileSaveAction = new QAction(cFileSaveIcon, tr("&Save"), this); 00442 m_pcFileSaveAction->setToolTip(tr("Save the current file")); 00443 m_pcFileSaveAction->setStatusTip(tr("Save the current file")); 00444 m_pcFileSaveAction->setShortcut(QKeySequence::Save); 00445 connect(m_pcFileSaveAction, SIGNAL(triggered()), 00446 this, SLOT(Save())); 00447 QIcon cFileSaveAsIcon; 00448 cFileSaveAsIcon.addPixmap(QPixmap(m_pcMainWindow->GetIconDir() + "/saveas.png")); 00449 m_pcFileSaveAsAction = new QAction(cFileSaveAsIcon, tr("S&ave as..."), this); 00450 m_pcFileSaveAsAction->setToolTip(tr("Save the current file under a new name")); 00451 m_pcFileSaveAsAction->setStatusTip(tr("Save the current file under a new name")); 00452 m_pcFileSaveAsAction->setShortcut(QKeySequence::SaveAs); 00453 connect(m_pcFileSaveAsAction, SIGNAL(triggered()), 00454 this, SLOT(SaveAs())); 00455 QMenu* pcMenu = menuBar()->addMenu(tr("&File")); 00456 pcMenu->addAction(m_pcFileNewAction); 00457 pcMenu->addSeparator(); 00458 pcMenu->addAction(m_pcFileOpenAction); 00459 pcMenu->addSeparator(); 00460 pcMenu->addAction(m_pcFileSaveAction); 00461 pcMenu->addAction(m_pcFileSaveAsAction); 00462 m_pcFileSeparateRecentAction = pcMenu->addSeparator(); 00463 for (int i = 0; i < MAX_RECENT_FILES; ++i) { 00464 pcMenu->addAction(m_pcFileOpenRecentAction[i]); 00465 } 00466 QToolBar* pcToolBar = addToolBar(tr("File")); 00467 pcToolBar->setObjectName("FileToolBar"); 00468 pcToolBar->addAction(m_pcFileNewAction); 00469 pcToolBar->addAction(m_pcFileOpenAction); 00470 pcToolBar->addAction(m_pcFileSaveAction); 00471 UpdateRecentFiles(); 00472 } 00473 00474 /****************************************/ 00475 /****************************************/ 00476 00477 void CQTOpenGLLuaMainWindow::CreateEditActions() { 00478 QIcon cEditUndoIcon; 00479 cEditUndoIcon.addPixmap(QPixmap(m_pcMainWindow->GetIconDir() + "/undo.png")); 00480 m_pcEditUndoAction = new QAction(cEditUndoIcon, tr("&Undo"), this); 00481 m_pcEditUndoAction->setToolTip(tr("Undo last operation")); 00482 m_pcEditUndoAction->setStatusTip(tr("Undo last operation")); 00483 m_pcEditUndoAction->setShortcut(QKeySequence::Undo); 00484 connect(m_pcEditUndoAction, SIGNAL(triggered()), 00485 m_pcCodeEditor, SLOT(undo())); 00486 QIcon cEditRedoIcon; 00487 cEditRedoIcon.addPixmap(QPixmap(m_pcMainWindow->GetIconDir() + "/redo.png")); 00488 m_pcEditRedoAction = new QAction(cEditRedoIcon, tr("&Redo"), this); 00489 m_pcEditRedoAction->setToolTip(tr("Redo last operation")); 00490 m_pcEditRedoAction->setStatusTip(tr("Redo last operation")); 00491 m_pcEditRedoAction->setShortcut(QKeySequence::Redo); 00492 connect(m_pcEditRedoAction, SIGNAL(triggered()), 00493 m_pcCodeEditor, SLOT(redo())); 00494 QIcon cEditCopyIcon; 00495 cEditCopyIcon.addPixmap(QPixmap(m_pcMainWindow->GetIconDir() + "/copy.png")); 00496 m_pcEditCopyAction = new QAction(cEditCopyIcon, tr("&Copy"), this); 00497 m_pcEditCopyAction->setToolTip(tr("Copy selected text into clipboard")); 00498 m_pcEditCopyAction->setStatusTip(tr("Copy selected text into clipboard")); 00499 m_pcEditCopyAction->setShortcut(QKeySequence::Copy); 00500 connect(m_pcEditCopyAction, SIGNAL(triggered()), 00501 m_pcCodeEditor, SLOT(copy())); 00502 QIcon cEditCutIcon; 00503 cEditCutIcon.addPixmap(QPixmap(m_pcMainWindow->GetIconDir() + "/cut.png")); 00504 m_pcEditCutAction = new QAction(cEditCutIcon, tr("&Cut"), this); 00505 m_pcEditCutAction->setToolTip(tr("Move selected text into clipboard")); 00506 m_pcEditCutAction->setStatusTip(tr("Move selected text into clipboard")); 00507 m_pcEditCutAction->setShortcut(QKeySequence::Cut); 00508 connect(m_pcEditCutAction, SIGNAL(triggered()), 00509 m_pcCodeEditor, SLOT(cut())); 00510 QIcon cEditPasteIcon; 00511 cEditPasteIcon.addPixmap(QPixmap(m_pcMainWindow->GetIconDir() + "/paste.png")); 00512 m_pcEditPasteAction = new QAction(cEditPasteIcon, tr("&Paste"), this); 00513 m_pcEditPasteAction->setToolTip(tr("Paste text from clipboard")); 00514 m_pcEditPasteAction->setStatusTip(tr("Paste text from clipboard")); 00515 m_pcEditPasteAction->setShortcut(QKeySequence::Paste); 00516 connect(m_pcEditPasteAction, SIGNAL(triggered()), 00517 m_pcCodeEditor, SLOT(paste())); 00518 // QIcon cEditFindIcon; 00519 // cEditFindIcon.addPixmap(QPixmap(m_pcMainWindow->GetIconDir() + "/find.png")); 00520 // m_pcEditFindAction = new QAction(cEditFindIcon, tr("&Find/Replace"), this); 00521 // m_pcEditFindAction->setToolTip(tr("Find/replace text")); 00522 // m_pcEditFindAction->setStatusTip(tr("Find/replace text")); 00523 // m_pcEditFindAction->setShortcut(QKeySequence::Find); 00524 // connect(m_pcEditFindAction, SIGNAL(triggered()), 00525 // this, SLOT(Find())); 00526 QMenu* pcMenu = menuBar()->addMenu(tr("&Edit")); 00527 pcMenu->addAction(m_pcEditUndoAction); 00528 pcMenu->addAction(m_pcEditRedoAction); 00529 pcMenu->addSeparator(); 00530 pcMenu->addAction(m_pcEditCopyAction); 00531 pcMenu->addAction(m_pcEditCutAction); 00532 pcMenu->addAction(m_pcEditPasteAction); 00533 // pcMenu->addSeparator(); 00534 // pcMenu->addAction(m_pcEditFindAction); 00535 QToolBar* pcToolBar = addToolBar(tr("Edit")); 00536 pcToolBar->setObjectName("EditToolBar"); 00537 pcToolBar->addAction(m_pcEditUndoAction); 00538 pcToolBar->addAction(m_pcEditRedoAction); 00539 pcToolBar->addSeparator(); 00540 pcToolBar->addAction(m_pcEditCopyAction); 00541 pcToolBar->addAction(m_pcEditCutAction); 00542 pcToolBar->addAction(m_pcEditPasteAction); 00543 // pcToolBar->addAction(m_pcEditFindAction); 00544 } 00545 00546 /****************************************/ 00547 /****************************************/ 00548 00549 void CQTOpenGLLuaMainWindow::CreateCodeActions() { 00550 QIcon cCodeExecuteIcon; 00551 cCodeExecuteIcon.addPixmap(QPixmap(m_pcMainWindow->GetIconDir() + "/execute.png")); 00552 m_pcCodeExecuteAction = new QAction(cCodeExecuteIcon, tr("&Execute"), this); 00553 m_pcCodeExecuteAction->setToolTip(tr("Execute code")); 00554 m_pcCodeExecuteAction->setStatusTip(tr("Execute code")); 00555 m_pcCodeExecuteAction->setShortcut(tr("Ctrl+E")); 00556 connect(m_pcCodeExecuteAction, SIGNAL(triggered()), 00557 this, SLOT(Execute())); 00558 QMenu* pcMenu = menuBar()->addMenu(tr("&Code")); 00559 pcMenu->addAction(m_pcCodeExecuteAction); 00560 QToolBar* pcToolBar = addToolBar(tr("Code")); 00561 pcToolBar->setObjectName("CodeToolBar"); 00562 pcToolBar->addAction(m_pcCodeExecuteAction); 00563 } 00564 00565 /****************************************/ 00566 /****************************************/ 00567 00568 void CQTOpenGLLuaMainWindow::OpenFile(const QString& str_path) { 00569 QFile cFile(str_path); 00570 if(! cFile.open(QFile::ReadOnly | QFile::Text)) { 00571 QMessageBox::warning(this, tr("ARGoS v" ARGOS_VERSION "-" ARGOS_RELEASE " - Lua Editor"), 00572 tr("Cannot read file %1:\n%2.") 00573 .arg(str_path) 00574 .arg(cFile.errorString())); 00575 return; 00576 } 00577 QApplication::setOverrideCursor(Qt::WaitCursor); 00578 m_pcCodeEditor->setPlainText(cFile.readAll()); 00579 QApplication::restoreOverrideCursor(); 00580 SetCurrentFile(str_path); 00581 statusBar()->showMessage(tr("File loaded"), 2000); 00582 } 00583 00584 /****************************************/ 00585 /****************************************/ 00586 00587 bool CQTOpenGLLuaMainWindow::SaveFile(const QString& str_path) { 00588 QFile cFile(str_path); 00589 if(! cFile.open(QFile::WriteOnly | QFile::Text)) { 00590 QMessageBox::warning(this, tr("ARGoS v" ARGOS_VERSION "-" ARGOS_RELEASE " - Lua Editor"), 00591 tr("Cannot write file %1:\n%2.") 00592 .arg(str_path) 00593 .arg(cFile.errorString())); 00594 return false; 00595 } 00596 QTextStream cOut(&cFile); 00597 QApplication::setOverrideCursor(Qt::WaitCursor); 00598 cOut << m_pcCodeEditor->toPlainText(); 00599 QApplication::restoreOverrideCursor(); 00600 SetCurrentFile(str_path); 00601 statusBar()->showMessage(tr("File saved"), 2000); 00602 return true; 00603 } 00604 00605 /****************************************/ 00606 /****************************************/ 00607 00608 void CQTOpenGLLuaMainWindow::SetCurrentFile(const QString& str_path) { 00609 m_strFileName = str_path; 00610 QString strShownName; 00611 if(m_strFileName.isEmpty()) { 00612 strShownName = "untitled"; 00613 } 00614 else { 00615 strShownName = StrippedFileName(m_strFileName); 00616 } 00617 setWindowTitle(tr("%1[*] - ARGoS v" ARGOS_VERSION "-" ARGOS_RELEASE " - Lua Editor").arg(strShownName)); 00618 if(!m_strFileName.isEmpty()) { 00619 m_pcCodeEditor->document()->setModified(false); 00620 setWindowModified(false); 00621 QSettings cSettings; 00622 cSettings.beginGroup("LuaEditor"); 00623 QStringList listFiles = cSettings.value("recent_files").toStringList(); 00624 listFiles.removeAll(m_strFileName); 00625 listFiles.prepend(m_strFileName); 00626 while(listFiles.size() > MAX_RECENT_FILES) { 00627 listFiles.removeLast(); 00628 } 00629 cSettings.setValue("recent_files", listFiles); 00630 cSettings.endGroup(); 00631 UpdateRecentFiles(); 00632 } 00633 else { 00634 m_pcCodeEditor->document()->setModified(true); 00635 setWindowModified(true); 00636 } 00637 } 00638 00639 /****************************************/ 00640 /****************************************/ 00641 00642 void CQTOpenGLLuaMainWindow::CheckLuaStatus(int n_step) { 00643 int nRow = 0; 00644 m_pcLuaMessageTable->clearContents(); 00645 m_pcLuaMessageTable->setRowCount(m_vecControllers.size()); 00646 for(size_t i = 0; i < m_vecControllers.size(); ++i) { 00647 if(! m_vecControllers[i]->IsOK()) { 00648 SetMessage(nRow, 00649 QString::fromStdString(m_vecControllers[i]->GetId()), 00650 QString::fromStdString(m_vecControllers[i]->GetErrorMessage())); 00651 ++nRow; 00652 } 00653 } 00654 m_pcLuaMessageTable->setRowCount(nRow); 00655 if(nRow > 0) { 00656 m_pcMainWindow->StopSimulation(); 00657 m_pcMainWindow->SimulationCanProceed(false); 00658 } 00659 else { 00660 m_pcLuaMsgDock->hide(); 00661 } 00662 } 00663 00664 /****************************************/ 00665 /****************************************/ 00666 00667 void CQTOpenGLLuaMainWindow::HandleMsgTableSelection() { 00668 QList<QTableWidgetItem*> listSel = m_pcLuaMessageTable->selectedItems(); 00669 if(! listSel.empty()) { 00670 int nLine = listSel[1]->data(Qt::DisplayRole).toInt(); 00671 QTextCursor cCursor = m_pcCodeEditor->textCursor(); 00672 int nCurLine = cCursor.blockNumber(); 00673 if(nCurLine < nLine) { 00674 cCursor.movePosition(QTextCursor::NextBlock, 00675 QTextCursor::MoveAnchor, 00676 nLine - nCurLine - 1); 00677 } 00678 else if(nCurLine > nLine) { 00679 cCursor.movePosition(QTextCursor::PreviousBlock, 00680 QTextCursor::MoveAnchor, 00681 nCurLine - nLine + 1); 00682 } 00683 cCursor.movePosition(QTextCursor::StartOfBlock); 00684 m_pcCodeEditor->setTextCursor(cCursor); 00685 m_pcCodeEditor->setFocus(); 00686 } 00687 } 00688 00689 /****************************************/ 00690 /****************************************/ 00691 00692 void CQTOpenGLLuaMainWindow::HandleEntitySelection(size_t un_index) { 00693 CComposableEntity* pcSelectedEntity = dynamic_cast<CComposableEntity*>(CSimulator::GetInstance().GetSpace().GetRootEntityVector()[un_index]); 00694 if(pcSelectedEntity != NULL) { 00695 bool bFound = false; 00696 m_unSelectedRobot = 0; 00697 while(!bFound && m_unSelectedRobot < m_vecRobots.size()) { 00698 if(m_vecRobots[m_unSelectedRobot] == pcSelectedEntity) { 00699 bFound = true; 00700 } 00701 else { 00702 ++m_unSelectedRobot; 00703 } 00704 } 00705 if(bFound && 00706 m_vecControllers[m_unSelectedRobot]->GetLuaState() != NULL) { 00707 CQTOpenGLLuaStateTreeVariableModel* pcVarModel = 00708 new CQTOpenGLLuaStateTreeVariableModel(m_vecControllers[m_unSelectedRobot]->GetLuaState(), 00709 false, 00710 m_pcLuaVariableTree); 00711 pcVarModel->Refresh(); 00712 connect(&(m_pcMainWindow->GetOpenGLWidget()), SIGNAL(StepDone(int)), 00713 pcVarModel, SLOT(Refresh(int))); 00714 connect(m_pcMainWindow, SIGNAL(SimulationReset()), 00715 pcVarModel, SLOT(Refresh())); 00716 connect(pcVarModel, SIGNAL(modelReset()), 00717 this, SLOT(VariableTreeChanged()), 00718 Qt::QueuedConnection); 00719 m_pcLuaVariableTree->setModel(pcVarModel); 00720 m_pcLuaVariableTree->setRootIndex(pcVarModel->index(0, 0)); 00721 m_pcLuaVariableTree->expandAll(); 00722 m_pcLuaVariableDock->show(); 00723 CQTOpenGLLuaStateTreeFunctionModel* pcFunModel = 00724 new CQTOpenGLLuaStateTreeFunctionModel(m_vecControllers[m_unSelectedRobot]->GetLuaState(), 00725 true, 00726 m_pcLuaFunctionTree); 00727 pcFunModel->Refresh(); 00728 connect(&(m_pcMainWindow->GetOpenGLWidget()), SIGNAL(StepDone(int)), 00729 pcFunModel, SLOT(Refresh(int))); 00730 connect(m_pcMainWindow, SIGNAL(SimulationReset()), 00731 pcFunModel, SLOT(Refresh())); 00732 connect(pcFunModel, SIGNAL(modelReset()), 00733 this, SLOT(FunctionTreeChanged()), 00734 Qt::QueuedConnection); 00735 m_pcLuaFunctionTree->setModel(pcFunModel); 00736 m_pcLuaFunctionTree->setRootIndex(pcFunModel->index(0, 0)); 00737 m_pcLuaFunctionTree->expandAll(); 00738 m_pcLuaFunctionDock->show(); 00739 } 00740 } 00741 } 00742 00743 /****************************************/ 00744 /****************************************/ 00745 00746 void CQTOpenGLLuaMainWindow::HandleEntityDeselection(size_t) { 00747 disconnect(&(m_pcMainWindow->GetOpenGLWidget()), SIGNAL(StepDone(int)), 00748 m_pcLuaVariableTree->model(), SLOT(Refresh(int))); 00749 disconnect(m_pcMainWindow, SIGNAL(SimulationReset()), 00750 m_pcLuaVariableTree->model(), SLOT(Refresh())); 00751 disconnect(m_pcLuaVariableTree->model(), SIGNAL(modelReset()), 00752 this, SLOT(VariableTreeChanged())); 00753 m_pcLuaVariableDock->hide(); 00754 delete m_pcLuaVariableTree->model(); 00755 m_pcLuaVariableTree->setModel(NULL); 00756 disconnect(&(m_pcMainWindow->GetOpenGLWidget()), SIGNAL(StepDone(int)), 00757 m_pcLuaFunctionTree->model(), SLOT(Refresh(int))); 00758 disconnect(m_pcMainWindow, SIGNAL(SimulationReset()), 00759 m_pcLuaFunctionTree->model(), SLOT(Refresh())); 00760 disconnect(m_pcLuaFunctionTree->model(), SIGNAL(modelReset()), 00761 this, SLOT(FunctionTreeChanged())); 00762 m_pcLuaFunctionDock->hide(); 00763 delete m_pcLuaFunctionTree->model(); 00764 m_pcLuaFunctionTree->setModel(NULL); 00765 } 00766 00767 /****************************************/ 00768 /****************************************/ 00769 00770 void CQTOpenGLLuaMainWindow::VariableTreeChanged() { 00771 m_pcLuaVariableTree->setRootIndex(m_pcLuaVariableTree->model()->index(0, 0)); 00772 m_pcLuaVariableTree->expandAll(); 00773 } 00774 00775 /****************************************/ 00776 /****************************************/ 00777 00778 void CQTOpenGLLuaMainWindow::FunctionTreeChanged() { 00779 m_pcLuaFunctionTree->setRootIndex(m_pcLuaFunctionTree->model()->index(0, 0)); 00780 m_pcLuaFunctionTree->expandAll(); 00781 } 00782 00783 /****************************************/ 00784 /****************************************/ 00785 00786 void CQTOpenGLLuaMainWindow::UpdateRecentFiles() { 00787 QSettings cSettings; 00788 cSettings.beginGroup("LuaEditor"); 00789 QStringList listFiles = cSettings.value("recent_files").toStringList(); 00790 int nRecentFiles = qMin(listFiles.size(), (int)MAX_RECENT_FILES); 00791 for(int i = 0; i < nRecentFiles; ++i) { 00792 m_pcFileOpenRecentAction[i]->setText(tr("&%1 %2").arg(i+1).arg(StrippedFileName(listFiles[i]))); 00793 m_pcFileOpenRecentAction[i]->setData(listFiles[i]); 00794 m_pcFileOpenRecentAction[i]->setVisible(true); 00795 } 00796 for(int i = nRecentFiles; i < MAX_RECENT_FILES; ++i) { 00797 m_pcFileOpenRecentAction[i]->setVisible(false); 00798 } 00799 m_pcFileSeparateRecentAction->setVisible(nRecentFiles > 0); 00800 cSettings.endGroup(); 00801 } 00802 00803 /****************************************/ 00804 /****************************************/ 00805 00806 void CQTOpenGLLuaMainWindow::SetMessage(int n_row, 00807 const QString& str_robot_id, 00808 const QString& str_message) { 00809 QStringList listFields = str_message.split(":", 00810 QString::KeepEmptyParts, 00811 Qt::CaseInsensitive); 00812 m_pcLuaMessageTable->setItem( 00813 n_row, 0, 00814 new QTableWidgetItem(str_robot_id)); 00815 if(listFields.size() == 3) { 00816 m_pcLuaMessageTable->setItem( 00817 n_row, 1, 00818 new QTableWidgetItem(listFields[1])); 00819 m_pcLuaMessageTable->setItem( 00820 n_row, 2, 00821 new QTableWidgetItem(listFields[2])); 00822 } 00823 else if(listFields.size() == 4) { 00824 m_pcLuaMessageTable->setItem( 00825 n_row, 1, 00826 new QTableWidgetItem(listFields[2])); 00827 m_pcLuaMessageTable->setItem( 00828 n_row, 2, 00829 new QTableWidgetItem(listFields[3])); 00830 } 00831 else { 00832 m_pcLuaMessageTable->setItem( 00833 n_row, 2, 00834 new QTableWidgetItem(str_message)); 00835 } 00836 m_pcLuaMsgDock->show(); 00837 } 00838 00839 /****************************************/ 00840 /****************************************/ 00841 00842 QString CQTOpenGLLuaMainWindow::StrippedFileName(const QString& str_path) { 00843 return QFileInfo(str_path).fileName(); 00844 } 00845 00846 /****************************************/ 00847 /****************************************/ 00848 00849 void CQTOpenGLLuaMainWindow::closeEvent(QCloseEvent* pc_event) { 00850 pc_event->ignore(); 00851 } 00852 00853 /****************************************/ 00854 /****************************************/ 00855 00856 }