MainWindow.cc 17 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
44

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

dogmaphobic's avatar
dogmaphobic committed
208
#ifndef __mobile__
209

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

235
    connect(_ui.actionStatusBar,  &QAction::triggered, this, &MainWindow::showStatusBarCallback);
236

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

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

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

MainWindow::~MainWindow()
{
277
278
279
280
281
    // Enforce thread-safe shutdown of the mavlink decoder
    mavlinkDecoder->finish();
    mavlinkDecoder->wait(1000);
    mavlinkDecoder->deleteLater();

282
283
284
285
    // 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
286
    _instance = NULL;
287
288
}

dogmaphobic's avatar
dogmaphobic committed
289
QString MainWindow::_getWindowGeometryKey()
290
291
292
293
{
    return "_geometry";
}

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

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

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

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

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

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

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

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

384
385
void MainWindow::_hideAllDockWidgets(void)
{
Don Gagne's avatar
Don Gagne committed
386
    foreach(QGCDockWidget* dockWidget, _mapName2DockWidget) {
387
388
389
390
391
392
        dockWidget->setVisible(false);
    }
}

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

399
400
401
402
403
404
void MainWindow::showStatusBarCallback(bool checked)
{
    _showStatusBar = checked;
    checked ? statusBar()->show() : statusBar()->hide();
}

405
void MainWindow::reallyClose(void)
406
{
407
408
    _forceClose = true;
    close();
409
410
}

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

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

425
    _storeCurrentViewState();
426
    storeSettings();
427
428

    emit mainWindowClosed();
429
430
431
432
}

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

void MainWindow::storeSettings()
{
    QSettings settings;
444
    settings.beginGroup(MAIN_SETTINGS_GROUP);
445
446
    settings.setValue("LOW_POWER_MODE",     _lowPowerMode);
    settings.setValue("SHOW_STATUSBAR",     _showStatusBar);
447
    settings.endGroup();
dogmaphobic's avatar
dogmaphobic committed
448
    settings.setValue(_getWindowGeometryKey(), saveGeometry());
449

Don Gagne's avatar
Don Gagne committed
450
451
452
#ifndef __mobile__
    _storeVisibleWidgetsSettings();
#endif
453
454
455
456
}

void MainWindow::configureWindowName()
{
457
    setWindowTitle(qApp->applicationName() + " " + qApp->applicationVersion());
458
459
460
461
462
463
464
465
}

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

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

477
void MainWindow::_vehicleAdded(Vehicle* vehicle)
478
{
Tomaz Canabrava's avatar
Tomaz Canabrava committed
479
    connect(vehicle->uas(), &UAS::valueChanged, this, &MainWindow::valueChanged);
480
481
}

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

dogmaphobic's avatar
dogmaphobic committed
491
    settings.setValue(_getWindowGeometryKey(), saveGeometry());
492
493
}

494
495
496
497
498
499
500
501
502
/// @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);
}

503
#ifdef QGC_MOUSE_ENABLED_LINUX
504
505
506
bool MainWindow::x11Event(XEvent *event)
{
    emit x11EventOccured(event);
507
    return false;
508
}
509
#endif // QGC_MOUSE_ENABLED_LINUX
510
511
512
513
514
515
516

#ifdef UNITTEST_BUILD
void MainWindow::_showQmlTestWidget(void)
{
    new QmlTestWidget();
}
#endif
Don Gagne's avatar
Don Gagne committed
517
518
519
520
521

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

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

Don Gagne's avatar
Don Gagne committed
525
526
    if (!widgets.isEmpty()) {
        QStringList nameList = widgets.split(",");
527

528
        foreach (const QString &name, nameList) {
Don Gagne's avatar
Don Gagne committed
529
530
531
532
533
534
535
536
537
            _showDockWidget(name, true);
        }
    }
}

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

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

Don Gagne's avatar
Don Gagne committed
547
548
549
            widgetNames += name;
        }
    }
550

Don Gagne's avatar
Don Gagne committed
551
    QSettings settings;
552

Don Gagne's avatar
Don Gagne committed
553
554
555
    settings.setValue(_visibleWidgetsKey, widgetNames);
}
#endif
556

Don Gagne's avatar
Don Gagne committed
557
QObject* MainWindow::rootQmlObject(void)
558
{
Don Gagne's avatar
Don Gagne committed
559
    return _mainQmlWidgetHolder->getRootObject();
560
}