MainWindow.cc 67.1 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
#include "QGCMapTool.h"
33

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

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

pixhawk's avatar
pixhawk committed
42

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

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

90
    setDefaultSettingsForAp();
91

92 93
    settings.sync();

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

97 98
    setVisible(false);

99
    buildCommonWidgets();
100

101
    connectCommonWidgets();
102

103
    arrangeCommonCenterStack();
104 105

    configureWindowName();
pixhawk's avatar
pixhawk committed
106

107
    loadStyle(currentStyle);
108

109
    // Create actions
110
    connectCommonActions();
111

112 113 114
    // Set dock options
    setDockOptions(AnimatedDocks | AllowTabbedDocks | AllowNestedDocks);

115
    // Load mavlink view as default widget set
116
    //loadMAVLinkView();
117

lm's avatar
lm committed
118 119
    statusBar()->setSizeGripEnabled(true);

120
    // Restore the window position and size
121
    if (settings.contains(getWindowGeometryKey())) {
122
        // Restore the window geometry
123
        restoreGeometry(settings.value(getWindowGeometryKey()).toByteArray());
124
    } else {
125 126 127
        // Adjust the size
        adjustSize();
    }
pixhawk's avatar
pixhawk committed
128

129 130
    // Populate link menu
    QList<LinkInterface*> links = LinkManager::instance()->getLinks();
131
    foreach(LinkInterface* link, links) {
132 133
        this->addLink(link);
    }
134

135 136
    connect(LinkManager::instance(), SIGNAL(newLink(LinkInterface*)), this, SLOT(addLink(LinkInterface*)));

137
    // Connect user interface devices
138
    if (!joystick) {
139 140 141
        joystick = new JoystickInput();
    }

lm's avatar
lm committed
142 143
    // Enable and update view
    presentView();
144 145

    // Connect link
146
    if (autoReconnect) {
147 148 149 150 151 152
        SerialLink* link = new SerialLink();
        // Add to registry
        LinkManager::instance()->add(link);
        LinkManager::instance()->addProtocol(link, mavlink);
        link->connect();
    }
153

154 155 156
    // Set low power mode
    enableLowPowerMode(lowPowerMode);

157 158
    // Initialize window state
    windowStateVal = windowState();
pixhawk's avatar
pixhawk committed
159 160
}

pixhawk's avatar
pixhawk committed
161
MainWindow::~MainWindow()
pixhawk's avatar
pixhawk committed
162
{
163 164 165
    // Store settings
    storeSettings();

166
    delete mavlink;
167
    delete joystick;
lm's avatar
lm committed
168

169 170 171 172 173 174
    // Get and delete all dockwidgets and contained
    // widgets
    QObjectList childList( this->children() );

    QObjectList::iterator i;
    QDockWidget* dockWidget;
175
    for (i = childList.begin(); i != childList.end(); ++i) {
176
        dockWidget = dynamic_cast<QDockWidget*>(*i);
177
        if (dockWidget) {
178 179 180 181 182 183
            // Remove dock widget from main window
            removeDockWidget(dockWidget);
            delete dockWidget->widget();
            delete dockWidget;
        }
    }
pixhawk's avatar
pixhawk committed
184 185
}

