MainWindow.cc 62.7 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

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

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

pixhawk's avatar
pixhawk committed
40

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

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

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

pixhawk's avatar
pixhawk committed
57 58 59 60 61 62 63
/**
* 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()
**/
64
MainWindow::MainWindow(QWidget *parent):
pixhawk's avatar
pixhawk committed
65
        QMainWindow(parent),
66
        toolsMenuActions(),
67
        currentView(VIEW_UNCONNECTED),
68
        aboutToCloseFlag(false),
69
        changingViewsFlag(false)
pixhawk's avatar
pixhawk committed
70
{
71 72 73 74 75 76 77
    if (!settings.contains("CURRENT_VIEW"))
    {
        // Set this view as default view
        settings.setValue("CURRENT_VIEW", currentView);
    }
    else
    {
78 79 80 81 82
        // 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)
83
        {
84
            currentView = currentViewCandidate;
85
        }
86 87
    }

88
    setDefaultSettingsForAp();
89

90 91
    settings.sync();

pixhawk's avatar
pixhawk committed
92 93 94
    // Setup user interface
    ui.setupUi(this);

95 96
    setVisible(false);

97
    buildCommonWidgets();
98

99
    connectCommonWidgets();
100

101
    arrangeCommonCenterStack();
102 103

    configureWindowName();
pixhawk's avatar
pixhawk committed
104 105 106 107

    // Set the application style (not the same as a style sheet)
    // Set the style to Plastique
    qApp->setStyle("plastique");
108

pixhawk's avatar
pixhawk committed
109
    // Set style sheet as last step
110 111 112 113 114 115 116
    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
117

118
    // Create actions
119
    connectCommonActions();
120

121 122 123
    // Set dock options
    setDockOptions(AnimatedDocks | AllowTabbedDocks | AllowNestedDocks);

124
    // Load mavlink view as default widget set
125
    //loadMAVLinkView();
126

lm's avatar
lm committed
127 128
    statusBar()->setSizeGripEnabled(true);

129 130
    // Restore the window position and size
    if (settings.contains(getWindowGeometryKey()))
131 132
    {
        // Restore the window geometry
133
        restoreGeometry(settings.value(getWindowGeometryKey()).toByteArray());
134 135 136 137 138 139
    }
    else
    {
        // Adjust the size
        adjustSize();
    }
pixhawk's avatar
pixhawk committed
140

141 142 143 144 145 146
    // Populate link menu
    QList<LinkInterface*> links = LinkManager::instance()->getLinks();
    foreach(LinkInterface* link, links)
    {
        this->addLink(link);
    }
147

148 149
    connect(LinkManager::instance(), SIGNAL(newLink(LinkInterface*)), this, SLOT(addLink(LinkInterface*)));

150 151 152 153 154 155
    // Connect user interface devices
    if (!joystick)
    {
        joystick = new JoystickInput();
    }

lm's avatar
lm committed
156 157
    // Enable and update view
    presentView();
pixhawk's avatar
pixhawk committed
158 159
}

pixhawk's avatar
pixhawk committed
160
MainWindow::~MainWindow()
pixhawk's avatar
pixhawk committed
161
{
lm's avatar
lm committed
162

pixhawk's avatar
pixhawk committed
163 164
}

