MainWindow.cc 50.9 KB
Newer Older
1
/*===================================================================
pixhawk's avatar
pixhawk committed
2 3 4 5
======================================================================*/

/**
 * @file
6
 *   @brief Implementation of class MainWindow
7
 *   @author Lorenz Meier <mail@qgroundcontrol.org>
pixhawk's avatar
pixhawk committed
8 9 10 11 12 13 14 15 16 17 18
 */

#include <QSettings>
#include <QDockWidget>
#include <QNetworkInterface>
#include <QMessageBox>
#include <QDebug>
#include <QTimer>
#include <QHostInfo>

#include "MG.h"
19
#include "QGC.h"
pixhawk's avatar
pixhawk committed
20 21 22 23 24 25 26 27
#include "MAVLinkSimulationLink.h"
#include "SerialLink.h"
#include "UDPLink.h"
#include "MAVLinkProtocol.h"
#include "CommConfigurationWindow.h"
#include "WaypointList.h"
#include "MainWindow.h"
#include "JoystickWidget.h"
pixhawk's avatar
pixhawk committed
28
#include "GAudioOutput.h"
29
#include "QGCToolWidget.h"
30
#include "QGCMAVLinkLogPlayer.h"
31

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

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

pixhawk's avatar
pixhawk committed
40 41 42

#include "LogCompressor.h"

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

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

pixhawk's avatar
pixhawk committed
57 58 59 60 61 62 63
/**
* Create new mainwindow. The constructor instantiates all parts of the user
* interface. It does NOT show the mainwindow. To display it, call the show()
* method.
*
* @see QMainWindow::show()
**/
64
MainWindow::MainWindow(QWidget *parent):
pixhawk's avatar
pixhawk committed
65
        QMainWindow(parent),
66
        toolsMenuActions(),
67
        currentView(VIEW_ENGINEER),
68
        aboutToCloseFlag(false),
69
        changingViewsFlag(false),
pixhawk's avatar
pixhawk committed
70
        settings()
pixhawk's avatar
pixhawk committed
71
{
72 73
    // Get current settings
    settings.sync();
74

75 76 77 78 79 80 81 82 83 84 85 86 87 88
    if (!settings.contains("CURRENT_VIEW"))
    {
        // Set this view as default view
        settings.setValue("CURRENT_VIEW", currentView);

        // Enable default tools

        // ENABLE UAS LIST
        settings.setValue(buildMenuKey(SUB_SECTION_CHECKED,MainWindow::MENU_UAS_LIST,currentView), true);
        // ENABLE COMMUNICATION CONSOLE
        settings.setValue(buildMenuKey(SUB_SECTION_CHECKED,MainWindow::MENU_DEBUG_CONSOLE,currentView), true);
    }
    else
    {
89 90 91 92
        if (settings.value("CURRENT_VIEW", VIEW_PILOT) != VIEW_PILOT)
        {
            currentView = (VIEW_SECTIONS) settings.value("CURRENT_VIEW", currentView).toInt();
        }
93 94
    }

95
    // Check if the settings exist, instantiate defaults if necessary
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119

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

    // ENGINEER VIEW DEFAULT
    centralKey = buildMenuKey(SUB_SECTION_CHECKED, CENTRAL_LINECHART, VIEW_ENGINEER);
    if (!settings.contains(centralKey))
    {
        settings.setValue(centralKey,true);
    }

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

    // PILOT VIEW DEFAULT
    centralKey = buildMenuKey(SUB_SECTION_CHECKED, CENTRAL_HUD, VIEW_PILOT);
120 121 122
    if (!settings.contains(centralKey))
    {
        settings.setValue(centralKey,true);
123 124 125 126 127
    }

    QString listKey = buildMenuKey(SUB_SECTION_CHECKED, MENU_UAS_LIST, currentView);
    if (!settings.contains(listKey))
    {
128 129
        settings.setValue(listKey, true);
    }
130

131
    settings.sync();
132

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

136 137
    setVisible(false);

138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
    // Bind together the perspective actions
    QActionGroup* perspectives = new QActionGroup(ui.menuPerspectives);
    perspectives->addAction(ui.actionEngineersView);
    perspectives->addAction(ui.actionMavlinkView);
    perspectives->addAction(ui.actionPilotsView);
    perspectives->addAction(ui.actionOperatorsView);
    perspectives->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);

    // The pilot view is not available on startup
    ui.actionPilotsView->setEnabled(false);

155
    buildCommonWidgets();
156

157
    connectCommonWidgets();
158

159
    arrangeCommonCenterStack();
160 161

    configureWindowName();
pixhawk's avatar
pixhawk committed
162 163 164 165

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

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

176
    // Create actions
177
    connectCommonActions();
178

179 180
    // Set dock options
    setDockOptions(AnimatedDocks | AllowTabbedDocks | AllowNestedDocks);
181

182
    // Load mavlink view as default widget set
183
    //loadMAVLinkView();
184

lm's avatar
lm committed
185 186
    statusBar()->setSizeGripEnabled(true);

187 188
    // Restore the window position and size
    if (settings.contains(getWindowGeometryKey()))
189 190
    {
        // Restore the window geometry
191
        restoreGeometry(settings.value(getWindowGeometryKey()).toByteArray());
192 193 194 195 196 197
    }
    else
    {
        // Adjust the size
        adjustSize();
    }
pixhawk's avatar
pixhawk committed
198

199 200 201
    // Populate link menu
    QList<LinkInterface*> links = LinkManager::instance()->getLinks();
    foreach(LinkInterface* link, links)
202
    {
203 204
        this->addLink(link);
    }
205

206 207
    connect(LinkManager::instance(), SIGNAL(newLink(LinkInterface*)), this, SLOT(addLink(LinkInterface*)));

lm's avatar
lm committed
208 209
    // Enable and update view
    presentView();
pixhawk's avatar
pixhawk committed
210 211
}

pixhawk's avatar
pixhawk committed
212
MainWindow::~MainWindow()
pixhawk's avatar
pixhawk committed
213
{
lm's avatar
lm committed
214

pixhawk's avatar
pixhawk committed
215 216
}

217 218 219 220 221 222 223 224 225 226
QString MainWindow::getWindowStateKey()
{
    return QString::number(currentView)+"/windowstate";
}

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

