MainWindow.cc 67.6 KB
Newer Older
1
/*===================================================================
pixhawk's avatar
pixhawk committed
2 3 4 5
======================================================================*/

/**
 * @file
6
 *   @brief Implementation of class MainWindow
7
 *   @author Lorenz Meier <mail@qgroundcontrol.org>
pixhawk's avatar
pixhawk committed
8 9 10 11 12 13 14 15 16 17 18
 */

#include <QSettings>
#include <QDockWidget>
#include <QNetworkInterface>
#include <QMessageBox>
#include <QDebug>
#include <QTimer>
#include <QHostInfo>

#include "MG.h"
19
#include "QGC.h"
pixhawk's avatar
pixhawk committed
20 21 22 23 24
#include "MAVLinkSimulationLink.h"
#include "SerialLink.h"
#include "UDPLink.h"
#include "MAVLinkProtocol.h"
#include "CommConfigurationWindow.h"
25
#include "QGCWaypointListMulti.h"
pixhawk's avatar
pixhawk committed
26 27
#include "MainWindow.h"
#include "JoystickWidget.h"
pixhawk's avatar
pixhawk committed
28
#include "GAudioOutput.h"
29
#include "QGCToolWidget.h"
30
#include "QGCMAVLinkLogPlayer.h"
31
#include "QGCSettingsWidget.h"
32

33
#ifdef QGC_OSG_ENABLED
34
#include "Q3DWidgetFactory.h"
35
#endif
pixhawk's avatar
pixhawk committed
36

lm's avatar
lm committed
37 38 39 40
// FIXME Move
#include "PxQuadMAV.h"
#include "SlugsMAV.h"

pixhawk's avatar
pixhawk committed
41

42
#include "LogCompressor.h"
pixhawk's avatar
pixhawk committed
43

44 45
MainWindow* MainWindow::instance()
{
46 47 48 49
    static MainWindow* _instance = 0;
    if(_instance == 0)
    {
        _instance = new MainWindow();
50

51
        /* Set the application as parent to ensure that this object
52
                 * will be destroyed when the main application exits */
53 54 55
        //_instance->setParent(qApp);
    }
    return _instance;
56 57
}

pixhawk's avatar
pixhawk committed
58 59 60 61 62 63 64
/**
* 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()
**/
65
MainWindow::MainWindow(QWidget *parent):
pixhawk's avatar
pixhawk committed
66
        QMainWindow(parent),
67
        toolsMenuActions(),
68
        currentView(VIEW_UNCONNECTED),
69
        aboutToCloseFlag(false),
70
        changingViewsFlag(false),
71 72 73
        styleFileName(QCoreApplication::applicationDirPath() + "/style-indoor.css"),
        autoReconnect(false),
        currentStyle(QGC_MAINWINDOW_STYLE_INDOOR)
pixhawk's avatar
pixhawk committed
74
{
75
    loadSettings();
76 77 78 79 80 81 82
    if (!settings.contains("CURRENT_VIEW"))
    {
        // Set this view as default view
        settings.setValue("CURRENT_VIEW", currentView);
    }
    else
    {
83 84 85 86 87
        // LOAD THE LAST VIEW
        VIEW_SECTIONS currentViewCandidate = (VIEW_SECTIONS) settings.value("CURRENT_VIEW", currentView).toInt();
        if (currentViewCandidate != VIEW_ENGINEER &&
            currentViewCandidate != VIEW_OPERATOR &&
            currentViewCandidate != VIEW_PILOT)
88
        {
89
            currentView = currentViewCandidate;
90
        }
91 92
    }

93
    setDefaultSettingsForAp();
94

95 96
    settings.sync();

pixhawk's avatar
pixhawk committed
97 98 99
    // Setup user interface
    ui.setupUi(this);

100 101
    setVisible(false);

102
    buildCommonWidgets();
103

104
    connectCommonWidgets();
105

106
    arrangeCommonCenterStack();
107 108

    configureWindowName();
pixhawk's avatar
pixhawk committed
109

110
    loadStyle(currentStyle);
111

112 113 114 115 116 117 118 119 120 121 122 123
//    // 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
//    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
124

125
    // Create actions
126
    connectCommonActions();
127

128 129 130
    // Set dock options
    setDockOptions(AnimatedDocks | AllowTabbedDocks | AllowNestedDocks);

131
    // Load mavlink view as default widget set
132
    //loadMAVLinkView();
133

lm's avatar
lm committed
134 135
    statusBar()->setSizeGripEnabled(true);

136 137
    // Restore the window position and size
    if (settings.contains(getWindowGeometryKey()))
138 139
    {
        // Restore the window geometry
140
        restoreGeometry(settings.value(getWindowGeometryKey()).toByteArray());
141 142 143 144 145 146
    }
    else
    {
        // Adjust the size
        adjustSize();
    }
pixhawk's avatar
pixhawk committed
147

148 149 150 151 152 153
    // Populate link menu
    QList<LinkInterface*> links = LinkManager::instance()->getLinks();
    foreach(LinkInterface* link, links)
    {
        this->addLink(link);
    }
154

155 156
    connect(LinkManager::instance(), SIGNAL(newLink(LinkInterface*)), this, SLOT(addLink(LinkInterface*)));

157 158 159 160 161 162
    // Connect user interface devices
    if (!joystick)
    {
        joystick = new JoystickInput();
    }

lm's avatar
lm committed
163 164
    // Enable and update view
    presentView();
165 166 167 168 169 170 171 172 173 174

    // Connect link
    if (autoReconnect)
    {
        SerialLink* link = new SerialLink();
        // Add to registry
        LinkManager::instance()->add(link);
        LinkManager::instance()->addProtocol(link, mavlink);
        link->connect();
    }
pixhawk's avatar
pixhawk committed
175 176
}

pixhawk's avatar
pixhawk committed
177
MainWindow::~MainWindow()
pixhawk's avatar
pixhawk committed
178
{
179 180 181
    // Store settings
    storeSettings();

182
    delete mavlink;
183
    delete joystick;
lm's avatar
lm committed
184

185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
    // Get and delete all dockwidgets and contained
    // widgets
    QObjectList childList( this->children() );

    QObjectList::iterator i;
    QDockWidget* dockWidget;
    for (i = childList.begin(); i != childList.end(); ++i)
    {
        dockWidget = dynamic_cast<QDockWidget*>(*i);
        if (dockWidget)
        {
            // Remove dock widget from main window
            removeDockWidget(dockWidget);
            delete dockWidget->widget();
            delete dockWidget;
        }
    }
pixhawk's avatar
pixhawk committed
202 203
}

204 205 206 207 208 209 210 211 212 213 214 215
/**
 * Set default settings for this AP type.
 */
void MainWindow::setDefaultSettingsForAp()
{
    // Check if the settings exist, instantiate defaults if necessary

    // UNCONNECTED VIEW DEFAULT
    QString centralKey = buildMenuKey(SUB_SECTION_CHECKED, CENTRAL_MAP, VIEW_UNCONNECTED);
    if (!settings.contains(centralKey))
    {
        settings.setValue(centralKey,true);
216 217 218 219 220

        // ENABLE UAS LIST
        settings.setValue(buildMenuKey(SUB_SECTION_CHECKED,MainWindow::MENU_UAS_LIST, VIEW_UNCONNECTED), true);
        // ENABLE COMMUNICATION CONSOLE
        settings.setValue(buildMenuKey(SUB_SECTION_CHECKED,MainWindow::MENU_DEBUG_CONSOLE, VIEW_UNCONNECTED), true);
221 222 223 224 225 226 227 228 229 230
    }

    // OPERATOR VIEW DEFAULT
    centralKey = buildMenuKey(SUB_SECTION_CHECKED, CENTRAL_MAP, VIEW_OPERATOR);
    if (!settings.contains(centralKey))
    {
        settings.setValue(centralKey,true);

        // ENABLE UAS LIST
        settings.setValue(buildMenuKey(SUB_SECTION_CHECKED,MainWindow::MENU_UAS_LIST,VIEW_OPERATOR), true);
231 232
        // ENABLE HUD TOOL WIDGET
        settings.setValue(buildMenuKey(SUB_SECTION_CHECKED,MainWindow::MENU_HUD,VIEW_OPERATOR), true);
233 234
        // ENABLE WAYPOINTS
        settings.setValue(buildMenuKey(SUB_SECTION_CHECKED,MainWindow::MENU_WAYPOINTS,VIEW_OPERATOR), true);
235 236 237 238 239 240 241
    }

    // ENGINEER VIEW DEFAULT
    centralKey = buildMenuKey(SUB_SECTION_CHECKED, CENTRAL_LINECHART, VIEW_ENGINEER);
    if (!settings.contains(centralKey))
    {
        settings.setValue(centralKey,true);
242 243
        // Enable Parameter widget
        settings.setValue(buildMenuKey(SUB_SECTION_CHECKED,MainWindow::MENU_PARAMETERS,VIEW_ENGINEER), true);
244 245 246 247 248 249 250 251 252 253 254 255 256 257
    }

    // 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);
258 259
        // Enable Flight display
        settings.setValue(buildMenuKey(SUB_SECTION_CHECKED,MainWindow::MENU_HDD_1,VIEW_PILOT), true);
260 261 262
    }
}

