MainWindow.cc 17.9 KB
Newer Older
1
2
3
4
5
6
7
8
/****************************************************************************
 *
 *   (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/
9
10
11
12
13
14
15
16
17
18
19
20
21


/**
 * @file
 *   @brief Implementation of class MainWindow
 *   @author Lorenz Meier <mail@qgroundcontrol.org>
 */

#include <QSettings>
#include <QNetworkInterface>
#include <QDebug>
#include <QTimer>
#include <QHostInfo>
22
#include <QQuickView>
23
#include <QDesktopWidget>
24
25
#include <QScreen>
#include <QDesktopServices>
26
#include <QDockWidget>
27
#include <QMenuBar>
Don Gagne's avatar
Don Gagne committed
28
#include <QDialog>
29

30
31
32
33
#include "QGC.h"
#include "MAVLinkProtocol.h"
#include "MainWindow.h"
#include "GAudioOutput.h"
dogmaphobic's avatar
dogmaphobic committed
34
#ifndef __mobile__
35
#include "QGCMAVLinkLogPlayer.h"
dogmaphobic's avatar
dogmaphobic committed
36
#endif
37
#include "MAVLinkDecoder.h"
Don Gagne's avatar
Don Gagne committed
38
#include "QGCApplication.h"
39
#include "MultiVehicleManager.h"
Don Gagne's avatar
Don Gagne committed
40
#include "HomePositionManager.h"
41
#include "LogCompressor.h"
Don Gagne's avatar
Don Gagne committed
42
#include "UAS.h"
dogmaphobic's avatar
dogmaphobic committed
43
#include "QGCImageProvider.h"
44
45

#ifndef __mobile__
Don Gagne's avatar
Don Gagne committed
46
47
#include "QGCDataPlot2D.h"
#include "Linecharts.h"
48
49
50
51
52
#include "QGCUASFileViewMulti.h"
#include "UASQuickView.h"
#include "QGCTabbedInfoView.h"
#include "CustomCommandWidget.h"
#include "QGCDockWidget.h"
53
#include "HILDockWidget.h"
54
#include "AppMessages.h"
55
56
57
58
59
#endif

#ifndef __ios__
#include "SerialLink.h"
#endif
60

61
62
63
64
#ifdef UNITTEST_BUILD
#include "QmlControls/QmlTestWidget.h"
#endif

65
66
67
/// The key under which the Main Window settings are saved
const char* MAIN_SETTINGS_GROUP = "QGC_MAINWINDOW";

68
#ifndef __mobile__
69
70
71
enum DockWidgetTypes {
    MAVLINK_INSPECTOR,
    CUSTOM_COMMAND,
Tomaz Canabrava's avatar
Tomaz Canabrava committed
72
73
74
    ONBOARD_FILES,
    INFO_VIEW,
    HIL_CONFIG,
Don Gagne's avatar
Don Gagne committed
75
    ANALYZE
Tomaz Canabrava's avatar
Tomaz Canabrava committed
76
77
78
79
80
81
82
83
};

static const char *rgDockWidgetNames[] = {
    "MAVLink Inspector",
    "Custom Command",
    "Onboard Files",
    "Info View",
    "HIL Config",
Don Gagne's avatar
Don Gagne committed
84
    "Analyze"
Tomaz Canabrava's avatar
Tomaz Canabrava committed
85
86
87
};

#define ARRAY_SIZE(ARRAY) (sizeof(ARRAY) / sizeof(ARRAY[0]))
88
89

static const char* _visibleWidgetsKey = "VisibleWidgets";
90
#endif
91

Don Gagne's avatar
Don Gagne committed
92
93
static MainWindow* _instance = NULL;   ///< @brief MainWindow singleton