186 187 188 189 190 191 192 193 194
/**
 * 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);
195
    if (!settings.contains(centralKey)) {
196
        settings.setValue(centralKey,true);
197 198 199 200 201

        // 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);
202 203 204 205
    }

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

        // ENABLE UAS LIST
        settings.setValue(buildMenuKey(SUB_SECTION_CHECKED,MainWindow::MENU_UAS_LIST,VIEW_OPERATOR), true);
211 212
        // ENABLE HUD TOOL WIDGET
        settings.setValue(buildMenuKey(SUB_SECTION_CHECKED,MainWindow::MENU_HUD,VIEW_OPERATOR), true);
213 214
        // ENABLE WAYPOINTS
        settings.setValue(buildMenuKey(SUB_SECTION_CHECKED,MainWindow::MENU_WAYPOINTS,VIEW_OPERATOR), true);
215 216 217 218
    }

    // ENGINEER VIEW DEFAULT
    centralKey = buildMenuKey(SUB_SECTION_CHECKED, CENTRAL_LINECHART, VIEW_ENGINEER);
219
    if (!settings.contains(centralKey)) {
220
        settings.setValue(centralKey,true);
221 222
        // Enable Parameter widget
        settings.setValue(buildMenuKey(SUB_SECTION_CHECKED,MainWindow::MENU_PARAMETERS,VIEW_ENGINEER), true);
223 224 225 226
    }

    // MAVLINK VIEW DEFAULT
    centralKey = buildMenuKey(SUB_SECTION_CHECKED, CENTRAL_PROTOCOL, VIEW_MAVLINK);
227
    if (!settings.contains(centralKey)) {
228 229 230 231 232
        settings.setValue(centralKey,true);
    }

    // PILOT VIEW DEFAULT
    centralKey = buildMenuKey(SUB_SECTION_CHECKED, CENTRAL_HUD, VIEW_PILOT);
233
    if (!settings.contains(centralKey)) {
234
        settings.setValue(centralKey,true);
235 236
        // Enable Flight display
        settings.setValue(buildMenuKey(SUB_SECTION_CHECKED,MainWindow::MENU_HDD_1,VIEW_PILOT), true);
237 238 239
    }
}

lm's avatar
lm committed
240 241 242
void MainWindow::resizeEvent(QResizeEvent * event)
{
    Q_UNUSED(event);
243
    if (height() < 800) {
lm's avatar
lm committed
244
        ui.statusBar->setVisible(false);
245
    } else {
lm's avatar
lm committed
246 247 248 249
        ui.statusBar->setVisible(true);
    }
}

250 251
QString MainWindow::getWindowStateKey()
{
252
    return QString::number(currentView)+"_windowstate";
253 254 255 256
}

QString MainWindow::getWindowGeometryKey()
{
257 258
    //return QString::number(currentView)+"_geometry";
    return "_geometry";
259 260
}

lm's avatar
lm committed
261 262 263
void MainWindow::buildCustomWidget()
{
    // Show custom widgets only if UAS is connected
264
    if (UASManager::instance()->getActiveUAS() != NULL) {
lm's avatar
lm committed
265 266 267 268 269 270
        // Enable custom widgets
        ui.actionNewCustomWidget->setEnabled(true);

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

271
        if (widgets.size() > 0) {
lm's avatar
lm committed
272 273 274
            ui.menuTools->addSeparator();
        }

275
        for(int i = 0; i < widgets.size(); ++i) {
lm's avatar
lm committed
276
            // Check if this widget already has a parent, do not create it in this case
277 278
            QGCToolWidget* tool = widgets.at(i);
            QDockWidget* dock = dynamic_cast<QDockWidget*>(tool->parentWidget());
279
            if (!dock) {
280 281 282 283
                QDockWidget* dock = new QDockWidget(tool->windowTitle(), this);
                dock->setObjectName(tool->objectName()+"_DOCK");
                dock->setWidget(tool);
                connect(tool, SIGNAL(destroyed()), dock, SLOT(deleteLater()));
lm's avatar
lm committed
284
                QAction* showAction = new QAction(widgets.at(i)->windowTitle(), this);
285
                showAction->setCheckable(true);
lm's avatar
lm committed
286 287 288 289
                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);
290 291 292 293 294 295 296 297

                // Load visibility for view (default is off)
                dock->setVisible(tool->isVisible(currentView));

                // Load dock widget location (default is bottom)
                Qt::DockWidgetArea location = static_cast <Qt::DockWidgetArea>(tool->getDockWidgetArea(currentView));

                addDockWidget(location, dock);
lm's avatar
lm committed
298 299 300 301 302
            }
        }
    }
}

303 304 305 306
void MainWindow::buildCommonWidgets()
{
    //TODO:  move protocol outside UI
    mavlink     = new MAVLinkProtocol();
307
    connect(mavlink, SIGNAL(protocolStatusMessage(QString,QString)), this, SLOT(showCriticalMessage(QString,QString)), Qt::QueuedConnection);
308 309

    // Dock widgets
310
    if (!controlDockWidget) {
311
        controlDockWidget = new QDockWidget(tr("Control"), this);
312
        controlDockWidget->setObjectName("UNMANNED_SYSTEM_CONTROL_DOCKWIDGET");
313
        controlDockWidget->setWidget( new UASControlWidget(this) );
314
        addToToolsMenu (controlDockWidget, tr("Control"), SLOT(showToolWidget(bool)), MENU_UAS_CONTROL, Qt::LeftDockWidgetArea);
315
    }
316

317
    if (!listDockWidget) {
318 319
        listDockWidget = new QDockWidget(tr("Unmanned Systems"), this);
        listDockWidget->setWidget( new UASListWidget(this) );
320
        listDockWidget->setObjectName("UNMANNED_SYSTEMS_LIST_DOCKWIDGET");
321
        addToToolsMenu (listDockWidget, tr("Unmanned Systems"), SLOT(showToolWidget(bool)), MENU_UAS_LIST, Qt::RightDockWidgetArea);
322
    }
323

324
    if (!waypointsDockWidget) {
325
        waypointsDockWidget = new QDockWidget(tr("Mission Plan"), this);
326
        waypointsDockWidget->setWidget( new QGCWaypointListMulti(this) );
327
        waypointsDockWidget->setObjectName("WAYPOINT_LIST_DOCKWIDGET");
328
        addToToolsMenu (waypointsDockWidget, tr("Mission Plan"), SLOT(showToolWidget(bool)), MENU_WAYPOINTS, Qt::BottomDockWidgetArea);
329
    }
330

331
    if (!infoDockWidget) {
332 333
        infoDockWidget = new QDockWidget(tr("Status Details"), this);
        infoDockWidget->setWidget( new UASInfoWidget(this) );
pixhawk's avatar
pixhawk committed
334
        infoDockWidget->setObjectName("UAS_STATUS_DETAILS_DOCKWIDGET");
335
        addToToolsMenu (infoDockWidget, tr("Status Details"), SLOT(showToolWidget(bool)), MENU_STATUS, Qt::RightDockWidgetArea);
336
    }
337

338
    if (!debugConsoleDockWidget) {
339 340
        debugConsoleDockWidget = new QDockWidget(tr("Communication Console"), this);
        debugConsoleDockWidget->setWidget( new DebugConsole(this) );
341
        debugConsoleDockWidget->setObjectName("COMMUNICATION_DEBUG_CONSOLE_DOCKWIDGET");
342
        addToToolsMenu (debugConsoleDockWidget, tr("Communication Console"), SLOT(showToolWidget(bool)), MENU_DEBUG_CONSOLE, Qt::BottomDockWidgetArea);
343
    }
344

345
    if (!logPlayerDockWidget) {
346 347 348
        logPlayerDockWidget = new QDockWidget(tr("MAVLink Log Player"), this);
        logPlayerDockWidget->setWidget( new QGCMAVLinkLogPlayer(mavlink, this) );
        logPlayerDockWidget->setObjectName("MAVLINK_LOG_PLAYER_DOCKWIDGET");
349
        addToToolsMenu(logPlayerDockWidget, tr("MAVLink Log Replay"), SLOT(showToolWidget(bool)), MENU_MAVLINK_LOG_PLAYER, Qt::RightDockWidgetArea);
350 351
    }

352
    // Center widgets
353 354
    if (!mapWidget)
    {
355
        mapWidget = new QGCMapTool(this);
356 357
        addToCentralWidgetsMenu (mapWidget, "Maps", SLOT(showCentralWidget()),CENTRAL_MAP);
    }
358

359
    if (!protocolWidget) {
360 361 362
        protocolWidget    = new XMLCommProtocolWidget(this);
        addToCentralWidgetsMenu (protocolWidget, "Mavlink Generator", SLOT(showCentralWidget()),CENTRAL_PROTOCOL);
    }
lm's avatar
lm committed
363

364
    if (!dataplotWidget) {
lm's avatar
lm committed
365
        dataplotWidget    = new QGCDataPlot2D(this);
366
        addToCentralWidgetsMenu (dataplotWidget, "Logfile Plot", SLOT(showCentralWidget()),CENTRAL_DATA_PLOT);
lm's avatar
lm committed
367
    }
368

369

370
}
371

372

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

pixhawk's avatar
pixhawk committed
381 382 383
    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");
384
    acceptList->append("0,airspeed,m/s,30");
385 386
    acceptList->append("0,groundspeed,m/s,30");
    acceptList->append("0,climbrate,m/s,30");
387
    acceptList->append("0,throttle,%,100");
388

pixhawk's avatar
pixhawk committed
389 390
    //FIXME: memory of acceptList2 will never be freed again
    QStringList* acceptList2 = new QStringList();
391 392 393 394 395 396 397 398
    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
399
    acceptList2->append("0,abs pressure,hPa,65500");
400 401 402
    //acceptList2->append("-2048,accel. x,raw,2048,s");
    //acceptList2->append("-2048,accel. y,raw,2048,s");
    //acceptList2->append("-2048,accel. z,raw,2048,s");
403

404
    if (!linechartWidget) {
405 406
        // Center widgets
        linechartWidget   = new Linecharts(this);
407
        addToCentralWidgetsMenu(linechartWidget, tr("Realtime Plot"), SLOT(showCentralWidget()), CENTRAL_LINECHART);
408
    }
409 410


411
    if (!hudWidget) {
412
        hudWidget         = new HUD(320, 240, this);
413
        addToCentralWidgetsMenu(hudWidget, tr("Head Up Display"), SLOT(showCentralWidget()), CENTRAL_HUD);
414
    }
415

416
    if (!dataplotWidget) {
417
        dataplotWidget    = new QGCDataPlot2D(this);
418
        addToCentralWidgetsMenu(dataplotWidget, "Logfile Plot", SLOT(showCentralWidget()), CENTRAL_DATA_PLOT);
419
    }
420

421
#ifdef QGC_OSG_ENABLED
422
    if (!_3DWidget) {
423
        _3DWidget         = Q3DWidgetFactory::get("PIXHAWK");
424
        addToCentralWidgetsMenu(_3DWidget, tr("Local 3D"), SLOT(showCentralWidget()), CENTRAL_3D_LOCAL);
425
    }
426
#endif
427

428
#ifdef QGC_OSGEARTH_ENABLED
429
    if (!_3DMapWidget) {
430
        _3DMapWidget = Q3DWidgetFactory::get("MAP3D");
431
        addToCentralWidgetsMenu(_3DMapWidget, tr("OSG Earth 3D"), SLOT(showCentralWidget()), CENTRAL_OSGEARTH);
432
    }
433
#endif
lm's avatar
lm committed
434

435
#if (defined _MSC_VER) | (defined Q_OS_MAC)
436
    if (!gEarthWidget) {
437
        gEarthWidget = new QGCGoogleEarthView(this);
438
        addToCentralWidgetsMenu(gEarthWidget, tr("Google Earth"), SLOT(showCentralWidget()), CENTRAL_GOOGLE_EARTH);
439
    }
440

441
#endif
442

pixhawk's avatar
pixhawk committed
443
    // Dock widgets
444

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

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

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

466
    if (!hsiDockWidget) {
467 468
        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("Horizontal Situation"), SLOT(showToolWidget(bool)), MENU_HSI, Qt::BottomDockWidgetArea);
471
    }
472

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

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

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

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

501
    if (!video1DockWidget) {
pixhawk's avatar
pixhawk committed
502 503 504 505 506 507 508
        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");
509
        addToToolsMenu (video1DockWidget, tr("Video Stream 1"), SLOT(showToolWidget(bool)), MENU_VIDEO_STREAM_1, Qt::LeftDockWidgetArea);
pixhawk's avatar
pixhawk committed
510 511
    }

512
    if (!video2DockWidget) {
pixhawk's avatar
pixhawk committed
513 514 515 516 517 518 519
        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");
520
        addToToolsMenu (video2DockWidget, tr("Video Stream 2"), SLOT(showToolWidget(bool)), MENU_VIDEO_STREAM_2, Qt::LeftDockWidgetArea);
521
    }
522

pixhawk's avatar
pixhawk committed
523 524
    // Dialogue widgets
    //FIXME: free memory in destructor
525 526 527 528
}

void MainWindow::buildSlugsWidgets()
{
529
    if (!linechartWidget) {
530 531
        // Center widgets
        linechartWidget   = new Linecharts(this);
532
        addToCentralWidgetsMenu(linechartWidget, tr("Realtime Plot"), SLOT(showCentralWidget()), CENTRAL_LINECHART);
533
    }
534

535
    if (!headUpDockWidget) {
536 537 538
        // Dock widgets
        headUpDockWidget = new QDockWidget(tr("Control Indicator"), this);
        headUpDockWidget->setWidget( new HUD(320, 240, this));
pixhawk's avatar
pixhawk committed
539
        headUpDockWidget->setObjectName("HEAD_UP_DISPLAY_DOCK_WIDGET");
540
        addToToolsMenu (headUpDockWidget, tr("Head Up Display"), SLOT(showToolWidget(bool)), MENU_HUD, Qt::LeftDockWidgetArea);
541
    }
542

543
    if (!rcViewDockWidget) {
544 545
        rcViewDockWidget = new QDockWidget(tr("Radio Control"), this);
        rcViewDockWidget->setWidget( new QGCRemoteControlView(this) );
pixhawk's avatar
pixhawk committed
546
        rcViewDockWidget->setObjectName("RADIO_CONTROL_CHANNELS_DOCK_WIDGET");
547
        addToToolsMenu (rcViewDockWidget, tr("Radio Control"), SLOT(showToolWidget(bool)), MENU_RC_VIEW, Qt::BottomDockWidgetArea);
548
    }
549

550
#if (defined _MSC_VER) | (defined Q_OS_MAC)
551
    if (!gEarthWidget) {
552 553 554 555 556 557
        gEarthWidget = new QGCGoogleEarthView(this);
        addToCentralWidgetsMenu(gEarthWidget, tr("Google Earth"), SLOT(showCentralWidget()), CENTRAL_GOOGLE_EARTH);
    }

#endif

558
    if (!slugsDataWidget) {
559 560 561 562 563 564
        // 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);
    }
565

566

567
    if (!slugsHilSimWidget) {
568 569 570 571 572
        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);
    }
573

574 575
    if (!controlParameterWidget) {
        controlParameterWidget = new QDockWidget(tr("Control Parameters"), this);
576 577 578
        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);
579
    }
580

581
    if (!parametersDockWidget) {
582 583 584 585 586 587
        parametersDockWidget = new QDockWidget(tr("Calibration and Onboard Parameters"), this);
        parametersDockWidget->setWidget( new ParameterInterface(this) );
        parametersDockWidget->setObjectName("PARAMETER_INTERFACE_DOCKWIDGET");
        addToToolsMenu (parametersDockWidget, tr("Calibration and Parameters"), SLOT(showToolWidget(bool)), MENU_PARAMETERS, Qt::RightDockWidgetArea);
    }

588
    if (!slugsCamControlWidget) {
589 590 591 592 593
        slugsCamControlWidget = new QDockWidget(tr("Camera Control"), this);
        slugsCamControlWidget->setWidget(new SlugsPadCameraControl(this));
        slugsCamControlWidget->setObjectName("SLUGS_CAM_CONTROL_DOCK_WIDGET");
        addToToolsMenu (slugsCamControlWidget, tr("Camera Control"), SLOT(showToolWidget(bool)), MENU_SLUGS_CAMERA, Qt::BottomDockWidgetArea);
    }
594

595
}
596 597 598


void MainWindow::addToCentralWidgetsMenu ( QWidget* widget,
599 600 601
        const QString title,
        const char * slotName,
        TOOLS_WIDGET_NAMES centralWidget)
602
{
603
    QAction* tempAction;
604

605

606
// Not needed any more - separate menu now available
607

608 609 610 611 612 613 614
//    // 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);
//    }
615

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

618 619
    tempAction->setCheckable(true);
    tempAction->setData(centralWidget);
620

621 622 623
    // populate the Hashes
    toolsMenuActions[centralWidget] = tempAction;
    dockWidgets[centralWidget] = widget;
624

625
    QString chKey = buildMenuKey(SUB_SECTION_CHECKED, centralWidget, currentView);
626

627
    if (!settings.contains(chKey)) {
628 629
        settings.setValue(chKey,false);
        tempAction->setChecked(false);
630
    } else {
631 632
        tempAction->setChecked(settings.value(chKey).toBool());
    }
633

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


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

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

646 647
    int tool = senderAction->data().toInt();
    QString chKey;
648

649
    // check the current action
650

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

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

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

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

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

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

684 685
        presentView();
    }
686
}
687

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

701

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

710 711
    tempAction->setCheckable(true);
    tempAction->setData(tool);
712

713 714 715
    // populate the Hashes
    toolsMenuActions[tool] = tempAction;
    dockWidgets[tool] = widget;
716
    //qDebug() << widget;
717

718
    posKey = buildMenuKey (SUB_SECTION_LOCATION,tool, currentView);
719

720
    if (!settings.contains(posKey)) {
721 722
        settings.setValue(posKey,location);
        dockWidgetLocations[tool] = location;
723
    } else {
724
        dockWidgetLocations[tool] = static_cast <Qt::DockWidgetArea> (settings.value(posKey, Qt::RightDockWidgetArea).toInt());
725
    }
726

727
    chKey = buildMenuKey(SUB_SECTION_CHECKED,tool, currentView);
728

729
    if (!settings.contains(chKey)) {
730 731
        settings.setValue(chKey,false);
        tempAction->setChecked(false);
732
        widget->setVisible(false);
733
    } else {
734
        tempAction->setChecked(settings.value(chKey, false).toBool());
735
        widget->setVisible(settings.value(chKey, false).toBool());
736
    }
737

738
    // connect the action
739 740 741
    connect(tempAction,SIGNAL(toggled(bool)),this, slotName);

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

744 745
    //  connect(qobject_cast <QDockWidget *>(dockWidgets[tool]),
    //          SIGNAL(visibilityChanged(bool)), this, SLOT(updateVisibilitySettings(bool)));
746

747 748
    connect(qobject_cast <QDockWidget *>(dockWidgets[tool]),
            SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), this, SLOT(updateLocationSettings(Qt::DockWidgetArea)));
749 750
}

751
void MainWindow::showToolWidget(bool visible)
752
{
753
    if (!aboutToCloseFlag && !changingViewsFlag) {
754 755
        QAction* action = qobject_cast<QAction *>(sender());

756
        // Prevent this to fire if undocked
757
        if (action) {
758
            int tool = action->data().toInt();
759

760
            QDockWidget* dockWidget = qobject_cast<QDockWidget *> (dockWidgets[tool]);
761

762 763
            if (dockWidget && dockWidget->isVisible() != visible) {
                if (visible) {
764 765
                    addDockWidget(dockWidgetLocations[tool], dockWidget);
                    dockWidget->show();
766
                } else {
767 768
                    removeDockWidget(dockWidget);
                }
769 770

                QHashIterator<int, QWidget*> i(dockWidgets);
771
                while (i.hasNext()) {
772
                    i.next();
773
                    if ((static_cast <QDockWidget *>(dockWidgets[i.key()])) == dockWidget) {
774 775
                        QString chKey = buildMenuKey (SUB_SECTION_CHECKED,static_cast<TOOLS_WIDGET_NAMES>(i.key()), currentView);
                        settings.setValue(chKey,visible);
776
                        //qDebug() << "showToolWidget(): Set key" << chKey << "to" << visible;
777 778 779
                        break;
                    }
                }
780
            }
781
        }
782 783 784

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

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

787
        if (dockWidget) {
788 789 790
            // Get action
            int tool = dockWidgets.key(dockWidget);

791
            //qDebug() << "Updating widget setting" << tool << "to" << visible;
792 793 794 795 796 797 798

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

            QHashIterator<int, QWidget*> i(dockWidgets);
799
            while (i.hasNext()) {
800
                i.next();
801
                if ((static_cast <QDockWidget *>(dockWidgets[i.key()])) == dockWidget) {
802 803
                    QString chKey = buildMenuKey (SUB_SECTION_CHECKED,static_cast<TOOLS_WIDGET_NAMES>(i.key()), currentView);
                    settings.setValue(chKey,visible);
804
                    // qDebug() << "showToolWidget(): Set key" << chKey << "to" << visible;
805 806 807
                    break;
                }
            }
808
        }
809 810 811 812
    }
}


813 814 815 816 817
void MainWindow::showTheWidget (TOOLS_WIDGET_NAMES widget, VIEW_SECTIONS view)
{
    bool tempVisible;
    Qt::DockWidgetArea tempLocation;
    QDockWidget* tempWidget = static_cast <QDockWidget *>(dockWidgets[widget]);
818

819
    tempVisible =  settings.value(buildMenuKey(SUB_SECTION_CHECKED,widget,view), false).toBool();
820

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

823
    if (tempWidget) {
824 825
        toolsMenuActions[widget]->setChecked(tempVisible);
    }
826 827


828
    //qDebug() <<  buildMenuKey (SUB_SECTION_CHECKED,widget,view) << tempVisible;
829

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

832 833
    if (tempWidget != NULL) {
        if (tempVisible) {
834 835 836
            addDockWidget(tempLocation, tempWidget);
            tempWidget->show();
        }
837 838
    }
}
839

840 841 842 843 844
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;

845 846 847 848 849
//    apType = (UASManager::instance() && UASManager::instance()->silentGetActiveUAS())?
//             UASManager::instance()->getActiveUAS()->getAutopilotType():
//             -1;

    apType = 1;
850

851 852 853 854 855
    return (QString::number(apType) + "_" +
            QString::number(SECTION_MENU) + "_" +
            QString::number(view) + "_" +
            QString::number(tool) + "_" +
            QString::number(section) + "_" );
856 857
}

858 859
void MainWindow::closeEvent(QCloseEvent *event)
{
860
    storeSettings();
861
    aboutToCloseFlag = true;
862
    mavlink->storeSettings();
863
    UASManager::instance()->storeSettings();
864 865
    QMainWindow::closeEvent(event);
}
866

867 868
void MainWindow::showDockWidget (bool vis)
{
869
    if (!aboutToCloseFlag && !changingViewsFlag) {
870 871
        QDockWidget* temp = qobject_cast<QDockWidget *>(sender());

872
        if (temp) {
873
            QHashIterator<int, QWidget*> i(dockWidgets);
874
            while (i.hasNext()) {
875
                i.next();
876
                if ((static_cast <QDockWidget *>(dockWidgets[i.key()])) == temp) {
877 878 879 880 881 882 883 884 885
                    QString chKey = buildMenuKey (SUB_SECTION_CHECKED,static_cast<TOOLS_WIDGET_NAMES>(i.key()), currentView);
                    settings.setValue(chKey,vis);
                    toolsMenuActions[i.key()]->setChecked(vis);
                    break;
                }
            }
        }
    }
}
886

887 888
void MainWindow::updateVisibilitySettings (bool vis)
{
889
    if (!aboutToCloseFlag && !changingViewsFlag) {
890 891
        QDockWidget* temp = qobject_cast<QDockWidget *>(sender());

892
        if (temp) {
893
            QHashIterator<int, QWidget*> i(dockWidgets);
894
            while (i.hasNext()) {
895
                i.next();
896
                if ((static_cast <QDockWidget *>(dockWidgets[i.key()])) == temp) {
897 898
                    QString chKey = buildMenuKey (SUB_SECTION_CHECKED,static_cast<TOOLS_WIDGET_NAMES>(i.key()), currentView);
                    settings.setValue(chKey,vis);
899 900 901 902 903 904
                    toolsMenuActions[i.key()]->setChecked(vis);
                    break;
                }
            }
        }
    }
905 906
}

907 908 909
void MainWindow::updateLocationSettings (Qt::DockWidgetArea location)
{
    QDockWidget* temp = qobject_cast<QDockWidget *>(sender());
910

911
    QHashIterator<int, QWidget*> i(dockWidgets);
912
    while (i.hasNext()) {
913
        i.next();
914
        if ((static_cast <QDockWidget *>(dockWidgets[i.key()])) == temp) {
915 916 917 918 919
            QString posKey = buildMenuKey (SUB_SECTION_LOCATION,static_cast<TOOLS_WIDGET_NAMES>(i.key()), currentView);
            settings.setValue(posKey,location);
            break;
        }
    }
920 921
}

922

923 924 925
/**
 * Connect the signals and slots of the common window widgets
 */
