MainWindow.cc 57.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>
38 39
#include <QGCHilLink.h>
#include <QGCHilConfiguration.h>
40
#include <QGCHilFlightGearConfiguration.h>
pixhawk's avatar
pixhawk committed
41

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

61
#ifdef QGC_OSG_ENABLED
62
#include "Q3DWidgetFactory.h"
63
#endif
pixhawk's avatar
pixhawk committed
64

lm's avatar
lm committed
65 66 67 68
// FIXME Move
#include "PxQuadMAV.h"
#include "SlugsMAV.h"

pixhawk's avatar
pixhawk committed
69

70
#include "LogCompressor.h"
pixhawk's avatar
pixhawk committed
71

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

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

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

126 127
    settings.sync();

lm's avatar
lm committed
128
    emit initStatusChanged("Loading Style.");
129
    loadStyle(currentStyle);
130

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

pixhawk's avatar
pixhawk committed
133 134
    // Setup user interface
    ui.setupUi(this);
lm's avatar
lm committed
135
    hide();
pixhawk's avatar
pixhawk committed
136

137 138 139 140 141 142
    // Set dock options
    setDockOptions(AnimatedDocks | AllowTabbedDocks | AllowNestedDocks);
    statusBar()->setSizeGripEnabled(true);

    configureWindowName();

143 144 145
    // Setup corners
    setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);

146
    // Setup UI state machines
147
	centerStackActionGroup->setExclusive(true);
148

149 150
    centerStack = new QStackedWidget(this);
    setCentralWidget(centerStack);
151

lm's avatar
lm committed
152 153 154 155 156 157 158 159
    // 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
160 161
    emit initStatusChanged("Building common widgets.");

162 163
    buildCommonWidgets();
    connectCommonWidgets();
164

lm's avatar
lm committed
165 166
    emit initStatusChanged("Building common actions.");

167
    // Create actions
168
    connectCommonActions();
169

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

178 179
    connect(LinkManager::instance(), SIGNAL(newLink(LinkInterface*)), this, SLOT(addLink(LinkInterface*)));

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

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

195 196 197
    // Set low power mode
    enableLowPowerMode(lowPowerMode);

198 199
    // Initialize window state
    windowStateVal = windowState();
200

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

203 204 205
    // Restore the window setup
    loadViewState();

lm's avatar
lm committed
206
    emit initStatusChanged("Restoring last window size.");
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
    // 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();
        }

    }
231 232 233

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

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

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

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

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

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

    QMainWindow::resizeEvent(event);
lm's avatar
lm committed
304 305
}

306 307
QString MainWindow::getWindowStateKey()
{
308
    return QString::number(currentView)+"_windowstate";
309 310 311 312
}

QString MainWindow::getWindowGeometryKey()
{
313 314
    //return QString::number(currentView)+"_geometry";
    return "_geometry";
315 316
}

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

lm's avatar
lm committed
322 323 324 325
    if (widgets.size() > 0)
    {
        ui.menuTools->addSeparator();
    }
lm's avatar
lm committed
326

lm's avatar
lm committed
327 328 329 330 331 332
    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)
333
        {
lm's avatar
lm committed
334 335 336 337 338 339 340 341 342 343 344 345 346 347 348
            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
349 350 351 352
        }
    }
}

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

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

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

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

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

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

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

403
        addTool(debugConsoleDockWidget, tr("Communication Console"), Qt::BottomDockWidgetArea);
404
    }
405

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

lm's avatar
lm committed
416 417 418 419 420
    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
421
        addTool(mavlinkInspectorWidget, tr("MAVLink Inspector"), Qt::RightDockWidgetArea);
lm's avatar
lm committed
422 423
    }

Lorenz Meier's avatar
Lorenz Meier committed
424 425
    if (!mavlinkSenderWidget)
    {
426 427 428 429
//        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
430 431
    }

pixhawk's avatar
pixhawk committed
432 433
    //FIXME: memory of acceptList will never be freed again
    QStringList* acceptList = new QStringList();
Lorenz Meier's avatar
Lorenz Meier committed
434 435 436
    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");
437

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

Lorenz Meier's avatar
Lorenz Meier committed
442 443
    if (!parametersDockWidget)
    {
444
        parametersDockWidget = new QDockWidget(tr("Onboard Parameters"), this);
lm's avatar
lm committed
445 446
        parametersDockWidget->setWidget( new ParameterInterface(this) );
        parametersDockWidget->setObjectName("PARAMETER_INTERFACE_DOCKWIDGET");
447
        addTool(parametersDockWidget, tr("Onboard Parameters"), Qt::RightDockWidgetArea);
lm's avatar
lm committed
448
    }
449
	
Lorenz Meier's avatar
Lorenz Meier committed
450 451
    if (!hsiDockWidget)
    {
lm's avatar
lm committed
452 453 454 455 456
        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);
    }
457
	
Lorenz Meier's avatar
Lorenz Meier committed
458 459
    if (!headDown1DockWidget)
    {
lm's avatar
lm committed
460
        headDown1DockWidget = new QDockWidget(tr("Flight Display"), this);
461 462 463
        HDDisplay* hdDisplay = new HDDisplay(acceptList, "Flight Display", this);
        hdDisplay->addSource(mavlinkDecoder);
        headDown1DockWidget->setWidget(hdDisplay);
lm's avatar
lm committed
464 465 466 467
        headDown1DockWidget->setObjectName("HEAD_DOWN_DISPLAY_1_DOCK_WIDGET");
        addTool(headDown1DockWidget, tr("Flight Display"), Qt::RightDockWidgetArea);
    }

