Skip to content
MainWindow.cc 69.7 KiB
Newer Older
LM's avatar
LM committed
        if (QGCToolWidget::instances()->size() < 2)
        {
            // This is the first widget
            ui.menuTools->addSeparator();
        }

        // Add widget to UI
        QDockWidget* dock = new QDockWidget(tool->getTitle(), this);
        connect(tool, SIGNAL(destroyed()), dock, SLOT(deleteLater()));
        dock->setWidget(tool);
        tool->setParent(dock);

        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);
    }
    // No special connections necessary at this point
    if (slugsHilSimWidget && slugsHilSimWidget->widget()) {
        connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)),
                slugsHilSimWidget->widget(), SLOT(activeUasSet(UASInterface*)));
    if (slugsDataWidget && slugsDataWidget->widget()) {
        connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)),
                slugsDataWidget->widget(), SLOT(setActiveUAS(UASInterface*)));
    if (controlParameterWidget && controlParameterWidget->widget()) {
        connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)),
                controlParameterWidget->widget(), SLOT(activeUasSet(UASInterface*)));
    }
    if(controlDockWidget && controlParameterWidget) {
        connect(controlDockWidget->widget(), SIGNAL(changedMode(int)), controlParameterWidget->widget(), SLOT(changedMode(int)));
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);
#if (defined _MSC_VER) | (defined Q_OS_MAC)
    if (gEarthWidget && (centerStack->indexOf(gEarthWidget) == -1)) centerStack->addWidget(gEarthWidget);
#endif

void MainWindow::loadSettings()
{
    QSettings settings;
    settings.beginGroup("QGC_MAINWINDOW");
    autoReconnect = settings.value("AUTO_RECONNECT", autoReconnect).toBool();
    currentStyle = (QGC_MAINWINDOW_STYLE)settings.value("CURRENT_STYLE", currentStyle).toInt();
    lowPowerMode = settings.value("LOW_POWER_MODE", lowPowerMode).toBool();
    settings.endGroup();
}

void MainWindow::storeSettings()
{
    QSettings settings;
    settings.beginGroup("QGC_MAINWINDOW");
    settings.setValue("AUTO_RECONNECT", autoReconnect);
    settings.setValue("CURRENT_STYLE", currentStyle);
    settings.endGroup();
    settings.setValue(getWindowGeometryKey(), saveGeometry());
    // 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()->getUASList().length() > 0) 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);
    // Save the current power mode
    settings.setValue("LOW_POWER_MODE", lowPowerMode);
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() + ": ");
    for (int i = 0; i < hostAddresses.size(); i++) {
pixhawk's avatar
pixhawk committed
        // Exclude loopback IPv4 and all IPv6 addresses
        if (hostAddresses.at(i) != QHostAddress("127.0.0.1") && !hostAddresses.at(i).toString().contains(":")) {
pixhawk's avatar
pixhawk committed
            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));
pixhawk's avatar
pixhawk committed
    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()) {
pixhawk's avatar
pixhawk committed
        window.save(screenFileName, format.toAscii());
    }
}