165 166 167 168 169 170 171 172 173 174 175 176
/**
 * 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);
177 178 179 180 181

        // 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);
182 183 184 185 186 187 188 189 190 191
    }

    // 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);
192 193
        // ENABLE HUD TOOL WIDGET
        settings.setValue(buildMenuKey(SUB_SECTION_CHECKED,MainWindow::MENU_HUD,VIEW_OPERATOR), true);
194 195 196 197 198 199 200
    }

    // ENGINEER VIEW DEFAULT
    centralKey = buildMenuKey(SUB_SECTION_CHECKED, CENTRAL_LINECHART, VIEW_ENGINEER);
    if (!settings.contains(centralKey))
    {
        settings.setValue(centralKey,true);
201 202
        // Enable Parameter widget
        settings.setValue(buildMenuKey(SUB_SECTION_CHECKED,MainWindow::MENU_PARAMETERS,VIEW_ENGINEER), true);
203 204 205 206 207 208 209 210 211 212 213 214 215 216
    }

    // 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);
217 218
        // Enable Flight display
        settings.setValue(buildMenuKey(SUB_SECTION_CHECKED,MainWindow::MENU_HDD_1,VIEW_PILOT), true);
219 220 221
    }
}

lm's avatar
lm committed
222 223 224 225 226 227 228 229 230 231 232 233 234
void MainWindow::resizeEvent(QResizeEvent * event)
{
    Q_UNUSED(event);
    if (height() < 800)
    {
        ui.statusBar->setVisible(false);
    }
    else
    {
        ui.statusBar->setVisible(true);
    }
}

235 236 237 238 239 240 241 242 243 244
QString MainWindow::getWindowStateKey()
{
    return QString::number(currentView)+"/windowstate";
}

QString MainWindow::getWindowGeometryKey()
{
    return QString::number(currentView)+"/geometry";
}

lm's avatar
lm committed
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
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)
        {
            qDebug() << "ADDING WIDGET #" << i << widgets.at(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);
            }
        }
    }
}

282 283 284 285
void MainWindow::buildCommonWidgets()
{
    //TODO:  move protocol outside UI
    mavlink     = new MAVLinkProtocol();
286
    connect(mavlink, SIGNAL(protocolStatusMessage(QString,QString)), this, SLOT(showCriticalMessage(QString,QString)), Qt::QueuedConnection);
287 288

    // Dock widgets
289 290 291
    if (!controlDockWidget)
    {
        controlDockWidget = new QDockWidget(tr("Control"), this);
292
        controlDockWidget->setObjectName("UNMANNED_SYSTEM_CONTROL_DOCKWIDGET");
293
        controlDockWidget->setWidget( new UASControlWidget(this) );
294
        addToToolsMenu (controlDockWidget, tr("Control"), SLOT(showToolWidget(bool)), MENU_UAS_CONTROL, Qt::LeftDockWidgetArea);
295
    }
296

297 298 299 300
    if (!listDockWidget)
    {
        listDockWidget = new QDockWidget(tr("Unmanned Systems"), this);
        listDockWidget->setWidget( new UASListWidget(this) );
301
        listDockWidget->setObjectName("UNMANNED_SYSTEMS_LIST_DOCKWIDGET");
302
        addToToolsMenu (listDockWidget, tr("Unmanned Systems"), SLOT(showToolWidget(bool)), MENU_UAS_LIST, Qt::RightDockWidgetArea);
303
    }
304

305 306 307
    if (!waypointsDockWidget)
    {
        waypointsDockWidget = new QDockWidget(tr("Waypoint List"), this);
308
        waypointsDockWidget->setWidget( new QGCWaypointListMulti(this) );
309
        waypointsDockWidget->setObjectName("WAYPOINT_LIST_DOCKWIDGET");
310
        addToToolsMenu (waypointsDockWidget, tr("Waypoints List"), SLOT(showToolWidget(bool)), MENU_WAYPOINTS, Qt::BottomDockWidgetArea);
311
    }
312

313 314 315 316
    if (!infoDockWidget)
    {
        infoDockWidget = new QDockWidget(tr("Status Details"), this);
        infoDockWidget->setWidget( new UASInfoWidget(this) );
pixhawk's avatar
pixhawk committed
317
        infoDockWidget->setObjectName("UAS_STATUS_DETAILS_DOCKWIDGET");
318
        addToToolsMenu (infoDockWidget, tr("Status Details"), SLOT(showToolWidget(bool)), MENU_STATUS, Qt::RightDockWidgetArea);
319
    }
320

321 322 323 324
    if (!debugConsoleDockWidget)
    {
        debugConsoleDockWidget = new QDockWidget(tr("Communication Console"), this);
        debugConsoleDockWidget->setWidget( new DebugConsole(this) );
325
        debugConsoleDockWidget->setObjectName("COMMUNICATION_DEBUG_CONSOLE_DOCKWIDGET");
326
        addToToolsMenu (debugConsoleDockWidget, tr("Communication Console"), SLOT(showToolWidget(bool)), MENU_DEBUG_CONSOLE, Qt::BottomDockWidgetArea);
327
    }
328

329 330 331 332 333
    if (!logPlayerDockWidget)
    {
        logPlayerDockWidget = new QDockWidget(tr("MAVLink Log Player"), this);
        logPlayerDockWidget->setWidget( new QGCMAVLinkLogPlayer(mavlink, this) );
        logPlayerDockWidget->setObjectName("MAVLINK_LOG_PLAYER_DOCKWIDGET");
334
        addToToolsMenu(logPlayerDockWidget, tr("MAVLink Log Replay"), SLOT(showToolWidget(bool)), MENU_MAVLINK_LOG_PLAYER, Qt::RightDockWidgetArea);
335 336
    }

337
    // Center widgets
338 339
    if (!mapWidget)
    {
340
        mapWidget = new MapWidget(this);
341 342
        addToCentralWidgetsMenu (mapWidget, "Maps", SLOT(showCentralWidget()),CENTRAL_MAP);
    }
343

344 345 346 347 348
    if (!protocolWidget)
    {
        protocolWidget    = new XMLCommProtocolWidget(this);
        addToCentralWidgetsMenu (protocolWidget, "Mavlink Generator", SLOT(showCentralWidget()),CENTRAL_PROTOCOL);
    }
lm's avatar
lm committed
349

350
#ifdef MAVLINK_ENABLED_SLUGS
Alejandro's avatar
Alejandro committed
351 352 353 354 355
    //TODO temporaly debug
    if (!slugsHilSimWidget)
    {
        slugsHilSimWidget = new QDockWidget(tr("Slugs Hil Sim"), this);
        slugsHilSimWidget->setWidget( new SlugsHilSim(this));
356
        addToToolsMenu (slugsHilSimWidget, tr("HIL Sim Configuration"), SLOT(showToolWidget(bool)), MENU_SLUGS_HIL, Qt::LeftDockWidgetArea);
Alejandro's avatar
Alejandro committed
357 358 359 360 361 362 363
    }

    //TODO temporaly debug
    if (!slugsCamControlWidget)
    {
        slugsCamControlWidget = new QDockWidget(tr("Slugs Video Camera Control"), this);
        slugsCamControlWidget->setWidget(new SlugsVideoCamControl(this));
364
        addToToolsMenu (slugsCamControlWidget, tr("Camera Control"), SLOT(showToolWidget(bool)), MENU_SLUGS_CAMERA, Qt::BottomDockWidgetArea);
Alejandro's avatar
Alejandro committed
365
    }
366 367
#endif

lm's avatar
lm committed
368 369 370 371 372
    if (!dataplotWidget)
    {
        dataplotWidget    = new QGCDataPlot2D(this);
        addToCentralWidgetsMenu (dataplotWidget, "Data Plot", SLOT(showCentralWidget()),CENTRAL_DATA_PLOT);
    }
373
}
374

375

376
void MainWindow::buildPxWidgets()
377
{
pixhawk's avatar
pixhawk committed
378 379
    //FIXME: memory of acceptList will never be freed again
    QStringList* acceptList = new QStringList();
lm's avatar
lm committed
380 381 382
    acceptList->append("-105,roll,deg,+105,s");
    acceptList->append("-105,pitch,deg,+105,s");
    acceptList->append("-105,yaw,deg,+105,s");
383

lm's avatar
lm committed
384 385 386
    acceptList->append("-260,rollspeed,deg/s,+260,s");
    acceptList->append("-260,pitchspeed,deg/s,+260,s");
    acceptList->append("-260,yawspeed,deg/s,+260,s");
387

pixhawk's avatar
pixhawk committed
388 389
    //FIXME: memory of acceptList2 will never be freed again
    QStringList* acceptList2 = new QStringList();
lm's avatar
lm committed
390
    acceptList2->append("0,abs pressure,hPa,65500");
391 392
    acceptList2->append("-999,accel. X,raw,999,s");
    acceptList2->append("-999,accel. Y,raw,999,s");
393

394 395 396 397 398 399
    if (!linechartWidget)
    {
        // Center widgets
        linechartWidget   = new Linecharts(this);
        addToCentralWidgetsMenu(linechartWidget, "Line Plots", SLOT(showCentralWidget()), CENTRAL_LINECHART);
    }
400 401


402 403 404 405 406
    if (!hudWidget)
    {
        hudWidget         = new HUD(320, 240, this);
        addToCentralWidgetsMenu(hudWidget, "HUD", SLOT(showCentralWidget()), CENTRAL_HUD);
    }
407

408 409 410 411 412
    if (!dataplotWidget)
    {
        dataplotWidget    = new QGCDataPlot2D(this);
        addToCentralWidgetsMenu(dataplotWidget, "Data Plots", SLOT(showCentralWidget()), CENTRAL_DATA_PLOT);
    }
413

414
#ifdef QGC_OSG_ENABLED
415 416
    if (!_3DWidget)
    {
417 418
        _3DWidget         = Q3DWidgetFactory::get("PIXHAWK");
        addToCentralWidgetsMenu(_3DWidget, "Local 3D", SLOT(showCentralWidget()), CENTRAL_3D_LOCAL);
419
    }
420
#endif
421

422
#ifdef QGC_OSGEARTH_ENABLED
423 424 425 426 427
    if (!_3DMapWidget)
    {
        _3DMapWidget = Q3DWidgetFactory::get("MAP3D");
        addToCentralWidgetsMenu(_3DMapWidget, "OSG Earth 3D", SLOT(showCentralWidget()), CENTRAL_OSGEARTH);
    }
428
#endif
lm's avatar
lm committed
429

430
#if (defined _MSC_VER) | (defined Q_OS_MAC)
431 432 433 434 435
    if (!gEarthWidget)
    {
        gEarthWidget = new QGCGoogleEarthView(this);
        addToCentralWidgetsMenu(gEarthWidget, "Google Earth", SLOT(showCentralWidget()), CENTRAL_GOOGLE_EARTH);
    }
436

437
#endif
438

pixhawk's avatar
pixhawk committed
439
    // Dock widgets
440

441 442 443 444
    if (!detectionDockWidget)
    {
        detectionDockWidget = new QDockWidget(tr("Object Recognition"), this);
        detectionDockWidget->setWidget( new ObjectDetectionView("images/patterns", this) );
pixhawk's avatar
pixhawk committed
445
        detectionDockWidget->setObjectName("OBJECT_DETECTION_DOCK_WIDGET");
446
        addToToolsMenu (detectionDockWidget, tr("Object Recognition"), SLOT(showToolWidget(bool)), MENU_DETECTION, Qt::RightDockWidgetArea);
447
    }
448

449 450
    if (!parametersDockWidget)
    {
451
        parametersDockWidget = new QDockWidget(tr("Calibration and Onboard Parameters"), this);
452
        parametersDockWidget->setWidget( new ParameterInterface(this) );
pixhawk's avatar
pixhawk committed
453
        parametersDockWidget->setObjectName("PARAMETER_INTERFACE_DOCKWIDGET");
454
        addToToolsMenu (parametersDockWidget, tr("Calibration and Parameters"), SLOT(showToolWidget(bool)), MENU_PARAMETERS, Qt::RightDockWidgetArea);
455
    }
456

457 458 459 460
    if (!watchdogControlDockWidget)
    {
        watchdogControlDockWidget = new QDockWidget(tr("Process Control"), this);
        watchdogControlDockWidget->setWidget( new WatchdogControl(this) );
pixhawk's avatar
pixhawk committed
461
        watchdogControlDockWidget->setObjectName("WATCHDOG_CONTROL_DOCKWIDGET");
462
        addToToolsMenu (watchdogControlDockWidget, tr("Process Control"), SLOT(showToolWidget(bool)), MENU_WATCHDOG, Qt::BottomDockWidgetArea);
463
    }
464

465 466 467 468
    if (!hsiDockWidget)
    {
        hsiDockWidget = new QDockWidget(tr("Horizontal Situation Indicator"), this);
        hsiDockWidget->setWidget( new HSIDisplay(this) );
469
        hsiDockWidget->setObjectName("HORIZONTAL_SITUATION_INDICATOR_DOCK_WIDGET");
470
        addToToolsMenu (hsiDockWidget, tr("HSI"), SLOT(showToolWidget(bool)), MENU_HSI, Qt::BottomDockWidgetArea);
471
    }
472

473 474
    if (!headDown1DockWidget)
    {
475 476
        headDown1DockWidget = new QDockWidget(tr("Flight Display"), this);
        headDown1DockWidget->setWidget( new HDDisplay(acceptList, "Flight Display", this) );
477
        headDown1DockWidget->setObjectName("HEAD_DOWN_DISPLAY_1_DOCK_WIDGET");
478
        addToToolsMenu (headDown1DockWidget, tr("Flight Display"), SLOT(showToolWidget(bool)), MENU_HDD_1, Qt::RightDockWidgetArea);
479
    }
480

481 482 483
    if (!headDown2DockWidget)
    {
        headDown2DockWidget = new QDockWidget(tr("Payload Status"), this);
484
        headDown2DockWidget->setWidget( new HDDisplay(acceptList2, "Payload Status", this) );
485
        headDown2DockWidget->setObjectName("HEAD_DOWN_DISPLAY_2_DOCK_WIDGET");
486
        addToToolsMenu (headDown2DockWidget, tr("Payload Status"), SLOT(showToolWidget(bool)), MENU_HDD_2, Qt::RightDockWidgetArea);
487
    }
488

489 490 491 492
    if (!rcViewDockWidget)
    {
        rcViewDockWidget = new QDockWidget(tr("Radio Control"), this);
        rcViewDockWidget->setWidget( new QGCRemoteControlView(this) );
493
        rcViewDockWidget->setObjectName("RADIO_CONTROL_CHANNELS_DOCK_WIDGET");
494
        addToToolsMenu (rcViewDockWidget, tr("Radio Control"), SLOT(showToolWidget(bool)), MENU_RC_VIEW, Qt::BottomDockWidgetArea);
495
    }
496

497 498 499 500
    if (!headUpDockWidget)
    {
        headUpDockWidget = new QDockWidget(tr("HUD"), this);
        headUpDockWidget->setWidget( new HUD(320, 240, this));
501
        headUpDockWidget->setObjectName("HEAD_UP_DISPLAY_DOCK_WIDGET");
502
        addToToolsMenu (headUpDockWidget, tr("Head Up Display"), SLOT(showToolWidget(bool)), MENU_HUD, Qt::RightDockWidgetArea);
503
    }
504

pixhawk's avatar
pixhawk committed
505 506 507 508 509 510 511 512 513
    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");
514
        addToToolsMenu (video1DockWidget, tr("Video Stream 1"), SLOT(showToolWidget(bool)), MENU_VIDEO_STREAM_1, Qt::LeftDockWidgetArea);
pixhawk's avatar
pixhawk committed
515 516 517 518 519 520 521 522 523 524 525
    }

    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");
526
        addToToolsMenu (video2DockWidget, tr("Video Stream 2"), SLOT(showToolWidget(bool)), MENU_VIDEO_STREAM_2, Qt::LeftDockWidgetArea);
pixhawk's avatar
pixhawk committed
527 528
    }

pixhawk's avatar
pixhawk committed
529 530
    // Dialogue widgets
    //FIXME: free memory in destructor
531 532 533 534
}

void MainWindow::buildSlugsWidgets()
{
535 536 537 538 539
    if (!linechartWidget)
    {
        // Center widgets
        linechartWidget   = new Linecharts(this);
    }
540

541 542 543 544 545
    if (!headUpDockWidget)
    {
        // Dock widgets
        headUpDockWidget = new QDockWidget(tr("Control Indicator"), this);
        headUpDockWidget->setWidget( new HUD(320, 240, this));
pixhawk's avatar
pixhawk committed
546
        headUpDockWidget->setObjectName("HEAD_UP_DISPLAY_DOCK_WIDGET");
547
        addToToolsMenu (headUpDockWidget, tr("HUD"), SLOT(showToolWidget(bool)), MENU_HUD, Qt::LeftDockWidgetArea);
548
    }
549

550 551 552 553
    if (!rcViewDockWidget)
    {
        rcViewDockWidget = new QDockWidget(tr("Radio Control"), this);
        rcViewDockWidget->setWidget( new QGCRemoteControlView(this) );
pixhawk's avatar
pixhawk committed
554
        rcViewDockWidget->setObjectName("RADIO_CONTROL_CHANNELS_DOCK_WIDGET");
555
        addToToolsMenu (rcViewDockWidget, tr("Radio Control"), SLOT(showToolWidget(bool)), MENU_RC_VIEW, Qt::BottomDockWidgetArea);
556
    }
557

558 559 560 561 562
    if (!slugsDataWidget)
    {
        // Dialog widgets
        slugsDataWidget = new QDockWidget(tr("Slugs Data"), this);
        slugsDataWidget->setWidget( new SlugsDataSensorView(this));
pixhawk's avatar
pixhawk committed
563
        slugsDataWidget->setObjectName("SLUGS_DATA_DOCK_WIDGET");
564
        addToToolsMenu (slugsDataWidget, tr("Telemetry Data"), SLOT(showToolWidget(bool)), MENU_SLUGS_DATA, Qt::RightDockWidgetArea);
565
    }
566

567 568 569 570
    if (!slugsPIDControlWidget)
    {
        slugsPIDControlWidget = new QDockWidget(tr("Slugs PID Control"), this);
        slugsPIDControlWidget->setWidget(new SlugsPIDControl(this));
pixhawk's avatar
pixhawk committed
571
        slugsPIDControlWidget->setObjectName("SLUGS_PID_CONTROL_DOCK_WIDGET");
572
        addToToolsMenu (slugsPIDControlWidget, tr("PID Configuration"), SLOT(showToolWidget(bool)), MENU_SLUGS_PID, Qt::LeftDockWidgetArea);
573
    }
574

575 576 577 578
    if (!slugsHilSimWidget)
    {
        slugsHilSimWidget = new QDockWidget(tr("Slugs Hil Sim"), this);
        slugsHilSimWidget->setWidget( new SlugsHilSim(this));
pixhawk's avatar
pixhawk committed
579
        slugsHilSimWidget->setObjectName("SLUGS_HIL_SIM_DOCK_WIDGET");
580
        addToToolsMenu (slugsHilSimWidget, tr("HIL Sim Configuration"), SLOT(showToolWidget(bool)), MENU_SLUGS_HIL, Qt::LeftDockWidgetArea);
581
    }
582

583 584 585 586
    if (!slugsCamControlWidget)
    {
        slugsCamControlWidget = new QDockWidget(tr("Slugs Video Camera Control"), this);
        slugsCamControlWidget->setWidget(new SlugsVideoCamControl(this));
pixhawk's avatar
pixhawk committed
587
        slugsCamControlWidget->setObjectName("SLUGS_CAM_CONTROL_DOCK_WIDGET");
588
        addToToolsMenu (slugsCamControlWidget, tr("Camera Control"), SLOT(showToolWidget(bool)), MENU_SLUGS_CAMERA, Qt::BottomDockWidgetArea);
589
    }
590
}
591 592 593 594 595


void MainWindow::addToCentralWidgetsMenu ( QWidget* widget,
                                           const QString title,
                                           const char * slotName,
596 597
                                           TOOLS_WIDGET_NAMES centralWidget)
{
598
    QAction* tempAction;
599

600

601
// Not needed any more - separate menu now available
602

603 604 605 606 607 608 609 610 611
//    // Add the separator that will separate tools from central Widgets
//    if (!toolsMenuActions[CENTRAL_SEPARATOR])
//    {
//        tempAction = ui.menuTools->addSeparator();
//        toolsMenuActions[CENTRAL_SEPARATOR] = tempAction;
//        tempAction->setData(CENTRAL_SEPARATOR);
//    }

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

613 614
    tempAction->setCheckable(true);
    tempAction->setData(centralWidget);
615

616 617 618
    // populate the Hashes
    toolsMenuActions[centralWidget] = tempAction;
    dockWidgets[centralWidget] = widget;
619

620
    QString chKey = buildMenuKey(SUB_SECTION_CHECKED, centralWidget, currentView);
621

622 623
    if (!settings.contains(chKey))
    {
624 625 626
        settings.setValue(chKey,false);
        tempAction->setChecked(false);
    }
627 628 629 630
    else
    {
        tempAction->setChecked(settings.value(chKey).toBool());
    }
631

632
    // connect the action
633
    connect(tempAction,SIGNAL(triggered(bool)),this, slotName);
634 635 636
}


lm's avatar
lm committed
637 638
void MainWindow::showCentralWidget()
{
639
    QAction* senderAction = qobject_cast<QAction *>(sender());
640 641 642 643

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

644 645
    int tool = senderAction->data().toInt();
    QString chKey;
646

647
    // check the current action
648

649 650 651 652
    if (senderAction && dockWidgets[tool])
    {
        // uncheck all central widget actions
        QHashIterator<int, QAction*> i(toolsMenuActions);
653 654
        while (i.hasNext())
        {
655
            i.next();
656 657 658
            //qDebug() << "shCW" << i.key() << "read";
            if (i.value() && i.value()->data().toInt() > 255)
            {
659 660 661
                // Block signals and uncheck action
                // firing would be unneccesary
                i.value()->blockSignals(true);
662
                i.value()->setChecked(false);
663
                i.value()->blockSignals(false);
664 665 666 667 668 669

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

671
        // check the current action
672
        //qDebug() << senderAction->text();
673
        senderAction->setChecked(true);
674

675 676
        // update the central widget
        centerStack->setCurrentWidget(dockWidgets[tool]);
677

678 679 680
        // store the selected central widget
        chKey = buildMenuKey (SUB_SECTION_CHECKED,static_cast<TOOLS_WIDGET_NAMES>(tool), currentView);
        settings.setValue(chKey,true);
681

682 683 684
        // Unblock sender action
        senderAction->blockSignals(false);

685 686
        presentView();
    }
687
}
688

lm's avatar
lm committed
689 690 691 692
/**
 * Adds a widget to the tools menu and sets it visible if it was
 * enabled last time.
 */
