MainWindow.cc 67.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
#include "QGCSettingsWidget.h"
32

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

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

pixhawk's avatar
pixhawk committed
41

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

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

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

pixhawk's avatar
pixhawk committed
58 59 60 61 62 63 64
/**
* Create new mainwindow. The constructor instantiates all parts of the user
* interface. It does NOT show the mainwindow. To display it, call the show()
* method.
*
* @see QMainWindow::show()
**/
65
MainWindow::MainWindow(QWidget *parent):
pixhawk's avatar
pixhawk committed
66
        QMainWindow(parent),
67
        toolsMenuActions(),
68
        currentView(VIEW_UNCONNECTED),
69
        aboutToCloseFlag(false),
70
        changingViewsFlag(false),
71 72 73
        styleFileName(QCoreApplication::applicationDirPath() + "/style-indoor.css"),
        autoReconnect(false),
        currentStyle(QGC_MAINWINDOW_STYLE_INDOOR)
pixhawk's avatar
pixhawk committed
74
{
75
    loadSettings();
76 77 78 79 80 81 82
    if (!settings.contains("CURRENT_VIEW"))
    {
        // Set this view as default view
        settings.setValue("CURRENT_VIEW", currentView);
    }
    else
    {
83 84 85 86 87
        // LOAD THE LAST VIEW
        VIEW_SECTIONS currentViewCandidate = (VIEW_SECTIONS) settings.value("CURRENT_VIEW", currentView).toInt();
        if (currentViewCandidate != VIEW_ENGINEER &&
            currentViewCandidate != VIEW_OPERATOR &&
            currentViewCandidate != VIEW_PILOT)
88
        {
89
            currentView = currentViewCandidate;
90
        }
91 92
    }

93
    setDefaultSettingsForAp();
94

95 96
    settings.sync();

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

100 101
    setVisible(false);

102
    buildCommonWidgets();
103

104
    connectCommonWidgets();
105

106
    arrangeCommonCenterStack();
107 108

    configureWindowName();
pixhawk's avatar
pixhawk committed
109

110
    loadStyle(currentStyle);
111

112 113 114 115 116 117 118 119 120 121 122 123
//    // Set the application style (not the same as a style sheet)
//    // Set the style to Plastique
//    qApp->setStyle("plastique");

//    // Set style sheet as last step
//    QFile* styleSheet = new QFile(":/images/style-mission.css");
//    if (styleSheet->open(QIODevice::ReadOnly | QIODevice::Text))
//    {
//        QString style = QString(styleSheet->readAll());
//        style.replace("ICONDIR", QCoreApplication::applicationDirPath()+ "/images/");
//        qApp->setStyleSheet(style);
//    }
pixhawk's avatar
pixhawk committed
124

125
    // Create actions
126
    connectCommonActions();
127

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    // MAVLINK VIEW DEFAULT
    centralKey = buildMenuKey(SUB_SECTION_CHECKED, CENTRAL_PROTOCOL, VIEW_MAVLINK);
    if (!settings.contains(centralKey))
    {
        settings.setValue(centralKey,true);
    }

    // PILOT VIEW DEFAULT
    centralKey = buildMenuKey(SUB_SECTION_CHECKED, CENTRAL_HUD, VIEW_PILOT);
    if (!settings.contains(centralKey))
    {
        settings.setValue(centralKey,true);
258 259
        // Enable Flight display
        settings.setValue(buildMenuKey(SUB_SECTION_CHECKED,MainWindow::MENU_HDD_1,VIEW_PILOT), true);
260 261 262
    }
}

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

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

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

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

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

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

        for(int i = 0; i < widgets.size(); ++i)
        {
            // Check if this widget already has a parent, do not create it in this case
            QDockWidget* dock = dynamic_cast<QDockWidget*>(widgets.at(i)->parentWidget());
            if (!dock)
            {
                QDockWidget* dock = new QDockWidget(widgets.at(i)->windowTitle(), this);
310
                dock->setObjectName(widgets.at(i)->objectName()+"_DOCK");
lm's avatar
lm committed
311 312 313
                dock->setWidget(widgets.at(i));
                connect(widgets.at(i), SIGNAL(destroyed()), dock, SLOT(deleteLater()));
                QAction* showAction = new QAction(widgets.at(i)->windowTitle(), this);
314
                showAction->setCheckable(true);
lm's avatar
lm committed
315 316 317 318 319 320 321 322 323 324
                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);
            }
        }
    }
}

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

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

340 341 342 343
    if (!listDockWidget)
    {
        listDockWidget = new QDockWidget(tr("Unmanned Systems"), this);
        listDockWidget->setWidget( new UASListWidget(this) );
344
        listDockWidget->setObjectName("UNMANNED_SYSTEMS_LIST_DOCKWIDGET");
345
        addToToolsMenu (listDockWidget, tr("Unmanned Systems"), SLOT(showToolWidget(bool)), MENU_UAS_LIST, Qt::RightDockWidgetArea);
346
    }
347

348 349
    if (!waypointsDockWidget)
    {
350
        waypointsDockWidget = new QDockWidget(tr("Mission Plan"), this);
351
        waypointsDockWidget->setWidget( new QGCWaypointListMulti(this) );
352
        waypointsDockWidget->setObjectName("WAYPOINT_LIST_DOCKWIDGET");
353
        addToToolsMenu (waypointsDockWidget, tr("Mission Plan"), SLOT(showToolWidget(bool)), MENU_WAYPOINTS, Qt::BottomDockWidgetArea);
354
    }
355

356 357 358 359
    if (!infoDockWidget)
    {
        infoDockWidget = new QDockWidget(tr("Status Details"), this);
        infoDockWidget->setWidget( new UASInfoWidget(this) );
pixhawk's avatar
pixhawk committed
360
        infoDockWidget->setObjectName("UAS_STATUS_DETAILS_DOCKWIDGET");
361
        addToToolsMenu (infoDockWidget, tr("Status Details"), SLOT(showToolWidget(bool)), MENU_STATUS, Qt::RightDockWidgetArea);
362
    }
363

364 365 366 367
    if (!debugConsoleDockWidget)
    {
        debugConsoleDockWidget = new QDockWidget(tr("Communication Console"), this);
        debugConsoleDockWidget->setWidget( new DebugConsole(this) );
368
        debugConsoleDockWidget->setObjectName("COMMUNICATION_DEBUG_CONSOLE_DOCKWIDGET");
369
        addToToolsMenu (debugConsoleDockWidget, tr("Communication Console"), SLOT(showToolWidget(bool)), MENU_DEBUG_CONSOLE, Qt::BottomDockWidgetArea);
370
    }
371

372 373 374 375 376
    if (!logPlayerDockWidget)
    {
        logPlayerDockWidget = new QDockWidget(tr("MAVLink Log Player"), this);
        logPlayerDockWidget->setWidget( new QGCMAVLinkLogPlayer(mavlink, this) );
        logPlayerDockWidget->setObjectName("MAVLINK_LOG_PLAYER_DOCKWIDGET");
377
        addToToolsMenu(logPlayerDockWidget, tr("MAVLink Log Replay"), SLOT(showToolWidget(bool)), MENU_MAVLINK_LOG_PLAYER, Qt::RightDockWidgetArea);
378 379
    }