lm's avatar
lm committed
263 264 265 266 267 268 269 270 271 272 273 274 275
void MainWindow::resizeEvent(QResizeEvent * event)
{
    Q_UNUSED(event);
    if (height() < 800)
    {
        ui.statusBar->setVisible(false);
    }
    else
    {
        ui.statusBar->setVisible(true);
    }
}

276 277
QString MainWindow::getWindowStateKey()
{
278
    return QString::number(currentView)+"_windowstate";
279 280 281 282
}

QString MainWindow::getWindowGeometryKey()
{
283 284
    //return QString::number(currentView)+"_geometry";
    return "_geometry";
285 286
}

lm's avatar
lm committed
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322
void MainWindow::buildCustomWidget()
{
    // Show custom widgets only if UAS is connected
    if (UASManager::instance()->getActiveUAS() != NULL)
    {
        // Enable custom widgets
        ui.actionNewCustomWidget->setEnabled(true);

        // Create custom widgets
        QList<QGCToolWidget*> widgets = QGCToolWidget::createWidgetsFromSettings(this);

        if (widgets.size() > 0)
        {
            ui.menuTools->addSeparator();
        }

        for(int i = 0; i < widgets.size(); ++i)
        {
            // Check if this widget already has a parent, do not create it in this case
            QDockWidget* dock = dynamic_cast<QDockWidget*>(widgets.at(i)->parentWidget());
            if (!dock)
            {
                QDockWidget* dock = new QDockWidget(widgets.at(i)->windowTitle(), this);
                dock->setWidget(widgets.at(i));
                connect(widgets.at(i), SIGNAL(destroyed()), dock, SLOT(deleteLater()));
                QAction* showAction = new QAction(widgets.at(i)->windowTitle(), this);
                connect(showAction, SIGNAL(triggered(bool)), dock, SLOT(setVisible(bool)));
                connect(dock, SIGNAL(visibilityChanged(bool)), showAction, SLOT(setChecked(bool)));
                widgets.at(i)->setMainMenuAction(showAction);
                ui.menuTools->addAction(showAction);
                addDockWidget(Qt::BottomDockWidgetArea, dock);
            }
        }
    }
}

323 324 325 326
void MainWindow::buildCommonWidgets()
{
    //TODO:  move protocol outside UI
    mavlink     = new MAVLinkProtocol();
327
    connect(mavlink, SIGNAL(protocolStatusMessage(QString,QString)), this, SLOT(showCriticalMessage(QString,QString)), Qt::QueuedConnection);
328 329

    // Dock widgets
330 331 332
    if (!controlDockWidget)
    {
        controlDockWidget = new QDockWidget(tr("Control"), this);
333
        controlDockWidget->setObjectName("UNMANNED_SYSTEM_CONTROL_DOCKWIDGET");
334
        controlDockWidget->setWidget( new UASControlWidget(this) );
335
        addToToolsMenu (controlDockWidget, tr("Control"), SLOT(showToolWidget(bool)), MENU_UAS_CONTROL, Qt::LeftDockWidgetArea);
336
    }
337

338 339 340 341 342 343 344 345
    if (!controlParameterWidget)
    {
        controlParameterWidget = new QDockWidget(tr("Control Parameters"), this);
        controlParameterWidget->setObjectName("UNMANNED_SYSTEM_CONTROL_PARAMETERWIDGET");
        controlParameterWidget->setWidget( new UASControlParameters(this) );
        addToToolsMenu (controlParameterWidget, tr("Control Parameters"), SLOT(showToolWidget(bool)), MENU_UAS_CONTROL_PARAM, Qt::LeftDockWidgetArea);
    }

346 347 348 349
    if (!listDockWidget)
    {
        listDockWidget = new QDockWidget(tr("Unmanned Systems"), this);
        listDockWidget->setWidget( new UASListWidget(this) );
350
        listDockWidget->setObjectName("UNMANNED_SYSTEMS_LIST_DOCKWIDGET");
351
        addToToolsMenu (listDockWidget, tr("Unmanned Systems"), SLOT(showToolWidget(bool)), MENU_UAS_LIST, Qt::RightDockWidgetArea);
352
    }
353

354 355
    if (!waypointsDockWidget)
    {
356
        waypointsDockWidget = new QDockWidget(tr("Mission Plan"), this);
357
        waypointsDockWidget->setWidget( new QGCWaypointListMulti(this) );
358
        waypointsDockWidget->setObjectName("WAYPOINT_LIST_DOCKWIDGET");
359
        addToToolsMenu (waypointsDockWidget, tr("Mission Plan"), SLOT(showToolWidget(bool)), MENU_WAYPOINTS, Qt::BottomDockWidgetArea);
360
    }
361

362 363 364 365
    if (!infoDockWidget)
    {
        infoDockWidget = new QDockWidget(tr("Status Details"), this);
        infoDockWidget->setWidget( new UASInfoWidget(this) );
pixhawk's avatar
pixhawk committed
366
        infoDockWidget->setObjectName("UAS_STATUS_DETAILS_DOCKWIDGET");
367
        addToToolsMenu (infoDockWidget, tr("Status Details"), SLOT(showToolWidget(bool)), MENU_STATUS, Qt::RightDockWidgetArea);
368
    }
369

370 371 372 373
    if (!debugConsoleDockWidget)
    {
        debugConsoleDockWidget = new QDockWidget(tr("Communication Console"), this);
        debugConsoleDockWidget->setWidget( new DebugConsole(this) );
374
        debugConsoleDockWidget->setObjectName("COMMUNICATION_DEBUG_CONSOLE_DOCKWIDGET");
375
        addToToolsMenu (debugConsoleDockWidget, tr("Communication Console"), SLOT(showToolWidget(bool)), MENU_DEBUG_CONSOLE, Qt::BottomDockWidgetArea);
376
    }
377

378 379 380 381 382
    if (!logPlayerDockWidget)
    {
        logPlayerDockWidget = new QDockWidget(tr("MAVLink Log Player"), this);
        logPlayerDockWidget->setWidget( new QGCMAVLinkLogPlayer(mavlink, this) );
        logPlayerDockWidget->setObjectName("MAVLINK_LOG_PLAYER_DOCKWIDGET");
383
        addToToolsMenu(logPlayerDockWidget, tr("MAVLink Log Replay"), SLOT(showToolWidget(bool)), MENU_MAVLINK_LOG_PLAYER, Qt::RightDockWidgetArea);
384 385
    }

386
    // Center widgets
387 388
    if (!mapWidget)
    {
389
        mapWidget = new MapWidget(this);
390 391
        addToCentralWidgetsMenu (mapWidget, "Maps", SLOT(showCentralWidget()),CENTRAL_MAP);
    }
392

393 394 395 396 397
    if (!protocolWidget)
    {
        protocolWidget    = new XMLCommProtocolWidget(this);
        addToCentralWidgetsMenu (protocolWidget, "Mavlink Generator", SLOT(showCentralWidget()),CENTRAL_PROTOCOL);
    }
lm's avatar
lm committed
398 399 400 401

    if (!dataplotWidget)
    {
        dataplotWidget    = new QGCDataPlot2D(this);
402
        addToCentralWidgetsMenu (dataplotWidget, "Logfile Plot", SLOT(showCentralWidget()),CENTRAL_DATA_PLOT);
lm's avatar
lm committed
403
    }
404
}
405

406