Lorenz Meier's avatar
Lorenz Meier committed
468 469
    if (!headDown2DockWidget)
    {
lm's avatar
lm committed
470
        headDown2DockWidget = new QDockWidget(tr("Actuator Status"), this);
471 472 473
        HDDisplay* hdDisplay = new HDDisplay(acceptList2, "Actuator Status", this);
        hdDisplay->addSource(mavlinkDecoder);
        headDown2DockWidget->setWidget(hdDisplay);
lm's avatar
lm committed
474 475 476
        headDown2DockWidget->setObjectName("HEAD_DOWN_DISPLAY_2_DOCK_WIDGET");
        addTool(headDown2DockWidget, tr("Actuator Status"), Qt::RightDockWidgetArea);
    }
477
	
Lorenz Meier's avatar
Lorenz Meier committed
478 479
    if (!rcViewDockWidget)
    {
lm's avatar
lm committed
480 481 482 483 484 485
        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
486 487
    if (!headUpDockWidget)
    {
lm's avatar
lm committed
488 489 490 491 492 493
        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
494 495
    if (!video1DockWidget)
    {
lm's avatar
lm committed
496
        video1DockWidget = new QDockWidget(tr("Video Stream 1"), this);
497
        QGCRGBDView* video1 =  new QGCRGBDView(160, 120, this);
lm's avatar
lm committed
498
        video1->enableHUDInstruments(false);
499
        video1->enableVideo(false);
lm's avatar
lm committed
500 501 502 503 504 505
        // 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
506 507
    if (!video2DockWidget)
    {
lm's avatar
lm committed
508
        video2DockWidget = new QDockWidget(tr("Video Stream 2"), this);
509
        QGCRGBDView* video2 =  new QGCRGBDView(160, 120, this);
lm's avatar
lm committed
510
        video2->enableHUDInstruments(false);
511
        video2->enableVideo(false);
lm's avatar
lm committed
512 513 514 515 516 517
        // FIXME select video stream as well
        video2DockWidget->setWidget(video2);
        video2DockWidget->setObjectName("VIDEO_STREAM_2_DOCK_WIDGET");
        addTool(video2DockWidget, tr("Video Stream 2"), Qt::LeftDockWidgetArea);
    }

518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539
//    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
540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555
    // 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");
    }

556 557 558 559 560
//    if (!firmwareUpdateWidget)
//    {
//        firmwareUpdateWidget    = new QGCFirmwareUpdate(this);
//        addCentralWidget(firmwareUpdateWidget, "Firmware Update");
//    }
Lorenz Meier's avatar
Lorenz Meier committed
561

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

568 569 570 571 572
    if (!configWidget)
    {
        configWidget = new QGCVehicleConfig(this);
        addCentralWidget(configWidget, tr("Vehicle Configuration"));
    }
573 574 575

    if (!dataplotWidget)
    {
576
        dataplotWidget    = new QGCDataPlot2D(this);
577
        addCentralWidget(dataplotWidget, tr("Logfile Plot"));
578
    }
579

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

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

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

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


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

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

626
        QAction* tempAction = ui.menuMain->addAction(title);
627

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


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

647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666
void MainWindow::showHILConfigurationWidget(UASInterface* uas)
{
    // Add simulation configuration widget
    UAS* mav = dynamic_cast<UAS*>(uas);

    if (mav)
    {
        QGCHilConfiguration* hconf = new QGCHilConfiguration(mav, this);
        QString hilDockName = tr("HIL Config (%1)").arg(uas->getUASName());
        QDockWidget* hilDock = new QDockWidget(hilDockName, this);
        hilDock->setWidget(hconf);
        hilDock->setObjectName(QString("HIL_CONFIG_%1").arg(uas->getUASID()));
        addTool(hilDock, hilDockName, Qt::RightDockWidgetArea);

    }

    // Reload view state in case new widgets were added
    loadViewState();
}

667 668
void MainWindow::closeEvent(QCloseEvent *event)
{
pixhawk's avatar
pixhawk committed
669
    if (isVisible()) storeViewState();
670
    storeSettings();
671
    aboutToCloseFlag = true;
672
    mavlink->storeSettings();
673
    UASManager::instance()->storeSettings();
674 675
    QMainWindow::closeEvent(event);
}
676 677 678 679

/**
 * Connect the signals and slots of the common window widgets
 */
680
void MainWindow::connectCommonWidgets()
681
{
Lorenz Meier's avatar
Lorenz Meier committed
682 683
    if (infoDockWidget && infoDockWidget->widget())
    {
pixhawk's avatar
pixhawk committed
684 685 686
        connect(mavlink, SIGNAL(receiveLossChanged(int, float)),
                infoDockWidget->widget(), SLOT(updateSendLoss(int, float)));
    }
687
}
688

689 690
void MainWindow::createCustomWidget()
{
691 692
    QDockWidget* dock = new QDockWidget("Unnamed Tool", this);
    QGCToolWidget* tool = new QGCToolWidget("Unnamed Tool", dock);
lm's avatar
lm committed
693

LM's avatar
LM committed
694 695
    if (QGCToolWidget::instances()->size() < 2)
    {
lm's avatar
lm committed
696 697 698 699 700
        // This is the first widget
        ui.menuTools->addSeparator();
    }

    connect(tool, SIGNAL(destroyed()), dock, SLOT(deleteLater()));
701
    dock->setWidget(tool);
702

703 704 705 706 707 708 709 710 711 712 713 714 715 716
    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));
717
    if (fileName != "") loadCustomWidget(fileName);
LM's avatar
LM committed
718
}
719