693
void MainWindow::addToToolsMenu ( QWidget* widget,
694 695 696 697
                                  const QString title,
                                  const char * slotName,
                                  TOOLS_WIDGET_NAMES tool,
                                  Qt::DockWidgetArea location)
lm's avatar
lm committed
698
{
699 700
    QAction* tempAction;
    QString posKey, chKey;
701

702

703 704
    if (toolsMenuActions[CENTRAL_SEPARATOR])
    {
705 706 707
        tempAction = new QAction(title, this);
        ui.menuTools->insertAction(toolsMenuActions[CENTRAL_SEPARATOR],
                                   tempAction);
708 709 710
    }
    else
    {
711 712
        tempAction = ui.menuTools->addAction(title);
    }
713

714 715
    tempAction->setCheckable(true);
    tempAction->setData(tool);
716

717 718 719
    // populate the Hashes
    toolsMenuActions[tool] = tempAction;
    dockWidgets[tool] = widget;
720
    //qDebug() << widget;
721

722
    posKey = buildMenuKey (SUB_SECTION_LOCATION,tool, currentView);
723

724 725
    if (!settings.contains(posKey))
    {
726 727
        settings.setValue(posKey,location);
        dockWidgetLocations[tool] = location;
728 729 730 731
    }
    else
    {
        dockWidgetLocations[tool] = static_cast <Qt::DockWidgetArea> (settings.value(posKey, Qt::RightDockWidgetArea).toInt());
732
    }
733

734
    chKey = buildMenuKey(SUB_SECTION_CHECKED,tool, currentView);
735

736 737 738 739
    if (!settings.contains(chKey))
    {
        settings.setValue(chKey,false);
        tempAction->setChecked(false);
740
        widget->setVisible(false);
741 742 743
    }
    else
    {
744
        tempAction->setChecked(settings.value(chKey, false).toBool());
745
        widget->setVisible(settings.value(chKey, false).toBool());
746
    }
747

748
    // connect the action
749 750 751
    connect(tempAction,SIGNAL(toggled(bool)),this, slotName);

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

754 755
    //  connect(qobject_cast <QDockWidget *>(dockWidgets[tool]),
    //          SIGNAL(visibilityChanged(bool)), this, SLOT(updateVisibilitySettings(bool)));
756

757 758
    connect(qobject_cast <QDockWidget *>(dockWidgets[tool]),
            SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), this, SLOT(updateLocationSettings(Qt::DockWidgetArea)));