926
void MainWindow::connectCommonWidgets()
927
{
928
    if (infoDockWidget && infoDockWidget->widget()) {
pixhawk's avatar
pixhawk committed
929 930 931
        connect(mavlink, SIGNAL(receiveLossChanged(int, float)),
                infoDockWidget->widget(), SLOT(updateSendLoss(int, float)));
    }
lm's avatar
lm committed
932 933 934 935 936
//    //TODO temporaly debug
//    if (slugsHilSimWidget && slugsHilSimWidget->widget()) {
//        connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)),
//                slugsHilSimWidget->widget(), SLOT(activeUasSet(UASInterface*)));
//    }
937
}
938

939 940
void MainWindow::createCustomWidget()
{
lm's avatar
lm committed
941 942
    QGCToolWidget* tool = new QGCToolWidget("Unnamed Tool", this);

943
    if (QGCToolWidget::instances()->size() < 2) {
lm's avatar
lm committed
944 945 946 947
        // This is the first widget
        ui.menuTools->addSeparator();
    }

948
    QDockWidget* dock = new QDockWidget("Unnamed Tool", this);
lm's avatar
lm committed
949
    connect(tool, SIGNAL(destroyed()), dock, SLOT(deleteLater()));
950
    dock->setWidget(tool);
951

lm's avatar
lm committed
952
    QAction* showAction = new QAction("Show Unnamed Tool", this);
953
    showAction->setCheckable(true);
lm's avatar
lm committed
954 955 956 957 958
    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);