LM's avatar
LM committed
720 721 722 723
void MainWindow::loadCustomWidget(const QString& fileName, bool singleinstance)
{
    QGCToolWidget* tool = new QGCToolWidget("", this);
    if (tool->loadSettings(fileName, true) || !singleinstance)
LM's avatar
LM committed
724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739
    {
        // 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
740 741 742
    else
    {
        return;
743
    }
744 745
}

LM's avatar
LM committed
746
void MainWindow::loadCustomWidgetsFromDefaults(const QString& systemType, const QString& autopilotType)
747
{
748 749
    QString defaultsDir = qApp->applicationDirPath() + "/files/" + autopilotType.toLower() + "/widgets/";
    QString platformDir = qApp->applicationDirPath() + "/files/" + autopilotType.toLower() + "/" + systemType.toLower() + "/widgets/";
750

LM's avatar
LM committed
751 752
    QDir widgets(defaultsDir);
    QStringList files = widgets.entryList();
753 754 755
    QDir platformWidgets(platformDir);
    files.append(platformWidgets.entryList());

LM's avatar
LM committed
756 757 758 759
    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
760
        showStatusMessage(tr("Did not find any custom widgets in %1").arg(defaultsDir));
761
    }
762

LM's avatar
LM committed
763 764
    // Load all custom widgets found in the AP folder
    for(int i = 0; i < files.count(); ++i)
lm's avatar
lm committed
765
    {
LM's avatar
LM committed
766 767 768 769 770
        QString file = files[i];
        if (file.endsWith(".qgw"))
        {
            // Will only be loaded if not already a custom widget with
            // the same name is present
771
            loadCustomWidget(defaultsDir+"/"+file, true);
lm's avatar
lm committed
772
            showStatusMessage(tr("Loaded custom widget %1").arg(defaultsDir+"/"+file));
LM's avatar
LM committed
773
        }
lm's avatar
lm committed
774
    }
775 776
}

777 778 779 780 781 782
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();
783
    lowPowerMode = settings.value("LOW_POWER_MODE", lowPowerMode).toBool();
784 785 786 787 788 789 790 791 792 793
    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
794 795 796 797 798 799 800 801 802 803 804
    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
    }
805
    settings.setValue("LOW_POWER_MODE", lowPowerMode);
806 807 808
    settings.sync();
}

809 810
void MainWindow::configureWindowName()
{
pixhawk's avatar
pixhawk committed
811 812 813
    QList<QHostAddress> hostAddresses = QNetworkInterface::allAddresses();
    QString windowname = qApp->applicationName() + " " + qApp->applicationVersion();
    bool prevAddr = false;
814

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

817 818
    for (int i = 0; i < hostAddresses.size(); i++)
    {
pixhawk's avatar
pixhawk committed
819
        // Exclude loopback IPv4 and all IPv6 addresses
820 821
        if (hostAddresses.at(i) != QHostAddress("127.0.0.1") && !hostAddresses.at(i).toString().contains(":"))
        {
pixhawk's avatar
pixhawk committed
822 823 824 825 826
            if(prevAddr) windowname.append("/");
            windowname.append(hostAddresses.at(i).toString());
            prevAddr = true;
        }
    }
827

pixhawk's avatar
pixhawk committed
828
    windowname.append(")");
829

pixhawk's avatar
pixhawk committed
830
    setWindowTitle(windowname);
831 832

#ifndef Q_WS_MAC
pixhawk's avatar
pixhawk committed
833
    //qApp->setWindowIcon(QIcon(":/core/images/qtcreator_logo_128.png"));
834 835 836
#endif
}

pixhawk's avatar
pixhawk committed
837
void MainWindow::startVideoCapture()
pixhawk's avatar
pixhawk committed
838 839 840 841 842
{
    QString format = "bmp";
    QString initialPath = QDir::currentPath() + tr("/untitled.") + format;

    QString screenFileName = QFileDialog::getSaveFileName(this, tr("Save As"),
lm's avatar
lm committed
843 844 845 846
                                                          initialPath,
                                                          tr("%1 Files (*.%2);;All Files (*)")
                                                          .arg(format.toUpper())
                                                          .arg(format));
pixhawk's avatar
pixhawk committed
847 848
    delete videoTimer;
    videoTimer = new QTimer(this);
849 850 851
    //videoTimer->setInterval(40);
    //connect(videoTimer, SIGNAL(timeout()), this, SLOT(saveScreen()));
    //videoTimer->stop();
pixhawk's avatar
pixhawk committed
852 853
}

pixhawk's avatar
pixhawk committed
854
void MainWindow::stopVideoCapture()
pixhawk's avatar
pixhawk committed
855 856 857 858 859 860
{
    videoTimer->stop();

    // TODO Convert raw images to PNG
}

pixhawk's avatar
pixhawk committed
861
void MainWindow::saveScreen()
pixhawk's avatar
pixhawk committed
862 863 864 865
{
    QPixmap window = QPixmap::grabWindow(this->winId());
    QString format = "bmp";

866 867
    if (!screenFileName.isEmpty())
    {
pixhawk's avatar
pixhawk committed
868 869 870 871
        window.save(screenFileName, format.toAscii());
    }
}

872
void MainWindow::enableAutoReconnect(bool enabled)
pixhawk's avatar
pixhawk committed
873
{
874 875
    autoReconnect = enabled;
}
876

877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893
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)
{
894 895 896 897 898 899 900 901 902
    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."));
903
        }
904 905
    }
    break;
906
    case QGC_MAINWINDOW_STYLE_INDOOR:
907 908
	qApp->setStyle("plastique");
        styleFileName = ":files/styles/style-indoor.css";
909 910 911
        reloadStylesheet();
        break;
    case QGC_MAINWINDOW_STYLE_OUTDOOR:
