MainWindow.cc 54.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*=====================================================================

QGroundControl Open Source Ground Control Station

(c) 2009 - 2011 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>

This file is part of the QGROUNDCONTROL project

    QGROUNDCONTROL is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    QGROUNDCONTROL is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.

pixhawk's avatar
pixhawk committed
22 23 24 25
======================================================================*/

/**
 * @file
26
 *   @brief Implementation of class MainWindow
27
 *   @author Lorenz Meier <mail@qgroundcontrol.org>
pixhawk's avatar
pixhawk committed
28 29 30 31 32 33 34 35 36
 */

#include <QSettings>
#include <QDockWidget>
#include <QNetworkInterface>
#include <QMessageBox>
#include <QDebug>
#include <QTimer>
#include <QHostInfo>
lm's avatar
lm committed
37
#include <QSplashScreen>
pixhawk's avatar
pixhawk committed
38

39
#include "QGC.h"
pixhawk's avatar
pixhawk committed
40 41 42 43 44
#include "MAVLinkSimulationLink.h"
#include "SerialLink.h"
#include "UDPLink.h"
#include "MAVLinkProtocol.h"
#include "CommConfigurationWindow.h"
45
#include "QGCWaypointListMulti.h"
pixhawk's avatar
pixhawk committed
46 47
#include "MainWindow.h"
#include "JoystickWidget.h"
pixhawk's avatar
pixhawk committed
48
#include "GAudioOutput.h"
49
#include "QGCToolWidget.h"
50
#include "QGCMAVLinkLogPlayer.h"
51
#include "QGCSettingsWidget.h"
52
#include "QGCMapTool.h"
LM's avatar
LM committed
53
#include "MAVLinkDecoder.h"
Lorenz Meier's avatar
Lorenz Meier committed
54
#include "QGCMAVLinkMessageSender.h"
55
#include "QGCRGBDView.h"
Lorenz Meier's avatar
Lorenz Meier committed
56
#include "QGCFirmwareUpdate.h"
57

58
#ifdef QGC_OSG_ENABLED
59
#include "Q3DWidgetFactory.h"
60
#endif
pixhawk's avatar
pixhawk committed
61

lm's avatar
lm committed
62 63 64 65
// FIXME Move
#include "PxQuadMAV.h"
#include "SlugsMAV.h"

pixhawk's avatar
pixhawk committed
66

67
#include "LogCompressor.h"
pixhawk's avatar
pixhawk committed
68

lm's avatar
lm committed
69
MainWindow* MainWindow::instance(QSplashScreen* screen)
70
{
71
    static MainWindow* _instance = 0;
72 73
    if(_instance == 0)
    {
74
        _instance = new MainWindow();
lm's avatar
lm committed
75
        if (screen) connect(_instance, SIGNAL(initStatusChanged(QString)), screen, SLOT(showMessage(QString)));
76

77
        /* Set the application as parent to ensure that this object
78
                 * will be destroyed when the main application exits */
79 80 81
        //_instance->setParent(qApp);
    }
    return _instance;
82 83
}

pixhawk's avatar
pixhawk committed
84 85 86 87 88 89 90
/**
* 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()
**/
91
MainWindow::MainWindow(QWidget *parent):
92 93
    QMainWindow(parent),
    currentView(VIEW_UNCONNECTED),
94
    currentStyle(QGC_MAINWINDOW_STYLE_INDOOR),
95 96
    aboutToCloseFlag(false),
    changingViewsFlag(false),
97
    centerStackActionGroup(new QActionGroup(this)),
98
    styleFileName(QCoreApplication::applicationDirPath() + "/style-indoor.css"),
99
    autoReconnect(false),
100
    lowPowerMode(false)
pixhawk's avatar
pixhawk committed
101
{
lm's avatar
lm committed
102 103
    hide();
    emit initStatusChanged("Loading UI Settings..");
104
    loadSettings();
105 106
    if (!settings.contains("CURRENT_VIEW"))
    {
107 108
        // Set this view as default view
        settings.setValue("CURRENT_VIEW", currentView);
109 110 111
    }
    else
    {
112 113 114
        // LOAD THE LAST VIEW
        VIEW_SECTIONS currentViewCandidate = (VIEW_SECTIONS) settings.value("CURRENT_VIEW", currentView).toInt();
        if (currentViewCandidate != VIEW_ENGINEER &&
115
                currentViewCandidate != VIEW_OPERATOR &&
116 117 118
                currentViewCandidate != VIEW_PILOT &&
                currentViewCandidate != VIEW_FULL)
        {
119
            currentView = currentViewCandidate;
120
        }
121 122
    }

123 124
    settings.sync();

lm's avatar
lm committed
125
    emit initStatusChanged("Loading Style.");
126
    loadStyle(currentStyle);
127

lm's avatar
lm committed
128 129
    emit initStatusChanged("Setting up user interface.");

pixhawk's avatar
pixhawk committed
130 131
    // Setup user interface
    ui.setupUi(this);
lm's avatar
lm committed
132
    hide();
pixhawk's avatar
pixhawk committed
133

134 135 136 137 138 139
    // Set dock options
    setDockOptions(AnimatedDocks | AllowTabbedDocks | AllowNestedDocks);
    statusBar()->setSizeGripEnabled(true);

    configureWindowName();

140 141 142
    // Setup corners
    setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);

143
    // Setup UI state machines
144
	centerStackActionGroup->setExclusive(true);
145

146 147
    centerStack = new QStackedWidget(this);
    setCentralWidget(centerStack);
148

lm's avatar
lm committed
149 150 151 152 153 154 155 156
    // Load Toolbar
    toolBar = new QGCToolBar(this);
    this->addToolBar(toolBar);
    // Add actions
    toolBar->addPerspectiveChangeAction(ui.actionOperatorsView);
    toolBar->addPerspectiveChangeAction(ui.actionEngineersView);
    toolBar->addPerspectiveChangeAction(ui.actionPilotsView);

lm's avatar
lm committed
157 158
    emit initStatusChanged("Building common widgets.");

159 160
    buildCommonWidgets();
    connectCommonWidgets();
161

lm's avatar
lm committed
162 163
    emit initStatusChanged("Building common actions.");

164
    // Create actions
165
    connectCommonActions();
166

167
    // Populate link menu
lm's avatar
lm committed
168
    emit initStatusChanged("Populating link menu");
169
    QList<LinkInterface*> links = LinkManager::instance()->getLinks();
170 171
    foreach(LinkInterface* link, links)
    {
172 173
        this->addLink(link);
    }
174

175 176
    connect(LinkManager::instance(), SIGNAL(newLink(LinkInterface*)), this, SLOT(addLink(LinkInterface*)));

177
    // Connect user interface devices
lm's avatar
lm committed
178
    emit initStatusChanged("Initializing joystick interface.");
179 180
    joystickWidget = 0;
    joystick = new JoystickInput();
181

182
    // Connect link
183 184
    if (autoReconnect)
    {
185 186 187 188 189 190
        SerialLink* link = new SerialLink();
        // Add to registry
        LinkManager::instance()->add(link);
        LinkManager::instance()->addProtocol(link, mavlink);
        link->connect();
    }
191

192 193 194
    // Set low power mode
    enableLowPowerMode(lowPowerMode);

195 196
    // Initialize window state
    windowStateVal = windowState();
197

lm's avatar
lm committed
198 199
    emit initStatusChanged("Restoring last view state.");

200 201 202
    // Restore the window setup
    loadViewState();

lm's avatar
lm committed
203
    emit initStatusChanged("Restoring last window size.");
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
    // Restore the window position and size
    if (settings.contains(getWindowGeometryKey()))
    {
        // Restore the window geometry
        restoreGeometry(settings.value(getWindowGeometryKey()).toByteArray());
        show();
    }
    else
    {
        // Adjust the size
        const int screenWidth = QApplication::desktop()->width();
        const int screenHeight = QApplication::desktop()->height();

        if (screenWidth < 1200)
        {
            showFullScreen();
        }
        else
        {
            resize(screenWidth*0.67f, qMin(screenHeight, (int)(screenWidth*0.67f*0.67f)));
            show();
        }

    }
228 229 230

    connect(&windowNameUpdateTimer, SIGNAL(timeout()), this, SLOT(configureWindowName()));
    windowNameUpdateTimer.start(15000);