380
    // Center widgets
381 382
    if (!mapWidget)
    {
383
        mapWidget = new MapWidget(this);
384 385
        addToCentralWidgetsMenu (mapWidget, "Maps", SLOT(showCentralWidget()),CENTRAL_MAP);
    }
386

387 388 389 390 391
    if (!protocolWidget)
    {
        protocolWidget    = new XMLCommProtocolWidget(this);
        addToCentralWidgetsMenu (protocolWidget, "Mavlink Generator", SLOT(showCentralWidget()),CENTRAL_PROTOCOL);
    }
lm's avatar
lm committed
392 393 394 395

    if (!dataplotWidget)
    {
        dataplotWidget    = new QGCDataPlot2D(this);
396
        addToCentralWidgetsMenu (dataplotWidget, "Logfile Plot", SLOT(showCentralWidget()),CENTRAL_DATA_PLOT);
lm's avatar
lm committed
397
    }
398
}
399

400

401
void MainWindow::buildPxWidgets()
402
{
pixhawk's avatar
pixhawk committed
403 404
    //FIXME: memory of acceptList will never be freed again
    QStringList* acceptList = new QStringList();
pixhawk's avatar
pixhawk committed
405 406 407
    acceptList->append("-105,roll deg,deg,+105,s");
    acceptList->append("-105,pitch deg,deg,+105,s");
    acceptList->append("-105,heading deg,deg,+105,s");
408

pixhawk's avatar
pixhawk committed
409 410 411
    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");
412
    acceptList->append("0,airspeed,m/s,30");
413 414
    acceptList->append("0,groundspeed,m/s,30");
    acceptList->append("0,climbrate,m/s,30");
415
    acceptList->append("0,throttle,%,100");
416

pixhawk's avatar
pixhawk committed
417 418
    //FIXME: memory of acceptList2 will never be freed again
    QStringList* acceptList2 = new QStringList();
419 420 421 422 423 424 425 426
    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
427
    acceptList2->append("0,abs pressure,hPa,65500");
428 429 430
    //acceptList2->append("-2048,accel. x,raw,2048,s");
    //acceptList2->append("-2048,accel. y,raw,2048,s");
    //acceptList2->append("-2048,accel. z,raw,2048,s");
431

432 433 434 435
    if (!linechartWidget)
    {
        // Center widgets
        linechartWidget   = new Linecharts(this);
436
        addToCentralWidgetsMenu(linechartWidget, tr("Realtime Plot"), SLOT(showCentralWidget()), CENTRAL_LINECHART);
437
    }
438 439


440 441 442
    if (!hudWidget)
    {
        hudWidget         = new HUD(320, 240, this);
443
        addToCentralWidgetsMenu(hudWidget, tr("Head Up Display"), SLOT(showCentralWidget()), CENTRAL_HUD);
444
    }
445

446 447 448
    if (!dataplotWidget)
    {
        dataplotWidget    = new QGCDataPlot2D(this);
449
        addToCentralWidgetsMenu(dataplotWidget, "Logfile Plot", SLOT(showCentralWidget()), CENTRAL_DATA_PLOT);
450
    }
451

452
#ifdef QGC_OSG_ENABLED
453 454
    if (!_3DWidget)
    {
455
        _3DWidget         = Q3DWidgetFactory::get("PIXHAWK");
456
        addToCentralWidgetsMenu(_3DWidget, tr("Local 3D"), SLOT(showCentralWidget()), CENTRAL_3D_LOCAL);
457
    }
458
#endif
459

460
#ifdef QGC_OSGEARTH_ENABLED
461 462 463
    if (!_3DMapWidget)
    {
        _3DMapWidget = Q3DWidgetFactory::get("MAP3D");
464
        addToCentralWidgetsMenu(_3DMapWidget, tr("OSG Earth 3D"), SLOT(showCentralWidget()), CENTRAL_OSGEARTH);
465
    }
466
#endif
lm's avatar
lm committed
467

468
#if (defined _MSC_VER) | (defined Q_OS_MAC)
469 470 471
    if (!gEarthWidget)
    {
        gEarthWidget = new QGCGoogleEarthView(this);
472
        addToCentralWidgetsMenu(gEarthWidget, tr("Google Earth"), SLOT(showCentralWidget()), CENTRAL_GOOGLE_EARTH);
473
    }
474

475
#endif
476

pixhawk's avatar
pixhawk committed
477
    // Dock widgets
478

479 480 481 482
    if (!detectionDockWidget)
    {
        detectionDockWidget = new QDockWidget(tr("Object Recognition"), this);
        detectionDockWidget->setWidget( new ObjectDetectionView("images/patterns", this) );
pixhawk's avatar
pixhawk committed
483
        detectionDockWidget->setObjectName("OBJECT_DETECTION_DOCK_WIDGET");
484
        addToToolsMenu (detectionDockWidget, tr("Object Recognition"), SLOT(showToolWidget(bool)), MENU_DETECTION, Qt::RightDockWidgetArea);
485
    }
486

487 488
    if (!parametersDockWidget)
    {
489
        parametersDockWidget = new QDockWidget(tr("Calibration and Onboard Parameters"), this);
490
        parametersDockWidget->setWidget( new ParameterInterface(this) );
pixhawk's avatar
pixhawk committed
491
        parametersDockWidget->setObjectName("PARAMETER_INTERFACE_DOCKWIDGET");
492
        addToToolsMenu (parametersDockWidget, tr("Calibration and Parameters"), SLOT(showToolWidget(bool)), MENU_PARAMETERS, Qt::RightDockWidgetArea);
493
    }
494

495 496 497 498
    if (!watchdogControlDockWidget)
    {
        watchdogControlDockWidget = new QDockWidget(tr("Process Control"), this);
        watchdogControlDockWidget->setWidget( new WatchdogControl(this) );
pixhawk's avatar
pixhawk committed
499
        watchdogControlDockWidget->setObjectName("WATCHDOG_CONTROL_DOCKWIDGET");
500
        addToToolsMenu (watchdogControlDockWidget, tr("Process Control"), SLOT(showToolWidget(bool)), MENU_WATCHDOG, Qt::BottomDockWidgetArea);
501
    }
502

503 504 505 506
    if (!hsiDockWidget)
    {
        hsiDockWidget = new QDockWidget(tr("Horizontal Situation Indicator"), this);
        hsiDockWidget->setWidget( new HSIDisplay(this) );
507
        hsiDockWidget->setObjectName("HORIZONTAL_SITUATION_INDICATOR_DOCK_WIDGET");
508
        addToToolsMenu (hsiDockWidget, tr("Horizontal Situation"), SLOT(showToolWidget(bool)), MENU_HSI, Qt::BottomDockWidgetArea);
509
    }
510

511 512
    if (!headDown1DockWidget)
    {
513 514
        headDown1DockWidget = new QDockWidget(tr("Flight Display"), this);
        headDown1DockWidget->setWidget( new HDDisplay(acceptList, "Flight Display", this) );
515
        headDown1DockWidget->setObjectName("HEAD_DOWN_DISPLAY_1_DOCK_WIDGET");
516
        addToToolsMenu (headDown1DockWidget, tr("Flight Display"), SLOT(showToolWidget(bool)), MENU_HDD_1, Qt::RightDockWidgetArea);
517
    }
518

519 520
    if (!headDown2DockWidget)
    {
521 522
        headDown2DockWidget = new QDockWidget(tr("Actuator Status"), this);
        headDown2DockWidget->setWidget( new HDDisplay(acceptList2, "Actuator Status", this) );
523
        headDown2DockWidget->setObjectName("HEAD_DOWN_DISPLAY_2_DOCK_WIDGET");
524
        addToToolsMenu (headDown2DockWidget, tr("Actuator Status"), SLOT(showToolWidget(bool)), MENU_HDD_2, Qt::RightDockWidgetArea);
525
    }
526

527 528 529 530
    if (!rcViewDockWidget)
    {
        rcViewDockWidget = new QDockWidget(tr("Radio Control"), this);
        rcViewDockWidget->setWidget( new QGCRemoteControlView(this) );
531
        rcViewDockWidget->setObjectName("RADIO_CONTROL_CHANNELS_DOCK_WIDGET");
532
        addToToolsMenu (rcViewDockWidget, tr("Radio Control"), SLOT(showToolWidget(bool)), MENU_RC_VIEW, Qt::BottomDockWidgetArea);
533
    }
534

535 536 537 538
    if (!headUpDockWidget)
    {
        headUpDockWidget = new QDockWidget(tr("HUD"), this);
        headUpDockWidget->setWidget( new HUD(320, 240, this));
539
        headUpDockWidget->setObjectName("HEAD_UP_DISPLAY_DOCK_WIDGET");
540
        addToToolsMenu (headUpDockWidget, tr("Head Up Display"), SLOT(showToolWidget(bool)), MENU_HUD, Qt::RightDockWidgetArea);
541
    }
542

pixhawk's avatar
pixhawk committed
543 544 545 546 547 548 549 550 551
    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");
552
        addToToolsMenu (video1DockWidget, tr("Video Stream 1"), SLOT(showToolWidget(bool)), MENU_VIDEO_STREAM_1, Qt::LeftDockWidgetArea);
pixhawk's avatar
pixhawk committed
553 554 555 556 557 558 559 560 561 562 563
    }

    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");