959
    dock->setVisible(true);
960 961 962 963
}

void MainWindow::connectPxWidgets()
{
964
    // No special connections necessary at this point
965 966 967 968
}

void MainWindow::connectSlugsWidgets()
{
969
    if (slugsHilSimWidget && slugsHilSimWidget->widget()) {
970 971
        connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)),
                slugsHilSimWidget->widget(), SLOT(activeUasSet(UASInterface*)));
972 973
    }

974
    if (slugsDataWidget && slugsDataWidget->widget()) {
975 976
        connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)),
                slugsDataWidget->widget(), SLOT(setActiveUAS(UASInterface*)));
977 978
    }

979
    if (controlParameterWidget && controlParameterWidget->widget()) {
980 981 982
        connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)),
                controlParameterWidget->widget(), SLOT(activeUasSet(UASInterface*)));
    }
983

984 985
    if(controlDockWidget && controlParameterWidget) {
        connect(controlDockWidget->widget(), SIGNAL(changedMode(int)), controlParameterWidget->widget(), SLOT(changedMode(int)));
986
    }
987 988
}

989
void MainWindow::arrangeCommonCenterStack()
990
{
991
    centerStack = new QStackedWidget(this);
992
    centerStack->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
993

pixhawk's avatar
pixhawk committed
994
    if (!centerStack) return;
995

996
    if (mapWidget && (centerStack->indexOf(mapWidget) == -1)) centerStack->addWidget(mapWidget);
lm's avatar
lm committed
997
    if (dataplotWidget && (centerStack->indexOf(dataplotWidget) == -1)) centerStack->addWidget(dataplotWidget);
998
    if (protocolWidget && (centerStack->indexOf(protocolWidget) == -1)) centerStack->addWidget(protocolWidget);
999 1000 1001 1002 1003 1004 1005

    setCentralWidget(centerStack);
}

