Skip to content
MainWindow.cc 77.1 KiB
Newer Older
/*=====================================================================

QGroundControl Open Source Ground Control Station

(c) 2009 - 2011 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>

This file is part of the QGROUNDCONTROL project

    QGROUNDCONTROL is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    QGROUNDCONTROL is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.

======================================================================*/

/**
 * @file
 *   @brief Implementation of class MainWindow
 *   @author Lorenz Meier <mail@qgroundcontrol.org>
 */

#include <QSettings>
#include <QDockWidget>
#include <QNetworkInterface>
#include <QMessageBox>
#include <QDebug>
#include <QTimer>
#include <QHostInfo>
#include <QSplashScreen>
#include <QGCHilLink.h>
#include <QGCHilConfiguration.h>
#include <QGCHilFlightGearConfiguration.h>

#include "QGC.h"
#include "MAVLinkSimulationLink.h"
#include "SerialLink.h"
#include "UDPLink.h"
#include "MAVLinkProtocol.h"
#include "CommConfigurationWindow.h"
#include "QGCWaypointListMulti.h"
#include "MainWindow.h"
#include "JoystickWidget.h"
#include "GAudioOutput.h"
#include "QGCToolWidget.h"
#include "QGCMAVLinkLogPlayer.h"
#include "QGCSettingsWidget.h"
#include "QGCMapTool.h"
#include "MAVLinkDecoder.h"
#include "QGCMAVLinkMessageSender.h"
#include "QGCRGBDView.h"
#include "QGCFirmwareUpdate.h"
#include "QGCStatusBar.h"

#ifdef QGC_OSG_ENABLED
#include "Q3DWidgetFactory.h"
#endif

// FIXME Move
#include "PxQuadMAV.h"
#include "SlugsMAV.h"


#include "LogCompressor.h"

MainWindow* MainWindow::instance(QSplashScreen* screen)
{
    static MainWindow* _instance = 0;
    if(_instance == 0)
    {
        _instance = new MainWindow();
        if (screen) connect(_instance, SIGNAL(initStatusChanged(QString)), screen, SLOT(showMessage(QString)));

        /* Set the application as parent to ensure that this object
                 * will be destroyed when the main application exits */
        //_instance->setParent(qApp);
    }
    return _instance;
}

/**
* 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()
**/
MainWindow::MainWindow(QWidget *parent):
    QMainWindow(parent),
    currentView(VIEW_UNCONNECTED),
    currentStyle(QGC_MAINWINDOW_STYLE_INDOOR),
    aboutToCloseFlag(false),
    changingViewsFlag(false),
    centerStackActionGroup(new QActionGroup(this)),
    styleFileName(QCoreApplication::applicationDirPath() + "/style-indoor.css"),
    autoReconnect(false),
    lowPowerMode(false)
{
    hide();
    emit initStatusChanged("Loading UI Settings..");
    loadSettings();
    if (!settings.contains("CURRENT_VIEW"))
    {
        // Set this view as default view
        settings.setValue("CURRENT_VIEW", currentView);
    }
    else
    {
        // LOAD THE LAST VIEW
        VIEW_SECTIONS currentViewCandidate = (VIEW_SECTIONS) settings.value("CURRENT_VIEW", currentView).toInt();
        if (currentViewCandidate != VIEW_ENGINEER &&
                currentViewCandidate != VIEW_OPERATOR &&
                currentViewCandidate != VIEW_PILOT &&
                currentViewCandidate != VIEW_FULL)
        {
            currentView = currentViewCandidate;
        }
    }

    settings.sync();

    emit initStatusChanged("Loading Style.");
    loadStyle(currentStyle);

    emit initStatusChanged("Setting up user interface.");

    // Setup user interface
    ui.setupUi(this);
    hide();

Lorenz Meier's avatar
Lorenz Meier committed
    // We only need this menu if we have more than one system
//    ui.menuConnected_Systems->setEnabled(false);
    // Set dock options
    setDockOptions(AnimatedDocks | AllowTabbedDocks | AllowNestedDocks);

    configureWindowName();

    // Setup corners
    setCorner(Qt::BottomRightCorner, Qt::BottomDockWidgetArea);

    // Setup UI state machines
	centerStackActionGroup->setExclusive(true);

    centerStack = new QStackedWidget(this);
    setCentralWidget(centerStack);

    // Load Toolbar
    toolBar = new QGCToolBar(this);
    this->addToolBar(toolBar);
    // Add actions (inverted order due to insert)
Lorenz Meier's avatar
Lorenz Meier committed

    QList<QAction*> actions;

    actions << ui.actionOperatorsView;
    actions << ui.actionPilotsView;
    actions << ui.actionEngineersView;
    actions << ui.actionSimulation_View;
Lorenz Meier's avatar
Lorenz Meier committed
    toolBar->setPerspectiveChangeActions(actions);

    customStatusBar = new QGCStatusBar(this);
    setStatusBar(customStatusBar);
    statusBar()->setSizeGripEnabled(true);

    emit initStatusChanged("Building common widgets.");

    buildCommonWidgets();
    connectCommonWidgets();

    emit initStatusChanged("Building common actions.");

    // Create actions
    connectCommonActions();

    // Populate link menu
    emit initStatusChanged("Populating link menu");
    QList<LinkInterface*> links = LinkManager::instance()->getLinks();
    foreach(LinkInterface* link, links)
    {
        this->addLink(link);
    }

    connect(LinkManager::instance(), SIGNAL(newLink(LinkInterface*)), this, SLOT(addLink(LinkInterface*)));

    // Connect user interface devices
    emit initStatusChanged("Initializing joystick interface.");
    joystickWidget = 0;
    joystick = new JoystickInput();

#ifdef MOUSE_ENABLED_WIN
    emit initStatusChanged("Initializing 3D mouse interface.");

    mouseInput = new Mouse3DInput(this);
    mouse = new Mouse6dofInput(mouseInput);
#endif //MOUSE_ENABLED_WIN

#if MOUSE_ENABLED_LINUX
    emit initStatusChanged("Initializing 3D mouse interface.");

    mouse = new Mouse6dofInput(this);
    connect(this, SIGNAL(x11EventOccured(XEvent*)), mouse, SLOT(handleX11Event(XEvent*)));
#endif //MOUSE_ENABLED_LINUX

    // Connect link
    if (autoReconnect)
    {
        SerialLink* link = new SerialLink();
        // Add to registry
        LinkManager::instance()->add(link);
        LinkManager::instance()->addProtocol(link, mavlink);
        link->connect();
    }

    // Set low power mode
    enableLowPowerMode(lowPowerMode);

    // Initialize window state
    windowStateVal = windowState();

    emit initStatusChanged("Restoring last view state.");

    // Restore the window setup
    loadViewState();

    emit initStatusChanged("Restoring last window size.");
    // Restore the window position and size
    if (settings.contains(getWindowGeometryKey()))
    {
        // Restore the window geometry
        restoreGeometry(settings.value(getWindowGeometryKey()).toByteArray());
        show();
    }
    else
    {
        // Adjust the size
        const int screenWidth = QApplication::desktop()->width();
        const int screenHeight = QApplication::desktop()->height();

Lorenz Meier's avatar
Lorenz Meier committed
        if (screenWidth < 1500)
            resize(screenWidth, screenHeight - 80);
            show();
        }
        else
        {
            resize(screenWidth*0.67f, qMin(screenHeight, (int)(screenWidth*0.67f*0.67f)));
            show();
        }

    }

    connect(&windowNameUpdateTimer, SIGNAL(timeout()), this, SLOT(configureWindowName()));
    windowNameUpdateTimer.start(15000);
    emit initStatusChanged("Done.");
    show();
}