407
void MainWindow::buildPxWidgets()
408
{
pixhawk's avatar
pixhawk committed
409 410
    //FIXME: memory of acceptList will never be freed again
    QStringList* acceptList = new QStringList();
pixhawk's avatar
pixhawk committed
411 412 413
    acceptList->append("-105,roll deg,deg,+105,s");
    acceptList->append("-105,pitch deg,deg,+105,s");
    acceptList->append("-105,heading deg,deg,+105,s");
414

pixhawk's avatar
pixhawk committed
415 416 417
    acceptList->append("-60,rollspeed d/s,deg/s,+60,s");
    acceptList->append("-60,pitchspeed d/s,deg/s,+60,s");
    acceptList->append("-60,yawspeed d/s,deg/s,+60,s");
418
    acceptList->append("0,airspeed,m/s,30");
419 420
    acceptList->append("0,groundspeed,m/s,30");
    acceptList->append("0,climbrate,m/s,30");
421
    acceptList->append("0,throttle,%,100");
422

pixhawk's avatar
pixhawk committed
423 424
    //FIXME: memory of acceptList2 will never be freed again
    QStringList* acceptList2 = new QStringList();
425 426 427 428 429 430 431 432
    acceptList2->append("900,servo #1,us,2100,s");
    acceptList2->append("900,servo #2,us,2100,s");
    acceptList2->append("900,servo #3,us,2100,s");
    acceptList2->append("900,servo #4,us,2100,s");
    acceptList2->append("900,servo #5,us,2100,s");
    acceptList2->append("900,servo #6,us,2100,s");
    acceptList2->append("900,servo #7,us,2100,s");
    acceptList2->append("900,servo #8,us,2100,s");
lm's avatar
lm committed
433
    acceptList2->append("0,abs pressure,hPa,65500");
434 435 436
    //acceptList2->append("-2048,accel. x,raw,2048,s");
    //acceptList2->append("-2048,accel. y,raw,2048,s");
    //acceptList2->append("-2048,accel. z,raw,2048,s");
437

438 439 440 441
    if (!linechartWidget)
    {
        // Center widgets
        linechartWidget   = new Linecharts(this);
442
        addToCentralWidgetsMenu(linechartWidget, tr("Realtime Plot"), SLOT(showCentralWidget()), CENTRAL_LINECHART);
443
    }
444 445


446 447 448
    if (!hudWidget)
    {
        hudWidget         = new HUD(320, 240, this);
449
        addToCentralWidgetsMenu(hudWidget, tr("Head Up Display"), SLOT(showCentralWidget()), CENTRAL_HUD);
450
    }
451

452 453 454
    if (!dataplotWidget)
    {
        dataplotWidget    = new QGCDataPlot2D(this);
455
        addToCentralWidgetsMenu(dataplotWidget, "Logfile Plot", SLOT(showCentralWidget()), CENTRAL_DATA_PLOT);
456
    }
457

458
#ifdef QGC_OSG_ENABLED
459 460
    if (!_3DWidget)
    {
461
        _3DWidget         = Q3DWidgetFactory::get("PIXHAWK");
462
        addToCentralWidgetsMenu(_3DWidget, tr("Local 3D"), SLOT(showCentralWidget()), CENTRAL_3D_LOCAL);
463
    }
464
#endif
465

466
#ifdef QGC_OSGEARTH_ENABLED
467 468 469
    if (!_3DMapWidget)
    {
        _3DMapWidget = Q3DWidgetFactory::get("MAP3D");
470
        addToCentralWidgetsMenu(_3DMapWidget, tr("OSG Earth 3D"), SLOT(showCentralWidget()), CENTRAL_OSGEARTH);
471
    }
472
#endif
lm's avatar
lm committed
473

474
#if (defined _MSC_VER) | (defined Q_OS_MAC)
475 476 477
    if (!gEarthWidget)
    {
        gEarthWidget = new QGCGoogleEarthView(this);
478
        addToCentralWidgetsMenu(gEarthWidget, tr("Google Earth"), SLOT(showCentralWidget()), CENTRAL_GOOGLE_EARTH);
479
    }
480

481
#endif
482

pixhawk's avatar
pixhawk committed
483
    // Dock widgets
484

485 486 487 488
    if (!detectionDockWidget)
    {
        detectionDockWidget = new QDockWidget(tr("Object Recognition"), this);
        detectionDockWidget->setWidget( new ObjectDetectionView("images/patterns", this) );
pixhawk's avatar
pixhawk committed
489
        detectionDockWidget->setObjectName("OBJECT_DETECTION_DOCK_WIDGET");
490
        addToToolsMenu (detectionDockWidget, tr("Object Recognition"), SLOT(showToolWidget(bool)), MENU_DETECTION, Qt::RightDockWidgetArea);
491
    }
492

493 494
    if (!parametersDockWidget)
    {
495
        parametersDockWidget = new QDockWidget(tr("Calibration and Onboard Parameters"), this);
496
        parametersDockWidget->setWidget( new ParameterInterface(this) );
pixhawk's avatar
pixhawk committed
497
        parametersDockWidget->setObjectName("PARAMETER_INTERFACE_DOCKWIDGET");
498
        addToToolsMenu (parametersDockWidget, tr("Calibration and Parameters"), SLOT(showToolWidget(bool)), MENU_PARAMETERS, Qt::RightDockWidgetArea);
499
    }
500

501 502 503 504
    if (!watchdogControlDockWidget)
    {
        watchdogControlDockWidget = new QDockWidget(tr("Process Control"), this);
        watchdogControlDockWidget->setWidget( new WatchdogControl(this) );
pixhawk's avatar
pixhawk committed
505
        watchdogControlDockWidget->setObjectName("WATCHDOG_CONTROL_DOCKWIDGET");
506
        addToToolsMenu (watchdogControlDockWidget, tr("Process Control"), SLOT(showToolWidget(bool)), MENU_WATCHDOG, Qt::BottomDockWidgetArea);
507
    }
508

509 510 511 512
    if (!hsiDockWidget)
    {
        hsiDockWidget = new QDockWidget(tr("Horizontal Situation Indicator"), this);
        hsiDockWidget->setWidget( new HSIDisplay(this) );
513
        hsiDockWidget->setObjectName("HORIZONTAL_SITUATION_INDICATOR_DOCK_WIDGET");
514
        addToToolsMenu (hsiDockWidget, tr("Horizontal Situation"), SLOT(showToolWidget(bool)), MENU_HSI, Qt::BottomDockWidgetArea);
515
    }
516

517 518
    if (!headDown1DockWidget)
    {
519 520
        headDown1DockWidget = new QDockWidget(tr("Flight Display"), this);
        headDown1DockWidget->setWidget( new HDDisplay(acceptList, "Flight Display", this) );
521
        headDown1DockWidget->setObjectName("HEAD_DOWN_DISPLAY_1_DOCK_WIDGET");
522
        addToToolsMenu (headDown1DockWidget, tr("Flight Display"), SLOT(showToolWidget(bool)), MENU_HDD_1, Qt::RightDockWidgetArea);
523
    }
524

525 526
    if (!headDown2DockWidget)
    {
527 528
        headDown2DockWidget = new QDockWidget(tr("Actuator Status"), this);
        headDown2DockWidget->setWidget( new HDDisplay(acceptList2, "Actuator Status", this) );
529
        headDown2DockWidget->setObjectName("HEAD_DOWN_DISPLAY_2_DOCK_WIDGET");
530
        addToToolsMenu (headDown2DockWidget, tr("Actuator Status"), SLOT(showToolWidget(bool)), MENU_HDD_2, Qt::RightDockWidgetArea);
531
    }
532

533 534 535 536
    if (!rcViewDockWidget)
    {
        rcViewDockWidget = new QDockWidget(tr("Radio Control"), this);
        rcViewDockWidget->setWidget( new QGCRemoteControlView(this) );
537
        rcViewDockWidget->setObjectName("RADIO_CONTROL_CHANNELS_DOCK_WIDGET");
538
        addToToolsMenu (rcViewDockWidget, tr("Radio Control"), SLOT(showToolWidget(bool)), MENU_RC_VIEW, Qt::BottomDockWidgetArea);
539
    }
540

541 542 543 544
    if (!headUpDockWidget)
    {
        headUpDockWidget = new QDockWidget(tr("HUD"), this);
        headUpDockWidget->setWidget( new HUD(320, 240, this));
545
        headUpDockWidget->setObjectName("HEAD_UP_DISPLAY_DOCK_WIDGET");
546
        addToToolsMenu (headUpDockWidget, tr("Head Up Display"), SLOT(showToolWidget(bool)), MENU_HUD, Qt::RightDockWidgetArea);
547
    }
548

pixhawk's avatar
pixhawk committed
549 550 551 552 553 554 555 556 557
    if (!video1DockWidget)
    {
        video1DockWidget = new QDockWidget(tr("Video Stream 1"), this);
        HUD* video1 =  new HUD(160, 120, this);
        video1->enableHUDInstruments(false);
        video1->enableVideo(true);
        // FIXME select video stream as well
        video1DockWidget->setWidget(video1);
        video1DockWidget->setObjectName("VIDEO_STREAM_1_DOCK_WIDGET");
558
        addToToolsMenu (video1DockWidget, tr("Video Stream 1"), SLOT(showToolWidget(bool)), MENU_VIDEO_STREAM_1, Qt::LeftDockWidgetArea);
pixhawk's avatar
pixhawk committed
559 560 561 562 563 564 565 566 567 568 569
    }

    if (!video2DockWidget)
    {
        video2DockWidget = new QDockWidget(tr("Video Stream 2"), this);
        HUD* video2 =  new HUD(160, 120, this);
        video2->enableHUDInstruments(false);
        video2->enableVideo(true);
        // FIXME select video stream as well
        video2DockWidget->setWidget(video2);
        video2DockWidget->setObjectName("VIDEO_STREAM_2_DOCK_WIDGET");
570
        addToToolsMenu (video2DockWidget, tr("Video Stream 2"), SLOT(showToolWidget(bool)), MENU_VIDEO_STREAM_2, Qt::LeftDockWidgetArea);
571
    }
572

pixhawk's avatar
pixhawk committed
573 574
    // Dialogue widgets
    //FIXME: free memory in destructor
575 576 577 578
}

