Skip to content
MainWindow.cc 44.3 KiB
Newer Older
/*===================================================================
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"

MainWindow* MainWindow::instance()
{
    static MainWindow* _instance = 0;
    if(_instance == 0)
    {
        _instance = new MainWindow();
        /* Set the application as parent to ensure that this object
                 * will be destroyed when the main application exits */
        //_instance->setParent(qApp);
    }
    return _instance;
pixhawk's avatar
pixhawk committed
/**
* 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),
        currentView(VIEW_OPERATOR),
        aboutToCloseFlag(false),
pixhawk's avatar
pixhawk committed
        settings()
pixhawk's avatar
pixhawk committed
{
    // Get current settings
    settings.sync();
    // Check if the settings exist, instantiate defaults if necessary
    QString centralKey = buildMenuKey(SUB_SECTION_CHECKED, CENTRAL_MAP, currentView);
    if (!settings.contains(centralKey))
    {
        settings.setValue(centralKey,true);
    }

    QString listKey = buildMenuKey(SUB_SECTION_CHECKED, MENU_UAS_LIST, currentView);
    if (!settings.contains(listKey))
    {
        settings.setValue(listKey, true);
    }
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
    // Add option for custom widgets
    connect(ui.actionNewCustomWidget, SIGNAL(triggered()), this, SLOT(createCustomWidget()));
    // Allow to mute audio
    ui.actionMuteAudioOutput->setChecked(GAudioOutput::instance()->isMuted());
    connect(ui.actionMuteAudioOutput, SIGNAL(triggered(bool)), GAudioOutput::instance(), SLOT(mute(bool)));
    // Set dock options
    setDockOptions(AnimatedDocks | AllowTabbedDocks | AllowNestedDocks);
    // Load mavlink view as default widget set
    if (settings.contains("geometry"))
    {
        // Restore the window geometry
        restoreGeometry(settings.value("geometry").toByteArray());
    }
    else
    {
    // Adjust the size
    adjustSize();
pixhawk's avatar
pixhawk committed

    // Populate link menu
    QList<LinkInterface*> links = LinkManager::instance()->getLinks();
    foreach(LinkInterface* link, links)
lm's avatar
lm committed
    // Enable and update view
    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("Control"), SLOT(showToolWidget()), MENU_UAS_CONTROL, Qt::LeftDockWidgetArea);
    }
    listDockWidget = new QDockWidget(tr("Unmanned Systems"), this);
    listDockWidget->setWidget( new UASListWidget(this) );
        addToToolsMenu (listDockWidget, tr("Unmanned Systems"), 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);
    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("-180,roll (deg),+180");
    acceptList->append("-180,pitch (deg),+180");
    acceptList->append("-180,yaw (deg),+180");

    acceptList->append("-500,roll V (deg/s),+500");
    acceptList->append("-500,pitch V (deg/s),+500");
    acceptList->append("-500,yaw V (deg/s),+500");
pixhawk's avatar
pixhawk committed
    //FIXME: memory of acceptList2 will never be freed again
    QStringList* acceptList2 = new QStringList();
    acceptList2->append("0,Abs pressure,65500");
    acceptList2->append("-2000,Accel. X, 2000");
    acceptList2->append("-2000,Accel. Y, 2000");
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 _MSC_VER) | (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("Flight Display"), this);
        headDown1DockWidget->setWidget( new HDDisplay(acceptList, "Flight Display", this) );
    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, "Payload Status", 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
pixhawk's avatar
pixhawk committed
    joystick    = new JoystickInput();
        linechartWidget   = new Linecharts(this);
    }
    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);
    if (!slugsPIDControlWidget)
    {
        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);
    if (!slugsCamControlWidget)
    {
        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,
  // 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);

    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;

    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);
        settings.sync();
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,
                                  Qt::DockWidgetArea location)
lm's avatar
lm committed
{
    if (toolsMenuActions[CENTRAL_SEPARATOR])
    {
    tempAction = new QAction(title, this);
    ui.menuTools->insertAction(toolsMenuActions[CENTRAL_SEPARATOR],
                               tempAction);
  tempAction->setCheckable(true);
  tempAction->setData(tool);

  // populate the Hashes
  toolsMenuActions[tool] = tempAction;
  dockWidgets[tool] = widget;
  posKey = buildMenuKey (SUB_SECTION_LOCATION,tool, currentView);
    settings.setValue(posKey,location);
    dockWidgetLocations[tool] = location;
    }
    else
    {
        dockWidgetLocations[tool] = static_cast <Qt::DockWidgetArea> (settings.value(posKey, Qt::RightDockWidgetArea).toInt());
  chKey = buildMenuKey(SUB_SECTION_CHECKED,tool, currentView);
    if (!settings.contains(chKey))
    {
    settings.setValue(chKey,false);
    tempAction->setChecked(false);
    tempAction->setChecked(settings.value(chKey).toBool());
        widget->setVisible(settings.value(chKey, false).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();
      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), false).toBool();
//    qDebug() << buildMenuKey (SUB_SECTION_CHECKED, widget,view) << tempVisible;

    // Some widgets are per default visible. Overwrite the settings value if not present.
    if (widget == MainWindow::MENU_UAS_LIST)
    {
        if (!settings.contains(buildMenuKey (SUB_SECTION_CHECKED,widget,view)))
        {
            tempVisible = true;
        }
    }
    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), QVariant(Qt::RightDockWidgetArea)).toInt());
    //    if (widget == MainWindow::MENU_UAS_LIST)
    //    {
    //        if (!settings.contains(buildMenuKey (SUB_SECTION_LOCATION,widget, view)))
    //        {
    //            tempLocation = Qt::RightDockWidgetArea;
    //        }
    //    }
    if ((tempWidget != NULL) && 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::closeEvent(QCloseEvent *event)
{
    settings.setValue("geometry", saveGeometry());
    //settings.setValue("windowState", saveState());
    aboutToCloseFlag = true;
    settings.setValue("VIEW_ON_APPLICATION_CLOSE", currentView);
    settings.sync();
    QMainWindow::closeEvent(event);
}
/**
 * Stores the visibility setting of each widget. This method
 * will only change the settings if the application is not
 * about to close.
 */