759 760
}

761
void MainWindow::showToolWidget(bool visible)
762
{
763
    if (!aboutToCloseFlag && !changingViewsFlag)
764
    {
765 766
        QAction* action = qobject_cast<QAction *>(sender());

767 768
        // Prevent this to fire if undocked
        if (action)
769
        {
770
            int tool = action->data().toInt();
771

772
            QDockWidget* dockWidget = qobject_cast<QDockWidget *> (dockWidgets[tool]);
773

774 775 776 777 778 779 780 781 782 783 784 785 786 787 788
            qDebug() << "DATA:" << tool << "FLOATING" << dockWidget->isFloating() << "checked" << action->isChecked() << "visible" << dockWidget->isVisible() << "action vis:" << action->isVisible();
            if (dockWidget && dockWidget->isVisible() != visible)
            {
                if (visible)
                {
                    qDebug() << "DOCK WIDGET ADDED";
                    addDockWidget(dockWidgetLocations[tool], dockWidget);
                    dockWidget->show();
                }
                else
                {
                    qDebug() << "DOCK WIDGET REMOVED";
                    removeDockWidget(dockWidget);
                    //dockWidget->hide();
                }
789 790 791 792 793 794 795 796 797 798 799 800 801

                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);
                        qDebug() << "showToolWidget(): Set key" << chKey << "to" << visible;
                        break;
                    }
                }
802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832
            }
        }

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

        qDebug() << "Trying to cast dockwidget" << dockWidget << "isvisible" << visible;

        if (dockWidget)
        {
            // Get action
            int tool = dockWidgets.key(dockWidget);

            qDebug() << "Updating widget setting" << tool << "to" << visible;

            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);
                    qDebug() << "showToolWidget(): Set key" << chKey << "to" << visible;
                    break;
                }
            }
833
        }
834 835 836 837
    }
}


838 839 840 841 842
void MainWindow::showTheWidget (TOOLS_WIDGET_NAMES widget, VIEW_SECTIONS view)
{
    bool tempVisible;
    Qt::DockWidgetArea tempLocation;
    QDockWidget* tempWidget = static_cast <QDockWidget *>(dockWidgets[widget]);
843

844
    tempVisible =  settings.value(buildMenuKey(SUB_SECTION_CHECKED,widget,view), false).toBool();
845

846 847
     qDebug() << "showTheWidget(): Set key" << buildMenuKey(SUB_SECTION_CHECKED,widget,view) << "to" << tempVisible;

848 849 850 851
    if (tempWidget)
    {
        toolsMenuActions[widget]->setChecked(tempVisible);
    }
852 853


854
    //qDebug() <<  buildMenuKey (SUB_SECTION_CHECKED,widget,view) << tempVisible;
855

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

858 859 860 861 862 863 864
    //    if (widget == MainWindow::MENU_UAS_LIST)
    //    {
    //        if (!settings.contains(buildMenuKey (SUB_SECTION_LOCATION,widget, view)))
    //        {
    //            tempLocation = Qt::RightDockWidgetArea;
    //        }
    //    }
865

866
    if (tempWidget != NULL)
867
    {
868 869 870 871 872
        if (tempVisible)
        {
            addDockWidget(tempLocation, tempWidget);
            tempWidget->show();
        }
873 874
    }
}
875