Lorenz Meier's avatar
Lorenz Meier committed
94
MainWindow* MainWindow::_create()
95
{
Don Gagne's avatar
Don Gagne committed
96
    Q_ASSERT(_instance == NULL);
Lorenz Meier's avatar
Lorenz Meier committed
97
    new MainWindow();
Don Gagne's avatar
Don Gagne committed
98
99
    // _instance is set in constructor
    Q_ASSERT(_instance);
100
101
102
    return _instance;
}

Don Gagne's avatar
Don Gagne committed
103
MainWindow* MainWindow::instance(void)
104
{
Don Gagne's avatar
Don Gagne committed
105
    return _instance;
106
107
}

Don Gagne's avatar
Don Gagne committed
108
109
void MainWindow::deleteInstance(void)
{
Don Gagne's avatar
Don Gagne committed
110
    delete this;
Don Gagne's avatar
Don Gagne committed
111
112
}

Don Gagne's avatar
Don Gagne committed
113
114
115
/// @brief Private constructor for MainWindow. MainWindow singleton is only ever created
///         by MainWindow::_create method. Hence no other code should have access to
///         constructor.
Lorenz Meier's avatar
Lorenz Meier committed
116
MainWindow::MainWindow()
117
    : _lowPowerMode(false)
118
    , _showStatusBar(false)
119
    , _mainQmlWidgetHolder(NULL)
120
    , _forceClose(false)
