MainWindow.cc 17.5 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"
40
#include "LogCompressor.h"
Don Gagne's avatar
Don Gagne committed
41
#include "UAS.h"
dogmaphobic's avatar
dogmaphobic committed
42
#include "QGCImageProvider.h"
43
#include "QGCCorePlugin.h"
44
45

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

Gus Grubba's avatar
Gus Grubba committed
56
#ifndef NO_SERIAL_LINK
57
58
#include "SerialLink.h"
#endif
59

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

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

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

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

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

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

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

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

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

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

Don Gagne's avatar
Don Gagne committed
112
113
114
/// @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
115
MainWindow::MainWindow()
116
    : _lowPowerMode(false)
117
    , _showStatusBar(false)
118
    , _mainQmlWidgetHolder(NULL)
119
    , _forceClose(false)
120
{
Don Gagne's avatar
Don Gagne committed
121
122
    Q_ASSERT(_instance == NULL);
    _instance = this;
123

dogmaphobic's avatar
dogmaphobic committed
124
125
126
127
128
129
130
131
    //-- 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";
    }

132
133
134
135
    // 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
136
    // Setup user interface
137
    loadSettings();
138
    emit initStatusChanged(tr("Setting up user interface"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
139

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

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

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

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

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

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

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

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

179
180
181
    connect(qgcApp()->toolbox()->corePlugin(), &QGCCorePlugin::showAdvancedUIChanged, this, &MainWindow::_showAdvancedUIChanged);
    _showAdvancedUIChanged(qgcApp()->toolbox()->corePlugin()->showAdvancedUI());

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

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

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

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

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

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

dogmaphobic's avatar
dogmaphobic committed
212
#ifndef __mobile__
213

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

239
    connect(_ui.actionStatusBar,  &QAction::triggered, this, &MainWindow::showStatusBarCallback);
240

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

    if (!qgcApp()->runningUnitTests()) {
246
247
        _ui.actionStatusBar->setChecked(_showStatusBar);
        showStatusBarCallback(_showStatusBar);
dogmaphobic's avatar
dogmaphobic committed
248
#ifdef __mobile__
249
250
        menuBar()->hide();
#endif
251
        show();
dogmaphobic's avatar
dogmaphobic committed
252
#ifdef __macos__
dogmaphobic's avatar
dogmaphobic committed
253
254
255
256
257
258
259
260
261
262
263
264
265
266
        // 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
267
    }
268

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

MainWindow::~MainWindow()
{
281
282
283
284
285
    // Enforce thread-safe shutdown of the mavlink decoder
    mavlinkDecoder->finish();
    mavlinkDecoder->wait(1000);
    mavlinkDecoder->deleteLater();

286
287
288
289
    // 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
290
    _instance = NULL;
291
292
}

dogmaphobic's avatar
dogmaphobic committed
293
QString MainWindow::_getWindowGeometryKey()
294
295
296
297
{
    return "_geometry";
}

298
#ifndef __mobile__
299
void MainWindow::_buildCommonWidgets(void)
300
301
{
    // Add generic MAVLink decoder
302
    mavlinkDecoder = new MAVLinkDecoder(qgcApp()->toolbox()->mavlinkProtocol());
303
    connect(mavlinkDecoder.data(), &MAVLinkDecoder::valueChanged, this, &MainWindow::valueChanged);
304

305
    // Log player
dogmaphobic's avatar
dogmaphobic committed
306
    // TODO: Make this optional with a preferences setting or under a "View" menu
Don Gagne's avatar
Don Gagne committed
307
    logPlayer = new QGCMAVLinkLogPlayer(statusBar());
Don Gagne's avatar
Don Gagne committed
308
    statusBar()->addPermanentWidget(logPlayer);
309

Don Gagne's avatar
Don Gagne committed
310
    // Populate widget menu
Tomaz Canabrava's avatar
Tomaz Canabrava committed
311
    for (int i = 0, end = ARRAY_SIZE(rgDockWidgetNames); i < end; i++) {
Don Gagne's avatar
Don Gagne committed
312
313
314
315
        if (i == ONBOARD_FILES) {
            // Temporarily removed until twe can fix all the problems with it
            continue;
        }
Tomaz Canabrava's avatar
Tomaz Canabrava committed
316

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

Don Gagne's avatar
Don Gagne committed
319
        // Add to menu
Don Gagne's avatar
Don Gagne committed
320
        QAction* action = new QAction(pDockWidgetName, this);
Don Gagne's avatar
Don Gagne committed
321
        action->setCheckable(true);
Tomaz Canabrava's avatar
Tomaz Canabrava committed
322
        action->setData(i);
Don Gagne's avatar
Don Gagne committed
323
324
325
        connect(action, &QAction::triggered, this, &MainWindow::_showDockWidgetAction);
        _ui.menuWidgets->addAction(action);
        _mapName2Action[pDockWidgetName] = action;
326
    }
327
}
328

329
330
/// Shows or hides the specified dock widget, creating if necessary
void MainWindow::_showDockWidget(const QString& name, bool show)
331
{
Don Gagne's avatar
Don Gagne committed
332
333
334
335
336
    if (name == rgDockWidgetNames[ONBOARD_FILES]) {
        // Temporarily disabled due to bugs
        return;
    }

337
    // Create the inner widget if we need to
Don Gagne's avatar
Don Gagne committed
338
    if (!_mapName2DockWidget.contains(name)) {
dogmaphobic's avatar
dogmaphobic committed
339
340
341
342
        if(!_createInnerDockWidget(name)) {
            qWarning() << "Trying to load non existing widget:" << name;
            return;
        }
343
    }
344
    Q_ASSERT(_mapName2DockWidget.contains(name));
Don Gagne's avatar
Don Gagne committed
345
    QGCDockWidget* dockWidget = _mapName2DockWidget[name];
346
347
    Q_ASSERT(dockWidget);
    dockWidget->setVisible(show);
Don Gagne's avatar
Don Gagne committed
348
349
    Q_ASSERT(_mapName2Action.contains(name));
    _mapName2Action[name]->setChecked(show);
350
351
352
}

/// Creates the specified inner dock widget and adds to the QDockWidget
dogmaphobic's avatar
dogmaphobic committed
353
bool MainWindow::_createInnerDockWidget(const QString& widgetName)
354
{
Don Gagne's avatar
Don Gagne committed
355
    QGCDockWidget* widget = NULL;
Tomaz Canabrava's avatar
Tomaz Canabrava committed
356
    QAction *action = _mapName2Action[widgetName];
dogmaphobic's avatar
dogmaphobic committed
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
    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
384
    }
dogmaphobic's avatar
dogmaphobic committed
385
    return widget != NULL;
386
}
387

388
389
void MainWindow::_hideAllDockWidgets(void)
{
Don Gagne's avatar
Don Gagne committed
390
    foreach(QGCDockWidget* dockWidget, _mapName2DockWidget) {
391
392
393
394
395
396
        dockWidget->setVisible(false);
    }
}

void MainWindow::_showDockWidgetAction(bool show)
{
397
    QAction* action = qobject_cast<QAction*>(QObject::sender());
398
    Q_ASSERT(action);
Tomaz Canabrava's avatar
Tomaz Canabrava committed
399
    _showDockWidget(rgDockWidgetNames[action->data().toInt()], show);
400
401
402
}
#endif

403
404
405
406
407
408
void MainWindow::showStatusBarCallback(bool checked)
{
    _showStatusBar = checked;
    checked ? statusBar()->show() : statusBar()->hide();
}

409
void MainWindow::reallyClose(void)
410
{
411
412
    _forceClose = true;
    close();
413
414
}

415
416
void MainWindow::closeEvent(QCloseEvent *event)
{
417
    if (!_forceClose) {
Ricardo de Almeida Gonzaga's avatar
Ricardo de Almeida Gonzaga committed
418
        // Attempt close from within the root Qml item
419
        qgcApp()->qmlAttemptWindowClose();
420
421
        event->ignore();
        return;
422
423
424
    }

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

429
    _storeCurrentViewState();
430
    storeSettings();
431
432

    emit mainWindowClosed();
433
434
435
436
}

void MainWindow::loadSettings()
{
437
    // Why the screaming?
438
    QSettings settings;
439
    settings.beginGroup(MAIN_SETTINGS_GROUP);
440
441
    _lowPowerMode   = settings.value("LOW_POWER_MODE",      _lowPowerMode).toBool();
    _showStatusBar  = settings.value("SHOW_STATUSBAR",      _showStatusBar).toBool();
442
443
444
445
446
447
    settings.endGroup();
}

void MainWindow::storeSettings()
{
    QSettings settings;
448
    settings.beginGroup(MAIN_SETTINGS_GROUP);
449
450
    settings.setValue("LOW_POWER_MODE",     _lowPowerMode);
    settings.setValue("SHOW_STATUSBAR",     _showStatusBar);
451
    settings.endGroup();
dogmaphobic's avatar
dogmaphobic committed
452
    settings.setValue(_getWindowGeometryKey(), saveGeometry());
453

Don Gagne's avatar
Don Gagne committed
454
455
456
#ifndef __mobile__
    _storeVisibleWidgetsSettings();
#endif
457
458
459
460
}

void MainWindow::configureWindowName()
{
461
    setWindowTitle(qApp->applicationName() + " " + qApp->applicationVersion());
462
463
464
465
466
467
468
469
}

/**
* @brief Create all actions associated to the main window
*
**/
void MainWindow::connectCommonActions()
{
470
    // Connect internal actions
471
    connect(qgcApp()->toolbox()->multiVehicleManager(), &MultiVehicleManager::vehicleAdded, this, &MainWindow::_vehicleAdded);
472
473
}

Don Gagne's avatar
Don Gagne committed
474
void MainWindow::_openUrl(const QString& url, const QString& errorMessage)
475
{
Don Gagne's avatar
Don Gagne committed
476
    if(!QDesktopServices::openUrl(QUrl(url))) {
477
        qgcApp()->showMessage(QString("Could not open information in browser: %1").arg(errorMessage));
478
479
480
    }
}

481
void MainWindow::_vehicleAdded(Vehicle* vehicle)
482
{
Tomaz Canabrava's avatar
Tomaz Canabrava committed
483
    connect(vehicle->uas(), &UAS::valueChanged, this, &MainWindow::valueChanged);
484
485
}

486
487
/// Stores the state of the toolbar, status bar and widgets associated with the current view
void MainWindow::_storeCurrentViewState(void)
488
{
Don Gagne's avatar
Don Gagne committed
489
#ifndef __mobile__
Don Gagne's avatar
Don Gagne committed
490
491
    foreach(QGCDockWidget* dockWidget, _mapName2DockWidget) {
        dockWidget->saveSettings();
492
    }
Don Gagne's avatar
Don Gagne committed
493
#endif
494

dogmaphobic's avatar
dogmaphobic committed
495
    settings.setValue(_getWindowGeometryKey(), saveGeometry());
496
497
}

498
499
500
501
502
503
504
505
506
/// @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);
}