876 877 878 879 880
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;

881 882 883 884 885
//    apType = (UASManager::instance() && UASManager::instance()->silentGetActiveUAS())?
//             UASManager::instance()->getActiveUAS()->getAutopilotType():
//             -1;

    apType = 1;
886

887 888 889 890 891
    return (QString::number(apType) + "_" +
            QString::number(SECTION_MENU) + "_" +
            QString::number(view) + "_" +
            QString::number(tool) + "_" +
            QString::number(section) + "_" );
892 893
}

894 895
void MainWindow::closeEvent(QCloseEvent *event)
{
896
    settings.setValue(getWindowGeometryKey(), saveGeometry());
897 898
    //settings.setValue("windowState", saveState());
    aboutToCloseFlag = true;
899 900 901 902 903 904
    // Save the last current view in any case
    settings.setValue("CURRENT_VIEW", currentView);
    // Save the current window state, but only if a system is connected (else no real number of widgets would be present)
    if (UASManager::instance()->getActiveUAS()) settings.setValue(getWindowStateKey(), saveState(QGC::applicationVersion()));
    // Save the current view only if a UAS is connected
    if (UASManager::instance()->getUASList().length() > 0) settings.setValue("CURRENT_VIEW_WITH_UAS_CONNECTED", currentView);
905 906 907
    settings.sync();
    QMainWindow::closeEvent(event);
}
908

909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931
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;
                }
            }
        }
    }
}
932

933 934
void MainWindow::updateVisibilitySettings (bool vis)
{
935
    if (!aboutToCloseFlag && !changingViewsFlag)
936 937 938 939 940 941
    {
        QDockWidget* temp = qobject_cast<QDockWidget *>(sender());

        if (temp)
        {
            QHashIterator<int, QWidget*> i(dockWidgets);
942 943
            while (i.hasNext())
            {
944
                i.next();
945 946
                if ((static_cast <QDockWidget *>(dockWidgets[i.key()])) == temp)
                {
947 948
                    QString chKey = buildMenuKey (SUB_SECTION_CHECKED,static_cast<TOOLS_WIDGET_NAMES>(i.key()), currentView);
                    settings.setValue(chKey,vis);
949 950 951 952 953 954
                    toolsMenuActions[i.key()]->setChecked(vis);
                    break;
                }
            }
        }
    }
955 956
}

957 958 959
void MainWindow::updateLocationSettings (Qt::DockWidgetArea location)
{
    QDockWidget* temp = qobject_cast<QDockWidget *>(sender());
960

961 962 963 964 965 966 967 968 969 970 971
    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;
        }
    }
972 973
}

974 975 976
/**
 * Connect the signals and slots of the common window widgets
 */
977
void MainWindow::connectCommonWidgets()
978
{
pixhawk's avatar
pixhawk committed
979 980 981 982 983
    if (infoDockWidget && infoDockWidget->widget())
    {
        connect(mavlink, SIGNAL(receiveLossChanged(int, float)),
                infoDockWidget->widget(), SLOT(updateSendLoss(int, float)));
    }
984

pixhawk's avatar
pixhawk committed
985 986
    if (mapWidget && waypointsDockWidget->widget())
    {
987

988
    }
Alejandro's avatar
Alejandro committed
989 990 991 992 993 994

    //TODO temporaly debug
    if (slugsHilSimWidget && slugsHilSimWidget->widget()){
        connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)),
                slugsHilSimWidget->widget(), SLOT(activeUasSet(UASInterface*)));
    }
995
}
996

997 998
void MainWindow::createCustomWidget()
{
999
    //qDebug() << "ADDING CUSTOM WIDGET";
lm's avatar
lm committed
1000 1001 1002 1003 1004 1005 1006 1007
    QGCToolWidget* tool = new QGCToolWidget("Unnamed Tool", this);

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

1008
    QDockWidget* dock = new QDockWidget("Unnamed Tool", this);
lm's avatar
lm committed
1009
    connect(tool, SIGNAL(destroyed()), dock, SLOT(deleteLater()));
1010
    dock->setWidget(tool);
lm's avatar
lm committed
1011 1012 1013 1014 1015 1016
    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);
1017
    dock->setVisible(true);
1018 1019 1020 1021
}

void MainWindow::connectPxWidgets()
{
1022
    // No special connections necessary at this point
1023 1024 1025 1026
}

void MainWindow::connectSlugsWidgets()
{
1027
    if (slugsHilSimWidget && slugsHilSimWidget->widget()){
1028 1029
        connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)),
                slugsHilSimWidget->widget(), SLOT(activeUasSet(UASInterface*)));
1030 1031 1032
    }

    if (slugsDataWidget && slugsDataWidget->widget()){
1033 1034
        connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)),
                slugsDataWidget->widget(), SLOT(setActiveUAS(UASInterface*)));
1035 1036
    }

1037

1038 1039
}

1040
void MainWindow::arrangeCommonCenterStack()
1041
{
1042
    centerStack = new QStackedWidget(this);
1043
    centerStack->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
1044

pixhawk's avatar
pixhawk committed
1045
    if (!centerStack) return;
1046

1047
    if (mapWidget && (centerStack->indexOf(mapWidget) == -1)) centerStack->addWidget(mapWidget);
lm's avatar
lm committed
1048
    if (dataplotWidget && (centerStack->indexOf(dataplotWidget) == -1)) centerStack->addWidget(dataplotWidget);
1049
    if (protocolWidget && (centerStack->indexOf(protocolWidget) == -1)) centerStack->addWidget(protocolWidget);
1050 1051 1052 1053 1054 1055 1056

    setCentralWidget(centerStack);
}

void MainWindow::arrangePxCenterStack()
{

1057 1058 1059 1060
    if (!centerStack) {
        qDebug() << "Center Stack not Created!";
        return;
    }
1061

1062 1063

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

1065
#ifdef QGC_OSG_ENABLED
1066
    if (_3DWidget && (centerStack->indexOf(_3DWidget) == -1)) centerStack->addWidget(_3DWidget);
1067
#endif
1068
#ifdef QGC_OSGEARTH_ENABLED
1069
    if (_3DMapWidget && (centerStack->indexOf(_3DMapWidget) == -1)) centerStack->addWidget(_3DMapWidget);
1070
#endif
1071
#if (defined _MSC_VER) | (defined Q_OS_MAC)
1072
    if (gEarthWidget && (centerStack->indexOf(gEarthWidget) == -1)) centerStack->addWidget(gEarthWidget);
1073
#endif
1074 1075
    if (hudWidget && (centerStack->indexOf(hudWidget) == -1)) centerStack->addWidget(hudWidget);
    if (dataplotWidget && (centerStack->indexOf(dataplotWidget) == -1)) centerStack->addWidget(dataplotWidget);
1076 1077 1078 1079 1080
}

void MainWindow::arrangeSlugsCenterStack()
{

1081 1082 1083 1084
    if (!centerStack) {
        qDebug() << "Center Stack not Created!";
        return;
    }
1085

1086 1087
    if (linechartWidget && (centerStack->indexOf(linechartWidget) == -1)) centerStack->addWidget(linechartWidget);
    if (hudWidget && (centerStack->indexOf(hudWidget) == -1)) centerStack->addWidget(hudWidget);
1088

1089 1090
}

1091 1092
void MainWindow::configureWindowName()
{
pixhawk's avatar
pixhawk committed
1093 1094 1095
    QList<QHostAddress> hostAddresses = QNetworkInterface::allAddresses();
    QString windowname = qApp->applicationName() + " " + qApp->applicationVersion();
    bool prevAddr = false;
1096

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

pixhawk's avatar
pixhawk committed
1099 1100 1101 1102 1103 1104 1105 1106 1107 1108
    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;
        }
    }
1109

pixhawk's avatar
pixhawk committed
1110
    windowname.append(")");
1111