912 913
	qApp->setStyle("plastique");
        styleFileName = ":files/styles/style-outdoor.css";
914 915 916 917 918 919
        reloadStylesheet();
        break;
    }
    currentStyle = style;
}

920
void MainWindow::selectStylesheet()
pixhawk's avatar
pixhawk committed
921
{
922
    // Let user select style sheet
923
    styleFileName = QFileDialog::getOpenFileName(this, tr("Specify stylesheet"), styleFileName, tr("CSS Stylesheet (*.css);;"));
924

Lorenz Meier's avatar
Lorenz Meier committed
925 926
    if (!styleFileName.endsWith(".css"))
    {
927 928 929 930 931 932 933 934 935 936
        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
937
    // Load style sheet
938 939 940 941 942 943 944
    reloadStylesheet();
}

void MainWindow::reloadStylesheet()
{
    // Load style sheet
    QFile* styleSheet = new QFile(styleFileName);
Lorenz Meier's avatar
Lorenz Meier committed
945 946
    if (!styleSheet->exists())
    {
947
        styleSheet = new QFile(":files/styles/style-indoor.css");
948
    }
Lorenz Meier's avatar
Lorenz Meier committed
949 950
    if (styleSheet->open(QIODevice::ReadOnly | QIODevice::Text))
    {
951
        QString style = QString(styleSheet->readAll());
952
        style.replace("ICONDIR", QCoreApplication::applicationDirPath()+ "files/styles/");
pixhawk's avatar
pixhawk committed
953
        qApp->setStyleSheet(style);
Lorenz Meier's avatar
Lorenz Meier committed
954 955 956
    }
    else
    {
957 958 959
        QMessageBox msgBox;
        msgBox.setIcon(QMessageBox::Information);
        msgBox.setText(tr("QGroundControl did lot load a new style"));
960
        msgBox.setInformativeText(tr("Stylesheet file %1 was not readable").arg(styleFileName));
961 962 963
        msgBox.setStandardButtons(QMessageBox::Ok);
        msgBox.setDefaultButton(QMessageBox::Ok);
        msgBox.exec();
pixhawk's avatar
pixhawk committed
964
    }
965
    delete styleSheet;
pixhawk's avatar
pixhawk committed
966 967
}

968 969 970 971 972 973
/**
 * 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
974
void MainWindow::showStatusMessage(const QString& status, int timeout)
pixhawk's avatar
pixhawk committed
975
{
lm's avatar
lm committed
976
    statusBar()->showMessage(status, timeout);
pixhawk's avatar
pixhawk committed
977 978
}

979 980 981 982 983 984
/**
 * 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
 */
985
void MainWindow::showStatusMessage(const QString& status)
pixhawk's avatar
pixhawk committed
986
{
lm's avatar
lm committed
987
    statusBar()->showMessage(status, 20000);
988 989 990 991
}

void MainWindow::showCriticalMessage(const QString& title, const QString& message)
{
992
    QMessageBox msgBox(this);
993 994 995 996 997 998
    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
999 1000
}

lm's avatar
lm committed
1001 1002
void MainWindow::showInfoMessage(const QString& title, const QString& message)
{
1003
    QMessageBox msgBox(this);
lm's avatar
lm committed
1004 1005 1006 1007 1008 1009 1010 1011
    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
1012 1013 1014 1015
/**
* @brief Create all actions associated to the main window
*
**/
1016
void MainWindow::connectCommonActions()
pixhawk's avatar
pixhawk committed
1017
{
1018 1019 1020 1021 1022 1023
    // 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
1024
    perspectives->addAction(ui.actionFirmwareUpdateView);
1025 1026 1027 1028 1029 1030 1031 1032
    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
1033
    if (currentView == VIEW_FIRMWAREUPDATE) ui.actionFirmwareUpdateView->setChecked(true);
1034 1035 1036 1037 1038 1039 1040 1041 1042
    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
1043 1044 1045 1046 1047
    // 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*)));
1048
    connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)), this, SLOT(setActiveUAS(UASInterface*)));
pixhawk's avatar
pixhawk committed
1049

1050
    // Unmanned System controls
pixhawk's avatar
pixhawk committed
1051 1052 1053 1054
    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()));
1055
    connect(ui.actionShutdownMAV, SIGNAL(triggered()), UASManager::instance(), SLOT(shutdownActiveUAS()));
pixhawk's avatar
pixhawk committed
1056 1057
    connect(ui.actionConfiguration, SIGNAL(triggered()), UASManager::instance(), SLOT(configureActiveUAS()));

1058
    // Views actions
1059
    connect(ui.actionPilotsView, SIGNAL(triggered()), this, SLOT(loadPilotView()));
1060
    connect(ui.actionEngineersView, SIGNAL(triggered()), this, SLOT(loadEngineerView()));
1061
    connect(ui.actionOperatorsView, SIGNAL(triggered()), this, SLOT(loadOperatorView()));
1062
    connect(ui.actionUnconnectedView, SIGNAL(triggered()), this, SLOT(loadUnconnectedView()));
1063

Lorenz Meier's avatar
Lorenz Meier committed
1064
    connect(ui.actionFirmwareUpdateView, SIGNAL(triggered()), this, SLOT(loadFirmwareUpdateView()));
1065
    connect(ui.actionMavlinkView, SIGNAL(triggered()), this, SLOT(loadMAVLinkView()));
Lorenz Meier's avatar
Lorenz Meier committed
1066

1067 1068
    connect(ui.actionReloadStylesheet, SIGNAL(triggered()), this, SLOT(reloadStylesheet()));
    connect(ui.actionSelectStylesheet, SIGNAL(triggered()), this, SLOT(selectStylesheet()));