lm's avatar
lm committed
231 232
    emit initStatusChanged("Done.");
    show();
pixhawk's avatar
pixhawk committed
233 234
}

pixhawk's avatar
pixhawk committed
235
MainWindow::~MainWindow()
pixhawk's avatar
pixhawk committed
236
{
Lorenz Meier's avatar
Lorenz Meier committed
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251
    if (mavlink)
    {
        delete mavlink;
        mavlink = NULL;
    }
//    if (simulationLink)
//    {
//        simulationLink->deleteLater();
//        simulationLink = NULL;
//    }
    if (joystick)
    {
        delete joystick;
        joystick = NULL;
    }
lm's avatar
lm committed
252

253 254
    // Get and delete all dockwidgets and contained
    // widgets
Lorenz Meier's avatar
Lorenz Meier committed
255
    QObjectList childList(this->children());
256 257 258

    QObjectList::iterator i;
    QDockWidget* dockWidget;
259 260
    for (i = childList.begin(); i != childList.end(); ++i)
    {
261
        dockWidget = dynamic_cast<QDockWidget*>(*i);
262 263
        if (dockWidget)
        {
264
            // Remove dock widget from main window
265 266
            // removeDockWidget(dockWidget);
            // delete dockWidget->widget();
267
            delete dockWidget;
Lorenz Meier's avatar
Lorenz Meier committed
268
            dockWidget = NULL;
269
        }
Lorenz Meier's avatar
Lorenz Meier committed
270
        else if (dynamic_cast<QWidget*>(*i))
LM's avatar
LM committed
271
        {
Lorenz Meier's avatar
Lorenz Meier committed
272 273
            delete dynamic_cast<QWidget*>(*i);
            *i = NULL;
LM's avatar
LM committed
274
        }
275
    }
LM's avatar
LM committed
276
    // Delete all UAS objects
277 278
}

lm's avatar
lm committed
279 280
void MainWindow::resizeEvent(QResizeEvent * event)
{
281 282
    if (height() < 800)
    {
lm's avatar
lm committed
283
        ui.statusBar->setVisible(false);
284 285 286
    }
    else
    {
lm's avatar
lm committed
287
        ui.statusBar->setVisible(true);
288
        ui.statusBar->setSizeGripEnabled(true);
lm's avatar
lm committed
289
    }
290 291 292 293 294 295 296 297 298 299 300

    if (width() > 1200)
    {
        toolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
    }
    else
    {
        toolBar->setToolButtonStyle(Qt::ToolButtonIconOnly);
    }

    QMainWindow::resizeEvent(event);
lm's avatar
lm committed
301 302
}

303 304
QString MainWindow::getWindowStateKey()
{
305
    return QString::number(currentView)+"_windowstate";
306 307 308 309
}

QString MainWindow::getWindowGeometryKey()
{
310 311
    //return QString::number(currentView)+"_geometry";
    return "_geometry";
312 313
}

lm's avatar
lm committed
314 315
void MainWindow::buildCustomWidget()
{
lm's avatar
lm committed
316 317
    // Create custom widgets
    QList<QGCToolWidget*> widgets = QGCToolWidget::createWidgetsFromSettings(this);
lm's avatar
lm committed
318

lm's avatar
lm committed
319 320 321 322
    if (widgets.size() > 0)
    {
        ui.menuTools->addSeparator();
    }
lm's avatar
lm committed
323

lm's avatar
lm committed
324 325 326 327 328 329
    for(int i = 0; i < widgets.size(); ++i)
    {
        // Check if this widget already has a parent, do not create it in this case
        QGCToolWidget* tool = widgets.at(i);
        QDockWidget* dock = dynamic_cast<QDockWidget*>(tool->parentWidget());
        if (!dock)
330
        {
lm's avatar
lm committed
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
            QDockWidget* dock = new QDockWidget(tool->windowTitle(), this);
            dock->setObjectName(tool->objectName()+"_DOCK");
            dock->setWidget(tool);
            connect(tool, SIGNAL(destroyed()), dock, SLOT(deleteLater()));
            QAction* showAction = new QAction(widgets.at(i)->windowTitle(), this);
            showAction->setCheckable(true);
            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);

            // 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
346 347 348 349
        }
    }
}