pixhawk's avatar
pixhawk committed
1112
    setWindowTitle(windowname);
1113 1114

#ifndef Q_WS_MAC
pixhawk's avatar
pixhawk committed
1115
    //qApp->setWindowIcon(QIcon(":/core/images/qtcreator_logo_128.png"));
1116 1117 1118
#endif
}

pixhawk's avatar
pixhawk committed
1119
void MainWindow::startVideoCapture()
pixhawk's avatar
pixhawk committed
1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130
{
    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);
1131 1132 1133
    //videoTimer->setInterval(40);
    //connect(videoTimer, SIGNAL(timeout()), this, SLOT(saveScreen()));
    //videoTimer->stop();
pixhawk's avatar
pixhawk committed
1134 1135
}

pixhawk's avatar
pixhawk committed
1136
void MainWindow::stopVideoCapture()
pixhawk's avatar
pixhawk committed
1137 1138 1139 1140 1141 1142
{
    videoTimer->stop();

    // TODO Convert raw images to PNG
}

pixhawk's avatar
pixhawk committed
1143
void MainWindow::saveScreen()
pixhawk's avatar
pixhawk committed
1144 1145 1146 1147 1148 1149 1150 1151 1152 1153
{
    QPixmap window = QPixmap::grabWindow(this->winId());
    QString format = "bmp";

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

1154 1155 1156 1157 1158 1159
/**
 * 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
1160
void MainWindow::reloadStylesheet()
pixhawk's avatar
pixhawk committed
1161
{
1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178
    QString fileName = QCoreApplication::applicationDirPath() + "/style-indoor.css";

    // Let user select style sheet
    fileName = QFileDialog::getOpenFileName(this, tr("Specify stylesheet"), fileName, tr("CSS Stylesheet (*.css);;"));

    if (!fileName.endsWith(".css"))
    {
        QMessageBox msgBox;
        msgBox.setIcon(QMessageBox::Information);
        msgBox.setText(tr("QGroundControl did lot load a new style"));
        msgBox.setInformativeText(tr("No suitable .css file selected. Please select a valid .css file."));
        msgBox.setStandardButtons(QMessageBox::Ok);
        msgBox.setDefaultButton(QMessageBox::Ok);
        msgBox.exec();
        return;
    }

pixhawk's avatar
pixhawk committed
1179
    // Load style sheet
1180
    QFile* styleSheet = new QFile(fileName);
1181 1182 1183 1184
    if (!styleSheet->exists())
    {
        styleSheet = new QFile(":/images/style-mission.css");
    }
1185 1186
    if (styleSheet->open(QIODevice::ReadOnly | QIODevice::Text))
    {
1187 1188
        QString style = QString(styleSheet->readAll());
        style.replace("ICONDIR", QCoreApplication::applicationDirPath()+ "/images/");
pixhawk's avatar
pixhawk committed
1189
        qApp->setStyleSheet(style);
1190 1191 1192
    }
    else
    {
1193 1194 1195 1196 1197 1198 1199
        QMessageBox msgBox;
        msgBox.setIcon(QMessageBox::Information);
        msgBox.setText(tr("QGroundControl did lot load a new style"));
        msgBox.setInformativeText(tr("Stylesheet file %1 was not readable").arg(fileName));
        msgBox.setStandardButtons(QMessageBox::Ok);
        msgBox.setDefaultButton(QMessageBox::Ok);
        msgBox.exec();
pixhawk's avatar
pixhawk committed
1200
    }
1201
    delete styleSheet;
pixhawk's avatar
pixhawk committed
1202 1203
}

1204 1205 1206 1207 1208 1209
/**
 * 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
1210
void MainWindow::showStatusMessage(const QString& status, int timeout)
pixhawk's avatar
pixhawk committed
1211
{
lm's avatar
lm committed
1212
    statusBar()->showMessage(status, timeout);
pixhawk's avatar
pixhawk committed
1213 1214
}

1215 1216 1217 1218 1219 1220
/**
 * 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
 */
1221
void MainWindow::showStatusMessage(const QString& status)
pixhawk's avatar
pixhawk committed
1222
{
lm's avatar
lm committed
1223
    statusBar()->showMessage(status, 20000);
1224 1225 1226 1227
}

void MainWindow::showCriticalMessage(const QString& title, const QString& message)
{
1228
    QMessageBox msgBox(this);
1229 1230 1231 1232 1233 1234
    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
1235 1236
}

lm's avatar
lm committed
1237 1238
void MainWindow::showInfoMessage(const QString& title, const QString& message)
{
1239
    QMessageBox msgBox(this);
lm's avatar
lm committed
1240 1241 1242 1243 1244 1245 1246 1247
    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
1248 1249 1250 1251
/**
* @brief Create all actions associated to the main window
*
**/
1252
void MainWindow::connectCommonActions()
pixhawk's avatar
pixhawk committed
1253
{
1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283
    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
1284 1285 1286 1287 1288
    // 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*)));
1289
    connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)), this, SLOT(setActiveUAS(UASInterface*)));
pixhawk's avatar
pixhawk committed
1290

1291
    // Unmanned System controls
pixhawk's avatar
pixhawk committed
1292 1293 1294 1295
    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()));
1296
    connect(ui.actionShutdownMAV, SIGNAL(triggered()), UASManager::instance(), SLOT(shutdownActiveUAS()));
pixhawk's avatar
pixhawk committed
1297 1298
    connect(ui.actionConfiguration, SIGNAL(triggered()), UASManager::instance(), SLOT(configureActiveUAS()));

1299
    // Views actions
1300
    connect(ui.actionPilotsView, SIGNAL(triggered()), this, SLOT(loadPilotView()));
1301
    connect(ui.actionEngineersView, SIGNAL(triggered()), this, SLOT(loadEngineerView()));
1302
    connect(ui.actionOperatorsView, SIGNAL(triggered()), this, SLOT(loadOperatorView()));
1303
    connect(ui.actionUnconnectedView, SIGNAL(triggered()), this, SLOT(loadUnconnectedView()));
1304

1305 1306
    connect(ui.actionMavlinkView, SIGNAL(triggered()), this, SLOT(loadMAVLinkView()));
    connect(ui.actionReloadStyle, SIGNAL(triggered()), this, SLOT(reloadStylesheet()));
1307

1308
    // Help Actions
1309
    connect(ui.actionOnline_Documentation, SIGNAL(triggered()), this, SLOT(showHelp()));
1310
    connect(ui.actionDeveloper_Credits, SIGNAL(triggered()), this, SLOT(showCredits()));
1311
    connect(ui.actionProject_Roadmap_2, SIGNAL(triggered()), this, SLOT(showRoadMap()));
1312 1313 1314

    // Custom widget actions
    connect(ui.actionNewCustomWidget, SIGNAL(triggered()), this, SLOT(createCustomWidget()));
1315 1316 1317 1318

    // Audio output
    ui.actionMuteAudioOutput->setChecked(GAudioOutput::instance()->isMuted());
    connect(ui.actionMuteAudioOutput, SIGNAL(triggered(bool)), GAudioOutput::instance(), SLOT(mute(bool)));
1319 1320 1321 1322 1323 1324 1325 1326 1327

    // 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);
    // Joystick configuration
    connect(ui.actionJoystickSettings, SIGNAL(triggered()), this, SLOT(configure()));
1328 1329 1330 1331 1332 1333 1334 1335 1336 1337
}

void MainWindow::connectPxActions()
{


}

void MainWindow::connectSlugsActions()
{
1338

pixhawk's avatar
pixhawk committed
1339 1340
}