void MainWindow::arrangePxCenterStack()
{

1006 1007 1008 1009
    if (!centerStack) {
        qDebug() << "Center Stack not Created!";
        return;
    }
1010

1011 1012

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

1014
#ifdef QGC_OSG_ENABLED
1015
    if (_3DWidget && (centerStack->indexOf(_3DWidget) == -1)) centerStack->addWidget(_3DWidget);
1016
#endif
1017
#ifdef QGC_OSGEARTH_ENABLED
1018
    if (_3DMapWidget && (centerStack->indexOf(_3DMapWidget) == -1)) centerStack->addWidget(_3DMapWidget);
1019
#endif
1020
#if (defined _MSC_VER) | (defined Q_OS_MAC)
1021
    if (gEarthWidget && (centerStack->indexOf(gEarthWidget) == -1)) centerStack->addWidget(gEarthWidget);
1022
#endif
1023 1024
    if (hudWidget && (centerStack->indexOf(hudWidget) == -1)) centerStack->addWidget(hudWidget);
    if (dataplotWidget && (centerStack->indexOf(dataplotWidget) == -1)) centerStack->addWidget(dataplotWidget);
1025 1026 1027 1028 1029
}

void MainWindow::arrangeSlugsCenterStack()
{

1030 1031 1032 1033
    if (!centerStack) {
        qDebug() << "Center Stack not Created!";
        return;
    }
1034

1035 1036
    if (linechartWidget && (centerStack->indexOf(linechartWidget) == -1)) centerStack->addWidget(linechartWidget);
    if (hudWidget && (centerStack->indexOf(hudWidget) == -1)) centerStack->addWidget(hudWidget);
1037

1038 1039 1040 1041
#if (defined _MSC_VER) | (defined Q_OS_MAC)
    if (gEarthWidget && (centerStack->indexOf(gEarthWidget) == -1)) centerStack->addWidget(gEarthWidget);
#endif

1042 1043
}

1044 1045 1046 1047 1048 1049
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();
1050
    lowPowerMode = settings.value("LOW_POWER_MODE", lowPowerMode).toBool();
1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067
    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);
1068 1069
    // Save the current power mode
    settings.setValue("LOW_POWER_MODE", lowPowerMode);
1070 1071 1072
    settings.sync();
}

1073 1074
void MainWindow::configureWindowName()
{
pixhawk's avatar
pixhawk committed
1075 1076 1077
    QList<QHostAddress> hostAddresses = QNetworkInterface::allAddresses();
    QString windowname = qApp->applicationName() + " " + qApp->applicationVersion();
    bool prevAddr = false;
1078

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

1081
    for (int i = 0; i < hostAddresses.size(); i++) {
pixhawk's avatar
pixhawk committed
1082
        // Exclude loopback IPv4 and all IPv6 addresses
1083
        if (hostAddresses.at(i) != QHostAddress("127.0.0.1") && !hostAddresses.at(i).toString().contains(":")) {
pixhawk's avatar
pixhawk committed
1084 1085 1086 1087 1088
            if(prevAddr) windowname.append("/");
            windowname.append(hostAddresses.at(i).toString());
            prevAddr = true;
        }
    }
1089

pixhawk's avatar
pixhawk committed
1090
    windowname.append(")");
1091

pixhawk's avatar
pixhawk committed
1092
    setWindowTitle(windowname);
1093 1094

#ifndef Q_WS_MAC
pixhawk's avatar
pixhawk committed
1095
    //qApp->setWindowIcon(QIcon(":/core/images/qtcreator_logo_128.png"));
1096 1097 1098
#endif
}

pixhawk's avatar
pixhawk committed
1099
void MainWindow::startVideoCapture()
pixhawk's avatar
pixhawk committed
1100 1101 1102 1103 1104
{
    QString format = "bmp";
    QString initialPath = QDir::currentPath() + tr("/untitled.") + format;

    QString screenFileName = QFileDialog::getSaveFileName(this, tr("Save As"),
1105 1106 1107 1108
                             initialPath,
                             tr("%1 Files (*.%2);;All Files (*)")
                             .arg(format.toUpper())
                             .arg(format));
pixhawk's avatar
pixhawk committed
1109 1110
    delete videoTimer;
    videoTimer = new QTimer(this);
1111 1112 1113
    //videoTimer->setInterval(40);
    //connect(videoTimer, SIGNAL(timeout()), this, SLOT(saveScreen()));
    //videoTimer->stop();
pixhawk's avatar
pixhawk committed
1114 1115
}

pixhawk's avatar
pixhawk committed
1116
void MainWindow::stopVideoCapture()
pixhawk's avatar
pixhawk committed
1117 1118 1119 1120 1121 1122
{
    videoTimer->stop();

    // TODO Convert raw images to PNG
}

pixhawk's avatar
pixhawk committed
1123
void MainWindow::saveScreen()
pixhawk's avatar
pixhawk committed
1124 1125 1126 1127
{
    QPixmap window = QPixmap::grabWindow(this->winId());
    QString format = "bmp";

1128
    if (!screenFileName.isEmpty()) {
pixhawk's avatar
pixhawk committed
1129 1130 1131 1132
        window.save(screenFileName, format.toAscii());
    }
}

1133
void MainWindow::enableAutoReconnect(bool enabled)
pixhawk's avatar
pixhawk committed
1134
{
1135 1136
    autoReconnect = enabled;
}
1137

1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154
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)
{
1155 1156 1157 1158 1159 1160 1161 1162 1163
    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."));
1164
        }
1165 1166
    }
    break;
1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180
    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;
}