227 228 229 230
void MainWindow::buildCommonWidgets()
{
    //TODO:  move protocol outside UI
    mavlink     = new MAVLinkProtocol();
231
    connect(mavlink, SIGNAL(protocolStatusMessage(QString,QString)), this, SLOT(showCriticalMessage(QString,QString)), Qt::QueuedConnection);
232 233

    // Dock widgets
234 235 236
    if (!controlDockWidget)
    {
        controlDockWidget = new QDockWidget(tr("Control"), this);
237
        controlDockWidget->setObjectName("UNMANNED_SYSTEM_CONTROL_DOCKWIDGET");
238 239 240
        controlDockWidget->setWidget( new UASControlWidget(this) );
        addToToolsMenu (controlDockWidget, tr("Control"), SLOT(showToolWidget()), MENU_UAS_CONTROL, Qt::LeftDockWidgetArea);
    }
241

242 243 244 245
    if (!listDockWidget)
    {
        listDockWidget = new QDockWidget(tr("Unmanned Systems"), this);
        listDockWidget->setWidget( new UASListWidget(this) );
246
        listDockWidget->setObjectName("UNMANNED_SYSTEMS_LIST_DOCKWIDGET");
247 248
        addToToolsMenu (listDockWidget, tr("Unmanned Systems"), SLOT(showToolWidget()), MENU_UAS_LIST, Qt::RightDockWidgetArea);
    }
249

250 251 252 253
    if (!waypointsDockWidget)
    {
        waypointsDockWidget = new QDockWidget(tr("Waypoint List"), this);
        waypointsDockWidget->setWidget( new WaypointList(this, NULL) );
254
        waypointsDockWidget->setObjectName("WAYPOINT_LIST_DOCKWIDGET");
255 256
        addToToolsMenu (waypointsDockWidget, tr("Waypoints List"), SLOT(showToolWidget()), MENU_WAYPOINTS, Qt::BottomDockWidgetArea);
    }
257

258 259 260 261
    if (!infoDockWidget)
    {
        infoDockWidget = new QDockWidget(tr("Status Details"), this);
        infoDockWidget->setWidget( new UASInfoWidget(this) );
pixhawk's avatar
pixhawk committed
262
        infoDockWidget->setObjectName("UAS_STATUS_DETAILS_DOCKWIDGET");
263 264
        addToToolsMenu (infoDockWidget, tr("Status Details"), SLOT(showToolWidget()), MENU_STATUS, Qt::RightDockWidgetArea);
    }
265

266 267 268 269
    if (!debugConsoleDockWidget)
    {
        debugConsoleDockWidget = new QDockWidget(tr("Communication Console"), this);
        debugConsoleDockWidget->setWidget( new DebugConsole(this) );
270
        debugConsoleDockWidget->setObjectName("COMMUNICATION_DEBUG_CONSOLE_DOCKWIDGET");
271 272
        addToToolsMenu (debugConsoleDockWidget, tr("Communication Console"), SLOT(showToolWidget()), MENU_DEBUG_CONSOLE, Qt::BottomDockWidgetArea);
    }
273

274 275 276 277 278 279
    if (!logPlayerDockWidget)
    {
        logPlayerDockWidget = new QDockWidget(tr("MAVLink Log Player"), this);
        logPlayerDockWidget->setWidget( new QGCMAVLinkLogPlayer(mavlink, this) );
        logPlayerDockWidget->setObjectName("MAVLINK_LOG_PLAYER_DOCKWIDGET");
        addToToolsMenu(logPlayerDockWidget, tr("MAVLink Log Replay"), SLOT(showToolWidget()), MENU_MAVLINK_LOG_PLAYER, Qt::RightDockWidgetArea);
280
    }
281

282
    // Center widgets
283 284 285 286 287
    if (!mapWidget)
    {
        mapWidget         = new MapWidget(this);
        addToCentralWidgetsMenu (mapWidget, "Maps", SLOT(showCentralWidget()),CENTRAL_MAP);
    }
288

289 290 291 292 293
    if (!protocolWidget)
    {
        protocolWidget    = new XMLCommProtocolWidget(this);
        addToCentralWidgetsMenu (protocolWidget, "Mavlink Generator", SLOT(showCentralWidget()),CENTRAL_PROTOCOL);
    }
lm's avatar
lm committed
294

Alejandro's avatar
Alejandro committed
295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
    //TODO temporaly debug
    if (!slugsHilSimWidget)
    {
        slugsHilSimWidget = new QDockWidget(tr("Slugs Hil Sim"), this);
        slugsHilSimWidget->setWidget( new SlugsHilSim(this));
        addToToolsMenu (slugsHilSimWidget, tr("HIL Sim Configuration"), SLOT(showToolWidget()), MENU_SLUGS_HIL, Qt::LeftDockWidgetArea);
    }

    //TODO temporaly debug
    if (!slugsCamControlWidget)
    {
        slugsCamControlWidget = new QDockWidget(tr("Slugs Video Camera Control"), this);
        slugsCamControlWidget->setWidget(new SlugsVideoCamControl(this));
        addToToolsMenu (slugsCamControlWidget, tr("Camera Control"), SLOT(showToolWidget()), MENU_SLUGS_CAMERA, Qt::BottomDockWidgetArea);
    }
lm's avatar
lm committed
310 311 312 313 314
    if (!dataplotWidget)
    {
        dataplotWidget    = new QGCDataPlot2D(this);
        addToCentralWidgetsMenu (dataplotWidget, "Data Plot", SLOT(showCentralWidget()),CENTRAL_DATA_PLOT);
    }
315
}
316

