Skip to content
Snippets Groups Projects
MainWindow.cc 17.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • pixhawk's avatar
    pixhawk committed
    /*=====================================================================
    
    
    QGroundControl Open Source Ground Control Station
    
    pixhawk's avatar
    pixhawk committed
    
    
    (c) 2009, 2010 QGROUNDCONTROL/PIXHAWK PROJECT
    <http://www.qgroundcontrol.org>
    <http://pixhawk.ethz.ch>
    
    pixhawk's avatar
    pixhawk committed
    
    
    This file is part of the QGROUNDCONTROL project
    
    pixhawk's avatar
    pixhawk committed
    
    
        QGROUNDCONTROL is free software: you can redistribute it and/or modify
    
    pixhawk's avatar
    pixhawk committed
        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,
    
    pixhawk's avatar
    pixhawk committed
        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/>.
    
    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 "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"
    
    pixhawk's avatar
    pixhawk committed
    
    
    #include "LogCompressor.h"
    
    /**
    * 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),
    
    pixhawk's avatar
    pixhawk committed
    settings()
    
    pixhawk's avatar
    pixhawk committed
    {
    
        this->hide();
        this->setVisible(false);
    
    
    pixhawk's avatar
    pixhawk committed
        mavlink = new MAVLinkProtocol();
    
        // Setup user interface
        ui.setupUi(this);
    
        // Initialize views, NOT show them yet, only initialize model and controller
        centerStack = new QStackedWidget(this);
    
        linechart = new Linecharts(this);
    
        connect(UASManager::instance(), SIGNAL(UASCreated(UASInterface*)), linechart, SLOT(addSystem(UASInterface*)));
        connect(UASManager::instance(), SIGNAL(activeUASSet(int)), linechart, SLOT(selectSystem(int)));
    
    pixhawk's avatar
    pixhawk committed
        centerStack->addWidget(linechart);
        control = new UASControlWidget(this);
        //controlDock = new QDockWidget(this);
        //controlDock->setWidget(control);
        list = new UASListWidget(this);
        list->setVisible(false);
        waypoints = new WaypointList(this, NULL);
        waypoints->setVisible(false);
        info = new UASInfoWidget(this);
        info->setVisible(false);
        detection = new ObjectDetectionView("test", this);
        detection->setVisible(false);
        hud = new HUD(640, 480, this);
        hud->setVisible(false);
        debugConsole = new DebugConsole(this);
        debugConsole->setVisible(false);
        map = new MapWidget(this);
        map->setVisible(false);
        protocol = new XMLCommProtocolWidget(this);
        protocol->setVisible(false);
    
    pixhawk's avatar
    pixhawk committed
        parameters = new ParameterInterface(this);
        parameters->setVisible(false);
    
        watchdogControl = new WatchdogControl(this);
    
        watchdogControl->setVisible(false);
    
    pixhawk's avatar
    pixhawk committed
    
        QStringList* acceptList = new QStringList();
        acceptList->append("roll IMU");
        acceptList->append("pitch IMU");
        acceptList->append("yaw IMU");
    
        acceptList->append("vx");
        acceptList->append("vy");
        acceptList->append("vz");
    
    pixhawk's avatar
    pixhawk committed
        headDown1 = new HDDisplay(acceptList, this);
    
    pixhawk's avatar
    pixhawk committed
        headDown1->setVisible(false);
    
    pixhawk's avatar
    pixhawk committed
    
        QStringList* acceptList2 = new QStringList();
        acceptList2->append("Battery");
        acceptList2->append("Pressure");
        headDown2 = new HDDisplay(acceptList2, this);
        headDown2->setVisible(false);
    
    pixhawk's avatar
    pixhawk committed
        centerStack->addWidget(map);
        centerStack->addWidget(hud);
        setCentralWidget(centerStack);
    
        // Get IPs
        QList<QHostAddress> hostAddresses = QNetworkInterface::allAddresses();
    
    
    pixhawk's avatar
    pixhawk committed
        QString windowname = qApp->applicationName() + " " + qApp->applicationVersion();
    
    lm's avatar
    lm committed
    
    
    pixhawk's avatar
    pixhawk committed
        windowname.append(" (" + QHostInfo::localHostName() + ": ");
        bool prevAddr = false;
        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;
            }
        }
    
        windowname.append(")");
    
        setWindowTitle(windowname);
    #ifndef Q_WS_MAC
        //qApp->setWindowIcon(QIcon(":/core/images/qtcreator_logo_128.png"));
    #endif
    
        // Add status bar
        setStatusBar(createStatusBar());
    
        // Set the application style (not the same as a style sheet)
        // Set the style to Plastique
        qApp->setStyle("plastique");
        // Set style sheet as last step
        reloadStylesheet();
    
        joystick = new JoystickInput();
    
    
        // Create actions
        connectActions();
    
    
        // Load widgets and show application window
        loadWidgets();
    
        // Adjust the size
        adjustSize();
    
    lm's avatar
    lm committed
    
        //
    
        connect(mavlink, SIGNAL(receiveLossChanged(float)), info, SLOT(updateSendLoss(float)));
    
    pixhawk's avatar
    pixhawk committed
    }
    
    
    pixhawk's avatar
    pixhawk committed
    MainWindow::~MainWindow()
    
    pixhawk's avatar
    pixhawk committed
    {
        delete statusBar;
        statusBar = NULL;
    }
    
    
    pixhawk's avatar
    pixhawk committed
    QStatusBar* MainWindow::createStatusBar()
    
    pixhawk's avatar
    pixhawk committed
    {
        QStatusBar* bar = new QStatusBar();
        /* Add status fields and messages */
        /* Enable resize grip in the bottom right corner */
        bar->setSizeGripEnabled(true);
        return bar;
    }
    
    
    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
    {
        // Load style sheet
    
        QFile* styleSheet = new QFile(QCoreApplication::applicationDirPath() + "/qgroundcontrol.css");
        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);
        } else {
    
            qDebug() << "Style not set:" << styleSheet->fileName() << "opened: " << styleSheet->isOpen();
    
    pixhawk's avatar
    pixhawk committed
        }
    
    pixhawk's avatar
    pixhawk committed
    }
    
    
    pixhawk's avatar
    pixhawk committed
    void MainWindow::showStatusMessage(const QString& status, int timeout)
    
    pixhawk's avatar
    pixhawk committed
    {
        statusBar->showMessage(status, timeout);
    }
    
    
    void MainWindow::showStatusMessage(const QString& status)
    
    pixhawk's avatar
    pixhawk committed
    {
    
        statusBar->showMessage(status, 5);
    
    pixhawk's avatar
    pixhawk committed
    }
    
    /**
    * @brief Create all actions associated to the main window
    *
    **/
    
    pixhawk's avatar
    pixhawk committed
    void MainWindow::connectActions()
    
    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 user interface controls
        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.actionConfiguration, SIGNAL(triggered()), UASManager::instance(), SLOT(configureActiveUAS()));
    
        // User interface actions
        connect(ui.actionPilotView, SIGNAL(triggered()), this, SLOT(loadPilotView()));
        connect(ui.actionEngineerView, SIGNAL(triggered()), this, SLOT(loadEngineerView()));
        connect(ui.actionOperatorView, SIGNAL(triggered()), this, SLOT(loadOperatorView()));
        connect(ui.actionSettingsView, SIGNAL(triggered()), this, SLOT(loadSettingsView()));
    
        connect(ui.actionShow_full_view, SIGNAL(triggered()), this, SLOT(loadAllView()));
    
        connect(ui.actionShow_MAVLink_view, SIGNAL(triggered()), this, SLOT(loadMAVLinkView()));
    
    pixhawk's avatar
    pixhawk committed
        connect(ui.actionStyleConfig, SIGNAL(triggered()), this, SLOT(reloadStylesheet()));
    
        // Joystick configuration
        connect(ui.actionJoystickSettings, SIGNAL(triggered()), this, SLOT(configure()));
    }
    
    
    pixhawk's avatar
    pixhawk committed
    void MainWindow::configure()
    
    pixhawk's avatar
    pixhawk committed
    {
        joystickWidget = new JoystickWidget(joystick, this);
    }
    
    
    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()->addProtocol(link, mavlink);
    
        CommConfigurationWindow* commWidget = new CommConfigurationWindow(link, mavlink, this);
    
        ui.menuNetwork->addAction(commWidget->getAction());
    
        commWidget->show();
    
        // TODO Implement the link removal!
    }
    
    
    pixhawk's avatar
    pixhawk committed
    void MainWindow::addLink(LinkInterface *link)
    {
        CommConfigurationWindow* commWidget = new CommConfigurationWindow(link, mavlink, this);
        ui.menuNetwork->addAction(commWidget->getAction());
        LinkManager::instance()->addProtocol(link, mavlink);
    
        // Special case for simulationlink
        MAVLinkSimulationLink* sim = dynamic_cast<MAVLinkSimulationLink*>(link);
        if (sim)
        {
    
            //connect(sim, SIGNAL(valueChanged(int,QString,double,quint64)), linechart, SLOT(appendData(int,QString,double,quint64)));
    
    pixhawk's avatar
    pixhawk committed
            connect(ui.actionSimulate, SIGNAL(triggered(bool)), sim, SLOT(connectLink(bool)));
        }
    }
    
    
    pixhawk's avatar
    pixhawk committed
    void MainWindow::UASCreated(UASInterface* uas)
    
    pixhawk's avatar
    pixhawk committed
    {
        // Connect the UAS to the full user interface
    
    lm's avatar
    lm committed
        //ui.menuConnected_Systems->addAction(QIcon(":/images/mavs/generic.svg"), tr("View ") + uas->getUASName(), uas, SLOT(setSelected()));
    
    pixhawk's avatar
    pixhawk committed
    
    
        // FIXME Should be not inside the mainwindow
        connect(uas, SIGNAL(textMessageReceived(int,int,QString)), debugConsole, SLOT(receiveTextMessage(int,int,QString)));
    
    
    pixhawk's avatar
    pixhawk committed
        // Health / System status indicator
        info->addUAS(uas);
    
        // UAS List
        list->addUAS(uas);
    
        // Camera view
        //camera->addUAS(uas);
    
        // Revalidate UI
        // TODO Stylesheet reloading should in theory not be necessary
        reloadStylesheet();
    }
    
    
    /**
     * Clears the current view completely
     */
    
    pixhawk's avatar
    pixhawk committed
    void MainWindow::clearView()
    
    pixhawk's avatar
    pixhawk committed
    { 
        // Halt HUD
        hud->stop();
    
    pixhawk's avatar
    pixhawk committed
        headDown1->stop();
        headDown2->stop();
    
    pixhawk's avatar
    pixhawk committed
    
        // Remove all dock widgets
        QList<QObject*> list = this->children();
    
        QList<QObject*>::iterator i;
        for (i = list.begin(); i != list.end(); ++i)
        {
            QDockWidget* widget = dynamic_cast<QDockWidget*>(*i);
            if (widget)
            {
                // Hide widgets
                QWidget* childWidget = dynamic_cast<QWidget*>(widget->widget());
                if (childWidget) childWidget->setVisible(false);
                // Remove dock widget
                this->removeDockWidget(widget);
                //delete widget;
            }
        }
    }
    
    
    pixhawk's avatar
    pixhawk committed
    void MainWindow::loadPilotView()
    
    pixhawk's avatar
    pixhawk committed
    {
        clearView();
    
        // HEAD UP DISPLAY
        centerStack->setCurrentWidget(hud);
        hud->start();
    
        //connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)), pfd, SLOT(setActiveUAS(UASInterface*)));
    
    pixhawk's avatar
    pixhawk committed
        QDockWidget* container1 = new QDockWidget(tr("Primary Flight Display"), this);
    
    pixhawk's avatar
    pixhawk committed
        container1->setWidget(headDown1);
        addDockWidget(Qt::RightDockWidgetArea, container1);
    
    
    pixhawk's avatar
    pixhawk committed
        QDockWidget* container2 = new QDockWidget(tr("Payload Status"), this);
    
    pixhawk's avatar
    pixhawk committed
        container2->setWidget(headDown2);
        addDockWidget(Qt::RightDockWidgetArea, container2);
    
    pixhawk's avatar
    pixhawk committed
    
        headDown1->start();
        headDown2->start();
    
    
    pixhawk's avatar
    pixhawk committed
        this->show();
    }
    
    
    pixhawk's avatar
    pixhawk committed
    void MainWindow::loadOperatorView()
    
    pixhawk's avatar
    pixhawk committed
    {
        clearView();
    
    
    pixhawk's avatar
    pixhawk committed
        centerStack->setCurrentWidget(map);
    
        // UAS CONTROL
        QDockWidget* container1 = new QDockWidget(tr("Control"), this);
        container1->setWidget(control);
        addDockWidget(Qt::LeftDockWidgetArea, container1);
    
        // UAS LIST
        QDockWidget* container4 = new QDockWidget(tr("Unmanned Systems"), this);
        container4->setWidget(list);
        addDockWidget(Qt::BottomDockWidgetArea, container4);
    
        // UAS STATUS
        QDockWidget* container3 = new QDockWidget(tr("Status Details"), this);
        container3->setWidget(info);
        addDockWidget(Qt::LeftDockWidgetArea, container3);
    
        // WAYPOINT LIST
        QDockWidget* container5 = new QDockWidget(tr("Waypoint List"), this);
        container5->setWidget(waypoints);
        addDockWidget(Qt::BottomDockWidgetArea, container5);
    
        // DEBUG CONSOLE
        QDockWidget* container7 = new QDockWidget(tr("Communication Console"), this);
        container7->setWidget(debugConsole);
        addDockWidget(Qt::BottomDockWidgetArea, container7);
    
        // OBJECT DETECTION
        QDockWidget* container6 = new QDockWidget(tr("Object Recognition"), this);
        container6->setWidget(detection);
        addDockWidget(Qt::RightDockWidgetArea, container6);
    
    
    pixhawk's avatar
    pixhawk committed
        // PROCESS CONTROL
        QDockWidget* pControl = new QDockWidget(tr("Process Control"), this);
        pControl->setWidget(watchdogControl);
        addDockWidget(Qt::RightDockWidgetArea, pControl);
    
    pixhawk's avatar
    pixhawk committed
        this->show();
    }
    
    
    pixhawk's avatar
    pixhawk committed
    void MainWindow::loadSettingsView()
    
    pixhawk's avatar
    pixhawk committed
    {
        clearView();
    
        // LINE CHART
    
    pixhawk's avatar
    pixhawk committed
        centerStack->setCurrentWidget(linechart);
    
    
    pixhawk's avatar
    pixhawk committed
        // COMM XML
        QDockWidget* container1 = new QDockWidget(tr("MAVLink XML to C Code Generator"), this);
        container1->setWidget(protocol);
    
        addDockWidget(Qt::LeftDockWidgetArea, container1);*/
    
    pixhawk's avatar
    pixhawk committed
    
        // ONBOARD PARAMETERS
        QDockWidget* container6 = new QDockWidget(tr("Onboard Parameters"), this);
        container6->setWidget(parameters);
        addDockWidget(Qt::RightDockWidgetArea, container6);
    
    pixhawk's avatar
    pixhawk committed
    }
    
    
    pixhawk's avatar
    pixhawk committed
    void MainWindow::loadEngineerView()
    
    pixhawk's avatar
    pixhawk committed
    {
        clearView();
        // Engineer view, used in EMAV2009
    
        // LINE CHART
    
    pixhawk's avatar
    pixhawk committed
        centerStack->setCurrentWidget(linechart);
    
        // UAS CONTROL
        QDockWidget* container1 = new QDockWidget(tr("Control"), this);
        container1->setWidget(control);
        addDockWidget(Qt::LeftDockWidgetArea, container1);
    
        // UAS LIST
        QDockWidget* container4 = new QDockWidget(tr("Unmanned Systems"), this);
        container4->setWidget(list);
        addDockWidget(Qt::BottomDockWidgetArea, container4);
    
        // UAS STATUS
        QDockWidget* container3 = new QDockWidget(tr("Status Details"), this);
        container3->setWidget(info);
        addDockWidget(Qt::LeftDockWidgetArea, container3);
    
        // WAYPOINT LIST
        QDockWidget* container5 = new QDockWidget(tr("Waypoint List"), this);
        container5->setWidget(waypoints);
        addDockWidget(Qt::BottomDockWidgetArea, container5);
    
        // DEBUG CONSOLE
        QDockWidget* container7 = new QDockWidget(tr("Communication Console"), this);
        container7->setWidget(debugConsole);
        addDockWidget(Qt::BottomDockWidgetArea, container7);
    
        this->show();
    }
    
    
    void MainWindow::loadMAVLinkView()
    {
        clearView();
        centerStack->setCurrentWidget(protocol);
    
        clearView();
    
        QDockWidget* containerPFD = new QDockWidget(tr("Primary Flight Display"), this);
        containerPFD->setWidget(headDown1);
        addDockWidget(Qt::RightDockWidgetArea, containerPFD);
    
        QDockWidget* containerPayload = new QDockWidget(tr("Payload Status"), this);
        containerPayload->setWidget(headDown2);
        addDockWidget(Qt::RightDockWidgetArea, containerPayload);
    
        headDown1->start();
        headDown2->start();
    
        // UAS CONTROL
        QDockWidget* containerControl = new QDockWidget(tr("Control"), this);
        containerControl->setWidget(control);
        addDockWidget(Qt::LeftDockWidgetArea, containerControl);
    
        // UAS LIST
        QDockWidget* containerUASList = new QDockWidget(tr("Unmanned Systems"), this);
        containerUASList->setWidget(list);
        addDockWidget(Qt::BottomDockWidgetArea, containerUASList);
    
        // UAS STATUS
        QDockWidget* containerStatus = new QDockWidget(tr("Status Details"), this);
        containerStatus->setWidget(info);
        addDockWidget(Qt::LeftDockWidgetArea, containerStatus);
    
        // WAYPOINT LIST
        QDockWidget* containerWaypoints = new QDockWidget(tr("Waypoint List"), this);
        containerWaypoints->setWidget(waypoints);
        addDockWidget(Qt::BottomDockWidgetArea, containerWaypoints);
    
        // DEBUG CONSOLE
        QDockWidget* containerComm = new QDockWidget(tr("Communication Console"), this);
        containerComm->setWidget(debugConsole);
        addDockWidget(Qt::BottomDockWidgetArea, containerComm);
    
        // OBJECT DETECTION
        QDockWidget* containerObjRec = new QDockWidget(tr("Object Recognition"), this);
        containerObjRec->setWidget(detection);
        addDockWidget(Qt::RightDockWidgetArea, containerObjRec);
    
        // LINE CHART
        linechart->setActive(true);
        centerStack->setCurrentWidget(linechart);
    
        // ONBOARD PARAMETERS
        QDockWidget* containerParams = new QDockWidget(tr("Onboard Parameters"), this);
        containerParams->setWidget(parameters);
        addDockWidget(Qt::RightDockWidgetArea, containerParams);
    
        this->show();
    
    pixhawk's avatar
    pixhawk committed
    void MainWindow::loadWidgets()
    
    pixhawk's avatar
    pixhawk committed
    {
    
        //loadOperatorView();
        loadEngineerView();
    
    pixhawk's avatar
    pixhawk committed
        //loadPilotView();
    }