1181
void MainWindow::selectStylesheet()
pixhawk's avatar
pixhawk committed
1182
{
1183
    // Let user select style sheet
1184
    styleFileName = QFileDialog::getOpenFileName(this, tr("Specify stylesheet"), styleFileName, tr("CSS Stylesheet (*.css);;"));
1185

1186
    if (!styleFileName.endsWith(".css")) {
1187 1188 1189 1190 1191 1192 1193 1194 1195 1196
        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
1197
    // Load style sheet
1198 1199 1200 1201 1202 1203 1204
    reloadStylesheet();
}

void MainWindow::reloadStylesheet()
{
    // Load style sheet
    QFile* styleSheet = new QFile(styleFileName);
1205
    if (!styleSheet->exists()) {
1206 1207
        styleSheet = new QFile(":/images/style-mission.css");
    }
1208
    if (styleSheet->open(QIODevice::ReadOnly | QIODevice::Text)) {
1209 1210
        QString style = QString(styleSheet->readAll());
        style.replace("ICONDIR", QCoreApplication::applicationDirPath()+ "/images/");
pixhawk's avatar
pixhawk committed
1211
        qApp->setStyleSheet(style);
1212
    } else {
1213 1214 1215
        QMessageBox msgBox;
        msgBox.setIcon(QMessageBox::Information);
        msgBox.setText(tr("QGroundControl did lot load a new style"));
1216
        msgBox.setInformativeText(tr("Stylesheet file %1 was not readable").arg(styleFileName));
1217 1218 1219
        msgBox.setStandardButtons(QMessageBox::Ok);
        msgBox.setDefaultButton(QMessageBox::Ok);
        msgBox.exec();
pixhawk's avatar
pixhawk committed
1220
    }
1221
    delete styleSheet;
pixhawk's avatar
pixhawk committed
1222 1223
}

1224 1225 1226 1227 1228 1229
/**
 * 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
1230
void MainWindow::showStatusMessage(const QString& status, int timeout)
pixhawk's avatar
pixhawk committed
1231
{
lm's avatar
lm committed
1232
    statusBar()->showMessage(status, timeout);
pixhawk's avatar
pixhawk committed
1233 1234
}

1235 1236 1237 1238 1239 1240
/**
 * 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
 */
1241
void MainWindow::showStatusMessage(const QString& status)
pixhawk's avatar
pixhawk committed
1242
{
lm's avatar
lm committed
1243
    statusBar()->showMessage(status, 20000);
1244 1245 1246 1247
}

void MainWindow::showCriticalMessage(const QString& title, const QString& message)
{
1248
    QMessageBox msgBox(this);
1249 1250 1251 1252 1253 1254
    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
1255 1256
}

lm's avatar
lm committed
1257 1258
void MainWindow::showInfoMessage(const QString& title, const QString& message)
{
1259
    QMessageBox msgBox(this);
lm's avatar
lm committed
1260 1261 1262 1263 1264 1265 1266 1267
    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
1268 1269 1270 1271
/**
* @brief Create all actions associated to the main window
*
**/
1272
void MainWindow::connectCommonActions()
pixhawk's avatar
pixhawk committed
1273
{
1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303
    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
1304 1305 1306 1307 1308
    // 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*)));
1309
    connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)), this, SLOT(setActiveUAS(UASInterface*)));
pixhawk's avatar
pixhawk committed
1310

1311
    // Unmanned System controls
pixhawk's avatar
pixhawk committed
1312 1313 1314 1315
    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()));
1316
    connect(ui.actionShutdownMAV, SIGNAL(triggered()), UASManager::instance(), SLOT(shutdownActiveUAS()));
pixhawk's avatar
pixhawk committed
1317 1318
    connect(ui.actionConfiguration, SIGNAL(triggered()), UASManager::instance(), SLOT(configureActiveUAS()));

1319
    // Views actions
1320
    connect(ui.actionPilotsView, SIGNAL(triggered()), this, SLOT(loadPilotView()));
1321
    connect(ui.actionEngineersView, SIGNAL(triggered()), this, SLOT(loadEngineerView()));
1322
    connect(ui.actionOperatorsView, SIGNAL(triggered()), this, SLOT(loadOperatorView()));
1323
    connect(ui.actionUnconnectedView, SIGNAL(triggered()), this, SLOT(loadUnconnectedView()));
1324

1325
    connect(ui.actionMavlinkView, SIGNAL(triggered()), this, SLOT(loadMAVLinkView()));
1326 1327
    connect(ui.actionReloadStylesheet, SIGNAL(triggered()), this, SLOT(reloadStylesheet()));
    connect(ui.actionSelectStylesheet, SIGNAL(triggered()), this, SLOT(selectStylesheet()));
1328

1329
    // Help Actions
1330
    connect(ui.actionOnline_Documentation, SIGNAL(triggered()), this, SLOT(showHelp()));
1331
    connect(ui.actionDeveloper_Credits, SIGNAL(triggered()), this, SLOT(showCredits()));
1332
    connect(ui.actionProject_Roadmap_2, SIGNAL(triggered()), this, SLOT(showRoadMap()));
1333 1334 1335

    // Custom widget actions
    connect(ui.actionNewCustomWidget, SIGNAL(triggered()), this, SLOT(createCustomWidget()));
1336 1337 1338

    // Audio output
    ui.actionMuteAudioOutput->setChecked(GAudioOutput::instance()->isMuted());
1339
    connect(GAudioOutput::instance(), SIGNAL(mutedChanged(bool)), ui.actionMuteAudioOutput, SLOT(setChecked(bool)));
1340
    connect(ui.actionMuteAudioOutput, SIGNAL(triggered(bool)), GAudioOutput::instance(), SLOT(mute(bool)));
1341 1342 1343 1344 1345 1346 1347

    // 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);
1348 1349 1350

    // Configuration
    // Joystick
1351
    connect(ui.actionJoystickSettings, SIGNAL(triggered()), this, SLOT(configure()));
1352 1353
    // Application Settings
    connect(ui.actionSettings, SIGNAL(triggered()), this, SLOT(showSettings()));
1354 1355 1356 1357 1358 1359 1360 1361 1362 1363
}

void MainWindow::connectPxActions()
{


}

void MainWindow::connectSlugsActions()
{
1364

pixhawk's avatar
pixhawk committed
1365 1366
}