317
void MainWindow::buildPxWidgets()
318
{
pixhawk's avatar
pixhawk committed
319 320
    //FIXME: memory of acceptList will never be freed again
    QStringList* acceptList = new QStringList();
lm's avatar
lm committed
321 322 323
    acceptList->append("-105,roll,deg,+105,s");
    acceptList->append("-105,pitch,deg,+105,s");
    acceptList->append("-105,yaw,deg,+105,s");
324

lm's avatar
lm committed
325 326 327
    acceptList->append("-260,rollspeed,deg/s,+260,s");
    acceptList->append("-260,pitchspeed,deg/s,+260,s");
    acceptList->append("-260,yawspeed,deg/s,+260,s");
328

pixhawk's avatar
pixhawk committed
329 330
    //FIXME: memory of acceptList2 will never be freed again
    QStringList* acceptList2 = new QStringList();
lm's avatar
lm committed
331
    acceptList2->append("0,abs pressure,hPa,65500");
332 333
    acceptList2->append("-999,accel. X,raw,999,s");
    acceptList2->append("-999,accel. Y,raw,999,s");
334

335 336 337 338 339 340
    if (!linechartWidget)
    {
        // Center widgets
        linechartWidget   = new Linecharts(this);
        addToCentralWidgetsMenu(linechartWidget, "Line Plots", SLOT(showCentralWidget()), CENTRAL_LINECHART);
    }
341 342


343 344 345 346 347
    if (!hudWidget)
    {
        hudWidget         = new HUD(320, 240, this);
        addToCentralWidgetsMenu(hudWidget, "HUD", SLOT(showCentralWidget()), CENTRAL_HUD);
    }
348

349 350 351 352 353
    if (!dataplotWidget)
    {
        dataplotWidget    = new QGCDataPlot2D(this);
        addToCentralWidgetsMenu(dataplotWidget, "Data Plots", SLOT(showCentralWidget()), CENTRAL_DATA_PLOT);
    }
354

355
#ifdef QGC_OSG_ENABLED
356 357 358 359 360
    if (!_3DWidget)
    {
        _3DWidget         = Q3DWidgetFactory::get("PIXHAWK");
        addToCentralWidgetsMenu(_3DWidget, "Local 3D", SLOT(showCentralWidget()), CENTRAL_3D_LOCAL);
    }
361
#endif
362

363
#ifdef QGC_OSGEARTH_ENABLED
364 365 366 367 368
    if (!_3DMapWidget)
    {
        _3DMapWidget = Q3DWidgetFactory::get("MAP3D");
        addToCentralWidgetsMenu(_3DMapWidget, "OSG Earth 3D", SLOT(showCentralWidget()), CENTRAL_OSGEARTH);
    }
369
#endif
lm's avatar
lm committed
370

371
#if (defined _MSC_VER) | (defined Q_OS_MAC)
372 373 374 375 376
    if (!gEarthWidget)
    {
        gEarthWidget = new QGCGoogleEarthView(this);
        addToCentralWidgetsMenu(gEarthWidget, "Google Earth", SLOT(showCentralWidget()), CENTRAL_GOOGLE_EARTH);
    }
377

378
#endif
379

pixhawk's avatar
pixhawk committed
380
    // Dock widgets
381

382 383 384 385
    if (!detectionDockWidget)
    {
        detectionDockWidget = new QDockWidget(tr("Object Recognition"), this);
        detectionDockWidget->setWidget( new ObjectDetectionView("images/patterns", this) );
pixhawk's avatar
pixhawk committed
386
        detectionDockWidget->setObjectName("OBJECT_DETECTION_DOCK_WIDGET");
387 388
        addToToolsMenu (detectionDockWidget, tr("Object Recognition"), SLOT(showToolWidget()), MENU_DETECTION, Qt::RightDockWidgetArea);
    }
389

390 391 392 393
    if (!parametersDockWidget)
    {
        parametersDockWidget = new QDockWidget(tr("Onboard Parameters"), this);
        parametersDockWidget->setWidget( new ParameterInterface(this) );
pixhawk's avatar
pixhawk committed
394
        parametersDockWidget->setObjectName("PARAMETER_INTERFACE_DOCKWIDGET");
395 396
        addToToolsMenu (parametersDockWidget, tr("Onboard Parameters"), SLOT(showToolWidget()), MENU_PARAMETERS, Qt::RightDockWidgetArea);
    }
397

398 399 400 401
    if (!watchdogControlDockWidget)
    {
        watchdogControlDockWidget = new QDockWidget(tr("Process Control"), this);
        watchdogControlDockWidget->setWidget( new WatchdogControl(this) );
pixhawk's avatar
pixhawk committed
402
        watchdogControlDockWidget->setObjectName("WATCHDOG_CONTROL_DOCKWIDGET");
403 404
        addToToolsMenu (watchdogControlDockWidget, tr("Process Control"), SLOT(showToolWidget()), MENU_WATCHDOG, Qt::BottomDockWidgetArea);
    }
405

406 407 408 409
    if (!hsiDockWidget)
    {
        hsiDockWidget = new QDockWidget(tr("Horizontal Situation Indicator"), this);
        hsiDockWidget->setWidget( new HSIDisplay(this) );
410
        hsiDockWidget->setObjectName("HORIZONTAL_SITUATION_INDICATOR_DOCK_WIDGET");
411 412
        addToToolsMenu (hsiDockWidget, tr("HSI"), SLOT(showToolWidget()), MENU_HSI, Qt::BottomDockWidgetArea);
    }
413

414 415
    if (!headDown1DockWidget)
    {
416 417
        headDown1DockWidget = new QDockWidget(tr("Flight Display"), this);
        headDown1DockWidget->setWidget( new HDDisplay(acceptList, "Flight Display", this) );
418
        headDown1DockWidget->setObjectName("HEAD_DOWN_DISPLAY_1_DOCK_WIDGET");
419 420
        addToToolsMenu (headDown1DockWidget, tr("Flight Display"), SLOT(showToolWidget()), MENU_HDD_1, Qt::RightDockWidgetArea);
    }
421

422 423 424
    if (!headDown2DockWidget)
    {
        headDown2DockWidget = new QDockWidget(tr("Payload Status"), this);
425
        headDown2DockWidget->setWidget( new HDDisplay(acceptList2, "Payload Status", this) );
426
        headDown2DockWidget->setObjectName("HEAD_DOWN_DISPLAY_2_DOCK_WIDGET");
427 428
        addToToolsMenu (headDown2DockWidget, tr("Payload Status"), SLOT(showToolWidget()), MENU_HDD_2, Qt::RightDockWidgetArea);
    }
429

430 431 432 433
    if (!rcViewDockWidget)
    {
        rcViewDockWidget = new QDockWidget(tr("Radio Control"), this);
        rcViewDockWidget->setWidget( new QGCRemoteControlView(this) );
434
        rcViewDockWidget->setObjectName("RADIO_CONTROL_CHANNELS_DOCK_WIDGET");
435 436
        addToToolsMenu (rcViewDockWidget, tr("Radio Control"), SLOT(showToolWidget()), MENU_RC_VIEW, Qt::BottomDockWidgetArea);
    }
437

438 439 440 441
    if (!headUpDockWidget)
    {
        headUpDockWidget = new QDockWidget(tr("HUD"), this);
        headUpDockWidget->setWidget( new HUD(320, 240, this));
442
        headUpDockWidget->setObjectName("HEAD_UP_DISPLAY_DOCK_WIDGET");
443 444
        addToToolsMenu (headUpDockWidget, tr("Control Indicator"), SLOT(showToolWidget()), MENU_HUD, Qt::LeftDockWidgetArea);
    }
445

pixhawk's avatar
pixhawk committed
446 447
    // Dialogue widgets
    //FIXME: free memory in destructor
448 449 450 451
    if (!joystick)
    {
        joystick    = new JoystickInput();
    }
452

453 454 455 456
}

void MainWindow::buildSlugsWidgets()
{
457 458 459 460 461
    if (!linechartWidget)
    {
        // Center widgets
        linechartWidget   = new Linecharts(this);
    }
462

463 464 465 466 467
    if (!headUpDockWidget)
    {
        // Dock widgets
        headUpDockWidget = new QDockWidget(tr("Control Indicator"), this);
        headUpDockWidget->setWidget( new HUD(320, 240, this));
pixhawk's avatar
pixhawk committed
468
        headUpDockWidget->setObjectName("HEAD_UP_DISPLAY_DOCK_WIDGET");
469 470
        addToToolsMenu (headUpDockWidget, tr("HUD"), SLOT(showToolWidget()), MENU_HUD, Qt::LeftDockWidgetArea);
    }
471

472 473 474 475
    if (!rcViewDockWidget)
    {
        rcViewDockWidget = new QDockWidget(tr("Radio Control"), this);
        rcViewDockWidget->setWidget( new QGCRemoteControlView(this) );
pixhawk's avatar
pixhawk committed
476
        rcViewDockWidget->setObjectName("RADIO_CONTROL_CHANNELS_DOCK_WIDGET");
477 478
        addToToolsMenu (rcViewDockWidget, tr("Radio Control"), SLOT(showToolWidget()), MENU_RC_VIEW, Qt::BottomDockWidgetArea);
    }
479

480 481 482 483 484
    if (!slugsDataWidget)
    {
        // Dialog widgets
        slugsDataWidget = new QDockWidget(tr("Slugs Data"), this);
        slugsDataWidget->setWidget( new SlugsDataSensorView(this));
pixhawk's avatar
pixhawk committed
485
        slugsDataWidget->setObjectName("SLUGS_DATA_DOCK_WIDGET");
486 487
        addToToolsMenu (slugsDataWidget, tr("Telemetry Data"), SLOT(showToolWidget()), MENU_SLUGS_DATA, Qt::RightDockWidgetArea);
    }
488

489 490 491 492
    if (!slugsPIDControlWidget)
    {
        slugsPIDControlWidget = new QDockWidget(tr("Slugs PID Control"), this);
        slugsPIDControlWidget->setWidget(new SlugsPIDControl(this));
pixhawk's avatar
pixhawk committed
493
        slugsPIDControlWidget->setObjectName("SLUGS_PID_CONTROL_DOCK_WIDGET");
494 495
        addToToolsMenu (slugsPIDControlWidget, tr("PID Configuration"), SLOT(showToolWidget()), MENU_SLUGS_PID, Qt::LeftDockWidgetArea);
    }
496

497 498 499 500
    if (!slugsHilSimWidget)
    {
        slugsHilSimWidget = new QDockWidget(tr("Slugs Hil Sim"), this);
        slugsHilSimWidget->setWidget( new SlugsHilSim(this));
pixhawk's avatar
pixhawk committed
501
        slugsHilSimWidget->setObjectName("SLUGS_HIL_SIM_DOCK_WIDGET");
502 503
        addToToolsMenu (slugsHilSimWidget, tr("HIL Sim Configuration"), SLOT(showToolWidget()), MENU_SLUGS_HIL, Qt::LeftDockWidgetArea);
    }
504

505 506 507 508
    if (!slugsCamControlWidget)
    {
        slugsCamControlWidget = new QDockWidget(tr("Slugs Video Camera Control"), this);
        slugsCamControlWidget->setWidget(new SlugsVideoCamControl(this));
pixhawk's avatar
pixhawk committed
509
        slugsCamControlWidget->setObjectName("SLUGS_CAM_CONTROL_DOCK_WIDGET");
510 511
        addToToolsMenu (slugsCamControlWidget, tr("Camera Control"), SLOT(showToolWidget()), MENU_SLUGS_CAMERA, Qt::BottomDockWidgetArea);
    }
512
}
513 514 515 516 517