350 351 352 353
void MainWindow::buildCommonWidgets()
{
    //TODO:  move protocol outside UI
    mavlink     = new MAVLinkProtocol();
354
    connect(mavlink, SIGNAL(protocolStatusMessage(QString,QString)), this, SLOT(showCriticalMessage(QString,QString)), Qt::QueuedConnection);
LM's avatar
LM committed
355 356
    // Add generic MAVLink decoder
    mavlinkDecoder = new MAVLinkDecoder(mavlink, this);
357 358

    // Dock widgets
359 360
    if (!controlDockWidget)
    {
361
        controlDockWidget = new QDockWidget(tr("Control"), this);
362
        controlDockWidget->setObjectName("UNMANNED_SYSTEM_CONTROL_DOCKWIDGET");
363
        controlDockWidget->setWidget( new UASControlWidget(this) );
364
        addTool(controlDockWidget, tr("Control"), Qt::LeftDockWidgetArea);
365
    }
366

367 368
    if (!listDockWidget)
    {
369 370
        listDockWidget = new QDockWidget(tr("Unmanned Systems"), this);
        listDockWidget->setWidget( new UASListWidget(this) );
371
        listDockWidget->setObjectName("UNMANNED_SYSTEMS_LIST_DOCKWIDGET");
372
        addTool(listDockWidget, tr("Unmanned Systems"), Qt::RightDockWidgetArea);
373
    }
374

375 376
    if (!waypointsDockWidget)
    {
377
        waypointsDockWidget = new QDockWidget(tr("Mission Plan"), this);
378
        waypointsDockWidget->setWidget( new QGCWaypointListMulti(this) );
379
        waypointsDockWidget->setObjectName("WAYPOINT_LIST_DOCKWIDGET");
380
        addTool(waypointsDockWidget, tr("Mission Plan"), Qt::BottomDockWidgetArea);
381
    }
382

383 384
    if (!infoDockWidget)
    {
385 386
        infoDockWidget = new QDockWidget(tr("Status Details"), this);
        infoDockWidget->setWidget( new UASInfoWidget(this) );
pixhawk's avatar
pixhawk committed
387
        infoDockWidget->setObjectName("UAS_STATUS_DETAILS_DOCKWIDGET");
388
        addTool(infoDockWidget, tr("Status Details"), Qt::RightDockWidgetArea);
389
    }
390

391 392
    if (!debugConsoleDockWidget)
    {
393 394
        debugConsoleDockWidget = new QDockWidget(tr("Communication Console"), this);
        debugConsoleDockWidget->setWidget( new DebugConsole(this) );
395
        debugConsoleDockWidget->setObjectName("COMMUNICATION_DEBUG_CONSOLE_DOCKWIDGET");
LM's avatar
LM committed
396 397 398 399

        DebugConsole *debugConsole = dynamic_cast<DebugConsole*>(debugConsoleDockWidget->widget());
        connect(mavlinkDecoder, SIGNAL(textMessageReceived(int, int, int, const QString)), debugConsole, SLOT(receiveTextMessage(int, int, int, const QString)));

400
        addTool(debugConsoleDockWidget, tr("Communication Console"), Qt::BottomDockWidgetArea);
401
    }
402

403 404
    if (!logPlayerDockWidget)
    {
405
        logPlayerDockWidget = new QDockWidget(tr("MAVLink Log Player"), this);
lm's avatar
lm committed
406 407 408
        logPlayer = new QGCMAVLinkLogPlayer(mavlink, this);
        toolBar->setLogPlayer(logPlayer);
        logPlayerDockWidget->setWidget(logPlayer);
409
        logPlayerDockWidget->setObjectName("MAVLINK_LOG_PLAYER_DOCKWIDGET");
410
        addTool(logPlayerDockWidget, tr("MAVLink Log Replay"), Qt::RightDockWidgetArea);
411 412
    }

lm's avatar
lm committed
413 414 415 416 417
    if (!mavlinkInspectorWidget)
    {
        mavlinkInspectorWidget = new QDockWidget(tr("MAVLink Message Inspector"), this);
        mavlinkInspectorWidget->setWidget( new QGCMAVLinkInspector(mavlink, this) );
        mavlinkInspectorWidget->setObjectName("MAVLINK_INSPECTOR_DOCKWIDGET");
lm's avatar
lm committed
418
        addTool(mavlinkInspectorWidget, tr("MAVLink Inspector"), Qt::RightDockWidgetArea);
lm's avatar
lm committed
419 420
    }

Lorenz Meier's avatar
Lorenz Meier committed
421 422
    if (!mavlinkSenderWidget)
    {
423 424 425 426
//        mavlinkSenderWidget = new QDockWidget(tr("MAVLink Message Sender"), this);
//        mavlinkSenderWidget->setWidget( new QGCMAVLinkMessageSender(mavlink, this) );
//        mavlinkSenderWidget->setObjectName("MAVLINK_SENDER_DOCKWIDGET");
//        addTool(mavlinkSenderWidget, tr("MAVLink Sender"), Qt::RightDockWidgetArea);
Lorenz Meier's avatar
Lorenz Meier committed
427 428
    }

pixhawk's avatar
pixhawk committed
429 430
    //FIXME: memory of acceptList will never be freed again
    QStringList* acceptList = new QStringList();
Lorenz Meier's avatar
Lorenz Meier committed
431 432 433
    acceptList->append("-3.3,ATTITUDE.roll,rad,+3.3,s");
    acceptList->append("-3.3,ATTITUDE.pitch,deg,+3.3,s");
    acceptList->append("-3.3,ATTITUDE.yaw,deg,+3.3,s");
434

pixhawk's avatar
pixhawk committed
435 436
    //FIXME: memory of acceptList2 will never be freed again
    QStringList* acceptList2 = new QStringList();
Lorenz Meier's avatar
Lorenz Meier committed
437
    acceptList2->append("0,RAW_PRESSURE.pres_abs,hPa,65500");
438

Lorenz Meier's avatar
Lorenz Meier committed
439 440
    if (!parametersDockWidget)
    {
441
        parametersDockWidget = new QDockWidget(tr("Onboard Parameters"), this);
lm's avatar
lm committed
442 443
        parametersDockWidget->setWidget( new ParameterInterface(this) );
        parametersDockWidget->setObjectName("PARAMETER_INTERFACE_DOCKWIDGET");
444
        addTool(parametersDockWidget, tr("Onboard Parameters"), Qt::RightDockWidgetArea);
lm's avatar
lm committed
445
    }
446
	
Lorenz Meier's avatar
Lorenz Meier committed
447 448
    if (!hsiDockWidget)
    {
lm's avatar
lm committed
449 450 451 452 453
        hsiDockWidget = new QDockWidget(tr("Horizontal Situation Indicator"), this);
        hsiDockWidget->setWidget( new HSIDisplay(this) );
        hsiDockWidget->setObjectName("HORIZONTAL_SITUATION_INDICATOR_DOCK_WIDGET");
        addTool(hsiDockWidget, tr("Horizontal Situation"), Qt::BottomDockWidgetArea);
    }
454
	
Lorenz Meier's avatar
Lorenz Meier committed
455 456
    if (!headDown1DockWidget)
    {
lm's avatar
lm committed
457
        headDown1DockWidget = new QDockWidget(tr("Flight Display"), this);
458 459 460
        HDDisplay* hdDisplay = new HDDisplay(acceptList, "Flight Display", this);
        hdDisplay->addSource(mavlinkDecoder);
        headDown1DockWidget->setWidget(hdDisplay);
lm's avatar
lm committed
461 462 463 464
        headDown1DockWidget->setObjectName("HEAD_DOWN_DISPLAY_1_DOCK_WIDGET");
        addTool(headDown1DockWidget, tr("Flight Display"), Qt::RightDockWidgetArea);
    }

Lorenz Meier's avatar
Lorenz Meier committed
465 466
    if (!headDown2DockWidget)
    {
lm's avatar
lm committed
467
        headDown2DockWidget = new QDockWidget(tr("Actuator Status"), this);
468 469 470
        HDDisplay* hdDisplay = new HDDisplay(acceptList2, "Actuator Status", this);
        hdDisplay->addSource(mavlinkDecoder);
        headDown2DockWidget->setWidget(hdDisplay);
lm's avatar
lm committed
471 472 473
        headDown2DockWidget->setObjectName("HEAD_DOWN_DISPLAY_2_DOCK_WIDGET");
        addTool(headDown2DockWidget, tr("Actuator Status"), Qt::RightDockWidgetArea);
    }
474
	
Lorenz Meier's avatar
Lorenz Meier committed
475 476
    if (!rcViewDockWidget)
    {
lm's avatar
lm committed
477 478 479 480 481 482
        rcViewDockWidget = new QDockWidget(tr("Radio Control"), this);
        rcViewDockWidget->setWidget( new QGCRemoteControlView(this) );
        rcViewDockWidget->setObjectName("RADIO_CONTROL_CHANNELS_DOCK_WIDGET");
        addTool(rcViewDockWidget, tr("Radio Control"), Qt::BottomDockWidgetArea);
    }

Lorenz Meier's avatar
Lorenz Meier committed
483 484
    if (!headUpDockWidget)
    {
lm's avatar
lm committed
485 486 487 488 489 490
        headUpDockWidget = new QDockWidget(tr("HUD"), this);
        headUpDockWidget->setWidget( new HUD(320, 240, this));
        headUpDockWidget->setObjectName("HEAD_UP_DISPLAY_DOCK_WIDGET");
        addTool(headUpDockWidget, tr("Head Up Display"), Qt::RightDockWidgetArea);
    }

Lorenz Meier's avatar
Lorenz Meier committed
491 492
    if (!video1DockWidget)
    {
lm's avatar
lm committed
493
        video1DockWidget = new QDockWidget(tr("Video Stream 1"), this);
494
        QGCRGBDView* video1 =  new QGCRGBDView(160, 120, this);
lm's avatar
lm committed
495
        video1->enableHUDInstruments(false);
496
        video1->enableVideo(false);
lm's avatar
lm committed
497 498 499 500 501 502
        // FIXME select video stream as well
        video1DockWidget->setWidget(video1);
        video1DockWidget->setObjectName("VIDEO_STREAM_1_DOCK_WIDGET");
        addTool(video1DockWidget, tr("Video Stream 1"), Qt::LeftDockWidgetArea);
    }

Lorenz Meier's avatar
Lorenz Meier committed
503 504
    if (!video2DockWidget)
    {
lm's avatar
lm committed
505
        video2DockWidget = new QDockWidget(tr("Video Stream 2"), this);
506
        QGCRGBDView* video2 =  new QGCRGBDView(160, 120, this);
lm's avatar
lm committed
507
        video2->enableHUDInstruments(false);
508
        video2->enableVideo(false);
lm's avatar
lm committed
509 510 511 512 513 514
        // FIXME select video stream as well
        video2DockWidget->setWidget(video2);
        video2DockWidget->setObjectName("VIDEO_STREAM_2_DOCK_WIDGET");
        addTool(video2DockWidget, tr("Video Stream 2"), Qt::LeftDockWidgetArea);
    }

515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536
//    if (!rgbd1DockWidget) {
//        rgbd1DockWidget = 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");
//        addTool(video1DockWidget, tr("Video Stream 1"), Qt::LeftDockWidgetArea);
//    }

//    if (!rgbd2DockWidget) {
//        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");
//        addTool(video2DockWidget, tr("Video Stream 2"), Qt::LeftDockWidgetArea);
//    }

lm's avatar
lm committed
537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552
    // Custom widgets, added last to all menus and layouts
    buildCustomWidget();

    // Center widgets
    if (!mapWidget)
    {
        mapWidget = new QGCMapTool(this);
        addCentralWidget(mapWidget, "Maps");
    }

    if (!protocolWidget)
    {
        protocolWidget    = new XMLCommProtocolWidget(this);
        addCentralWidget(protocolWidget, "Mavlink Generator");
    }

Lorenz Meier's avatar
Lorenz Meier committed
553 554 555 556 557 558
    if (!firmwareUpdateWidget)
    {
        firmwareUpdateWidget    = new QGCFirmwareUpdate(this);
        addCentralWidget(firmwareUpdateWidget, "Firmware Update");
    }

559 560
    if (!hudWidget)
    {
561
        hudWidget         = new HUD(320, 240, this);
562
        addCentralWidget(hudWidget, tr("Head Up Display"));
lm's avatar
lm committed
563 564
    }

565 566 567 568 569 570 571 572
    if (!configWidget)
    {
        configWidget = new QGCVehicleConfig(this);
        addCentralWidget(configWidget, tr("Vehicle Configuration"));
    }

    if (!dataplotWidget)
    {
573
        dataplotWidget    = new QGCDataPlot2D(this);
574
        addCentralWidget(dataplotWidget, tr("Logfile Plot"));
575
    }
576

577
#ifdef QGC_OSG_ENABLED
578 579
    if (!_3DWidget)
    {
580
        _3DWidget         = Q3DWidgetFactory::get("PIXHAWK", this);
581
        addCentralWidget(_3DWidget, tr("Local 3D"));
582
    }
583
#endif
584

585
#if (defined _MSC_VER) | (defined Q_OS_MAC)
586 587
    if (!gEarthWidget)
    {
588
        gEarthWidget = new QGCGoogleEarthView(this);
589
        addCentralWidget(gEarthWidget, tr("Google Earth"));
590
    }
591
#endif
lm's avatar
lm committed
592
}
593