void MainWindow::updateVisibilitySettings (bool vis)
{
    if (!aboutToCloseFlag) {

      QDockWidget* temp = qobject_cast<QDockWidget *>(sender());

      if (temp) {
        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()), currentView);
            settings.setValue(chKey,vis);
            settings.sync();
            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())
    {
        if ((static_cast <QDockWidget *>(dockWidgets[i.key()])) == temp)
        {
        QString posKey = buildMenuKey (SUB_SECTION_LOCATION,static_cast<TOOLS_WIDGET_NAMES>(i.key()), currentView);
/**
 * 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::createCustomWidget()
{
    qDebug() << "ADDING CUSTOM WIDGET";
    QGCToolWidget* tool = new QGCToolWidget(this);
    QDockWidget* dock = new QDockWidget("Unnamed Tool", this);
    dock->setWidget(tool);
    this->addDockWidget(Qt::LeftDockWidgetArea, dock);
    dock->setVisible(true);
    // No special connections necessary at this point
    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;
    if (mapWidget && (centerStack->indexOf(mapWidget) == -1)) centerStack->addWidget(mapWidget);
    if (protocolWidget && (centerStack->indexOf(protocolWidget) == -1)) centerStack->addWidget(protocolWidget);

    setCentralWidget(centerStack);
}

void MainWindow::arrangePxCenterStack()
{

  if (!centerStack) {
    qDebug() << "Center Stack not Created!";
    return;
  }


    if (linechartWidget && (centerStack->indexOf(linechartWidget) == -1)) centerStack->addWidget(linechartWidget);
    if (_3DWidget && (centerStack->indexOf(_3DWidget) == -1)) centerStack->addWidget(_3DWidget);
    if (_3DMapWidget && (centerStack->indexOf(_3DMapWidget) == -1)) centerStack->addWidget(_3DMapWidget);
#if (defined _MSC_VER) | (defined Q_OS_MAC)
    if (gEarthWidget && (centerStack->indexOf(gEarthWidget) == -1)) centerStack->addWidget(gEarthWidget);
    if (hudWidget && (centerStack->indexOf(hudWidget) == -1)) centerStack->addWidget(hudWidget);
    if (dataplotWidget && (centerStack->indexOf(dataplotWidget) == -1)) centerStack->addWidget(dataplotWidget);
}

void MainWindow::arrangeSlugsCenterStack()
{

  if (!centerStack) {
    qDebug() << "Center Stack not Created!";
    return;
  }

    if (linechartWidget && (centerStack->indexOf(linechartWidget) == -1)) centerStack->addWidget(linechartWidget);
    if (hudWidget && (centerStack->indexOf(hudWidget) == -1)) 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
}

/**
 * The status message will be overwritten if a new message is posted to this function
 *
 * @param status message text
 * @param timeout how long the status should be displayed
 */
pixhawk's avatar
pixhawk committed
void MainWindow::showStatusMessage(const QString& status, int timeout)
pixhawk's avatar
pixhawk committed
{
    statusBar->showMessage(status, timeout);
pixhawk's avatar
pixhawk committed
}

/**
 * The status message will be overwritten if a new message is posted to this function.
 * it will be automatically hidden after 5 seconds.
 *
 * @param status message text
 */
void MainWindow::showStatusMessage(const QString& status)
pixhawk's avatar
pixhawk committed
{
    statusBar->showMessage(status, 5);
}

void MainWindow::showCriticalMessage(const QString& title, const QString& message)
{
    QMessageBox msgBox(MainWindow::instance());
    msgBox.setIcon(QMessageBox::Critical);
    msgBox.setText(title);
    msgBox.setInformativeText(message);
    msgBox.setStandardButtons(QMessageBox::Ok);
    msgBox.setDefaultButton(QMessageBox::Ok);
    msgBox.exec();
pixhawk's avatar
pixhawk committed
}

/**
* @brief Create all actions associated to the main window
*
**/
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.");