MainWindow::~MainWindow()
{
    if (mavlink)
    {
        delete mavlink;
        mavlink = NULL;
    }
//    if (simulationLink)
//    {
//        simulationLink->deleteLater();
//        simulationLink = NULL;
//    }
    if (joystick)
    {
        joystick->shutdown();
        joystick->wait(5000);
        delete joystick;
        joystick = NULL;
    }

    // Get and delete all dockwidgets and contained
    // widgets
    QObjectList childList(this->children());

    QObjectList::iterator i;
    QDockWidget* dockWidget;
    for (i = childList.begin(); i != childList.end(); ++i)
    {
        dockWidget = dynamic_cast<QDockWidget*>(*i);
        if (dockWidget)
        {
            // Remove dock widget from main window
            // removeDockWidget(dockWidget);
            // delete dockWidget->widget();
            delete dockWidget;
            dockWidget = NULL;
        }
        else if (dynamic_cast<QWidget*>(*i))
        {
            delete dynamic_cast<QWidget*>(*i);
            *i = NULL;
        }
    }
    // Delete all UAS objects
}

void MainWindow::resizeEvent(QResizeEvent * event)
{
    if (width() > 1200)
    {
        toolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
    }
    else
    {
        toolBar->setToolButtonStyle(Qt::ToolButtonIconOnly);
    }

    QMainWindow::resizeEvent(event);
}

QString MainWindow::getWindowStateKey()
{
    return QString::number(currentView)+"_windowstate";
}

QString MainWindow::getWindowGeometryKey()
{
    //return QString::number(currentView)+"_geometry";
    return "_geometry";
}

void MainWindow::buildCustomWidget()
{
    // Create custom widgets
    QList<QGCToolWidget*> widgets = QGCToolWidget::createWidgetsFromSettings(this);

    if (widgets.size() > 0)
    {
        ui.menuTools->addSeparator();
    }

    for(int i = 0; i < widgets.size(); ++i)
    {
        // Check if this widget already has a parent, do not create it in this case
        QGCToolWidget* tool = widgets.at(i);
        QDockWidget* dock = dynamic_cast<QDockWidget*>(tool->parentWidget());
        if (!dock)
        {
            QDockWidget* dock = new QDockWidget(tool->windowTitle(), this);
            dock->setObjectName(tool->objectName()+"_DOCK");
            dock->setWidget(tool);
            connect(tool, SIGNAL(destroyed()), dock, SLOT(deleteLater()));
            QAction* showAction = new QAction(widgets.at(i)->windowTitle(), this);
            showAction->setCheckable(true);
            connect(showAction, SIGNAL(triggered(bool)), dock, SLOT(setVisible(bool)));
            connect(dock, SIGNAL(visibilityChanged(bool)), showAction, SLOT(setChecked(bool)));
            widgets.at(i)->setMainMenuAction(showAction);
            ui.menuTools->addAction(showAction);

            // Load dock widget location (default is bottom)
            Qt::DockWidgetArea location = static_cast <Qt::DockWidgetArea>(tool->getDockWidgetArea(currentView));

            addDockWidget(location, dock);
        }
    }
}