564
        addToToolsMenu (video2DockWidget, tr("Video Stream 2"), SLOT(showToolWidget(bool)), MENU_VIDEO_STREAM_2, Qt::LeftDockWidgetArea);
565
    }
566

pixhawk's avatar
pixhawk committed
567 568
    // Dialogue widgets
    //FIXME: free memory in destructor
569 570 571 572
}

void MainWindow::buildSlugsWidgets()
{
573 574 575 576
    if (!linechartWidget)
    {
        // Center widgets
        linechartWidget   = new Linecharts(this);
577
        addToCentralWidgetsMenu(linechartWidget, tr("Realtime Plot"), SLOT(showCentralWidget()), CENTRAL_LINECHART);
578
    }
579

580 581 582 583 584
    if (!headUpDockWidget)
    {
        // Dock widgets
        headUpDockWidget = new QDockWidget(tr("Control Indicator"), this);
        headUpDockWidget->setWidget( new HUD(320, 240, this));
pixhawk's avatar
pixhawk committed
585
        headUpDockWidget->setObjectName("HEAD_UP_DISPLAY_DOCK_WIDGET");
586
        addToToolsMenu (headUpDockWidget, tr("Head Up Display"), SLOT(showToolWidget(bool)), MENU_HUD, Qt::LeftDockWidgetArea);
587
    }
588

589 590 591 592
    if (!rcViewDockWidget)
    {
        rcViewDockWidget = new QDockWidget(tr("Radio Control"), this);
        rcViewDockWidget->setWidget( new QGCRemoteControlView(this) );
pixhawk's avatar
pixhawk committed
593
        rcViewDockWidget->setObjectName("RADIO_CONTROL_CHANNELS_DOCK_WIDGET");
594
        addToToolsMenu (rcViewDockWidget, tr("Radio Control"), SLOT(showToolWidget(bool)), MENU_RC_VIEW, Qt::BottomDockWidgetArea);
595
    }
596

597 598 599 600 601 602 603 604 605
#if (defined _MSC_VER) | (defined Q_OS_MAC)
    if (!gEarthWidget)
    {
        gEarthWidget = new QGCGoogleEarthView(this);
        addToCentralWidgetsMenu(gEarthWidget, tr("Google Earth"), SLOT(showCentralWidget()), CENTRAL_GOOGLE_EARTH);
    }

#endif

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

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

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

631 632 633 634 635 636 637 638
    if (!parametersDockWidget)
    {
        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);
    }

639 640 641 642 643 644 645
//    if (!slugsCamControlWidget)
//    {
//        slugsCamControlWidget = new QDockWidget(tr("Slugs Video Camera Control"), this);
//        slugsCamControlWidget->setWidget(new SlugsVideoCamControl(this));
//        slugsCamControlWidget->setObjectName("SLUGS_CAM_CONTROL_DOCK_WIDGET");
//        addToToolsMenu (slugsCamControlWidget, tr("Camera Control"), SLOT(showToolWidget()), MENU_SLUGS_CAMERA, Qt::BottomDockWidgetArea);
//    }
646
}
647 648 649 650 651


void MainWindow::addToCentralWidgetsMenu ( QWidget* widget,
                                           const QString title,
                                           const char * slotName,
652 653
                                           TOOLS_WIDGET_NAMES centralWidget)
{
654
    QAction* tempAction;
655

656

657
// Not needed any more - separate menu now available
658

659 660 661 662 663 664 665
//    // 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);
//    }
666

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

669 670
    tempAction->setCheckable(true);
    tempAction->setData(centralWidget);
671

672 673 674
    // populate the Hashes
    toolsMenuActions[centralWidget] = tempAction;
    dockWidgets[centralWidget] = widget;
675

676
    QString chKey = buildMenuKey(SUB_SECTION_CHECKED, centralWidget, currentView);
677

678 679
    if (!settings.contains(chKey))
    {
680 681 682
        settings.setValue(chKey,false);
        tempAction->setChecked(false);
    }
683 684 685 686
    else
    {
        tempAction->setChecked(settings.value(chKey).toBool());
    }
687

688
    // connect the action
689
    connect(tempAction,SIGNAL(triggered(bool)),this, slotName);
690 691 692
}