void MainWindow::enableAutoReconnect(bool enabled)
pixhawk's avatar
pixhawk committed
{
void MainWindow::loadNativeStyle()
{
    loadStyle(QGC_MAINWINDOW_STYLE_NATIVE);
}

void MainWindow::loadIndoorStyle()
{
    loadStyle(QGC_MAINWINDOW_STYLE_INDOOR);
}

void MainWindow::loadOutdoorStyle()
{
    loadStyle(QGC_MAINWINDOW_STYLE_OUTDOOR);
}

void MainWindow::loadStyle(QGC_MAINWINDOW_STYLE style)
{
    switch (style) {
    case QGC_MAINWINDOW_STYLE_NATIVE: {
        // Native mode means setting no style
        // so if we were already in native mode
        // take no action
        // Only if a style was set, remove it.
        if (style != currentStyle) {
            qApp->setStyleSheet("");
            showInfoMessage(tr("Please restart QGroundControl"), tr("Please restart QGroundControl to switch to fully native look and feel. Currently you have loaded Qt's plastique style."));
    case QGC_MAINWINDOW_STYLE_INDOOR:
        qApp->setStyle("plastique");
        styleFileName = ":/images/style-mission.css";
        reloadStylesheet();
        break;
    case QGC_MAINWINDOW_STYLE_OUTDOOR:
        qApp->setStyle("plastique");
        styleFileName = ":/images/style-outdoor.css";
        reloadStylesheet();
        break;
    }
    currentStyle = style;
}

void MainWindow::selectStylesheet()
pixhawk's avatar
pixhawk committed
{
    // Let user select style sheet
    styleFileName = QFileDialog::getOpenFileName(this, tr("Specify stylesheet"), styleFileName, tr("CSS Stylesheet (*.css);;"));
    if (!styleFileName.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
    reloadStylesheet();
}

void MainWindow::reloadStylesheet()
{
    // Load style sheet
    QFile* styleSheet = new QFile(styleFileName);
    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(styleFileName));
        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
 *
 * @param status message text
 * @param timeout how long the status should be displayed
 */
pixhawk's avatar
pixhawk committed
void MainWindow::showStatusMessage(const QString& status, int timeout)
pixhawk's avatar
pixhawk committed
{
lm's avatar
lm committed
    statusBar()->showMessage(status, timeout);
pixhawk's avatar
pixhawk committed
}

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

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

lm's avatar
lm committed
void MainWindow::showInfoMessage(const QString& title, const QString& message)
{
    QMessageBox msgBox(this);
lm's avatar
lm committed
    msgBox.setIcon(QMessageBox::Information);
    msgBox.setText(title);
    msgBox.setInformativeText(message);
    msgBox.setStandardButtons(QMessageBox::Ok);
    msgBox.setDefaultButton(QMessageBox::Ok);
    msgBox.exec();
}

pixhawk's avatar
pixhawk committed
/**
* @brief Create all actions associated to the main window
*
**/
pixhawk's avatar
pixhawk committed
{
    ui.actionNewCustomWidget->setEnabled(false);

    // 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->addAction(ui.actionUnconnectedView);
    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);
    if (currentView == VIEW_UNCONNECTED) ui.actionUnconnectedView->setChecked(true);

    // The pilot, engineer and operator view are not available on startup
    // since they only make sense with a system connected.
    ui.actionPilotsView->setEnabled(false);
    ui.actionOperatorsView->setEnabled(false);
    ui.actionEngineersView->setEnabled(false);
    // The UAS actions are not enabled without connection to system
    ui.actionLiftoff->setEnabled(false);
    ui.actionLand->setEnabled(false);
    ui.actionEmergency_Kill->setEnabled(false);
    ui.actionEmergency_Land->setEnabled(false);
    ui.actionShutdownMAV->setEnabled(false);

pixhawk's avatar
pixhawk committed
    // Connect actions from ui
    connect(ui.actionAdd_Link, SIGNAL(triggered()), this, SLOT(addLink()));

    // Connect internal actions
    connect(UASManager::instance(), SIGNAL(UASCreated(UASInterface*)), this, SLOT(UASCreated(UASInterface*)));
    connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)), this, SLOT(setActiveUAS(UASInterface*)));
pixhawk's avatar
pixhawk committed

pixhawk's avatar
pixhawk committed
    connect(ui.actionLiftoff, SIGNAL(triggered()), UASManager::instance(), SLOT(launchActiveUAS()));
    connect(ui.actionLand, SIGNAL(triggered()), UASManager::instance(), SLOT(returnActiveUAS()));
    connect(ui.actionEmergency_Land, SIGNAL(triggered()), UASManager::instance(), SLOT(stopActiveUAS()));
    connect(ui.actionEmergency_Kill, SIGNAL(triggered()), UASManager::instance(), SLOT(killActiveUAS()));
    connect(ui.actionShutdownMAV, SIGNAL(triggered()), UASManager::instance(), SLOT(shutdownActiveUAS()));
pixhawk's avatar
pixhawk committed
    connect(ui.actionConfiguration, SIGNAL(triggered()), UASManager::instance(), SLOT(configureActiveUAS()));

    connect(ui.actionPilotsView, SIGNAL(triggered()), this, SLOT(loadPilotView()));
    connect(ui.actionEngineersView, SIGNAL(triggered()), this, SLOT(loadEngineerView()));
    connect(ui.actionOperatorsView, SIGNAL(triggered()), this, SLOT(loadOperatorView()));
    connect(ui.actionUnconnectedView, SIGNAL(triggered()), this, SLOT(loadUnconnectedView()));
    connect(ui.actionMavlinkView, SIGNAL(triggered()), this, SLOT(loadMAVLinkView()));
    connect(ui.actionReloadStylesheet, SIGNAL(triggered()), this, SLOT(reloadStylesheet()));
    connect(ui.actionSelectStylesheet, SIGNAL(triggered()), this, SLOT(selectStylesheet()));
    connect(ui.actionOnline_Documentation, SIGNAL(triggered()), this, SLOT(showHelp()));
    connect(ui.actionDeveloper_Credits, SIGNAL(triggered()), this, SLOT(showCredits()));
    connect(ui.actionProject_Roadmap_2, SIGNAL(triggered()), this, SLOT(showRoadMap()));

    // Custom widget actions
    connect(ui.actionNewCustomWidget, SIGNAL(triggered()), this, SLOT(createCustomWidget()));
    connect(ui.actionLoadCustomWidgetFile, SIGNAL(triggered()), this, SLOT(loadCustomWidget()));

    // Audio output
    ui.actionMuteAudioOutput->setChecked(GAudioOutput::instance()->isMuted());
    connect(GAudioOutput::instance(), SIGNAL(mutedChanged(bool)), ui.actionMuteAudioOutput, SLOT(setChecked(bool)));
    connect(ui.actionMuteAudioOutput, SIGNAL(triggered(bool)), GAudioOutput::instance(), SLOT(mute(bool)));

    // User interaction
    // NOTE: Joystick thread is not started and
    // configuration widget is not instantiated
    // unless it is actually used
    // so no ressources spend on this.
    ui.actionJoystickSettings->setVisible(true);
    connect(ui.actionJoystickSettings, SIGNAL(triggered()), this, SLOT(configure()));
    // Application Settings
    connect(ui.actionSettings, SIGNAL(triggered()), this, SLOT(showSettings()));
pixhawk's avatar
pixhawk committed
}