594
void MainWindow::addTool(QDockWidget* widget, const QString& title, Qt::DockWidgetArea area)
lm's avatar
lm committed
595
{
596
    QAction* tempAction = ui.menuTools->addAction(title);
597

598
    tempAction->setCheckable(true);
599 600 601 602
    QVariant var;
    var.setValue((QWidget*)widget);
    tempAction->setData(var);
    connect(tempAction,SIGNAL(triggered(bool)),this, SLOT(showTool(bool)));
LM's avatar
LM committed
603 604
    connect(widget, SIGNAL(visibilityChanged(bool)), tempAction, SLOT(setChecked(bool)));
    tempAction->setChecked(widget->isVisible());
605
    addDockWidget(area, widget);
606 607 608
}


609
void MainWindow::showTool(bool show)
lm's avatar
lm committed
610
{
611 612 613
    QAction* act = qobject_cast<QAction *>(sender());
    QWidget* widget = qVariantValue<QWidget *>(act->data());
    widget->setVisible(show);
614
}
615

616
void MainWindow::addCentralWidget(QWidget* widget, const QString& title)
lm's avatar
lm committed
617
{
618 619 620 621
    // Check if this widget already has been added
    if (centerStack->indexOf(widget) == -1)
    {
        centerStack->addWidget(widget);
622

623
        QAction* tempAction = ui.menuMain->addAction(title);
624

625 626 627 628
        tempAction->setCheckable(true);
        QVariant var;
        var.setValue((QWidget*)widget);
        tempAction->setData(var);
629
        centerStackActionGroup->addAction(tempAction);
630
        connect(tempAction,SIGNAL(triggered()),this, SLOT(showCentralWidget()));
LM's avatar
LM committed
631 632
        connect(widget, SIGNAL(visibilityChanged(bool)), tempAction, SLOT(setChecked(bool)));
        tempAction->setChecked(widget->isVisible());
633 634 635 636
    }
}


637
void MainWindow::showCentralWidget()
638
{
639 640 641
    QAction* act = qobject_cast<QAction *>(sender());
    QWidget* widget = qVariantValue<QWidget *>(act->data());
    centerStack->setCurrentWidget(widget);
642 643
}

644 645
void MainWindow::closeEvent(QCloseEvent *event)
{
pixhawk's avatar
pixhawk committed
646
    if (isVisible()) storeViewState();
647
    storeSettings();
648
    aboutToCloseFlag = true;
649
    mavlink->storeSettings();
650
    UASManager::instance()->storeSettings();
651 652
    QMainWindow::closeEvent(event);
}
653 654 655 656

/**
 * Connect the signals and slots of the common window widgets
 */
657
void MainWindow::connectCommonWidgets()
658
{
Lorenz Meier's avatar
Lorenz Meier committed
659 660
    if (infoDockWidget && infoDockWidget->widget())
    {
pixhawk's avatar
pixhawk committed
661 662 663
        connect(mavlink, SIGNAL(receiveLossChanged(int, float)),
                infoDockWidget->widget(), SLOT(updateSendLoss(int, float)));
    }
664
}
665

666 667
void MainWindow::createCustomWidget()
{
668 669
    QDockWidget* dock = new QDockWidget("Unnamed Tool", this);
    QGCToolWidget* tool = new QGCToolWidget("Unnamed Tool", dock);
lm's avatar
lm committed
670

LM's avatar
LM committed
671 672
    if (QGCToolWidget::instances()->size() < 2)
    {
lm's avatar
lm committed
673 674 675 676 677
        // This is the first widget
        ui.menuTools->addSeparator();
    }

    connect(tool, SIGNAL(destroyed()), dock, SLOT(deleteLater()));
678
    dock->setWidget(tool);
679

680 681 682 683 684 685 686 687 688 689 690 691 692 693
    QAction* showAction = new QAction(tool->getTitle(), this);
    showAction->setCheckable(true);
    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);
    dock->setVisible(true);
}

void MainWindow::loadCustomWidget()
{
    QString widgetFileExtension(".qgw");
    QString fileName = QFileDialog::getOpenFileName(this, tr("Specify Widget File Name"), QDesktopServices::storageLocation(QDesktopServices::DesktopLocation), tr("QGroundControl Widget (*%1);;").arg(widgetFileExtension));
694
    if (fileName != "") loadCustomWidget(fileName);
LM's avatar
LM committed
695
}
696

LM's avatar
LM committed
697 698 699 700
void MainWindow::loadCustomWidget(const QString& fileName, bool singleinstance)
{
    QGCToolWidget* tool = new QGCToolWidget("", this);
    if (tool->loadSettings(fileName, true) || !singleinstance)
LM's avatar
LM committed
701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716
    {
        // Add widget to UI
        QDockWidget* dock = new QDockWidget(tool->getTitle(), this);
        connect(tool, SIGNAL(destroyed()), dock, SLOT(deleteLater()));
        dock->setWidget(tool);
        tool->setParent(dock);

        QAction* showAction = new QAction(tool->getTitle(), this);
        showAction->setCheckable(true);
        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);
        dock->setVisible(true);
    }
LM's avatar
LM committed
717 718 719
    else
    {
        return;
720
    }
721 722
}

LM's avatar
LM committed
723
void MainWindow::loadCustomWidgetsFromDefaults(const QString& systemType, const QString& autopilotType)
724
{
725
    QString defaultsDir = qApp->applicationDirPath() + "/files/" + autopilotType.toLower() + "/" + systemType.toLower() + "/widgets/";
726

LM's avatar
LM committed
727 728 729 730 731 732
    QDir widgets(defaultsDir);
    QStringList files = widgets.entryList();
    if (files.count() == 0)
    {
        qDebug() << "No default custom widgets for system " << systemType << "autopilot" << autopilotType << " found";
        qDebug() << "Tried with path: " << defaultsDir;
lm's avatar
lm committed
733
        showStatusMessage(tr("Did not find any custom widgets in %1").arg(defaultsDir));
734
    }
735

LM's avatar
LM committed
736 737
    // Load all custom widgets found in the AP folder
    for(int i = 0; i < files.count(); ++i)
lm's avatar
lm committed
738
    {
LM's avatar
LM committed
739 740 741 742 743
        QString file = files[i];
        if (file.endsWith(".qgw"))
        {
            // Will only be loaded if not already a custom widget with
            // the same name is present
744
            loadCustomWidget(defaultsDir+"/"+file, true);
lm's avatar
lm committed
745
            showStatusMessage(tr("Loaded custom widget %1").arg(defaultsDir+"/"+file));
LM's avatar
LM committed
746
        }
lm's avatar
lm committed
747
    }
748 749
}

750 751 752 753 754 755
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();
756
    lowPowerMode = settings.value("LOW_POWER_MODE", lowPowerMode).toBool();
757 758 759 760 761 762 763 764 765 766
    settings.endGroup();
}

