Skip to content
Snippets Groups Projects
MainWindow.cc 57.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • /*===================================================================
    
    pixhawk's avatar
    pixhawk committed
    ======================================================================*/
    
    /**
     * @file
    
     *   @brief Implementation of class MainWindow
    
     *   @author Lorenz Meier <mail@qgroundcontrol.org>
    
    pixhawk's avatar
    pixhawk committed
     */
    
    #include <QSettings>
    #include <QDockWidget>
    #include <QNetworkInterface>
    #include <QMessageBox>
    #include <QDebug>
    #include <QTimer>
    #include <QHostInfo>
    
    #include "MG.h"
    
    #include "QGC.h"
    
    pixhawk's avatar
    pixhawk committed
    #include "MAVLinkSimulationLink.h"
    #include "SerialLink.h"
    #include "UDPLink.h"
    #include "MAVLinkProtocol.h"
    #include "CommConfigurationWindow.h"
    #include "WaypointList.h"
    #include "MainWindow.h"
    #include "JoystickWidget.h"
    
    pixhawk's avatar
    pixhawk committed
    #include "GAudioOutput.h"
    
    #ifdef QGC_OSG_ENABLED
    
    #include "Q3DWidgetFactory.h"
    
    pixhawk's avatar
    pixhawk committed
    
    
    lm's avatar
    lm committed
    // FIXME Move
    #include "PxQuadMAV.h"
    #include "SlugsMAV.h"
    
    
    pixhawk's avatar
    pixhawk committed
    
    #include "LogCompressor.h"
    
    /**
    * Create new mainwindow. The constructor instantiates all parts of the user
    * interface. It does NOT show the mainwindow. To display it, call the show()
    * method.
    *
    * @see QMainWindow::show()
    **/
    
    pixhawk's avatar
    pixhawk committed
            QMainWindow(parent),
    
    pixhawk's avatar
    pixhawk committed
            settings()
    
    pixhawk's avatar
    pixhawk committed
    {
    
        this->hide();
        this->setVisible(false);
    
    
    pixhawk's avatar
    pixhawk committed
        // Setup user interface
        ui.setupUi(this);
    
    
    pixhawk's avatar
    pixhawk committed
    
        // Add status bar
    
        //setStatusBar(createStatusBar());
    
    pixhawk's avatar
    pixhawk committed
    
        // Set the application style (not the same as a style sheet)
        // Set the style to Plastique
        qApp->setStyle("plastique");
    
    pixhawk's avatar
    pixhawk committed
        // Set style sheet as last step
        reloadStylesheet();
    
    
        // Create actions
    
        // Load mavlink view as default widget set
        loadMAVLinkView();
    
    
        // Adjust the size
        adjustSize();
    
    pixhawk's avatar
    pixhawk committed
    
    
        // Load previous widget setup
    
    
    lm's avatar
    lm committed
    //    // FIXME WORK IN PROGRESS
    //    QSettings settings(QGC::COMPANYNAME, QGC::APPNAME);
    
    lm's avatar
    lm committed
    //    QList<QDockWidget *> dockwidgets = qFindChildren<QDockWidget *>(this);
    //    if (dockwidgets.size())
    //    {
    //        settings.beginGroup("mainwindow/dockwidgets");
    //        for (int i = 0; i < dockwidgets.size(); ++i)
    //        {
    //            QDockWidget *dockWidget = dockwidgets.at(i);
    //            if (dockWidget->parentWidget() == this)
    //            {
    //                if (settings.contains(dockWidget->windowTitle()))
    //                {
    //                    dockWidget->setVisible(settings.value(dockWidget->windowTitle(), dockWidget->isVisible()).toBool());
    //                }
    //            }
    //        }
    //        settings.endGroup();
    //    }
    
    lm's avatar
    lm committed
        // Enable and update view
    
    lm's avatar
    lm committed
        presentView();
    
    pixhawk's avatar
    pixhawk committed
    }
    
    
    pixhawk's avatar
    pixhawk committed
    MainWindow::~MainWindow()
    
    pixhawk's avatar
    pixhawk committed
    {
        delete statusBar;
        statusBar = NULL;
    }
    
    
    void MainWindow::buildCommonWidgets()
    {
        //TODO:  move protocol outside UI
        mavlink     = new MAVLinkProtocol();
    
        // Dock widgets
        controlDockWidget = new QDockWidget(tr("Control"), this);
        controlDockWidget->setWidget( new UASControlWidget(this) );
    
        addToToolsMenu (controlDockWidget, tr("UAS Control"), SLOT(showToolWidget()), MENU_UAS_CONTROL, Qt::LeftDockWidgetArea);
    
    
        listDockWidget = new QDockWidget(tr("Unmanned Systems"), this);
        listDockWidget->setWidget( new UASListWidget(this) );
    
        addToToolsMenu (listDockWidget, tr("UAS List"), SLOT(showToolWidget()), MENU_UAS_LIST, Qt::RightDockWidgetArea);
    
    
        waypointsDockWidget = new QDockWidget(tr("Waypoint List"), this);
        waypointsDockWidget->setWidget( new WaypointList(this, NULL) );
    
        addToToolsMenu (waypointsDockWidget, tr("Waypoints List"), SLOT(showToolWidget()), MENU_WAYPOINTS, Qt::BottomDockWidgetArea);
    
    
        infoDockWidget = new QDockWidget(tr("Status Details"), this);
        infoDockWidget->setWidget( new UASInfoWidget(this) );
    
        addToToolsMenu (infoDockWidget, tr("Status Details"), SLOT(showToolWidget()), MENU_STATUS, Qt::RightDockWidgetArea);
    
    
    
        debugConsoleDockWidget = new QDockWidget(tr("Communication Console"), this);
        debugConsoleDockWidget->setWidget( new DebugConsole(this) );
    
        addToToolsMenu (debugConsoleDockWidget, tr("Communication Console"), SLOT(showToolWidget()), MENU_DEBUG_CONSOLE, Qt::BottomDockWidgetArea);
    
        // Center widgets
        mapWidget         = new MapWidget(this);
    
        addToCentralWidgetsMenu (mapWidget, "Maps", SLOT(showCentralWidget()),CENTRAL_MAP);
    
    
        protocolWidget    = new XMLCommProtocolWidget(this);
    
        addToCentralWidgetsMenu (protocolWidget, "Mavlink Generator", SLOT(showCentralWidget()),CENTRAL_PROTOCOL);
    
    
    pixhawk's avatar
    pixhawk committed
        //FIXME: memory of acceptList will never be freed again
        QStringList* acceptList = new QStringList();
        acceptList->append("roll IMU");
        acceptList->append("pitch IMU");
        acceptList->append("yaw IMU");
        acceptList->append("rollspeed IMU");
        acceptList->append("pitchspeed IMU");
        acceptList->append("yawspeed IMU");
    
    pixhawk's avatar
    pixhawk committed
        //FIXME: memory of acceptList2 will never be freed again
        QStringList* acceptList2 = new QStringList();
        acceptList2->append("Battery");
        acceptList2->append("Pressure");
    
    pixhawk's avatar
    pixhawk committed
        // Center widgets
        linechartWidget   = new Linecharts(this);
    
        addToCentralWidgetsMenu(linechartWidget, "Line Plots", SLOT(showCentralWidget()), CENTRAL_LINECHART);
    
    
    
        hudWidget         = new HUD(320, 240, this);
    
        addToCentralWidgetsMenu(hudWidget, "HUD", SLOT(showCentralWidget()), CENTRAL_HUD);
    
    
    pixhawk's avatar
    pixhawk committed
        dataplotWidget    = new QGCDataPlot2D(this);
    
        addToCentralWidgetsMenu(dataplotWidget, "Data Plots", SLOT(showCentralWidget()), CENTRAL_DATA_PLOT);
    
        _3DWidget         = Q3DWidgetFactory::get("PIXHAWK");
    
        addToCentralWidgetsMenu(_3DWidget, "Local 3D", SLOT(showCentralWidget()), CENTRAL_3D_LOCAL);
    
    
    #ifdef QGC_OSGEARTH_ENABLED
        _3DMapWidget = Q3DWidgetFactory::get("MAP3D");
    
        addToCentralWidgetsMenu(_3DMapWidget, "OSG Earth 3D", SLOT(showCentralWidget()), CENTRAL_OSGEARTH);
    
    lm's avatar
    lm committed
    
    
    #if (defined Q_OS_WIN) | (defined Q_OS_MAC)
    
    pixhawk's avatar
    pixhawk committed
        gEarthWidget = new QGCGoogleEarthView(this);
    
        addToCentralWidgetsMenu(gEarthWidget, "Google Earth", SLOT(showCentralWidget()), CENTRAL_GOOGLE_EARTH);
    
    
    pixhawk's avatar
    pixhawk committed
        // Dock widgets
    
    pixhawk's avatar
    pixhawk committed
        detectionDockWidget = new QDockWidget(tr("Object Recognition"), this);
        detectionDockWidget->setWidget( new ObjectDetectionView("images/patterns", this) );
    
        addToToolsMenu (detectionDockWidget, tr("Object Recognition"), SLOT(showToolWidget()), MENU_DETECTION, Qt::RightDockWidgetArea);
    
    
    pixhawk's avatar
    pixhawk committed
        parametersDockWidget = new QDockWidget(tr("Onboard Parameters"), this);
        parametersDockWidget->setWidget( new ParameterInterface(this) );
    
        addToToolsMenu (parametersDockWidget, tr("Onboard Parameters"), SLOT(showToolWidget()), MENU_PARAMETERS, Qt::RightDockWidgetArea);
    
    pixhawk's avatar
    pixhawk committed
        watchdogControlDockWidget = new QDockWidget(tr("Process Control"), this);
        watchdogControlDockWidget->setWidget( new WatchdogControl(this) );
    
        addToToolsMenu (watchdogControlDockWidget, tr("Process Control"), SLOT(showToolWidget()), MENU_WATCHDOG, Qt::BottomDockWidgetArea);
    
    
    pixhawk's avatar
    pixhawk committed
        hsiDockWidget = new QDockWidget(tr("Horizontal Situation Indicator"), this);
        hsiDockWidget->setWidget( new HSIDisplay(this) );
    
        addToToolsMenu (hsiDockWidget, tr("HSI"), SLOT(showToolWidget()), MENU_HSI, Qt::BottomDockWidgetArea);
    
        headDown1DockWidget = new QDockWidget(tr("System Stats"), this);
    
    pixhawk's avatar
    pixhawk committed
        headDown1DockWidget->setWidget( new HDDisplay(acceptList, this) );
    
    lm's avatar
    lm committed
    
    
        addToToolsMenu (headDown1DockWidget, tr("Flight Display"), SLOT(showToolWidget()), MENU_HDD_1, Qt::RightDockWidgetArea);
    
    pixhawk's avatar
    pixhawk committed
        headDown2DockWidget = new QDockWidget(tr("Payload Status"), this);
        headDown2DockWidget->setWidget( new HDDisplay(acceptList2, this) );
    
        addToToolsMenu (headDown2DockWidget, tr("Payload Status"), SLOT(showToolWidget()), MENU_HDD_2, Qt::RightDockWidgetArea);
    
    pixhawk's avatar
    pixhawk committed
        rcViewDockWidget = new QDockWidget(tr("Radio Control"), this);
        rcViewDockWidget->setWidget( new QGCRemoteControlView(this) );
    
        addToToolsMenu (rcViewDockWidget, tr("Radio Control"), SLOT(showToolWidget()), MENU_RC_VIEW, Qt::BottomDockWidgetArea);
    
        headUpDockWidget = new QDockWidget(tr("HUD"), this);
    
        headUpDockWidget->setWidget( new HUD(320, 240, this));
    
        addToToolsMenu (headUpDockWidget, tr("Control Indicator"), SLOT(showToolWidget()), MENU_HUD, Qt::LeftDockWidgetArea);
    
    pixhawk's avatar
    pixhawk committed
        // Dialogue widgets
        //FIXME: free memory in destructor
        joystick    = new JoystickInput();
    
    }
    
    void MainWindow::buildSlugsWidgets()
    {
        // Center widgets
        linechartWidget   = new Linecharts(this);
    
        // Dock widgets
    
        headUpDockWidget = new QDockWidget(tr("Control Indicator"), this);
        headUpDockWidget->setWidget( new HUD(320, 240, this));
        addToToolsMenu (headUpDockWidget, tr("HUD"), SLOT(showToolWidget()), MENU_HUD, Qt::LeftDockWidgetArea);
    
    
    
        rcViewDockWidget = new QDockWidget(tr("Radio Control"), this);
        rcViewDockWidget->setWidget( new QGCRemoteControlView(this) );
    
        addToToolsMenu (rcViewDockWidget, tr("Radio Control"), SLOT(showToolWidget()), MENU_RC_VIEW, Qt::BottomDockWidgetArea);
    
        slugsDataWidget = new QDockWidget(tr("Slugs Data"), this);
        slugsDataWidget->setWidget( new SlugsDataSensorView(this));
    
        addToToolsMenu (slugsDataWidget, tr("Telemetry Data"), SLOT(showToolWidget()), MENU_SLUGS_DATA, Qt::RightDockWidgetArea);
    
    
        slugsPIDControlWidget = new QDockWidget(tr("Slugs PID Control"), this);
    
        slugsPIDControlWidget->setWidget(new SlugsPIDControl(this));
    
        addToToolsMenu (slugsPIDControlWidget, tr("PID Configuration"), SLOT(showToolWidget()), MENU_SLUGS_PID, Qt::LeftDockWidgetArea);
    
        slugsHilSimWidget = new QDockWidget(tr("Slugs Hil Sim"), this);
        slugsHilSimWidget->setWidget( new SlugsHilSim(this));
    
        addToToolsMenu (slugsHilSimWidget, tr("HIL Sim Configuration"), SLOT(showToolWidget()), MENU_SLUGS_HIL, Qt::LeftDockWidgetArea);
    
        slugsCamControlWidget = new QDockWidget(tr("Slugs Video Camera Control"), this);
    
        slugsCamControlWidget->setWidget(new SlugsVideoCamControl(this));
    
        addToToolsMenu (slugsCamControlWidget, tr("Camera Control"), SLOT(showToolWidget()), MENU_SLUGS_CAMERA, Qt::BottomDockWidgetArea);
    
    
    
    void MainWindow::addToCentralWidgetsMenu ( QWidget* widget,
                                               const QString title,
                                               const char * slotName,
                                               TOOLS_WIDGET_NAMES centralWidget){
      QAction* tempAction;
    
    
      // Add the separator that will separate tools from central Widgets
      if (!toolsMenuActions[CENTRAL_SEPARATOR]){
        tempAction = ui.menuTools->addSeparator();
        toolsMenuActions[CENTRAL_SEPARATOR] = tempAction;
    
      }
    
      tempAction = ui.menuTools->addAction(title);
    
      tempAction->setCheckable(true);
      tempAction->setData(centralWidget);
    
      // populate the Hashes
      toolsMenuActions[centralWidget] = tempAction;
      dockWidgets[centralWidget] = widget;
    
      QString chKey = buildMenuKey(SUB_SECTION_CHECKED, centralWidget, currentView);
    
      if (!settings.contains(chKey)){
        settings.setValue(chKey,false);
        tempAction->setChecked(false);
      }
    
    //  else {
    //    tempAction->setChecked(settings.value(chKey).toBool());
    //  }
    
    
      // connect the action
      connect(tempAction,SIGNAL(triggered()),this, slotName);
    
    }
    
    
    
    lm's avatar
    lm committed
    void MainWindow::showCentralWidget()
    {
    
      QAction* senderAction = qobject_cast<QAction *>(sender());
      int tool = senderAction->data().toInt();
      QString chKey;
    
    
    lm's avatar
    lm committed
      if (senderAction && dockWidgets[tool])
      {
    
    
        // uncheck all central widget actions
        QHashIterator<int, QAction*> i(toolsMenuActions);
         while (i.hasNext()) {
    
           i.next();
           qDebug() << "shCW" << i.key() << "read";
           if (i.value() && i.value()->data().toInt() > 255){
    
               i.value()->setChecked(false);
    
               // update the settings
               chKey = buildMenuKey (SUB_SECTION_CHECKED,static_cast<TOOLS_WIDGET_NAMES>(i.value()->data().toInt()), currentView);
               settings.setValue(chKey,false);
             }
         }
    
        // check the current action
    
        senderAction->setChecked(true);
    
        // update the central widget
        centerStack->setCurrentWidget(dockWidgets[tool]);
    
        // store the selected central widget
        chKey = buildMenuKey (SUB_SECTION_CHECKED,static_cast<TOOLS_WIDGET_NAMES>(tool), currentView);
        settings.setValue(chKey,true);
    
    lm's avatar
    lm committed
    /**
     * Adds a widget to the tools menu and sets it visible if it was
     * enabled last time.
     */
    
    void MainWindow::addToToolsMenu ( QWidget* widget,
                                     const QString title,
                                     const char * slotName,
                                     TOOLS_WIDGET_NAMES tool,
    
    lm's avatar
    lm committed
                                     Qt::DockWidgetArea location)
    {
    
      if (toolsMenuActions[CENTRAL_SEPARATOR]){
        tempAction = new QAction(title, this);
        ui.menuTools->insertAction(toolsMenuActions[CENTRAL_SEPARATOR],
                                   tempAction);
      } else {
        tempAction = ui.menuTools->addAction(title);
      }
    
    
      tempAction->setCheckable(true);
      tempAction->setData(tool);
    
      // populate the Hashes
      toolsMenuActions[tool] = tempAction;
      dockWidgets[tool] = widget;
    
      posKey = buildMenuKey (SUB_SECTION_LOCATION,tool, currentView);
    
    
      if (!settings.contains(posKey)){
        settings.setValue(posKey,location);
        dockWidgetLocations[tool] = location;
      } else {
        dockWidgetLocations[tool] = static_cast <Qt::DockWidgetArea> (settings.value(posKey).toInt());
      }
    
    
      chKey = buildMenuKey(SUB_SECTION_CHECKED,tool, currentView);
    
    lm's avatar
    lm committed
      if (!settings.contains(chKey))
      {
    
        settings.setValue(chKey,false);
        tempAction->setChecked(false);
    
    lm's avatar
    lm committed
      }
      else
      {
    
        tempAction->setChecked(settings.value(chKey).toBool());
    
    lm's avatar
    lm committed
        widget->setVisible(settings.value(chKey).toBool());
    
      }
    
      // connect the action
      connect(tempAction,SIGNAL(triggered()),this, slotName);
    
    
      connect(qobject_cast <QDockWidget *>(dockWidgets[tool]),
    
              SIGNAL(visibilityChanged(bool)), this, SLOT(updateVisibilitySettings(bool)));
    
    
      connect(qobject_cast <QDockWidget *>(dockWidgets[tool]),
    
              SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), this, SLOT(updateLocationSettings(Qt::DockWidgetArea)));
    
    }
    
    
    void MainWindow::showToolWidget(){
      QAction* temp = qobject_cast<QAction *>(sender());
      int tool = temp->data().toInt();
    
    
      if (temp && dockWidgets[tool]){
        if (temp->isChecked()){
          addDockWidget(dockWidgetLocations[tool], qobject_cast<QDockWidget *> (dockWidgets[tool]));
          qobject_cast<QDockWidget *>(dockWidgets[tool])->show();
        } else {
          removeDockWidget(qobject_cast<QDockWidget *>(dockWidgets[tool]));
        }
        QString chKey = buildMenuKey (SUB_SECTION_CHECKED,static_cast<TOOLS_WIDGET_NAMES>(tool), currentView);
        settings.setValue(chKey,temp->isChecked());
      }
    }
    
    
    void MainWindow::showTheWidget (TOOLS_WIDGET_NAMES widget, VIEW_SECTIONS view){
      bool tempVisible;
      Qt::DockWidgetArea tempLocation;
      QDockWidget* tempWidget = static_cast <QDockWidget *>(dockWidgets[widget]);
    
      tempVisible =  settings.value(buildMenuKey (SUB_SECTION_CHECKED,widget,view)).toBool();
    
      if (tempWidget){
        toolsMenuActions[widget]->setChecked(tempVisible);
      }
    
    
      //qDebug() <<  buildMenuKey (SUB_SECTION_CHECKED,widget,view) << tempVisible;
    
      tempLocation = static_cast <Qt::DockWidgetArea>(settings.value(buildMenuKey (SUB_SECTION_LOCATION,widget, view)).toInt());
    
      if (tempWidget && tempVisible){
        addDockWidget(tempLocation, tempWidget);
        tempWidget->show();
      }
    
    }
    
    
    QString MainWindow::buildMenuKey(SETTINGS_SECTIONS section, TOOLS_WIDGET_NAMES tool, VIEW_SECTIONS view){
      // Key is built as follows: autopilot_type/section_menu/view/tool/section
      int apType;
    
      apType = (UASManager::instance() && UASManager::instance()->silentGetActiveUAS())?
               UASManager::instance()->getActiveUAS()->getAutopilotType():
               -1;
    
      return (QString::number(apType) + "/" +
              QString::number(SECTION_MENU) + "/" +
              QString::number(view) + "/" +
    
              QString::number(tool) + "/" +
              QString::number(section) + "/" );
    }
    
    void MainWindow::updateVisibilitySettings (bool vis){
      Q_UNUSED(vis);
    
      // This is commented since when the application closes
      // sets the visibility to false.
    
      // TODO: A workaround is needed. The QApplication::aboutToQuit
      //       did not work
    
      /*
      QDockWidget* temp = qobject_cast<QDockWidget *>(sender());
    
      QHashIterator<int, QWidget*> i(dockWidgets);
      while (i.hasNext()) {
          i.next();
          if ((static_cast <QDockWidget *>(dockWidgets[i.key()])) == temp){
            QString chKey = buildMenuKey (SUB_SECTION_CHECKED,static_cast<TOOLS_WIDGET_NAMES>(i.key()));
            qDebug() << "Key in visibility changed" << chKey;
            settings.setValue(chKey,vis);
            toolsMenuActions[i.key()]->setChecked(vis);
            break;
          }
      }
    */
    }
    
    void MainWindow::updateLocationSettings (Qt::DockWidgetArea location){
      QDockWidget* temp = qobject_cast<QDockWidget *>(sender());
    
      QHashIterator<int, QWidget*> i(dockWidgets);
      while (i.hasNext()) {
          i.next();
          if ((static_cast <QDockWidget *>(dockWidgets[i.key()])) == temp){
    
            QString posKey = buildMenuKey (SUB_SECTION_LOCATION,static_cast<TOOLS_WIDGET_NAMES>(i.key()), currentView);
    
    lm's avatar
    lm committed
    //=======
    //    addDockWidget(Qt::BottomDockWidgetArea, slugsCamControlWidget);
    //    slugsCamControlWidget->hide();
    
    //    //FIXME: free memory in destructor
    //    joystick    = new JoystickInput();
    //>>>>>>> master
    
    /**
     * Connect the signals and slots of the common window widgets
     */
    
    pixhawk's avatar
    pixhawk committed
        if (infoDockWidget && infoDockWidget->widget())
        {
            connect(mavlink, SIGNAL(receiveLossChanged(int, float)),
                    infoDockWidget->widget(), SLOT(updateSendLoss(int, float)));
        }
    
    pixhawk's avatar
    pixhawk committed
        if (mapWidget && waypointsDockWidget->widget())
        {
            // clear path create on the map
            connect(waypointsDockWidget->widget(), SIGNAL(clearPathclicked()), mapWidget, SLOT(clearPath()));
            // add Waypoint widget in the WaypointList widget when mouse clicked
            connect(mapWidget, SIGNAL(captureMapCoordinateClick(QPointF)), waypointsDockWidget->widget(), SLOT(addWaypointMouse(QPointF)));
    
    
            // it notifies that a waypoint global goes to do create and a map graphic too
            connect(waypointsDockWidget->widget(), SIGNAL(createWaypointAtMap(QPointF)), mapWidget, SLOT(createWaypointGraphAtMap(QPointF)));
    
        }
    
    }
    
    void MainWindow::connectPxWidgets()
    {
        if (linechartWidget)
        {
            connect(linechartWidget, SIGNAL(logfileWritten(QString)),
                    this, SLOT(loadDataView(QString)));
        }
    
    }
    
    void MainWindow::connectSlugsWidgets()
    {
        if (linechartWidget)
        {
            connect(UASManager::instance(), SIGNAL(UASCreated(UASInterface*)),
                    linechartWidget, SLOT(addSystem(UASInterface*)));
            connect(UASManager::instance(), SIGNAL(activeUASSet(int)),
                    linechartWidget, SLOT(selectSystem(int)));
            connect(linechartWidget, SIGNAL(logfileWritten(QString)),
                    this, SLOT(loadDataView(QString)));
    
    pixhawk's avatar
    pixhawk committed
        }
    
        if (slugsHilSimWidget && slugsHilSimWidget->widget()){
          connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)),
                  slugsHilSimWidget->widget(), SLOT(activeUasSet(UASInterface*)));
        }
    
        if (slugsDataWidget && slugsDataWidget->widget()){
          connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)),
                  slugsDataWidget->widget(), SLOT(setActiveUAS(UASInterface*)));
    
    void MainWindow::arrangeCommonCenterStack()
    
    pixhawk's avatar
    pixhawk committed
        if (!centerStack) return;
    
    pixhawk's avatar
    pixhawk committed
        if (mapWidget) centerStack->addWidget(mapWidget);
    
        if (protocolWidget) centerStack->addWidget(protocolWidget);
    
        setCentralWidget(centerStack);
    }
    
    void MainWindow::arrangePxCenterStack()
    {
    
      if (!centerStack) {
        qDebug() << "Center Stack not Created!";
        return;
      }
    
        if (linechartWidget) centerStack->addWidget(linechartWidget);
    
    
        if (_3DWidget) centerStack->addWidget(_3DWidget);
    
        if (_3DMapWidget) centerStack->addWidget(_3DMapWidget);
    
    #endif
    #if (defined Q_OS_WIN) | (defined Q_OS_MAC)
    
    pixhawk's avatar
    pixhawk committed
        if (gEarthWidget) centerStack->addWidget(gEarthWidget);
    
    pixhawk's avatar
    pixhawk committed
        if (hudWidget) centerStack->addWidget(hudWidget);
        if (dataplotWidget) centerStack->addWidget(dataplotWidget);
    
    }
    
    void MainWindow::arrangeSlugsCenterStack()
    {
    
      if (!centerStack) {
        qDebug() << "Center Stack not Created!";
        return;
      }
    
      if (linechartWidget) centerStack->addWidget(linechartWidget);
    
    
      if (hudWidget) centerStack->addWidget(hudWidget);
    
    
    pixhawk's avatar
    pixhawk committed
        QList<QHostAddress> hostAddresses = QNetworkInterface::allAddresses();
        QString windowname = qApp->applicationName() + " " + qApp->applicationVersion();
        bool prevAddr = false;
    
    pixhawk's avatar
    pixhawk committed
        windowname.append(" (" + QHostInfo::localHostName() + ": ");
    
    pixhawk's avatar
    pixhawk committed
        for (int i = 0; i < hostAddresses.size(); i++)
        {
            // Exclude loopback IPv4 and all IPv6 addresses
            if (hostAddresses.at(i) != QHostAddress("127.0.0.1") && !hostAddresses.at(i).toString().contains(":"))
            {
                if(prevAddr) windowname.append("/");
                windowname.append(hostAddresses.at(i).toString());
                prevAddr = true;
            }
        }
    
    pixhawk's avatar
    pixhawk committed
        windowname.append(")");
    
    pixhawk's avatar
    pixhawk committed
        setWindowTitle(windowname);
    
    pixhawk's avatar
    pixhawk committed
        //qApp->setWindowIcon(QIcon(":/core/images/qtcreator_logo_128.png"));
    
    pixhawk's avatar
    pixhawk committed
    QStatusBar* MainWindow::createStatusBar()
    
    pixhawk's avatar
    pixhawk committed
    {
        QStatusBar* bar = new QStatusBar();
        /* Add status fields and messages */
        /* Enable resize grip in the bottom right corner */
        bar->setSizeGripEnabled(true);
        return bar;
    }
    
    
    pixhawk's avatar
    pixhawk committed
    void MainWindow::startVideoCapture()
    
    pixhawk's avatar
    pixhawk committed
    {
        QString format = "bmp";
        QString initialPath = QDir::currentPath() + tr("/untitled.") + format;
    
        QString screenFileName = QFileDialog::getSaveFileName(this, tr("Save As"),
                                                              initialPath,
                                                              tr("%1 Files (*.%2);;All Files (*)")
                                                              .arg(format.toUpper())
                                                              .arg(format));
        delete videoTimer;
        videoTimer = new QTimer(this);
    
        //videoTimer->setInterval(40);
        //connect(videoTimer, SIGNAL(timeout()), this, SLOT(saveScreen()));
        //videoTimer->stop();
    
    pixhawk's avatar
    pixhawk committed
    void MainWindow::stopVideoCapture()
    
    pixhawk's avatar
    pixhawk committed
    {
        videoTimer->stop();
    
        // TODO Convert raw images to PNG
    }
    
    
    pixhawk's avatar
    pixhawk committed
    void MainWindow::saveScreen()
    
    pixhawk's avatar
    pixhawk committed
    {
        QPixmap window = QPixmap::grabWindow(this->winId());
        QString format = "bmp";
    
        if (!screenFileName.isEmpty())
        {
            window.save(screenFileName, format.toAscii());
        }
    }
    
    
    /**
     * Reload the style sheet from disk. The function tries to load "qgroundcontrol.css" from the application
     * directory (which by default does not exist). If it fails, it will load the bundled default CSS
     * from memory.
     * To customize the application, just create a qgroundcontrol.css file in the application directory
     */
    
    pixhawk's avatar
    pixhawk committed
    void MainWindow::reloadStylesheet()
    
    pixhawk's avatar
    pixhawk committed
    {
        // Load style sheet
    
        QFile* styleSheet = new QFile(QCoreApplication::applicationDirPath() + "/qgroundcontrol.css");
        if (!styleSheet->exists())
        {
            styleSheet = new QFile(":/images/style-mission.css");
        }
    
        if (styleSheet->open(QIODevice::ReadOnly | QIODevice::Text))
        {
    
            QString style = QString(styleSheet->readAll());
            style.replace("ICONDIR", QCoreApplication::applicationDirPath()+ "/images/");
    
    pixhawk's avatar
    pixhawk committed
            qApp->setStyleSheet(style);
    
            qDebug() << "Style not set:" << styleSheet->fileName() << "opened: " << styleSheet->isOpen();
    
    pixhawk's avatar
    pixhawk committed
        }
    
    pixhawk's avatar
    pixhawk committed
    }
    
    
    pixhawk's avatar
    pixhawk committed
    void MainWindow::showStatusMessage(const QString& status, int timeout)
    
    pixhawk's avatar
    pixhawk committed
    {
    
    lm's avatar
    lm committed
        Q_UNUSED(status);
        Q_UNUSED(timeout);
    
        //statusBar->showMessage(status, timeout);
    
    pixhawk's avatar
    pixhawk committed
    }
    
    
    void MainWindow::showStatusMessage(const QString& status)
    
    pixhawk's avatar
    pixhawk committed
    {
    
    lm's avatar
    lm committed
        Q_UNUSED(status);
    
        //statusBar->showMessage(status, 5);
    
    pixhawk's avatar
    pixhawk committed
    }
    
    /**
    * @brief Create all actions associated to the main window
    *
    **/
    
    pixhawk's avatar
    pixhawk committed
    {
    
    pixhawk's avatar
    pixhawk committed
        // Connect actions from ui
        connect(ui.actionAdd_Link, SIGNAL(triggered()), this, SLOT(addLink()));
    
        // Connect internal actions
        connect(UASManager::instance(), SIGNAL(UASCreated(UASInterface*)), this, SLOT(UASCreated(UASInterface*)));
    
    
    pixhawk's avatar
    pixhawk committed
        connect(ui.actionLiftoff, SIGNAL(triggered()), UASManager::instance(), SLOT(launchActiveUAS()));
        connect(ui.actionLand, SIGNAL(triggered()), UASManager::instance(), SLOT(returnActiveUAS()));
        connect(ui.actionEmergency_Land, SIGNAL(triggered()), UASManager::instance(), SLOT(stopActiveUAS()));
        connect(ui.actionEmergency_Kill, SIGNAL(triggered()), UASManager::instance(), SLOT(killActiveUAS()));
    
        connect(ui.actionConfiguration, SIGNAL(triggered()), UASManager::instance(), SLOT(configureActiveUAS()));
    
    
        connect(ui.actionPilotsView, SIGNAL(triggered()), this, SLOT(loadPilotView()));
    
        connect(ui.actionEngineersView, SIGNAL(triggered()), this, SLOT(loadEngineerView()));
    
        connect(ui.actionOperatorsView, SIGNAL(triggered()), this, SLOT(loadOperatorView()));
    
        connect(ui.actionMavlinkView, SIGNAL(triggered()), this, SLOT(loadMAVLinkView()));
        connect(ui.actionReloadStyle, SIGNAL(triggered()), this, SLOT(reloadStylesheet()));
    
        connect(ui.actionOnline_documentation, SIGNAL(triggered()), this, SLOT(showHelp()));
        connect(ui.actionDeveloper_Credits, SIGNAL(triggered()), this, SLOT(showCredits()));
        connect(ui.actionProject_Roadmap, SIGNAL(triggered()), this, SLOT(showRoadMap()));
    
    }
    
    void MainWindow::connectPxActions()
    {
    
      ui.actionJoystickSettings->setVisible(true);
    
      // Joystick configuration
      connect(ui.actionJoystickSettings, SIGNAL(triggered()), this, SLOT(configure()));
    
    }
    
    void MainWindow::connectSlugsActions()
    {
    
    pixhawk's avatar
    pixhawk committed
    }
    
    
    void MainWindow::showHelp()
    {
        if(!QDesktopServices::openUrl(QUrl("http://qgroundcontrol.org/user_guide")))
        {
            QMessageBox msgBox;
            msgBox.setIcon(QMessageBox::Critical);
            msgBox.setText("Could not open help in browser");
            msgBox.setInformativeText("To get to the online help, please open http://qgroundcontrol.org/user_guide in a browser.");
            msgBox.setStandardButtons(QMessageBox::Ok);
            msgBox.setDefaultButton(QMessageBox::Ok);
            msgBox.exec();
        }
    }
    
    void MainWindow::showCredits()
    {
        if(!QDesktopServices::openUrl(QUrl("http://qgroundcontrol.org/credits")))
        {
            QMessageBox msgBox;
            msgBox.setIcon(QMessageBox::Critical);
            msgBox.setText("Could not open credits in browser");
            msgBox.setInformativeText("To get to the online help, please open http://qgroundcontrol.org/credits in a browser.");
            msgBox.setStandardButtons(QMessageBox::Ok);
            msgBox.setDefaultButton(QMessageBox::Ok);
            msgBox.exec();
        }
    }
    
    void MainWindow::showRoadMap()
    {
        if(!QDesktopServices::openUrl(QUrl("http://qgroundcontrol.org/roadmap")))
        {
            QMessageBox msgBox;
            msgBox.setIcon(QMessageBox::Critical);
            msgBox.setText("Could not open roadmap in browser");
            msgBox.setInformativeText("To get to the online help, please open http://qgroundcontrol.org/roadmap in a browser.");
            msgBox.setStandardButtons(QMessageBox::Ok);
            msgBox.setDefaultButton(QMessageBox::Ok);
            msgBox.exec();
        }
    }
    
    
    pixhawk's avatar
    pixhawk committed
    void MainWindow::configure()
    
    pixhawk's avatar
    pixhawk committed
    {
        joystickWidget = new JoystickWidget(joystick, this);
    }
    
    
    pixhawk's avatar
    pixhawk committed
    void MainWindow::addLink()
    
    pixhawk's avatar
    pixhawk committed
    {
        SerialLink* link = new SerialLink();
        // TODO This should be only done in the dialog itself
    
        LinkManager::instance()->addProtocol(link, mavlink);
    
        CommConfigurationWindow* commWidget = new CommConfigurationWindow(link, mavlink, this);
    
        ui.menuNetwork->addAction(commWidget->getAction());
    
        commWidget->show();
    
        // TODO Implement the link removal!
    }
    
    
    pixhawk's avatar
    pixhawk committed
    void MainWindow::addLink(LinkInterface *link)
    {
    
        LinkManager::instance()->addProtocol(link, mavlink);
    
    pixhawk's avatar
    pixhawk committed
        CommConfigurationWindow* commWidget = new CommConfigurationWindow(link, mavlink, this);
        ui.menuNetwork->addAction(commWidget->getAction());
    
        // Special case for simulationlink
        MAVLinkSimulationLink* sim = dynamic_cast<MAVLinkSimulationLink*>(link);
        if (sim)
        {
    
            //connect(sim, SIGNAL(valueChanged(int,QString,double,quint64)), linechart, SLOT(appendData(int,QString,double,quint64)));
    
    pixhawk's avatar
    pixhawk committed
            connect(ui.actionSimulate, SIGNAL(triggered(bool)), sim, SLOT(connectLink(bool)));
        }
    }
    
    
    pixhawk's avatar
    pixhawk committed
    void MainWindow::UASCreated(UASInterface* uas)
    
    pixhawk's avatar
    pixhawk committed
    {
        // Connect the UAS to the full user interface
    
    
        if (uas != NULL)
        {
            QIcon icon;
            // Set matching icon
            switch (uas->getSystemType())
            {
            case 0:
                icon = QIcon(":/images/mavs/generic.svg");
                break;
            case 1:
                icon = QIcon(":/images/mavs/fixed-wing.svg");
                break;
            case 2:
                icon = QIcon(":/images/mavs/quadrotor.svg");
                break;
            case 3:
                icon = QIcon(":/images/mavs/coaxial.svg");
                break;
            case 4:
                icon = QIcon(":/images/mavs/helicopter.svg");
                break;
            case 5:
                icon = QIcon(":/images/mavs/groundstation.svg");
                break;
            default:
                icon = QIcon(":/images/mavs/unknown.svg");
                break;
            }
    
            ui.menuConnected_Systems->addAction(icon, tr("Select %1 for control").arg(uas->getUASName()), uas, SLOT(setSelected()));
    
            // FIXME Should be not inside the mainwindow
    
            if (debugConsoleDockWidget)
            {
    
    pixhawk's avatar
    pixhawk committed
                DebugConsole *debugConsole = dynamic_cast<DebugConsole*>(debugConsoleDockWidget->widget());
                if (debugConsole)
                {
                    connect(uas, SIGNAL(textMessageReceived(int,int,int,QString)),
                            debugConsole, SLOT(receiveTextMessage(int,int,int,QString)));
                }
    
    
            // Health / System status indicator
    
    pixhawk's avatar
    pixhawk committed
                UASInfoWidget *infoWidget = dynamic_cast<UASInfoWidget*>(infoDockWidget->widget());
                if (infoWidget)
                {
                    infoWidget->addUAS(uas);
                }
    
    pixhawk's avatar
    pixhawk committed
                UASListWidget *listWidget = dynamic_cast<UASListWidget*>(listDockWidget->widget());
                if (listWidget)
                {
                    listWidget->addUAS(uas);
                }
    
    
            // Camera view
            //camera->addUAS(uas);
    
            // Revalidate UI
            // TODO Stylesheet reloading should in theory not be necessary
            reloadStylesheet();
    
    
            switch (uas->getAutopilotType()){
              case (MAV_AUTOPILOT_GENERIC):
              case (MAV_AUTOPILOT_ARDUPILOTMEGA):
              case (MAV_AUTOPILOT_PIXHAWK):
              {
                // Build Pixhawk Widgets
                buildPxWidgets();
    
                // Connect Pixhawk Widgets
                connectPxWidgets();
    
                // Arrange Pixhawk Centerstack
                arrangePxCenterStack();
    
                // Connect Pixhawk Actions
                connectPxActions();
    
                // FIXME: This type checking might be redundant
                // Check which type this UAS is of
    //            PxQuadMAV* mav = dynamic_cast<PxQuadMAV*>(uas);
    //            if (mav) loadPixhawkEngineerView();
              } break;
    
              case (MAV_AUTOPILOT_SLUGS):
              {
                // Build Slugs Widgets
                buildSlugsWidgets();
    
                // Connect Slugs Widgets
                connectSlugsWidgets();
    
                // Arrange Slugs Centerstack
                arrangeSlugsCenterStack();
    
                // Connect Slugs Actions
                connectSlugsActions();
    
                // FIXME: This type checking might be redundant
    //            if (slugsDataWidget) {
    //              SlugsDataSensorView* dataWidget = dynamic_cast<SlugsDataSensorView*>(slugsDataWidget->widget());
    //              if (dataWidget) {
    //                SlugsMAV* mav2 = dynamic_cast<SlugsMAV*>(uas);
    //                if (mav2) {
                      (dynamic_cast<SlugsDataSensorView*>(slugsDataWidget->widget()))->addUAS(uas);
    //                  //loadSlugsView();
    //                  loadGlobalOperatorView();
    //                }
    //              }
    //            }
              } break;