lm's avatar
lm committed
693 694
void MainWindow::showCentralWidget()
{
695
    QAction* senderAction = qobject_cast<QAction *>(sender());
696 697 698 699

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

700 701
    int tool = senderAction->data().toInt();
    QString chKey;
702

703
    // check the current action
704

705 706 707 708
    if (senderAction && dockWidgets[tool])
    {
        // uncheck all central widget actions
        QHashIterator<int, QAction*> i(toolsMenuActions);
709 710
        while (i.hasNext())
        {
711
            i.next();
712 713 714
            //qDebug() << "shCW" << i.key() << "read";
            if (i.value() && i.value()->data().toInt() > 255)
            {
715 716 717
                // Block signals and uncheck action
                // firing would be unneccesary
                i.value()->blockSignals(true);
718
                i.value()->setChecked(false);
719
                i.value()->blockSignals(false);
720 721 722 723 724 725

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

727
        // check the current action
728
        //qDebug() << senderAction->text();
729
        senderAction->setChecked(true);
730

731 732
        // update the central widget
        centerStack->setCurrentWidget(dockWidgets[tool]);
733

734 735 736
        // store the selected central widget
        chKey = buildMenuKey (SUB_SECTION_CHECKED,static_cast<TOOLS_WIDGET_NAMES>(tool), currentView);
        settings.setValue(chKey,true);
737

738 739 740
        // Unblock sender action
        senderAction->blockSignals(false);

741 742
        presentView();
    }
743
}
744

lm's avatar
lm committed
745 746 747 748
/**
 * Adds a widget to the tools menu and sets it visible if it was
 * enabled last time.
 */
749
void MainWindow::addToToolsMenu ( QWidget* widget,
750 751 752 753
                                  const QString title,
                                  const char * slotName,
                                  TOOLS_WIDGET_NAMES tool,
                                  Qt::DockWidgetArea location)
lm's avatar
lm committed
754
{
755 756
    QAction* tempAction;
    QString posKey, chKey;
757

758

759 760
    if (toolsMenuActions[CENTRAL_SEPARATOR])
    {
761 762 763
        tempAction = new QAction(title, this);
        ui.menuTools->insertAction(toolsMenuActions[CENTRAL_SEPARATOR],
                                   tempAction);
764 765 766
    }
    else
    {
767 768
        tempAction = ui.menuTools->addAction(title);
    }
769

770 771
    tempAction->setCheckable(true);
    tempAction->setData(tool);
772

773 774 775
    // populate the Hashes
    toolsMenuActions[tool] = tempAction;
    dockWidgets[tool] = widget;
776
    //qDebug() << widget;
777

778
    posKey = buildMenuKey (SUB_SECTION_LOCATION,tool, currentView);
779

780 781
    if (!settings.contains(posKey))
    {
782 783
        settings.setValue(posKey,location);
        dockWidgetLocations[tool] = location;
784 785 786 787
    }
    else
    {
        dockWidgetLocations[tool] = static_cast <Qt::DockWidgetArea> (settings.value(posKey, Qt::RightDockWidgetArea).toInt());
788
    }
789

790
    chKey = buildMenuKey(SUB_SECTION_CHECKED,tool, currentView);
791

792 793 794 795
    if (!settings.contains(chKey))
    {
        settings.setValue(chKey,false);
        tempAction->setChecked(false);
796
        widget->setVisible(false);
797 798 799
    }
    else
    {
800
        tempAction->setChecked(settings.value(chKey, false).toBool());
801
        widget->setVisible(settings.value(chKey, false).toBool());
802
    }
803

804
    // connect the action
805 806 807
    connect(tempAction,SIGNAL(toggled(bool)),this, slotName);

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

810 811
    //  connect(qobject_cast <QDockWidget *>(dockWidgets[tool]),
    //          SIGNAL(visibilityChanged(bool)), this, SLOT(updateVisibilitySettings(bool)));
812

813 814
    connect(qobject_cast <QDockWidget *>(dockWidgets[tool]),
            SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), this, SLOT(updateLocationSettings(Qt::DockWidgetArea)));
815 816
}

817
void MainWindow::showToolWidget(bool visible)
818
{
819
    if (!aboutToCloseFlag && !changingViewsFlag)
820
    {
821 822
        QAction* action = qobject_cast<QAction *>(sender());

823 824
        // Prevent this to fire if undocked
        if (action)
825
        {
826
            int tool = action->data().toInt();
827

828
            QDockWidget* dockWidget = qobject_cast<QDockWidget *> (dockWidgets[tool]);
829

830 831 832 833 834 835 836 837 838 839 840
            if (dockWidget && dockWidget->isVisible() != visible)
            {
                if (visible)
                {
                    addDockWidget(dockWidgetLocations[tool], dockWidget);
                    dockWidget->show();
                }
                else
                {
                    removeDockWidget(dockWidget);
                }
841 842 843 844 845 846 847 848 849

                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);
850
                        //qDebug() << "showToolWidget(): Set key" << chKey << "to" << visible;
851 852 853
                        break;
                    }
                }
854
            }
855
        }
856 857 858

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

859
        //qDebug() << "Trying to cast dockwidget" << dockWidget << "isvisible" << visible;
860 861

        if (dockWidget)
862
        {
863 864 865
            // Get action
            int tool = dockWidgets.key(dockWidget);

866
            //qDebug() << "Updating widget setting" << tool << "to" << visible;
867 868 869 870 871 872 873 874 875 876 877 878 879 880

            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);
881
                   // qDebug() << "showToolWidget(): Set key" << chKey << "to" << visible;
882 883 884
                    break;
                }
            }
885
        }
886 887 888 889
    }
}


890 891 892 893 894
void MainWindow::showTheWidget (TOOLS_WIDGET_NAMES widget, VIEW_SECTIONS view)
{
    bool tempVisible;
    Qt::DockWidgetArea tempLocation;
    QDockWidget* tempWidget = static_cast <QDockWidget *>(dockWidgets[widget]);
895

896
    tempVisible =  settings.value(buildMenuKey(SUB_SECTION_CHECKED,widget,view), false).toBool();
897

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

900 901 902 903
    if (tempWidget)
    {
        toolsMenuActions[widget]->setChecked(tempVisible);
    }
904 905


906
    //qDebug() <<  buildMenuKey (SUB_SECTION_CHECKED,widget,view) << tempVisible;
907

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

910
    if (tempWidget != NULL)
911
    {
912 913 914 915 916
        if (tempVisible)
        {
            addDockWidget(tempLocation, tempWidget);
            tempWidget->show();
        }
917 918
    }
}
919

920 921 922 923 924
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;

925 926 927 928 929
//    apType = (UASManager::instance() && UASManager::instance()->silentGetActiveUAS())?
//             UASManager::instance()->getActiveUAS()->getAutopilotType():
//             -1;

    apType = 1;
930

931 932 933 934 935
    return (QString::number(apType) + "_" +
            QString::number(SECTION_MENU) + "_" +
            QString::number(view) + "_" +
            QString::number(tool) + "_" +
            QString::number(section) + "_" );
936 937
}

938 939
void MainWindow::closeEvent(QCloseEvent *event)
{
940
    storeSettings();
941
    aboutToCloseFlag = true;
942
    mavlink->storeSettings();
943
    UASManager::instance()->storeSettings();
944 945
    QMainWindow::closeEvent(event);
}
946

947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969
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;
                }
            }
        }
    }
}
970

971 972
void MainWindow::updateVisibilitySettings (bool vis)
{
973
    if (!aboutToCloseFlag && !changingViewsFlag)
974 975 976 977 978 979
    {
        QDockWidget* temp = qobject_cast<QDockWidget *>(sender());

        if (temp)
        {
            QHashIterator<int, QWidget*> i(dockWidgets);
980 981
            while (i.hasNext())
            {
982
                i.next();
983 984
                if ((static_cast <QDockWidget *>(dockWidgets[i.key()])) == temp)
                {
985 986
                    QString chKey = buildMenuKey (SUB_SECTION_CHECKED,static_cast<TOOLS_WIDGET_NAMES>(i.key()), currentView);
                    settings.setValue(chKey,vis);
987 988 989 990 991 992
                    toolsMenuActions[i.key()]->setChecked(vis);
                    break;
                }
            }
        }
    }
993 994
}