void MainWindow::storeSettings()
{
    QSettings settings;
    settings.beginGroup("QGC_MAINWINDOW");
    settings.setValue("AUTO_RECONNECT", autoReconnect);
    settings.setValue("CURRENT_STYLE", currentStyle);
    settings.endGroup();
pixhawk's avatar
pixhawk committed
767 768 769 770 771 772 773 774 775 776 777
    if (!aboutToCloseFlag && isVisible())
    {
        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);
        // Save the current power mode
    }
778
    settings.setValue("LOW_POWER_MODE", lowPowerMode);
779 780 781
    settings.sync();
}

782 783
void MainWindow::configureWindowName()
{
pixhawk's avatar
pixhawk committed
784 785 786
    QList<QHostAddress> hostAddresses = QNetworkInterface::allAddresses();
    QString windowname = qApp->applicationName() + " " + qApp->applicationVersion();
    bool prevAddr = false;
787

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

790 791
    for (int i = 0; i < hostAddresses.size(); i++)
    {
pixhawk's avatar
pixhawk committed
792
        // Exclude loopback IPv4 and all IPv6 addresses
793 794
        if (hostAddresses.at(i) != QHostAddress("127.0.0.1") && !hostAddresses.at(i).toString().contains(":"))
        {
pixhawk's avatar
pixhawk committed
795 796 797 798 799
            if(prevAddr) windowname.append("/");
            windowname.append(hostAddresses.at(i).toString());
            prevAddr = true;
        }
    }
800

pixhawk's avatar
pixhawk committed
801
    windowname.append(")");
802

pixhawk's avatar
pixhawk committed
803
    setWindowTitle(windowname);
804 805

#ifndef Q_WS_MAC
pixhawk's avatar
pixhawk committed
806
    //qApp->setWindowIcon(QIcon(":/core/images/qtcreator_logo_128.png"));
807 808 809
#endif
}

pixhawk's avatar
pixhawk committed
810
void MainWindow::startVideoCapture()
pixhawk's avatar
pixhawk committed
811 812 813 814 815
{
    QString format = "bmp";
    QString initialPath = QDir::currentPath() + tr("/untitled.") + format;

    QString screenFileName = QFileDialog::getSaveFileName(this, tr("Save As"),
lm's avatar
lm committed
816 817 818 819
                                                          initialPath,
                                                          tr("%1 Files (*.%2);;All Files (*)")
                                                          .arg(format.toUpper())
                                                          .arg(format));
pixhawk's avatar
pixhawk committed
820 821
    delete videoTimer;
    videoTimer = new QTimer(this);
822 823 824
    //videoTimer->setInterval(40);
    //connect(videoTimer, SIGNAL(timeout()), this, SLOT(saveScreen()));
    //videoTimer->stop();
pixhawk's avatar
pixhawk committed
825 826
}

pixhawk's avatar
pixhawk committed
827
void MainWindow::stopVideoCapture()
pixhawk's avatar
pixhawk committed
828 829 830 831 832 833
{
    videoTimer->stop();

    // TODO Convert raw images to PNG
}

pixhawk's avatar
pixhawk committed
834
void MainWindow::saveScreen()
pixhawk's avatar
pixhawk committed
835 836 837 838
{
    QPixmap window = QPixmap::grabWindow(this->winId());
    QString format = "bmp";

839 840
    if (!screenFileName.isEmpty())
    {
pixhawk's avatar
pixhawk committed
841 842 843 844
        window.save(screenFileName, format.toAscii());
    }
}

845
void MainWindow::enableAutoReconnect(bool enabled)
pixhawk's avatar
pixhawk committed
846
{
847 848
    autoReconnect = enabled;
}
849

850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866
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)
{
867 868 869 870 871 872 873 874 875
    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."));
876
        }
877 878
    }
    break;
879
    case QGC_MAINWINDOW_STYLE_INDOOR:
880 881
	qApp->setStyle("plastique");
        styleFileName = ":files/styles/style-indoor.css";
882 883 884
        reloadStylesheet();
        break;
    case QGC_MAINWINDOW_STYLE_OUTDOOR:
885 886
	qApp->setStyle("plastique");
        styleFileName = ":files/styles/style-outdoor.css";
887 888 889 890 891 892
        reloadStylesheet();
        break;
    }
    currentStyle = style;
}

893
void MainWindow::selectStylesheet()
pixhawk's avatar
pixhawk committed
894
{
895
    // Let user select style sheet
896
    styleFileName = QFileDialog::getOpenFileName(this, tr("Specify stylesheet"), styleFileName, tr("CSS Stylesheet (*.css);;"));
897

Lorenz Meier's avatar
Lorenz Meier committed
898 899
    if (!styleFileName.endsWith(".css"))
    {
900 901 902 903 904 905 906 907 908 909
        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
910
    // Load style sheet
911 912 913 914 915 916 917
    reloadStylesheet();
}

void MainWindow::reloadStylesheet()
{
    // Load style sheet
    QFile* styleSheet = new QFile(styleFileName);
Lorenz Meier's avatar
Lorenz Meier committed
918 919
    if (!styleSheet->exists())
    {
920
        styleSheet = new QFile(":files/styles/style-indoor.css");
921
    }
Lorenz Meier's avatar
Lorenz Meier committed
922 923
    if (styleSheet->open(QIODevice::ReadOnly | QIODevice::Text))
    {
924
        QString style = QString(styleSheet->readAll());
925
        style.replace("ICONDIR", QCoreApplication::applicationDirPath()+ "files/styles/");
pixhawk's avatar
pixhawk committed
926
        qApp->setStyleSheet(style);
Lorenz Meier's avatar
Lorenz Meier committed
927 928 929
    }
    else
    {
930 931 932
        QMessageBox msgBox;
        msgBox.setIcon(QMessageBox::Information);
        msgBox.setText(tr("QGroundControl did lot load a new style"));
933
        msgBox.setInformativeText(tr("Stylesheet file %1 was not readable").arg(styleFileName));
934 935 936
        msgBox.setStandardButtons(QMessageBox::Ok);
        msgBox.setDefaultButton(QMessageBox::Ok);
        msgBox.exec();
pixhawk's avatar
pixhawk committed
937
    }
938
    delete styleSheet;
pixhawk's avatar
pixhawk committed
939 940
}

941 942 943 944 945 946
/**
 * 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
947
void MainWindow::showStatusMessage(const QString& status, int timeout)
pixhawk's avatar
pixhawk committed
948
{
lm's avatar
lm committed
949
    statusBar()->showMessage(status, timeout);
pixhawk's avatar
pixhawk committed
950 951
}

952 953 954 955 956 957
/**
 * 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
 */
958
void MainWindow::showStatusMessage(const QString& status)
pixhawk's avatar
pixhawk committed
959
{
lm's avatar
lm committed
960
    statusBar()->showMessage(status, 20000);
961 962 963 964
}

void MainWindow::showCriticalMessage(const QString& title, const QString& message)
{
965
    QMessageBox msgBox(this);
966 967 968 969 970 971
    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
972 973
}

lm's avatar
lm committed
974 975
void MainWindow::showInfoMessage(const QString& title, const QString& message)
{
976
    QMessageBox msgBox(this);
lm's avatar
lm committed
977 978 979 980 981 982 983 984
    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
985 986 987 988
/**
* @brief Create all actions associated to the main window
*
**/
989
void MainWindow::connectCommonActions()
pixhawk's avatar
pixhawk committed
990
{
991 992 993 994 995 996
    // 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);
Lorenz Meier's avatar
Lorenz Meier committed
997
    perspectives->addAction(ui.actionFirmwareUpdateView);
998 999 1000 1001 1002 1003 1004 1005
    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);
Lorenz Meier's avatar
Lorenz Meier committed
1006
    if (currentView == VIEW_FIRMWAREUPDATE) ui.actionFirmwareUpdateView->setChecked(true);
1007 1008 1009 1010 1011 1012 1013 1014 1015
    if (currentView == VIEW_UNCONNECTED) ui.actionUnconnectedView->setChecked(true);

    // 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
1016 1017 1018 1019 1020
    // 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*)));
1021
    connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)), this, SLOT(setActiveUAS(UASInterface*)));
pixhawk's avatar
pixhawk committed
1022