void MainWindow::buildCommonWidgets()
{
    //TODO:  move protocol outside UI
    mavlink     = new MAVLinkProtocol();
    connect(mavlink, SIGNAL(protocolStatusMessage(QString,QString)), this, SLOT(showCriticalMessage(QString,QString)), Qt::QueuedConnection);
    // Add generic MAVLink decoder
    mavlinkDecoder = new MAVLinkDecoder(mavlink, this);

    // Log player
    logPlayer = new QGCMAVLinkLogPlayer(mavlink, customStatusBar);
    customStatusBar->setLogPlayer(logPlayer);


    // Center widgets
    if (!plannerView)
    {
        plannerView = new SubMainWindow(this);
        plannerView->setCentralWidget(new QGCMapTool(this));
        //mapWidget = new QGCMapTool(this);
        addCentralWidget(plannerView, "Maps");
    }

    //pilotView
    if (!pilotView)
    {
        pilotView = new SubMainWindow(this);
        pilotView->setObjectName("VIEW_PILOT");
        pilotView->setCentralWidget(new HUD(320,240,this));
        //hudWidget         = new HUD(320, 240, this);
        //addCentralWidget(hudWidget, tr("Head Up Display"));
        //mapWidget = new QGCMapTool(this);
        addCentralWidget(pilotView, "Pilot");
    }
    if (!configView)
    {
        configView = new SubMainWindow(this);
        configView->setObjectName("VIEW_CONFIGURATION");
        configView->setCentralWidget(new QGCVehicleConfig(this));
        addCentralWidget(configView,"Config");

    }
    if (!engineeringView)
    {
        engineeringView = new SubMainWindow(this);
        engineeringView->setObjectName("VIEW_ENGINEER");
        engineeringView->setCentralWidget(new XMLCommProtocolWidget(this));
        addCentralWidget(engineeringView,"Mavlink Generator");
    }
    if (!dataView)
    {
        dataView = new SubMainWindow(this);
        dataView->setObjectName("VIEW_DATA");
        dataView->setCentralWidget(new QGCDataPlot2D(this));
        addCentralWidget(dataView,tr("Logfile Plot"));
    }
    if (!simView)
    {
        simView = new SubMainWindow(this);
        simView->setObjectName("VIEW_SIMULATOR");
        simView->setCentralWidget(new QGCMapTool(this));
        addCentralWidget(simView,tr("Simulation View"));
    }

    /*    QAction* tempAction = ui.menuTools->addAction(title);

    tempAction->setCheckable(true);
    QVariant var;
    var.setValue((QWidget*)widget);
    tempAction->setData(var);
    connect(tempAction,SIGNAL(triggered(bool)),this, SLOT(showTool(bool)));
    connect(widget, SIGNAL(visibilityChanged(bool)), tempAction, SLOT(setChecked(bool)));
    tempAction->setChecked(widget->isVisible());
    addDockWidget(area, widget);*/

    QAction* tempAction = ui.menuTools->addAction(tr("Control"));
    tempAction->setCheckable(true);
    connect(tempAction,SIGNAL(triggered(bool)),this, SLOT(showTool(bool)));

    if (!controlDockWidget)
    {
        controlDockWidget = new QDockWidget(tr("Control"), this);
        dockToTitleBarMap[controlDockWidget] = controlDockWidget->titleBarWidget();
        controlDockWidget->setTitleBarWidget(new QWidget(this));
        controlDockWidget->setObjectName("UNMANNED_SYSTEM_CONTROL_DOCKWIDGET");
        controlDockWidget->setWidget( new UASControlWidget(this) );
        //addTool(controlDockWidget, tr("Control"), Qt::LeftDockWidgetArea);
        addTool(simView,VIEW_SIMULATION,controlDockWidget,tr("Control"),Qt::LeftDockWidgetArea);


        //addDockWidgetToWindow()
       /* QDockWidget *widget = new QDockWidget(tr("Control"), plannerView);
        dockToTitleBarMap[widget] = widget->titleBarWidget();
        widget->setTitleBarWidget(new QWidget(this));
        widget->setObjectName("UNMANNED_SYSTEM_CONTROL_DOCKWIDGET");
        widget->setWidget( new UASControlWidget(this) );
        plannerView->addDockWidget(Qt::LeftDockWidgetArea, widget);

        centralWidgetToDockWidgetsMap["Maps"]["Control"] = widget;
        QAction* tempAction = ui.menuTools->addAction("Control");
        tempAction->setCheckable(true);
        connect(tempAction,SIGNAL(triggered(bool)),this, SLOT(showTool(bool)));
        tempAction->setChecked(widget->isVisible());*/
        /*listDockWidget = new QDockWidget(tr("Unmanned Systems"), this);
        dockToTitleBarMap[listDockWidget] = listDockWidget->titleBarWidget();
        listDockWidget->setTitleBarWidget(new QWidget(this));
        listDockWidget->setWidget( new UASListWidget(this) );
        listDockWidget->setObjectName("UNMANNED_SYSTEMS_LIST_DOCKWIDGET");
        addTool(listDockWidget, tr("Unmanned Systems"), Qt::RightDockWidgetArea);*/
        QDockWidget *listDockWidget1 = new QDockWidget(/*tr("Unmanned Systems"), */this);
        dockToTitleBarMap[listDockWidget1] = listDockWidget1->titleBarWidget();
        listDockWidget1->setTitleBarWidget(new QWidget(this));
        listDockWidget1->setWidget( new UASListWidget(this) );
        listDockWidget1->setObjectName("UNMANNED_SYSTEMS_LIST_DOCKWIDGET");
        addTool(pilotView,VIEW_PILOT,listDockWidget1, tr("Unmanned Systems"), Qt::RightDockWidgetArea);
        QDockWidget *listDockWidget2 = new QDockWidget(/*tr("Unmanned Systems"), */this);
        dockToTitleBarMap[listDockWidget2] = listDockWidget2->titleBarWidget();
        listDockWidget2->setTitleBarWidget(new QWidget(this));
        listDockWidget2->setWidget( new UASListWidget(this) );
        listDockWidget2->setObjectName("UNMANNED_SYSTEMS_LIST_DOCKWIDGET");
        addTool(plannerView,VIEW_OPERATOR,listDockWidget2, tr("Unmanned Systems"), Qt::RightDockWidgetArea);

        //pilotView
        //plannerView
        /*waypointsDockWidget = new QDockWidget(tr("Mission Plan"), this);
        waypointsDockWidget->setWidget( new QGCWaypointListMulti(this) );
        dockToTitleBarMap[waypointsDockWidget] = waypointsDockWidget->titleBarWidget();
        waypointsDockWidget->setTitleBarWidget(new QWidget(this));
        waypointsDockWidget->setObjectName("WAYPOINT_LIST_DOCKWIDGET");
        addTool(waypointsDockWidget, tr("Mission Plan"), Qt::BottomDockWidgetArea);*/

        QDockWidget *waypointsDockWidget1 = new QDockWidget(tr("Mission Plan"), this);
        waypointsDockWidget1->setWidget( new QGCWaypointListMulti(this) );
        dockToTitleBarMap[waypointsDockWidget1] = waypointsDockWidget1->titleBarWidget();
        waypointsDockWidget1->setTitleBarWidget(new QWidget(this));
        waypointsDockWidget1->setObjectName("WAYPOINT_LIST_DOCKWIDGET");
        addTool(plannerView,VIEW_OPERATOR,waypointsDockWidget1, tr("Mission Plan"), Qt::BottomDockWidgetArea);

        QDockWidget *waypointsDockWidget2 = new QDockWidget(tr("Mission Plan"), this);
        waypointsDockWidget2->setWidget( new QGCWaypointListMulti(this) );
        dockToTitleBarMap[waypointsDockWidget2] = waypointsDockWidget2->titleBarWidget();
        waypointsDockWidget2->setTitleBarWidget(new QWidget(this));
        waypointsDockWidget2->setObjectName("WAYPOINT_LIST_DOCKWIDGET");
        addTool(simView,VIEW_SIMULATION,waypointsDockWidget2, tr("Mission Plan"), Qt::BottomDockWidgetArea);



        //plannerView
        //simView
        /*infoDockWidget = new QDockWidget(tr("Status Details"), this);
        dockToTitleBarMap[infoDockWidget] = infoDockWidget->titleBarWidget();
        infoDockWidget->setTitleBarWidget(new QWidget(this));
        infoDockWidget->setWidget( new UASInfoWidget(this) );
        infoDockWidget->setObjectName("UAS_STATUS_DETAILS_DOCKWIDGET");
        addTool(infoDockWidget, tr("Status Details"), Qt::RightDockWidgetArea);*/
        QAction* tempAction = ui.menuTools->addAction(tr("Status Details"));
        tempAction->setCheckable(true);
        connect(tempAction,SIGNAL(triggered(bool)),this, SLOT(showTool(bool)));
        //connect(widget, SIGNAL(visibilityChanged(bool)), tempAction, SLOT(setChecked(bool)));
        //tempAction->setChecked(widget->isVisible());
        debugConsoleDockWidget = new QDockWidget(tr("Communication Console"), this);
        dockToTitleBarMap[debugConsoleDockWidget] = debugConsoleDockWidget->titleBarWidget();
        debugConsoleDockWidget->setTitleBarWidget(new QWidget(this));
        debugConsoleDockWidget->setWidget( new DebugConsole(this) );
        debugConsoleDockWidget->setObjectName("COMMUNICATION_DEBUG_CONSOLE_DOCKWIDGET");

        DebugConsole *debugConsole = dynamic_cast<DebugConsole*>(debugConsoleDockWidget->widget());
        connect(mavlinkDecoder, SIGNAL(textMessageReceived(int, int, int, const QString)), debugConsole, SLOT(receiveTextMessage(int, int, int, const QString)));

        addTool(debugConsoleDockWidget, tr("Communication Console"), Qt::BottomDockWidgetArea);*/
        QAction* tempAction = ui.menuTools->addAction(tr("Communication Console"));
        tempAction->setCheckable(true);
        connect(tempAction,SIGNAL(triggered(bool)),this, SLOT(showTool(bool)));
//    if (!logPlayerDockWidget)
//    {
//        logPlayerDockWidget = new QDockWidget(tr("MAVLink Log Player"), this);
//        logPlayer = new QGCMAVLinkLogPlayer(mavlink, this);
//        customStatusBar->setLogPlayer(logPlayer);
//        logPlayerDockWidget->setWidget(logPlayer);
//        logPlayerDockWidget->setObjectName("MAVLINK_LOG_PLAYER_DOCKWIDGET");
//        addTool(logPlayerDockWidget, tr("MAVLink Log Replay"), Qt::RightDockWidgetArea);
//    }

    if (!mavlinkInspectorWidget)
    {
        /*mavlinkInspectorWidget = new QDockWidget(tr("MAVLink Message Inspector"), this);
        dockToTitleBarMap[mavlinkInspectorWidget] = mavlinkInspectorWidget->titleBarWidget();
        mavlinkInspectorWidget->setTitleBarWidget(new QWidget(this));
        mavlinkInspectorWidget->setWidget( new QGCMAVLinkInspector(mavlink, this) );
        mavlinkInspectorWidget->setObjectName("MAVLINK_INSPECTOR_DOCKWIDGET");
        addTool(mavlinkInspectorWidget, tr("MAVLink Inspector"), Qt::RightDockWidgetArea);*/


        QDockWidget *mavlinkInspectorWidget1 = new QDockWidget(tr("MAVLink Message Inspector"), this);
        dockToTitleBarMap[mavlinkInspectorWidget1] = mavlinkInspectorWidget1->titleBarWidget();
        mavlinkInspectorWidget1->setTitleBarWidget(new QWidget(this));
        mavlinkInspectorWidget1->setWidget( new QGCMAVLinkInspector(mavlink, this) );
        mavlinkInspectorWidget1->setObjectName("MAVLINK_INSPECTOR_DOCKWIDGET");
        addTool(engineeringView,VIEW_ENGINEER,mavlinkInspectorWidget1, tr("MAVLink Inspector"), Qt::RightDockWidgetArea);

    }

    if (!mavlinkSenderWidget)
    {
//        mavlinkSenderWidget = new QDockWidget(tr("MAVLink Message Sender"), this);
//        mavlinkSenderWidget->setWidget( new QGCMAVLinkMessageSender(mavlink, this) );
//        mavlinkSenderWidget->setObjectName("MAVLINK_SENDER_DOCKWIDGET");
//        addTool(mavlinkSenderWidget, tr("MAVLink Sender"), Qt::RightDockWidgetArea);
    }

    //FIXME: memory of acceptList will never be freed again
    QStringList* acceptList = new QStringList();
    acceptList->append("-3.3,ATTITUDE.roll,rad,+3.3,s");
    acceptList->append("-3.3,ATTITUDE.pitch,deg,+3.3,s");
    acceptList->append("-3.3,ATTITUDE.yaw,deg,+3.3,s");

    //FIXME: memory of acceptList2 will never be freed again
    QStringList* acceptList2 = new QStringList();
    acceptList2->append("0,RAW_PRESSURE.pres_abs,hPa,65500");

    if (!parametersDockWidget)
    {
        /*parametersDockWidget = new QDockWidget(tr("Onboard Parameters"), this);
        dockToTitleBarMap[parametersDockWidget] = parametersDockWidget->titleBarWidget();
        parametersDockWidget->setTitleBarWidget(new QWidget(this));
        parametersDockWidget->setWidget( new ParameterInterface(this) );
        parametersDockWidget->setObjectName("PARAMETER_INTERFACE_DOCKWIDGET");
        addTool(parametersDockWidget, tr("Onboard Parameters"), Qt::RightDockWidgetArea);*/

        QDockWidget *parametersDockWidget1 = new QDockWidget(tr("Onboard Parameters"), this);
        dockToTitleBarMap[parametersDockWidget1] = parametersDockWidget1->titleBarWidget();
        parametersDockWidget1->setTitleBarWidget(new QWidget(this));
        parametersDockWidget1->setWidget( new ParameterInterface(this) );
        parametersDockWidget1->setObjectName("PARAMETER_INTERFACE_DOCKWIDGET");
        addTool(engineeringView,VIEW_ENGINEER,parametersDockWidget1, tr("Onboard Parameters"), Qt::RightDockWidgetArea);

        QDockWidget *parametersDockWidget2 = new QDockWidget(tr("Onboard Parameters"), this);
        dockToTitleBarMap[parametersDockWidget2] = parametersDockWidget2->titleBarWidget();
        parametersDockWidget2->setTitleBarWidget(new QWidget(this));
        parametersDockWidget2->setWidget( new ParameterInterface(this) );
        parametersDockWidget2->setObjectName("PARAMETER_INTERFACE_DOCKWIDGET");
        addTool(simView,VIEW_SIMULATION,parametersDockWidget2, tr("Onboard Parameters"), Qt::RightDockWidgetArea);
        /*hsiDockWidget = new QDockWidget(tr("Horizontal Situation Indicator"), this);
        dockToTitleBarMap[hsiDockWidget] = hsiDockWidget->titleBarWidget();
        hsiDockWidget->setTitleBarWidget(new QWidget(this));
        hsiDockWidget->setWidget( new HSIDisplay(this) );
        hsiDockWidget->setObjectName("HORIZONTAL_SITUATION_INDICATOR_DOCK_WIDGET");
        addTool(hsiDockWidget, tr("Horizontal Situation"), Qt::BottomDockWidgetArea);*/

        QDockWidget *hsiDockWidget1 = new QDockWidget(tr("Horizontal Situation Indicator"), this);
        dockToTitleBarMap[hsiDockWidget1] = hsiDockWidget1->titleBarWidget();
        hsiDockWidget1->setTitleBarWidget(new QWidget(this));
        hsiDockWidget1->setWidget( new HSIDisplay(this) );
        hsiDockWidget1->setObjectName("HORIZONTAL_SITUATION_INDICATOR_DOCK_WIDGET");
        addTool(pilotView,VIEW_PILOT,hsiDockWidget1, tr("Horizontal Situation"), Qt::BottomDockWidgetArea);

        QDockWidget *hsiDockWidget2 = new QDockWidget(tr("Horizontal Situation Indicator"), this);
        dockToTitleBarMap[hsiDockWidget2] = hsiDockWidget2->titleBarWidget();
        hsiDockWidget2->setTitleBarWidget(new QWidget(this));
        hsiDockWidget2->setWidget( new HSIDisplay(this) );
        hsiDockWidget2->setObjectName("HORIZONTAL_SITUATION_INDICATOR_DOCK_WIDGET");
        addTool(simView,VIEW_SIMULATION,hsiDockWidget2, tr("Horizontal Situation"), Qt::BottomDockWidgetArea);
       /* headDown1DockWidget = new QDockWidget(tr("Flight Display"), this);
        dockToTitleBarMap[headDown1DockWidget] = headDown1DockWidget->titleBarWidget();
        headDown1DockWidget->setTitleBarWidget(new QWidget(this));
        HDDisplay* hdDisplay = new HDDisplay(acceptList, "Flight Display", this);
        hdDisplay->addSource(mavlinkDecoder);
        headDown1DockWidget->setWidget(hdDisplay);
        headDown1DockWidget->setObjectName("HEAD_DOWN_DISPLAY_1_DOCK_WIDGET");*/
        //addTool(headDown1DockWidget, tr("Flight Display"), Qt::RightDockWidgetArea);

        QDockWidget *headDown1DockWidget1 = new QDockWidget(tr("Flight Display"), this);
        dockToTitleBarMap[headDown1DockWidget1] = headDown1DockWidget1->titleBarWidget();
        headDown1DockWidget1->setTitleBarWidget(new QWidget(this));
        HDDisplay* hdDisplay = new HDDisplay(acceptList, "Flight Display", this);
        hdDisplay->addSource(mavlinkDecoder);
        headDown1DockWidget1->setWidget(hdDisplay);
        headDown1DockWidget1->setObjectName("HEAD_DOWN_DISPLAY_1_DOCK_WIDGET");
        addTool(pilotView,VIEW_PILOT,headDown1DockWidget1, tr("Flight Display"), Qt::RightDockWidgetArea);

        /*headDown2DockWidget = new QDockWidget(tr("Actuator Status"), this);
        dockToTitleBarMap[headDown2DockWidget] = headDown2DockWidget->titleBarWidget();
        headDown2DockWidget->setTitleBarWidget(new QWidget(this));
        HDDisplay* hdDisplay = new HDDisplay(acceptList2, "Actuator Status", this);
        hdDisplay->addSource(mavlinkDecoder);
        headDown2DockWidget->setWidget(hdDisplay);
        headDown2DockWidget->setObjectName("HEAD_DOWN_DISPLAY_2_DOCK_WIDGET");
        //addTool(headDown2DockWidget, tr("Actuator Status"), Qt::RightDockWidgetArea);*/


        QDockWidget *headDown2DockWidget1 = new QDockWidget(tr("Actuator Status"), this);
        dockToTitleBarMap[headDown2DockWidget1] = headDown2DockWidget1->titleBarWidget();
        headDown2DockWidget1->setTitleBarWidget(new QWidget(this));
        HDDisplay* hdDisplay = new HDDisplay(acceptList2, "Actuator Status", this);
        hdDisplay->addSource(mavlinkDecoder);
        headDown2DockWidget1->setWidget(hdDisplay);
        headDown2DockWidget1->setObjectName("HEAD_DOWN_DISPLAY_2_DOCK_WIDGET");
        addTool(pilotView,VIEW_PILOT,headDown2DockWidget1, tr("Actuator Status"), Qt::RightDockWidgetArea);
        /*rcViewDockWidget = new QDockWidget(tr("Radio Control"), this);
        dockToTitleBarMap[rcViewDockWidget] = rcViewDockWidget->titleBarWidget();
        rcViewDockWidget->setTitleBarWidget(new QWidget(this));
        rcViewDockWidget->setWidget( new QGCRemoteControlView(this) );
        rcViewDockWidget->setObjectName("RADIO_CONTROL_CHANNELS_DOCK_WIDGET");*/
        QAction* tempAction = ui.menuTools->addAction(tr("Radio Control"));
        tempAction->setCheckable(true);
        connect(tempAction,SIGNAL(triggered(bool)),this, SLOT(showTool(bool)));
        //addTool(rcViewDockWidget, tr("Radio Control"), Qt::BottomDockWidgetArea);
        /*headUpDockWidget = new QDockWidget(tr("HUD"), this);
        dockToTitleBarMap[headUpDockWidget] = headUpDockWidget->titleBarWidget();
        headUpDockWidget->setTitleBarWidget(new QWidget(this));
        headUpDockWidget->setWidget( new HUD(320, 240, this));
        headUpDockWidget->setObjectName("HEAD_UP_DISPLAY_DOCK_WIDGET");*/
       // addTool(headUpDockWidget, tr("Head Up Display"), Qt::RightDockWidgetArea);

        QDockWidget *headUpDockWidget1 = new QDockWidget(tr("HUD"), this);
        dockToTitleBarMap[headUpDockWidget1] = headUpDockWidget1->titleBarWidget();
        headUpDockWidget1->setTitleBarWidget(new QWidget(this));
        headUpDockWidget1->setWidget( new HUD(320, 240, this));
        headUpDockWidget1->setObjectName("HEAD_UP_DISPLAY_DOCK_WIDGET");
        headUpDockWidget1->setMinimumWidth(this->width()/1.5);
        addTool(simView,VIEW_SIMULATION,headUpDockWidget1, tr("Head Up Display"), Qt::RightDockWidgetArea);
       /* video1DockWidget = new QDockWidget(tr("Video Stream 1"), this);
        dockToTitleBarMap[video1DockWidget] = video1DockWidget->titleBarWidget();
        video1DockWidget->setTitleBarWidget(new QWidget(this));
        QGCRGBDView* video1 =  new QGCRGBDView(160, 120, this);
        video1->enableHUDInstruments(false);
        video1->enableVideo(false);
        // FIXME select video stream as well
        video1DockWidget->setWidget(video1);
        video1DockWidget->setObjectName("VIDEO_STREAM_1_DOCK_WIDGET");*/
        //addTool(video1DockWidget, tr("Video Stream 1"), Qt::LeftDockWidgetArea);
        /*video2DockWidget = new QDockWidget(tr("Video Stream 2"), this);
        dockToTitleBarMap[video2DockWidget] = video2DockWidget->titleBarWidget();
        video2DockWidget->setTitleBarWidget(new QWidget(this));
        QGCRGBDView* video2 =  new QGCRGBDView(160, 120, this);
        video2->enableHUDInstruments(false);
        video2->enableVideo(false);
        // FIXME select video stream as well
        video2DockWidget->setWidget(video2);
        video2DockWidget->setObjectName("VIDEO_STREAM_2_DOCK_WIDGET");*/
       // addTool(video2DockWidget, tr("Video Stream 2"), Qt::LeftDockWidgetArea);
    }//

//    if (!rgbd1DockWidget) {
//        rgbd1DockWidget = new QDockWidget(tr("Video Stream 1"), this);
//        HUD* video1 =  new HUD(160, 120, this);
//        video1->enableHUDInstruments(false);
//        video1->enableVideo(true);
//        // FIXME select video stream as well
//        video1DockWidget->setWidget(video1);
//        video1DockWidget->setObjectName("VIDEO_STREAM_1_DOCK_WIDGET");
//        addTool(video1DockWidget, tr("Video Stream 1"), Qt::LeftDockWidgetArea);
//    }

//    if (!rgbd2DockWidget) {
//        video2DockWidget = new QDockWidget(tr("Video Stream 2"), this);
//        HUD* video2 =  new HUD(160, 120, this);
//        video2->enableHUDInstruments(false);
//        video2->enableVideo(true);
//        // FIXME select video stream as well
//        video2DockWidget->setWidget(video2);
//        video2DockWidget->setObjectName("VIDEO_STREAM_2_DOCK_WIDGET");
//        addTool(video2DockWidget, tr("Video Stream 2"), Qt::LeftDockWidgetArea);
//    }

    // Custom widgets, added last to all menus and layouts
    buildCustomWidget();


    {
        protocolWidget    = new XMLCommProtocolWidget(this);
        addCentralWidget(protocolWidget, "Mavlink Generator");

//    if (!firmwareUpdateWidget)
//    {
//        firmwareUpdateWidget    = new QGCFirmwareUpdate(this);
//        addCentralWidget(firmwareUpdateWidget, "Firmware Update");
//    }

    {
        hudWidget         = new HUD(320, 240, this);
        addCentralWidget(hudWidget, tr("Head Up Display"));
    {
        configWidget = new QGCVehicleConfig(this);
        addCentralWidget(configWidget, tr("Vehicle Configuration"));
    {
        dataplotWidget    = new QGCDataPlot2D(this);
        addCentralWidget(dataplotWidget, tr("Logfile Plot"));

#ifdef QGC_OSG_ENABLED
    if (!_3DWidget)
    {
        _3DWidget         = Q3DWidgetFactory::get("PIXHAWK", this);
        addCentralWidget(_3DWidget, tr("Local 3D"));
    }
#endif

#if (defined _MSC_VER) | (defined Q_OS_MAC)
    if (!gEarthWidget)
    {
        gEarthWidget = new QGCGoogleEarthView(this);
        addCentralWidget(gEarthWidget, tr("Google Earth"));
    }
#endif
}

void MainWindow::addTool(SubMainWindow *parent,VIEW_SECTIONS view,QDockWidget* widget, const QString& title, Qt::DockWidgetArea area)
    QList<QAction*> actionlist = ui.menuTools->actions();
    bool found = false;
    for (int i=0;i<actionlist.size();i++)
    {
        if (actionlist[i]->text() == title)
        {
            found = true;
        }
    }
    if (!found)
    {
        QAction* tempAction = ui.menuTools->addAction(title);
        tempAction->setCheckable(true);
        menuToDockNameMap[tempAction] = title;
        if (!centralWidgetToDockWidgetsMap.contains(view))
        {
            centralWidgetToDockWidgetsMap[view] = QMap<QString,QWidget*>();
        }
        centralWidgetToDockWidgetsMap[view][title]= widget;
        connect(tempAction,SIGNAL(triggered(bool)),this, SLOT(showTool(bool)));
        connect(widget, SIGNAL(visibilityChanged(bool)), tempAction, SLOT(setChecked(bool)));
        tempAction->setChecked(widget->isVisible());
    }
    parent->addDockWidget(area,widget);
}


void MainWindow::showTool(bool show)
{
    //Called when a menu item is clicked on, regardless of view.

    QAction* act = qobject_cast<QAction *>(sender());
    if (menuToDockNameMap.contains(act))
    {
        QString name = menuToDockNameMap[act];
        if (centralWidgetToDockWidgetsMap.contains(currentView))
        {
            if (centralWidgetToDockWidgetsMap[currentView].contains(name))
            {
                centralWidgetToDockWidgetsMap[currentView][name]->show();
            }
            else
            {
                //if (name == )
            }
        }
    }
    //QWidget* widget = qVariantValue<QWidget *>(act->data());
    //widget->setVisible(show);
}
/*void addToolByName(QString name,SubMainWindow parent,const QString& title, Qt::DockWidgetArea area)
{
    if (name == "Control")
    {
        QDockWidget *widget = new QDockWidget(tr("Control"),this);
        dockToTitleBarMap[widget] = widget->titleBarWidget();
        widget->setObjectName("UNMANNED_SYSTEM_CONTROL_DOCKWIDGET");
        widget->setWidget(new UASControlWidget(this));
        addTool(parent,VIEW_SIMULATION,widget,tr("Control"),area);
    }
}*/
void MainWindow::addCentralWidget(QWidget* widget, const QString& title)
{
    // Check if this widget already has been added
    if (centerStack->indexOf(widget) == -1)
    {
        centerStack->addWidget(widget);

        QAction* tempAction = ui.menuMain->addAction(title);

        tempAction->setCheckable(true);
        QVariant var;
        var.setValue((QWidget*)widget);
        tempAction->setData(var);
        centerStackActionGroup->addAction(tempAction);
        connect(tempAction,SIGNAL(triggered()),this, SLOT(showCentralWidget()));
        connect(widget, SIGNAL(visibilityChanged(bool)), tempAction, SLOT(setChecked(bool)));
        tempAction->setChecked(widget->isVisible());
    }
}


void MainWindow::showCentralWidget()
{
    QAction* act = qobject_cast<QAction *>(sender());
    QWidget* widget = qVariantValue<QWidget *>(act->data());
    centerStack->setCurrentWidget(widget);
}

void MainWindow::showHILConfigurationWidget(UASInterface* uas)
{
    // Add simulation configuration widget
    UAS* mav = dynamic_cast<UAS*>(uas);

    if (mav && !hilDocks.contains(mav->getUASID()))
    {
        QGCHilConfiguration* hconf = new QGCHilConfiguration(mav, this);
        QString hilDockName = tr("HIL Config (%1)").arg(uas->getUASName());
        QDockWidget* hilDock = new QDockWidget(hilDockName, this);
        hilDock->setWidget(hconf);
        hilDock->setObjectName(QString("HIL_CONFIG_%1").arg(uas->getUASID()));
        //addTool(hilDock, hilDockName, Qt::LeftDockWidgetArea);
        hilDocks.insert(mav->getUASID(), hilDock);
        if (currentView != VIEW_SIMULATION)
            hilDock->hide();
        else
            hilDock->show();
    }
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    if (isVisible()) storeViewState();
    storeSettings();
    aboutToCloseFlag = true;
    mavlink->storeSettings();
    UASManager::instance()->storeSettings();
    QMainWindow::closeEvent(event);
}

/**
 * Connect the signals and slots of the common window widgets
 */
void MainWindow::connectCommonWidgets()
{
    if (infoDockWidget && infoDockWidget->widget())
    {
        connect(mavlink, SIGNAL(receiveLossChanged(int, float)),
                infoDockWidget->widget(), SLOT(updateSendLoss(int, float)));
    }
}

void MainWindow::createCustomWidget()
{
    QDockWidget* dock = new QDockWidget("Unnamed Tool", this);
    QGCToolWidget* tool = new QGCToolWidget("Unnamed Tool", dock);

    if (QGCToolWidget::instances()->size() < 2)
    {
        // This is the first widget
        ui.menuTools->addSeparator();
    }

    connect(tool, SIGNAL(destroyed()), dock, SLOT(deleteLater()));
    dock->setWidget(tool);

    QAction* showAction = new QAction(tool->getTitle(), this);
    showAction->setCheckable(true);
    connect(dock, SIGNAL(visibilityChanged(bool)), showAction, SLOT(setChecked(bool)));
    connect(showAction, SIGNAL(triggered(bool)), dock, SLOT(setVisible(bool)));
    tool->setMainMenuAction(showAction);
    ui.menuTools->addAction(showAction);
    this->addDockWidget(Qt::BottomDockWidgetArea, dock);
    dock->setVisible(true);