void MainWindow::buildSlugsWidgets()
{
579 580 581 582
    if (!linechartWidget)
    {
        // Center widgets
        linechartWidget   = new Linecharts(this);
583
        addToCentralWidgetsMenu(linechartWidget, tr("Realtime Plot"), SLOT(showCentralWidget()), CENTRAL_LINECHART);
584
    }
585

586 587 588 589 590
    if (!headUpDockWidget)
    {
        // Dock widgets
        headUpDockWidget = new QDockWidget(tr("Control Indicator"), this);
        headUpDockWidget->setWidget( new HUD(320, 240, this));
pixhawk's avatar
pixhawk committed
591
        headUpDockWidget->setObjectName("HEAD_UP_DISPLAY_DOCK_WIDGET");
592
        addToToolsMenu (headUpDockWidget, tr("Head Up Display"), SLOT(showToolWidget(bool)), MENU_HUD, Qt::LeftDockWidgetArea);
593
    }
594

595 596 597 598
    if (!rcViewDockWidget)
    {
        rcViewDockWidget = new QDockWidget(tr("Radio Control"), this);
        rcViewDockWidget->setWidget( new QGCRemoteControlView(this) );
pixhawk's avatar
pixhawk committed
599
        rcViewDockWidget->setObjectName("RADIO_CONTROL_CHANNELS_DOCK_WIDGET");
600
        addToToolsMenu (rcViewDockWidget, tr("Radio Control"), SLOT(showToolWidget(bool)), MENU_RC_VIEW, Qt::BottomDockWidgetArea);
601
    }
602

603 604 605 606 607 608 609 610
    if (!slugsDataWidget)
    {
        // Dialog widgets
        slugsDataWidget = new QDockWidget(tr("Slugs Data"), this);
        slugsDataWidget->setWidget( new SlugsDataSensorView(this));
        slugsDataWidget->setObjectName("SLUGS_DATA_DOCK_WIDGET");
        addToToolsMenu (slugsDataWidget, tr("Telemetry Data"), SLOT(showToolWidget(bool)), MENU_SLUGS_DATA, Qt::RightDockWidgetArea);
    }
611

612 613 614 615 616 617 618
    if (!slugsPIDControlWidget)
    {
        slugsPIDControlWidget = new QDockWidget(tr("Slugs PID Control"), this);
        slugsPIDControlWidget->setWidget(new SlugsPIDControl(this));
        slugsPIDControlWidget->setObjectName("SLUGS_PID_CONTROL_DOCK_WIDGET");
        addToToolsMenu (slugsPIDControlWidget, tr("PID Configuration"), SLOT(showToolWidget(bool)), MENU_SLUGS_PID, Qt::LeftDockWidgetArea);
    }
619

620 621 622 623 624 625 626
    if (!slugsHilSimWidget)
    {
        slugsHilSimWidget = new QDockWidget(tr("Slugs Hil Sim"), this);
        slugsHilSimWidget->setWidget( new SlugsHilSim(this));
        slugsHilSimWidget->setObjectName("SLUGS_HIL_SIM_DOCK_WIDGET");
        addToToolsMenu (slugsHilSimWidget, tr("HIL Sim Configuration"), SLOT(showToolWidget(bool)), MENU_SLUGS_HIL, Qt::LeftDockWidgetArea);
    }
627

628

629 630 631 632 633 634 635
//    if (!slugsCamControlWidget)
//    {
//        slugsCamControlWidget = new QDockWidget(tr("Slugs Video Camera Control"), this);
//        slugsCamControlWidget->setWidget(new SlugsVideoCamControl(this));
//        slugsCamControlWidget->setObjectName("SLUGS_CAM_CONTROL_DOCK_WIDGET");
//        addToToolsMenu (slugsCamControlWidget, tr("Camera Control"), SLOT(showToolWidget()), MENU_SLUGS_CAMERA, Qt::BottomDockWidgetArea);
//    }
636
}
637 638 639 640 641


void MainWindow::addToCentralWidgetsMenu ( QWidget* widget,
                                           const QString title,
                                           const char * slotName,
642 643
                                           TOOLS_WIDGET_NAMES centralWidget)
{
644
    QAction* tempAction;
645

646

647
// Not needed any more - separate menu now available
648

649 650 651 652 653 654 655
//    // 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);
//    }
656

657
    tempAction = ui.menuMain->addAction(title);
658

659 660
    tempAction->setCheckable(true);
    tempAction->setData(centralWidget);
661

662 663 664
    // populate the Hashes
    toolsMenuActions[centralWidget] = tempAction;
    dockWidgets[centralWidget] = widget;
665

666
    QString chKey = buildMenuKey(SUB_SECTION_CHECKED, centralWidget, currentView);
667

668 669
    if (!settings.contains(chKey))
    {
670 671 672
        settings.setValue(chKey,false);
        tempAction->setChecked(false);
    }
673 674 675 676
    else
    {
        tempAction->setChecked(settings.value(chKey).toBool());
    }
677

678
    // connect the action
679
    connect(tempAction,SIGNAL(triggered(bool)),this, slotName);
680 681 682
}


lm's avatar
lm committed
683 684
void MainWindow::showCentralWidget()
{
685
    QAction* senderAction = qobject_cast<QAction *>(sender());
686 687 688 689

    // Block sender action while manipulating state
    senderAction->blockSignals(true);

690 691
    int tool = senderAction->data().toInt();
    QString chKey;
692

693
    // check the current action
694

695 696 697 698
    if (senderAction && dockWidgets[tool])
    {
        // uncheck all central widget actions
        QHashIterator<int, QAction*> i(toolsMenuActions);
699 700
        while (i.hasNext())
        {
701
            i.next();
702 703 704
            //qDebug() << "shCW" << i.key() << "read";
            if (i.value() && i.value()->data().toInt() > 255)
            {
705 706 707
                // Block signals and uncheck action
                // firing would be unneccesary
                i.value()->blockSignals(true);
708
                i.value()->setChecked(false);
709
                i.value()->blockSignals(false);
710 711 712 713 714 715

                // update the settings
                chKey = buildMenuKey (SUB_SECTION_CHECKED,static_cast<TOOLS_WIDGET_NAMES>(i.value()->data().toInt()), currentView);
                settings.setValue(chKey,false);
            }
        }
716

717
        // check the current action
718
        //qDebug() << senderAction->text();
719
        senderAction->setChecked(true);
720

721 722
        // update the central widget
        centerStack->setCurrentWidget(dockWidgets[tool]);
723

724 725 726
        // store the selected central widget
        chKey = buildMenuKey (SUB_SECTION_CHECKED,static_cast<TOOLS_WIDGET_NAMES>(tool), currentView);
        settings.setValue(chKey,true);
727

728 729 730
        // Unblock sender action
        senderAction->blockSignals(false);

731 732
        presentView();
    }
733
}
734

lm's avatar
lm committed
735 736 737 738
/**
 * Adds a widget to the tools menu and sets it visible if it was
 * enabled last time.
 */
739
void MainWindow::addToToolsMenu ( QWidget* widget,
740 741 742 743
                                  const QString title,
                                  const char * slotName,
                                  TOOLS_WIDGET_NAMES tool,
                                  Qt::DockWidgetArea location)
lm's avatar
lm committed
744
{
745 746
    QAction* tempAction;
    QString posKey, chKey;
747

748

749 750
    if (toolsMenuActions[CENTRAL_SEPARATOR])
    {
751 752 753
        tempAction = new QAction(title, this);
        ui.menuTools->insertAction(toolsMenuActions[CENTRAL_SEPARATOR],
                                   tempAction);
754 755 756
    }
    else
    {
757 758
        tempAction = ui.menuTools->addAction(title);
    }
759

760 761
    tempAction->setCheckable(true);
    tempAction->setData(tool);
762

763 764 765
    // populate the Hashes
    toolsMenuActions[tool] = tempAction;
    dockWidgets[tool] = widget;
766
    //qDebug() << widget;
767

768
    posKey = buildMenuKey (SUB_SECTION_LOCATION,tool, currentView);
769

770 771
    if (!settings.contains(posKey))
    {
772 773
        settings.setValue(posKey,location);
        dockWidgetLocations[tool] = location;
774 775 776 777
    }
    else
    {
        dockWidgetLocations[tool] = static_cast <Qt::DockWidgetArea> (settings.value(posKey, Qt::RightDockWidgetArea).toInt());
778
    }
779

780
    chKey = buildMenuKey(SUB_SECTION_CHECKED,tool, currentView);
781

782 783 784 785
    if (!settings.contains(chKey))
    {
        settings.setValue(chKey,false);
        tempAction->setChecked(false);
786
        widget->setVisible(false);
787 788 789
    }
    else
    {
790
        tempAction->setChecked(settings.value(chKey, false).toBool());
791
        widget->setVisible(settings.value(chKey, false).toBool());
792
    }
793

794
    // connect the action
795 796 797
    connect(tempAction,SIGNAL(toggled(bool)),this, slotName);

    connect(qobject_cast <QDockWidget *>(dockWidgets[tool]),
798
            SIGNAL(visibilityChanged(bool)), this, SLOT(showToolWidget(bool)));
799

800 801
    //  connect(qobject_cast <QDockWidget *>(dockWidgets[tool]),
    //          SIGNAL(visibilityChanged(bool)), this, SLOT(updateVisibilitySettings(bool)));
802

803 804
    connect(qobject_cast <QDockWidget *>(dockWidgets[tool]),
            SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), this, SLOT(updateLocationSettings(Qt::DockWidgetArea)));
805 806
}

