Skip to content
MainWindow.cc 50.8 KiB
Newer Older
Don Gagne's avatar
Don Gagne committed
                              errorMessage);
Don Gagne's avatar
Don Gagne committed
void MainWindow::showHelp()
{
    _openUrl("http://qgroundcontrol.org/users/start",
             tr("To get to the online help, please open http://qgroundcontrol.org/user_guide in a browser."));
}

void MainWindow::showCredits()
{
Don Gagne's avatar
Don Gagne committed
    _openUrl("http://qgroundcontrol.org/credits",
             tr("To get to the credits, please open http://qgroundcontrol.org/credits in a browser."));
Don Gagne's avatar
Don Gagne committed
    _openUrl("http://qgroundcontrol.org/dev/roadmap",
             tr("To get to the online help, please open http://qgroundcontrol.org/roadmap in a browser."));
Don Gagne's avatar
Don Gagne committed
    SettingsDialog settings(joystick, this);
    settings.exec();
// FIXME: Where is this called from
LinkInterface* MainWindow::addLink()
{
    SerialLink* link = new SerialLink();
    // TODO This should be only done in the dialog itself

    LinkManager::instance()->addLink(link);

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

    const int32_t& linkIndex(LinkManager::instance()->getLinks().indexOf(link));
    const int32_t& linkID(LinkManager::instance()->getLinks()[linkIndex]->getId());

    foreach (QAction* act, actions)
    {
        if (act->data().toInt() == linkID)

bool MainWindow::configLink(LinkInterface *link)
{
    // Go searching for this link's configuration window
    QList<QAction*> actions = ui.menuNetwork->actions();

    bool found(false);

    const int32_t& linkIndex(LinkManager::instance()->getLinks().indexOf(link));
    const int32_t& linkID(LinkManager::instance()->getLinks()[linkIndex]->getId());

    foreach (QAction* action, actions)
    {
        if (action->data().toInt() == linkID)
            found = true;
            action->trigger(); // Show the Link Config Dialog
        }
    }

    return found;
}

void MainWindow::_addLinkMenu(LinkInterface *link)
{
    // Go fishing for this link's configuration window
    QList<QAction*> actions = ui.menuNetwork->actions();

    bool alreadyAdded = false;
    const int32_t& linkIndex(LinkManager::instance()->getLinks().indexOf(link));
    const int32_t& linkID(LinkManager::instance()->getLinks()[linkIndex]->getId());
    foreach (QAction* act, actions) {
        if (act->data().toInt() == linkID) {
            alreadyAdded = true;
            break;
    if (!alreadyAdded) {
        CommConfigurationWindow* commWidget = new CommConfigurationWindow(link, this);
        commsWidgetList.append(commWidget);
        connect(commWidget,SIGNAL(destroyed(QObject*)),this,SLOT(commsWidgetDestroyed(QObject*)));
        QAction* action = commWidget->getAction();
        ui.menuNetwork->addAction(action);
    }
}
void MainWindow::simulateLink(bool simulate) {
Don Gagne's avatar
Don Gagne committed
    if (simulate) {
        if (!simulationLink) {
            simulationLink = new MAVLinkSimulationLink(":/demo-log.txt");
            Q_CHECK_PTR(simulationLink);
        }
        LinkManager::instance()->connectLink(simulationLink);
    } else {
        Q_ASSERT(simulationLink);
        LinkManager::instance()->disconnectLink(simulationLink);
    }
void MainWindow::commsWidgetDestroyed(QObject *obj)
{
    // Do not dynamic cast or de-reference QObject, since object is either in destructor or may have already
    // been destroyed.

    if (commsWidgetList.contains(obj))
    {
        commsWidgetList.removeOne(obj);
    }
}

void MainWindow::setActiveUAS(UASInterface* uas)
{
    Q_UNUSED(uas);
        restoreState(settings.value(getWindowStateKey()).toByteArray());
}

void MainWindow::UASSpecsChanged(int uas)
{
    Q_UNUSED(uas);
    // TODO: Update UAS properties if its specs change
}

void MainWindow::UASCreated(UASInterface* uas)
{
    // 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);

    QIcon icon;
    // Set matching icon
    switch (uas->getSystemType())
    {
    case MAV_TYPE_GENERIC:
        icon = QIcon(":files/images/mavs/generic.svg");
        break;
    case MAV_TYPE_FIXED_WING:
        icon = QIcon(":files/images/mavs/fixed-wing.svg");
        break;
    case MAV_TYPE_QUADROTOR:
        icon = QIcon(":files/images/mavs/quadrotor.svg");
        break;
    case MAV_TYPE_COAXIAL:
        icon = QIcon(":files/images/mavs/coaxial.svg");
        break;
    case MAV_TYPE_HELICOPTER:
        icon = QIcon(":files/images/mavs/helicopter.svg");
        break;
    case MAV_TYPE_ANTENNA_TRACKER:
        icon = QIcon(":files/images/mavs/antenna-tracker.svg");
        break;
    case MAV_TYPE_GCS:
        icon = QIcon(":files/images/mavs/groundstation.svg");
        break;
    case MAV_TYPE_AIRSHIP:
        icon = QIcon(":files/images/mavs/airship.svg");
        break;
    case MAV_TYPE_FREE_BALLOON:
        icon = QIcon(":files/images/mavs/free-balloon.svg");
        break;
    case MAV_TYPE_ROCKET:
        icon = QIcon(":files/images/mavs/rocket.svg");
        break;
    case MAV_TYPE_GROUND_ROVER:
        icon = QIcon(":files/images/mavs/ground-rover.svg");
        break;
    case MAV_TYPE_SURFACE_BOAT:
        icon = QIcon(":files/images/mavs/surface-boat.svg");
        break;
    case MAV_TYPE_SUBMARINE:
        icon = QIcon(":files/images/mavs/submarine.svg");
        break;
    case MAV_TYPE_HEXAROTOR:
        icon = QIcon(":files/images/mavs/hexarotor.svg");
        break;
    case MAV_TYPE_OCTOROTOR:
        icon = QIcon(":files/images/mavs/octorotor.svg");
        break;
    case MAV_TYPE_TRICOPTER:
        icon = QIcon(":files/images/mavs/tricopter.svg");
        break;
    case MAV_TYPE_FLAPPING_WING:
        icon = QIcon(":files/images/mavs/flapping-wing.svg");
        break;
    case MAV_TYPE_KITE:
        icon = QIcon(":files/images/mavs/kite.svg");
        break;
    default:
        icon = QIcon(":files/images/mavs/unknown.svg");
        break;
    }
    connect(uas, SIGNAL(systemSpecsChanged(int)), this, SLOT(UASSpecsChanged(int)));
John Tapsell's avatar
John Tapsell committed
    connect(uas, SIGNAL(valueChanged(int,QString,QString,QVariant,quint64)), this, SIGNAL(valueChanged(int,QString,QString,QVariant,quint64)));
    connect(uas, SIGNAL(misconfigurationDetected(UASInterface*)), this, SLOT(handleMisconfiguration(UASInterface*)));
    _showHILConfigurationWidgets();
    if (!linechartWidget)
    {
        linechartWidget = new Linecharts(this);
        linechartWidget->setVisible(false);
    linechartWidget->addSource(mavlinkDecoder);
    if (_engineeringView != linechartWidget)
        _engineeringView = linechartWidget;

    // Reload view state in case new widgets were added
    _loadCurrentViewState();
}

void MainWindow::UASDeleted(UASInterface* uas)
{
    Q_UNUSED(uas);
    // TODO: Update the UI when a UAS is deleted
/// Stores the state of the toolbar, status bar and widgets associated with the current view
void MainWindow::_storeCurrentViewState(void)
    // HIL dock widgets are dynamic and are not part of the saved state
    _hideAllHilDockWidgets();
    
    // Save list of visible widgets

    bool firstWidget = true;
    QString widgetNames = "";
    foreach(QDockWidget* dockWidget, _mapName2DockWidget) {
        if (dockWidget->isVisible()) {
            if (!firstWidget) {
                widgetNames += ",";
            }
            widgetNames += dockWidget->objectName();
            firstWidget = false;
        }
    
    settings.setValue(getWindowStateKey() + "WIDGETS", widgetNames);
    settings.setValue(getWindowStateKey(), saveState());
    settings.setValue(getWindowGeometryKey(), saveGeometry());
/// Restores the state of the toolbar, status bar and widgets associated with the current view
void MainWindow::_loadCurrentViewState(void)
Don Gagne's avatar
Don Gagne committed
    QWidget* centerView = NULL;
    QString defaultWidgets;
    
    switch (_currentView) {
            _buildSetupView();
            centerView = _setupView;
            _buildEngineeringView();
            centerView = _engineeringView;
            defaultWidgets = "MAVLINK_INSPECTOR_DOCKWIDGET,PARAMETER_INTERFACE_DOCKWIDGET,FILE_VIEW_DOCKWIDGET,HEAD_UP_DISPLAY_DOCKWIDGET";
            _buildPilotView();
            centerView = _pilotView;
            defaultWidgets = "COMMUNICATION_CONSOLE_DOCKWIDGET,UAS_INFO_INFOVIEW_DOCKWIDGET";
            _buildPlannerView();
            centerView = _plannerView;
            defaultWidgets = "UNMANNED_SYSTEM_LIST_DOCKWIDGET,WAYPOINT_LIST_DOCKWIDGET";
            _buildSimView();
            centerView = _simView;
            defaultWidgets = "UNMANNED_SYSTEM_CONTROL_DOCKWIDGET,WAYPOINT_LIST_DOCKWIDGET,PARAMETER_INTERFACE_DOCKWIDGET,PRIMARY_FLIGHT_DISPLAY_DOCKWIDGET";
        case VIEW_TERMINAL:
            _buildTerminalView();
            centerView = _terminalView;
            _buildGoogleEarthView();
            centerView = _googleEarthView;
            _buildLocal3DView();
            centerView = _local3DView;
    }
    
    // Remove old view
    if (_currentViewWidget) {
        _currentViewWidget->setVisible(false);
        Q_ASSERT(_centralLayout->count() == 1);
        QLayoutItem *child = _centralLayout->takeAt(0);
        Q_ASSERT(child);
        delete child;
    }
    
    // Add the new one
    Q_ASSERT(centerView);
    Q_ASSERT(_centralLayout->count() == 0);
    _currentViewWidget = centerView;
    _centralLayout->addWidget(_currentViewWidget);
    _currentViewWidget->setVisible(true);
    
    // Hide all widgets from previous view
    _hideAllDockWidgets();

    // Restore the widgets for the new view
    QString widgetNames = settings.value(getWindowStateKey() + "WIDGETS", defaultWidgets).toString();
    if (!widgetNames.isEmpty()) {
        QStringList split = widgetNames.split(",");
        foreach (QString widgetName, split) {
            Q_ASSERT(!widgetName.isEmpty());
            _showDockWidget(widgetName, true);
    if (settings.contains(getWindowStateKey())) {
        restoreState(settings.value(getWindowStateKey()).toByteArray());
    
    // HIL dock widget are dynamic and don't take part in the saved window state, so this
    // need to happen after we restore state
    _showHILConfigurationWidgets();
}

void MainWindow::_hideAllHilDockWidgets(void)
{
    foreach(QDockWidget* dockWidget, _mapUasId2HilDockWidget) {
        dockWidget->setVisible(false);
    }
}

void MainWindow::_hideAllDockWidgets(void)
{
    foreach(QDockWidget* dockWidget, _mapName2DockWidget) {
        dockWidget->setVisible(false);
    
    _hideAllHilDockWidgets();

void MainWindow::_showDockWidgetAction(bool show)
    QAction* action = dynamic_cast<QAction*>(QObject::sender());
    Q_ASSERT(action);
    
    _showDockWidget(action->data().toString(), show);
void MainWindow::handleMisconfiguration(UASInterface* uas)
{
    static QTime lastTime;
    
    // We have to debounce this signal
    if (!lastTime.isValid()) {
        lastTime.start();
    } else {
        if (lastTime.elapsed() < 10000) {
            lastTime.start();
            return;
        }
    }
    // Ask user if he wants to handle this now
Don Gagne's avatar
Don Gagne committed
    QMessageBox::StandardButton button = QGCMessageBox::question(tr("Missing or Invalid Onboard Configuration"),
                                                                    tr("The onboard system configuration is missing or incomplete. Do you want to resolve this now?"),
                                                                    QMessageBox::Ok | QMessageBox::Cancel,
                                                                    QMessageBox::Ok);
    if (button == QMessageBox::Ok) {
        // He wants to handle it, make sure this system is selected
        UASManager::instance()->setActiveUAS(uas);

        // Flick to config view
void MainWindow::loadEngineerView()
{
    if (_currentView != VIEW_ENGINEER)
        _storeCurrentViewState();
        _currentView = VIEW_ENGINEER;
        ui.actionEngineersView->setChecked(true);
        _loadCurrentViewState();
    if (_currentView != VIEW_MISSION)
        _storeCurrentViewState();
        _currentView = VIEW_MISSION;
        ui.actionMissionView->setChecked(true);
        _loadCurrentViewState();
void MainWindow::loadSetupView()
    if (_currentView != VIEW_SETUP)
        _storeCurrentViewState();
        _currentView = VIEW_SETUP;
        ui.actionSetup->setChecked(true);
        _loadCurrentViewState();
void MainWindow::loadTerminalView()
{
    if (_currentView != VIEW_TERMINAL)
        _storeCurrentViewState();
        _currentView = VIEW_TERMINAL;
        ui.actionTerminalView->setChecked(true);
        _loadCurrentViewState();
void MainWindow::loadGoogleEarthView()
{
    if (_currentView != VIEW_GOOGLEEARTH)
        _storeCurrentViewState();
        _currentView = VIEW_GOOGLEEARTH;
        ui.actionGoogleEarthView->setChecked(true);
        _loadCurrentViewState();
    if (_currentView != VIEW_LOCAL3D)
        _storeCurrentViewState();
        _currentView = VIEW_LOCAL3D;
        ui.actionLocal3DView->setChecked(true);
        _loadCurrentViewState();
void MainWindow::loadPilotView()
{
    if (_currentView != VIEW_FLIGHT)
        _storeCurrentViewState();
        _currentView = VIEW_FLIGHT;
        ui.actionFlightView->setChecked(true);
        _loadCurrentViewState();
void MainWindow::loadSimulationView()
{
    if (_currentView != VIEW_SIMULATION)
        _storeCurrentViewState();
        _currentView = VIEW_SIMULATION;
        ui.actionSimulationView->setChecked(true);
        _loadCurrentViewState();
QList<QAction*> MainWindow::listLinkMenuActions()
{
    return ui.menuNetwork->actions();
}
Don Gagne's avatar
Don Gagne committed
/// @brief Hides the spash screen if it is currently being shown
void MainWindow::hideSplashScreen(void)
Don Gagne's avatar
Don Gagne committed
{
    if (_splashScreen) {
        _splashScreen->hide();
        _splashScreen = NULL;
    }
}


#ifdef QGC_MOUSE_ENABLED_LINUX
bool MainWindow::x11Event(XEvent *event)
{
    emit x11EventOccured(event);
#endif // QGC_MOUSE_ENABLED_LINUX