507
#ifdef QGC_MOUSE_ENABLED_LINUX
508
509
510
bool MainWindow::x11Event(XEvent *event)
{
    emit x11EventOccured(event);
511
    return false;
512
}
513
#endif // QGC_MOUSE_ENABLED_LINUX
514
515
516
517
518
519
520

#ifdef UNITTEST_BUILD
void MainWindow::_showQmlTestWidget(void)
{
    new QmlTestWidget();
}
#endif
Don Gagne's avatar
Don Gagne committed
521
522
523
524
525

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

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

Don Gagne's avatar
Don Gagne committed
529
530
    if (!widgets.isEmpty()) {
        QStringList nameList = widgets.split(",");
531

532
        foreach (const QString &name, nameList) {
Don Gagne's avatar
Don Gagne committed
533
534
535
536
537
538
539
540
541
            _showDockWidget(name, true);
        }
    }
}

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

543
    foreach (const QString &name, _mapName2DockWidget.keys()) {
Don Gagne's avatar
Don Gagne committed
544
545
546
547
548
549
        if (_mapName2DockWidget[name]->isVisible()) {
            if (!firstWidget) {
                widgetNames += ",";
            } else {
                firstWidget = false;
            }
550

Don Gagne's avatar
Don Gagne committed
551
552
553
            widgetNames += name;
        }
    }
554

Don Gagne's avatar
Don Gagne committed
555
    QSettings settings;
556

Don Gagne's avatar
Don Gagne committed
557
558
559
    settings.setValue(_visibleWidgetsKey, widgetNames);
}
#endif
560

Don Gagne's avatar
Don Gagne committed
561
QObject* MainWindow::rootQmlObject(void)
562
{
Don Gagne's avatar
Don Gagne committed
563
    return _mainQmlWidgetHolder->getRootObject();
564
}
565
566
567
568
569
570
571
572
573
574

void MainWindow::_showAdvancedUIChanged(bool advanced)
{
    if (advanced) {
        menuBar()->addMenu(_ui.menuFile);
        menuBar()->addMenu(_ui.menuWidgets);
    } else {
        menuBar()->clear();
    }
}