1069

1070
    // Help Actions
1071
    connect(ui.actionOnline_Documentation, SIGNAL(triggered()), this, SLOT(showHelp()));
1072
    connect(ui.actionDeveloper_Credits, SIGNAL(triggered()), this, SLOT(showCredits()));
1073
    connect(ui.actionProject_Roadmap_2, SIGNAL(triggered()), this, SLOT(showRoadMap()));
1074 1075 1076

    // Custom widget actions
    connect(ui.actionNewCustomWidget, SIGNAL(triggered()), this, SLOT(createCustomWidget()));
1077
    connect(ui.actionLoadCustomWidgetFile, SIGNAL(triggered()), this, SLOT(loadCustomWidget()));
1078 1079 1080

    // Audio output
    ui.actionMuteAudioOutput->setChecked(GAudioOutput::instance()->isMuted());
1081
    connect(GAudioOutput::instance(), SIGNAL(mutedChanged(bool)), ui.actionMuteAudioOutput, SLOT(setChecked(bool)));
1082
    connect(ui.actionMuteAudioOutput, SIGNAL(triggered(bool)), GAudioOutput::instance(), SLOT(mute(bool)));
1083 1084 1085 1086 1087 1088 1089

    // 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);
1090 1091 1092

    // Configuration
    // Joystick
1093
    connect(ui.actionJoystickSettings, SIGNAL(triggered()), this, SLOT(configure()));
1094 1095
    // Application Settings
    connect(ui.actionSettings, SIGNAL(triggered()), this, SLOT(showSettings()));
1096 1097
}

1098 1099
void MainWindow::showHelp()
{
Lorenz Meier's avatar
Lorenz Meier committed
1100 1101
    if(!QDesktopServices::openUrl(QUrl("http://qgroundcontrol.org/users/start")))
    {
1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113
        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
1114 1115
    if(!QDesktopServices::openUrl(QUrl("http://qgroundcontrol.org/credits")))
    {
1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127
        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
1128 1129
    if(!QDesktopServices::openUrl(QUrl("http://qgroundcontrol.org/dev/roadmap")))
    {
1130 1131 1132 1133 1134 1135 1136 1137 1138 1139
        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
1140
void MainWindow::configure()
pixhawk's avatar
pixhawk committed
1141
{
Lorenz Meier's avatar
Lorenz Meier committed
1142 1143 1144 1145
    if (!joystickWidget)
    {
        if (!joystick->isRunning())
        {
1146 1147 1148 1149 1150
            joystick->start();
        }
        joystickWidget = new JoystickWidget(joystick);
    }
    joystickWidget->show();
pixhawk's avatar
pixhawk committed
1151 1152
}

1153 1154 1155 1156 1157 1158
void MainWindow::showSettings()
{
    QGCSettingsWidget* settings = new QGCSettingsWidget(this);
    settings->show();
}

pixhawk's avatar
pixhawk committed
1159
void MainWindow::addLink()
pixhawk's avatar
pixhawk committed
1160 1161 1162 1163
{
    SerialLink* link = new SerialLink();
    // TODO This should be only done in the dialog itself

1164
    LinkManager::instance()->add(link);
pixhawk's avatar
pixhawk committed
1165 1166
    LinkManager::instance()->addProtocol(link, mavlink);

1167 1168
    // Go fishing for this link's configuration window
    QList<QAction*> actions = ui.menuNetwork->actions();
pixhawk's avatar
pixhawk committed
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());
oberion's avatar
oberion committed
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
            act->trigger();
            break;
        }
    }
pixhawk's avatar
pixhawk committed
1181 1182
}

pixhawk's avatar
pixhawk committed
1183 1184
void MainWindow::addLink(LinkInterface *link)
{
1185 1186 1187 1188
    // 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)
1189
    LinkManager::instance()->add(link);
1190
    LinkManager::instance()->addProtocol(link, mavlink);
1191

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

oberion's avatar
oberion committed
1195
    bool found(false);
1196

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

Lorenz Meier's avatar
Lorenz Meier committed
1200 1201 1202 1203
    foreach (QAction* act, actions)
    {
        if (act->data().toInt() == linkID)
        { // LinkManager::instance()->getLinks().indexOf(link)
1204 1205 1206 1207
            found = true;
        }
    }

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

Lorenz Meier's avatar
Lorenz Meier committed
1210 1211
    if (!found)
    {  //  || udp
1212 1213 1214 1215 1216 1217 1218 1219
        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);
1220 1221
        if (sim)
        {
1222 1223
            connect(ui.actionSimulate, SIGNAL(triggered(bool)), sim, SLOT(connectLink(bool)));
        }
pixhawk's avatar
pixhawk committed
1224 1225 1226
    }
}

1227 1228 1229 1230 1231 1232 1233
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);
}

1234 1235 1236
void MainWindow::UASSpecsChanged(int uas)
{
    UASInterface* activeUAS = UASManager::instance()->getActiveUAS();
1237 1238 1239 1240
    if (activeUAS)
    {
        if (activeUAS->getUASID() == uas)
        {
1241 1242 1243
            ui.menuUnmanned_System->setTitle(activeUAS->getUASName());
        }
    }
1244 1245 1246 1247 1248 1249
    else
    {
        // Last system deleted
        ui.menuUnmanned_System->setTitle(tr("No System"));
        ui.menuUnmanned_System->setEnabled(false);
    }
1250 1251
}