void MainWindow::addToCentralWidgetsMenu ( QWidget* widget,
                                           const QString title,
                                           const char * slotName,
518 519
                                           TOOLS_WIDGET_NAMES centralWidget)
{
520
    QAction* tempAction;
521

522

523
    // Add the separator that will separate tools from central Widgets
524 525
    if (!toolsMenuActions[CENTRAL_SEPARATOR])
    {
526 527 528 529
        tempAction = ui.menuTools->addSeparator();
        toolsMenuActions[CENTRAL_SEPARATOR] = tempAction;
        tempAction->setData(CENTRAL_SEPARATOR);
    }
530

531
    tempAction = ui.menuTools->addAction(title);
532

533 534
    tempAction->setCheckable(true);
    tempAction->setData(centralWidget);
535

536 537 538
    // populate the Hashes
    toolsMenuActions[centralWidget] = tempAction;
    dockWidgets[centralWidget] = widget;
539

540
    QString chKey = buildMenuKey(SUB_SECTION_CHECKED, centralWidget, currentView);
541

542 543
    if (!settings.contains(chKey))
    {
544 545 546
        settings.setValue(chKey,false);
        tempAction->setChecked(false);
    }
547 548 549 550
    else
    {
        tempAction->setChecked(settings.value(chKey).toBool());
    }
551

552 553
    // connect the action
    connect(tempAction,SIGNAL(triggered()),this, slotName);
554 555 556
}


lm's avatar
lm committed
557 558
void MainWindow::showCentralWidget()
{
559 560 561
    QAction* senderAction = qobject_cast<QAction *>(sender());
    int tool = senderAction->data().toInt();
    QString chKey;
562

563
    // check the current action
564

565 566
    if (senderAction && dockWidgets[tool])
    {
567

568 569
        // uncheck all central widget actions
        QHashIterator<int, QAction*> i(toolsMenuActions);
570 571
        while (i.hasNext())
        {
572
            i.next();
573 574 575
            //qDebug() << "shCW" << i.key() << "read";
            if (i.value() && i.value()->data().toInt() > 255)
            {
576
                i.value()->setChecked(false);
577

578 579 580 581 582
                // update the settings
                chKey = buildMenuKey (SUB_SECTION_CHECKED,static_cast<TOOLS_WIDGET_NAMES>(i.value()->data().toInt()), currentView);
                settings.setValue(chKey,false);
            }
        }
583

584
        // check the current action
585
        //qDebug() << senderAction->text();
586
        senderAction->setChecked(true);
587

588 589
        // update the central widget
        centerStack->setCurrentWidget(dockWidgets[tool]);
590

591 592 593
        // store the selected central widget
        chKey = buildMenuKey (SUB_SECTION_CHECKED,static_cast<TOOLS_WIDGET_NAMES>(tool), currentView);
        settings.setValue(chKey,true);
594

595 596
        presentView();
    }
597
}
598

lm's avatar
lm committed
599 600 601 602
/**
 * Adds a widget to the tools menu and sets it visible if it was
 * enabled last time.
 */
603
void MainWindow::addToToolsMenu ( QWidget* widget,
604 605 606 607
                                  const QString title,
                                  const char * slotName,
                                  TOOLS_WIDGET_NAMES tool,
                                  Qt::DockWidgetArea location)
lm's avatar
lm committed
608
{
609 610
    QAction* tempAction;
    QString posKey, chKey;
611

612

613 614
    if (toolsMenuActions[CENTRAL_SEPARATOR])
    {
615 616 617
        tempAction = new QAction(title, this);
        ui.menuTools->insertAction(toolsMenuActions[CENTRAL_SEPARATOR],
                                   tempAction);
618 619 620
    }
    else
    {
621 622
        tempAction = ui.menuTools->addAction(title);
    }
623

624 625
    tempAction->setCheckable(true);
    tempAction->setData(tool);
626

627 628 629
    // populate the Hashes
    toolsMenuActions[tool] = tempAction;
    dockWidgets[tool] = widget;
630
    //qDebug() << widget;
631

632
    posKey = buildMenuKey (SUB_SECTION_LOCATION,tool, currentView);
633

634 635
    if (!settings.contains(posKey))
    {
636 637
        settings.setValue(posKey,location);
        dockWidgetLocations[tool] = location;
638 639 640 641
    }
    else
    {
        dockWidgetLocations[tool] = static_cast <Qt::DockWidgetArea> (settings.value(posKey, Qt::RightDockWidgetArea).toInt());
642
    }
643

644
    chKey = buildMenuKey(SUB_SECTION_CHECKED,tool, currentView);
645

646 647 648 649
    if (!settings.contains(chKey))
    {
        settings.setValue(chKey,false);
        tempAction->setChecked(false);
650
        widget->setVisible(false);
651 652 653 654
    }
    else
    {
        tempAction->setChecked(settings.value(chKey).toBool());
655
        widget->setVisible(settings.value(chKey, false).toBool());
656
    }
657

658 659
    // connect the action
    connect(tempAction,SIGNAL(triggered()),this, slotName);
660

661 662
//  connect(qobject_cast <QDockWidget *>(dockWidgets[tool]),
//          SIGNAL(visibilityChanged(bool)), this, SLOT(updateVisibilitySettings(bool)));
663

664 665
    connect(qobject_cast <QDockWidget *>(dockWidgets[tool]),
            SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), this, SLOT(updateLocationSettings(Qt::DockWidgetArea)));
666 667 668

}

669 670 671 672
void MainWindow::showToolWidget()
{
    QAction* temp = qobject_cast<QAction *>(sender());
    int tool = temp->data().toInt();
673

674 675 676 677 678 679 680 681 682 683 684
    if (temp && dockWidgets[tool])
    {
        if (temp->isChecked())
        {
            addDockWidget(dockWidgetLocations[tool], qobject_cast<QDockWidget *> (dockWidgets[tool]));
            qobject_cast<QDockWidget *>(dockWidgets[tool])->show();
        }
        else
        {
            removeDockWidget(qobject_cast<QDockWidget *>(dockWidgets[tool]));
        }
685
    }
686

687 688 689
}


690 691 692 693 694
void MainWindow::showTheWidget (TOOLS_WIDGET_NAMES widget, VIEW_SECTIONS view)
{
    bool tempVisible;
    Qt::DockWidgetArea tempLocation;
    QDockWidget* tempWidget = static_cast <QDockWidget *>(dockWidgets[widget]);
695

696
    tempVisible =  settings.value(buildMenuKey(SUB_SECTION_CHECKED,widget,view), false).toBool();
697

698 699 700 701
    if (tempWidget)
    {
        toolsMenuActions[widget]->setChecked(tempVisible);
    }
702 703


704
    //qDebug() <<  buildMenuKey (SUB_SECTION_CHECKED,widget,view) << tempVisible;
705

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

708 709 710 711 712 713 714
    //    if (widget == MainWindow::MENU_UAS_LIST)
    //    {
    //        if (!settings.contains(buildMenuKey (SUB_SECTION_LOCATION,widget, view)))
    //        {
    //            tempLocation = Qt::RightDockWidgetArea;
    //        }
    //    }
715

716
    if ((tempWidget != NULL) && tempVisible)
717 718 719 720
    {
        addDockWidget(tempLocation, tempWidget);
        tempWidget->show();
    }
721 722 723

}

724 725 726 727 728 729 730 731 732 733 734 735 736 737
QString MainWindow::buildMenuKey(SETTINGS_SECTIONS section, TOOLS_WIDGET_NAMES tool, VIEW_SECTIONS view)
{
    // Key is built as follows: autopilot_type/section_menu/view/tool/section
    int apType;

    apType = (UASManager::instance() && UASManager::instance()->silentGetActiveUAS())?
             UASManager::instance()->getActiveUAS()->getAutopilotType():
             -1;

    return (QString::number(apType) + "/" +
            QString::number(SECTION_MENU) + "/" +
            QString::number(view) + "/" +
            QString::number(tool) + "/" +
            QString::number(section) + "/" );
738 739
}