807
void MainWindow::showToolWidget(bool visible)
808
{
809
    if (!aboutToCloseFlag && !changingViewsFlag)
810
    {
811 812
        QAction* action = qobject_cast<QAction *>(sender());

813 814
        // Prevent this to fire if undocked
        if (action)
815
        {
816
            int tool = action->data().toInt();
817

818
            QDockWidget* dockWidget = qobject_cast<QDockWidget *> (dockWidgets[tool]);
819

820 821 822 823 824 825 826 827 828 829
            if (dockWidget && dockWidget->isVisible() != visible)
            {
                if (visible)
                {
                    addDockWidget(dockWidgetLocations[tool], dockWidget);
                    dockWidget->show();
                }
                else
                {
                    removeDockWidget(dockWidget);
830
                }              
831 832 833 834 835 836 837 838 839

                QHashIterator<int, QWidget*> i(dockWidgets);
                while (i.hasNext())
                {
                    i.next();
                    if ((static_cast <QDockWidget *>(dockWidgets[i.key()])) == dockWidget)
                    {
                        QString chKey = buildMenuKey (SUB_SECTION_CHECKED,static_cast<TOOLS_WIDGET_NAMES>(i.key()), currentView);
                        settings.setValue(chKey,visible);
840
                        //qDebug() << "showToolWidget(): Set key" << chKey << "to" << visible;
841 842 843
                        break;
                    }
                }
844
            }
845
        }
846 847 848

        QDockWidget* dockWidget = qobject_cast<QDockWidget*>(QObject::sender());

849
        //qDebug() << "Trying to cast dockwidget" << dockWidget << "isvisible" << visible;
850 851

        if (dockWidget)
852
        {
853 854 855
            // Get action
            int tool = dockWidgets.key(dockWidget);

856
            //qDebug() << "Updating widget setting" << tool << "to" << visible;
857 858 859 860 861 862 863 864 865 866 867 868 869 870

            QAction* action = toolsMenuActions[tool];
            action->blockSignals(true);
            action->setChecked(visible);
            action->blockSignals(false);

            QHashIterator<int, QWidget*> i(dockWidgets);
            while (i.hasNext())
            {
                i.next();
                if ((static_cast <QDockWidget *>(dockWidgets[i.key()])) == dockWidget)
                {
                    QString chKey = buildMenuKey (SUB_SECTION_CHECKED,static_cast<TOOLS_WIDGET_NAMES>(i.key()), currentView);
                    settings.setValue(chKey,visible);
871
                   // qDebug() << "showToolWidget(): Set key" << chKey << "to" << visible;
872 873 874
                    break;
                }
            }
875
        }
876 877 878 879
    }
}


880 881 882 883 884
void MainWindow::showTheWidget (TOOLS_WIDGET_NAMES widget, VIEW_SECTIONS view)
{
    bool tempVisible;
    Qt::DockWidgetArea tempLocation;
    QDockWidget* tempWidget = static_cast <QDockWidget *>(dockWidgets[widget]);
885

886
    tempVisible =  settings.value(buildMenuKey(SUB_SECTION_CHECKED,widget,view), false).toBool();
887

888
     //qDebug() << "showTheWidget(): Set key" << buildMenuKey(SUB_SECTION_CHECKED,widget,view) << "to" << tempVisible;
889

890 891 892 893
    if (tempWidget)
    {
        toolsMenuActions[widget]->setChecked(tempVisible);
    }
894 895


896
    //qDebug() <<  buildMenuKey (SUB_SECTION_CHECKED,widget,view) << tempVisible;
897

898 899
    tempLocation = static_cast <Qt::DockWidgetArea>(settings.value(buildMenuKey (SUB_SECTION_LOCATION,widget, view), QVariant(Qt::RightDockWidgetArea)).toInt());

900
    if (tempWidget != NULL)
901
    {
902 903 904 905 906
        if (tempVisible)
        {
            addDockWidget(tempLocation, tempWidget);
            tempWidget->show();
        }
907 908
    }
}
909

910 911 912 913 914
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;

915 916 917 918 919
//    apType = (UASManager::instance() && UASManager::instance()->silentGetActiveUAS())?
//             UASManager::instance()->getActiveUAS()->getAutopilotType():
//             -1;

    apType = 1;
920

921 922 923 924 925
    return (QString::number(apType) + "_" +
            QString::number(SECTION_MENU) + "_" +
            QString::number(view) + "_" +
            QString::number(tool) + "_" +
            QString::number(section) + "_" );
926 927
}

928 929
void MainWindow::closeEvent(QCloseEvent *event)
{
930
    storeSettings();
931
    aboutToCloseFlag = true;
932
    mavlink->storeSettings();
933
    UASManager::instance()->storeSettings();
934 935
    QMainWindow::closeEvent(event);
}
936

937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959
void MainWindow::showDockWidget (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;
                }
            }
        }
    }
}
960

961 962
void MainWindow::updateVisibilitySettings (bool vis)
{
963
    if (!aboutToCloseFlag && !changingViewsFlag)
964 965 966 967 968 969
    {
        QDockWidget* temp = qobject_cast<QDockWidget *>(sender());

        if (temp)
        {
            QHashIterator<int, QWidget*> i(dockWidgets);
970 971
            while (i.hasNext())
            {
972
                i.next();
973 974
                if ((static_cast <QDockWidget *>(dockWidgets[i.key()])) == temp)
                {
975 976
                    QString chKey = buildMenuKey (SUB_SECTION_CHECKED,static_cast<TOOLS_WIDGET_NAMES>(i.key()), currentView);
                    settings.setValue(chKey,vis);
977 978 979 980 981 982
                    toolsMenuActions[i.key()]->setChecked(vis);
                    break;
                }
            }
        }
    }
983 984
}

985 986 987
void MainWindow::updateLocationSettings (Qt::DockWidgetArea location)
{
    QDockWidget* temp = qobject_cast<QDockWidget *>(sender());
988

989 990 991 992 993 994 995 996 997 998 999
    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;
        }
    }
1000 1001
}

1002

1003 1004 1005
/**
 * Connect the signals and slots of the common window widgets
 */
1006
void MainWindow::connectCommonWidgets()
1007
{
pixhawk's avatar
pixhawk committed
1008 1009 1010 1011 1012
    if (infoDockWidget && infoDockWidget->widget())
    {
        connect(mavlink, SIGNAL(receiveLossChanged(int, float)),
                infoDockWidget->widget(), SLOT(updateSendLoss(int, float)));
    }
1013

pixhawk's avatar
pixhawk committed
1014 1015
    if (mapWidget && waypointsDockWidget->widget())
    {
1016

1017 1018
        //
        connect(waypointsDockWidget->widget(), SIGNAL(changePointList()), mapWidget, SLOT(clearWaypoints()));
1019
    }
1020

Alejandro's avatar
Alejandro committed
1021 1022 1023 1024 1025
    //TODO temporaly debug
    if (slugsHilSimWidget && slugsHilSimWidget->widget()){
        connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)),
                slugsHilSimWidget->widget(), SLOT(activeUasSet(UASInterface*)));
    }
1026 1027 1028 1029 1030

    if (controlParameterWidget && controlParameterWidget->widget()){
        connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)),
                controlParameterWidget->widget(), SLOT(activeUasSet(UASInterface*)));
    }
1031 1032 1033 1034 1035

    if(controlDockWidget && controlParameterWidget)
    {
       connect(controlDockWidget->widget(), SIGNAL(changedMode(int)), controlParameterWidget->widget(), SLOT(changedMode(int)));
    }
1036
}
1037

1038 1039
void MainWindow::createCustomWidget()
{
lm's avatar
lm committed
1040 1041 1042 1043 1044 1045 1046 1047
    QGCToolWidget* tool = new QGCToolWidget("Unnamed Tool", this);

    if (QGCToolWidget::instances()->size() < 2)
    {
        // This is the first widget
        ui.menuTools->addSeparator();
    }

1048
    QDockWidget* dock = new QDockWidget("Unnamed Tool", this);
lm's avatar
lm committed
1049
    connect(tool, SIGNAL(destroyed()), dock, SLOT(deleteLater()));
1050
    dock->setWidget(tool);
1051

lm's avatar
lm committed
1052 1053 1054 1055 1056 1057
    QAction* showAction = new QAction("Show Unnamed Tool", this);
    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);
1058
    dock->setVisible(true);
1059 1060 1061 1062
}

void MainWindow::connectPxWidgets()
{
1063
    // No special connections necessary at this point
1064 1065 1066 1067
}

void MainWindow::connectSlugsWidgets()
{
1068
    if (slugsHilSimWidget && slugsHilSimWidget->widget()){
1069 1070
        connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)),
                slugsHilSimWidget->widget(), SLOT(activeUasSet(UASInterface*)));
1071 1072 1073
    }

    if (slugsDataWidget && slugsDataWidget->widget()){
1074 1075
        connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)),
                slugsDataWidget->widget(), SLOT(setActiveUAS(UASInterface*)));
1076 1077
    }

1078 1079 1080 1081
    if (slugsPIDControlWidget && slugsPIDControlWidget->widget()){
        connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)),
                slugsPIDControlWidget->widget(), SLOT(activeUasSet(UASInterface*)));
    }
1082 1083


1084 1085
}

