ARGoS  3
A parallel, multi-engine simulator for swarm robotics
plugins/simulator/visualizations/qt-opengl/qtopengl_main_window.cpp
Go to the documentation of this file.
00001 
00007 #include "qtopengl_widget.h"
00008 #include "qtopengl_log_stream.h"
00009 #include "qtopengl_user_functions.h"
00010 #include "qtopengl_main_window.h"
00011 
00012 #include <argos3/core/config.h>
00013 #include <argos3/core/utility/plugins/dynamic_loading.h>
00014 #include <argos3/core/utility/logging/argos_log.h>
00015 #include <argos3/core/simulator/simulator.h>
00016 
00017 #include <QtCore/QVariant>
00018 #include <QtGui/QAction>
00019 #include <QtGui/QApplication>
00020 #include <QtGui/QDockWidget>
00021 #include <QtGui/QHeaderView>
00022 #include <QtGui/QLCDNumber>
00023 #include <QtGui/QPushButton>
00024 #include <QtGui/QSpinBox>
00025 #include <QtGui/QDoubleSpinBox>
00026 #include <QtGui/QStatusBar>
00027 #include <QtGui/QWidget>
00028 #include <QLabel>
00029 #include <QCloseEvent>
00030 #include <QMessageBox>
00031 #include <QDir>
00032 #include <QFile>
00033 #include <QTextStream>
00034 #include <QToolBar>
00035 #include <QLayout>
00036 #include <QMenuBar>
00037 #include <QSettings>
00038 
00039 #include <cstdio>
00040 
00041 namespace argos {
00042 
00043    /****************************************/
00044    /****************************************/
00045 
00046    class CQTOpenGLLayout : public QLayout {
00047 
00048    public:
00049 
00050       CQTOpenGLLayout() :
00051          m_pcQTOpenGLItem(NULL) {
00052          setContentsMargins(0, 0, 0, 0);
00053       }
00054 
00055       virtual ~CQTOpenGLLayout() {
00056          if(m_pcQTOpenGLItem != NULL) {
00057             delete m_pcQTOpenGLItem;
00058          }
00059       }
00060 
00061       virtual void addItem(QLayoutItem* item) {
00062          if(m_pcQTOpenGLItem != NULL) {
00063             delete m_pcQTOpenGLItem;
00064          }
00065          m_pcQTOpenGLItem = item;
00066       }
00067       virtual int count() const {
00068          return (m_pcQTOpenGLItem != NULL) ? 1 : 0;
00069       }
00070 
00071       virtual QLayoutItem* itemAt(int index) const {
00072          return (index == 0) ? m_pcQTOpenGLItem : NULL;
00073       }
00074 
00075       virtual QLayoutItem* takeAt(int index) {
00076          if(index == 0) {
00077             QLayoutItem* pcRetVal = m_pcQTOpenGLItem;
00078             m_pcQTOpenGLItem = NULL;
00079             return pcRetVal;
00080          }
00081          else {
00082             return NULL;
00083          }
00084       }
00085 
00086       virtual QSize minimumSize () const {
00087          return QSize(320,240);
00088       }
00089 
00090       virtual QSize sizeHint () const {
00091          return QSize(640,480);
00092       }
00093 
00094       virtual void setGeometry(const QRect& r) {
00095          /* Set the layout geometry */
00096          QLayout::setGeometry(r);
00097          if(m_pcQTOpenGLItem != NULL) {
00098             /* Calculate the candidate sizes for the QTOpenGL widget */
00099             /* One is height-driven */
00100             QRect cCandidate1(r.x(), r.y(), (r.height() * 4) / 3, r.height());
00101             /* The other is width-driven */
00102             QRect cCandidate2(r.x(), r.y(), r.width(), (r.width() * 3) / 4);
00103             /* Pick the one that fits the rectangle better */
00104             if(r.contains(cCandidate1)) {
00105                /* Horizontal padding needed */
00106                int nPadding = (r.width() - cCandidate1.width()) / 2;
00107                cCandidate1.translate(nPadding, 0);
00108                m_pcQTOpenGLItem->setGeometry(cCandidate1);
00109             }
00110             else {
00111                /* Vertical padding needed */
00112                int nPadding = (r.height() - cCandidate2.height()) / 2;
00113                cCandidate2.translate(0, nPadding);
00114                m_pcQTOpenGLItem->setGeometry(cCandidate2);
00115             }
00116          }
00117       }
00118 
00119    private:
00120 
00121       QLayoutItem* m_pcQTOpenGLItem;
00122 
00123    };
00124 
00125    /****************************************/
00126    /****************************************/
00127 
00128    CQTOpenGLMainWindow::CQTOpenGLMainWindow(TConfigurationNode& t_tree) :
00129       m_pcUserFunctions(NULL) {
00130       /* Main window settings */
00131       std::string strTitle;
00132       GetNodeAttributeOrDefault<std::string>(t_tree, "title", strTitle, "ARGoS v" ARGOS_VERSION "-" ARGOS_RELEASE);
00133       setWindowTitle(tr(strTitle.c_str()));
00134       /* Restore settings, if any */
00135       ReadSettingsPreCreation();
00136       /* Add a status bar */
00137       m_pcStatusbar = new QStatusBar(this);
00138       setStatusBar(m_pcStatusbar);
00139       /* Create actions */
00140       CreateSimulationActions();
00141       CreateCameraActions();
00142       // CreatePOVRayActions();
00143       CreateHelpActions();
00144       /* Create the central widget */
00145       CreateOpenGLWidget(t_tree);
00146       /* Create menus */
00147       CreateSimulationMenu();
00148       CreateCameraMenu();
00149       // CreatePOVRayMenu();
00150       CreateHelpMenu();
00151       /* Create toolbars */
00152       CreateSimulationToolBar();
00153       CreateCameraToolBar();
00154       /* Create the message dock window */
00155       CreateLogMessageDock();
00156       /* Restore settings, if any */
00157       ReadSettingsPostCreation();
00158       /* Creates the signal/slot connections */
00159       CreateConnections();
00160    }
00161 
00162    /****************************************/
00163    /****************************************/
00164 
00165    CQTOpenGLMainWindow::~CQTOpenGLMainWindow() {
00166       delete m_pcUserFunctions;
00167       delete m_pcLogStream;
00168       delete m_pcLogErrStream;
00169       if(m_bWasLogColored) {
00170          LOG.EnableColoredOutput();
00171          LOGERR.EnableColoredOutput();
00172       }
00173    }
00174 
00175    /****************************************/
00176    /****************************************/
00177 
00178    void CQTOpenGLMainWindow::ReadSettingsPreCreation() {
00179       QSettings cSettings;
00180       cSettings.beginGroup("MainWindow");
00181       resize(cSettings.value("size", QSize(640,480)).toSize());
00182       move(cSettings.value("position", QPoint(0,0)).toPoint());
00183       if(cSettings.contains("icon_dir")) {
00184          m_strIconDir = cSettings.value("icon_dir").toString();
00185          if(m_strIconDir.at(m_strIconDir.length()-1) != '/') {
00186             m_strIconDir.append("/");
00187          }
00188       }
00189       else {
00190          m_strIconDir = QString::fromStdString(CSimulator::GetInstance().GetInstallationDirectory());
00191          m_strIconDir += "/include/argos3/plugins/simulator/visualizations/qt-opengl/icons/";
00192       }
00193       if(cSettings.contains("texture_dir")) {
00194          m_strTextureDir = cSettings.value("texture_dir").toString();
00195          if(m_strTextureDir.at(m_strIconDir.length()-1) != '/') {
00196             m_strTextureDir.append("/");
00197          }
00198       }
00199       else {
00200          m_strTextureDir = QString::fromStdString(CSimulator::GetInstance().GetInstallationDirectory());
00201          m_strTextureDir += "/include/argos3/plugins/simulator/visualizations/qt-opengl/textures/";
00202       }
00203       cSettings.endGroup();
00204    }
00205 
00206    /****************************************/
00207    /****************************************/
00208 
00209    void CQTOpenGLMainWindow::ReadSettingsPostCreation() {
00210       QSettings cSettings;
00211       cSettings.beginGroup("MainWindow");
00212       restoreState(cSettings.value("docks").toByteArray());
00213       cSettings.endGroup();
00214    }
00215 
00216    /****************************************/
00217    /****************************************/
00218 
00219    void CQTOpenGLMainWindow::WriteSettings() {
00220       QSettings cSettings;
00221       cSettings.beginGroup("MainWindow");
00222       cSettings.setValue("docks", saveState());
00223       cSettings.setValue("size", size());
00224       cSettings.setValue("position", pos());
00225       cSettings.setValue("anti-aliasing", m_pcToggleAntiAliasingAction->isChecked());
00226       cSettings.setValue("icon_dir", m_strIconDir);
00227       cSettings.setValue("texture_dir", m_strTextureDir);
00228       cSettings.endGroup();
00229    }
00230 
00231    /****************************************/
00232    /****************************************/
00233 
00234    void CQTOpenGLMainWindow::CreateSimulationActions() {
00235       /* Add the play button */
00236       QIcon cPlayIcon;
00237       cPlayIcon.addPixmap(QPixmap(m_strIconDir + "/play.png"));
00238       m_pcPlayAction = new QAction(cPlayIcon, tr("&Play"), this);
00239       m_pcPlayAction->setToolTip(tr("Play/pause simulation"));
00240       m_pcPlayAction->setStatusTip(tr("Play/pause simulation"));
00241       m_pcPlayAction->setCheckable(true);
00242       m_pcPlayAction->setShortcut(Qt::Key_P);
00243       /* Add the pause/step button */
00244       QIcon cStepIcon;
00245       cStepIcon.addPixmap(QPixmap(m_strIconDir + "/step.png"));
00246       m_pcStepAction = new QAction(cStepIcon, tr("&Step"), this);
00247       m_pcStepAction->setToolTip(tr("Step simulation"));
00248       m_pcStepAction->setStatusTip(tr("Step simulation"));
00249       m_pcStepAction->setShortcut(Qt::Key_S);
00250       /* Add the fast forward button */
00251       QIcon cFastForwardIcon;
00252       cFastForwardIcon.addPixmap(QPixmap(m_strIconDir + "/fast_forward.png"));
00253       m_pcFastForwardAction = new QAction(cFastForwardIcon, tr("&Fast Forward"), this);
00254       m_pcFastForwardAction->setToolTip(tr("Fast forward simulation"));
00255       m_pcFastForwardAction->setStatusTip(tr("Fast forward simulation"));
00256       m_pcFastForwardAction->setCheckable(true);
00257       m_pcFastForwardAction->setShortcut(Qt::Key_F);
00258       /* Add the reset button */
00259       QIcon cResetIcon;
00260       cResetIcon.addPixmap(QPixmap(m_strIconDir + "/reset.png"));
00261       m_pcResetAction = new QAction(cResetIcon, tr("&Reset"), this);
00262       m_pcResetAction->setToolTip(tr("Reset simulation"));
00263       m_pcResetAction->setStatusTip(tr("Reset simulation"));
00264       m_pcResetAction->setShortcut(Qt::Key_R);
00265       /* Add the capture button */
00266       QIcon cCaptureIcon;
00267       cCaptureIcon.addPixmap(QPixmap(m_strIconDir + "/record.png"));
00268       m_pcCaptureAction = new QAction(cCaptureIcon, tr("&Capture"), this);
00269       m_pcCaptureAction->setToolTip(tr("Capture frames"));
00270       m_pcCaptureAction->setStatusTip(tr("Capture frames"));
00271       m_pcCaptureAction->setCheckable(true);
00272       m_pcCaptureAction->setShortcut(Qt::Key_C);
00273       /* Add the quit button */
00274       m_pcQuitAction = new QAction(tr("&Quit"), this);
00275       m_pcQuitAction->setStatusTip(tr("Quit the simulator"));
00276       m_pcQuitAction->setShortcut(Qt::Key_Q);
00277    }
00278 
00279    /****************************************/
00280    /****************************************/
00281 
00282    void CQTOpenGLMainWindow::CreateCameraActions() {
00283       /* Add the switch camera buttons */
00284       m_pcSwitchCameraActionGroup = new QActionGroup(this);
00285       QIcon cCameraIcon;
00286       cCameraIcon.addPixmap(QPixmap(m_strIconDir + "/camera.png"));
00287       for(UInt32 i = 0; i < 12; ++i) {
00288          QAction* pcAction = new QAction(cCameraIcon, tr(QString("Camera %1").arg(i+1).toAscii().data()), m_pcSwitchCameraActionGroup);
00289          pcAction->setToolTip(tr(QString("Switch to camera %1").arg(i+1).toAscii().data()));
00290          pcAction->setStatusTip(tr(QString("Switch to camera %1").arg(i+1).toAscii().data()));
00291          pcAction->setCheckable(true);
00292          pcAction->setShortcut(Qt::Key_F1 + i);
00293          pcAction->setData(i);
00294          m_pcSwitchCameraActions.push_back(pcAction);
00295       }
00296       m_pcSwitchCameraActions.first()->setChecked(true);
00297       /* Add the toogle anti-aliasing button */
00298       m_pcToggleAntiAliasingAction = new QAction(tr("&Anti-alias"), this);
00299       m_pcToggleAntiAliasingAction->setStatusTip(tr("Toogle anti-aliasing in OpenGL rendering"));
00300       m_pcToggleAntiAliasingAction->setCheckable(true);
00301       /* Add the show camera XML button */
00302       m_pcShowCameraXMLAction = new QAction(tr("&Show XML..."), this);
00303       m_pcShowCameraXMLAction->setStatusTip(tr("Show XML configuration for all cameras"));
00304    }
00305 
00306    /****************************************/
00307    /****************************************/
00308 
00309    // void CQTOpenGLMainWindow::CreatePOVRayActions() {
00310    //    /* Add the POVRay XML button */
00311    //    QIcon cPOVRayXMLIcon;
00312    //    m_pcPOVRayXMLAction = new QAction(cPOVRayXMLIcon, tr("&Edit XML"), this);
00313    //    m_pcPOVRayXMLAction->setToolTip(tr("Edit POV-Ray XML configuration"));
00314    //    m_pcPOVRayXMLAction->setStatusTip(tr("Edit POV-Ray XML configuration"));
00315    //    /* Add the POVRay Preview button */
00316    //    QIcon cPOVRayPreviewIcon;
00317    //    m_pcPOVRayPreviewAction = new QAction(cPOVRayPreviewIcon, tr("&Preview"), this);
00318    //    m_pcPOVRayPreviewAction->setToolTip(tr("Preview POV-Ray rendering of this scene"));
00319    //    m_pcPOVRayPreviewAction->setStatusTip(tr("Preview POV-Ray rendering of this scene"));
00320    // }
00321 
00322    /****************************************/
00323    /****************************************/
00324 
00325    void CQTOpenGLMainWindow::CreateHelpActions() {
00326       /* Add the 'about qt' button */
00327       m_pcAboutQTAction = new QAction(tr("About &Qt"), this);
00328       m_pcAboutQTAction->setStatusTip(tr("Show the Qt library's About box"));
00329    }
00330 
00331    /****************************************/
00332    /****************************************/
00333 
00334    void CQTOpenGLMainWindow::CreateSimulationToolBar() {
00335       m_pcSimulationToolBar = addToolBar(tr("Simulation"));
00336       m_pcSimulationToolBar->setObjectName("SimulationToolBar");
00337       m_pcCurrentStepLCD = new QLCDNumber(m_pcSimulationToolBar);
00338       m_pcCurrentStepLCD->setToolTip(tr("Current step"));
00339       m_pcCurrentStepLCD->setNumDigits(6);
00340       m_pcCurrentStepLCD->setSegmentStyle(QLCDNumber::Flat);
00341       m_pcSimulationToolBar->addWidget(m_pcCurrentStepLCD);
00342       m_pcSimulationToolBar->addSeparator();
00343       m_pcSimulationToolBar->addAction(m_pcPlayAction);
00344       m_pcSimulationToolBar->addAction(m_pcStepAction);
00345       m_pcSimulationToolBar->addAction(m_pcFastForwardAction);
00346       m_pcDrawFrameEvery = new QSpinBox(m_pcSimulationToolBar);
00347       m_pcDrawFrameEvery->setToolTip(tr("Draw frame every X steps when in fast-forward"));
00348       m_pcDrawFrameEvery->setMinimum(1);
00349       m_pcDrawFrameEvery->setMaximum(999);
00350       m_pcDrawFrameEvery->setValue(1);
00351       m_pcSimulationToolBar->addWidget(m_pcDrawFrameEvery);
00352       m_pcSimulationToolBar->addSeparator();
00353       m_pcSimulationToolBar->addAction(m_pcResetAction);
00354       m_pcSimulationToolBar->addAction(m_pcCaptureAction);
00355    }
00356 
00357    /****************************************/
00358    /****************************************/
00359 
00360    void CQTOpenGLMainWindow::CreateSimulationMenu() {
00361       m_pcSimulationMenu = menuBar()->addMenu(tr("&Simulation"));
00362       m_pcSimulationMenu->addAction(m_pcPlayAction);
00363       m_pcSimulationMenu->addAction(m_pcStepAction);
00364       m_pcSimulationMenu->addAction(m_pcFastForwardAction);
00365       m_pcSimulationMenu->addSeparator();
00366       m_pcSimulationMenu->addAction(m_pcResetAction);
00367       m_pcSimulationMenu->addAction(m_pcCaptureAction);
00368       m_pcSimulationMenu->addSeparator();
00369       m_pcSimulationMenu->addAction(m_pcQuitAction);
00370    }
00371 
00372    /****************************************/
00373    /****************************************/
00374 
00375    void CQTOpenGLMainWindow::CreateCameraToolBar() {
00376       m_pcCameraToolBar = new QToolBar(tr("Camera"));
00377       m_pcCameraToolBar->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea | Qt::BottomToolBarArea);
00378       m_pcCameraToolBar->setObjectName("CameraToolBar");
00379       m_pcCameraToolBar->addActions(m_pcSwitchCameraActions);
00380       m_pcCameraToolBar->addSeparator();
00381       m_pcFocalLength = new QDoubleSpinBox(m_pcCameraToolBar);
00382       m_pcFocalLength->setToolTip(tr("Set the focal length of the current camera"));
00383       m_pcFocalLength->setSuffix("mm");
00384       m_pcFocalLength->setDecimals(1);
00385       m_pcFocalLength->setSingleStep(1.0f);
00386       m_pcFocalLength->setRange(1.0f, 999.0f);
00387       m_pcFocalLength->setValue(m_pcOpenGLWidget->GetCamera().GetSetting(0).LensFocalLength * 1000.0f);
00388       m_pcCameraToolBar->addWidget(m_pcFocalLength);
00389       addToolBar(Qt::LeftToolBarArea, m_pcCameraToolBar);
00390    }
00391 
00392    /****************************************/
00393    /****************************************/
00394 
00395    void CQTOpenGLMainWindow::CreateCameraMenu() {
00396       m_pcCameraMenu = menuBar()->addMenu(tr("&Camera"));
00397       m_pcCameraMenu->addActions(m_pcSwitchCameraActions);
00398       m_pcCameraMenu->addAction(m_pcShowCameraXMLAction);
00399       m_pcCameraMenu->addSeparator();
00400       m_pcCameraMenu->addAction(m_pcToggleAntiAliasingAction);
00401    }
00402 
00403    /****************************************/
00404    /****************************************/
00405 
00406    // void CQTOpenGLMainWindow::CreatePOVRayMenu() {
00407    //    m_pcPOVRayMenu = menuBar()->addMenu(tr("&POVRay"));
00408    //    m_pcPOVRayMenu->addAction(m_pcPOVRayPreviewAction);
00409    //    m_pcPOVRayMenu->addAction(m_pcPOVRayXMLAction);
00410    // }
00411 
00412    /****************************************/
00413    /****************************************/
00414 
00415    void CQTOpenGLMainWindow::CreateHelpMenu() {
00416       m_pcHelpMenu = menuBar()->addMenu(tr("&?"));
00417       m_pcHelpMenu->addAction(m_pcAboutQTAction);
00418    }
00419 
00420    /****************************************/
00421    /****************************************/
00422 
00423    void CQTOpenGLMainWindow::CreateOpenGLWidget(TConfigurationNode& t_tree) {
00424       /* Create user functions */
00425       m_pcUserFunctions = CreateUserFunctions(t_tree);
00426       /* Initialize OpenGL settings */
00427       QGLFormat cGLFormat;
00428       cGLFormat.setSampleBuffers(true);
00429       /* Create the widget */
00430       QWidget* pcPlaceHolder = new QWidget(this);
00431       m_pcOpenGLWidget = new CQTOpenGLWidget(cGLFormat, pcPlaceHolder, this, *m_pcUserFunctions);
00432       m_pcOpenGLWidget->setCursor(QCursor(Qt::OpenHandCursor));
00433       m_pcOpenGLWidget->GetCamera().Init(t_tree);
00434       m_pcOpenGLWidget->GetFrameGrabData().Init(t_tree);
00435       if(cGLFormat.sampleBuffers()) {
00436          /* Get OpenGL settings */
00437          QSettings cSettings;
00438          bool bAntiAliasing;
00439          cSettings.beginGroup("MainWindow");
00440          if(cSettings.contains("anti-aliasing")) {
00441             bAntiAliasing = cSettings.value("anti-aliasing").toBool();
00442          }
00443          else {
00444             bAntiAliasing = true;
00445          }
00446          cSettings.endGroup();
00447          m_pcToggleAntiAliasingAction->setChecked(bAntiAliasing);
00448          m_pcOpenGLWidget->SetAntiAliasing(bAntiAliasing);
00449       }
00450       else {
00451          m_pcToggleAntiAliasingAction->setChecked(false);
00452          m_pcToggleAntiAliasingAction->setEnabled(false);
00453       }
00454       /* Invert mouse controls? */
00455       bool bInvertMouse;
00456       GetNodeAttributeOrDefault(t_tree, "invert_mouse", bInvertMouse, false);
00457       m_pcOpenGLWidget->SetInvertMouse(bInvertMouse);
00458       /* Set the window as the central widget */
00459       CQTOpenGLLayout* pcQTOpenGLLayout = new CQTOpenGLLayout();
00460       pcQTOpenGLLayout->addWidget(m_pcOpenGLWidget);
00461       pcPlaceHolder->setLayout(pcQTOpenGLLayout);
00462       setCentralWidget(pcPlaceHolder);
00463    }
00464 
00465    /****************************************/
00466    /****************************************/
00467 
00468    void CQTOpenGLMainWindow::CreateLogMessageDock() {
00469       /* Store the log color flag to be able to restore at exit */
00470       m_bWasLogColored = LOG.IsColoredOutput();
00471       /* Create a dockable window */
00472       m_pcLogDock = new QDockWidget(tr("Log"), this);
00473       m_pcLogDock->setObjectName("LogDockWindow");
00474       m_pcLogDock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
00475       m_pcLogDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea);
00476       /* Create a textual window to be used as a buffer */
00477       m_pcDockLogBuffer = new QTextEdit();
00478       m_pcDockLogBuffer->setReadOnly(true);
00479       LOG.Flush(); /* Write all the pending stuff */
00480       LOG.DisableColoredOutput(); /* Colors are not necessary */
00481       m_pcDockLogBuffer->append("<b>[t=0]</b> Log started."); /* Write something in the buffer */
00482       /* Redirect stdout to the buffer */
00483       m_pcLogStream = new CQTOpenGLLogStream(LOG.GetStream(), m_pcDockLogBuffer);
00484       /* Add the dockable window to the main widget */
00485       m_pcLogDock->setWidget(m_pcDockLogBuffer);
00486       addDockWidget(Qt::RightDockWidgetArea, m_pcLogDock);
00487       /* Create a dockable window */
00488       m_pcLogErrDock = new QDockWidget(tr("LogErr"), this);
00489       m_pcLogErrDock->setObjectName("LogErrDockWindow");
00490       m_pcLogErrDock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
00491       m_pcLogErrDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea);
00492       /* Create a textual window to be used as a buffer */
00493       m_pcDockLogErrBuffer = new QTextEdit();
00494       m_pcDockLogErrBuffer->setReadOnly(true);
00495       LOGERR.Flush(); /* Write all the pending stuff */
00496       LOGERR.DisableColoredOutput(); /* Colors are not necessary */
00497       m_pcDockLogErrBuffer->append("<b>[t=0]</b> LogErr started."); /* Write something in the buffer */
00498       /* Redirect stderr to the buffer */
00499       m_pcLogErrStream = new CQTOpenGLLogStream(LOGERR.GetStream(), m_pcDockLogErrBuffer);
00500       m_pcLogErrDock->setWidget(m_pcDockLogErrBuffer);
00501       /* Add the dockable window to the main widget */
00502       addDockWidget(Qt::RightDockWidgetArea, m_pcLogErrDock);
00503 
00504    }
00505 
00506    /****************************************/
00507    /****************************************/
00508 
00509    void CQTOpenGLMainWindow::CreateConnections() {
00510       /* Play/pause button pressed */
00511       connect(m_pcPlayAction, SIGNAL(triggered(bool)),
00512               m_pcOpenGLWidget, SLOT(PlayPauseSimulation(bool)));
00513       /* Step button pressed */
00514       connect(m_pcStepAction, SIGNAL(triggered()),
00515               m_pcOpenGLWidget, SLOT(StepSimulation()));
00516       /* Fast forward button pressed */
00517       connect(m_pcFastForwardAction, SIGNAL(triggered(bool)),
00518               m_pcOpenGLWidget, SLOT(FastForwardPauseSimulation(bool)));
00519       /* Reset button pressed */
00520       connect(m_pcResetAction, SIGNAL(triggered()),
00521               m_pcOpenGLWidget, SLOT(ResetSimulation()));
00522       connect(m_pcResetAction, SIGNAL(triggered()),
00523               this, SLOT(ResetSimulation()));
00524       /* Capture button toggled */
00525       connect(m_pcCaptureAction, SIGNAL(triggered(bool)),
00526               m_pcOpenGLWidget, SLOT(SetGrabFrame(bool)));
00527       // /* POV-Ray XML button pressed */
00528       // connect(m_pcPOVRayXMLAction, SIGNAL(triggered()),
00529       //         this, SLOT(POVRaySceneXMLPopUp()));
00530       // /* POV-Ray XML button pressed */
00531       // connect(m_pcPOVRayPreviewAction, SIGNAL(triggered()),
00532       //         this, SLOT(POVRayScenePreview()));
00533       /* 'Draw frame every' spin box value changed */
00534       connect(m_pcDrawFrameEvery, SIGNAL(valueChanged(int)),
00535               m_pcOpenGLWidget, SLOT(SetDrawFrameEvery(int)));
00536       /* A simulation step has been completed */
00537       connect(m_pcOpenGLWidget, SIGNAL(StepDone(int)),
00538               m_pcCurrentStepLCD, SLOT(display(int)));
00539       /* The simulation has been completed */
00540       connect(m_pcOpenGLWidget, SIGNAL(SimulationDone()),
00541               this, SLOT(SimulationDone()));
00542       /* Toggle antialiasing */
00543       connect(m_pcToggleAntiAliasingAction, SIGNAL(triggered(bool)),
00544               m_pcOpenGLWidget, SLOT(SetAntiAliasing(bool)));
00545       /* Quit the simulator */
00546       connect(m_pcQuitAction, SIGNAL(triggered()),
00547               qApp, SLOT(quit()));
00548       /* Quit the simulator */
00549       connect(m_pcAboutQTAction, SIGNAL(triggered()),
00550               qApp, SLOT(aboutQt()));
00551       /* Toggle the camera */
00552       connect(m_pcSwitchCameraActionGroup, SIGNAL(triggered(QAction*)),
00553               this, SLOT(SwitchCamera(QAction*)));
00554       connect(this, SIGNAL(CameraSwitched(int)),
00555               m_pcOpenGLWidget, SLOT(SetCamera(int)));
00556       /* Camera focal length */
00557       connect(m_pcFocalLength, SIGNAL(valueChanged(double)),
00558               m_pcOpenGLWidget, SLOT(SetCameraFocalLength(double)));
00559       /* POV-Ray XML button pressed */
00560       connect(m_pcShowCameraXMLAction, SIGNAL(triggered()),
00561               this, SLOT(CameraXMLPopUp()));
00562    }
00563 
00564    /****************************************/
00565    /****************************************/
00566 
00567    CQTOpenGLUserFunctions* CQTOpenGLMainWindow::CreateUserFunctions(TConfigurationNode& t_tree) {
00568       /* Parse XML for user functions */
00569       if(NodeExists(t_tree, "user_functions")) {
00570          /* Use the passed user functions */
00571          /* Get data from XML */
00572          TConfigurationNode tNode = GetNode(t_tree, "user_functions");
00573          std::string strLabel, strLibrary;
00574          GetNodeAttribute(tNode, "label", strLabel);
00575          GetNodeAttributeOrDefault(tNode, "library", strLibrary, strLibrary);
00576          try {
00577             /* Load the library */
00578             if(strLibrary != "") {
00579                CDynamicLoading::LoadLibrary(strLibrary);
00580             }
00581             /* Create the user functions */
00582             return CFactory<CQTOpenGLUserFunctions>::New(strLabel);
00583          }
00584          catch(CARGoSException& ex) {
00585             THROW_ARGOSEXCEPTION_NESTED("Failed opening QTOpenGL user function library", ex);
00586          }
00587       }
00588       else {
00589          /* Use standard (empty) user functions */
00590          return new CQTOpenGLUserFunctions;
00591       }
00592    }
00593 
00594    /****************************************/
00595    /****************************************/
00596 
00597    void CQTOpenGLMainWindow::closeEvent(QCloseEvent* pc_event) {
00598       WriteSettings();
00599       pc_event->accept();
00600    }
00601 
00602    /****************************************/
00603    /****************************************/
00604 
00605    void CQTOpenGLMainWindow::StopSimulation() {
00606       m_pcOpenGLWidget->StopSimulation();
00607    }
00608 
00609    /****************************************/
00610    /****************************************/
00611 
00612    void CQTOpenGLMainWindow::SimulationCanProceed(bool b_allowed) {
00613       if(b_allowed) {
00614          m_pcPlayAction->setEnabled(true);
00615          m_pcStepAction->setEnabled(true);
00616          m_pcFastForwardAction->setEnabled(true);
00617          m_pcCaptureAction->setEnabled(true);
00618       }
00619       else {
00620          StopSimulation();
00621          m_pcPlayAction->setChecked(false);
00622          m_pcPlayAction->setEnabled(false);
00623          m_pcStepAction->setEnabled(false);
00624          m_pcFastForwardAction->setChecked(false);
00625          m_pcFastForwardAction->setEnabled(false);
00626          m_pcCaptureAction->setEnabled(false);
00627       }
00628    }
00629 
00630    /****************************************/
00631    /****************************************/
00632 
00633    void CQTOpenGLMainWindow::SimulationDone() {
00634       m_pcPlayAction->setChecked(false);
00635       m_pcPlayAction->setEnabled(false);
00636       m_pcStepAction->setEnabled(false);
00637       m_pcFastForwardAction->setChecked(false);
00638       m_pcFastForwardAction->setEnabled(false);
00639       m_pcCaptureAction->setEnabled(false);
00640    }
00641 
00642    /****************************************/
00643    /****************************************/
00644 
00645    void CQTOpenGLMainWindow::ResetSimulation() {
00646       m_pcPlayAction->setChecked(false);
00647       m_pcPlayAction->setEnabled(true);
00648       m_pcStepAction->setEnabled(true);
00649       m_pcFastForwardAction->setChecked(false);
00650       m_pcFastForwardAction->setEnabled(true);
00651       m_pcCaptureAction->setEnabled(true);
00652       m_pcCurrentStepLCD->display(0);
00653       m_pcDockLogBuffer->setHtml("<b>[t=0]</b> Log restarted.");
00654       m_pcDockLogErrBuffer->setHtml("<b>[t=0]</b> LogErr restarted.");
00655       emit SimulationReset();
00656    }
00657 
00658    /****************************************/
00659    /****************************************/
00660 
00661    void CQTOpenGLMainWindow::CameraXMLPopUp() {
00662       /* Set the text window up */
00663       QTextEdit* pcXMLOutput = new QTextEdit();
00664       /* Calculate the geometry of the window so that it's 1/4 of the main window
00665          and placed in the exact center of it */
00666       QRect cGeom = geometry();
00667       cGeom.setBottomRight(geometry().center());
00668       cGeom.moveCenter(geometry().center());
00669       pcXMLOutput->setGeometry(cGeom);
00670       /* This window steals all input */
00671       pcXMLOutput->setWindowModality(Qt::ApplicationModal);
00672       /* You can't modify its contents (but can copy-paste them) */
00673       pcXMLOutput->setReadOnly(true);
00674       /* Set nice document name and window title */
00675       pcXMLOutput->setDocumentTitle("ARGoS XML camera config");
00676       pcXMLOutput->setWindowTitle("ARGoS XML camera config");
00677       /* Set the actual text to visualize */
00678       pcXMLOutput->setPlainText(GetCameraXMLData());
00679       /* Finally, show the resulting window */
00680       pcXMLOutput->show();
00681    }
00682 
00683    /****************************************/
00684    /****************************************/
00685 
00686    // void CQTOpenGLMainWindow::POVRaySceneXMLPopUp() {
00687    //    /* Set the text window up */
00688    //    QTextEdit* pcPOVRayOutput = new QTextEdit();
00689    //    /* Calculate the geometry of the window so that it's 1/4 of the main window
00690    //       and placed in the exact center of it */
00691    //    QRect cGeom = geometry();
00692    //    cGeom.setBottomRight(geometry().center());
00693    //    cGeom.moveCenter(geometry().center());
00694    //    pcPOVRayOutput->setGeometry(cGeom);
00695    //    /* This window steals all input */
00696    //    pcPOVRayOutput->setWindowModality(Qt::ApplicationModal);
00697    //    /* You can't modify its contents (but can copy-paste them) */
00698    //    pcPOVRayOutput->setReadOnly(true);
00699    //    /* Set nice document name and window title */
00700    //    pcPOVRayOutput->setDocumentTitle("ARGoS-POVRay XML camera config");
00701    //    pcPOVRayOutput->setWindowTitle("ARGoS-POVRay XML camera config");
00702    //    /* Set the actual text to visualize */
00703    //    pcPOVRayOutput->setPlainText(GetPOVRaySceneXMLData());
00704    //    /* Finally, show the resulting window */
00705    //    pcPOVRayOutput->show();
00706    // }
00707 
00708    /****************************************/
00709    /****************************************/
00710 
00711    QString CQTOpenGLMainWindow::GetCameraXMLData() {
00712       QString strResult("<camera>\n");
00713       /* Get a reference to the camera */
00714       CQTOpenGLCamera& cCamera = m_pcOpenGLWidget->GetCamera();
00715       for(UInt32 i = 0; i < 12; ++i) {
00716          /* Get its position and target */
00717          const CQTOpenGLCamera::SSettings& sSettings = cCamera.GetSetting(i);
00718          const CVector3& cPos = sSettings.Position;
00719          const CVector3& cLookAt = sSettings.Target;
00720          strResult.append(
00721             QString("   <placement idx=\"%1\" position=\"%2,%3,%4\" look_at=\"%5,%6,%7\" lens_focal_length=\"%8\" />\n")
00722             .arg(i)
00723             .arg(cPos.GetX())
00724             .arg(cPos.GetY())
00725             .arg(cPos.GetZ())
00726             .arg(cLookAt.GetX())
00727             .arg(cLookAt.GetY())
00728             .arg(cLookAt.GetZ())
00729             .arg(sSettings.LensFocalLength * 1000.0f));
00730       }
00731       strResult.append("</camera>\n");
00732       return strResult;
00733    }
00734 
00735    /****************************************/
00736    /****************************************/
00737 
00738    // QString CQTOpenGLMainWindow::GetPOVRaySceneXMLData() {
00739    //    /* Get the current simulation step */
00740    //    UInt32 unStep = CSimulator::GetInstance().GetSpace().GetSimulationClock();
00741    //    /* Get a reference to the camera */
00742    //    const CQTOpenGLCamera& cCamera = m_pcOpenGLWidget->GetCamera();
00743    //    /* Get its current position and target */
00744    //    const CVector3& cPos = cCamera.GetPosition();
00745    //    const CVector3& cLookAt = cCamera.GetTarget();
00746    //    /* Get the environment node and its contents from the 'povray_render', if defined */
00747    //    TConfigurationNode& tExperiment = CSimulator::GetInstance().GetConfigurationRoot();
00748    //    TConfigurationNode& tVisualization = GetNode(tExperiment, "visualization");
00749    //    QString strPOVRayEnvironment;
00750    //    if(NodeExists(tVisualization,"povray_render")) {
00751    //       TConfigurationNode& tPOVRayVisualization = GetNode(tVisualization, "povray_render");
00752    //       TConfigurationNode& tPOVRayEnvironment = GetNode(tPOVRayVisualization, "environment");
00753    //       std::string strPOVRayEnvironmentNodeContent = tPOVRayEnvironment.ToString(tPOVRayEnvironment);
00754    //       strPOVRayEnvironment = strPOVRayEnvironmentNodeContent.c_str();
00755    //    }
00756 
00757    //    /* Return the XML portion */
00758    //    return QString(
00759    //       "%1\n"
00760    //       "<scene step=\"%2\">\n"
00761    //       "   <camera type=\"normal\"\n"
00762    //       "           position=\"%3,%4,%5\"\n"
00763    //       "           look_at=\"%6,%7,%8\"\n"
00764    //       "           focal_length=\"%9\" />\n"
00765    //       "</scene>\n"
00766    //       )
00767    //       .arg(strPOVRayEnvironment)
00768    //       .arg(unStep)
00769    //       .arg(cPos.GetX())
00770    //       .arg(cPos.GetY())
00771    //       .arg(cPos.GetZ())
00772    //       .arg(cLookAt.GetX())
00773    //       .arg(cLookAt.GetY())
00774    //       .arg(cLookAt.GetZ())
00775    //       .arg(cCamera.GetLensFocalLength() * 1000.0f);
00776    // }
00777 
00778    /****************************************/
00779    /****************************************/
00780 
00781    // void CQTOpenGLMainWindow::POVRayScenePreview() {
00782    //    try {
00783    //       /* Initialize the POV-Ray working directory */
00784    //       QDir cDirectory(QDir::tempPath() + "/argos-povray");
00785    //       /* Erase it if it exists */
00786    //       if(cDirectory.exists()) {
00787    //          if(::system(QString("rm -rf %1").arg(cDirectory.absolutePath()).toAscii().data()) != 0) {
00788    //             THROW_ARGOSEXCEPTION("Could not remove directory \"" <<
00789    //                                  cDirectory.absolutePath().toAscii().data() << "\".");
00790    //          }
00791    //       }
00792    //       /* Create the directory */
00793    //       if(::system(QString("mkdir %1").arg(cDirectory.absolutePath()).toAscii().data()) != 0) {
00794    //          THROW_ARGOSEXCEPTION("Could not create directory \"" <<
00795    //                               cDirectory.absolutePath().toAscii().data() << "\".");
00796    //       }
00797    //       /* Now create the XML file that will contain the POV-Ray scene configuration */
00798    //       QFile cPOVRayXMLConf(cDirectory.absolutePath() + "/argos-povray.xml");
00799    //       cPOVRayXMLConf.open(QFile::WriteOnly | QFile::Truncate);
00800    //       /* Associate a text stream to perform writing to it */
00801    //       QTextStream cPOVRayXMLConfStream(&cPOVRayXMLConf);
00802    //       /* Write the configuration */
00803    //       cPOVRayXMLConfStream << "<povray_render id=\"pov\" output_folder=\"" << cDirectory.absolutePath() << "\">\n";
00804    //       cPOVRayXMLConfStream << GetPOVRaySceneXMLData();
00805    //       cPOVRayXMLConfStream << "</povray_render>\n";
00806    //       cPOVRayXMLConf.close();
00807    //       /* Now parse this file as an ARGoS TConfigurationTree */
00808    //       ticpp::Document tPOVRayXMLConfTree(cPOVRayXMLConf.fileName().toAscii().data());
00809    //       tPOVRayXMLConfTree.LoadFile();
00810    //       /* It's time to create the POV-Ray visualization */
00811    //       CPovrayRender cPOVRayRender;
00812    //       cPOVRayRender.Init(*tPOVRayXMLConfTree.FirstChildElement());
00813    //       /* Write the .pov frame file */
00814    //       cPOVRayRender.WriteOneFrame(cDirectory.absolutePath().append("/pov/frame.pov").toAscii().data());
00815    //       /* Eventually, call POV-Ray to render the file */
00816    //       if(::system(QString("cd %1 && ")
00817    //                   .arg(cDirectory.absolutePath())
00818    //                   .append("./render_single_frame_on_pc.sh pov/frame.pov")
00819    //                   .toAscii().data()) !=0) {
00820    //          THROW_ARGOSEXCEPTION("Could not create POV-Ray preview");
00821    //       }
00822    //    }
00823    //    catch(CARGoSException& ex) {
00824    //       QString strError = QString("Error creating POV-Ray preview\n%1").arg(QString(ex.what()));
00825    //       QMessageBox::critical(this,
00826    //                             tr("ARGoS v2.0"),
00827    //                             strError,
00828    //                             QMessageBox::Ok);
00829    //    }
00830    // }
00831 
00832    /****************************************/
00833    /****************************************/
00834 
00835    void CQTOpenGLMainWindow::SwitchCamera(QAction* pc_action) {
00836       emit CameraSwitched(pc_action->data().toInt());
00837       m_pcFocalLength->setValue(m_pcOpenGLWidget->GetCamera().GetActiveSettings().LensFocalLength * 1000.0f);
00838    }
00839 
00840    /****************************************/
00841    /****************************************/
00842 
00843 }