740 741
void MainWindow::closeEvent(QCloseEvent *event)
{
742
    settings.setValue(getWindowGeometryKey(), saveGeometry());
743 744
    //settings.setValue("windowState", saveState());
    aboutToCloseFlag = true;
745 746 747 748 749 750
    // Save the last current view in any case
    settings.setValue("CURRENT_VIEW", currentView);
    // Save the current window state, but only if a system is connected (else no real number of widgets would be present)
    if (UASManager::instance()->getActiveUAS()) settings.setValue(getWindowStateKey(), saveState(QGC::applicationVersion()));
    // Save the current view only if a UAS is connected
    if (UASManager::instance()->getUASList().length() > 0) settings.setValue("CURRENT_VIEW_WITH_UAS_CONNECTED", currentView);
751 752 753
    settings.sync();
    QMainWindow::closeEvent(event);
}
754

755

756 757
void MainWindow::updateVisibilitySettings (bool vis)
{
758
    if (!aboutToCloseFlag && !changingViewsFlag)
759 760
    {
        QDockWidget* temp = qobject_cast<QDockWidget *>(sender());
761

762 763 764
        if (temp)
        {
            QHashIterator<int, QWidget*> i(dockWidgets);
765
        while (i.hasNext()) {
766
                i.next();
767
          if ((static_cast <QDockWidget *>(dockWidgets[i.key()])) == temp) {
768 769
                    QString chKey = buildMenuKey (SUB_SECTION_CHECKED,static_cast<TOOLS_WIDGET_NAMES>(i.key()), currentView);
                    settings.setValue(chKey,vis);
770 771 772 773 774 775
                    toolsMenuActions[i.key()]->setChecked(vis);
                    break;
                }
            }
        }
    }
776 777
}

778 779 780
void MainWindow::updateLocationSettings (Qt::DockWidgetArea location)
{
    QDockWidget* temp = qobject_cast<QDockWidget *>(sender());
781

782 783 784 785 786 787 788 789 790 791 792
    QHashIterator<int, QWidget*> i(dockWidgets);
    while (i.hasNext())
    {
        i.next();
        if ((static_cast <QDockWidget *>(dockWidgets[i.key()])) == temp)
        {
            QString posKey = buildMenuKey (SUB_SECTION_LOCATION,static_cast<TOOLS_WIDGET_NAMES>(i.key()), currentView);
            settings.setValue(posKey,location);
            break;
        }
    }
793 794
}

795 796 797
/**
 * Connect the signals and slots of the common window widgets
 */
798
void MainWindow::connectCommonWidgets()
799
{
pixhawk's avatar
pixhawk committed
800 801 802 803 804
    if (infoDockWidget && infoDockWidget->widget())
    {
        connect(mavlink, SIGNAL(receiveLossChanged(int, float)),
                infoDockWidget->widget(), SLOT(updateSendLoss(int, float)));
    }
805

pixhawk's avatar
pixhawk committed
806 807 808
    if (mapWidget && waypointsDockWidget->widget())
    {
        // clear path create on the map
809
        connect(waypointsDockWidget->widget(), SIGNAL(clearPathclicked()), mapWidget, SLOT(clearWaypoints()));
pixhawk's avatar
pixhawk committed
810 811
        // add Waypoint widget in the WaypointList widget when mouse clicked
        connect(mapWidget, SIGNAL(captureMapCoordinateClick(QPointF)), waypointsDockWidget->widget(), SLOT(addWaypointMouse(QPointF)));
812 813 814

        // it notifies that a waypoint global goes to do create and a map graphic too
        connect(waypointsDockWidget->widget(), SIGNAL(createWaypointAtMap(QPointF)), mapWidget, SLOT(createWaypointGraphAtMap(QPointF)));
815
    }
Alejandro's avatar
Alejandro committed
816 817 818 819 820 821

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

824 825
void MainWindow::createCustomWidget()
{
826
    //qDebug() << "ADDING CUSTOM WIDGET";
827 828 829 830 831
    QGCToolWidget* tool = new QGCToolWidget(this);
    QDockWidget* dock = new QDockWidget("Unnamed Tool", this);
    dock->setWidget(tool);
    this->addDockWidget(Qt::LeftDockWidgetArea, dock);
    dock->setVisible(true);
832 833 834 835
}

void MainWindow::connectPxWidgets()
{
836
    // No special connections necessary at this point
837 838 839 840
}

void MainWindow::connectSlugsWidgets()
{
841
    if (slugsHilSimWidget && slugsHilSimWidget->widget()){
842 843
        connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)),
                slugsHilSimWidget->widget(), SLOT(activeUasSet(UASInterface*)));
844 845 846
    }

    if (slugsDataWidget && slugsDataWidget->widget()){
847 848
        connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)),
                slugsDataWidget->widget(), SLOT(setActiveUAS(UASInterface*)));
849 850
    }

851

852 853
}

854
void MainWindow::arrangeCommonCenterStack()
855
{
856
    centerStack = new QStackedWidget(this);
857
    centerStack->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
858

pixhawk's avatar
pixhawk committed
859
    if (!centerStack) return;
860

861
    if (mapWidget && (centerStack->indexOf(mapWidget) == -1)) centerStack->addWidget(mapWidget);
lm's avatar
lm committed
862
    if (dataplotWidget && (centerStack->indexOf(dataplotWidget) == -1)) centerStack->addWidget(dataplotWidget);
863
    if (protocolWidget && (centerStack->indexOf(protocolWidget) == -1)) centerStack->addWidget(protocolWidget);
864 865 866 867 868 869 870

    setCentralWidget(centerStack);
}

void MainWindow::arrangePxCenterStack()
{

871 872 873 874
    if (!centerStack) {
        qDebug() << "Center Stack not Created!";
        return;
    }
875

876 877

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

879
#ifdef QGC_OSG_ENABLED
880
    if (_3DWidget && (centerStack->indexOf(_3DWidget) == -1)) centerStack->addWidget(_3DWidget);
881
#endif
882
#ifdef QGC_OSGEARTH_ENABLED
883
    if (_3DMapWidget && (centerStack->indexOf(_3DMapWidget) == -1)) centerStack->addWidget(_3DMapWidget);
884
#endif
885
#if (defined _MSC_VER) | (defined Q_OS_MAC)
886
    if (gEarthWidget && (centerStack->indexOf(gEarthWidget) == -1)) centerStack->addWidget(gEarthWidget);
887
#endif
888 889
    if (hudWidget && (centerStack->indexOf(hudWidget) == -1)) centerStack->addWidget(hudWidget);
    if (dataplotWidget && (centerStack->indexOf(dataplotWidget) == -1)) centerStack->addWidget(dataplotWidget);
890 891 892 893 894
}

void MainWindow::arrangeSlugsCenterStack()
{

895 896 897 898
    if (!centerStack) {
        qDebug() << "Center Stack not Created!";
        return;
    }
899

900 901
    if (linechartWidget && (centerStack->indexOf(linechartWidget) == -1)) centerStack->addWidget(linechartWidget);
    if (hudWidget && (centerStack->indexOf(hudWidget) == -1)) centerStack->addWidget(hudWidget);
902

903 904
}