995 996 997
void MainWindow::updateLocationSettings (Qt::DockWidgetArea location)
{
    QDockWidget* temp = qobject_cast<QDockWidget *>(sender());
998

999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009
    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;
        }
    }
1010 1011
}

1012

1013 1014 1015
/**
 * Connect the signals and slots of the common window widgets
 */
1016
void MainWindow::connectCommonWidgets()
1017
{
pixhawk's avatar
pixhawk committed
1018 1019 1020 1021 1022
    if (infoDockWidget && infoDockWidget->widget())
    {
        connect(mavlink, SIGNAL(receiveLossChanged(int, float)),
                infoDockWidget->widget(), SLOT(updateSendLoss(int, float)));
    }
1023

pixhawk's avatar
pixhawk committed
1024 1025
    if (mapWidget && waypointsDockWidget->widget())
    {
1026

1027 1028 1029 1030 1031 1032
        //
        connect(waypointsDockWidget->widget(), SIGNAL(changePointList()), mapWidget, SLOT(clearWaypoints()));




1033
    }
Alejandro's avatar
Alejandro committed
1034 1035 1036 1037 1038 1039

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

1042 1043
void MainWindow::createCustomWidget()
{
lm's avatar
lm committed
1044 1045 1046 1047 1048 1049 1050 1051
    QGCToolWidget* tool = new QGCToolWidget("Unnamed Tool", this);

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

1052
    QDockWidget* dock = new QDockWidget("Unnamed Tool", this);
lm's avatar
lm committed
1053
    connect(tool, SIGNAL(destroyed()), dock, SLOT(deleteLater()));
1054
    dock->setWidget(tool);
1055

lm's avatar
lm committed
1056
    QAction* showAction = new QAction("Show Unnamed Tool", this);
1057
    showAction->setCheckable(true);
lm's avatar
lm committed
1058 1059 1060 1061 1062
    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);
1063
    dock->setVisible(true);
1064 1065 1066 1067
}

void MainWindow::connectPxWidgets()
{
1068
    // No special connections necessary at this point
1069 1070 1071 1072
}

void MainWindow::connectSlugsWidgets()
{
1073
    if (slugsHilSimWidget && slugsHilSimWidget->widget()){
1074 1075
        connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)),
                slugsHilSimWidget->widget(), SLOT(activeUasSet(UASInterface*)));
1076 1077 1078
    }

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

1083 1084 1085 1086
    if (slugsPIDControlWidget && slugsPIDControlWidget->widget()){
        connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)),
                slugsPIDControlWidget->widget(), SLOT(activeUasSet(UASInterface*)));
    }
1087 1088
}

1089
void MainWindow::arrangeCommonCenterStack()
1090
{
1091
    centerStack = new QStackedWidget(this);
1092
    centerStack->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
1093

pixhawk's avatar
pixhawk committed
1094
    if (!centerStack) return;
1095

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

    setCentralWidget(centerStack);
}

void MainWindow::arrangePxCenterStack()
{

1106 1107 1108 1109
    if (!centerStack) {
        qDebug() << "Center Stack not Created!";
        return;
    }
1110

1111 1112

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

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

void MainWindow::arrangeSlugsCenterStack()
{

1130 1131 1132 1133
    if (!centerStack) {
        qDebug() << "Center Stack not Created!";
        return;
    }
1134

1135 1136
    if (linechartWidget && (centerStack->indexOf(linechartWidget) == -1)) centerStack->addWidget(linechartWidget);
    if (hudWidget && (centerStack->indexOf(hudWidget) == -1)) centerStack->addWidget(hudWidget);
1137

1138 1139 1140 1141
#if (defined _MSC_VER) | (defined Q_OS_MAC)
    if (gEarthWidget && (centerStack->indexOf(gEarthWidget) == -1)) centerStack->addWidget(gEarthWidget);
#endif

1142 1143
}

1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169
void MainWindow::loadSettings()
{
    QSettings settings;
    settings.beginGroup("QGC_MAINWINDOW");
    autoReconnect = settings.value("AUTO_RECONNECT", autoReconnect).toBool();
    currentStyle = (QGC_MAINWINDOW_STYLE)settings.value("CURRENT_STYLE", currentStyle).toInt();
    settings.endGroup();
}

void MainWindow::storeSettings()
{
    QSettings settings;
    settings.beginGroup("QGC_MAINWINDOW");
    settings.setValue("AUTO_RECONNECT", autoReconnect);
    settings.setValue("CURRENT_STYLE", currentStyle);
    settings.endGroup();
    settings.setValue(getWindowGeometryKey(), saveGeometry());
    // Save the last current view in any case
    settings.setValue("CURRENT_VIEW", currentView);
    // Save the current window state, but only if a system is connected (else no real number of widgets would be present)
    if (UASManager::instance()->getUASList().length() > 0) settings.setValue(getWindowStateKey(), saveState(QGC::applicationVersion()));
    // Save the current view only if a UAS is connected
    if (UASManager::instance()->getUASList().length() > 0) settings.setValue("CURRENT_VIEW_WITH_UAS_CONNECTED", currentView);
    settings.sync();
}

1170 1171
void MainWindow::configureWindowName()
{
pixhawk's avatar
pixhawk committed
1172 1173 1174
    QList<QHostAddress> hostAddresses = QNetworkInterface::allAddresses();
    QString windowname = qApp->applicationName() + " " + qApp->applicationVersion();
    bool prevAddr = false;
1175

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

pixhawk's avatar
pixhawk committed
1178 1179 1180 1181 1182 1183 1184 1185 1186 1187
    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;
        }
    }
1188

pixhawk's avatar
pixhawk committed
1189
    windowname.append(")");
1190

pixhawk's avatar
pixhawk committed
1191
    setWindowTitle(windowname);
1192 1193

#ifndef Q_WS_MAC
pixhawk's avatar
pixhawk committed
1194
    //qApp->setWindowIcon(QIcon(":/core/images/qtcreator_logo_128.png"));
1195 1196 1197
#endif
}

pixhawk's avatar
pixhawk committed
1198
void MainWindow::startVideoCapture()
pixhawk's avatar
pixhawk committed
1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209
{
    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);
1210 1211 1212
    //videoTimer->setInterval(40);
    //connect(videoTimer, SIGNAL(timeout()), this, SLOT(saveScreen()));
    //videoTimer->stop();
pixhawk's avatar
pixhawk committed
1213 1214
}

pixhawk's avatar
pixhawk committed
1215
void MainWindow::stopVideoCapture()
pixhawk's avatar
pixhawk committed
1216 1217 1218 1219 1220 1221
{
    videoTimer->stop();

    // TODO Convert raw images to PNG
}