1023
    // Unmanned System controls
pixhawk's avatar
pixhawk committed
1024 1025 1026 1027
    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()));
1028
    connect(ui.actionShutdownMAV, SIGNAL(triggered()), UASManager::instance(), SLOT(shutdownActiveUAS()));
pixhawk's avatar
pixhawk committed
1029 1030
    connect(ui.actionConfiguration, SIGNAL(triggered()), UASManager::instance(), SLOT(configureActiveUAS()));

1031
    // Views actions
1032
    connect(ui.actionPilotsView, SIGNAL(triggered()), this, SLOT(loadPilotView()));
1033
    connect(ui.actionEngineersView, SIGNAL(triggered()), this, SLOT(loadEngineerView()));
1034
    connect(ui.actionOperatorsView, SIGNAL(triggered()), this, SLOT(loadOperatorView()));
1035
    connect(ui.actionUnconnectedView, SIGNAL(triggered()), this, SLOT(loadUnconnectedView()));
1036

Lorenz Meier's avatar
Lorenz Meier committed
1037
    connect(ui.actionFirmwareUpdateView, SIGNAL(triggered()), this, SLOT(loadFirmwareUpdateView()));
1038
    connect(ui.actionMavlinkView, SIGNAL(triggered()), this, SLOT(loadMAVLinkView()));
Lorenz Meier's avatar
Lorenz Meier committed
1039

1040 1041
    connect(ui.actionReloadStylesheet, SIGNAL(triggered()), this, SLOT(reloadStylesheet()));
    connect(ui.actionSelectStylesheet, SIGNAL(triggered()), this, SLOT(selectStylesheet()));
1042

1043
    // Help Actions
1044
    connect(ui.actionOnline_Documentation, SIGNAL(triggered()), this, SLOT(showHelp()));
1045
    connect(ui.actionDeveloper_Credits, SIGNAL(triggered()), this, SLOT(showCredits()));
1046
    connect(ui.actionProject_Roadmap_2, SIGNAL(triggered()), this, SLOT(showRoadMap()));
1047 1048 1049

    // Custom widget actions
    connect(ui.actionNewCustomWidget, SIGNAL(triggered()), this, SLOT(createCustomWidget()));
1050
    connect(ui.actionLoadCustomWidgetFile, SIGNAL(triggered()), this, SLOT(loadCustomWidget()));
1051 1052 1053

    // Audio output
    ui.actionMuteAudioOutput->setChecked(GAudioOutput::instance()->isMuted());
1054
    connect(GAudioOutput::instance(), SIGNAL(mutedChanged(bool)), ui.actionMuteAudioOutput, SLOT(setChecked(bool)));
1055
    connect(ui.actionMuteAudioOutput, SIGNAL(triggered(bool)), GAudioOutput::instance(), SLOT(mute(bool)));
1056 1057 1058 1059 1060 1061 1062

    // 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);
1063 1064 1065

    // Configuration
    // Joystick
1066
    connect(ui.actionJoystickSettings, SIGNAL(triggered()), this, SLOT(configure()));
1067 1068
    // Application Settings
    connect(ui.actionSettings, SIGNAL(triggered()), this, SLOT(showSettings()));
1069 1070
}