1341 1342
void MainWindow::showHelp()
{
1343
    if(!QDesktopServices::openUrl(QUrl("http://qgroundcontrol.org/users/")))
1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356
    {
        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()
{
1357
    if(!QDesktopServices::openUrl(QUrl("http://qgroundcontrol.org/credits/")))
1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370
    {
        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()
{
1371
    if(!QDesktopServices::openUrl(QUrl("http://qgroundcontrol.org/roadmap/")))
1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382
    {
        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
1383
void MainWindow::configure()
pixhawk's avatar
pixhawk committed
1384
{
1385 1386 1387 1388 1389 1390 1391 1392 1393
    if (!joystickWidget)
    {
        if (!joystick->isRunning())
        {
            joystick->start();
        }
        joystickWidget = new JoystickWidget(joystick);
    }
    joystickWidget->show();
pixhawk's avatar
pixhawk committed
1394 1395
}

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

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

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

1407 1408 1409 1410 1411 1412 1413 1414
    foreach (QAction* act, actions)
    {
        if (act->data().toInt() == LinkManager::instance()->getLinks().indexOf(link))
        {
            act->trigger();
            break;
        }
    }
pixhawk's avatar
pixhawk committed
1415 1416
}

pixhawk's avatar
pixhawk committed
1417 1418
void MainWindow::addLink(LinkInterface *link)
{
1419
    LinkManager::instance()->add(link);
1420
    LinkManager::instance()->addProtocol(link, mavlink);
1421

pixhawk's avatar
pixhawk committed
1422 1423 1424
    CommConfigurationWindow* commWidget = new CommConfigurationWindow(link, mavlink, this);
    ui.menuNetwork->addAction(commWidget->getAction());

1425 1426 1427
    // Error handling
    connect(link, SIGNAL(communicationError(QString,QString)), this, SLOT(showCriticalMessage(QString,QString)), Qt::QueuedConnection);

1428 1429
    //qDebug() << "ADDING LINK:" << link->getName() << "ACTION IS: " << commWidget->getAction();

pixhawk's avatar
pixhawk committed
1430 1431 1432 1433
    // Special case for simulationlink
    MAVLinkSimulationLink* sim = dynamic_cast<MAVLinkSimulationLink*>(link);
    if (sim)
    {
1434
        //connect(sim, SIGNAL(valueChanged(int,QString,double,quint64)), linechart, SLOT(appendData(int,QString,double,quint64)));
pixhawk's avatar
pixhawk committed
1435 1436 1437 1438
        connect(ui.actionSimulate, SIGNAL(triggered(bool)), sim, SLOT(connectLink(bool)));
    }
}

1439 1440 1441 1442 1443 1444 1445
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);
}

1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457
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
1458
void MainWindow::UASCreated(UASInterface* uas)
pixhawk's avatar
pixhawk committed
1459
{
1460

pixhawk's avatar
pixhawk committed
1461 1462
    // Connect the UAS to the full user interface

1463 1464
    if (uas != NULL)
    {
1465 1466 1467 1468
        // Set default settings
        setDefaultSettingsForAp();

        // The pilot, operator and engineer views were not available on startup, enable them now
1469
        ui.actionPilotsView->setEnabled(true);
1470 1471
        ui.actionOperatorsView->setEnabled(true);
        ui.actionEngineersView->setEnabled(true);
1472 1473 1474 1475 1476 1477
        // 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);
1478

1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505
        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;
        }

1506 1507 1508
        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()));
1509
        connect(uas, SIGNAL(systemSpecsChanged(int)), this, SLOT(UASSpecsChanged(int)));
1510 1511

        ui.menuConnected_Systems->addAction(uasAction);
1512 1513

        // FIXME Should be not inside the mainwindow
1514 1515
        if (debugConsoleDockWidget)
        {
pixhawk's avatar
pixhawk committed
1516 1517 1518 1519 1520 1521
            DebugConsole *debugConsole = dynamic_cast<DebugConsole*>(debugConsoleDockWidget->widget());
            if (debugConsole)
            {
                connect(uas, SIGNAL(textMessageReceived(int,int,int,QString)),
                        debugConsole, SLOT(receiveTextMessage(int,int,int,QString)));
            }
1522
        }
1523 1524

        // Health / System status indicator
1525 1526
        if (infoDockWidget)
        {
pixhawk's avatar
pixhawk committed
1527 1528 1529 1530 1531
            UASInfoWidget *infoWidget = dynamic_cast<UASInfoWidget*>(infoDockWidget->widget());
            if (infoWidget)
            {
                infoWidget->addUAS(uas);
            }
1532
        }
1533 1534

        // UAS List
1535 1536
        if (listDockWidget)
        {
pixhawk's avatar
pixhawk committed
1537 1538 1539 1540 1541
            UASListWidget *listWidget = dynamic_cast<UASListWidget*>(listDockWidget->widget());
            if (listWidget)
            {
                listWidget->addUAS(uas);
            }
1542
        }
1543

1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571
        switch (uas->getAutopilotType())
        {
        case (MAV_AUTOPILOT_SLUGS):
            {
                // Build Slugs Widgets
                buildSlugsWidgets();

                // Connect Slugs Widgets
                connectSlugsWidgets();

                // Arrange Slugs Centerstack
                arrangeSlugsCenterStack();

                // Connect Slugs Actions
                connectSlugsActions();

                // FIXME: This type checking might be redundant
                //            if (slugsDataWidget) {
                //              SlugsDataSensorView* dataWidget = dynamic_cast<SlugsDataSensorView*>(slugsDataWidget->widget());
                //              if (dataWidget) {
                //                SlugsMAV* mav2 = dynamic_cast<SlugsMAV*>(uas);
                //                if (mav2) {
                (dynamic_cast<SlugsDataSensorView*>(slugsDataWidget->widget()))->addUAS(uas);
                //                  //loadSlugsView();
                //                  loadGlobalOperatorView();
                //                }
                //              }
                //            }
1572

1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598
            }
            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
1599
        if (UASManager::instance()->getUASList().size() == 1)
1600
        {
1601
            //qDebug() << "UPDATING THE VIEW SINCE THIS IS THE FIRST CONNECTED SYSTEM";
1602 1603

            // Load last view if setting is present
1604
            if (settings.contains("CURRENT_VIEW_WITH_UAS_CONNECTED"))
1605
            {
1606
                clearView();
1607
                int view = settings.value("CURRENT_VIEW_WITH_UAS_CONNECTED").toInt();
1608
                switch (view)
1609
                {
1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625
                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;
1626
                }
1627 1628 1629
            }
            else
            {
1630
                loadOperatorView();
1631
            }
1632
        }
1633

1634
    }
1635 1636

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

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

1642 1643 1644
/**
 * Clears the current view completely
 */
pixhawk's avatar
pixhawk committed
1645
void MainWindow::clearView()
1646
{
1647
    // Save current state
1648
    if (UASManager::instance()->getUASList().count() > 0) settings.setValue(getWindowStateKey(), saveState(QGC::applicationVersion()));
1649
    settings.setValue(getWindowGeometryKey(), saveGeometry());
1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660

    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)
        {
1661
            qDebug() << "TOOL:" << chKey << "IS:" << temp->isChecked();
1662 1663 1664 1665
            settings.setValue(chKey,temp->isChecked());
        }
        else
        {
1666
            qDebug() << "TOOL:" << chKey << "IS DEFAULT AND UNCHECKED";
1667 1668 1669 1670
            settings.setValue(chKey,false);
        }
    }

1671
    changingViewsFlag = true;
1672 1673
    // Remove all dock widgets from main window
    QObjectList childList( this->children() );
pixhawk's avatar
pixhawk committed
1674

1675 1676 1677
    QObjectList::iterator i;
    QDockWidget* dockWidget;
    for (i = childList.begin(); i != childList.end(); ++i)
pixhawk's avatar
pixhawk committed
1678
    {
1679 1680
        dockWidget = dynamic_cast<QDockWidget*>(*i);
        if (dockWidget)
pixhawk's avatar
pixhawk committed
1681
        {
1682
            // Remove dock widget from main window
1683
            removeDockWidget(dockWidget);
1684
            dockWidget->hide();
1685
            //dockWidget->setVisible(false);
pixhawk's avatar
pixhawk committed
1686 1687
        }
    }
1688
    changingViewsFlag = false;
pixhawk's avatar
pixhawk committed
1689 1690
}