pixhawk's avatar
pixhawk committed
1252
void MainWindow::UASCreated(UASInterface* uas)
pixhawk's avatar
pixhawk committed
1253
{
1254

pixhawk's avatar
pixhawk committed
1255 1256
    // Connect the UAS to the full user interface

pixhawk's avatar
pixhawk committed
1257 1258
    //if (uas != NULL)
    //{
1259
        // The pilot, operator and engineer views were not available on startup, enable them now
1260
        ui.actionPilotsView->setEnabled(true);
1261 1262
        ui.actionOperatorsView->setEnabled(true);
        ui.actionEngineersView->setEnabled(true);
1263 1264 1265 1266 1267 1268
        // 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);
1269

1270 1271
        QIcon icon;
        // Set matching icon
1272 1273 1274
        switch (uas->getSystemType())
		{
        case MAV_TYPE_GENERIC:
1275
            icon = QIcon(":files/images/mavs/generic.svg");
1276
            break;
1277
        case MAV_TYPE_FIXED_WING:
1278
            icon = QIcon(":files/images/mavs/fixed-wing.svg");
1279
            break;
1280
        case MAV_TYPE_QUADROTOR:
1281
            icon = QIcon(":files/images/mavs/quadrotor.svg");
1282
            break;
1283
        case MAV_TYPE_COAXIAL:
1284
            icon = QIcon(":files/images/mavs/coaxial.svg");
1285
            break;
1286
        case MAV_TYPE_HELICOPTER:
1287
            icon = QIcon(":files/images/mavs/helicopter.svg");
1288
            break;
1289 1290 1291
        case MAV_TYPE_ANTENNA_TRACKER:
            icon = QIcon(":files/images/mavs/antenna-tracker.svg");
            break;
1292
        case MAV_TYPE_GCS:
1293
            icon = QIcon(":files/images/mavs/groundstation.svg");
1294
            break;
1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327
        case MAV_TYPE_AIRSHIP:
            icon = QIcon(":files/images/mavs/airship.svg");
            break;
        case MAV_TYPE_FREE_BALLOON:
            icon = QIcon(":files/images/mavs/free-balloon.svg");
            break;
        case MAV_TYPE_ROCKET:
            icon = QIcon(":files/images/mavs/rocket.svg");
            break;
        case MAV_TYPE_GROUND_ROVER:
            icon = QIcon(":files/images/mavs/ground-rover.svg");
            break;
        case MAV_TYPE_SURFACE_BOAT:
            icon = QIcon(":files/images/mavs/surface-boat.svg");
            break;
        case MAV_TYPE_SUBMARINE:
            icon = QIcon(":files/images/mavs/submarine.svg");
            break;
        case MAV_TYPE_HEXAROTOR:
            icon = QIcon(":files/images/mavs/hexarotor.svg");
            break;
        case MAV_TYPE_OCTOROTOR:
            icon = QIcon(":files/images/mavs/octorotor.svg");
            break;
        case MAV_TYPE_TRICOPTER:
            icon = QIcon(":files/images/mavs/tricopter.svg");
            break;
        case MAV_TYPE_FLAPPING_WING:
            icon = QIcon(":files/images/mavs/flapping-wing.svg");
            break;
        case MAV_TYPE_KITE:
            icon = QIcon(":files/images/mavs/kite.svg");
            break;
1328
        default:
1329
            icon = QIcon(":files/images/mavs/unknown.svg");
1330 1331 1332
            break;
        }

1333 1334 1335
        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()));
1336
        connect(uas, SIGNAL(systemSpecsChanged(int)), this, SLOT(UASSpecsChanged(int)));
1337 1338

        ui.menuConnected_Systems->addAction(uasAction);
1339 1340

        // FIXME Should be not inside the mainwindow
1341 1342
        if (debugConsoleDockWidget)
        {
pixhawk's avatar
pixhawk committed
1343
            DebugConsole *debugConsole = dynamic_cast<DebugConsole*>(debugConsoleDockWidget->widget());
1344 1345
            if (debugConsole)
            {
pixhawk's avatar
pixhawk committed
1346 1347 1348
                connect(uas, SIGNAL(textMessageReceived(int,int,int,QString)),
                        debugConsole, SLOT(receiveTextMessage(int,int,int,QString)));
            }
1349
        }
1350 1351

        // Health / System status indicator
1352 1353
        if (infoDockWidget)
        {
pixhawk's avatar
pixhawk committed
1354
            UASInfoWidget *infoWidget = dynamic_cast<UASInfoWidget*>(infoDockWidget->widget());
1355 1356
            if (infoWidget)
            {
pixhawk's avatar
pixhawk committed
1357 1358
                infoWidget->addUAS(uas);
            }
1359
        }
1360 1361

        // UAS List
lm's avatar
lm committed
1362 1363
        if (listDockWidget)
        {
pixhawk's avatar
pixhawk committed
1364
            UASListWidget *listWidget = dynamic_cast<UASListWidget*>(listDockWidget->widget());
lm's avatar
lm committed
1365 1366
            if (listWidget)
            {
pixhawk's avatar
pixhawk committed
1367 1368
                listWidget->addUAS(uas);
            }
1369
        }
1370

1371 1372
        // Line chart
        if (!linechartWidget)
lm's avatar
lm committed
1373
        {
1374
            // Center widgets
LM's avatar
LM committed
1375
            linechartWidget = new Linecharts(this);
1376
            linechartWidget->addSource(mavlinkDecoder);
1377
            addCentralWidget(linechartWidget, tr("Realtime Plot"));
1378
        }
1379

LM's avatar
LM committed
1380
        // Load default custom widgets for this autopilot type
lm's avatar
lm committed
1381
        loadCustomWidgetsFromDefaults(uas->getSystemTypeName(), uas->getAutopilotTypeName());
1382 1383