pixhawk's avatar
pixhawk committed
1222
void MainWindow::saveScreen()
pixhawk's avatar
pixhawk committed
1223 1224 1225 1226 1227 1228 1229 1230 1231 1232
{
    QPixmap window = QPixmap::grabWindow(this->winId());
    QString format = "bmp";

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

1233
void MainWindow::enableAutoReconnect(bool enabled)
pixhawk's avatar
pixhawk committed
1234
{
1235 1236
    autoReconnect = enabled;
}
1237

1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283
void MainWindow::loadNativeStyle()
{
    loadStyle(QGC_MAINWINDOW_STYLE_NATIVE);
}

void MainWindow::loadIndoorStyle()
{
    loadStyle(QGC_MAINWINDOW_STYLE_INDOOR);
}

void MainWindow::loadOutdoorStyle()
{
    loadStyle(QGC_MAINWINDOW_STYLE_OUTDOOR);
}

void MainWindow::loadStyle(QGC_MAINWINDOW_STYLE style)
{
    switch (style)
    {
    case QGC_MAINWINDOW_STYLE_NATIVE:
        {
            // Native mode means setting no style
            // so if we were already in native mode
            // take no action
            // Only if a style was set, remove it.
            if (style != currentStyle)
            {
                qApp->setStyleSheet("");
                showInfoMessage(tr("Please restart QGroundControl"), tr("Please restart QGroundControl to switch to fully native look and feel. Currently you have loaded Qt's plastique style."));
            }
        }
        break;
    case QGC_MAINWINDOW_STYLE_INDOOR:
        qApp->setStyle("plastique");
        styleFileName = ":/images/style-mission.css";
        reloadStylesheet();
        break;
    case QGC_MAINWINDOW_STYLE_OUTDOOR:
        qApp->setStyle("plastique");
        styleFileName = ":/images/style-outdoor.css";
        reloadStylesheet();
        break;
    }
    currentStyle = style;
}

1284
void MainWindow::selectStylesheet()
pixhawk's avatar
pixhawk committed
1285
{
1286
    // Let user select style sheet
1287
    styleFileName = QFileDialog::getOpenFileName(this, tr("Specify stylesheet"), styleFileName, tr("CSS Stylesheet (*.css);;"));
1288

1289
    if (!styleFileName.endsWith(".css"))
1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300
    {
        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
1301
    // Load style sheet
1302 1303 1304 1305 1306 1307 1308
    reloadStylesheet();
}

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

1332 1333 1334 1335 1336 1337
/**
 * 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
1338
void MainWindow::showStatusMessage(const QString& status, int timeout)
pixhawk's avatar
pixhawk committed
1339
{
lm's avatar
lm committed
1340
    statusBar()->showMessage(status, timeout);
pixhawk's avatar
pixhawk committed
1341 1342
}

1343 1344 1345 1346 1347 1348
/**
 * 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
 */
1349
void MainWindow::showStatusMessage(const QString& status)
pixhawk's avatar
pixhawk committed
1350
{
lm's avatar
lm committed
1351
    statusBar()->showMessage(status, 20000);
1352 1353 1354 1355
}

void MainWindow::showCriticalMessage(const QString& title, const QString& message)
{
1356
    QMessageBox msgBox(this);
1357 1358 1359 1360 1361 1362
    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
1363 1364
}

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

1419
    // Unmanned System controls
pixhawk's avatar
pixhawk committed
1420 1421 1422 1423
    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()));
1424
    connect(ui.actionShutdownMAV, SIGNAL(triggered()), UASManager::instance(), SLOT(shutdownActiveUAS()));
pixhawk's avatar
pixhawk committed
1425 1426
    connect(ui.actionConfiguration, SIGNAL(triggered()), UASManager::instance(), SLOT(configureActiveUAS()));

1427
    // Views actions
1428
    connect(ui.actionPilotsView, SIGNAL(triggered()), this, SLOT(loadPilotView()));
1429
    connect(ui.actionEngineersView, SIGNAL(triggered()), this, SLOT(loadEngineerView()));
1430
    connect(ui.actionOperatorsView, SIGNAL(triggered()), this, SLOT(loadOperatorView()));
1431
    connect(ui.actionUnconnectedView, SIGNAL(triggered()), this, SLOT(loadUnconnectedView()));
1432

1433
    connect(ui.actionMavlinkView, SIGNAL(triggered()), this, SLOT(loadMAVLinkView()));
1434 1435
    connect(ui.actionReloadStylesheet, SIGNAL(triggered()), this, SLOT(reloadStylesheet()));
    connect(ui.actionSelectStylesheet, SIGNAL(triggered()), this, SLOT(selectStylesheet()));
1436

1437
    // Help Actions
1438
    connect(ui.actionOnline_Documentation, SIGNAL(triggered()), this, SLOT(showHelp()));
1439
    connect(ui.actionDeveloper_Credits, SIGNAL(triggered()), this, SLOT(showCredits()));
1440
    connect(ui.actionProject_Roadmap_2, SIGNAL(triggered()), this, SLOT(showRoadMap()));
1441 1442 1443

    // Custom widget actions
    connect(ui.actionNewCustomWidget, SIGNAL(triggered()), this, SLOT(createCustomWidget()));
1444 1445 1446

    // Audio output
    ui.actionMuteAudioOutput->setChecked(GAudioOutput::instance()->isMuted());
1447
    connect(GAudioOutput::instance(), SIGNAL(mutedChanged(bool)), ui.actionMuteAudioOutput, SLOT(setChecked(bool)));
1448
    connect(ui.actionMuteAudioOutput, SIGNAL(triggered(bool)), GAudioOutput::instance(), SLOT(mute(bool)));
1449 1450 1451 1452 1453 1454 1455

    // 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);
1456 1457 1458

    // Configuration
    // Joystick
1459
    connect(ui.actionJoystickSettings, SIGNAL(triggered()), this, SLOT(configure()));
1460 1461
    // Application Settings
    connect(ui.actionSettings, SIGNAL(triggered()), this, SLOT(showSettings()));
1462 1463 1464 1465 1466 1467 1468 1469 1470 1471
}

void MainWindow::connectPxActions()
{


}

void MainWindow::connectSlugsActions()
{
1472

pixhawk's avatar
pixhawk committed
1473 1474
}

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

1530 1531 1532 1533 1534 1535
void MainWindow::showSettings()
{
    QGCSettingsWidget* settings = new QGCSettingsWidget(this);
    settings->show();
}

pixhawk's avatar
pixhawk committed
1536
void MainWindow::addLink()
pixhawk's avatar
pixhawk committed
1537 1538 1539 1540
{
    SerialLink* link = new SerialLink();
    // TODO This should be only done in the dialog itself

1541
    LinkManager::instance()->add(link);
pixhawk's avatar
pixhawk committed
1542 1543
    LinkManager::instance()->addProtocol(link, mavlink);

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

1547 1548 1549 1550 1551 1552 1553 1554
    foreach (QAction* act, actions)
    {
        if (act->data().toInt() == LinkManager::instance()->getLinks().indexOf(link))
        {
            act->trigger();
            break;
        }
    }
pixhawk's avatar
pixhawk committed
1555 1556
}