void MainWindow::showHelp()
{
    if(!QDesktopServices::openUrl(QUrl("http://qgroundcontrol.org/users/"))) {
        QMessageBox msgBox;
        msgBox.setIcon(QMessageBox::Critical);
        msgBox.setText("Could not open help in browser");
        msgBox.setInformativeText("To get to the online help, please open http://qgroundcontrol.org/user_guide in a browser.");
        msgBox.setStandardButtons(QMessageBox::Ok);
        msgBox.setDefaultButton(QMessageBox::Ok);
        msgBox.exec();
    }
}

void MainWindow::showCredits()
{
    if(!QDesktopServices::openUrl(QUrl("http://qgroundcontrol.org/credits/"))) {
        QMessageBox msgBox;
        msgBox.setIcon(QMessageBox::Critical);
        msgBox.setText("Could not open credits in browser");
        msgBox.setInformativeText("To get to the online help, please open http://qgroundcontrol.org/credits in a browser.");
        msgBox.setStandardButtons(QMessageBox::Ok);
        msgBox.setDefaultButton(QMessageBox::Ok);
        msgBox.exec();
    }
}

void MainWindow::showRoadMap()
{
    if(!QDesktopServices::openUrl(QUrl("http://qgroundcontrol.org/roadmap/"))) {
        QMessageBox msgBox;
        msgBox.setIcon(QMessageBox::Critical);
        msgBox.setText("Could not open roadmap in browser");
        msgBox.setInformativeText("To get to the online help, please open http://qgroundcontrol.org/roadmap in a browser.");
        msgBox.setStandardButtons(QMessageBox::Ok);
        msgBox.setDefaultButton(QMessageBox::Ok);
        msgBox.exec();
    }
}

pixhawk's avatar
pixhawk committed
void MainWindow::configure()
pixhawk's avatar
pixhawk committed
{
    if (!joystickWidget) {
        if (!joystick->isRunning()) {
            joystick->start();
        }
        joystickWidget = new JoystickWidget(joystick);
    }
    joystickWidget->show();
pixhawk's avatar
pixhawk committed
}

void MainWindow::showSettings()
{
    QGCSettingsWidget* settings = new QGCSettingsWidget(this);
    settings->show();
}

