Skip to content
Snippets Groups Projects
MainWindow.cc 50.3 KiB
Newer Older
  • Learn to ignore specific revisions
  • /*===================================================================
    
    pixhawk's avatar
    pixhawk committed
    ======================================================================*/
    
    /**
     * @file
    
     *   @brief Implementation of class MainWindow
    
     *   @author Lorenz Meier <mail@qgroundcontrol.org>
    
    pixhawk's avatar
    pixhawk committed
     */
    
    #include <QSettings>
    #include <QDockWidget>
    #include <QNetworkInterface>
    #include <QMessageBox>
    #include <QDebug>
    #include <QTimer>
    #include <QHostInfo>
    
    #include "MG.h"
    
    #include "QGC.h"
    
    pixhawk's avatar
    pixhawk committed
    #include "MAVLinkSimulationLink.h"
    #include "SerialLink.h"
    #include "UDPLink.h"
    #include "MAVLinkProtocol.h"
    #include "CommConfigurationWindow.h"
    #include "WaypointList.h"
    #include "MainWindow.h"
    #include "JoystickWidget.h"
    
    pixhawk's avatar
    pixhawk committed
    #include "GAudioOutput.h"
    
    #ifdef QGC_OSG_ENABLED
    
    #include "Q3DWidgetFactory.h"
    
    pixhawk's avatar
    pixhawk committed
    
    
    lm's avatar
    lm committed
    // FIXME Move
    #include "PxQuadMAV.h"
    #include "SlugsMAV.h"
    
    
    pixhawk's avatar
    pixhawk committed
    
    #include "LogCompressor.h"
    
    
    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_ENGINEER),
    
            aboutToCloseFlag(false),
    
            changingViewsFlag(false)
    
    pixhawk's avatar
    pixhawk committed
    {
    
        if (!settings.contains("CURRENT_VIEW"))
        {
            // Set this view as default view
            settings.setValue("CURRENT_VIEW", currentView);
    
            // Enable default tools
    
            // ENABLE UAS LIST
            settings.setValue(buildMenuKey(SUB_SECTION_CHECKED,MainWindow::MENU_UAS_LIST,currentView), true);
            // ENABLE COMMUNICATION CONSOLE
            settings.setValue(buildMenuKey(SUB_SECTION_CHECKED,MainWindow::MENU_DEBUG_CONSOLE,currentView), true);
        }
        else
        {
    
            if (settings.value("CURRENT_VIEW", VIEW_PILOT) != VIEW_PILOT)
            {
                currentView = (VIEW_SECTIONS) settings.value("CURRENT_VIEW", currentView).toInt();
            }
    
        // Check if the settings exist, instantiate defaults if necessary
    
    
        // OPERATOR VIEW DEFAULT
        QString centralKey = buildMenuKey(SUB_SECTION_CHECKED, CENTRAL_MAP, VIEW_OPERATOR);
        if (!settings.contains(centralKey))
        {
            settings.setValue(centralKey,true);
        }
    
        // ENGINEER VIEW DEFAULT
        centralKey = buildMenuKey(SUB_SECTION_CHECKED, CENTRAL_LINECHART, VIEW_ENGINEER);
        if (!settings.contains(centralKey))
        {
            settings.setValue(centralKey,true);
        }
    
        // MAVLINK VIEW DEFAULT
        centralKey = buildMenuKey(SUB_SECTION_CHECKED, CENTRAL_PROTOCOL, VIEW_MAVLINK);
        if (!settings.contains(centralKey))
        {
            settings.setValue(centralKey,true);
        }
    
        // PILOT VIEW DEFAULT
        centralKey = buildMenuKey(SUB_SECTION_CHECKED, CENTRAL_HUD, VIEW_PILOT);
    
        if (!settings.contains(centralKey))
        {
            settings.setValue(centralKey,true);
    
        }
    
        QString listKey = buildMenuKey(SUB_SECTION_CHECKED, MENU_UAS_LIST, currentView);
        if (!settings.contains(listKey))
        {
    
    pixhawk's avatar
    pixhawk committed
        // Setup user interface
        ui.setupUi(this);
    
    
        // Bind together the perspective actions
        QActionGroup* perspectives = new QActionGroup(ui.menuPerspectives);
        perspectives->addAction(ui.actionEngineersView);
        perspectives->addAction(ui.actionMavlinkView);
        perspectives->addAction(ui.actionPilotsView);
        perspectives->addAction(ui.actionOperatorsView);
        perspectives->setExclusive(true);
    
        // Mark the right one as selected
        if (currentView == VIEW_ENGINEER) ui.actionEngineersView->setChecked(true);
        if (currentView == VIEW_MAVLINK) ui.actionMavlinkView->setChecked(true);
        if (currentView == VIEW_PILOT) ui.actionPilotsView->setChecked(true);
        if (currentView == VIEW_OPERATOR) ui.actionOperatorsView->setChecked(true);
    
        // The pilot view is not available on startup
        ui.actionPilotsView->setEnabled(false);
    
    
    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
    
        QFile* 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/");
            qApp->setStyleSheet(style);
        }
    
    pixhawk's avatar
    pixhawk committed
    
    
        // 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
    
    lm's avatar
    lm committed
        statusBar()->setSizeGripEnabled(true);
    
    
        // Restore the window position and size
        if (settings.contains(getWindowGeometryKey()))
    
            restoreGeometry(settings.value(getWindowGeometryKey()).toByteArray());
    
    pixhawk's avatar
    pixhawk committed
    
    
        // Populate 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*)));
    
    
    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
    {
    
    pixhawk's avatar
    pixhawk committed
    }
    
    
    QString MainWindow::getWindowStateKey()
    {
        return QString::number(currentView)+"/windowstate";
    }
    
    QString MainWindow::getWindowGeometryKey()
    {
        return QString::number(currentView)+"/geometry";
    }
    
    
    void MainWindow::buildCommonWidgets()
    {
        //TODO:  move protocol outside UI
        mavlink     = new MAVLinkProtocol();
    
        connect(mavlink, SIGNAL(protocolStatusMessage(QString,QString)), this, SLOT(showCriticalMessage(QString,QString)), Qt::QueuedConnection);
    
        if (!controlDockWidget)
        {
            controlDockWidget = new QDockWidget(tr("Control"), this);
    
            controlDockWidget->setObjectName("UNMANNED_SYSTEM_CONTROL_DOCKWIDGET");
    
            controlDockWidget->setWidget( new UASControlWidget(this) );
            addToToolsMenu (controlDockWidget, tr("Control"), SLOT(showToolWidget()), MENU_UAS_CONTROL, Qt::LeftDockWidgetArea);
        }
    
        if (!listDockWidget)
        {
            listDockWidget = new QDockWidget(tr("Unmanned Systems"), this);
            listDockWidget->setWidget( new UASListWidget(this) );
    
            listDockWidget->setObjectName("UNMANNED_SYSTEMS_LIST_DOCKWIDGET");
    
            addToToolsMenu (listDockWidget, tr("Unmanned Systems"), SLOT(showToolWidget()), MENU_UAS_LIST, Qt::RightDockWidgetArea);
        }
    
        if (!waypointsDockWidget)
        {
            waypointsDockWidget = new QDockWidget(tr("Waypoint List"), this);
            waypointsDockWidget->setWidget( new WaypointList(this, NULL) );
    
            waypointsDockWidget->setObjectName("WAYPOINT_LIST_DOCKWIDGET");
    
            addToToolsMenu (waypointsDockWidget, tr("Waypoints List"), SLOT(showToolWidget()), MENU_WAYPOINTS, Qt::BottomDockWidgetArea);
        }
    
        if (!infoDockWidget)
        {
            infoDockWidget = new QDockWidget(tr("Status Details"), this);
            infoDockWidget->setWidget( new UASInfoWidget(this) );
    
    pixhawk's avatar
    pixhawk committed
            infoDockWidget->setObjectName("UAS_STATUS_DETAILS_DOCKWIDGET");
    
            addToToolsMenu (infoDockWidget, tr("Status Details"), SLOT(showToolWidget()), MENU_STATUS, Qt::RightDockWidgetArea);
        }
    
        if (!debugConsoleDockWidget)
        {
            debugConsoleDockWidget = new QDockWidget(tr("Communication Console"), this);
            debugConsoleDockWidget->setWidget( new DebugConsole(this) );
    
            debugConsoleDockWidget->setObjectName("COMMUNICATION_DEBUG_CONSOLE_DOCKWIDGET");
    
            addToToolsMenu (debugConsoleDockWidget, tr("Communication Console"), SLOT(showToolWidget()), MENU_DEBUG_CONSOLE, Qt::BottomDockWidgetArea);
        }
    
        if (!logPlayerDockWidget)
        {
            logPlayerDockWidget = new QDockWidget(tr("MAVLink Log Player"), this);
            logPlayerDockWidget->setWidget( new QGCMAVLinkLogPlayer(mavlink, this) );
            logPlayerDockWidget->setObjectName("MAVLINK_LOG_PLAYER_DOCKWIDGET");
            addToToolsMenu(logPlayerDockWidget, tr("MAVLink Log Replay"), SLOT(showToolWidget()), MENU_MAVLINK_LOG_PLAYER, Qt::RightDockWidgetArea);
        }
    
    
        if (!mapWidget)
        {
            mapWidget         = new MapWidget(this);
            addToCentralWidgetsMenu (mapWidget, "Maps", SLOT(showCentralWidget()),CENTRAL_MAP);
        }
    
        if (!protocolWidget)
        {
            protocolWidget    = new XMLCommProtocolWidget(this);
            addToCentralWidgetsMenu (protocolWidget, "Mavlink Generator", SLOT(showCentralWidget()),CENTRAL_PROTOCOL);
        }
    
    lm's avatar
    lm committed
    
        if (!dataplotWidget)
        {
            dataplotWidget    = new QGCDataPlot2D(this);
            addToCentralWidgetsMenu (dataplotWidget, "Data Plot", SLOT(showCentralWidget()),CENTRAL_DATA_PLOT);
        }
    
    pixhawk's avatar
    pixhawk committed
        //FIXME: memory of acceptList will never be freed again
        QStringList* acceptList = new QStringList();
    
    lm's avatar
    lm committed
        acceptList->append("-105,roll,deg,+105,s");
        acceptList->append("-105,pitch,deg,+105,s");
        acceptList->append("-105,yaw,deg,+105,s");
    
    lm's avatar
    lm committed
        acceptList->append("-260,rollspeed,deg/s,+260,s");
        acceptList->append("-260,pitchspeed,deg/s,+260,s");
        acceptList->append("-260,yawspeed,deg/s,+260,s");
    
    pixhawk's avatar
    pixhawk committed
        //FIXME: memory of acceptList2 will never be freed again
        QStringList* acceptList2 = new QStringList();
    
    lm's avatar
    lm committed
        acceptList2->append("0,abs pressure,hPa,65500");
    
        acceptList2->append("-999,accel. X,raw,999,s");
        acceptList2->append("-999,accel. Y,raw,999,s");
    
        if (!linechartWidget)
        {
            // Center widgets
            linechartWidget   = new Linecharts(this);
            addToCentralWidgetsMenu(linechartWidget, "Line Plots", SLOT(showCentralWidget()), CENTRAL_LINECHART);
        }
    
        if (!hudWidget)
        {
            hudWidget         = new HUD(320, 240, this);
            addToCentralWidgetsMenu(hudWidget, "HUD", SLOT(showCentralWidget()), CENTRAL_HUD);
        }
    
        if (!dataplotWidget)
        {
            dataplotWidget    = new QGCDataPlot2D(this);
            addToCentralWidgetsMenu(dataplotWidget, "Data Plots", SLOT(showCentralWidget()), CENTRAL_DATA_PLOT);
        }
    
        if (!_3DWidget)
        {
            _3DWidget         = Q3DWidgetFactory::get("PIXHAWK");
            addToCentralWidgetsMenu(_3DWidget, "Local 3D", SLOT(showCentralWidget()), CENTRAL_3D_LOCAL);
        }
    
    #ifdef QGC_OSGEARTH_ENABLED
    
        if (!_3DMapWidget)
        {
            _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)
    
        if (!gEarthWidget)
        {
            gEarthWidget = new QGCGoogleEarthView(this);
            addToCentralWidgetsMenu(gEarthWidget, "Google Earth", SLOT(showCentralWidget()), CENTRAL_GOOGLE_EARTH);
        }
    
    pixhawk's avatar
    pixhawk committed
        // Dock widgets
    
        if (!detectionDockWidget)
        {
            detectionDockWidget = new QDockWidget(tr("Object Recognition"), this);
            detectionDockWidget->setWidget( new ObjectDetectionView("images/patterns", this) );
    
    pixhawk's avatar
    pixhawk committed
            detectionDockWidget->setObjectName("OBJECT_DETECTION_DOCK_WIDGET");
    
            addToToolsMenu (detectionDockWidget, tr("Object Recognition"), SLOT(showToolWidget()), MENU_DETECTION, Qt::RightDockWidgetArea);
        }
    
        if (!parametersDockWidget)
        {
            parametersDockWidget = new QDockWidget(tr("Onboard Parameters"), this);
            parametersDockWidget->setWidget( new ParameterInterface(this) );
    
    pixhawk's avatar
    pixhawk committed
            parametersDockWidget->setObjectName("PARAMETER_INTERFACE_DOCKWIDGET");
    
            addToToolsMenu (parametersDockWidget, tr("Onboard Parameters"), SLOT(showToolWidget()), MENU_PARAMETERS, Qt::RightDockWidgetArea);
        }
    
        if (!watchdogControlDockWidget)
        {
            watchdogControlDockWidget = new QDockWidget(tr("Process Control"), this);
            watchdogControlDockWidget->setWidget( new WatchdogControl(this) );
    
    pixhawk's avatar
    pixhawk committed
            watchdogControlDockWidget->setObjectName("WATCHDOG_CONTROL_DOCKWIDGET");
    
            addToToolsMenu (watchdogControlDockWidget, tr("Process Control"), SLOT(showToolWidget()), MENU_WATCHDOG, Qt::BottomDockWidgetArea);
        }
    
        if (!hsiDockWidget)
        {
            hsiDockWidget = new QDockWidget(tr("Horizontal Situation Indicator"), this);
            hsiDockWidget->setWidget( new HSIDisplay(this) );
    
            hsiDockWidget->setObjectName("HORIZONTAL_SITUATION_INDICATOR_DOCK_WIDGET");
    
            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) );
    
            headDown1DockWidget->setObjectName("HEAD_DOWN_DISPLAY_1_DOCK_WIDGET");
    
            addToToolsMenu (headDown1DockWidget, tr("Flight Display"), SLOT(showToolWidget()), MENU_HDD_1, Qt::RightDockWidgetArea);
        }
    
        if (!headDown2DockWidget)
        {
            headDown2DockWidget = new QDockWidget(tr("Payload Status"), this);
    
            headDown2DockWidget->setWidget( new HDDisplay(acceptList2, "Payload Status", this) );
    
            headDown2DockWidget->setObjectName("HEAD_DOWN_DISPLAY_2_DOCK_WIDGET");
    
            addToToolsMenu (headDown2DockWidget, tr("Payload Status"), SLOT(showToolWidget()), MENU_HDD_2, Qt::RightDockWidgetArea);
        }
    
        if (!rcViewDockWidget)
        {
            rcViewDockWidget = new QDockWidget(tr("Radio Control"), this);
            rcViewDockWidget->setWidget( new QGCRemoteControlView(this) );
    
            rcViewDockWidget->setObjectName("RADIO_CONTROL_CHANNELS_DOCK_WIDGET");
    
            addToToolsMenu (rcViewDockWidget, tr("Radio Control"), SLOT(showToolWidget()), MENU_RC_VIEW, Qt::BottomDockWidgetArea);
        }
    
        if (!headUpDockWidget)
        {
            headUpDockWidget = new QDockWidget(tr("HUD"), this);
            headUpDockWidget->setWidget( new HUD(320, 240, this));
    
            headUpDockWidget->setObjectName("HEAD_UP_DISPLAY_DOCK_WIDGET");
    
            addToToolsMenu (headUpDockWidget, tr("Control Indicator"), SLOT(showToolWidget()), MENU_HUD, Qt::LeftDockWidgetArea);
        }
    
    pixhawk's avatar
    pixhawk committed
        // Dialogue widgets
        //FIXME: free memory in destructor
    
        if (!joystick)
        {
            joystick    = new JoystickInput();
        }
    
        if (!linechartWidget)
        {
            // Center widgets
            linechartWidget   = new Linecharts(this);
        }
    
        if (!headUpDockWidget)
        {
            // Dock widgets
            headUpDockWidget = new QDockWidget(tr("Control Indicator"), this);
            headUpDockWidget->setWidget( new HUD(320, 240, this));
    
    pixhawk's avatar
    pixhawk committed
            headUpDockWidget->setObjectName("HEAD_UP_DISPLAY_DOCK_WIDGET");
    
            addToToolsMenu (headUpDockWidget, tr("HUD"), SLOT(showToolWidget()), MENU_HUD, Qt::LeftDockWidgetArea);
        }
    
        if (!rcViewDockWidget)
        {
            rcViewDockWidget = new QDockWidget(tr("Radio Control"), this);
            rcViewDockWidget->setWidget( new QGCRemoteControlView(this) );
    
    pixhawk's avatar
    pixhawk committed
            rcViewDockWidget->setObjectName("RADIO_CONTROL_CHANNELS_DOCK_WIDGET");
    
            addToToolsMenu (rcViewDockWidget, tr("Radio Control"), SLOT(showToolWidget()), MENU_RC_VIEW, Qt::BottomDockWidgetArea);
        }
    
        if (!slugsDataWidget)
        {
            // Dialog widgets
            slugsDataWidget = new QDockWidget(tr("Slugs Data"), this);
            slugsDataWidget->setWidget( new SlugsDataSensorView(this));
    
    pixhawk's avatar
    pixhawk committed
            slugsDataWidget->setObjectName("SLUGS_DATA_DOCK_WIDGET");
    
            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));
    
    pixhawk's avatar
    pixhawk committed
            slugsPIDControlWidget->setObjectName("SLUGS_PID_CONTROL_DOCK_WIDGET");
    
            addToToolsMenu (slugsPIDControlWidget, tr("PID Configuration"), SLOT(showToolWidget()), MENU_SLUGS_PID, Qt::LeftDockWidgetArea);
        }
    
        if (!slugsHilSimWidget)
        {
            slugsHilSimWidget = new QDockWidget(tr("Slugs Hil Sim"), this);
            slugsHilSimWidget->setWidget( new SlugsHilSim(this));
    
    pixhawk's avatar
    pixhawk committed
            slugsHilSimWidget->setObjectName("SLUGS_HIL_SIM_DOCK_WIDGET");
    
            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));
    
    pixhawk's avatar
    pixhawk committed
            slugsCamControlWidget->setObjectName("SLUGS_CAM_CONTROL_DOCK_WIDGET");
    
            addToToolsMenu (slugsCamControlWidget, tr("Camera Control"), SLOT(showToolWidget()), MENU_SLUGS_CAMERA, Qt::BottomDockWidgetArea);
        }
    
    
    
    void MainWindow::addToCentralWidgetsMenu ( QWidget* widget,
                                               const QString title,
                                               const char * slotName,
    
        QAction* tempAction;
    
        // Add the separator that will separate tools from central Widgets
    
        if (!toolsMenuActions[CENTRAL_SEPARATOR])
        {
    
            tempAction = ui.menuTools->addSeparator();
            toolsMenuActions[CENTRAL_SEPARATOR] = tempAction;
            tempAction->setData(CENTRAL_SEPARATOR);
        }
    
        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;
    
        // check the current action
    
        if (senderAction && dockWidgets[tool])
        {
    
            // uncheck all central widget actions
            QHashIterator<int, QAction*> i(toolsMenuActions);
    
                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);
    
            presentView();
        }
    
    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
    {
    
        QAction* tempAction;
        QString posKey, chKey;
    
        if (toolsMenuActions[CENTRAL_SEPARATOR])
        {
    
            tempAction = new QAction(title, this);
            ui.menuTools->insertAction(toolsMenuActions[CENTRAL_SEPARATOR],
                                       tempAction);
    
            tempAction = ui.menuTools->addAction(title);
        }
    
        tempAction->setCheckable(true);
        tempAction->setData(tool);
    
        // populate the Hashes
        toolsMenuActions[tool] = tempAction;
        dockWidgets[tool] = widget;
    
        posKey = buildMenuKey (SUB_SECTION_LOCATION,tool, currentView);
    
            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);
    
        }
        else
        {
            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();
            }
            else
            {
                removeDockWidget(qobject_cast<QDockWidget *>(dockWidgets[tool]));
            }
    
    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();
    
        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(getWindowGeometryKey(), saveGeometry());
    
        //settings.setValue("windowState", saveState());
        aboutToCloseFlag = true;
    
        // Save the last current view in any case
        settings.setValue("CURRENT_VIEW", currentView);
        // Save the current window state, but only if a system is connected (else no real number of widgets would be present)
        if (UASManager::instance()->getActiveUAS()) settings.setValue(getWindowStateKey(), saveState(QGC::applicationVersion()));
        // Save the current view only if a UAS is connected
        if (UASManager::instance()->getUASList().length() > 0) settings.setValue("CURRENT_VIEW_WITH_UAS_CONNECTED", currentView);
    
        settings.sync();
        QMainWindow::closeEvent(event);
    }
    
    void MainWindow::updateVisibilitySettings (bool vis)
    {
    
        if (!aboutToCloseFlag && !changingViewsFlag)
    
        {
            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);
    
                        toolsMenuActions[i.key()]->setChecked(vis);
                        break;
                    }
                }
            }
        }
    
    void MainWindow::updateLocationSettings (Qt::DockWidgetArea location)
    {
        QDockWidget* temp = qobject_cast<QDockWidget *>(sender());
    
        QHashIterator<int, QWidget*> i(dockWidgets);
        while (i.hasNext())
        {
            i.next();
            if ((static_cast <QDockWidget *>(dockWidgets[i.key()])) == temp)
            {
                QString posKey = buildMenuKey (SUB_SECTION_LOCATION,static_cast<TOOLS_WIDGET_NAMES>(i.key()), currentView);
                settings.setValue(posKey,location);
                break;
            }
        }
    
    /**
     * 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(clearWaypoints()));
    
    pixhawk's avatar
    pixhawk committed
            // 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)));
    
        //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*)));
    
            connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)),
                    slugsDataWidget->widget(), SLOT(setActiveUAS(UASInterface*)));
    
    void MainWindow::arrangeCommonCenterStack()
    
        centerStack->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    
    pixhawk's avatar
    pixhawk committed
        if (!centerStack) return;
    
        if (mapWidget && (centerStack->indexOf(mapWidget) == -1)) centerStack->addWidget(mapWidget);
    
    lm's avatar
    lm committed
        if (dataplotWidget && (centerStack->indexOf(dataplotWidget) == -1)) centerStack->addWidget(dataplotWidget);
    
        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);
    
        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
    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
    {
    
        QString fileName = QCoreApplication::applicationDirPath() + "/style-indoor.css";
    
        // Let user select style sheet
        fileName = QFileDialog::getOpenFileName(this, tr("Specify stylesheet"), fileName, tr("CSS Stylesheet (*.css);;"));
    
        if (!fileName.endsWith(".css"))
        {
            QMessageBox msgBox;
            msgBox.setIcon(QMessageBox::Information);
            msgBox.setText(tr("QGroundControl did lot load a new style"));
            msgBox.setInformativeText(tr("No suitable .css file selected. Please select a valid .css file."));
            msgBox.setStandardButtons(QMessageBox::Ok);
            msgBox.setDefaultButton(QMessageBox::Ok);
            msgBox.exec();
            return;
        }
    
    
    pixhawk's avatar
    pixhawk committed
        // Load style sheet
    
        QFile* styleSheet = new QFile(fileName);
    
        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);
    
            QMessageBox msgBox;
            msgBox.setIcon(QMessageBox::Information);
            msgBox.setText(tr("QGroundControl did lot load a new style"));
            msgBox.setInformativeText(tr("Stylesheet file %1 was not readable").arg(fileName));
            msgBox.setStandardButtons(QMessageBox::Ok);
            msgBox.setDefaultButton(QMessageBox::Ok);
            msgBox.exec();
    
    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