1367 1368
void MainWindow::showHelp()
{
1369
    if(!QDesktopServices::openUrl(QUrl("http://qgroundcontrol.org/users/"))) {
1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381
        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()
{
1382
    if(!QDesktopServices::openUrl(QUrl("http://qgroundcontrol.org/credits/"))) {
1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394
        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()
{
1395
    if(!QDesktopServices::openUrl(QUrl("http://qgroundcontrol.org/roadmap/"))) {
1396 1397 1398 1399 1400 1401 1402 1403 1404 1405
        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
1406
void MainWindow::configure()
pixhawk's avatar
pixhawk committed
1407
{
1408 1409
    if (!joystickWidget) {
        if (!joystick->isRunning()) {
1410 1411 1412 1413 1414
            joystick->start();
        }
        joystickWidget = new JoystickWidget(joystick);
    }
    joystickWidget->show();
pixhawk's avatar
pixhawk committed
1415 1416
}

1417 1418 1419 1420 1421 1422
void MainWindow::showSettings()
{
    QGCSettingsWidget* settings = new QGCSettingsWidget(this);
    settings->show();
}

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

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

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

1434 1435
    foreach (QAction* act, actions) {
        if (act->data().toInt() == LinkManager::instance()->getLinks().indexOf(link)) {
1436 1437 1438 1439
            act->trigger();
            break;
        }
    }
pixhawk's avatar
pixhawk committed
1440 1441
}

pixhawk's avatar
pixhawk committed
1442 1443
void MainWindow::addLink(LinkInterface *link)
{
1444 1445 1446 1447
    // 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)
1448
    LinkManager::instance()->add(link);
1449
    LinkManager::instance()->addProtocol(link, mavlink);
1450

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

1454
    bool found = false;
1455

1456 1457
    foreach (QAction* act, actions) {
        if (act->data().toInt() == LinkManager::instance()->getLinks().indexOf(link)) {
1458 1459 1460 1461 1462
            found = true;
        }
    }

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

1464
    if (!found || udp) {
1465 1466 1467 1468 1469 1470 1471 1472
        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);
1473
        if (sim) {
1474 1475 1476
            //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
1477 1478 1479
    }
}

1480 1481 1482 1483 1484 1485 1486
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);
}

1487 1488 1489
void MainWindow::UASSpecsChanged(int uas)
{
    UASInterface* activeUAS = UASManager::instance()->getActiveUAS();
1490 1491
    if (activeUAS) {
        if (activeUAS->getUASID() == uas) {
1492 1493 1494 1495 1496
            ui.menuUnmanned_System->setTitle(activeUAS->getUASName());
        }
    }
}

pixhawk's avatar
pixhawk committed
1497
void MainWindow::UASCreated(UASInterface* uas)
pixhawk's avatar
pixhawk committed
1498
{
1499

pixhawk's avatar
pixhawk committed
1500 1501
    // Connect the UAS to the full user interface

1502
    if (uas != NULL) {
1503 1504 1505 1506
        // Set default settings
        setDefaultSettingsForAp();

        // The pilot, operator and engineer views were not available on startup, enable them now
1507
        ui.actionPilotsView->setEnabled(true);
1508 1509
        ui.actionOperatorsView->setEnabled(true);
        ui.actionEngineersView->setEnabled(true);
1510 1511 1512 1513 1514 1515
        // 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);
1516

1517 1518
        QIcon icon;
        // Set matching icon
1519
        switch (uas->getSystemType()) {
1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542
        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;
        }

1543 1544 1545
        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()));
1546
        connect(uas, SIGNAL(systemSpecsChanged(int)), this, SLOT(UASSpecsChanged(int)));
1547 1548

        ui.menuConnected_Systems->addAction(uasAction);
1549 1550

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

        // Health / System status indicator
1560
        if (infoDockWidget) {
pixhawk's avatar
pixhawk committed
1561
            UASInfoWidget *infoWidget = dynamic_cast<UASInfoWidget*>(infoDockWidget->widget());
1562
            if (infoWidget) {
pixhawk's avatar
pixhawk committed
1563 1564
                infoWidget->addUAS(uas);
            }
1565
        }
1566 1567

        // UAS List
1568
        if (listDockWidget) {
pixhawk's avatar
pixhawk committed
1569
            UASListWidget *listWidget = dynamic_cast<UASListWidget*>(listDockWidget->widget());
1570
            if (listWidget) {
pixhawk's avatar
pixhawk committed
1571 1572
                listWidget->addUAS(uas);
            }
1573
        }
1574

1575 1576 1577 1578
        switch (uas->getAutopilotType()) {
        case (MAV_AUTOPILOT_SLUGS): {
            // Build Slugs Widgets
            buildSlugsWidgets();
1579

1580 1581
            // Connect Slugs Widgets
            connectSlugsWidgets();
1582

1583 1584
            // Arrange Slugs Centerstack
            arrangeSlugsCenterStack();
1585

1586 1587
            // Connect Slugs Actions
            connectSlugsActions();
1588

1589 1590 1591 1592 1593 1594 1595 1596 1597
//                if(slugsDataWidget)
//                {
//                    SlugsDataSensorView *mm = dynamic_cast<SlugsDataSensorView*>(slugsDataWidget->widget());
//                    if(mm)
//                    {
//                        mm->addUAS(uas);
//                    }
//                }

1598
            // FIXME: This type checking might be redundant
1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609
//                //            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();
//                //                }
//                //              }
//                //            }
1610

1611 1612
        }
        break;
1613 1614 1615
        default:
        case (MAV_AUTOPILOT_GENERIC):
        case (MAV_AUTOPILOT_ARDUPILOTMEGA):
1616 1617 1618
        case (MAV_AUTOPILOT_PIXHAWK): {
            // Build Pixhawk Widgets
            buildPxWidgets();
1619

1620 1621
            // Connect Pixhawk Widgets
            connectPxWidgets();
1622

1623 1624
            // Arrange Pixhawk Centerstack
            arrangePxCenterStack();
1625

1626 1627 1628 1629
            // Connect Pixhawk Actions
            connectPxActions();
        }
        break;
1630 1631 1632 1633 1634 1635
        }

        // 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
1636
        if (UASManager::instance()->getUASList().size() == 1) {
1637
            // Load last view if setting is present
1638
            if (settings.contains("CURRENT_VIEW_WITH_UAS_CONNECTED")) {
1639
                clearView();
1640
                int view = settings.value("CURRENT_VIEW_WITH_UAS_CONNECTED").toInt();
1641
                switch (view) {
1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657
                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;
1658
                }
1659
            } else {
1660
                loadOperatorView();
1661
            }
1662
        }
1663

1664
    }
1665 1666

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

    // Custom widgets, added last to all menus and layouts
    buildCustomWidget();
1670
    // Restore the mainwindow size
1671
    if (settings.contains(getWindowGeometryKey())) {
1672 1673
        restoreGeometry(settings.value(getWindowGeometryKey()).toByteArray());
    }
pixhawk's avatar
pixhawk committed
1674 1675
}

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

    QAction* temp;

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

1696
        if (temp) {
1697
            //qDebug() << "TOOL:" << chKey << "IS:" << temp->isChecked();
1698
            settings.setValue(chKey,temp->isChecked());
1699
        } else {
1700
            //qDebug() << "TOOL:" << chKey << "IS DEFAULT AND UNCHECKED";
1701 1702 1703 1704
            settings.setValue(chKey,false);
        }
    }

1705
    changingViewsFlag = true;
1706 1707
    // Remove all dock widgets from main window
    QObjectList childList( this->children() );
pixhawk's avatar
pixhawk committed
1708

1709 1710
    QObjectList::iterator i;
    QDockWidget* dockWidget;
1711
    for (i = childList.begin(); i != childList.end(); ++i) {
1712
        dockWidget = dynamic_cast<QDockWidget*>(*i);
1713
        if (dockWidget) {
1714
            // Remove dock widget from main window
1715
            removeDockWidget(dockWidget);
1716
            dockWidget->hide();
1717
            //dockWidget->setVisible(false);
pixhawk's avatar
pixhawk committed
1718 1719
        }
    }
1720
    changingViewsFlag = false;
pixhawk's avatar
pixhawk committed
1721 1722
}

1723
void MainWindow::loadEngineerView()
lm's avatar
lm committed
1724
{
1725
    if (currentView != VIEW_ENGINEER) {
1726 1727 1728 1729
        clearView();
        currentView = VIEW_ENGINEER;
        ui.actionEngineersView->setChecked(true);
        presentView();
1730
    }
lm's avatar
lm committed
1731 1732
}

1733
void MainWindow::loadOperatorView()
lm's avatar
lm committed
1734
{
1735
    if (currentView != VIEW_OPERATOR) {
1736 1737 1738 1739 1740 1741
        clearView();
        currentView = VIEW_OPERATOR;
        ui.actionOperatorsView->setChecked(true);
        presentView();
    }
}
lm's avatar
lm committed
1742