pixhawk's avatar
pixhawk committed
void MainWindow::addLink()
pixhawk's avatar
pixhawk committed
{
    SerialLink* link = new SerialLink();
    // TODO This should be only done in the dialog itself

    LinkManager::instance()->add(link);
pixhawk's avatar
pixhawk committed
    LinkManager::instance()->addProtocol(link, mavlink);

    // Go fishing for this link's configuration window
    QList<QAction*> actions = ui.menuNetwork->actions();
pixhawk's avatar
pixhawk committed

    foreach (QAction* act, actions) {
        if (act->data().toInt() == LinkManager::instance()->getLinks().indexOf(link)) {
pixhawk's avatar
pixhawk committed
}

pixhawk's avatar
pixhawk committed
void MainWindow::addLink(LinkInterface *link)
{
    // IMPORTANT! KEEP THESE TWO LINES
    // THEY MAKE SURE THE LINK IS PROPERLY REGISTERED
    // BEFORE LINKING THE UI AGAINST IT
    // Register (does nothing if already registered)
    LinkManager::instance()->add(link);
    LinkManager::instance()->addProtocol(link, mavlink);
    // Go fishing for this link's configuration window
    QList<QAction*> actions = ui.menuNetwork->actions();
    foreach (QAction* act, actions) {
        if (act->data().toInt() == LinkManager::instance()->getLinks().indexOf(link)) {
            found = true;
        }
    }

    UDPLink* udp = dynamic_cast<UDPLink*>(link);
    if (!found || udp) {
        CommConfigurationWindow* commWidget = new CommConfigurationWindow(link, mavlink, this);
        QAction* action = commWidget->getAction();
        ui.menuNetwork->addAction(action);

        // Error handling
        connect(link, SIGNAL(communicationError(QString,QString)), this, SLOT(showCriticalMessage(QString,QString)), Qt::QueuedConnection);
        // Special case for simulationlink
        MAVLinkSimulationLink* sim = dynamic_cast<MAVLinkSimulationLink*>(link);
            //connect(sim, SIGNAL(valueChanged(int,QString,double,quint64)), linechart, SLOT(appendData(int,QString,double,quint64)));
            connect(ui.actionSimulate, SIGNAL(triggered(bool)), sim, SLOT(connectLink(bool)));
        }
void MainWindow::setActiveUAS(UASInterface* uas)
{
    // Enable and rename menu
    ui.menuUnmanned_System->setTitle(uas->getUASName());
    if (!ui.menuUnmanned_System->isEnabled()) ui.menuUnmanned_System->setEnabled(true);
}

void MainWindow::UASSpecsChanged(int uas)
{
    UASInterface* activeUAS = UASManager::instance()->getActiveUAS();
    if (activeUAS) {
        if (activeUAS->getUASID() == uas) {
            ui.menuUnmanned_System->setTitle(activeUAS->getUASName());
        }
    }
}

pixhawk's avatar
pixhawk committed
void MainWindow::UASCreated(UASInterface* uas)
pixhawk's avatar
pixhawk committed
{
pixhawk's avatar
pixhawk committed
    // Connect the UAS to the full user interface

    if (uas != NULL) {
        // Set default settings
        setDefaultSettingsForAp();

        // The pilot, operator and engineer views were not available on startup, enable them now
        ui.actionPilotsView->setEnabled(true);
        ui.actionOperatorsView->setEnabled(true);
        ui.actionEngineersView->setEnabled(true);
        // The UAS actions are not enabled without connection to system
        ui.actionLiftoff->setEnabled(true);
        ui.actionLand->setEnabled(true);
        ui.actionEmergency_Kill->setEnabled(true);
        ui.actionEmergency_Land->setEnabled(true);
        ui.actionShutdownMAV->setEnabled(true);
        switch (uas->getSystemType()) {
        case 0:
            icon = QIcon(":/images/mavs/generic.svg");
            break;
        case 1:
            icon = QIcon(":/images/mavs/fixed-wing.svg");
            break;
        case 2:
            icon = QIcon(":/images/mavs/quadrotor.svg");
            break;
        case 3:
            icon = QIcon(":/images/mavs/coaxial.svg");
            break;
        case 4:
            icon = QIcon(":/images/mavs/helicopter.svg");
            break;
        case 5:
            icon = QIcon(":/images/mavs/groundstation.svg");
            break;
        default:
            icon = QIcon(":/images/mavs/unknown.svg");
            break;
        }

        QAction* uasAction = new QAction(icon, tr("Select %1 for control").arg(uas->getUASName()), ui.menuConnected_Systems);
        connect(uas, SIGNAL(systemRemoved()), uasAction, SLOT(deleteLater()));
        connect(uasAction, SIGNAL(triggered()), uas, SLOT(setSelected()));
        connect(uas, SIGNAL(systemSpecsChanged(int)), this, SLOT(UASSpecsChanged(int)));

        ui.menuConnected_Systems->addAction(uasAction);

        // FIXME Should be not inside the mainwindow
        if (debugConsoleDockWidget) {
pixhawk's avatar
pixhawk committed
            DebugConsole *debugConsole = dynamic_cast<DebugConsole*>(debugConsoleDockWidget->widget());
            if (debugConsole) {
pixhawk's avatar
pixhawk committed
                connect(uas, SIGNAL(textMessageReceived(int,int,int,QString)),
                        debugConsole, SLOT(receiveTextMessage(int,int,int,QString)));
            }

        // Health / System status indicator
        if (infoDockWidget) {
pixhawk's avatar
pixhawk committed
            UASInfoWidget *infoWidget = dynamic_cast<UASInfoWidget*>(infoDockWidget->widget());
            if (infoWidget) {
pixhawk's avatar
pixhawk committed
                infoWidget->addUAS(uas);
            }
lm's avatar
lm committed
        if (listDockWidget)
        {
pixhawk's avatar
pixhawk committed
            UASListWidget *listWidget = dynamic_cast<UASListWidget*>(listDockWidget->widget());
lm's avatar
lm committed
            if (listWidget)
            {
pixhawk's avatar
pixhawk committed
                listWidget->addUAS(uas);
            }
lm's avatar
lm committed
        switch (uas->getAutopilotType())
        {
        case (MAV_AUTOPILOT_SLUGS): {
            // Build Slugs Widgets
            buildSlugsWidgets();
            // Connect Slugs Widgets
            connectSlugsWidgets();
            // Arrange Slugs Centerstack
            arrangeSlugsCenterStack();
            // Connect Slugs Actions
            connectSlugsActions();
//                if(slugsDataWidget)
//                {
//                    SlugsDataSensorView *mm = dynamic_cast<SlugsDataSensorView*>(slugsDataWidget->widget());
//                    if(mm)
//                    {
//                        mm->addUAS(uas);
//                    }
//                }

            // FIXME: This type checking might be redundant
//                //            if (slugsDataWidget) {
//                //              SlugsDataSensorView* dataWidget = dynamic_cast<SlugsDataSensorView*>(slugsDataWidget->widget());
//                //              if (dataWidget) {
//                //                SlugsMAV* mav2 = dynamic_cast<SlugsMAV*>(uas);
//                //                if (mav2) {
//                (dynamic_cast<SlugsDataSensorView*>(slugsDataWidget->widget()))->addUAS(uas);
//                //                  //loadSlugsView();
//                //                  loadGlobalOperatorView();
//                //                }
//                //              }
//                //            }
        default:
        case (MAV_AUTOPILOT_GENERIC):
        case (MAV_AUTOPILOT_ARDUPILOTMEGA):
        case (MAV_AUTOPILOT_PIXHAWK): {
            // Build Pixhawk Widgets
            buildPxWidgets();
            // Connect Pixhawk Widgets
            connectPxWidgets();
            // Arrange Pixhawk Centerstack
            arrangePxCenterStack();
            // Connect Pixhawk Actions
            connectPxActions();
        }
        break;
        }

        // Change the view only if this is the first UAS

        // If this is the first connected UAS, it is both created as well as
        // the currently active UAS
        if (UASManager::instance()->getUASList().size() == 1) {
            // Load last view if setting is present
            if (settings.contains("CURRENT_VIEW_WITH_UAS_CONNECTED")) {
                clearView();
                int view = settings.value("CURRENT_VIEW_WITH_UAS_CONNECTED").toInt();
                switch (view) {
                case VIEW_ENGINEER:
                    loadEngineerView();
                    break;
                case VIEW_MAVLINK:
                    loadMAVLinkView();
                    break;
                case VIEW_PILOT:
                    loadPilotView();
                    break;
                case VIEW_UNCONNECTED:
                    loadUnconnectedView();
                    break;
                case VIEW_OPERATOR:
                default:
                    loadOperatorView();
                    break;
                loadOperatorView();

    if (!ui.menuConnected_Systems->isEnabled()) ui.menuConnected_Systems->setEnabled(true);
lm's avatar
lm committed

    // Custom widgets, added last to all menus and layouts
    buildCustomWidget();
    if (settings.contains(getWindowGeometryKey())) {
        restoreGeometry(settings.value(getWindowGeometryKey()).toByteArray());
    }
pixhawk's avatar
pixhawk committed
}

/**
 * Clears the current view completely
 */
pixhawk's avatar
pixhawk committed
void MainWindow::clearView()
    // Save current state
    if (UASManager::instance()->getUASList().count() > 0) settings.setValue(getWindowStateKey(), saveState(QGC::applicationVersion()));
    // Although we want save the state of the window, we do not want to change the top-leve state (minimized, maximized, etc)
    // therefore this state is stored here and restored after applying the rest of the settings in the new
    // perspective.
    windowStateVal = this->windowState();
    settings.setValue(getWindowGeometryKey(), saveGeometry());

    QAction* temp;

    // Set tool widget visibility settings for this view
    foreach (int key, toolsMenuActions.keys()) {
        temp = toolsMenuActions[key];
        QString chKey = buildMenuKey (SUB_SECTION_CHECKED,static_cast<TOOLS_WIDGET_NAMES>(key), currentView);

            //qDebug() << "TOOL:" << chKey << "IS:" << temp->isChecked();
            settings.setValue(chKey,temp->isChecked());
            //qDebug() << "TOOL:" << chKey << "IS DEFAULT AND UNCHECKED";
    // Remove all dock widgets from main window
    QObjectList childList( this->children() );
pixhawk's avatar
pixhawk committed

    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);
            dockWidget->hide();
            //dockWidget->setVisible(false);
pixhawk's avatar
pixhawk committed
        }
    }
pixhawk's avatar
pixhawk committed
}

lm's avatar
lm committed
{
    if (currentView != VIEW_ENGINEER) {
        clearView();
        currentView = VIEW_ENGINEER;
        ui.actionEngineersView->setChecked(true);
        presentView();
lm's avatar
lm committed
}

lm's avatar
lm committed
{
    if (currentView != VIEW_OPERATOR) {
        clearView();
        currentView = VIEW_OPERATOR;
        ui.actionOperatorsView->setChecked(true);
        presentView();
    }
}
lm's avatar
lm committed

void MainWindow::loadUnconnectedView()
{
    if (currentView != VIEW_UNCONNECTED) {
        clearView();
        currentView = VIEW_UNCONNECTED;
        ui.actionUnconnectedView->setChecked(true);
        presentView();
lm's avatar
lm committed
}

    if (currentView != VIEW_PILOT) {
        clearView();
        currentView = VIEW_PILOT;
        ui.actionPilotsView->setChecked(true);
        presentView();
    if (currentView != VIEW_MAVLINK) {
        clearView();
        currentView = VIEW_MAVLINK;
        ui.actionMavlinkView->setChecked(true);
        presentView();
lm's avatar
lm committed
void MainWindow::presentView()
{
    // LINE CHART
    showTheCentralWidget(CENTRAL_LINECHART, currentView);
    // MAP
    showTheCentralWidget(CENTRAL_MAP, currentView);
pixhawk's avatar
pixhawk committed

    // PROTOCOL
    showTheCentralWidget(CENTRAL_PROTOCOL, currentView);
pixhawk's avatar
pixhawk committed

    // HEAD UP DISPLAY
    showTheCentralWidget(CENTRAL_HUD, currentView);
pixhawk's avatar
pixhawk committed

    // GOOGLE EARTH
    showTheCentralWidget(CENTRAL_GOOGLE_EARTH, currentView);

    // LOCAL 3D VIEW
    showTheCentralWidget(CENTRAL_3D_LOCAL, currentView);

    // GLOBAL 3D VIEW
    showTheCentralWidget(CENTRAL_3D_MAP, currentView);

    // DATA PLOT
    showTheCentralWidget(CENTRAL_DATA_PLOT, currentView);

    // Show docked widgets based on current view and autopilot type
    // UAS CONTROL
    showTheWidget(MENU_UAS_CONTROL, currentView);
    showTheWidget(MENU_UAS_CONTROL_PARAM, currentView);

    // UAS LIST
    showTheWidget(MENU_UAS_LIST, currentView);
    // WAYPOINT LIST
    showTheWidget(MENU_WAYPOINTS, currentView);
    // UAS STATUS
    showTheWidget(MENU_STATUS, currentView);
    // DETECTION
    showTheWidget(MENU_DETECTION, currentView);
    // DEBUG CONSOLE
    showTheWidget(MENU_DEBUG_CONSOLE, currentView);
    // ONBOARD PARAMETERS
    showTheWidget(MENU_PARAMETERS, currentView);
    // WATCHDOG
    showTheWidget(MENU_WATCHDOG, currentView);
    // HUD
    showTheWidget(MENU_HUD, currentView);
    if (headUpDockWidget) {
        HUD* tmpHud = dynamic_cast<HUD*>( headUpDockWidget->widget() );
        if (tmpHud) {
            if (settings.value(buildMenuKey (SUB_SECTION_CHECKED,MENU_HUD,currentView)).toBool()) {
                addDockWidget(static_cast <Qt::DockWidgetArea>(settings.value(buildMenuKey (SUB_SECTION_LOCATION,MENU_HUD, currentView)).toInt()),
                              headUpDockWidget);
                headUpDockWidget->show();
                headUpDockWidget->hide();
            }
    // RC View
    showTheWidget(MENU_RC_VIEW, currentView);
    // SLUGS DATA
    showTheWidget(MENU_SLUGS_DATA, currentView);
    // SLUGS PID
    showTheWidget(MENU_SLUGS_PID, currentView);
    // SLUGS HIL
    showTheWidget(MENU_SLUGS_HIL, currentView);
    // SLUGS CAMERA
    showTheWidget(MENU_SLUGS_CAMERA, currentView);
    // HORIZONTAL SITUATION INDICATOR
    showTheWidget(MENU_HSI, currentView);
    // HEAD DOWN 1
    showTheWidget(MENU_HDD_1, currentView);

    // HEAD DOWN 2
    showTheWidget(MENU_HDD_2, currentView);
    // MAVLINK LOG PLAYER
    showTheWidget(MENU_MAVLINK_LOG_PLAYER, currentView);

    // VIDEO 1
    showTheWidget(MENU_VIDEO_STREAM_1, currentView);

    // VIDEO 2
    showTheWidget(MENU_VIDEO_STREAM_2, currentView);

    // Restore window state
    if (UASManager::instance()->getUASList().count() > 0) {
//        // Restore the mainwindow size
//        if (settings.contains(getWindowGeometryKey()))
//        {
//            restoreGeometry(settings.value(getWindowGeometryKey()).toByteArray());
//        }

        // Restore the widget positions and size
        if (settings.contains(getWindowStateKey())) {
            restoreState(settings.value(getWindowStateKey()).toByteArray(), QGC::applicationVersion());
        }
    }
    // ACTIVATE HUD WIDGET
    if (headUpDockWidget) {
lm's avatar
lm committed
        HUD* tmpHud = dynamic_cast<HUD*>( headUpDockWidget->widget() );
        if (tmpHud) {
    this->setWindowState(windowStateVal);
lm's avatar
lm committed
    this->show();
void MainWindow::showTheCentralWidget (TOOLS_WIDGET_NAMES centralWidget, VIEW_SECTIONS view)
{
    bool tempVisible;
    QWidget* tempWidget = dockWidgets[centralWidget];
    tempVisible =  settings.value(buildMenuKey(SUB_SECTION_CHECKED,centralWidget,view), false).toBool();
    //qDebug() << buildMenuKey (SUB_SECTION_CHECKED,centralWidget,view) << tempVisible;
    if (toolsMenuActions[centralWidget]) {
        //qDebug() << "SETTING TO:" << tempVisible;
        toolsMenuActions[centralWidget]->setChecked(tempVisible);
    if (centerStack && tempWidget && tempVisible) {
        //qDebug() << "ACTIVATING MAIN WIDGET";
        centerStack->setCurrentWidget(tempWidget);
void MainWindow::loadDataView(QString fileName)
{
    clearView();

    // Unload line chart
    QString chKey = buildMenuKey (SUB_SECTION_CHECKED,static_cast<TOOLS_WIDGET_NAMES>(CENTRAL_LINECHART), currentView);
    settings.setValue(chKey,false);

    // Set data plot in settings as current widget and then run usual update procedure
    chKey = buildMenuKey (SUB_SECTION_CHECKED,static_cast<TOOLS_WIDGET_NAMES>(CENTRAL_DATA_PLOT), currentView);
    settings.setValue(chKey,true);
    presentView();