lm's avatar
lm committed
1384 1385 1386 1387 1388 1389
        if (uas->getAutopilotType() == MAV_AUTOPILOT_PIXHAWK)
        {
            // Dock widgets
            if (!detectionDockWidget)
            {
                detectionDockWidget = new QDockWidget(tr("Object Recognition"), this);
1390
                detectionDockWidget->setWidget( new ObjectDetectionView("files/images/patterns", this) );
lm's avatar
lm committed
1391 1392 1393 1394
                detectionDockWidget->setObjectName("OBJECT_DETECTION_DOCK_WIDGET");
                addTool(detectionDockWidget, tr("Object Recognition"), Qt::RightDockWidgetArea);
            }

1395 1396
            if (!watchdogControlDockWidget)
            {
lm's avatar
lm committed
1397 1398 1399 1400 1401
                watchdogControlDockWidget = new QDockWidget(tr("Process Control"), this);
                watchdogControlDockWidget->setWidget( new WatchdogControl(this) );
                watchdogControlDockWidget->setObjectName("WATCHDOG_CONTROL_DOCKWIDGET");
                addTool(watchdogControlDockWidget, tr("Process Control"), Qt::BottomDockWidgetArea);
            }
1402 1403 1404 1405 1406 1407
        }

        // 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
1408 1409
        if (UASManager::instance()->getUASList().size() == 1)
        {
1410
            // Load last view if setting is present
1411 1412
            if (settings.contains("CURRENT_VIEW_WITH_UAS_CONNECTED"))
            {
1413
                int view = settings.value("CURRENT_VIEW_WITH_UAS_CONNECTED").toInt();
Lorenz Meier's avatar
Lorenz Meier committed
1414 1415
                switch (view)
                {
1416 1417 1418 1419 1420 1421
                case VIEW_ENGINEER:
                    loadEngineerView();
                    break;
                case VIEW_MAVLINK:
                    loadMAVLinkView();
                    break;
Lorenz Meier's avatar
Lorenz Meier committed
1422 1423 1424
                case VIEW_FIRMWAREUPDATE:
                    loadFirmwareUpdateView();
                    break;
1425 1426 1427 1428 1429 1430 1431 1432 1433 1434
                case VIEW_PILOT:
                    loadPilotView();
                    break;
                case VIEW_UNCONNECTED:
                    loadUnconnectedView();
                    break;
                case VIEW_OPERATOR:
                default:
                    loadOperatorView();
                    break;
1435
                }
1436 1437 1438
            }
            else
            {
1439
                loadOperatorView();
1440
            }
1441
        }
1442

pixhawk's avatar
pixhawk committed
1443
    //}
1444 1445

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

1448 1449
    // Reload view state in case new widgets were added
    loadViewState();
pixhawk's avatar
pixhawk committed
1450 1451
}

1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470
void MainWindow::UASDeleted(UASInterface* uas)
{
    if (UASManager::instance()->getUASList().count() == 0)
    {
        // Last system deleted
        ui.menuUnmanned_System->setTitle(tr("No System"));
        ui.menuUnmanned_System->setEnabled(false);
    }

    QAction* act;
    QList<QAction*> actions = ui.menuConnected_Systems->actions();

    foreach (act, actions)
    {
        if (act->text().contains(uas->getUASName()))
            ui.menuConnected_Systems->removeAction(act);
    }
}

1471
/**
1472
 * Stores the current view state
1473
 */
1474
void MainWindow::storeViewState()
1475
{
pixhawk's avatar
pixhawk committed
1476
    if (!aboutToCloseFlag)
lm's avatar
lm committed
1477
    {
pixhawk's avatar
pixhawk committed
1478 1479 1480 1481 1482 1483 1484 1485
        // 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());
1486
    }
1487
}
1488