1086
void MainWindow::arrangeCommonCenterStack()
1087
{
1088
    centerStack = new QStackedWidget(this);
1089
    centerStack->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
1090

pixhawk's avatar
pixhawk committed
1091
    if (!centerStack) return;
1092

1093
    if (mapWidget && (centerStack->indexOf(mapWidget) == -1)) centerStack->addWidget(mapWidget);
lm's avatar
lm committed
1094
    if (dataplotWidget && (centerStack->indexOf(dataplotWidget) == -1)) centerStack->addWidget(dataplotWidget);
1095
    if (protocolWidget && (centerStack->indexOf(protocolWidget) == -1)) centerStack->addWidget(protocolWidget);
1096 1097 1098 1099 1100 1101 1102

    setCentralWidget(centerStack);
}

void MainWindow::arrangePxCenterStack()
{

1103 1104 1105 1106
    if (!centerStack) {
        qDebug() << "Center Stack not Created!";
        return;
    }
1107

1108 1109

    if (linechartWidget && (centerStack->indexOf(linechartWidget) == -1)) centerStack->addWidget(linechartWidget);
1110

1111
#ifdef QGC_OSG_ENABLED
1112
    if (_3DWidget && (centerStack->indexOf(_3DWidget) == -1)) centerStack->addWidget(_3DWidget);
1113
#endif
1114
#ifdef QGC_OSGEARTH_ENABLED
1115
    if (_3DMapWidget && (centerStack->indexOf(_3DMapWidget) == -1)) centerStack->addWidget(_3DMapWidget);
1116
#endif
1117
#if (defined _MSC_VER) | (defined Q_OS_MAC)
1118
    if (gEarthWidget && (centerStack->indexOf(gEarthWidget) == -1)) centerStack->addWidget(gEarthWidget);
1119
#endif
1120 1121
    if (hudWidget && (centerStack->indexOf(hudWidget) == -1)) centerStack->addWidget(hudWidget);
    if (dataplotWidget && (centerStack->indexOf(dataplotWidget) == -1)) centerStack->addWidget(dataplotWidget);
1122 1123 1124 1125 1126
}

void MainWindow::arrangeSlugsCenterStack()
{

1127 1128 1129 1130
    if (!centerStack) {
        qDebug() << "Center Stack not Created!";
        return;
    }
1131

1132 1133
    if (linechartWidget && (centerStack->indexOf(linechartWidget) == -1)) centerStack->addWidget(linechartWidget);
    if (hudWidget && (centerStack->indexOf(hudWidget) == -1)) centerStack->addWidget(hudWidget);
1134

1135 1136
}

1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162
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();
    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);
    settings.sync();
}

1163 1164
void MainWindow::configureWindowName()
{
pixhawk's avatar
pixhawk committed
1165 1166 1167
    QList<QHostAddress> hostAddresses = QNetworkInterface::allAddresses();
    QString windowname = qApp->applicationName() + " " + qApp->applicationVersion();
    bool prevAddr = false;
1168

pixhawk's avatar
pixhawk committed
1169
    windowname.append(" (" + QHostInfo::localHostName() + ": ");
1170

pixhawk's avatar
pixhawk committed
1171 1172 1173 1174 1175 1176 1177 1178 1179 1180
    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;
        }
    }
1181

pixhawk's avatar
pixhawk committed
1182
    windowname.append(")");
1183

pixhawk's avatar
pixhawk committed
1184
    setWindowTitle(windowname);
1185 1186

#ifndef Q_WS_MAC
pixhawk's avatar
pixhawk committed
1187
    //qApp->setWindowIcon(QIcon(":/core/images/qtcreator_logo_128.png"));
1188 1189 1190
#endif
}

pixhawk's avatar
pixhawk committed
1191
void MainWindow::startVideoCapture()
pixhawk's avatar
pixhawk committed
1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202
{
    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);
1203 1204 1205
    //videoTimer->setInterval(40);
    //connect(videoTimer, SIGNAL(timeout()), this, SLOT(saveScreen()));
    //videoTimer->stop();
pixhawk's avatar
pixhawk committed
1206 1207
}

pixhawk's avatar
pixhawk committed
1208
void MainWindow::stopVideoCapture()
pixhawk's avatar
pixhawk committed
1209 1210 1211 1212 1213 1214
{
    videoTimer->stop();

    // TODO Convert raw images to PNG
}

pixhawk's avatar
pixhawk committed
1215
void MainWindow::saveScreen()
pixhawk's avatar
pixhawk committed
1216 1217 1218 1219 1220 1221 1222 1223 1224 1225
{
    QPixmap window = QPixmap::grabWindow(this->winId());
    QString format = "bmp";

    if (!screenFileName.isEmpty())
    {
        window.save(screenFileName, format.toAscii());
    }
}

1226
void MainWindow::enableAutoReconnect(bool enabled)
pixhawk's avatar
pixhawk committed
1227
{
1228 1229
    autoReconnect = enabled;
}
1230

1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276
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."));
            }
        }
        break;
    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;
}

1277
void MainWindow::selectStylesheet()
pixhawk's avatar
pixhawk committed
1278
{
1279
    // Let user select style sheet
1280
    styleFileName = QFileDialog::getOpenFileName(this, tr("Specify stylesheet"), styleFileName, tr("CSS Stylesheet (*.css);;"));
1281

1282
    if (!styleFileName.endsWith(".css"))
1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293
    {
        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
1294
    // Load style sheet
1295 1296 1297 1298 1299 1300 1301
    reloadStylesheet();
}

void MainWindow::reloadStylesheet()
{
    // Load style sheet
    QFile* styleSheet = new QFile(styleFileName);
1302 1303 1304 1305
    if (!styleSheet->exists())
    {
        styleSheet = new QFile(":/images/style-mission.css");
    }
1306 1307
    if (styleSheet->open(QIODevice::ReadOnly | QIODevice::Text))
    {
1308 1309
        QString style = QString(styleSheet->readAll());
        style.replace("ICONDIR", QCoreApplication::applicationDirPath()+ "/images/");
pixhawk's avatar
pixhawk committed
1310
        qApp->setStyleSheet(style);
1311 1312 1313
    }
    else
    {
1314 1315 1316
        QMessageBox msgBox;
        msgBox.setIcon(QMessageBox::Information);
        msgBox.setText(tr("QGroundControl did lot load a new style"));
1317
        msgBox.setInformativeText(tr("Stylesheet file %1 was not readable").arg(styleFileName));
1318 1319 1320
        msgBox.setStandardButtons(QMessageBox::Ok);
        msgBox.setDefaultButton(QMessageBox::Ok);
        msgBox.exec();
pixhawk's avatar
pixhawk committed
1321
    }
1322
    delete styleSheet;
pixhawk's avatar
pixhawk committed
1323 1324
}

1325 1326 1327 1328 1329 1330
/**
 * 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
1331
void MainWindow::showStatusMessage(const QString& status, int timeout)
pixhawk's avatar
pixhawk committed
1332
{
lm's avatar
lm committed
1333
    statusBar()->showMessage(status, timeout);
pixhawk's avatar
pixhawk committed
1334 1335
}

1336 1337 1338 1339 1340 1341
/**
 * 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
 */
1342
void MainWindow::showStatusMessage(const QString& status)
pixhawk's avatar
pixhawk committed
1343
{
lm's avatar
lm committed
1344
    statusBar()->showMessage(status, 20000);
1345 1346 1347 1348
}

void MainWindow::showCriticalMessage(const QString& title, const QString& message)
{
1349
    QMessageBox msgBox(this);
1350 1351 1352 1353 1354 1355
    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
1356 1357
}

lm's avatar
lm committed
1358 1359
void MainWindow::showInfoMessage(const QString& title, const QString& message)
{
1360
    QMessageBox msgBox(this);
lm's avatar
lm committed
1361 1362 1363 1364 1365 1366 1367 1368
    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
1369 1370 1371 1372
/**
* @brief Create all actions associated to the main window
*
**/
1373
void MainWindow::connectCommonActions()
pixhawk's avatar
pixhawk committed
1374
{
1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404
    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
1405 1406 1407 1408 1409
    // 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*)));
1410
    connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)), this, SLOT(setActiveUAS(UASInterface*)));
pixhawk's avatar
pixhawk committed
1411

1412
    // Unmanned System controls
pixhawk's avatar
pixhawk committed
1413 1414 1415 1416
    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()));
1417
    connect(ui.actionShutdownMAV, SIGNAL(triggered()), UASManager::instance(), SLOT(shutdownActiveUAS()));
pixhawk's avatar
pixhawk committed
1418 1419
    connect(ui.actionConfiguration, SIGNAL(triggered()), UASManager::instance(), SLOT(configureActiveUAS()));

1420
    // Views actions
1421
    connect(ui.actionPilotsView, SIGNAL(triggered()), this, SLOT(loadPilotView()));
1422
    connect(ui.actionEngineersView, SIGNAL(triggered()), this, SLOT(loadEngineerView()));
1423
    connect(ui.actionOperatorsView, SIGNAL(triggered()), this, SLOT(loadOperatorView()));
1424
    connect(ui.actionUnconnectedView, SIGNAL(triggered()), this, SLOT(loadUnconnectedView()));
1425

1426
    connect(ui.actionMavlinkView, SIGNAL(triggered()), this, SLOT(loadMAVLinkView()));