905 906
void MainWindow::configureWindowName()
{
pixhawk's avatar
pixhawk committed
907 908 909
    QList<QHostAddress> hostAddresses = QNetworkInterface::allAddresses();
    QString windowname = qApp->applicationName() + " " + qApp->applicationVersion();
    bool prevAddr = false;
910

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

pixhawk's avatar
pixhawk committed
913 914 915 916 917 918 919 920 921 922
    for (int i = 0; i < hostAddresses.size(); i++)
    {
        // Exclude loopback IPv4 and all IPv6 addresses
        if (hostAddresses.at(i) != QHostAddress("127.0.0.1") && !hostAddresses.at(i).toString().contains(":"))
        {
            if(prevAddr) windowname.append("/");
            windowname.append(hostAddresses.at(i).toString());
            prevAddr = true;
        }
    }
923

pixhawk's avatar
pixhawk committed
924
    windowname.append(")");
925

pixhawk's avatar
pixhawk committed
926
    setWindowTitle(windowname);
927 928

#ifndef Q_WS_MAC
pixhawk's avatar
pixhawk committed
929
    //qApp->setWindowIcon(QIcon(":/core/images/qtcreator_logo_128.png"));
930 931 932
#endif
}

pixhawk's avatar
pixhawk committed
933
void MainWindow::startVideoCapture()
pixhawk's avatar
pixhawk committed
934 935 936 937 938 939 940 941 942 943 944
{
    QString format = "bmp";
    QString initialPath = QDir::currentPath() + tr("/untitled.") + format;

    QString screenFileName = QFileDialog::getSaveFileName(this, tr("Save As"),
                                                          initialPath,
                                                          tr("%1 Files (*.%2);;All Files (*)")
                                                          .arg(format.toUpper())
                                                          .arg(format));
    delete videoTimer;
    videoTimer = new QTimer(this);
945 946 947
    //videoTimer->setInterval(40);
    //connect(videoTimer, SIGNAL(timeout()), this, SLOT(saveScreen()));
    //videoTimer->stop();
pixhawk's avatar
pixhawk committed
948 949
}

pixhawk's avatar
pixhawk committed
950
void MainWindow::stopVideoCapture()
pixhawk's avatar
pixhawk committed
951 952 953 954 955 956
{
    videoTimer->stop();

    // TODO Convert raw images to PNG
}

pixhawk's avatar
pixhawk committed
957
void MainWindow::saveScreen()
pixhawk's avatar
pixhawk committed
958 959 960 961 962 963 964 965 966 967
{
    QPixmap window = QPixmap::grabWindow(this->winId());
    QString format = "bmp";

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

968 969 970 971 972 973
/**
 * Reload the style sheet from disk. The function tries to load "qgroundcontrol.css" from the application
 * directory (which by default does not exist). If it fails, it will load the bundled default CSS
 * from memory.
 * To customize the application, just create a qgroundcontrol.css file in the application directory
 */
pixhawk's avatar
pixhawk committed
974
void MainWindow::reloadStylesheet()
pixhawk's avatar
pixhawk committed
975
{
976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992
    QString fileName = QCoreApplication::applicationDirPath() + "/style-indoor.css";

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

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

pixhawk's avatar
pixhawk committed
993
    // Load style sheet
994
    QFile* styleSheet = new QFile(fileName);
995 996 997 998
    if (!styleSheet->exists())
    {
        styleSheet = new QFile(":/images/style-mission.css");
    }
999 1000
    if (styleSheet->open(QIODevice::ReadOnly | QIODevice::Text))
    {
1001 1002
        QString style = QString(styleSheet->readAll());
        style.replace("ICONDIR", QCoreApplication::applicationDirPath()+ "/images/");
pixhawk's avatar
pixhawk committed
1003
        qApp->setStyleSheet(style);
1004 1005 1006
    }
    else
    {
1007 1008 1009 1010 1011 1012 1013
        QMessageBox msgBox;
        msgBox.setIcon(QMessageBox::Information);
        msgBox.setText(tr("QGroundControl did lot load a new style"));
        msgBox.setInformativeText(tr("Stylesheet file %1 was not readable").arg(fileName));
        msgBox.setStandardButtons(QMessageBox::Ok);
        msgBox.setDefaultButton(QMessageBox::Ok);
        msgBox.exec();
pixhawk's avatar
pixhawk committed
1014
    }
1015
    delete styleSheet;
pixhawk's avatar
pixhawk committed
1016 1017
}

1018 1019 1020 1021 1022 1023
/**
 * 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
1024
void MainWindow::showStatusMessage(const QString& status, int timeout)
pixhawk's avatar
pixhawk committed
1025
{
lm's avatar
lm committed
1026
    statusBar()->showMessage(status, timeout);
pixhawk's avatar
pixhawk committed
1027 1028
}

1029 1030 1031 1032 1033 1034
/**
 * 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
 */
1035
void MainWindow::showStatusMessage(const QString& status)
pixhawk's avatar
pixhawk committed
1036
{
lm's avatar
lm committed
1037
    statusBar()->showMessage(status, 20000);
1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048
}

void MainWindow::showCriticalMessage(const QString& title, const QString& message)
{
    QMessageBox msgBox(MainWindow::instance());
    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
1049 1050
}

lm's avatar
lm committed
1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061
void MainWindow::showInfoMessage(const QString& title, const QString& message)
{
    QMessageBox msgBox(MainWindow::instance());
    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
1062 1063 1064 1065
/**
* @brief Create all actions associated to the main window
*
**/
1066
void MainWindow::connectCommonActions()
pixhawk's avatar
pixhawk committed
1067 1068 1069 1070 1071 1072
{
    // 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*)));
1073
    connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)), this, SLOT(setActiveUAS(UASInterface*)));
pixhawk's avatar
pixhawk committed
1074

1075
    // Unmanned System controls
pixhawk's avatar
pixhawk committed
1076 1077 1078 1079 1080 1081 1082
    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()));

    connect(ui.actionConfiguration, SIGNAL(triggered()), UASManager::instance(), SLOT(configureActiveUAS()));

1083
    // Views actions
1084
    connect(ui.actionPilotsView, SIGNAL(triggered()), this, SLOT(loadPilotView()));
1085
    connect(ui.actionEngineersView, SIGNAL(triggered()), this, SLOT(loadEngineerView()));
1086
    connect(ui.actionOperatorsView, SIGNAL(triggered()), this, SLOT(loadOperatorView()));
1087

1088 1089
    connect(ui.actionMavlinkView, SIGNAL(triggered()), this, SLOT(loadMAVLinkView()));
    connect(ui.actionReloadStyle, SIGNAL(triggered()), this, SLOT(reloadStylesheet()));
1090

1091
    // Help Actions
1092
    connect(ui.actionOnline_Documentation, SIGNAL(triggered()), this, SLOT(showHelp()));
1093
    connect(ui.actionDeveloper_Credits, SIGNAL(triggered()), this, SLOT(showCredits()));
1094
    connect(ui.actionProject_Roadmap_2, SIGNAL(triggered()), this, SLOT(showRoadMap()));
1095 1096 1097 1098
}

void MainWindow::connectPxActions()
{
1099
    ui.actionJoystickSettings->setVisible(true);
1100

1101 1102
    // Joystick configuration
    connect(ui.actionJoystickSettings, SIGNAL(triggered()), this, SLOT(configure()));
1103 1104 1105 1106 1107

}

void MainWindow::connectSlugsActions()
{
1108

pixhawk's avatar
pixhawk committed
1109 1110
}