1071 1072
void MainWindow::showHelp()
{
Lorenz Meier's avatar
Lorenz Meier committed
1073 1074
    if(!QDesktopServices::openUrl(QUrl("http://qgroundcontrol.org/users/start")))
    {
1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086
        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()
{
Lorenz Meier's avatar
Lorenz Meier committed
1087 1088
    if(!QDesktopServices::openUrl(QUrl("http://qgroundcontrol.org/credits")))
    {
1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100
        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()
{
Lorenz Meier's avatar
Lorenz Meier committed
1101 1102
    if(!QDesktopServices::openUrl(QUrl("http://qgroundcontrol.org/dev/roadmap")))
    {
1103 1104 1105 1106 1107 1108 1109 1110 1111 1112
        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
1113
void MainWindow::configure()
pixhawk's avatar
pixhawk committed
1114
{
Lorenz Meier's avatar
Lorenz Meier committed
1115 1116 1117 1118
    if (!joystickWidget)
    {
        if (!joystick->isRunning())
        {
1119 1120 1121 1122 1123
            joystick->start();
        }
        joystickWidget = new JoystickWidget(joystick);
    }
    joystickWidget->show();
pixhawk's avatar
pixhawk committed
1124 1125
}

1126 1127 1128 1129 1130 1131
void MainWindow::showSettings()
{
    QGCSettingsWidget* settings = new QGCSettingsWidget(this);
    settings->show();
}

pixhawk's avatar
pixhawk committed
1132
void MainWindow::addLink()
pixhawk's avatar
pixhawk committed
1133 1134 1135 1136
{
    SerialLink* link = new SerialLink();
    // TODO This should be only done in the dialog itself

1137
    LinkManager::instance()->add(link);
pixhawk's avatar
pixhawk committed
1138 1139
    LinkManager::instance()->addProtocol(link, mavlink);

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

oberion's avatar
oberion committed
1143 1144
	const int32_t& linkIndex(LinkManager::instance()->getLinks().indexOf(link));
	const int32_t& linkID(LinkManager::instance()->getLinks()[linkIndex]->getId());
oberion's avatar
oberion committed
1145

Lorenz Meier's avatar
Lorenz Meier committed
1146 1147 1148 1149
    foreach (QAction* act, actions)
    {
        if (act->data().toInt() == linkID)
        { // LinkManager::instance()->getLinks().indexOf(link)
1150 1151 1152 1153
            act->trigger();
            break;
        }
    }
pixhawk's avatar
pixhawk committed
1154 1155
}

pixhawk's avatar
pixhawk committed
1156 1157
void MainWindow::addLink(LinkInterface *link)
{
1158 1159 1160 1161
    // 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)
1162
    LinkManager::instance()->add(link);
1163
    LinkManager::instance()->addProtocol(link, mavlink);
1164

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

oberion's avatar
oberion committed
1168
    bool found(false);
1169

oberion's avatar
oberion committed
1170 1171
	const int32_t& linkIndex(LinkManager::instance()->getLinks().indexOf(link));
	const int32_t& linkID(LinkManager::instance()->getLinks()[linkIndex]->getId());
1172

Lorenz Meier's avatar
Lorenz Meier committed
1173 1174 1175 1176
    foreach (QAction* act, actions)
    {
        if (act->data().toInt() == linkID)
        { // LinkManager::instance()->getLinks().indexOf(link)
1177 1178 1179 1180
            found = true;
        }
    }

oberion's avatar
oberion committed
1181
    //UDPLink* udp = dynamic_cast<UDPLink*>(link);
1182

Lorenz Meier's avatar
Lorenz Meier committed
1183 1184
    if (!found)
    {  //  || udp
1185 1186 1187 1188 1189 1190 1191 1192
        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);
1193 1194
        if (sim)
        {
1195 1196
            connect(ui.actionSimulate, SIGNAL(triggered(bool)), sim, SLOT(connectLink(bool)));
        }
pixhawk's avatar
pixhawk committed
1197 1198 1199
    }
}

1200 1201 1202 1203 1204 1205 1206
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);
}

1207 1208 1209
void MainWindow::UASSpecsChanged(int uas)
{
    UASInterface* activeUAS = UASManager::instance()->getActiveUAS();
1210 1211 1212 1213
    if (activeUAS)
    {
        if (activeUAS->getUASID() == uas)
        {
1214 1215 1216 1217 1218
            ui.menuUnmanned_System->setTitle(activeUAS->getUASName());
        }
    }
}

pixhawk's avatar
pixhawk committed
1219
void MainWindow::UASCreated(UASInterface* uas)
pixhawk's avatar
pixhawk committed
1220
{
1221

pixhawk's avatar
pixhawk committed
1222 1223
    // Connect the UAS to the full user interface

pixhawk's avatar
pixhawk committed
1224 1225
    //if (uas != NULL)
    //{
1226
        // The pilot, operator and engineer views were not available on startup, enable them now
1227
        ui.actionPilotsView->setEnabled(true);
1228 1229
        ui.actionOperatorsView->setEnabled(true);
        ui.actionEngineersView->setEnabled(true);
1230 1231 1232 1233 1234 1235
        // 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);
1236

1237 1238
        QIcon icon;
        // Set matching icon
1239 1240 1241
        switch (uas->getSystemType())
		{
        case MAV_TYPE_GENERIC:
1242
            icon = QIcon(":files/images/mavs/generic.svg");
1243
            break;
1244
        case MAV_TYPE_FIXED_WING:
1245
            icon = QIcon(":files/images/mavs/fixed-wing.svg");
1246
            break;
1247
        case MAV_TYPE_QUADROTOR:
1248
            icon = QIcon(":files/images/mavs/quadrotor.svg");
1249
            break;
1250
        case MAV_TYPE_COAXIAL:
1251
            icon = QIcon(":files/images/mavs/coaxial.svg");
1252
            break;
1253
        case MAV_TYPE_HELICOPTER:
1254
            icon = QIcon(":files/images/mavs/helicopter.svg");
1255
            break;
1256
        case MAV_TYPE_GCS:
1257
            icon = QIcon(":files/images/mavs/groundstation.svg");
1258 1259
            break;
        default:
1260
            icon = QIcon(":files/images/mavs/unknown.svg");
1261 1262 1263
            break;
        }

1264 1265 1266
        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()));
1267
        connect(uas, SIGNAL(systemSpecsChanged(int)), this, SLOT(UASSpecsChanged(int)));
1268 1269

        ui.menuConnected_Systems->addAction(uasAction);
1270 1271

        // FIXME Should be not inside the mainwindow
1272 1273
        if (debugConsoleDockWidget)
        {
pixhawk's avatar
pixhawk committed
1274
            DebugConsole *debugConsole = dynamic_cast<DebugConsole*>(debugConsoleDockWidget->widget());
1275 1276
            if (debugConsole)
            {
pixhawk's avatar
pixhawk committed
1277 1278 1279
                connect(uas, SIGNAL(textMessageReceived(int,int,int,QString)),
                        debugConsole, SLOT(receiveTextMessage(int,int,int,QString)));
            }
1280
        }
1281 1282

        // Health / System status indicator
1283 1284
        if (infoDockWidget)
        {
pixhawk's avatar
pixhawk committed
1285
            UASInfoWidget *infoWidget = dynamic_cast<UASInfoWidget*>(infoDockWidget->widget());
1286 1287
            if (infoWidget)
            {
pixhawk's avatar
pixhawk committed
1288 1289
                infoWidget->addUAS(uas);
            }
1290
        }
1291 1292

        // UAS List
lm's avatar
lm committed
1293 1294
        if (listDockWidget)
        {
pixhawk's avatar
pixhawk committed
1295
            UASListWidget *listWidget = dynamic_cast<UASListWidget*>(listDockWidget->widget());
lm's avatar
lm committed
1296 1297
            if (listWidget)
            {
pixhawk's avatar
pixhawk committed
1298 1299
                listWidget->addUAS(uas);
            }
1300
        }
1301

1302 1303
        // Line chart
        if (!linechartWidget)
lm's avatar
lm committed
1304
        {
1305
            // Center widgets
LM's avatar
LM committed
1306
            linechartWidget = new Linecharts(this);
1307
            linechartWidget->addSource(mavlinkDecoder);
1308
            addCentralWidget(linechartWidget, tr("Realtime Plot"));
1309
        }
1310

LM's avatar
LM committed
1311
        // Load default custom widgets for this autopilot type
lm's avatar
lm committed
1312
        loadCustomWidgetsFromDefaults(uas->getSystemTypeName(), uas->getAutopilotTypeName());
1313 1314


lm's avatar
lm committed
1315 1316 1317 1318 1319 1320
        if (uas->getAutopilotType() == MAV_AUTOPILOT_PIXHAWK)
        {
            // Dock widgets
            if (!detectionDockWidget)
            {
                detectionDockWidget = new QDockWidget(tr("Object Recognition"), this);
1321
                detectionDockWidget->setWidget( new ObjectDetectionView("files/images/patterns", this) );
lm's avatar
lm committed
1322 1323 1324 1325
                detectionDockWidget->setObjectName("OBJECT_DETECTION_DOCK_WIDGET");
                addTool(detectionDockWidget, tr("Object Recognition"), Qt::RightDockWidgetArea);
            }

1326 1327
            if (!watchdogControlDockWidget)
            {
lm's avatar
lm committed
1328 1329 1330 1331 1332
                watchdogControlDockWidget = new QDockWidget(tr("Process Control"), this);
                watchdogControlDockWidget->setWidget( new WatchdogControl(this) );
                watchdogControlDockWidget->setObjectName("WATCHDOG_CONTROL_DOCKWIDGET");
                addTool(watchdogControlDockWidget, tr("Process Control"), Qt::BottomDockWidgetArea);
            }
1333 1334 1335 1336 1337 1338
        }

        // 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
1339 1340
        if (UASManager::instance()->getUASList().size() == 1)
        {
1341
            // Load last view if setting is present
1342 1343
            if (settings.contains("CURRENT_VIEW_WITH_UAS_CONNECTED"))
            {
1344
                int view = settings.value("CURRENT_VIEW_WITH_UAS_CONNECTED").toInt();
Lorenz Meier's avatar
Lorenz Meier committed
1345 1346
                switch (view)
                {
1347 1348 1349 1350 1351 1352
                case VIEW_ENGINEER:
                    loadEngineerView();
                    break;
                case VIEW_MAVLINK:
                    loadMAVLinkView();
                    break;
Lorenz Meier's avatar
Lorenz Meier committed
1353 1354 1355
                case VIEW_FIRMWAREUPDATE:
                    loadFirmwareUpdateView();
                    break;
1356 1357 1358 1359 1360 1361 1362 1363 1364 1365
                case VIEW_PILOT:
                    loadPilotView();
                    break;
                case VIEW_UNCONNECTED:
                    loadUnconnectedView();
                    break;
                case VIEW_OPERATOR:
                default:
                    loadOperatorView();
                    break;
1366
                }
1367 1368 1369
            }
            else
            {
1370
                loadOperatorView();
1371
            }
1372
        }
1373

pixhawk's avatar
pixhawk committed
1374
    //}
1375 1376

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

1378 1379
    // Reload view state in case new widgets were added
    loadViewState();
pixhawk's avatar
pixhawk committed
1380 1381
}

1382
/**
1383
 * Stores the current view state
1384
 */
1385
void MainWindow::storeViewState()
1386
{
pixhawk's avatar
pixhawk committed
1387
    if (!aboutToCloseFlag)
lm's avatar
lm committed
1388
    {
pixhawk's avatar
pixhawk committed
1389 1390 1391 1392 1393 1394 1395 1396
        // Save current state
        settings.setValue(getWindowStateKey(), saveState(QGC::applicationVersion()));
        settings.setValue(getWindowStateKey()+"CENTER_WIDGET", centerStack->currentIndex());
        // 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();
        settings.setValue(getWindowGeometryKey(), saveGeometry());
1397
    }
1398
}
1399

1400 1401 1402
void MainWindow::loadViewState()
{
    // Restore center stack state
lm's avatar
lm committed
1403
    int index = settings.value(getWindowStateKey()+"CENTER_WIDGET", -1).toInt();
LM's avatar
LM committed
1404 1405 1406 1407 1408 1409
    // The offline plot view is usually the consequence of a logging run, always show the realtime view first
    if (centerStack->indexOf(dataplotWidget) == index)
    {
        // Rewrite to realtime plot
        index = centerStack->indexOf(linechartWidget);
    }
pixhawk's avatar
pixhawk committed
1410

lm's avatar
lm committed
1411 1412 1413 1414 1415 1416
    if (index != -1)
    {
        centerStack->setCurrentIndex(index);
    }
    else
    {
1417 1418 1419 1420
        // Hide custom widgets
        if (detectionDockWidget) detectionDockWidget->hide();
        if (watchdogControlDockWidget) watchdogControlDockWidget->hide();

lm's avatar
lm committed
1421 1422 1423 1424 1425
        // Load defaults
        switch (currentView)
        {
        case VIEW_ENGINEER:
            centerStack->setCurrentWidget(linechartWidget);
lm's avatar
lm committed
1426 1427 1428 1429 1430 1431 1432
            controlDockWidget->hide();
            listDockWidget->hide();
            waypointsDockWidget->hide();
            infoDockWidget->hide();
            debugConsoleDockWidget->show();
            logPlayerDockWidget->show();
            mavlinkInspectorWidget->show();
1433
            //mavlinkSenderWidget->show();
lm's avatar
lm committed
1434 1435 1436 1437 1438 1439 1440 1441
            parametersDockWidget->show();
            hsiDockWidget->hide();
            headDown1DockWidget->hide();
            headDown2DockWidget->hide();
            rcViewDockWidget->hide();
            headUpDockWidget->hide();
            video1DockWidget->hide();
            video2DockWidget->hide();
lm's avatar
lm committed
1442 1443 1444
            break;
        case VIEW_PILOT:
            centerStack->setCurrentWidget(hudWidget);
lm's avatar
lm committed
1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457
            controlDockWidget->hide();
            listDockWidget->hide();
            waypointsDockWidget->hide();
            infoDockWidget->hide();
            debugConsoleDockWidget->hide();
            logPlayerDockWidget->hide();
            mavlinkInspectorWidget->hide();
            parametersDockWidget->hide();
            hsiDockWidget->show();
            headDown1DockWidget->show();
            headDown2DockWidget->show();
            rcViewDockWidget->hide();
            headUpDockWidget->hide();
1458
            video1DockWidget->hide();
lm's avatar
lm committed
1459
            video2DockWidget->hide();
lm's avatar
lm committed
1460 1461 1462
            break;
        case VIEW_MAVLINK:
            centerStack->setCurrentWidget(protocolWidget);
lm's avatar
lm committed
1463 1464 1465 1466 1467 1468
            controlDockWidget->hide();
            listDockWidget->hide();
            waypointsDockWidget->hide();
            infoDockWidget->hide();
            debugConsoleDockWidget->hide();
            logPlayerDockWidget->hide();
Lorenz Meier's avatar
Lorenz Meier committed
1469
            mavlinkInspectorWidget->show();
1470
            //mavlinkSenderWidget->show();
Lorenz Meier's avatar
Lorenz Meier committed
1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487
            parametersDockWidget->hide();
            hsiDockWidget->hide();
            headDown1DockWidget->hide();
            headDown2DockWidget->hide();
            rcViewDockWidget->hide();
            headUpDockWidget->hide();
            video1DockWidget->hide();
            video2DockWidget->hide();
            break;
        case VIEW_FIRMWAREUPDATE:
            centerStack->setCurrentWidget(firmwareUpdateWidget);
            controlDockWidget->hide();
            listDockWidget->hide();
            waypointsDockWidget->hide();
            infoDockWidget->hide();
            debugConsoleDockWidget->hide();
            logPlayerDockWidget->hide();
lm's avatar
lm committed
1488
            mavlinkInspectorWidget->hide();
1489
            //mavlinkSenderWidget->hide();
lm's avatar
lm committed
1490 1491 1492 1493 1494 1495 1496 1497
            parametersDockWidget->hide();
            hsiDockWidget->hide();
            headDown1DockWidget->hide();
            headDown2DockWidget->hide();
            rcViewDockWidget->hide();
            headUpDockWidget->hide();
            video1DockWidget->hide();
            video2DockWidget->hide();
lm's avatar
lm committed
1498 1499
            break;
        case VIEW_OPERATOR:
1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516
            centerStack->setCurrentWidget(mapWidget);
            controlDockWidget->hide();
            listDockWidget->show();
            waypointsDockWidget->show();
            infoDockWidget->hide();
            debugConsoleDockWidget->show();
            logPlayerDockWidget->show();
            parametersDockWidget->hide();
            hsiDockWidget->show();
            headDown1DockWidget->hide();
            headDown2DockWidget->hide();
            rcViewDockWidget->hide();
            headUpDockWidget->show();
            video1DockWidget->hide();
            video2DockWidget->hide();
            mavlinkInspectorWidget->hide();
            break;
lm's avatar
lm committed
1517 1518 1519 1520
        case VIEW_UNCONNECTED:
        case VIEW_FULL:
        default:
            centerStack->setCurrentWidget(mapWidget);
1521
            controlDockWidget->hide();
lm's avatar
lm committed
1522
            listDockWidget->show();
1523 1524
            waypointsDockWidget->hide();
            infoDockWidget->hide();
lm's avatar
lm committed
1525 1526 1527
            debugConsoleDockWidget->show();
            logPlayerDockWidget->show();
            parametersDockWidget->hide();
1528
            hsiDockWidget->hide();
lm's avatar
lm committed
1529 1530 1531 1532 1533 1534
            headDown1DockWidget->hide();
            headDown2DockWidget->hide();
            rcViewDockWidget->hide();
            headUpDockWidget->show();
            video1DockWidget->hide();
            video2DockWidget->hide();
1535
            mavlinkInspectorWidget->show();
lm's avatar
lm committed
1536
            break;
pixhawk's avatar
pixhawk committed
1537 1538 1539
        }
    }

1540 1541 1542 1543
    // Restore the widget positions and size
    if (settings.contains(getWindowStateKey()))
    {
        restoreState(settings.value(getWindowStateKey()).toByteArray(), QGC::applicationVersion());
pixhawk's avatar
pixhawk committed
1544 1545 1546
    }
}

1547
void MainWindow::loadEngineerView()
lm's avatar
lm committed
1548
{
1549 1550
    if (currentView != VIEW_ENGINEER)
    {
1551
        storeViewState();
1552 1553
        currentView = VIEW_ENGINEER;
        ui.actionEngineersView->setChecked(true);
1554
        loadViewState();
1555
    }
lm's avatar
lm committed
1556 1557
}

1558
void MainWindow::loadOperatorView()
lm's avatar
lm committed
1559
{
1560 1561
    if (currentView != VIEW_OPERATOR)
    {
1562
        storeViewState();
1563 1564
        currentView = VIEW_OPERATOR;
        ui.actionOperatorsView->setChecked(true);
1565
        loadViewState();
1566 1567
    }
}
lm's avatar
lm committed
1568

1569 1570
void MainWindow::loadUnconnectedView()
{
1571 1572 1573
    if (currentView != VIEW_UNCONNECTED)
    {
        storeViewState();
1574 1575
        currentView = VIEW_UNCONNECTED;
        ui.actionUnconnectedView->setChecked(true);
1576
        loadViewState();
1577
    }
lm's avatar
lm committed
1578 1579
}

1580
void MainWindow::loadPilotView()
1581
{
1582 1583 1584
    if (currentView != VIEW_PILOT)
    {
        storeViewState();
1585 1586
        currentView = VIEW_PILOT;
        ui.actionPilotsView->setChecked(true);
1587
        loadViewState();
1588
    }
1589 1590
}

1591
void MainWindow::loadMAVLinkView()
1592
{
1593 1594 1595
    if (currentView != VIEW_MAVLINK)
    {
        storeViewState();
1596 1597
        currentView = VIEW_MAVLINK;
        ui.actionMavlinkView->setChecked(true);
1598
        loadViewState();
1599
    }
1600 1601
}

Lorenz Meier's avatar
Lorenz Meier committed
1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612
void MainWindow::loadFirmwareUpdateView()
{
    if (currentView != VIEW_FIRMWAREUPDATE)
    {
        storeViewState();
        currentView = VIEW_FIRMWAREUPDATE;
        ui.actionFirmwareUpdateView->setChecked(true);
        loadViewState();
    }
}

1613 1614
void MainWindow::loadDataView(QString fileName)
{
1615
    // Plot is now selected, now load data from file
1616 1617 1618 1619 1620 1621 1622 1623
    if (dataplotWidget)
    {
        dataplotWidget->loadFile(fileName);
    }
    QStackedWidget *centerStack = dynamic_cast<QStackedWidget*>(centralWidget());
    if (centerStack)
    {
        centerStack->setCurrentWidget(dataplotWidget);
1624
        dataplotWidget->loadFile(fileName);
1625
    }
1626 1627 1628
}


oberion's avatar
oberion committed
1629 1630
QList<QAction*> MainWindow::listLinkMenuActions(void)
{
lm's avatar
lm committed
1631
    return ui.menuNetwork->actions();
1632
}