Skip to content
Snippets Groups Projects
MainWindow.cc 81.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • /*=====================================================================
    
    QGroundControl Open Source Ground Control Station
    
    
    (c) 2009 - 2013 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 <QDeclarativeView>
    
    #include "dockwidgettitlebareventfilter.h"
    
    #include "dockwidgeteventfilter.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 "QGCStatusBar.h"
    
    #include "QGCDataPlot2D.h"
    #include "Linecharts.h"
    
    #include "UASActionsWidget.h"
    #include "QGCTabbedInfoView.h"
    #include "UASRawStatusView.h"
    
    #include <apmtoolbar.h>
    #include <ApmHardwareConfig.h>
    #include <ApmSoftwareConfig.h>
    
    #include <QGCConfigView.h>
    
    #include "SerialSettingsDialog.h"
    #include "terminalconsole.h"
    
    
    #ifdef QGC_OSG_ENABLED
    #include "Q3DWidgetFactory.h"
    #endif
    
    // FIXME Move
    #include "PxQuadMAV.h"
    #include "SlugsMAV.h"
    
    #include "LogCompressor.h"
    
    
    // Set up some constants
    const QString MainWindow::defaultDarkStyle = ":files/styles/style-dark.css";
    const QString MainWindow::defaultLightStyle = ":files/styles/style-light.css";
    
    
    MainWindow* MainWindow::instance_mode(QSplashScreen* screen, enum MainWindow::CUSTOM_MODE mode)
    
    {
        static MainWindow* _instance = 0;
    
        {
            _instance = new MainWindow();
    
            _instance->setCustomMode(mode);
    
            if (screen)
            {
                connect(_instance, SIGNAL(initStatusChanged(QString,int,QColor)),
                        screen, SLOT(showMessage(QString,int,QColor)));
            }
            _instance->init();
    
    MainWindow* MainWindow::instance(QSplashScreen* screen)
    {
    
        return instance_mode(screen, CUSTOM_MODE_UNCHANGED);
    
    /**
    * 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_FLIGHT),
    
        currentStyle(QGC_MAINWINDOW_STYLE_DARK),
    
        aboutToCloseFlag(false),
        changingViewsFlag(false),
        centerStackActionGroup(new QActionGroup(this)),
    
        darkStyleFileName(defaultDarkStyle),
        lightStyleFileName(defaultLightStyle),
    
        autoReconnect(false),
    
        simulationLink(NULL),
    
    Lorenz Meier's avatar
    Lorenz Meier committed
        mavlink(new MAVLinkProtocol()),
    
        dockWidgetTitleBarEnabled(true),
    
        customMode(CUSTOM_MODE_NONE)
    
        this->setAttribute(Qt::WA_DeleteOnClose);
    
    Lorenz Meier's avatar
    Lorenz Meier committed
        //TODO:  move protocol outside UI
        connect(mavlink, SIGNAL(protocolStatusMessage(QString,QString)), this, SLOT(showCriticalMessage(QString,QString)), Qt::QueuedConnection);
    
        emit initStatusChanged(tr("Loading style"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
    
        if (currentStyle == QGC_MAINWINDOW_STYLE_LIGHT)
        {
            loadStyle(currentStyle, lightStyleFileName);
        }
        else
        {
            loadStyle(currentStyle, darkStyleFileName);
        }
    
        if (settings.contains("ADVANCED_MODE"))
        {
            isAdvancedMode = settings.value("ADVANCED_MODE").toBool();
        }
    
    
        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_MISSION &&
                    currentViewCandidate != VIEW_FLIGHT &&
    
                    currentViewCandidate != VIEW_FULL)
            {
                currentView = currentViewCandidate;
            }
        }
    
        settings.sync();
    
        emit initStatusChanged(tr("Setting up user interface"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
    
    
        // 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);
    
    
        if (!(getCustomMode() == CUSTOM_MODE_APM)) {
    
            toolBar = new QGCToolBar(this);
            this->addToolBar(toolBar);
    
    
            ui.actionHardwareConfig->setText(tr("Config"));
    
    
            // Add actions for average users (displayed next to each other)
            QList<QAction*> actions;
            actions << ui.actionFlightView;
            actions << ui.actionMissionView;
            actions << ui.actionHardwareConfig;
            toolBar->setPerspectiveChangeActions(actions);
    
            // Add actions for advanced users (displayed in dropdown under "advanced")
            QList<QAction*> advancedActions;
            advancedActions << ui.actionSimulation_View;
            advancedActions << ui.actionEngineersView;
    
            toolBar->setPerspectiveChangeAdvancedActions(advancedActions);
        }
    
        customStatusBar = new QGCStatusBar(this);
    
        setStatusBar(customStatusBar);
        statusBar()->setSizeGripEnabled(true);
    
        emit initStatusChanged(tr("Building common widgets."), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
    
    
        buildCommonWidgets();
        connectCommonWidgets();
    
    
        emit initStatusChanged(tr("Building common actions"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
    
    
        // Create actions
        connectCommonActions();
    
        // Populate link menu
    
        emit initStatusChanged(tr("Populating link menu"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
    
        QList<LinkInterface*> links = LinkManager::instance()->getLinks();
        foreach(LinkInterface* link, links)
        {
            this->addLink(link);
        }
    
        connect(LinkManager::instance(), SIGNAL(newLink(LinkInterface*)), this, SLOT(addLink(LinkInterface*)));
    
    
        if (getCustomMode() == CUSTOM_MODE_APM) {
    
            // Add the APM 'toolbar'
    
            APMToolBar *apmToolBar = new APMToolBar(this);
            apmToolBar->setFlightViewAction(ui.actionFlightView);
            apmToolBar->setFlightPlanViewAction(ui.actionMissionView);
            apmToolBar->setHardwareViewAction(ui.actionHardwareConfig);
            apmToolBar->setSoftwareViewAction(ui.actionSoftwareConfig);
            apmToolBar->setSimulationViewAction(ui.actionSimulation_View);
    
    Lorenz Meier's avatar
    Lorenz Meier committed
            apmToolBar->setTerminalViewAction(ui.actionTerminalView);
    
    
            QDockWidget *widget = new QDockWidget(tr("APM Tool Bar"),this);
            widget->setWidget(apmToolBar);
            widget->setMinimumHeight(72);
            widget->setMaximumHeight(72);
            widget->setMinimumWidth(1024);
            widget->setFeatures(QDockWidget::NoDockWidgetFeatures);
            widget->setTitleBarWidget(new QWidget(this)); // Disables the title bar
        //    /*widget*/->setStyleSheet("QDockWidget { border: 0px solid #FFFFFF; border-radius: 0px; border-bottom: 0px;}");
            this->addDockWidget(Qt::TopDockWidgetArea, widget);
        }
    
        // Connect user interface devices
    
        emit initStatusChanged(tr("Initializing joystick interface"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
    
        joystickWidget = 0;
        joystick = new JoystickInput();
    
    #ifdef MOUSE_ENABLED_WIN
    
        emit initStatusChanged(tr("Initializing 3D mouse interface"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
    
    
        mouseInput = new Mouse3DInput(this);
        mouse = new Mouse6dofInput(mouseInput);
    #endif //MOUSE_ENABLED_WIN
    
    
    #if MOUSE_ENABLED_LINUX
    
        emit initStatusChanged(tr("Initializing 3D mouse interface"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
    
    
        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(tr("Restoring last view state"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
    
    
        // Restore the window setup
        loadViewState();
    
    
        emit initStatusChanged(tr("Restoring last window size"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
    
        // 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(tr("Done"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
    
        show();
    }
    
    MainWindow::~MainWindow()
    {
        if (mavlink)
        {
            delete mavlink;
            mavlink = NULL;
        }
    
        if (simulationLink)
        {
            delete simulationLink;
            simulationLink = NULL;
        }
    
            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
    
    
    
        if (debugConsole)
        {
            delete debugConsole;
        }
        for (int i=0;i<commsWidgetList.size();i++)
        {
            commsWidgetList[i]->deleteLater();
        }
    
    }
    
    void MainWindow::resizeEvent(QResizeEvent * event)
    {
        QMainWindow::resizeEvent(event);
    }
    
    QString MainWindow::getWindowStateKey()
    {
    
        if (UASManager::instance()->getActiveUAS())
        {
            return QString::number(currentView)+"_windowstate_" + UASManager::instance()->getActiveUAS()->getAutopilotTypeName();
        }
        else
    
            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)
            {
    
                QSettings settings;
                settings.beginGroup("QGC_MAINWINDOW");
    
                /*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);
    
    
                // Load dock widget location (default is bottom)
    
                Qt::DockWidgetArea location = tool->getDockWidgetArea(currentView);
    
                //addDockWidget(location, dock);
                //dock->hide();
                int view = settings.value(QString("TOOL_PARENT_") + tool->objectName(),-1).toInt();
                //settings.setValue(QString("TOOL_PARENT_") + "UNNAMED_TOOL_" + QString::number(ui.menuTools->actions().size()),currentView);
                settings.endGroup();
    
    
                QDockWidget* dock;
    
    
                    dock = createDockWidget(engineeringView,tool,tool->getTitle(),tool->objectName(),(VIEW_SECTIONS)view,location);
    
                    dock = createDockWidget(pilotView,tool,tool->getTitle(),tool->objectName(),(VIEW_SECTIONS)view,location);
    
                    dock = createDockWidget(simView,tool,tool->getTitle(),tool->objectName(),(VIEW_SECTIONS)view,location);
    
                    dock = createDockWidget(plannerView,tool,tool->getTitle(),tool->objectName(),(VIEW_SECTIONS)view,location);
    
                case VIEW_MAVLINK:
                    dock = createDockWidget(mavlinkView,tool,tool->getTitle(),tool->objectName(),(VIEW_SECTIONS)view,location);
                    break;
    
                    dock = createDockWidget(centerStack->currentWidget(),tool,tool->getTitle(),tool->objectName(),(VIEW_SECTIONS)view,location);
    
                // XXX temporary "fix"
                dock->hide();
    
    
                //createDockWidget(0,tool,tool->getTitle(),tool->objectName(),view,location);
    
            }
        }
    }
    
    void MainWindow::buildCommonWidgets()
    {
        // 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->setObjectName("VIEW_MISSION");
    
            plannerView->setCentralWidget(new QGCMapTool(this));
    
            addToCentralStackedWidget(plannerView, VIEW_MISSION, "Maps");
    
        //pilotView (aka Flight or Mission View)
    
        if (!pilotView)
        {
            pilotView = new SubMainWindow(this);
    
            pilotView->setObjectName("VIEW_FLIGHT");
    
            pilotView->setCentralWidget(new QGCMapTool(this));
    
            addToCentralStackedWidget(pilotView, VIEW_FLIGHT, "Pilot");
    
        if (getCustomMode() == CUSTOM_MODE_APM) {
    
            if (!configView)
            {
                configView = new SubMainWindow(this);
                configView->setObjectName("VIEW_HARDWARE_CONFIG");
                configView->setCentralWidget(new ApmHardwareConfig(this));
    
    Lorenz Meier's avatar
    Lorenz Meier committed
                addToCentralStackedWidget(configView, VIEW_HARDWARE_CONFIG, "Hardware");
    
            }
            if (!softwareConfigView)
            {
                softwareConfigView = new SubMainWindow(this);
                softwareConfigView->setObjectName("VIEW_SOFTWARE_CONFIG");
                softwareConfigView->setCentralWidget(new ApmSoftwareConfig(this));
    
    Lorenz Meier's avatar
    Lorenz Meier committed
                addToCentralStackedWidget(softwareConfigView, VIEW_SOFTWARE_CONFIG, "Software");
            }
            if (!terminalView)
            {
                terminalView = new SubMainWindow(this);
                terminalView->setObjectName("VIEW_TERMINAL");
                TerminalConsole *terminalConsole = new TerminalConsole(this);
                terminalView->setCentralWidget(terminalConsole);
                addToCentralStackedWidget(terminalView, VIEW_TERMINAL, tr("Terminal View"));
    
            }
        } else {
            if (!configView)
            {
                configView = new SubMainWindow(this);
                configView->setObjectName("VIEW_HARDWARE_CONFIG");
                configView->setCentralWidget(new QGCConfigView(this));
    
    Lorenz Meier's avatar
    Lorenz Meier committed
                addToCentralStackedWidget(configView, VIEW_HARDWARE_CONFIG, "Config");
    
        if (!engineeringView)
        {
            engineeringView = new SubMainWindow(this);
            engineeringView->setObjectName("VIEW_ENGINEER");
    
            engineeringView->setCentralWidget(new QGCDataPlot2D(this));
    
            addToCentralStackedWidget(engineeringView, VIEW_ENGINEER, tr("Logfile Plot"));
    
            mavlinkView = new SubMainWindow(this);
            mavlinkView->setObjectName("VIEW_MAVLINK");
            mavlinkView->setCentralWidget(new XMLCommProtocolWidget(this));
    
            addToCentralStackedWidget(mavlinkView, VIEW_MAVLINK, tr("Mavlink Generator"));
    
        if (!simView)
        {
            simView = new SubMainWindow(this);
            simView->setObjectName("VIEW_SIMULATOR");
            simView->setCentralWidget(new QGCMapTool(this));
    
            addToCentralStackedWidget(simView, VIEW_SIMULATION, tr("Simulation View"));
    
        QAction* tempAction = ui.menuTools->addAction(tr("Control"));
        tempAction->setCheckable(true);
        connect(tempAction,SIGNAL(triggered(bool)),this, SLOT(showTool(bool)));
    
    
        createDockWidget(simView,new UASControlWidget(this),tr("Control"),"UNMANNED_SYSTEM_CONTROL_DOCKWIDGET",VIEW_SIMULATION,Qt::LeftDockWidgetArea);
    
        createDockWidget(plannerView,new UASListWidget(this),tr("Unmanned Systems"),"UNMANNED_SYSTEM_LIST_DOCKWIDGET",VIEW_MISSION,Qt::LeftDockWidgetArea);
    
        createDockWidget(plannerView,new QGCWaypointListMulti(this),tr("Mission Plan"),"WAYPOINT_LIST_DOCKWIDGET",VIEW_MISSION,Qt::BottomDockWidgetArea);
    
            //createDockWidget(plannerView,new QGCWaypointListMulti(this),tr("Mission Plan"),"WAYPOINT_LIST_DOCKWIDGET",VIEW_MISSION,Qt::BottomDockWidgetArea);
            QAction* tempAction = ui.menuTools->addAction(tr("Mission Plan"));
            tempAction->setCheckable(true);
            connect(tempAction,SIGNAL(triggered(bool)),this, SLOT(showTool(bool)));
            menuToDockNameMap[tempAction] = "WAYPOINT_LIST_DOCKWIDGET";
    
        createDockWidget(simView,new QGCWaypointListMulti(this),tr("Mission Plan"),"WAYPOINT_LIST_DOCKWIDGET",VIEW_SIMULATION,Qt::BottomDockWidgetArea);
        createDockWidget(engineeringView,new QGCMAVLinkInspector(mavlink,this),tr("MAVLink Inspector"),"MAVLINK_INSPECTOR_DOCKWIDGET",VIEW_ENGINEER,Qt::RightDockWidgetArea);
    
        createDockWidget(engineeringView,new ParameterInterface(this),tr("Onboard Parameters"),"PARAMETER_INTERFACE_DOCKWIDGET",VIEW_ENGINEER,Qt::RightDockWidgetArea);
        createDockWidget(simView,new ParameterInterface(this),tr("Onboard Parameters"),"PARAMETER_INTERFACE_DOCKWIDGET",VIEW_SIMULATION,Qt::RightDockWidgetArea);
    
            QAction* tempAction = ui.menuTools->addAction(tr("Status Details"));
    
            menuToDockNameMap[tempAction] = "UAS_STATUS_DETAILS_DOCKWIDGET";
    
            tempAction->setCheckable(true);
            connect(tempAction,SIGNAL(triggered(bool)),this, SLOT(showTool(bool)));
    
            if (!debugConsole)
            {
                debugConsole = new DebugConsole();
                debugConsole->setWindowTitle("Communications Console");
    
                QAction* tempAction = ui.menuTools->addAction(tr("Communication Console"));
                //menuToDockNameMap[tempAction] = "COMMUNICATION_DEBUG_CONSOLE_DOCKWIDGET";
                tempAction->setCheckable(true);
                connect(tempAction,SIGNAL(triggered(bool)),debugConsole,SLOT(setShown(bool)));
    
            }
    
        }
        createDockWidget(simView,new HSIDisplay(this),tr("Horizontal Situation"),"HORIZONTAL_SITUATION_INDICATOR_DOCKWIDGET",VIEW_SIMULATION,Qt::BottomDockWidgetArea);
    
            QAction* tempAction = ui.menuTools->addAction(tr("Flight Display"));
            tempAction->setCheckable(true);
            connect(tempAction,SIGNAL(triggered(bool)),this, SLOT(showTool(bool)));
            menuToDockNameMap[tempAction] = "HEAD_DOWN_DISPLAY_1_DOCKWIDGET";
    
            QAction* tempAction = ui.menuTools->addAction(tr("Actuator Status"));
            tempAction->setCheckable(true);
            connect(tempAction,SIGNAL(triggered(bool)),this, SLOT(showTool(bool)));
            menuToDockNameMap[tempAction] = "HEAD_DOWN_DISPLAY_2_DOCKWIDGET";
    
            QAction* tempAction = ui.menuTools->addAction(tr("Radio Control"));
            tempAction->setCheckable(true);
            connect(tempAction,SIGNAL(triggered(bool)),this, SLOT(showTool(bool)));
    
        createDockWidget(engineeringView,new HUD(320,240,this),tr("Video Downlink"),"HEAD_UP_DISPLAY_DOCKWIDGET",VIEW_ENGINEER,Qt::RightDockWidgetArea,this->width()/1.5);
    
        createDockWidget(engineeringView,new HUD(320,240,this),tr("Video Downlink"),"HEAD_UP_DISPLAY_DOCKWIDGET",VIEW_ENGINEER,Qt::RightDockWidgetArea,this->width()/1.5);
    
        createDockWidget(simView,new PrimaryFlightDisplay(320,240,this),tr("Primary Flight Display"),"PRIMARY_FLIGHT_DISPLAY_DOCKWIDGET",VIEW_SIMULATION,Qt::RightDockWidgetArea,this->width()/1.5);
    
        createDockWidget(pilotView,new PrimaryFlightDisplay(320,240,this),tr("Primary Flight Display"),"PRIMARY_FLIGHT_DISPLAY_DOCKWIDGET",VIEW_FLIGHT,Qt::LeftDockWidgetArea,this->width()/1.8);
    
        QGCTabbedInfoView *infoview = new QGCTabbedInfoView(this);
    
        infoview->addSource(mavlinkDecoder);
    
        createDockWidget(pilotView,infoview,tr("Info View"),"UAS_INFO_INFOVIEW_DOCKWIDGET",VIEW_FLIGHT,Qt::LeftDockWidgetArea);
    
    
    
        //createDockWidget(pilotView,new HUD(320,240,this),tr("Head Up Display"),"HEAD_UP_DISPLAY_DOCKWIDGET",VIEW_FLIGHT,Qt::LeftDockWidgetArea,this->width()/1.8);
    
    
    //    createDockWidget(pilotView,new UASQuickView(this),tr("Quick View"),"UAS_INFO_QUICKVIEW_DOCKWIDGET",VIEW_FLIGHT,Qt::LeftDockWidgetArea);
    //    createDockWidget(pilotView,new HSIDisplay(this),tr("Horizontal Situation"),"HORIZONTAL_SITUATION_INDICATOR_DOCKWIDGET",VIEW_FLIGHT,Qt::LeftDockWidgetArea);
    //    pilotView->setTabPosition(Qt::LeftDockWidgetArea,QTabWidget::North);
    //    pilotView->tabifyDockWidget((QDockWidget*)centralWidgetToDockWidgetsMap[VIEW_FLIGHT]["HORIZONTAL_SITUATION_INDICATOR_DOCKWIDGET"],(QDockWidget*)centralWidgetToDockWidgetsMap[VIEW_FLIGHT]["UAS_INFO_QUICKVIEW_DOCKWIDGET"]);
    
    
        //UASRawStatusView *view = new UASRawStatusView();
        //view->setDecoder(mavlinkDecoder);
        //view->show();
    
        //hddisplay->addSource(mavlinkDecoder);
    
        //createDockWidget(pilotView,new HSIDisplay(this),tr("Horizontal Situation"),"HORIZONTAL_SITUATION_INDICATOR_DOCKWIDGET",VIEW_FLIGHT,Qt::LeftDockWidgetArea);
        //pilotView->setTabPosition(Qt::LeftDockWidgetArea,QTabWidget::North);
        //pilotView->tabifyDockWidget((QDockWidget*)centralWidgetToDockWidgetsMap[VIEW_FLIGHT]["HORIZONTAL_SITUATION_INDICATOR_DOCKWIDGET"],(QDockWidget*)centralWidgetToDockWidgetsMap[VIEW_FLIGHT]["UAS_INFO_QUICKVIEW_DOCKWIDGET"]);
    
    
        //createDockWidget(pilotView,new UASActionsWidget(this),tr("Actions"),"UNMANNED_SYSTEM_ACTION_DOCKWIDGET",VIEW_FLIGHT,Qt::RightDockWidgetArea);
    
    
        // 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"));
    
        if (q3DWidget)
    
            q3DWidget = Q3DWidgetFactory::get("PIXHAWK", this);
            q3DWidget->setObjectName("VIEW_3DWIDGET");
    
            addToCentralStackedWidget(q3DWidget, VIEW_3DWIDGET, tr("Local 3D"));
    
    #if (defined _MSC_VER) /*| (defined Q_OS_MAC) mac os doesn't support gearth right now */
    
    akistanov's avatar
    akistanov committed
        if (!earthWidget)
    
            earthWidget = new QGCGoogleEarthView(this);
            addToCentralStackedWidget(earthWidget,VIEW_GOOGLEEARTH, tr("Google Earth"));
    
    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] = widget->objectName();
    
            if (!centralWidgetToDockWidgetsMap.contains(view))
            {
                centralWidgetToDockWidgetsMap[view] = QMap<QString,QWidget*>();
            }
    
            centralWidgetToDockWidgetsMap[view][widget->objectName()]= widget;
    
            connect(tempAction,SIGNAL(triggered(bool)),this, SLOT(showTool(bool)));
            connect(widget, SIGNAL(visibilityChanged(bool)), tempAction, SLOT(setChecked(bool)));
    
            connect(widget, SIGNAL(destroyed()), tempAction, SLOT(deleteLater()));
    
            tempAction->setChecked(widget->isVisible());
        }
    
        else
        {
            if (!menuToDockNameMap.contains(targetAction))
            {
    
                menuToDockNameMap[targetAction] = widget->objectName();
                //menuToDockNameMap[targetAction] = title;
    
            }
            if (!centralWidgetToDockWidgetsMap.contains(view))
            {
                centralWidgetToDockWidgetsMap[view] = QMap<QString,QWidget*>();
            }
    
            centralWidgetToDockWidgetsMap[view][widget->objectName()]= widget;
    
            connect(widget, SIGNAL(visibilityChanged(bool)), targetAction, SLOT(setChecked(bool)));
        }
    
    QDockWidget* MainWindow::createDockWidget(QWidget *parent,QWidget *child,QString title,QString objectname,VIEW_SECTIONS view,Qt::DockWidgetArea area,int minwidth,int minheight)
    
        QDockWidget *widget = new QDockWidget(title,this);
    
        dockWidgets.append(widget);
        setDockWidgetTitleBar(widget);
    
        widget->setWidget(child);
        if (minheight != 0 || minwidth != 0)
        {
            widget->setMinimumHeight(minheight);
            widget->setMinimumWidth(minwidth);
        }
        addTool(qobject_cast<SubMainWindow*>(parent),view,widget,title,area);
    
        connect(child, SIGNAL(destroyed()), widget, SLOT(deleteLater()));
        connect(widget, SIGNAL(destroyed()), this, SLOT(dockWidgetDestroyed()));
    
    
        return widget;
    
    void MainWindow::dockWidgetDestroyed()
    {
        QDockWidget *dock = dynamic_cast<QDockWidget *>(QObject::sender());
        Q_ASSERT(dock);
        if(!dock) return;
    
        dockWidgets.removeAll(dock);
    }
    
    
    void MainWindow::loadDockWidget(QString name)
    {
        if (centralWidgetToDockWidgetsMap[currentView].contains(name))
        {
            return;
        }
    
        if (name.startsWith("HIL_CONFIG"))
        {
            //It's a HIL widget.
            showHILConfigurationWidget(UASManager::instance()->getActiveUAS());
        }
        else if (name == "UNMANNED_SYSTEM_CONTROL_DOCKWIDGET")
    
        {
            createDockWidget(centerStack->currentWidget(),new UASControlWidget(this),tr("Control"),"UNMANNED_SYSTEM_CONTROL_DOCKWIDGET",currentView,Qt::LeftDockWidgetArea);
        }
        else if (name == "UNMANNED_SYSTEM_LIST_DOCKWIDGET")
        {
            createDockWidget(centerStack->currentWidget(),new UASListWidget(this),tr("Unmanned Systems"),"UNMANNED_SYSTEM_LIST_DOCKWIDGET",currentView,Qt::RightDockWidgetArea);
        }
        else if (name == "WAYPOINT_LIST_DOCKWIDGET")
        {
            createDockWidget(centerStack->currentWidget(),new QGCWaypointListMulti(this),tr("Mission Plan"),"WAYPOINT_LIST_DOCKWIDGET",currentView,Qt::BottomDockWidgetArea);
        }
        else if (name == "MAVLINK_INSPECTOR_DOCKWIDGET")
        {
            createDockWidget(centerStack->currentWidget(),new QGCMAVLinkInspector(mavlink,this),tr("MAVLink Inspector"),"MAVLINK_INSPECTOR_DOCKWIDGET",currentView,Qt::RightDockWidgetArea);
        }
        else if (name == "PARAMETER_INTERFACE_DOCKWIDGET")
        {
            createDockWidget(centerStack->currentWidget(),new ParameterInterface(this),tr("Onboard Parameters"),"PARAMETER_INTERFACE_DOCKWIDGET",currentView,Qt::RightDockWidgetArea);
        }
        else if (name == "UAS_STATUS_DETAILS_DOCKWIDGET")
        {
            createDockWidget(centerStack->currentWidget(),new UASInfoWidget(this),tr("Status Details"),"UAS_STATUS_DETAILS_DOCKWIDGET",currentView,Qt::RightDockWidgetArea);
        }
        else if (name == "COMMUNICATION_DEBUG_CONSOLE_DOCKWIDGET")
        {
    
            //This is now a permanently detached window.
            //centralWidgetToDockWidgetsMap[currentView][name] = console;
            //createDockWidget(centerStack->currentWidget(),new DebugConsole(this),tr("Communication Console"),"COMMUNICATION_DEBUG_CONSOLE_DOCKWIDGET",currentView,Qt::BottomDockWidgetArea);
    
        }
        else if (name == "HORIZONTAL_SITUATION_INDICATOR_DOCKWIDGET")
        {
            createDockWidget(centerStack->currentWidget(),new HSIDisplay(this),tr("Horizontal Situation"),"HORIZONTAL_SITUATION_INDICATOR_DOCKWIDGET",currentView,Qt::BottomDockWidgetArea);
        }
        else if (name == "HEAD_DOWN_DISPLAY_1_DOCKWIDGET")
        {
            //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");
            HDDisplay *hddisplay = new HDDisplay(acceptList,"Flight Display",this);
            hddisplay->addSource(mavlinkDecoder);
            createDockWidget(centerStack->currentWidget(),hddisplay,tr("Flight Display"),"HEAD_DOWN_DISPLAY_1_DOCKWIDGET",currentView,Qt::RightDockWidgetArea);
        }
        else if (name == "HEAD_DOWN_DISPLAY_2_DOCKWIDGET")
        {
            //FIXME: memory of acceptList2 will never be freed again
            QStringList* acceptList2 = new QStringList();
            acceptList2->append("0,RAW_PRESSURE.pres_abs,hPa,65500");
            HDDisplay *hddisplay = new HDDisplay(acceptList2,"Actuator Status",this);
            hddisplay->addSource(mavlinkDecoder);
            createDockWidget(centerStack->currentWidget(),hddisplay,tr("Actuator Status"),"HEAD_DOWN_DISPLAY_2_DOCKWIDGET",currentView,Qt::RightDockWidgetArea);
        }
        else if (name == "Radio Control")
        {
            qDebug() << "Error loading window:" << name << "Unknown window type";
            //createDockWidget(centerStack->currentWidget(),hddisplay,tr("Actuator Status"),"HEADS_DOWN_DISPLAY_2_DOCKWIDGET",currentView,Qt::RightDockWidgetArea);
        }
    
        else if (name == "PRIMARY_FLIGHT_DISPLAY_DOCKWIDGET")
    
            // createDockWidget(centerStack->currentWidget(),new HUD(320,240,this),tr("Head Up Display"),"PRIMARY_FLIGHT_DISPLAY_DOCKWIDGET",currentView,Qt::RightDockWidgetArea);
            createDockWidget(centerStack->currentWidget(),new PrimaryFlightDisplay(320,240,this),tr("Primary Flight Display"),"HEAD_UP_DISPLAY_DOCKWIDGET",currentView,Qt::RightDockWidgetArea);
    
        else if (name == "UAS_INFO_QUICKVIEW_DOCKWIDGET")
        {
            createDockWidget(centerStack->currentWidget(),new UASQuickView(this),tr("Quick View"),"UAS_INFO_QUICKVIEW_DOCKWIDGET",currentView,Qt::LeftDockWidgetArea);
        }
    
            if (customWidgetNameToFilenameMap.contains(name))
            {
                loadCustomWidget(customWidgetNameToFilenameMap[name],currentView);
                //customWidgetNameToFilenameMap.remove(name);
            }
            else
            {
                qDebug() << "Error loading window:" << name;
            }
    
    void MainWindow::setDockWidgetTitleBar(QDockWidget* widget)
    {
        QWidget* oldTitleBar = widget->titleBarWidget();
    
        // In advanced mode, we use the default titlebar provided by Qt.
        if (isAdvancedMode)
        {
            widget->setTitleBarWidget(0);
        }
        // Otherwise, if just a textlabel should be shown, make that the titlebar.
        else if (dockWidgetTitleBarEnabled)
        {
            QLabel* label = new QLabel(this);
            label->setText(widget->windowTitle());
    
            label->installEventFilter(new DockWidgetTitleBarEventFilter()); //Ignore mouse clicks
            widget->installEventFilter(new DockWidgetEventFilter()); //Update label if window title changes
    
            widget->setTitleBarWidget(label);
        }
        // And if nothing should be shown, use an empty widget.
        else
        {
            QWidget* newTitleBar = new QWidget(this);
            widget->setTitleBarWidget(newTitleBar);
        }
    
        // Be sure to clean up the old titlebar. When using QDockWidget::setTitleBarWidget(),
        // it doesn't delete the old titlebar object.
        if (oldTitleBar)
        {
            delete oldTitleBar;
        }
    }
    
    
    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))
                {
    
                    if (show)
                    {
                        centralWidgetToDockWidgetsMap[currentView][name]->show();
                    }
                    else
                    {
                        centralWidgetToDockWidgetsMap[currentView][name]->hide();
                    }
    
                }
            }
        }
        //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::addToCentralStackedWidget(QWidget* widget, VIEW_SECTIONS viewSection, const QString& title)
    
        Q_UNUSED(title);
    
        Q_ASSERT(widget->objectName().length() != 0);
    
        // Check if this widget already has been added
        if (centerStack->indexOf(widget) == -1)
        {
            centerStack->addWidget(widget);
    
            centralWidgetToDockWidgetsMap[viewSection] = QMap<QString,QWidget*>();
    
        }
    }
    
    
    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()))
    
            //QGCToolWidget* tool = new QGCToolWidget("Unnamed Tool " + QString::number(ui.menuTools->actions().size()));
            //createDockWidget(centerStack->currentWidget(),tool,"Unnamed Tool " + QString::number(ui.menuTools->actions().size()),"UNNAMED_TOOL_" + QString::number(ui.menuTools->actions().size())+"DOCK",currentView,Qt::BottomDockWidgetArea);