1489 1490 1491
void MainWindow::loadViewState()
{
    // Restore center stack state
lm's avatar
lm committed
1492
    int index = settings.value(getWindowStateKey()+"CENTER_WIDGET", -1).toInt();
LM's avatar
LM committed
1493 1494 1495 1496 1497 1498
    // 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
1499

lm's avatar
lm committed
1500 1501 1502 1503 1504 1505
    if (index != -1)
    {
        centerStack->setCurrentIndex(index);
    }
    else
    {
1506 1507 1508 1509
        // Hide custom widgets
        if (detectionDockWidget) detectionDockWidget->hide();
        if (watchdogControlDockWidget) watchdogControlDockWidget->hide();

lm's avatar
lm committed
1510 1511 1512 1513 1514
        // Load defaults
        switch (currentView)
        {
        case VIEW_ENGINEER:
            centerStack->setCurrentWidget(linechartWidget);
lm's avatar
lm committed
1515 1516 1517 1518 1519 1520 1521
            controlDockWidget->hide();
            listDockWidget->hide();
            waypointsDockWidget->hide();
            infoDockWidget->hide();
            debugConsoleDockWidget->show();
            logPlayerDockWidget->show();
            mavlinkInspectorWidget->show();
1522
            //mavlinkSenderWidget->show();
lm's avatar
lm committed
1523 1524 1525 1526 1527 1528 1529 1530
            parametersDockWidget->show();
            hsiDockWidget->hide();
            headDown1DockWidget->hide();
            headDown2DockWidget->hide();
            rcViewDockWidget->hide();
            headUpDockWidget->hide();
            video1DockWidget->hide();
            video2DockWidget->hide();
lm's avatar
lm committed
1531 1532 1533
            break;
        case VIEW_PILOT:
            centerStack->setCurrentWidget(hudWidget);
lm's avatar
lm committed
1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546
            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();
1547
            video1DockWidget->hide();
lm's avatar
lm committed
1548
            video2DockWidget->hide();
lm's avatar
lm committed
1549 1550 1551
            break;
        case VIEW_MAVLINK:
            centerStack->setCurrentWidget(protocolWidget);
lm's avatar
lm committed
1552 1553 1554 1555 1556 1557
            controlDockWidget->hide();
            listDockWidget->hide();
            waypointsDockWidget->hide();
            infoDockWidget->hide();
            debugConsoleDockWidget->hide();
            logPlayerDockWidget->hide();
Lorenz Meier's avatar
Lorenz Meier committed
1558
            mavlinkInspectorWidget->show();
1559
            //mavlinkSenderWidget->show();
Lorenz Meier's avatar
Lorenz Meier committed
1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576
            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
1577
            mavlinkInspectorWidget->hide();
1578
            //mavlinkSenderWidget->hide();
lm's avatar
lm committed
1579 1580 1581 1582 1583 1584 1585 1586
            parametersDockWidget->hide();
            hsiDockWidget->hide();
            headDown1DockWidget->hide();
            headDown2DockWidget->hide();
            rcViewDockWidget->hide();
            headUpDockWidget->hide();
            video1DockWidget->hide();
            video2DockWidget->hide();
lm's avatar
lm committed
1587 1588
            break;
        case VIEW_OPERATOR:
1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605
            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
1606 1607 1608 1609
        case VIEW_UNCONNECTED:
        case VIEW_FULL:
        default:
            centerStack->setCurrentWidget(mapWidget);
1610
            controlDockWidget->hide();
lm's avatar
lm committed
1611
            listDockWidget->show();
1612 1613
            waypointsDockWidget->hide();
            infoDockWidget->hide();
lm's avatar
lm committed
1614 1615 1616
            debugConsoleDockWidget->show();
            logPlayerDockWidget->show();
            parametersDockWidget->hide();
1617
            hsiDockWidget->hide();
lm's avatar
lm committed
1618 1619 1620 1621 1622 1623
            headDown1DockWidget->hide();
            headDown2DockWidget->hide();
            rcViewDockWidget->hide();
            headUpDockWidget->show();
            video1DockWidget->hide();
            video2DockWidget->hide();
1624
            mavlinkInspectorWidget->show();
lm's avatar
lm committed
1625
            break;
pixhawk's avatar
pixhawk committed
1626 1627 1628
        }
    }

1629 1630 1631 1632
    // Restore the widget positions and size
    if (settings.contains(getWindowStateKey()))
    {
        restoreState(settings.value(getWindowStateKey()).toByteArray(), QGC::applicationVersion());
pixhawk's avatar
pixhawk committed
1633 1634 1635
    }
}

1636
void MainWindow::loadEngineerView()
lm's avatar
lm committed
1637
{
1638 1639
    if (currentView != VIEW_ENGINEER)
    {
1640
        storeViewState();
1641 1642
        currentView = VIEW_ENGINEER;
        ui.actionEngineersView->setChecked(true);
1643
        loadViewState();
1644
    }
lm's avatar
lm committed
1645 1646
}

1647
void MainWindow::loadOperatorView()
lm's avatar
lm committed
1648
{
1649 1650
    if (currentView != VIEW_OPERATOR)
    {
1651
        storeViewState();
1652 1653
        currentView = VIEW_OPERATOR;
        ui.actionOperatorsView->setChecked(true);
1654
        loadViewState();
1655 1656
    }
}
lm's avatar
lm committed
1657

1658 1659
void MainWindow::loadUnconnectedView()
{
1660 1661 1662
    if (currentView != VIEW_UNCONNECTED)
    {
        storeViewState();
1663 1664
        currentView = VIEW_UNCONNECTED;
        ui.actionUnconnectedView->setChecked(true);
1665
        loadViewState();
1666
    }
lm's avatar
lm committed
1667 1668
}

1669
void MainWindow::loadPilotView()
1670
{
1671 1672 1673
    if (currentView != VIEW_PILOT)
    {
        storeViewState();
1674 1675
        currentView = VIEW_PILOT;
        ui.actionPilotsView->setChecked(true);
1676
        loadViewState();
1677
    }
1678 1679
}

1680
void MainWindow::loadMAVLinkView()
1681
{
1682 1683 1684
    if (currentView != VIEW_MAVLINK)
    {
        storeViewState();
1685 1686
        currentView = VIEW_MAVLINK;
        ui.actionMavlinkView->setChecked(true);
1687
        loadViewState();
1688
    }
1689 1690
}

Lorenz Meier's avatar
Lorenz Meier committed
1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701
void MainWindow::loadFirmwareUpdateView()
{
    if (currentView != VIEW_FIRMWAREUPDATE)
    {
        storeViewState();
        currentView = VIEW_FIRMWAREUPDATE;
        ui.actionFirmwareUpdateView->setChecked(true);
        loadViewState();
    }
}

1702 1703
void MainWindow::loadDataView(QString fileName)
{
1704
    // Plot is now selected, now load data from file
1705 1706 1707 1708 1709 1710 1711 1712
    if (dataplotWidget)
    {
        dataplotWidget->loadFile(fileName);
    }
    QStackedWidget *centerStack = dynamic_cast<QStackedWidget*>(centralWidget());
    if (centerStack)
    {
        centerStack->setCurrentWidget(dataplotWidget);
1713
        dataplotWidget->loadFile(fileName);
1714
    }
1715 1716 1717
}


oberion's avatar
oberion committed
1718 1719
QList<QAction*> MainWindow::listLinkMenuActions(void)
{
lm's avatar
lm committed
1720
    return ui.menuNetwork->actions();
1721
}