1427 1428
    connect(ui.actionReloadStylesheet, SIGNAL(triggered()), this, SLOT(reloadStylesheet()));
    connect(ui.actionSelectStylesheet, SIGNAL(triggered()), this, SLOT(selectStylesheet()));
1429

1430
    // Help Actions
1431
    connect(ui.actionOnline_Documentation, SIGNAL(triggered()), this, SLOT(showHelp()));
1432
    connect(ui.actionDeveloper_Credits, SIGNAL(triggered()), this, SLOT(showCredits()));
1433
    connect(ui.actionProject_Roadmap_2, SIGNAL(triggered()), this, SLOT(showRoadMap()));
1434 1435 1436

    // Custom widget actions
    connect(ui.actionNewCustomWidget, SIGNAL(triggered()), this, SLOT(createCustomWidget()));
1437 1438 1439

    // Audio output
    ui.actionMuteAudioOutput->setChecked(GAudioOutput::instance()->isMuted());
1440
    connect(GAudioOutput::instance(), SIGNAL(mutedChanged(bool)), ui.actionMuteAudioOutput, SLOT(setChecked(bool)));
1441
    connect(ui.actionMuteAudioOutput, SIGNAL(triggered(bool)), GAudioOutput::instance(), SLOT(mute(bool)));
1442 1443 1444 1445 1446 1447 1448

    // 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);
1449 1450 1451

    // Configuration
    // Joystick
1452
    connect(ui.actionJoystickSettings, SIGNAL(triggered()), this, SLOT(configure()));
1453 1454
    // Application Settings
    connect(ui.actionSettings, SIGNAL(triggered()), this, SLOT(showSettings()));
1455 1456 1457 1458 1459 1460 1461 1462 1463 1464
}

void MainWindow::connectPxActions()
{


}

void MainWindow::connectSlugsActions()
{
1465

pixhawk's avatar
pixhawk committed
1466 1467
}

1468 1469
void MainWindow::showHelp()
{
1470
    if(!QDesktopServices::openUrl(QUrl("http://qgroundcontrol.org/users/")))
1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483
    {
        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()
{
1484
    if(!QDesktopServices::openUrl(QUrl("http://qgroundcontrol.org/credits/")))
1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497
    {
        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()
{
1498
    if(!QDesktopServices::openUrl(QUrl("http://qgroundcontrol.org/roadmap/")))
1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509
    {
        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
1510
void MainWindow::configure()
pixhawk's avatar
pixhawk committed
1511
{
1512 1513 1514 1515 1516 1517 1518 1519 1520
    if (!joystickWidget)
    {
        if (!joystick->isRunning())
        {
            joystick->start();
        }
        joystickWidget = new JoystickWidget(joystick);
    }
    joystickWidget->show();
pixhawk's avatar
pixhawk committed
1521 1522
}

1523 1524 1525 1526 1527 1528
void MainWindow::showSettings()
{
    QGCSettingsWidget* settings = new QGCSettingsWidget(this);
    settings->show();
}

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

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

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

1540 1541 1542 1543 1544 1545 1546 1547
    foreach (QAction* act, actions)
    {
        if (act->data().toInt() == LinkManager::instance()->getLinks().indexOf(link))
        {
            act->trigger();
            break;
        }
    }
pixhawk's avatar
pixhawk committed
1548 1549
}

pixhawk's avatar
pixhawk committed
1550 1551
void MainWindow::addLink(LinkInterface *link)
{
1552 1553 1554 1555
    // 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)
1556
    LinkManager::instance()->add(link);
1557
    LinkManager::instance()->addProtocol(link, mavlink);
1558

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

1562
    bool found = false;
1563

1564
    foreach (QAction* act, actions)
pixhawk's avatar
pixhawk committed
1565
    {
1566 1567 1568 1569 1570 1571 1572
        if (act->data().toInt() == LinkManager::instance()->getLinks().indexOf(link))
        {
            found = true;
        }
    }

    UDPLink* udp = dynamic_cast<UDPLink*>(link);
1573

1574
    if (!found || udp)
pixhawk's avatar
pixhawk committed
1575
    {
1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588
        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);
        if (sim)
        {
            //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)));
        }
pixhawk's avatar
pixhawk committed
1589 1590 1591
    }
}

1592 1593 1594 1595 1596 1597 1598
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);
}

1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610
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
1611
void MainWindow::UASCreated(UASInterface* uas)
pixhawk's avatar
pixhawk committed
1612
{
1613

pixhawk's avatar
pixhawk committed
1614 1615
    // Connect the UAS to the full user interface

1616 1617
    if (uas != NULL)
    {
1618 1619 1620 1621
        // Set default settings
        setDefaultSettingsForAp();

        // The pilot, operator and engineer views were not available on startup, enable them now
1622
        ui.actionPilotsView->setEnabled(true);
1623 1624
        ui.actionOperatorsView->setEnabled(true);
        ui.actionEngineersView->setEnabled(true);
1625 1626 1627 1628 1629 1630
        // 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);
1631

1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658
        QIcon icon;
        // Set matching icon
        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;
        }

1659 1660 1661
        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()));
1662
        connect(uas, SIGNAL(systemSpecsChanged(int)), this, SLOT(UASSpecsChanged(int)));
1663 1664

        ui.menuConnected_Systems->addAction(uasAction);
1665 1666

        // FIXME Should be not inside the mainwindow
1667 1668
        if (debugConsoleDockWidget)
        {
pixhawk's avatar
pixhawk committed
1669 1670 1671 1672 1673 1674
            DebugConsole *debugConsole = dynamic_cast<DebugConsole*>(debugConsoleDockWidget->widget());
            if (debugConsole)
            {
                connect(uas, SIGNAL(textMessageReceived(int,int,int,QString)),
                        debugConsole, SLOT(receiveTextMessage(int,int,int,QString)));
            }
1675
        }
1676 1677

        // Health / System status indicator
1678 1679
        if (infoDockWidget)
        {
pixhawk's avatar
pixhawk committed
1680 1681 1682 1683 1684
            UASInfoWidget *infoWidget = dynamic_cast<UASInfoWidget*>(infoDockWidget->widget());
            if (infoWidget)
            {
                infoWidget->addUAS(uas);
            }
1685
        }
1686 1687

        // UAS List
1688 1689
        if (listDockWidget)
        {
pixhawk's avatar
pixhawk committed
1690 1691 1692 1693 1694
            UASListWidget *listWidget = dynamic_cast<UASListWidget*>(listDockWidget->widget());
            if (listWidget)
            {
                listWidget->addUAS(uas);
            }
1695
        }
1696

1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712
        switch (uas->getAutopilotType())
        {
        case (MAV_AUTOPILOT_SLUGS):
            {
                // Build Slugs Widgets
                buildSlugsWidgets();

                // Connect Slugs Widgets
                connectSlugsWidgets();

                // Arrange Slugs Centerstack
                arrangeSlugsCenterStack();

                // Connect Slugs Actions
                connectSlugsActions();

1713 1714 1715 1716 1717 1718 1719 1720 1721
//                if(slugsDataWidget)
//                {
//                    SlugsDataSensorView *mm = dynamic_cast<SlugsDataSensorView*>(slugsDataWidget->widget());
//                    if(mm)
//                    {
//                        mm->addUAS(uas);
//                    }
//                }

1722
                // FIXME: This type checking might be redundant
1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733
//                //            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();
//                //                }
//                //              }
//                //            }
1734

1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760
            }
            break;
        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
1761
        if (UASManager::instance()->getUASList().size() == 1)
1762 1763
        {
            // Load last view if setting is present
1764
            if (settings.contains("CURRENT_VIEW_WITH_UAS_CONNECTED"))
1765
            {
1766
                clearView();
1767
                int view = settings.value("CURRENT_VIEW_WITH_UAS_CONNECTED").toInt();
1768
                switch (view)
1769
                {
1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785
                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;
1786
                }
1787 1788 1789
            }
            else
            {
1790
                loadOperatorView();
1791
            }
1792
        }
1793

1794
    }
1795 1796

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

    // Custom widgets, added last to all menus and layouts
    buildCustomWidget();
pixhawk's avatar
pixhawk committed
1800 1801
}

1802 1803 1804
/**
 * Clears the current view completely
 */
pixhawk's avatar
pixhawk committed
1805
void MainWindow::clearView()
1806
{
1807
    // Save current state
1808
    if (UASManager::instance()->getUASList().count() > 0) settings.setValue(getWindowStateKey(), saveState(QGC::applicationVersion()));
1809
    settings.setValue(getWindowGeometryKey(), saveGeometry());
1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820

    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);

        if (temp)
        {
1821
            //qDebug() << "TOOL:" << chKey << "IS:" << temp->isChecked();
1822 1823 1824 1825
            settings.setValue(chKey,temp->isChecked());
        }
        else
        {
1826
            //qDebug() << "TOOL:" << chKey << "IS DEFAULT AND UNCHECKED";
1827 1828 1829 1830
            settings.setValue(chKey,false);
        }
    }

1831
    changingViewsFlag = true;
1832 1833
    // Remove all dock widgets from main window
    QObjectList childList( this->children() );