1691
void MainWindow::loadEngineerView()
lm's avatar
lm committed
1692
{
1693 1694
    if (currentView != VIEW_ENGINEER)
    {
1695 1696 1697 1698
        clearView();
        currentView = VIEW_ENGINEER;
        ui.actionEngineersView->setChecked(true);
        presentView();
1699
    }
lm's avatar
lm committed
1700 1701
}

1702
void MainWindow::loadOperatorView()
lm's avatar
lm committed
1703
{
1704 1705
    if (currentView != VIEW_OPERATOR)
    {
1706 1707 1708 1709 1710 1711
        clearView();
        currentView = VIEW_OPERATOR;
        ui.actionOperatorsView->setChecked(true);
        presentView();
    }
}
lm's avatar
lm committed
1712

1713 1714 1715 1716 1717 1718 1719 1720
void MainWindow::loadUnconnectedView()
{
    if (currentView != VIEW_UNCONNECTED)
    {
        clearView();
        currentView = VIEW_UNCONNECTED;
        ui.actionUnconnectedView->setChecked(true);
        presentView();
1721
    }
lm's avatar
lm committed
1722 1723
}

1724
void MainWindow::loadPilotView()
1725
{
1726 1727
    if (currentView != VIEW_PILOT)
    {
1728 1729 1730 1731
        clearView();
        currentView = VIEW_PILOT;
        ui.actionPilotsView->setChecked(true);
        presentView();
1732
    }
1733 1734
}

1735
void MainWindow::loadMAVLinkView()
1736
{
1737 1738
    if (currentView != VIEW_MAVLINK)
    {
1739 1740 1741 1742
        clearView();
        currentView = VIEW_MAVLINK;
        ui.actionMavlinkView->setChecked(true);
        presentView();
1743
    }
1744 1745
}

lm's avatar
lm committed
1746 1747
void MainWindow::presentView()
{
1748
    // LINE CHART
1749
    showTheCentralWidget(CENTRAL_LINECHART, currentView);
1750

1751 1752
    // MAP
    showTheCentralWidget(CENTRAL_MAP, currentView);
pixhawk's avatar
pixhawk committed
1753

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

1757 1758
    // HEAD UP DISPLAY
    showTheCentralWidget(CENTRAL_HUD, currentView);
pixhawk's avatar
pixhawk committed
1759 1760 1761 1762 1763 1764 1765 1766 1767 1768

    // GOOGLE EARTH
    showTheCentralWidget(CENTRAL_GOOGLE_EARTH, currentView);

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

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

1769 1770 1771
    // DATA PLOT
    showTheCentralWidget(CENTRAL_DATA_PLOT, currentView);

pixhawk's avatar
pixhawk committed
1772

1773
    // Show docked widgets based on current view and autopilot type
1774

1775 1776
    // UAS CONTROL
    showTheWidget(MENU_UAS_CONTROL, currentView);
1777

1778 1779
    // UAS LIST
    showTheWidget(MENU_UAS_LIST, currentView);
1780

1781 1782
    // WAYPOINT LIST
    showTheWidget(MENU_WAYPOINTS, currentView);
pixhawk's avatar
pixhawk committed
1783

1784 1785
    // UAS STATUS
    showTheWidget(MENU_STATUS, currentView);
1786

1787 1788
    // DETECTION
    showTheWidget(MENU_DETECTION, currentView);
1789

1790 1791
    // DEBUG CONSOLE
    showTheWidget(MENU_DEBUG_CONSOLE, currentView);
1792

1793 1794
    // ONBOARD PARAMETERS
    showTheWidget(MENU_PARAMETERS, currentView);
1795

1796 1797
    // WATCHDOG
    showTheWidget(MENU_WATCHDOG, currentView);
1798

1799 1800 1801 1802 1803
    // HUD
    showTheWidget(MENU_HUD, currentView);
    if (headUpDockWidget)
    {
        HUD* tmpHud = dynamic_cast<HUD*>( headUpDockWidget->widget() );
1804 1805 1806 1807
        if (tmpHud)
        {
            if (settings.value(buildMenuKey (SUB_SECTION_CHECKED,MENU_HUD,currentView)).toBool())
            {
1808
                addDockWidget(static_cast <Qt::DockWidgetArea>(settings.value(buildMenuKey (SUB_SECTION_LOCATION,MENU_HUD, currentView)).toInt()),
1809
                        headUpDockWidget);
1810
                headUpDockWidget->show();
1811 1812 1813
            }
            else
            {
1814 1815
                headUpDockWidget->hide();
            }
1816
        }
1817
    }
1818

1819

1820 1821
    // RC View
    showTheWidget(MENU_RC_VIEW, currentView);
1822

1823 1824
    // SLUGS DATA
    showTheWidget(MENU_SLUGS_DATA, currentView);
1825

1826 1827
    // SLUGS PID
    showTheWidget(MENU_SLUGS_PID, currentView);
1828

1829 1830
    // SLUGS HIL
    showTheWidget(MENU_SLUGS_HIL, currentView);
1831

1832 1833
    // SLUGS CAMERA
    showTheWidget(MENU_SLUGS_CAMERA, currentView);
1834

1835 1836
    // HORIZONTAL SITUATION INDICATOR
    showTheWidget(MENU_HSI, currentView);
1837

1838 1839 1840 1841 1842
    // HEAD DOWN 1
    showTheWidget(MENU_HDD_1, currentView);

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

1844 1845 1846
    // MAVLINK LOG PLAYER
    showTheWidget(MENU_MAVLINK_LOG_PLAYER, currentView);

1847 1848 1849 1850 1851 1852
    // VIDEO 1
    showTheWidget(MENU_VIDEO_STREAM_1, currentView);

    // VIDEO 2
    showTheWidget(MENU_VIDEO_STREAM_2, currentView);

1853
    this->show();
1854

1855
    // Restore window state
1856 1857 1858
    if (UASManager::instance()->getUASList().count() > 0)
    {
        // Restore the mainwindow size
1859 1860 1861 1862
        if (settings.contains(getWindowGeometryKey()))
        {
            restoreGeometry(settings.value(getWindowGeometryKey()).toByteArray());
        }
1863 1864 1865 1866 1867 1868 1869

        // Restore the widget positions and size
        if (settings.contains(getWindowStateKey()))
        {
            restoreState(settings.value(getWindowStateKey()).toByteArray(), QGC::applicationVersion());
        }
    }
1870
}
1871

1872 1873 1874 1875
void MainWindow::showTheCentralWidget (TOOLS_WIDGET_NAMES centralWidget, VIEW_SECTIONS view)
{
    bool tempVisible;
    QWidget* tempWidget = dockWidgets[centralWidget];
1876

1877 1878
    tempVisible =  settings.value(buildMenuKey(SUB_SECTION_CHECKED,centralWidget,view), false).toBool();
    qDebug() << buildMenuKey (SUB_SECTION_CHECKED,centralWidget,view) << tempVisible;
1879
    if (toolsMenuActions[centralWidget])
1880
    {
1881
        qDebug() << "SETTING TO:" << tempVisible;
1882
        toolsMenuActions[centralWidget]->setChecked(tempVisible);
1883
    }
1884

1885
    if (centerStack && tempWidget && tempVisible)
1886
    {
1887
        qDebug() << "ACTIVATING MAIN WIDGET";
1888
        centerStack->setCurrentWidget(tempWidget);
1889
    }
1890 1891
}

1892 1893
void MainWindow::loadDataView(QString fileName)
{
1894
    clearView();
1895 1896 1897 1898 1899

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

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

1904
    presentView();
1905

1906 1907
    // Plot is now selected, now load data from file
    if (dataplotWidget)
1908
    {
1909
        dataplotWidget->loadFile(fileName);
1910
        }
1911 1912 1913 1914 1915 1916 1917
//        QStackedWidget *centerStack = dynamic_cast<QStackedWidget*>(centralWidget());
//        if (centerStack)
//        {
//            centerStack->setCurrentWidget(dataplotWidget);
//            dataplotWidget->loadFile(fileName);
//        }
//    }
1918 1919 1920
}