pixhawk's avatar
pixhawk committed
1557 1558
void MainWindow::addLink(LinkInterface *link)
{
1559 1560 1561 1562
    // 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)
1563
    LinkManager::instance()->add(link);
1564
    LinkManager::instance()->addProtocol(link, mavlink);
1565

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

1569
    bool found = false;
1570

1571
    foreach (QAction* act, actions)
pixhawk's avatar
pixhawk committed
1572
    {
1573 1574 1575 1576 1577 1578 1579
        if (act->data().toInt() == LinkManager::instance()->getLinks().indexOf(link))
        {
            found = true;
        }
    }

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

1581
    if (!found || udp)
pixhawk's avatar
pixhawk committed
1582
    {
1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595
        CommConfigurationWindow* commWidget = new CommConfigurationWindow(link, mavlink, this);
        QAction* action = commWidget->getAction();
        ui.menuNetwork->addAction(action);

        // Error handling
        connect(link, SIGNAL(communicationError(QString,QString)), this, SLOT(showCriticalMessage(QString,QString)), Qt::QueuedConnection);
        // Special case for simulationlink
        MAVLinkSimulationLink* sim = dynamic_cast<MAVLinkSimulationLink*>(link);
        if (sim)
        {
            //connect(sim, SIGNAL(valueChanged(int,QString,double,quint64)), linechart, SLOT(appendData(int,QString,double,quint64)));
            connect(ui.actionSimulate, SIGNAL(triggered(bool)), sim, SLOT(connectLink(bool)));
        }
pixhawk's avatar
pixhawk committed
1596 1597 1598
    }
}

1599 1600 1601 1602 1603 1604 1605
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);
}

1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617
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
1618
void MainWindow::UASCreated(UASInterface* uas)
pixhawk's avatar
pixhawk committed
1619
{
1620

pixhawk's avatar
pixhawk committed
1621 1622
    // Connect the UAS to the full user interface

1623 1624
    if (uas != NULL)
    {
1625 1626 1627 1628
        // Set default settings
        setDefaultSettingsForAp();

        // The pilot, operator and engineer views were not available on startup, enable them now
1629
        ui.actionPilotsView->setEnabled(true);
1630 1631
        ui.actionOperatorsView->setEnabled(true);
        ui.actionEngineersView->setEnabled(true);
1632 1633 1634 1635 1636 1637
        // 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);
1638

1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665
        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;
        }

1666 1667 1668
        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()));
1669
        connect(uas, SIGNAL(systemSpecsChanged(int)), this, SLOT(UASSpecsChanged(int)));
1670 1671

        ui.menuConnected_Systems->addAction(uasAction);
1672 1673

        // FIXME Should be not inside the mainwindow
1674 1675
        if (debugConsoleDockWidget)
        {
pixhawk's avatar
pixhawk committed
1676 1677 1678 1679 1680 1681
            DebugConsole *debugConsole = dynamic_cast<DebugConsole*>(debugConsoleDockWidget->widget());
            if (debugConsole)
            {
                connect(uas, SIGNAL(textMessageReceived(int,int,int,QString)),
                        debugConsole, SLOT(receiveTextMessage(int,int,int,QString)));
            }
1682
        }
1683 1684

        // Health / System status indicator
1685 1686
        if (infoDockWidget)
        {
pixhawk's avatar
pixhawk committed
1687 1688 1689 1690 1691
            UASInfoWidget *infoWidget = dynamic_cast<UASInfoWidget*>(infoDockWidget->widget());
            if (infoWidget)
            {
                infoWidget->addUAS(uas);
            }
1692
        }
1693 1694

        // UAS List
1695 1696
        if (listDockWidget)
        {
pixhawk's avatar
pixhawk committed
1697 1698 1699 1700 1701
            UASListWidget *listWidget = dynamic_cast<UASListWidget*>(listDockWidget->widget());
            if (listWidget)
            {
                listWidget->addUAS(uas);
            }
1702
        }
1703

1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719
        switch (uas->getAutopilotType())
        {
        case (MAV_AUTOPILOT_SLUGS):
            {
                // Build Slugs Widgets
                buildSlugsWidgets();

                // Connect Slugs Widgets
                connectSlugsWidgets();

                // Arrange Slugs Centerstack
                arrangeSlugsCenterStack();

                // Connect Slugs Actions
                connectSlugsActions();

1720 1721 1722 1723 1724 1725 1726 1727 1728
//                if(slugsDataWidget)
//                {
//                    SlugsDataSensorView *mm = dynamic_cast<SlugsDataSensorView*>(slugsDataWidget->widget());
//                    if(mm)
//                    {
//                        mm->addUAS(uas);
//                    }
//                }

1729
                // FIXME: This type checking might be redundant
1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740
//                //            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();
//                //                }
//                //              }
//                //            }
1741

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

1801
    }
1802 1803

    if (!ui.menuConnected_Systems->isEnabled()) ui.menuConnected_Systems->setEnabled(true);
lm's avatar
lm committed
1804 1805 1806

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

1809 1810 1811
/**
 * Clears the current view completely
 */
pixhawk's avatar
pixhawk committed
1812
void MainWindow::clearView()
1813
{
1814
    // Save current state
1815
    if (UASManager::instance()->getUASList().count() > 0) settings.setValue(getWindowStateKey(), saveState(QGC::applicationVersion()));
1816
    settings.setValue(getWindowGeometryKey(), saveGeometry());
1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827

    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)
        {
1828
            //qDebug() << "TOOL:" << chKey << "IS:" << temp->isChecked();
1829 1830 1831 1832
            settings.setValue(chKey,temp->isChecked());
        }
        else
        {
1833
            //qDebug() << "TOOL:" << chKey << "IS DEFAULT AND UNCHECKED";
1834 1835 1836 1837
            settings.setValue(chKey,false);
        }
    }

1838
    changingViewsFlag = true;
1839 1840
    // Remove all dock widgets from main window
    QObjectList childList( this->children() );
pixhawk's avatar
pixhawk committed
1841

1842 1843 1844
    QObjectList::iterator i;
    QDockWidget* dockWidget;
    for (i = childList.begin(); i != childList.end(); ++i)
pixhawk's avatar
pixhawk committed
1845
    {
1846 1847
        dockWidget = dynamic_cast<QDockWidget*>(*i);
        if (dockWidget)
pixhawk's avatar
pixhawk committed
1848
        {
1849
            // Remove dock widget from main window
1850
            removeDockWidget(dockWidget);
1851
            dockWidget->hide();
1852
            //dockWidget->setVisible(false);
pixhawk's avatar
pixhawk committed
1853 1854
        }
    }
1855
    changingViewsFlag = false;
pixhawk's avatar
pixhawk committed
1856 1857
}

1858
void MainWindow::loadEngineerView()
lm's avatar
lm committed
1859
{
1860 1861
    if (currentView != VIEW_ENGINEER)
    {
1862 1863 1864 1865
        clearView();
        currentView = VIEW_ENGINEER;
        ui.actionEngineersView->setChecked(true);
        presentView();
1866
    }
lm's avatar
lm committed
1867 1868
}

1869
void MainWindow::loadOperatorView()
lm's avatar
lm committed
1870
{
1871 1872
    if (currentView != VIEW_OPERATOR)
    {
1873 1874 1875 1876 1877 1878
        clearView();
        currentView = VIEW_OPERATOR;
        ui.actionOperatorsView->setChecked(true);
        presentView();
    }
}
lm's avatar
lm committed
1879

1880 1881 1882 1883 1884 1885 1886 1887
void MainWindow::loadUnconnectedView()
{
    if (currentView != VIEW_UNCONNECTED)
    {
        clearView();
        currentView = VIEW_UNCONNECTED;
        ui.actionUnconnectedView->setChecked(true);
        presentView();
1888
    }
lm's avatar
lm committed
1889 1890
}