1111 1112
void MainWindow::showHelp()
{
1113
    if(!QDesktopServices::openUrl(QUrl("http://qgroundcontrol.org/users/")))
1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126
    {
        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()
{
1127
    if(!QDesktopServices::openUrl(QUrl("http://qgroundcontrol.org/credits/")))
1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140
    {
        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()
{
1141
    if(!QDesktopServices::openUrl(QUrl("http://qgroundcontrol.org/roadmap/")))
1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152
    {
        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
1153
void MainWindow::configure()
pixhawk's avatar
pixhawk committed
1154 1155 1156 1157
{
    joystickWidget = new JoystickWidget(joystick, this);
}

pixhawk's avatar
pixhawk committed
1158
void MainWindow::addLink()
pixhawk's avatar
pixhawk committed
1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171
{
    SerialLink* link = new SerialLink();
    // TODO This should be only done in the dialog itself

    LinkManager::instance()->addProtocol(link, mavlink);

    CommConfigurationWindow* commWidget = new CommConfigurationWindow(link, mavlink, this);

    ui.menuNetwork->addAction(commWidget->getAction());

    commWidget->show();
}

pixhawk's avatar
pixhawk committed
1172 1173
void MainWindow::addLink(LinkInterface *link)
{
1174
    LinkManager::instance()->addProtocol(link, mavlink);
pixhawk's avatar
pixhawk committed
1175 1176 1177
    CommConfigurationWindow* commWidget = new CommConfigurationWindow(link, mavlink, this);
    ui.menuNetwork->addAction(commWidget->getAction());

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

pixhawk's avatar
pixhawk committed
1180 1181 1182 1183
    // Special case for simulationlink
    MAVLinkSimulationLink* sim = dynamic_cast<MAVLinkSimulationLink*>(link);
    if (sim)
    {
1184
        //connect(sim, SIGNAL(valueChanged(int,QString,double,quint64)), linechart, SLOT(appendData(int,QString,double,quint64)));
pixhawk's avatar
pixhawk committed
1185 1186 1187 1188
        connect(ui.actionSimulate, SIGNAL(triggered(bool)), sim, SLOT(connectLink(bool)));
    }
}

1189 1190 1191 1192 1193 1194 1195
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);
}

pixhawk's avatar
pixhawk committed
1196
void MainWindow::UASCreated(UASInterface* uas)
pixhawk's avatar
pixhawk committed
1197
{
1198

pixhawk's avatar
pixhawk committed
1199 1200
    // Connect the UAS to the full user interface

1201 1202
    if (uas != NULL)
    {
1203 1204 1205
        // The pilot view was not available on startup, enable it now
        ui.actionPilotsView->setEnabled(true);

1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235
        QIcon icon;
        // Set matching icon
        switch (uas->getSystemType())
        {
        case 0:
            icon = QIcon(":/images/mavs/generic.svg");
            break;
        case 1:
            icon = QIcon(":/images/mavs/fixed-wing.svg");
            break;
        case 2:
            icon = QIcon(":/images/mavs/quadrotor.svg");
            break;
        case 3:
            icon = QIcon(":/images/mavs/coaxial.svg");
            break;
        case 4:
            icon = QIcon(":/images/mavs/helicopter.svg");
            break;
        case 5:
            icon = QIcon(":/images/mavs/groundstation.svg");
            break;
        default:
            icon = QIcon(":/images/mavs/unknown.svg");
            break;
        }

        ui.menuConnected_Systems->addAction(icon, tr("Select %1 for control").arg(uas->getUASName()), uas, SLOT(setSelected()));

        // FIXME Should be not inside the mainwindow
1236 1237
        if (debugConsoleDockWidget)
        {
pixhawk's avatar
pixhawk committed
1238 1239 1240 1241 1242 1243
            DebugConsole *debugConsole = dynamic_cast<DebugConsole*>(debugConsoleDockWidget->widget());
            if (debugConsole)
            {
                connect(uas, SIGNAL(textMessageReceived(int,int,int,QString)),
                        debugConsole, SLOT(receiveTextMessage(int,int,int,QString)));
            }
1244
        }
1245 1246

        // Health / System status indicator
1247 1248
        if (infoDockWidget)
        {
pixhawk's avatar
pixhawk committed
1249 1250 1251 1252 1253
            UASInfoWidget *infoWidget = dynamic_cast<UASInfoWidget*>(infoDockWidget->widget());
            if (infoWidget)
            {
                infoWidget->addUAS(uas);
            }
1254
        }
1255 1256

        // UAS List
1257 1258
        if (listDockWidget)
        {
pixhawk's avatar
pixhawk committed
1259 1260 1261 1262 1263
            UASListWidget *listWidget = dynamic_cast<UASListWidget*>(listDockWidget->widget());
            if (listWidget)
            {
                listWidget->addUAS(uas);
            }
1264
        }
1265

1266 1267 1268 1269 1270 1271
        switch (uas->getAutopilotType())
        {
        case (MAV_AUTOPILOT_SLUGS):
            {
                // Build Slugs Widgets
                buildSlugsWidgets();
1272

1273 1274
                // Connect Slugs Widgets
                connectSlugsWidgets();
1275

1276 1277
                // Arrange Slugs Centerstack
                arrangeSlugsCenterStack();
1278

1279 1280
                // Connect Slugs Actions
                connectSlugsActions();
1281

1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313
                // FIXME: This type checking might be redundant
                //            if (slugsDataWidget) {
                //              SlugsDataSensorView* dataWidget = dynamic_cast<SlugsDataSensorView*>(slugsDataWidget->widget());
                //              if (dataWidget) {
                //                SlugsMAV* mav2 = dynamic_cast<SlugsMAV*>(uas);
                //                if (mav2) {
                (dynamic_cast<SlugsDataSensorView*>(slugsDataWidget->widget()))->addUAS(uas);
                //                  //loadSlugsView();
                //                  loadGlobalOperatorView();
                //                }
                //              }
                //            }
            }
            break;
        default:
        case (MAV_AUTOPILOT_GENERIC):
        case (MAV_AUTOPILOT_ARDUPILOTMEGA):
        case (MAV_AUTOPILOT_PIXHAWK):
            {
                // Build Pixhawk Widgets
                buildPxWidgets();

                // Connect Pixhawk Widgets
                connectPxWidgets();

                // Arrange Pixhawk Centerstack
                arrangePxCenterStack();

                // Connect Pixhawk Actions
                connectPxActions();
            }
            break;
1314

1315
        loadOperatorView();
1316
        }
pixhawk's avatar
pixhawk committed
1317

1318
        // Change the view only if this is the first UAS
1319

1320 1321 1322 1323
        // If this is the first connected UAS, it is both created as well as
        // the currently active UAS
        if (UASManager::instance()->getActiveUAS() == uas)
        {
1324
            //qDebug() << "UPDATING THE VIEW SINCE THIS IS THE FIRST CONNECTED SYSTEM";
1325

1326
            // Load last view if setting is present
1327
            if (settings.contains("CURRENT_VIEW_WITH_UAS_CONNECTED"))
1328
            {
1329
                int view = settings.value("CURRENT_VIEW_WITH_UAS_CONNECTED").toInt();
1330 1331
                currentView = (VIEW_SECTIONS) view;
                presentView();
1332 1333 1334 1335 1336

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

1339 1340 1341 1342 1343
            }
            else
            {
                loadEngineerView();
            }
1344
        }
pixhawk's avatar
pixhawk committed
1345

1346
    }
1347 1348

    if (!ui.menuConnected_Systems->isEnabled()) ui.menuConnected_Systems->setEnabled(true);
pixhawk's avatar
pixhawk committed
1349
}
1350

1351 1352 1353
/**
 * Clears the current view completely
 */
pixhawk's avatar
pixhawk committed
1354
void MainWindow::clearView()
1355
{
1356 1357 1358
    // Save current state
    if (UASManager::instance()->getActiveUAS()) settings.setValue(getWindowStateKey(), saveState(QGC::applicationVersion()));
    settings.setValue(getWindowGeometryKey(), saveGeometry());
1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369

    QAction* temp;

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

        if (temp)
        {
1370
            //qDebug() << "TOOL:" << chKey << "IS:" << temp->isChecked();
1371 1372 1373 1374
            settings.setValue(chKey,temp->isChecked());
        }
        else
        {
1375
            //qDebug() << "TOOL:" << chKey << "IS DEFAULT AND UNCHECKED";
1376 1377 1378 1379
            settings.setValue(chKey,false);
        }
    }

1380
    changingViewsFlag = true;
1381 1382
    // Remove all dock widgets from main window
    QObjectList childList( this->children() );
pixhawk's avatar
pixhawk committed
1383

1384 1385 1386
    QObjectList::iterator i;
    QDockWidget* dockWidget;
    for (i = childList.begin(); i != childList.end(); ++i)
pixhawk's avatar
pixhawk committed
1387
    {
1388 1389
        dockWidget = dynamic_cast<QDockWidget*>(*i);
        if (dockWidget)
pixhawk's avatar
pixhawk committed
1390
        {
1391
            // Remove dock widget from main window
1392 1393
            //this->removeDockWidget(dockWidget);
            dockWidget->setVisible(false);
1394 1395 1396
            // Deletion of dockWidget would also delete all child
            // widgets of dockWidget
            // Is there a way to unset a widget from QDockWidget?
pixhawk's avatar
pixhawk committed
1397 1398
        }
    }
1399
    changingViewsFlag = false;
pixhawk's avatar
pixhawk committed
1400 1401
}

1402
void MainWindow::loadEngineerView()
lm's avatar
lm committed
1403
{
1404 1405
    if (currentView != VIEW_ENGINEER)
    {
1406
    clearView();
lm's avatar
lm committed
1407

1408
    currentView = VIEW_ENGINEER;
lm's avatar
lm committed
1409

1410
    presentView();
1411
    }
lm's avatar
lm committed
1412 1413
}

1414
void MainWindow::loadOperatorView()
lm's avatar
lm committed
1415
{
1416 1417
    if (currentView != VIEW_OPERATOR)
    {
1418 1419 1420
    clearView();

    currentView = VIEW_OPERATOR;
lm's avatar
lm committed
1421

1422
    presentView();
1423
    }
lm's avatar
lm committed
1424 1425
}

1426
void MainWindow::loadPilotView()
1427
{
1428 1429
    if (currentView != VIEW_PILOT)
    {
1430
    clearView();
1431

1432 1433 1434
    currentView = VIEW_PILOT;

    presentView();
1435
    }
1436 1437
}

1438
void MainWindow::loadMAVLinkView()
1439
{
1440 1441
    if (currentView != VIEW_MAVLINK)
    {
1442
    clearView();
pixhawk's avatar
pixhawk committed
1443

1444 1445 1446
    currentView = VIEW_MAVLINK;

    presentView();
1447
    }
1448 1449
}

lm's avatar
lm committed
1450 1451
void MainWindow::presentView()
{
1452
    // LINE CHART
1453
    showTheCentralWidget(CENTRAL_LINECHART, currentView);
1454

1455 1456
    // MAP
    showTheCentralWidget(CENTRAL_MAP, currentView);
pixhawk's avatar
pixhawk committed
1457

1458 1459
    // PROTOCOL
    showTheCentralWidget(CENTRAL_PROTOCOL, currentView);
pixhawk's avatar
pixhawk committed
1460

1461 1462
    // HEAD UP DISPLAY
    showTheCentralWidget(CENTRAL_HUD, currentView);
pixhawk's avatar
pixhawk committed
1463 1464 1465 1466 1467 1468 1469 1470 1471 1472

    // GOOGLE EARTH
    showTheCentralWidget(CENTRAL_GOOGLE_EARTH, currentView);

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

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

1473 1474 1475
    // DATA PLOT
    showTheCentralWidget(CENTRAL_DATA_PLOT, currentView);

pixhawk's avatar
pixhawk committed
1476

pixhawk's avatar
pixhawk committed
1477

1478
    // Show docked widgets based on current view and autopilot type
1479

1480 1481
    // UAS CONTROL
    showTheWidget(MENU_UAS_CONTROL, currentView);
1482

1483 1484
    // UAS LIST
    showTheWidget(MENU_UAS_LIST, currentView);
1485

1486 1487
    // WAYPOINT LIST
    showTheWidget(MENU_WAYPOINTS, currentView);
pixhawk's avatar
pixhawk committed
1488

1489 1490
    // UAS STATUS
    showTheWidget(MENU_STATUS, currentView);
1491

1492 1493
    // DETECTION
    showTheWidget(MENU_DETECTION, currentView);
1494

1495 1496
    // DEBUG CONSOLE
    showTheWidget(MENU_DEBUG_CONSOLE, currentView);
1497

1498 1499
    // ONBOARD PARAMETERS
    showTheWidget(MENU_PARAMETERS, currentView);
1500

1501 1502
    // WATCHDOG
    showTheWidget(MENU_WATCHDOG, currentView);
1503

1504 1505 1506 1507 1508
    // HUD
    showTheWidget(MENU_HUD, currentView);
    if (headUpDockWidget)
    {
        HUD* tmpHud = dynamic_cast<HUD*>( headUpDockWidget->widget() );
1509 1510 1511 1512
        if (tmpHud)
        {
            if (settings.value(buildMenuKey (SUB_SECTION_CHECKED,MENU_HUD,currentView)).toBool())
            {
1513
                addDockWidget(static_cast <Qt::DockWidgetArea>(settings.value(buildMenuKey (SUB_SECTION_LOCATION,MENU_HUD, currentView)).toInt()),
1514
                        headUpDockWidget);
1515
                headUpDockWidget->show();
1516 1517 1518
            }
            else
            {
1519 1520
                headUpDockWidget->hide();
            }
1521
        }
1522
    }
1523

1524

1525 1526
    // RC View
    showTheWidget(MENU_RC_VIEW, currentView);
1527

1528 1529
    // SLUGS DATA
    showTheWidget(MENU_SLUGS_DATA, currentView);
1530

1531 1532
    // SLUGS PID
    showTheWidget(MENU_SLUGS_PID, currentView);
1533

1534 1535
    // SLUGS HIL
    showTheWidget(MENU_SLUGS_HIL, currentView);
1536

1537 1538
    // SLUGS CAMERA
    showTheWidget(MENU_SLUGS_CAMERA, currentView);
1539

1540 1541
    // HORIZONTAL SITUATION INDICATOR
    showTheWidget(MENU_HSI, currentView);
1542

1543 1544
    // HEAD DOWN 1
    showTheWidget(MENU_HDD_1, currentView);
1545

1546 1547
    // HEAD DOWN 2
    showTheWidget(MENU_HDD_2, currentView);
1548

1549 1550 1551
    // MAVLINK LOG PLAYER
    showTheWidget(MENU_MAVLINK_LOG_PLAYER, currentView);

1552
    this->show();
1553

1554 1555
}

1556 1557 1558 1559
void MainWindow::showTheCentralWidget (TOOLS_WIDGET_NAMES centralWidget, VIEW_SECTIONS view)
{
    bool tempVisible;
    QWidget* tempWidget = dockWidgets[centralWidget];
1560

1561
    tempVisible =  settings.value(buildMenuKey (SUB_SECTION_CHECKED,centralWidget,view), false).toBool();
1562
    //qDebug() << buildMenuKey (SUB_SECTION_CHECKED,centralWidget,view) << tempVisible;
1563
    if (toolsMenuActions[centralWidget])
1564
    {
1565
        toolsMenuActions[centralWidget]->setChecked(tempVisible);
1566
    }
1567

1568
    if (centerStack && tempWidget && tempVisible)
1569
    {
1570
        centerStack->setCurrentWidget(tempWidget);
1571 1572 1573 1574 1575
    }
}

void MainWindow::loadDataView(QString fileName)
{
1576
    clearView();
1577

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

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

1586
    presentView();
1587

1588 1589
    // Plot is now selected, now load data from file
    if (dataplotWidget)
1590
    {
1591
        dataplotWidget->loadFile(fileName);
1592
        }
1593 1594 1595 1596 1597 1598 1599
//        QStackedWidget *centerStack = dynamic_cast<QStackedWidget*>(centralWidget());
//        if (centerStack)
//        {
//            centerStack->setCurrentWidget(dataplotWidget);
//            dataplotWidget->loadFile(fileName);
//        }
//    }
1600 1601
}

1602