1743 1744
void MainWindow::loadUnconnectedView()
{
1745
    if (currentView != VIEW_UNCONNECTED) {
1746 1747 1748 1749
        clearView();
        currentView = VIEW_UNCONNECTED;
        ui.actionUnconnectedView->setChecked(true);
        presentView();
1750
    }
lm's avatar
lm committed
1751 1752
}

1753
void MainWindow::loadPilotView()
1754
{
1755
    if (currentView != VIEW_PILOT) {
1756 1757 1758 1759
        clearView();
        currentView = VIEW_PILOT;
        ui.actionPilotsView->setChecked(true);
        presentView();
1760
    }
1761 1762
}

1763
void MainWindow::loadMAVLinkView()
1764
{
1765
    if (currentView != VIEW_MAVLINK) {
1766 1767 1768 1769
        clearView();
        currentView = VIEW_MAVLINK;
        ui.actionMavlinkView->setChecked(true);
        presentView();
1770
    }
1771 1772
}

lm's avatar
lm committed
1773 1774
void MainWindow::presentView()
{
1775
    // LINE CHART
1776
    showTheCentralWidget(CENTRAL_LINECHART, currentView);
1777

1778 1779
    // MAP
    showTheCentralWidget(CENTRAL_MAP, currentView);
pixhawk's avatar
pixhawk committed
1780

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

1784 1785
    // HEAD UP DISPLAY
    showTheCentralWidget(CENTRAL_HUD, currentView);
pixhawk's avatar
pixhawk committed
1786 1787 1788 1789 1790 1791 1792 1793 1794 1795

    // GOOGLE EARTH
    showTheCentralWidget(CENTRAL_GOOGLE_EARTH, currentView);

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

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

1796 1797 1798
    // DATA PLOT
    showTheCentralWidget(CENTRAL_DATA_PLOT, currentView);

pixhawk's avatar
pixhawk committed
1799

1800
    // Show docked widgets based on current view and autopilot type
1801

1802 1803
    // UAS CONTROL
    showTheWidget(MENU_UAS_CONTROL, currentView);
1804

1805 1806
    showTheWidget(MENU_UAS_CONTROL_PARAM, currentView);

1807 1808
    // UAS LIST
    showTheWidget(MENU_UAS_LIST, currentView);
1809

1810 1811
    // WAYPOINT LIST
    showTheWidget(MENU_WAYPOINTS, currentView);
pixhawk's avatar
pixhawk committed
1812

1813 1814
    // UAS STATUS
    showTheWidget(MENU_STATUS, currentView);
1815

1816 1817
    // DETECTION
    showTheWidget(MENU_DETECTION, currentView);
1818

1819 1820
    // DEBUG CONSOLE
    showTheWidget(MENU_DEBUG_CONSOLE, currentView);
1821

1822 1823
    // ONBOARD PARAMETERS
    showTheWidget(MENU_PARAMETERS, currentView);
1824

1825 1826
    // WATCHDOG
    showTheWidget(MENU_WATCHDOG, currentView);
1827

1828 1829
    // HUD
    showTheWidget(MENU_HUD, currentView);
1830
    if (headUpDockWidget) {
1831
        HUD* tmpHud = dynamic_cast<HUD*>( headUpDockWidget->widget() );
1832 1833
        if (tmpHud) {
            if (settings.value(buildMenuKey (SUB_SECTION_CHECKED,MENU_HUD,currentView)).toBool()) {
1834
                addDockWidget(static_cast <Qt::DockWidgetArea>(settings.value(buildMenuKey (SUB_SECTION_LOCATION,MENU_HUD, currentView)).toInt()),
1835
                              headUpDockWidget);
1836
                headUpDockWidget->show();
1837
            } else {
1838 1839
                headUpDockWidget->hide();
            }
1840
        }
1841
    }
1842

1843

1844 1845
    // RC View
    showTheWidget(MENU_RC_VIEW, currentView);
1846

1847 1848
    // SLUGS DATA
    showTheWidget(MENU_SLUGS_DATA, currentView);
1849

1850 1851
    // SLUGS PID
    showTheWidget(MENU_SLUGS_PID, currentView);
1852

1853 1854
    // SLUGS HIL
    showTheWidget(MENU_SLUGS_HIL, currentView);
1855

1856 1857
    // SLUGS CAMERA
    showTheWidget(MENU_SLUGS_CAMERA, currentView);
1858

1859 1860
    // HORIZONTAL SITUATION INDICATOR
    showTheWidget(MENU_HSI, currentView);
1861

1862 1863 1864 1865 1866
    // HEAD DOWN 1
    showTheWidget(MENU_HDD_1, currentView);

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

1868 1869 1870
    // MAVLINK LOG PLAYER
    showTheWidget(MENU_MAVLINK_LOG_PLAYER, currentView);

1871 1872 1873 1874 1875 1876 1877
    // VIDEO 1
    showTheWidget(MENU_VIDEO_STREAM_1, currentView);

    // VIDEO 2
    showTheWidget(MENU_VIDEO_STREAM_2, currentView);

    // Restore window state
1878
    if (UASManager::instance()->getUASList().count() > 0) {
1879 1880 1881 1882 1883
//        // Restore the mainwindow size
//        if (settings.contains(getWindowGeometryKey()))
//        {
//            restoreGeometry(settings.value(getWindowGeometryKey()).toByteArray());
//        }
1884 1885

        // Restore the widget positions and size
1886
        if (settings.contains(getWindowStateKey())) {
1887 1888 1889
            restoreState(settings.value(getWindowStateKey()).toByteArray(), QGC::applicationVersion());
        }
    }
lm's avatar
lm committed
1890

1891
    // ACTIVATE HUD WIDGET
1892
    if (headUpDockWidget) {
lm's avatar
lm committed
1893
        HUD* tmpHud = dynamic_cast<HUD*>( headUpDockWidget->widget() );
1894
        if (tmpHud) {
lm's avatar
lm committed
1895 1896 1897 1898

        }
    }

1899
    this->setWindowState(windowStateVal);
lm's avatar
lm committed
1900
    this->show();
1901
}
1902

1903 1904 1905 1906
void MainWindow::showTheCentralWidget (TOOLS_WIDGET_NAMES centralWidget, VIEW_SECTIONS view)
{
    bool tempVisible;
    QWidget* tempWidget = dockWidgets[centralWidget];
1907

1908
    tempVisible =  settings.value(buildMenuKey(SUB_SECTION_CHECKED,centralWidget,view), false).toBool();
1909
    //qDebug() << buildMenuKey (SUB_SECTION_CHECKED,centralWidget,view) << tempVisible;
1910
    if (toolsMenuActions[centralWidget]) {
1911
        //qDebug() << "SETTING TO:" << tempVisible;
1912
        toolsMenuActions[centralWidget]->setChecked(tempVisible);
1913
    }
1914

1915
    if (centerStack && tempWidget && tempVisible) {
1916
        //qDebug() << "ACTIVATING MAIN WIDGET";
1917
        centerStack->setCurrentWidget(tempWidget);
1918
    }
1919 1920
}

1921 1922
void MainWindow::loadDataView(QString fileName)
{
1923
    clearView();
1924 1925 1926 1927 1928

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

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

1933
    presentView();
1934

1935
    // Plot is now selected, now load data from file
1936
    if (dataplotWidget) {
1937
        dataplotWidget->loadFile(fileName);
1938
    }
1939 1940 1941 1942 1943 1944 1945
//        QStackedWidget *centerStack = dynamic_cast<QStackedWidget*>(centralWidget());
//        if (centerStack)
//        {
//            centerStack->setCurrentWidget(dataplotWidget);
//            dataplotWidget->loadFile(fileName);
//        }
//    }
1946 1947 1948
}