121
{
Don Gagne's avatar
Don Gagne committed
122
123
    Q_ASSERT(_instance == NULL);
    _instance = this;
124

dogmaphobic's avatar
dogmaphobic committed
125
126
127
128
129
130
131
132
    //-- Load fonts
    if(QFontDatabase::addApplicationFont(":/fonts/opensans") < 0) {
        qWarning() << "Could not load /fonts/opensans font";
    }
    if(QFontDatabase::addApplicationFont(":/fonts/opensans-demibold") < 0) {
        qWarning() << "Could not load /fonts/opensans-demibold font";
    }

133
134
135
136
    // Qt 4/5 on Ubuntu does place the native menubar correctly so on Linux we revert back to in-window menu bar.
#ifdef Q_OS_LINUX
    menuBar()->setNativeMenuBar(false);
#endif
dogmaphobic's avatar
dogmaphobic committed
137
    // Setup user interface
138
    loadSettings();
139
    emit initStatusChanged(tr("Setting up user interface"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
140

dogmaphobic's avatar
dogmaphobic committed
141
142
    _ui.setupUi(this);
    // Make sure tool bar elements all fit before changing minimum width
dogmaphobic's avatar
dogmaphobic committed
143
    setMinimumWidth(1008);
dogmaphobic's avatar
dogmaphobic committed
144
    configureWindowName();
145

146
147
    // Setup central widget with a layout to hold the views
    _centralLayout = new QVBoxLayout();
148
    _centralLayout->setContentsMargins(0, 0, 0, 0);
149
    centralWidget()->setLayout(_centralLayout);
150
151
152
153
154

    _mainQmlWidgetHolder = new QGCQmlWidgetHolder(QString(), NULL, this);
    _centralLayout->addWidget(_mainQmlWidgetHolder);
    _mainQmlWidgetHolder->setVisible(true);

155
    QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
156
    _mainQmlWidgetHolder->setContextPropertyObject("controller", this);
Nate Weibley's avatar
Nate Weibley committed
157
    _mainQmlWidgetHolder->setContextPropertyObject("debugMessageModel", AppMessages::getModel());
Don Gagne's avatar
Don Gagne committed
158
    _mainQmlWidgetHolder->setSource(QUrl::fromUserInput("qrc:qml/MainWindowHybrid.qml"));
159

dogmaphobic's avatar
dogmaphobic committed
160
161
162
163
    // Image provider
    QQuickImageProvider* pImgProvider = dynamic_cast<QQuickImageProvider*>(qgcApp()->toolbox()->imageProvider());
    _mainQmlWidgetHolder->getEngine()->addImageProvider(QLatin1String("QGCImages"), pImgProvider);

164
    // Set dock options
165
    setDockOptions(0);
166
    // Setup corners
167
    setCorner(Qt::BottomRightCorner, Qt::BottomDockWidgetArea);
168

dogmaphobic's avatar
dogmaphobic committed
169
170
171
    // On Mobile devices, we don't want any main menus at all.
#ifdef __mobile__
    menuBar()->setNativeMenuBar(false);
dogmaphobic's avatar
dogmaphobic committed
172
#endif
dogmaphobic's avatar
dogmaphobic committed
173

174
175
176
#ifdef UNITTEST_BUILD
    QAction* qmlTestAction = new QAction("Test QML palette and controls", NULL);
    connect(qmlTestAction, &QAction::triggered, this, &MainWindow::_showQmlTestWidget);
177
    _ui.menuWidgets->addAction(qmlTestAction);
178
#endif
Lorenz Meier's avatar
Lorenz Meier committed
179

dogmaphobic's avatar
dogmaphobic committed
180
    // Status Bar
Don Gagne's avatar
Don Gagne committed
181
    setStatusBar(new QStatusBar(this));
182
    statusBar()->setSizeGripEnabled(true);
183

184
#ifndef __mobile__
185
    emit initStatusChanged(tr("Building common widgets."), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
186
    _buildCommonWidgets();
187
    emit initStatusChanged(tr("Building common actions"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
188
#endif
189

190
191
192
    // Create actions
    connectCommonActions();
    // Connect user interface devices
193
#ifdef QGC_MOUSE_ENABLED_WIN
194
    emit initStatusChanged(tr("Initializing 3D mouse interface"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
195
196
    mouseInput = new Mouse3DInput(this);
    mouse = new Mouse6dofInput(mouseInput);
197
#endif //QGC_MOUSE_ENABLED_WIN
198

199
#if QGC_MOUSE_ENABLED_LINUX
200
    emit initStatusChanged(tr("Initializing 3D mouse interface"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
201
202

    mouse = new Mouse6dofInput(this);
Tomaz Canabrava's avatar
Tomaz Canabrava committed
203
    connect(this, &MainWindow::x11EventOccured, mouse, &Mouse6dofInput::handleX11Event);
204
#endif //QGC_MOUSE_ENABLED_LINUX
205

206
    // Set low power mode
dogmaphobic's avatar
dogmaphobic committed
207
    enableLowPowerMode(_lowPowerMode);
208
    emit initStatusChanged(tr("Restoring last view state"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
209

dogmaphobic's avatar
dogmaphobic committed
210
#ifndef __mobile__
211

212
    // Restore the window position and size
dogmaphobic's avatar
dogmaphobic committed
213
214
    emit initStatusChanged(tr("Restoring last window size"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
    if (settings.contains(_getWindowGeometryKey()))
215
    {
dogmaphobic's avatar
dogmaphobic committed
216
        restoreGeometry(settings.value(_getWindowGeometryKey()).toByteArray());
217
218
219
220
    }
    else
    {
        // Adjust the size
dogmaphobic's avatar
dogmaphobic committed
221
222
223
        QScreen* scr = QApplication::primaryScreen();
        QSize scrSize = scr->availableSize();
        if (scrSize.width() <= 1280)
224
        {
dogmaphobic's avatar
dogmaphobic committed
225
            resize(scrSize.width(), scrSize.height());
226
227
228
        }
        else
        {
dogmaphobic's avatar
dogmaphobic committed
229
230
231
            int w = scrSize.width()  > 1600 ? 1600 : scrSize.width();
            int h = scrSize.height() >  800 ?  800 : scrSize.height();
            resize(w, h);
232
            move((scrSize.width() - w) / 2, (scrSize.height() - h) / 2);
233
234
        }
    }
235
236
#endif

237
    connect(_ui.actionStatusBar,  &QAction::triggered, this, &MainWindow::showStatusBarCallback);
238

Tomaz Canabrava's avatar
Tomaz Canabrava committed
239
    connect(&windowNameUpdateTimer, &QTimer::timeout, this, &MainWindow::configureWindowName);
240
    windowNameUpdateTimer.start(15000);
241
    emit initStatusChanged(tr("Done"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
242
243

    if (!qgcApp()->runningUnitTests()) {
244
245
        _ui.actionStatusBar->setChecked(_showStatusBar);
        showStatusBarCallback(_showStatusBar);
dogmaphobic's avatar
dogmaphobic committed
246
#ifdef __mobile__
247
248
        menuBar()->hide();
#endif
249
        show();
dogmaphobic's avatar
dogmaphobic committed
250
#ifdef __macos__
dogmaphobic's avatar
dogmaphobic committed
251
252
253
254
255
256
257
258
259
260
261
262
263
264
        // TODO HACK
        // This is a really ugly hack. For whatever reason, by having a QQuickWidget inside a
        // QDockWidget (MainToolBar above), the main menu is not shown when the app first
        // starts. I looked everywhere and I could not find a solution. What I did notice was
        // that if any other window gets focus, the menu comes up when you come back to QGC.
        // That is, if you were to click on another window and then back to QGC, the menus
        // would appear. This hack below creates a 0x0 dialog and immediately closes it.
        // That works around the issue and it will do until I find the root of the problem.
        QDialog qd(this);
        qd.show();
        qd.raise();
        qd.activateWindow();
        qd.close();
#endif
265
    }
266

Don Gagne's avatar
Don Gagne committed
267
268
269
#ifndef __mobile__
    _loadVisibleWidgetsSettings();
#endif
270
271
272
273
274
    //-- Enable message handler display of messages in main window
    UASMessageHandler* msgHandler = qgcApp()->toolbox()->uasMessageHandler();
    if(msgHandler) {
        msgHandler->showErrorsInToolbar();
    }
275
276
277
278
}

MainWindow::~MainWindow()
{
279
280
281
282
    // This needs to happen before we get into the QWidget dtor
    // otherwise  the QML engine reads freed data and tries to
    // destroy MainWindow a second time.
    delete _mainQmlWidgetHolder;
Don Gagne's avatar
Don Gagne committed
283
    _instance = NULL;
284
285
}

dogmaphobic's avatar
dogmaphobic committed
286
QString MainWindow::_getWindowGeometryKey()
287
288
289
290
{
    return "_geometry";
}

291
#ifndef __mobile__
292
void MainWindow::_buildCommonWidgets(void)
293
294
{
    // Add generic MAVLink decoder
dogmaphobic's avatar
dogmaphobic committed
295
    // TODO: This is never deleted
296
    mavlinkDecoder = new MAVLinkDecoder(qgcApp()->toolbox()->mavlinkProtocol(), this);
297
    connect(mavlinkDecoder.data(), &MAVLinkDecoder::valueChanged, this, &MainWindow::valueChanged);
298

299
    // Log player
dogmaphobic's avatar
dogmaphobic committed
300
    // TODO: Make this optional with a preferences setting or under a "View" menu
Don Gagne's avatar
Don Gagne committed
301
    logPlayer = new QGCMAVLinkLogPlayer(statusBar());
Don Gagne's avatar
Don Gagne committed
302
    statusBar()->addPermanentWidget(logPlayer);
303

Tomaz Canabrava's avatar
Tomaz Canabrava committed
304
305
    for (int i = 0, end = ARRAY_SIZE(rgDockWidgetNames); i < end; i++) {

Don Gagne's avatar
Don Gagne committed
306
        const char* pDockWidgetName = rgDockWidgetNames[i];
307

Don Gagne's avatar
Don Gagne committed
308
        // Add to menu
309
        QAction* action = new QAction(tr(pDockWidgetName), this);
Don Gagne's avatar
Don Gagne committed
310
        action->setCheckable(true);
Tomaz Canabrava's avatar
Tomaz Canabrava committed
311
        action->setData(i);
Don Gagne's avatar
Don Gagne committed
312
313
314
        connect(action, &QAction::triggered, this, &MainWindow::_showDockWidgetAction);
        _ui.menuWidgets->addAction(action);
        _mapName2Action[pDockWidgetName] = action;
315
    }
316
}
317

318
319
/// Shows or hides the specified dock widget, creating if necessary
void MainWindow::_showDockWidget(const QString& name, bool show)
320
{
321
    // Create the inner widget if we need to
Don Gagne's avatar
Don Gagne committed
322
    if (!_mapName2DockWidget.contains(name)) {
dogmaphobic's avatar
dogmaphobic committed
323
324
325
326
        if(!_createInnerDockWidget(name)) {
            qWarning() << "Trying to load non existing widget:" << name;
            return;
        }
327
    }
328
    Q_ASSERT(_mapName2DockWidget.contains(name));
Don Gagne's avatar
Don Gagne committed
329
    QGCDockWidget* dockWidget = _mapName2DockWidget[name];
330
331
    Q_ASSERT(dockWidget);
    dockWidget->setVisible(show);
Don Gagne's avatar
Don Gagne committed
332
333
    Q_ASSERT(_mapName2Action.contains(name));
    _mapName2Action[name]->setChecked(show);
334
335
336
}

/// Creates the specified inner dock widget and adds to the QDockWidget
dogmaphobic's avatar
dogmaphobic committed
337
bool MainWindow::_createInnerDockWidget(const QString& widgetName)
338
{
Don Gagne's avatar
Don Gagne committed
339
    QGCDockWidget* widget = NULL;
Tomaz Canabrava's avatar
Tomaz Canabrava committed
340
    QAction *action = _mapName2Action[widgetName];
dogmaphobic's avatar
dogmaphobic committed
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
    if(action) {
        switch(action->data().toInt()) {
            case MAVLINK_INSPECTOR:
                widget = new QGCMAVLinkInspector(widgetName, action, qgcApp()->toolbox()->mavlinkProtocol(),this);
                break;
            case CUSTOM_COMMAND:
                widget = new CustomCommandWidget(widgetName, action, this);
                break;
            case ONBOARD_FILES:
                widget = new QGCUASFileViewMulti(widgetName, action, this);
                break;
            case HIL_CONFIG:
                widget = new HILDockWidget(widgetName, action, this);
                break;
            case ANALYZE:
                widget = new Linecharts(widgetName, action, mavlinkDecoder, this);
                break;
            case INFO_VIEW:
                widget= new QGCTabbedInfoView(widgetName, action, this);
                break;
        }
        if(action->data().toInt() == INFO_VIEW) {
            qobject_cast<QGCTabbedInfoView*>(widget)->addSource(mavlinkDecoder);
        }
        if(widget) {
            _mapName2DockWidget[widgetName] = widget;
        }
Tomaz Canabrava's avatar
Tomaz Canabrava committed
368
    }
dogmaphobic's avatar
dogmaphobic committed
369
    return widget != NULL;
370
}
371

372
373
void MainWindow::_hideAllDockWidgets(void)
{
Don Gagne's avatar
Don Gagne committed
374
    foreach(QGCDockWidget* dockWidget, _mapName2DockWidget) {
375
376
377
378
379
380
        dockWidget->setVisible(false);
    }
}

void MainWindow::_showDockWidgetAction(bool show)
{
381
    QAction* action = qobject_cast<QAction*>(QObject::sender());
382
    Q_ASSERT(action);
Tomaz Canabrava's avatar
Tomaz Canabrava committed
383
    _showDockWidget(rgDockWidgetNames[action->data().toInt()], show);
384
385
386
}
#endif

387
388
389
390
391
392
void MainWindow::showStatusBarCallback(bool checked)
{
    _showStatusBar = checked;
    checked ? statusBar()->show() : statusBar()->hide();
}

393
void MainWindow::reallyClose(void)
394
{
395
396
    _forceClose = true;
    close();
397
398
}

399
400
void MainWindow::closeEvent(QCloseEvent *event)
{
401
    if (!_forceClose) {
Ricardo de Almeida Gonzaga's avatar
Ricardo de Almeida Gonzaga committed
402
        // Attempt close from within the root Qml item
403
        qgcApp()->qmlAttemptWindowClose();
404
405
        event->ignore();
        return;
406
407
408
    }

    // Should not be any active connections
Don Gagne's avatar
Don Gagne committed
409
    if (qgcApp()->toolbox()->multiVehicleManager()->activeVehicle()) {
Don Gagne's avatar
Don Gagne committed
410
411
        qWarning() << "All links should be disconnected by now";
    }
412

413
    _storeCurrentViewState();
414
    storeSettings();
415
416

    emit mainWindowClosed();
417
418
419
420
}

void MainWindow::loadSettings()
{
421
    // Why the screaming?
422
    QSettings settings;
423
    settings.beginGroup(MAIN_SETTINGS_GROUP);
424
425
    _lowPowerMode   = settings.value("LOW_POWER_MODE",      _lowPowerMode).toBool();
    _showStatusBar  = settings.value("SHOW_STATUSBAR",      _showStatusBar).toBool();
426
427
428
429
430
431
    settings.endGroup();
}

void MainWindow::storeSettings()
{
    QSettings settings;
432
    settings.beginGroup(MAIN_SETTINGS_GROUP);
433
434
    settings.setValue("LOW_POWER_MODE",     _lowPowerMode);
    settings.setValue("SHOW_STATUSBAR",     _showStatusBar);
435
    settings.endGroup();
dogmaphobic's avatar
dogmaphobic committed
436
    settings.setValue(_getWindowGeometryKey(), saveGeometry());
437

Don Gagne's avatar
Don Gagne committed
438
439
440
#ifndef __mobile__
    _storeVisibleWidgetsSettings();
#endif
441
442
443
444
445
446
}

void MainWindow::configureWindowName()
{
    QList<QHostAddress> hostAddresses = QNetworkInterface::allAddresses();
    QString windowname = qApp->applicationName() + " " + qApp->applicationVersion();
Lorenz Meier's avatar
Lorenz Meier committed
447
448
449
450
451

    // XXX we do have UDP MAVLink heartbeat broadcast now in SITL and will have it on the
    // WIFI radio, so people should not be in need any more of knowing their IP.
    // this can go once we are certain its not needed any more.
    #if 0
Lorenz Meier's avatar
Lorenz Meier committed
452
    bool prevAddr = false;
453
454
455
456
457
458
459
460
461
462
463
464
    windowname.append(" (" + QHostInfo::localHostName() + ": ");
    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;
        }
    }
    windowname.append(")");
Lorenz Meier's avatar
Lorenz Meier committed
465
    #endif
466
467
468
469
470
471
472
473
474
475
    setWindowTitle(windowname);
}

/**
* @brief Create all actions associated to the main window
*
**/
void MainWindow::connectCommonActions()
{
    // Audio output
476
    _ui.actionMuteAudioOutput->setChecked(qgcApp()->toolbox()->audioOutput()->isMuted());
Tomaz Canabrava's avatar
Tomaz Canabrava committed
477
478
    connect(qgcApp()->toolbox()->audioOutput(), &GAudioOutput::mutedChanged, _ui.actionMuteAudioOutput, &QAction::setChecked);
    connect(_ui.actionMuteAudioOutput, &QAction::triggered, qgcApp()->toolbox()->audioOutput(), &GAudioOutput::mute);
479

480
    // Connect internal actions
481
    connect(qgcApp()->toolbox()->multiVehicleManager(), &MultiVehicleManager::vehicleAdded, this, &MainWindow::_vehicleAdded);
482
483
}

Don Gagne's avatar
Don Gagne committed
484
void MainWindow::_openUrl(const QString& url, const QString& errorMessage)
485
{
Don Gagne's avatar
Don Gagne committed
486
    if(!QDesktopServices::openUrl(QUrl(url))) {
487
        qgcApp()->showMessage(QString("Could not open information in browser: %1").arg(errorMessage));
488
489
490
    }
}

491
void MainWindow::_vehicleAdded(Vehicle* vehicle)
492
{
Tomaz Canabrava's avatar
Tomaz Canabrava committed
493
    connect(vehicle->uas(), &UAS::valueChanged, this, &MainWindow::valueChanged);
494
495
}

496
497
/// Stores the state of the toolbar, status bar and widgets associated with the current view
void MainWindow::_storeCurrentViewState(void)
498
{
Don Gagne's avatar
Don Gagne committed
499
#ifndef __mobile__
Don Gagne's avatar
Don Gagne committed
500
501
    foreach(QGCDockWidget* dockWidget, _mapName2DockWidget) {
        dockWidget->saveSettings();
502
    }
Don Gagne's avatar
Don Gagne committed
503
#endif
504

dogmaphobic's avatar
dogmaphobic committed
505
    settings.setValue(_getWindowGeometryKey(), saveGeometry());
506
507
}

508
509
510
511
512
513
514
515
516
/// @brief Saves the last used connection
void MainWindow::saveLastUsedConnection(const QString connection)
{
    QSettings settings;
    QString key(MAIN_SETTINGS_GROUP);
    key += "/LAST_CONNECTION";
    settings.setValue(key, connection);
}

517
#ifdef QGC_MOUSE_ENABLED_LINUX
518
519
520
bool MainWindow::x11Event(XEvent *event)
{
    emit x11EventOccured(event);
521
    return false;
522
}
523
#endif // QGC_MOUSE_ENABLED_LINUX
524
525
526
527
528
529
530

#ifdef UNITTEST_BUILD
void MainWindow::_showQmlTestWidget(void)
{
    new QmlTestWidget();
}
#endif
Don Gagne's avatar
Don Gagne committed
531
532
533
534
535

#ifndef __mobile__
void MainWindow::_loadVisibleWidgetsSettings(void)
{
    QSettings settings;
536

Don Gagne's avatar
Don Gagne committed
537
    QString widgets = settings.value(_visibleWidgetsKey).toString();
538

Don Gagne's avatar
Don Gagne committed
539
540
    if (!widgets.isEmpty()) {
        QStringList nameList = widgets.split(",");
541

542
        foreach (const QString &name, nameList) {
Don Gagne's avatar
Don Gagne committed
543
544
545
546
547
548
549
550
551
            _showDockWidget(name, true);
        }
    }
}

void MainWindow::_storeVisibleWidgetsSettings(void)
{
    QString widgetNames;
    bool firstWidget = true;
552

553
    foreach (const QString &name, _mapName2DockWidget.keys()) {
Don Gagne's avatar
Don Gagne committed
554
555
556
557
558
559
        if (_mapName2DockWidget[name]->isVisible()) {
            if (!firstWidget) {
                widgetNames += ",";
            } else {
                firstWidget = false;
            }
560

Don Gagne's avatar
Don Gagne committed
561
562
563
            widgetNames += name;
        }
    }
564

Don Gagne's avatar
Don Gagne committed
565
    QSettings settings;
566

Don Gagne's avatar
Don Gagne committed
567
568
569
    settings.setValue(_visibleWidgetsKey, widgetNames);
}
#endif
570

Don Gagne's avatar
Don Gagne committed
571
QObject* MainWindow::rootQmlObject(void)
572
{
Don Gagne's avatar
Don Gagne committed
573
    return _mainQmlWidgetHolder->getRootObject();
574
}