Newer
Older
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2013 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief Implementation of class MainWindow
* @author Lorenz Meier <mail@qgroundcontrol.org>
*/
#include <QSettings>
#include <QNetworkInterface>
#include <QDebug>
#include <QTimer>
#include <QHostInfo>
#include <QSplashScreen>
#include <QQuickView>
#include <QScreen>
#include <QDesktopServices>
#include "QGC.h"
#include "MAVLinkProtocol.h"
#include "MainWindow.h"
#include "GAudioOutput.h"
#include "QGCMAVLinkLogPlayer.h"
#include "MAVLinkDecoder.h"
#include "QGCDataPlot2D.h"
#include "Linecharts.h"
#include "QGCUASFileViewMulti.h"
#include "UASQuickView.h"
#include "QGCTabbedInfoView.h"
#include "UASRawStatusView.h"
#include "CustomCommandWidget.h"
#include "QGCDockWidget.h"
#include "FlightDisplayWidget.h"
#include "UASInfoWidget.h"
#include "HILDockWidget.h"
#endif
#ifndef __ios__
#include "SerialLink.h"
#endif
#ifdef UNITTEST_BUILD
#include "QmlControls/QmlTestWidget.h"
#endif
#ifdef QGC_OSG_ENABLED
#include "Q3DWidgetFactory.h"
#endif
dogmaphobic
committed
/// The key under which the Main Window settings are saved
const char* MAIN_SETTINGS_GROUP = "QGC_MAINWINDOW";
const char* MainWindow::_mavlinkDockWidgetName = "MAVLink Inspector";
const char* MainWindow::_customCommandWidgetName = "Custom Command";
const char* MainWindow::_filesDockWidgetName = "Onboard Files";
const char* MainWindow::_uasStatusDetailsDockWidgetName = "Status Details";
const char* MainWindow::_pfdDockWidgetName = "Primary Flight Display";
const char* MainWindow::_uasInfoViewDockWidgetName = "Info View";
const char* MainWindow::_hilDockWidgetName = "HIL Config";
const char* MainWindow::_analyzeDockWidgetName = "Analyze";
const char* MainWindow::_visibleWidgetsKey = "VisibleWidgets";
static MainWindow* _instance = NULL; ///< @brief MainWindow singleton
MainWindow* MainWindow::_create(QSplashScreen* splashScreen)
// _instance is set in constructor
Q_ASSERT(_instance);
return _instance;
}
void MainWindow::deleteInstance(void)
{
/// @brief Private constructor for MainWindow. MainWindow singleton is only ever created
/// by MainWindow::_create method. Hence no other code should have access to
/// constructor.
MainWindow::MainWindow(QSplashScreen* splashScreen)
: _autoReconnect(false)
, _lowPowerMode(false)
, _showStatusBar(false)
, _centerStackActionGroup(new QActionGroup(this))
, _centralLayout(NULL)
, _currentViewWidget(NULL)
, _splashScreen(splashScreen)
, _currentView(VIEW_SETUP)
Q_ASSERT(_instance == NULL);
_instance = this;
dogmaphobic
committed
if (splashScreen) {
connect(this, &MainWindow::initStatusChanged, splashScreen, &QSplashScreen::showMessage);
}
dogmaphobic
committed
// 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
loadSettings();
emit initStatusChanged(tr("Setting up user interface"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
_ui.setupUi(this);
// Make sure tool bar elements all fit before changing minimum width
dogmaphobic
committed
// Setup central widget with a layout to hold the views
_centralLayout = new QVBoxLayout();
_centralLayout->setContentsMargins(0,0,0,0);
centralWidget()->setLayout(_centralLayout);
// Set dock options
setDockOptions(AnimatedDocks | AllowTabbedDocks | AllowNestedDocks);
// Setup corners
setCorner(Qt::BottomRightCorner, Qt::BottomDockWidgetArea);
// On Mobile devices, we don't want any main menus at all.
#ifdef __mobile__
menuBar()->setNativeMenuBar(false);
#ifdef UNITTEST_BUILD
QAction* qmlTestAction = new QAction("Test QML palette and controls", NULL);
connect(qmlTestAction, &QAction::triggered, this, &MainWindow::_showQmlTestWidget);
_ui.menuWidgets->addAction(qmlTestAction);
// Load QML Toolbar
QDockWidget* widget = new QDockWidget(this);
widget->setObjectName("ToolBarDockWidget");
qmlRegisterType<MainToolBar>("QGroundControl.MainToolBar", 1, 0, "MainToolBar");
widget->setWidget(_mainToolBar);
widget->setFeatures(QDockWidget::NoDockWidgetFeatures);
widget->setTitleBarWidget(new QWidget(this)); // Disables the title bar
addDockWidget(Qt::TopDockWidgetArea, widget);
// Setup UI state machines
_centerStackActionGroup->setExclusive(true);
// Status Bar
statusBar()->setSizeGripEnabled(true);
Michael Carpenter
committed
Lorenz Meier
committed
emit initStatusChanged(tr("Building common widgets."), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
emit initStatusChanged(tr("Building common actions"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
// Create actions
connectCommonActions();
// Connect user interface devices
emit initStatusChanged(tr("Initializing 3D mouse interface"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
mouseInput = new Mouse3DInput(this);
mouse = new Mouse6dofInput(mouseInput);
emit initStatusChanged(tr("Initializing 3D mouse interface"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
mouse = new Mouse6dofInput(this);
Matthias Krebs
committed
connect(this, SIGNAL(x11EventOccured(XEvent*)), mouse, SLOT(handleX11Event(XEvent*)));
// These also cause the screen to redraw so we need to update any OpenGL canvases in QML controls
connect(LinkManager::instance(), &LinkManager::linkConnected, this, &MainWindow::_linkStateChange);
connect(LinkManager::instance(), &LinkManager::linkDisconnected, this, &MainWindow::_linkStateChange);
dogmaphobic
committed
restoreLastUsedConnection();
}
// Set low power mode
emit initStatusChanged(tr("Restoring last view state"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
// Restore the window setup
_loadCurrentViewState();
// Restore the window position and size
emit initStatusChanged(tr("Restoring last window size"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
if (settings.contains(_getWindowGeometryKey()))
restoreGeometry(settings.value(_getWindowGeometryKey()).toByteArray());
}
else
{
// Adjust the size
QScreen* scr = QApplication::primaryScreen();
QSize scrSize = scr->availableSize();
if (scrSize.width() <= 1280)
int w = scrSize.width() > 1600 ? 1600 : scrSize.width();
int h = scrSize.height() > 800 ? 800 : scrSize.height();
resize(w, h);
move((scrSize.width() - w) / 2, (scrSize.height() - h) / 2);
// Make sure the proper fullscreen/normal menu item is checked properly.
if (isFullScreen())
{
_ui.actionFullscreen->setChecked(true);
_ui.actionNormal->setChecked(false);
}
else
{
_ui.actionFullscreen->setChecked(false);
_ui.actionNormal->setChecked(true);
}
// And that they will stay checked properly after user input
connect(_ui.actionFullscreen, &QAction::triggered, this, &MainWindow::fullScreenActionItemCallback);
connect(_ui.actionNormal, &QAction::triggered, this, &MainWindow::normalActionItemCallback);
connect(_ui.actionStatusBar, &QAction::triggered, this, &MainWindow::showStatusBarCallback);
// Set OS dependent keyboard shortcuts for the main window, non OS dependent shortcuts are set in MainWindow.ui
#ifdef Q_OS_MACX
_ui.actionSetup->setShortcut(QApplication::translate("MainWindow", "Meta+1", 0));
_ui.actionPlan->setShortcut(QApplication::translate("MainWindow", "Meta+2", 0));
_ui.actionFlight->setShortcut(QApplication::translate("MainWindow", "Meta+3", 0));
_ui.actionFullscreen->setShortcut(QApplication::translate("MainWindow", "Meta+Return", 0));
_ui.actionSetup->setShortcut(QApplication::translate("MainWindow", "Ctrl+1", 0));
_ui.actionPlan->setShortcut(QApplication::translate("MainWindow", "Ctrl+2", 0));
_ui.actionFlight->setShortcut(QApplication::translate("MainWindow", "Ctrl+3", 0));
_ui.actionFullscreen->setShortcut(QApplication::translate("MainWindow", "Ctrl+Return", 0));
connect(&windowNameUpdateTimer, SIGNAL(timeout()), this, SLOT(configureWindowName()));
windowNameUpdateTimer.start(15000);
emit initStatusChanged(tr("Done"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
dogmaphobic
committed
if (!qgcApp()->runningUnitTests()) {
_ui.actionStatusBar->setChecked(_showStatusBar);
showStatusBarCallback(_showStatusBar);
menuBar()->hide();
#endif
dogmaphobic
committed
show();
#ifdef Q_OS_MAC
// 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
dogmaphobic
committed
}
#ifndef __mobile__
_loadVisibleWidgetsSettings();
#endif
}
MainWindow::~MainWindow()
{
// Delete all UAS objects
Michael Carpenter
committed
{
Michael Carpenter
committed
}
}
void MainWindow::resizeEvent(QResizeEvent * event)
{
QMainWindow::resizeEvent(event);
}
return QString::number(_currentView)+"_windowstate_";
{
return "_geometry";
}
void MainWindow::_buildCommonWidgets(void)
{
// Add generic MAVLink decoder
mavlinkDecoder = new MAVLinkDecoder(MAVLinkProtocol::instance(), this);
connect(mavlinkDecoder, SIGNAL(valueChanged(int,QString,QString,QVariant,quint64)),
this, SIGNAL(valueChanged(int,QString,QString,QVariant,quint64)));
// TODO: Make this optional with a preferences setting or under a "View" menu
static const char* rgDockWidgetNames[] = {
_mavlinkDockWidgetName,
_customCommandWidgetName,
_filesDockWidgetName,
_uasStatusDetailsDockWidgetName,
_pfdDockWidgetName,
_uasInfoViewDockWidgetName,
_hilDockWidgetName,
static const size_t cDockWidgetNames = sizeof(rgDockWidgetNames) / sizeof(rgDockWidgetNames[0]);
dogmaphobic
committed
for (size_t i=0; i<cDockWidgetNames; i++) {
const char* pDockWidgetName = rgDockWidgetNames[i];
// Add to menu
QAction* action = new QAction(pDockWidgetName, NULL);
action->setCheckable(true);
action->setData(pDockWidgetName);
connect(action, &QAction::triggered, this, &MainWindow::_showDockWidgetAction);
_ui.menuWidgets->addAction(action);
_mapName2Action[pDockWidgetName] = action;
/// Shows or hides the specified dock widget, creating if necessary
void MainWindow::_showDockWidget(const QString& name, bool show)
Michael Carpenter
committed
{
// Create the inner widget if we need to
if (!_mapName2DockWidget.contains(name)) {
_createInnerDockWidget(name);
Michael Carpenter
committed
}
Q_ASSERT(_mapName2DockWidget.contains(name));
QGCDockWidget* dockWidget = _mapName2DockWidget[name];
dockWidget->setVisible(show);
Q_ASSERT(_mapName2Action.contains(name));
_mapName2Action[name]->setChecked(show);
}
/// Creates the specified inner dock widget and adds to the QDockWidget
void MainWindow::_createInnerDockWidget(const QString& widgetName)
{
if (widgetName == _mavlinkDockWidgetName) {
widget = new QGCMAVLinkInspector(widgetName, _mapName2Action[widgetName], MAVLinkProtocol::instance(),this);
} else if (widgetName == _customCommandWidgetName) {
widget = new CustomCommandWidget(widgetName, _mapName2Action[widgetName], this);
} else if (widgetName == _filesDockWidgetName) {
widget = new QGCUASFileViewMulti(widgetName, _mapName2Action[widgetName], this);
} else if (widgetName == _uasStatusDetailsDockWidgetName) {
widget = new UASInfoWidget(widgetName, _mapName2Action[widgetName], this);
} else if (widgetName == _pfdDockWidgetName) {
widget = new FlightDisplayWidget(widgetName, _mapName2Action[widgetName], this);
} else if (widgetName == _hilDockWidgetName) {
widget = new HILDockWidget(widgetName, _mapName2Action[widgetName], this);
} else if (widgetName == _analyzeDockWidgetName) {
widget = new Linecharts(widgetName, _mapName2Action[widgetName], mavlinkDecoder, this);
} else if (widgetName == _uasInfoViewDockWidgetName) {
QGCTabbedInfoView* pInfoView = new QGCTabbedInfoView(widgetName, _mapName2Action[widgetName], this);
pInfoView->addSource(mavlinkDecoder);
widget = pInfoView;
} else {
qWarning() << "Attempt to create unknown Inner Dock Widget" << widgetName;
Michael Carpenter
committed
}
_mapName2DockWidget[widgetName] = widget;
Michael Carpenter
committed
}
void MainWindow::_hideAllDockWidgets(void)
{
foreach(QGCDockWidget* dockWidget, _mapName2DockWidget) {
dockWidget->setVisible(false);
}
}
void MainWindow::_showDockWidgetAction(bool show)
{
QAction* action = dynamic_cast<QAction*>(QObject::sender());
Q_ASSERT(action);
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
}
#endif
void MainWindow::_buildMissionEditorView(void)
{
if (!_missionEditorView) {
_missionEditorView = new MissionEditor(this);
_missionEditorView->setVisible(false);
}
}
void MainWindow::_buildFlightView(void)
{
if (!_flightView) {
_flightView = new FlightDisplayView(this);
_flightView->setVisible(false);
}
}
void MainWindow::_buildSetupView(void)
{
if (!_setupView) {
_setupView = new SetupView(this);
_setupView->setVisible(false);
}
}
void MainWindow::fullScreenActionItemCallback(bool)
void MainWindow::normalActionItemCallback(bool)
void MainWindow::showStatusBarCallback(bool checked)
{
_showStatusBar = checked;
checked ? statusBar()->show() : statusBar()->hide();
}
void MainWindow::closeEvent(QCloseEvent *event)
{
// Disallow window close if there are active connections
if (LinkManager::instance()->anyConnectedLinks()) {
QGCMessageBox::StandardButton button =
QGCMessageBox::warning(
tr("QGroundControl close"),
tr("There are still active connections to vehicles. Do you want to disconnect these before closing?"),
QMessageBox::Yes | QMessageBox::Cancel,
QMessageBox::Cancel);
if (button == QMessageBox::Yes) {
LinkManager::instance()->disconnectAll();
// The above disconnect causes a flurry of activity as the vehicle components are removed. This in turn
// causes the Windows Version of Qt to crash if you allow the close event to be accepted. In order to prevent
// the crash, we ignore the close event and setup a delayed timer to close the window after things settle down.
QTimer::singleShot(1500, this, &MainWindow::_closeWindow);
}
event->ignore();
return;
// This will process any remaining flight log save dialogs
qgcApp()->processEvents(QEventLoop::ExcludeUserInputEvents);
// Should not be any active connections
Q_ASSERT(!LinkManager::instance()->anyConnectedLinks());
_storeCurrentViewState();
Michael Carpenter
committed
storeSettings();
}
void MainWindow::loadSettings()
{
dogmaphobic
committed
// Why the screaming?
QSettings settings;
dogmaphobic
committed
settings.beginGroup(MAIN_SETTINGS_GROUP);
_autoReconnect = settings.value("AUTO_RECONNECT", _autoReconnect).toBool();
_lowPowerMode = settings.value("LOW_POWER_MODE", _lowPowerMode).toBool();
_showStatusBar = settings.value("SHOW_STATUSBAR", _showStatusBar).toBool();
settings.endGroup();
}
void MainWindow::storeSettings()
{
QSettings settings;
dogmaphobic
committed
settings.beginGroup(MAIN_SETTINGS_GROUP);
settings.setValue("AUTO_RECONNECT", _autoReconnect);
settings.setValue("LOW_POWER_MODE", _lowPowerMode);
settings.setValue("SHOW_STATUSBAR", _showStatusBar);
settings.setValue(_getWindowGeometryKey(), saveGeometry());
// Save the last current view in any case
settings.setValue("CURRENT_VIEW", _currentView);
settings.setValue(_getWindowStateKey(), saveState());
#ifndef __mobile__
_storeVisibleWidgetsSettings();
#endif
}
void MainWindow::configureWindowName()
{
QList<QHostAddress> hostAddresses = QNetworkInterface::allAddresses();
QString windowname = qApp->applicationName() + " " + qApp->applicationVersion();
bool prevAddr = false;
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(")");
setWindowTitle(windowname);
}
void MainWindow::enableAutoReconnect(bool enabled)
{
}
/**
* @brief Create all actions associated to the main window
*
**/
void MainWindow::connectCommonActions()
{
// Bind together the perspective actions
QActionGroup* perspectives = new QActionGroup(_ui.menuPerspectives);
perspectives->addAction(_ui.actionPlan);
perspectives->setExclusive(true);
if (_currentView == VIEW_FLIGHT)
_ui.actionFlight->setChecked(true);
_ui.actionFlight->activate(QAction::Trigger);
if (_currentView == VIEW_MISSIONEDITOR)
_ui.actionPlan->setChecked(true);
_ui.actionPlan->activate(QAction::Trigger);
}
if (_currentView == VIEW_SETUP)
_ui.actionSetup->setChecked(true);
_ui.actionSetup->activate(QAction::Trigger);
Michael Carpenter
committed
}
// Connect actions from ui
connect(_ui.actionAdd_Link, SIGNAL(triggered()), this, SLOT(manageLinks()));
// Connect internal actions
connect(MultiVehicleManager::instance(), &MultiVehicleManager::vehicleAdded, this, &MainWindow::_vehicleAdded);
// Views actions
connect(_ui.actionFlight, SIGNAL(triggered()), this, SLOT(loadFlightView()));
connect(_ui.actionPlan, SIGNAL(triggered()), this, SLOT(loadPlanView()));
connect(_ui.actionOnline_Documentation, SIGNAL(triggered()), this, SLOT(showHelp()));
connect(_ui.actionDeveloper_Credits, SIGNAL(triggered()), this, SLOT(showCredits()));
connect(_ui.actionProject_Roadmap, SIGNAL(triggered()), this, SLOT(showRoadMap()));
// Audio output
_ui.actionMuteAudioOutput->setChecked(GAudioOutput::instance()->isMuted());
connect(GAudioOutput::instance(), SIGNAL(mutedChanged(bool)), _ui.actionMuteAudioOutput, SLOT(setChecked(bool)));
connect(_ui.actionMuteAudioOutput, SIGNAL(triggered(bool)), GAudioOutput::instance(), SLOT(mute(bool)));
// Application Settings
connect(_ui.actionSettings, SIGNAL(triggered()), this, SLOT(showSettings()));
_mainToolBar->setCurrentView(_currentView);
void MainWindow::_openUrl(const QString& url, const QString& errorMessage)
QMessageBox::critical(
this,
tr("Could not open information in browser"),
errorMessage);
_openUrl(
"http://qgroundcontrol.org/users/start",
tr("To get to the online help, please open http://qgroundcontrol.org/user_guide in a browser."));
void MainWindow::showCredits()
{
_openUrl(
"http://qgroundcontrol.org/credits",
tr("To get to the credits, please open http://qgroundcontrol.org/credits in a browser."));
}
void MainWindow::showRoadMap()
{
_openUrl(
"http://qgroundcontrol.org/dev/roadmap",
tr("To get to the online help, please open http://qgroundcontrol.org/roadmap in a browser."));
}
void MainWindow::showSettings()
{
Michael Carpenter
committed
void MainWindow::commsWidgetDestroyed(QObject *obj)
{
// Do not dynamic cast or de-reference QObject, since object is either in destructor or may have already
// been destroyed.
Michael Carpenter
committed
{
Michael Carpenter
committed
}
}
void MainWindow::_vehicleAdded(Vehicle* vehicle)
connect(vehicle->uas(), SIGNAL(valueChanged(int,QString,QString,QVariant,quint64)), this, SIGNAL(valueChanged(int,QString,QString,QVariant,quint64)));
/// Stores the state of the toolbar, status bar and widgets associated with the current view
void MainWindow::_storeCurrentViewState(void)
foreach(QGCDockWidget* dockWidget, _mapName2DockWidget) {
dockWidget->saveSettings();
settings.setValue(_getWindowStateKey(), saveState());
settings.setValue(_getWindowGeometryKey(), saveGeometry());
/// Restores the state of the toolbar, status bar and widgets associated with the current view
void MainWindow::_loadCurrentViewState(void)
dogmaphobic
committed
_buildSetupView();
centerView = _setupView;
break;
dogmaphobic
committed
case VIEW_FLIGHT:
_buildFlightView();
centerView = _flightView;
dogmaphobic
committed
case VIEW_MISSIONEDITOR:
_buildMissionEditorView();
centerView = _missionEditorView;
break;
dogmaphobic
committed
// Remove old view
if (_currentViewWidget) {
_currentViewWidget->setVisible(false);
Q_ASSERT(_centralLayout->count() == 1);
QLayoutItem *child = _centralLayout->takeAt(0);
Q_ASSERT(child);
delete child;
}
dogmaphobic
committed
// Add the new one
Q_ASSERT(centerView);
Q_ASSERT(_centralLayout->count() == 0);
_currentViewWidget = centerView;
_centralLayout->addWidget(_currentViewWidget);
_centralLayout->setContentsMargins(0, 0, 0, 0);
_currentViewWidget->setVisible(true);
dogmaphobic
committed
if (settings.contains(_getWindowStateKey())) {
restoreState(settings.value(_getWindowStateKey()).toByteArray());
Michael Carpenter
committed
}
dogmaphobic
committed
// There is a bug in Qt where a Canvas element inside a QQuickWidget does not
// receive update requests. Here we emit a signal for them to get repainted.
emit repaintCanvas();
if (_currentView != VIEW_MISSIONEDITOR)
{
_storeCurrentViewState();
_currentView = VIEW_MISSIONEDITOR;
_ui.actionPlan->setChecked(true);
_loadCurrentViewState();
void MainWindow::loadSetupView()
Michael Carpenter
committed
{
if (_currentView != VIEW_SETUP)
Michael Carpenter
committed
{
_storeCurrentViewState();
_currentView = VIEW_SETUP;
_loadCurrentViewState();
Michael Carpenter
committed
}
}
if (_currentView != VIEW_FLIGHT)
_storeCurrentViewState();
_currentView = VIEW_FLIGHT;
_loadCurrentViewState();
/// @brief Hides the spash screen if it is currently being shown
void MainWindow::hideSplashScreen(void)
{
if (_splashScreen) {
_splashScreen->hide();
_splashScreen = NULL;
}
}
dogmaphobic
committed
void MainWindow::manageLinks()
{
SettingsDialog settings(this, SettingsDialog::ShowCommLinks);
dogmaphobic
committed
settings.exec();
}
/// @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);
}
/// @brief Restore (and connects) the last used connection (if any)
void MainWindow::restoreLastUsedConnection()
{
// TODO This should check and see of the port/whatever is present
// first. That is, if the last connection was to a PX4 on some serial
// port, it should check and see if the port is present before making
// the connection.
QSettings settings;
QString key(MAIN_SETTINGS_GROUP);
key += "/LAST_CONNECTION";
if(settings.contains(key)) {
QString connection = settings.value(key).toString();
dogmaphobic
committed
// Create a link for it
LinkManager::instance()->createConnectedLink(connection);
dogmaphobic
committed
}
}
void MainWindow::_linkStateChange(LinkInterface*)
{
emit repaintCanvas();
}
bool MainWindow::x11Event(XEvent *event)
{
emit x11EventOccured(event);
Matthias Krebs
committed
return false;
#ifdef UNITTEST_BUILD
void MainWindow::_showQmlTestWidget(void)
{
new QmlTestWidget();
}
#endif
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
#ifndef __mobile__
void MainWindow::_loadVisibleWidgetsSettings(void)
{
QSettings settings;
QString widgets = settings.value(_visibleWidgetsKey).toString();
if (!widgets.isEmpty()) {
QStringList nameList = widgets.split(",");
foreach (QString name, nameList) {
_showDockWidget(name, true);
}
}
}
void MainWindow::_storeVisibleWidgetsSettings(void)
{
QString widgetNames;
bool firstWidget = true;
foreach (QString name, _mapName2DockWidget.keys()) {
if (_mapName2DockWidget[name]->isVisible()) {
if (!firstWidget) {
widgetNames += ",";
} else {
firstWidget = false;
}
widgetNames += name;
}
}
QSettings settings;
settings.setValue(_visibleWidgetsKey, widgetNames);
}
#endif