pixhawk's avatar
pixhawk committed
1834

1835 1836 1837
    QObjectList::iterator i;
    QDockWidget* dockWidget;
    for (i = childList.begin(); i != childList.end(); ++i)
pixhawk's avatar
pixhawk committed
1838
    {
1839 1840
        dockWidget = dynamic_cast<QDockWidget*>(*i);
        if (dockWidget)
pixhawk's avatar
pixhawk committed
1841
        {
1842
            // Remove dock widget from main window
1843
            removeDockWidget(dockWidget);
1844
            dockWidget->hide();
1845
            //dockWidget->setVisible(false);
pixhawk's avatar
pixhawk committed
1846 1847
        }
    }
1848
    changingViewsFlag = false;
pixhawk's avatar
pixhawk committed
1849 1850
}

1851
void MainWindow::loadEngineerView()
lm's avatar
lm committed
1852
{
1853 1854
    if (currentView != VIEW_ENGINEER)
    {
1855 1856 1857 1858
        clearView();
        currentView = VIEW_ENGINEER;
        ui.actionEngineersView->setChecked(true);
        presentView();
1859
    }
lm's avatar
lm committed
1860 1861
}

1862
void MainWindow::loadOperatorView()
lm's avatar
lm committed
1863
{
1864 1865
    if (currentView != VIEW_OPERATOR)
    {
1866 1867 1868 1869 1870 1871
        clearView();
        currentView = VIEW_OPERATOR;
        ui.actionOperatorsView->setChecked(true);
        presentView();
    }
}
lm's avatar
lm committed
1872

1873 1874 1875 1876 1877 1878 1879 1880
void MainWindow::loadUnconnectedView()
{
    if (currentView != VIEW_UNCONNECTED)
    {
        clearView();
        currentView = VIEW_UNCONNECTED;
        ui.actionUnconnectedView->setChecked(true);
        presentView();
1881
    }
lm's avatar
lm committed
1882 1883
}

1884
void MainWindow::loadPilotView()
1885
{
1886 1887
    if (currentView != VIEW_PILOT)
    {
1888 1889 1890 1891
        clearView();
        currentView = VIEW_PILOT;
        ui.actionPilotsView->setChecked(true);
        presentView();
1892
    }
1893 1894
}

1895
void MainWindow::loadMAVLinkView()
1896
{
1897 1898
    if (currentView != VIEW_MAVLINK)
    {
1899 1900 1901 1902
        clearView();
        currentView = VIEW_MAVLINK;
        ui.actionMavlinkView->setChecked(true);
        presentView();
1903
    }
1904 1905
}

lm's avatar
lm committed
1906 1907
void MainWindow::presentView()
{
1908
    // LINE CHART
1909
    showTheCentralWidget(CENTRAL_LINECHART, currentView);
1910

1911 1912
    // MAP
    showTheCentralWidget(CENTRAL_MAP, currentView);
pixhawk's avatar
pixhawk committed
1913

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

1917 1918
    // HEAD UP DISPLAY
    showTheCentralWidget(CENTRAL_HUD, currentView);
pixhawk's avatar
pixhawk committed
1919 1920 1921 1922 1923 1924 1925 1926 1927 1928

    // GOOGLE EARTH
    showTheCentralWidget(CENTRAL_GOOGLE_EARTH, currentView);

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

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

1929 1930 1931
    // DATA PLOT
    showTheCentralWidget(CENTRAL_DATA_PLOT, currentView);

pixhawk's avatar
pixhawk committed
1932

1933
    // Show docked widgets based on current view and autopilot type
1934

1935 1936
    // UAS CONTROL
    showTheWidget(MENU_UAS_CONTROL, currentView);
1937

1938 1939
    // UAS LIST
    showTheWidget(MENU_UAS_LIST, currentView);
1940

1941 1942
    // WAYPOINT LIST
    showTheWidget(MENU_WAYPOINTS, currentView);
pixhawk's avatar
pixhawk committed
1943

1944 1945
    // UAS STATUS
    showTheWidget(MENU_STATUS, currentView);
1946

1947 1948
    // DETECTION
    showTheWidget(MENU_DETECTION, currentView);
1949

1950 1951
    // DEBUG CONSOLE
    showTheWidget(MENU_DEBUG_CONSOLE, currentView);
1952

1953 1954
    // ONBOARD PARAMETERS
    showTheWidget(MENU_PARAMETERS, currentView);
1955

1956 1957
    // WATCHDOG
    showTheWidget(MENU_WATCHDOG, currentView);
1958

1959 1960 1961 1962 1963
    // HUD
    showTheWidget(MENU_HUD, currentView);
    if (headUpDockWidget)
    {
        HUD* tmpHud = dynamic_cast<HUD*>( headUpDockWidget->widget() );
1964 1965 1966 1967
        if (tmpHud)
        {
            if (settings.value(buildMenuKey (SUB_SECTION_CHECKED,MENU_HUD,currentView)).toBool())
            {
1968
                addDockWidget(static_cast <Qt::DockWidgetArea>(settings.value(buildMenuKey (SUB_SECTION_LOCATION,MENU_HUD, currentView)).toInt()),
1969
                        headUpDockWidget);
1970
                headUpDockWidget->show();
1971 1972 1973
            }
            else
            {
1974 1975
                headUpDockWidget->hide();
            }
1976
        }
1977
    }
1978

1979

1980 1981
    // RC View
    showTheWidget(MENU_RC_VIEW, currentView);
1982

1983 1984
    // SLUGS DATA
    showTheWidget(MENU_SLUGS_DATA, currentView);
1985

1986 1987
    // SLUGS PID
    showTheWidget(MENU_SLUGS_PID, currentView);
1988

1989 1990
    // SLUGS HIL
    showTheWidget(MENU_SLUGS_HIL, currentView);
1991

1992 1993
    // SLUGS CAMERA
    showTheWidget(MENU_SLUGS_CAMERA, currentView);
1994

1995 1996
    // HORIZONTAL SITUATION INDICATOR
    showTheWidget(MENU_HSI, currentView);
1997

1998 1999 2000 2001 2002
    // HEAD DOWN 1
    showTheWidget(MENU_HDD_1, currentView);

    // HEAD DOWN 2
    showTheWidget(MENU_HDD_2, currentView);
2003

2004 2005 2006
    // MAVLINK LOG PLAYER
    showTheWidget(MENU_MAVLINK_LOG_PLAYER, currentView);

2007 2008 2009 2010 2011 2012 2013
    // VIDEO 1
    showTheWidget(MENU_VIDEO_STREAM_1, currentView);

    // VIDEO 2
    showTheWidget(MENU_VIDEO_STREAM_2, currentView);

    // Restore window state
2014 2015 2016
    if (UASManager::instance()->getUASList().count() > 0)
    {
        // Restore the mainwindow size
2017 2018 2019 2020
        if (settings.contains(getWindowGeometryKey()))
        {
            restoreGeometry(settings.value(getWindowGeometryKey()).toByteArray());
        }
2021 2022 2023 2024 2025 2026 2027

        // Restore the widget positions and size
        if (settings.contains(getWindowStateKey()))
        {
            restoreState(settings.value(getWindowStateKey()).toByteArray(), QGC::applicationVersion());
        }
    }
lm's avatar
lm committed
2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039

    // ACTIVATE MAP WIDGET
    if (headUpDockWidget)
    {
        HUD* tmpHud = dynamic_cast<HUD*>( headUpDockWidget->widget() );
        if (tmpHud)
        {

        }
    }

    this->show();
2040
}
2041

2042 2043 2044 2045
void MainWindow::showTheCentralWidget (TOOLS_WIDGET_NAMES centralWidget, VIEW_SECTIONS view)
{
    bool tempVisible;
    QWidget* tempWidget = dockWidgets[centralWidget];
2046

2047
    tempVisible =  settings.value(buildMenuKey(SUB_SECTION_CHECKED,centralWidget,view), false).toBool();
2048
    //qDebug() << buildMenuKey (SUB_SECTION_CHECKED,centralWidget,view) << tempVisible;
2049
    if (toolsMenuActions[centralWidget])
2050
    {
2051
        //qDebug() << "SETTING TO:" << tempVisible;
2052
        toolsMenuActions[centralWidget]->setChecked(tempVisible);
2053
    }
2054

2055
    if (centerStack && tempWidget && tempVisible)
2056
    {
2057
        //qDebug() << "ACTIVATING MAIN WIDGET";
2058
        centerStack->setCurrentWidget(tempWidget);
2059
    }
2060 2061
}

2062 2063
void MainWindow::loadDataView(QString fileName)
{
2064
    clearView();
2065 2066 2067 2068 2069

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

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

2074
    presentView();
2075

2076 2077
    // Plot is now selected, now load data from file
    if (dataplotWidget)
2078
    {
2079
        dataplotWidget->loadFile(fileName);
2080
        }
2081 2082 2083 2084 2085 2086 2087
//        QStackedWidget *centerStack = dynamic_cast<QStackedWidget*>(centralWidget());
//        if (centerStack)
//        {
//            centerStack->setCurrentWidget(dataplotWidget);
//            dataplotWidget->loadFile(fileName);
//        }
//    }
2088 2089 2090
}