1891
void MainWindow::loadPilotView()
1892
{
1893 1894
    if (currentView != VIEW_PILOT)
    {
1895 1896 1897 1898
        clearView();
        currentView = VIEW_PILOT;
        ui.actionPilotsView->setChecked(true);
        presentView();
1899
    }
1900 1901
}

1902
void MainWindow::loadMAVLinkView()
1903
{
1904 1905
    if (currentView != VIEW_MAVLINK)
    {
1906 1907 1908 1909
        clearView();
        currentView = VIEW_MAVLINK;
        ui.actionMavlinkView->setChecked(true);
        presentView();
1910
    }
1911 1912
}

lm's avatar
lm committed
1913 1914
void MainWindow::presentView()
{
1915
    // LINE CHART
1916
    showTheCentralWidget(CENTRAL_LINECHART, currentView);
1917

1918 1919
    // MAP
    showTheCentralWidget(CENTRAL_MAP, currentView);
pixhawk's avatar
pixhawk committed
1920

1921 1922
    // PROTOCOL
    showTheCentralWidget(CENTRAL_PROTOCOL, currentView);
pixhawk's avatar
pixhawk committed
1923

1924 1925
    // HEAD UP DISPLAY
    showTheCentralWidget(CENTRAL_HUD, currentView);
pixhawk's avatar
pixhawk committed
1926 1927 1928 1929 1930 1931 1932 1933 1934 1935

    // GOOGLE EARTH
    showTheCentralWidget(CENTRAL_GOOGLE_EARTH, currentView);

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

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

1936 1937 1938
    // DATA PLOT
    showTheCentralWidget(CENTRAL_DATA_PLOT, currentView);

pixhawk's avatar
pixhawk committed
1939

1940
    // Show docked widgets based on current view and autopilot type
1941

1942 1943
    // UAS CONTROL
    showTheWidget(MENU_UAS_CONTROL, currentView);
1944

1945 1946
    // UAS LIST
    showTheWidget(MENU_UAS_LIST, currentView);
1947

1948 1949
    // WAYPOINT LIST
    showTheWidget(MENU_WAYPOINTS, currentView);
pixhawk's avatar
pixhawk committed
1950

1951 1952
    // UAS STATUS
    showTheWidget(MENU_STATUS, currentView);
1953

1954 1955
    // DETECTION
    showTheWidget(MENU_DETECTION, currentView);
1956

1957 1958
    // DEBUG CONSOLE
    showTheWidget(MENU_DEBUG_CONSOLE, currentView);
1959

1960 1961
    // ONBOARD PARAMETERS
    showTheWidget(MENU_PARAMETERS, currentView);
1962

1963 1964
    // WATCHDOG
    showTheWidget(MENU_WATCHDOG, currentView);
1965

1966 1967 1968 1969 1970
    // HUD
    showTheWidget(MENU_HUD, currentView);
    if (headUpDockWidget)
    {
        HUD* tmpHud = dynamic_cast<HUD*>( headUpDockWidget->widget() );
1971 1972 1973 1974
        if (tmpHud)
        {
            if (settings.value(buildMenuKey (SUB_SECTION_CHECKED,MENU_HUD,currentView)).toBool())
            {
1975
                addDockWidget(static_cast <Qt::DockWidgetArea>(settings.value(buildMenuKey (SUB_SECTION_LOCATION,MENU_HUD, currentView)).toInt()),
1976
                        headUpDockWidget);
1977
                headUpDockWidget->show();
1978 1979 1980
            }
            else
            {
1981 1982
                headUpDockWidget->hide();
            }
1983
        }
1984
    }
1985

1986

1987 1988
    // RC View
    showTheWidget(MENU_RC_VIEW, currentView);
1989

1990 1991
    // SLUGS DATA
    showTheWidget(MENU_SLUGS_DATA, currentView);
1992

1993 1994
    // SLUGS PID
    showTheWidget(MENU_SLUGS_PID, currentView);
1995

1996 1997
    // SLUGS HIL
    showTheWidget(MENU_SLUGS_HIL, currentView);
1998

1999 2000
    // SLUGS CAMERA
    showTheWidget(MENU_SLUGS_CAMERA, currentView);
2001

2002 2003
    // HORIZONTAL SITUATION INDICATOR
    showTheWidget(MENU_HSI, currentView);
2004

2005 2006 2007 2008 2009
    // HEAD DOWN 1
    showTheWidget(MENU_HDD_1, currentView);

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

2011 2012 2013
    // MAVLINK LOG PLAYER
    showTheWidget(MENU_MAVLINK_LOG_PLAYER, currentView);

2014 2015 2016 2017 2018 2019 2020
    // VIDEO 1
    showTheWidget(MENU_VIDEO_STREAM_1, currentView);

    // VIDEO 2
    showTheWidget(MENU_VIDEO_STREAM_2, currentView);

    // Restore window state
2021 2022 2023
    if (UASManager::instance()->getUASList().count() > 0)
    {
        // Restore the mainwindow size
2024 2025 2026 2027
        if (settings.contains(getWindowGeometryKey()))
        {
            restoreGeometry(settings.value(getWindowGeometryKey()).toByteArray());
        }
2028 2029 2030 2031 2032 2033 2034

        // Restore the widget positions and size
        if (settings.contains(getWindowStateKey()))
        {
            restoreState(settings.value(getWindowStateKey()).toByteArray(), QGC::applicationVersion());
        }
    }
lm's avatar
lm committed
2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046

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

        }
    }

    this->show();
2047
}
2048

2049 2050 2051 2052
void MainWindow::showTheCentralWidget (TOOLS_WIDGET_NAMES centralWidget, VIEW_SECTIONS view)
{
    bool tempVisible;
    QWidget* tempWidget = dockWidgets[centralWidget];
2053

2054
    tempVisible =  settings.value(buildMenuKey(SUB_SECTION_CHECKED,centralWidget,view), false).toBool();
2055
    //qDebug() << buildMenuKey (SUB_SECTION_CHECKED,centralWidget,view) << tempVisible;
2056
    if (toolsMenuActions[centralWidget])
2057
    {
2058
        //qDebug() << "SETTING TO:" << tempVisible;
2059
        toolsMenuActions[centralWidget]->setChecked(tempVisible);
2060
    }
2061

2062
    if (centerStack && tempWidget && tempVisible)
2063
    {
2064
        //qDebug() << "ACTIVATING MAIN WIDGET";
2065
        centerStack->setCurrentWidget(tempWidget);
2066
    }
2067 2068
}

2069 2070
void MainWindow::loadDataView(QString fileName)
{
2071
    clearView();
2072 2073 2074 2075 2076

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

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

2081
    presentView();
2082

2083 2084
    // Plot is now selected, now load data from file
    if (dataplotWidget)
2085
    {
2086
        dataplotWidget->loadFile(fileName);
2087
        }
2088 2089 2090 2091 2092 2093 2094
//        QStackedWidget *centerStack = dynamic_cast<QStackedWidget*>(centralWidget());
//        if (centerStack)
//        {
//            centerStack->setCurrentWidget(dataplotWidget);
//            dataplotWidget->loadFile(fileName);
//        }
//    }
2095 2096 2097
}