From 4f080b9d3db259b87c46113a4a34cf120519ac80 Mon Sep 17 00:00:00 2001 From: Don Gagne <don@thegagnes.com> Date: Tue, 8 Dec 2015 11:36:54 -0800 Subject: [PATCH] Mobile runs Native QML --- QGCCommon.pri | 1 - qgroundcontrol.pro | 4 +- qgroundcontrol.qrc | 4 +- src/AutoPilotPlugins/AutoPilotPlugin.cc | 3 +- src/QGCApplication.cc | 91 +++++- src/QGCApplication.h | 23 +- src/QmlControls/ParameterEditorController.cc | 2 +- src/QmlControls/QGroundControlQmlGlobal.cc | 6 - src/QmlControls/QGroundControlQmlGlobal.h | 5 - src/QmlControls/ScreenToolsController.cc | 1 - src/VehicleSetup/SetupViewTest.cc | 10 +- src/comm/LinkManager.cc | 12 +- src/comm/LinkManager.h | 2 +- src/main.cc | 1 - src/ui/MainWindow.cc | 20 +- src/ui/MainWindow.h | 25 +- src/ui/MainWindow.qml | 424 -------------------------- src/ui/MainWindowHybrid.qml | 75 +++++ src/ui/MainWindowInner.qml | 438 +++++++++++++++++++++++++++ src/ui/MainWindowNative.qml | 90 ++++++ src/ui/preferences/GeneralSettings.qml | 9 - src/ui/toolbar/MainToolBar.qml | 35 ++- src/ui/toolbar/MainToolBarController.cc | 16 - src/ui/toolbar/MainToolBarController.h | 4 - 24 files changed, 754 insertions(+), 547 deletions(-) delete mode 100644 src/ui/MainWindow.qml create mode 100644 src/ui/MainWindowHybrid.qml create mode 100644 src/ui/MainWindowInner.qml create mode 100644 src/ui/MainWindowNative.qml diff --git a/QGCCommon.pri b/QGCCommon.pri index ef571bd..52d71ef 100644 --- a/QGCCommon.pri +++ b/QGCCommon.pri @@ -37,7 +37,6 @@ linux { DEFINES += __android__ DEFINES += __STDC_LIMIT_MACROS target.path = $$DESTDIR - warning("Android build is experimental and not fully functional") } else { error("Unsuported Linux toolchain, only GCC 32- or 64-bit is supported") } diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index c4f265c..98dc921 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -278,7 +278,6 @@ HEADERS += \ src/uas/UAS.h \ src/uas/UASInterface.h \ src/uas/UASMessageHandler.h \ - src/ui/MainWindow.h \ src/ui/toolbar/MainToolBarController.h \ src/AutoPilotPlugins/PX4/PX4AirframeLoader.h \ src/QmlControls/QGCImageProvider.h \ @@ -327,6 +326,7 @@ HEADERS += \ src/ui/linechart/Scrollbar.h \ src/ui/linechart/ScrollZoomer.h \ src/ui/LogReplayLinkConfigurationWidget.h \ + src/ui/MainWindow.h \ src/ui/MAVLinkDecoder.h \ src/ui/MAVLinkSettingsWidget.h \ src/ui/MultiVehicleDockWidget.h \ @@ -400,7 +400,6 @@ SOURCES += \ src/QmlControls/QmlObjectListModel.cc \ src/uas/UAS.cc \ src/uas/UASMessageHandler.cc \ - src/ui/MainWindow.cc \ src/ui/toolbar/MainToolBarController.cc \ src/AutoPilotPlugins/PX4/PX4AirframeLoader.cc \ src/QmlControls/QGCImageProvider.cc \ @@ -453,6 +452,7 @@ SOURCES += \ src/ui/linechart/LinechartWidget.cc \ src/ui/linechart/Scrollbar.cc \ src/ui/linechart/ScrollZoomer.cc \ + src/ui/MainWindow.cc \ src/ui/MultiVehicleDockWidget.cc \ src/ui/QGCDataPlot2D.cc \ src/ui/QGCHilConfiguration.cc \ diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc index f6e741b..54bf367 100644 --- a/qgroundcontrol.qrc +++ b/qgroundcontrol.qrc @@ -32,7 +32,9 @@ <file alias="JoystickConfig.qml">src/VehicleSetup/JoystickConfig.qml</file> <file alias="MainToolBar.qml">src/ui/toolbar/MainToolBar.qml</file> - <file alias="MainWindow.qml">src/ui/MainWindow.qml</file> + <file alias="MainWindowHybrid.qml">src/ui/MainWindowHybrid.qml</file> + <file alias="MainWindowInner.qml">src/ui/MainWindowInner.qml</file> + <file alias="MainWindowNative.qml">src/ui/MainWindowNative.qml</file> <file alias="MainWindowLeftPanel.qml">src/ui/MainWindowLeftPanel.qml</file> <file alias="MissionEditor.qml">src/MissionEditor/MissionEditor.qml</file> <file alias="MissionEditorHelp.qml">src/MissionEditor/MissionEditorHelp.qml</file> diff --git a/src/AutoPilotPlugins/AutoPilotPlugin.cc b/src/AutoPilotPlugins/AutoPilotPlugin.cc index d44f95d..dd92394 100644 --- a/src/AutoPilotPlugins/AutoPilotPlugin.cc +++ b/src/AutoPilotPlugins/AutoPilotPlugin.cc @@ -26,7 +26,6 @@ #include "AutoPilotPlugin.h" #include "QGCApplication.h" -#include "MainWindow.h" #include "ParameterLoader.h" #include "UAS.h" #include "FirmwarePlugin.h" @@ -65,7 +64,7 @@ void AutoPilotPlugin::_parametersReadyChanged(bool parametersReady) qgcApp()->showMessage("One or more vehicle components require setup prior to flight."); // Take the user to Vehicle Summary - MainWindow::instance()->showSetupView(); + qgcApp()->showSetupView(); qgcApp()->processEvents(QEventLoop::ExcludeUserInputEvents); } } diff --git a/src/QGCApplication.cc b/src/QGCApplication.cc index 50ee6e7..a0462f6 100644 --- a/src/QGCApplication.cc +++ b/src/QGCApplication.cc @@ -43,10 +43,8 @@ #include "QGC.h" #include "QGCApplication.h" -#include "MainWindow.h" #include "GAudioOutput.h" #include "CmdLineOptParser.h" -#include "MainWindow.h" #include "UDPLink.h" #include "LinkManager.h" #include "HomePositionManager.h" @@ -101,6 +99,7 @@ #include "QGCMessageBox.h" #include "FirmwareUpgradeController.h" #include "JoystickConfigController.h" + #include "MainWindow.h" #endif #ifdef QGC_RTLAB_ENABLED @@ -154,7 +153,12 @@ static QObject* qgroundcontrolQmlGlobalSingletonFactory(QQmlEngine*, QJSEngine*) **/ QGCApplication::QGCApplication(int &argc, char* argv[], bool unitTesting) +#ifdef __mobile__ + : QGuiApplication(argc, argv) + , _qmlAppEngine(NULL) +#else : QApplication(argc, argv) +#endif , _runningUnitTests(unitTesting) #if defined (__mobile__) , _styleIsDark(false) @@ -323,10 +327,12 @@ QGCApplication::QGCApplication(int &argc, char* argv[], bool unitTesting) QGCApplication::~QGCApplication() { +#ifndef __mobile__ MainWindow* mainWindow = MainWindow::instance(); if (mainWindow) { delete mainWindow; } +#endif shutdownVideoStreaming(); delete _toolbox; } @@ -446,18 +452,23 @@ bool QGCApplication::_initForNormalAppBoot(void) // Exit main application when last window is closed connect(this, SIGNAL(lastWindowClosed()), this, SLOT(quit())); +#ifdef __mobile__ + _qmlAppEngine = new QQmlApplicationEngine(this); + _qmlAppEngine->addImportPath("qrc:/qml"); + _qmlAppEngine->rootContext()->setContextProperty("multiVehicleManager", toolbox()->multiVehicleManager()); + _qmlAppEngine->rootContext()->setContextProperty("joystickManager", toolbox()->joystickManager()); + _qmlAppEngine->load(QUrl(QStringLiteral("qrc:/qml/MainWindowNative.qml"))); +#else // Start the user interface MainWindow* mainWindow = MainWindow::_create(); Q_CHECK_PTR(mainWindow); -#ifndef __mobile__ // If we made it this far and we still don't have a location. Either the specfied location was invalid // or we coudn't create a default location. Either way, we need to let the user know and prompt for a new /// settings. QString savedFilesLocation = settings.value(_savedFilesLocationKey).toString(); if (savedFilesLocation.isEmpty()) { showMessage("The location to save files to is invalid, or cannot be written to. Please provide a new one."); - mainWindow->showSettings(); } // Now that main window is up check for lost log files @@ -653,12 +664,10 @@ void QGCApplication::setStyle(bool styleIsDark) void QGCApplication::_loadCurrentStyle(void) { +#ifndef __mobile__ bool success = true; QString styles; - // Signal to the user that the app will pause to apply a new stylesheet - setOverrideCursor(Qt::WaitCursor); - // The dark style sheet is the master. Any other selected style sheet just overrides // the colors of the master sheet. QFile masterStyleSheet(_darkStyleFile); @@ -687,11 +696,9 @@ void QGCApplication::_loadCurrentStyle(void) // Fall back to plastique if we can't load our own setStyle("plastique"); } +#endif QGCPalette::setGlobalTheme(_styleIsDark ? QGCPalette::Dark : QGCPalette::Light); - - // Finally restore the cursor before returning. - restoreOverrideCursor(); } void QGCApplication::reportMissingParameter(int componentId, const QString& name) @@ -718,12 +725,64 @@ void QGCApplication::_missingParamsDisplay(void) showMessage(QString("Parameters missing from firmware: %1.\n\nYou should quit QGroundControl immediately and update your firmware.").arg(params)); } +QObject* QGCApplication::_rootQmlObject(void) +{ +#ifdef __mobile__ + return _qmlAppEngine->rootObjects()[0]; +#else + return MainWindow::instance()->rootQmlObject(); +#endif +} + + void QGCApplication::showMessage(const QString& message) { - MainWindow* mainWindow = MainWindow::instance(); - if (mainWindow) { - mainWindow->showMessage(message); - } else { - qWarning() << "showMessage with no mainWindow" << message; - } + QVariant varReturn; + QVariant varMessage = QVariant::fromValue(message); + + QMetaObject::invokeMethod(_rootQmlObject(), "showMessage", Q_RETURN_ARG(QVariant, varReturn), Q_ARG(QVariant, varMessage)); +} + +void QGCApplication::showFlyView(void) +{ + QMetaObject::invokeMethod(_rootQmlObject(), "showFlyView"); +} + +void QGCApplication::showPlanView(void) +{ + QMetaObject::invokeMethod(_rootQmlObject(), "showPlanView"); +} + +void QGCApplication::showSetupView(void) +{ + QMetaObject::invokeMethod(_rootQmlObject(), "showSetupView"); +} + +void QGCApplication::showWindowCloseMessage(void) +{ + QMetaObject::invokeMethod(_rootQmlObject(), "showWindowCloseMessage"); +} + + +void QGCApplication::_showSetupFirmware(void) +{ + QMetaObject::invokeMethod(_rootQmlObject(), "showSetupFirmware"); +} + +void QGCApplication::_showSetupParameters(void) +{ + QMetaObject::invokeMethod(_rootQmlObject(), "showSetupParameters"); +} + +void QGCApplication::_showSetupSummary(void) +{ + QMetaObject::invokeMethod(_rootQmlObject(), "showSetupSummary"); +} + +void QGCApplication::_showSetupVehicleComponent(VehicleComponent* vehicleComponent) +{ + QVariant varReturn; + QVariant varComponent = QVariant::fromValue(vehicleComponent); + + QMetaObject::invokeMethod(_rootQmlObject(), "showSetupVehicleComponent", Q_RETURN_ARG(QVariant, varReturn), Q_ARG(QVariant, varComponent)); } diff --git a/src/QGCApplication.h b/src/QGCApplication.h index 3d0e62d..4928039 100644 --- a/src/QGCApplication.h +++ b/src/QGCApplication.h @@ -64,7 +64,12 @@ class QGCToolbox; * the central management unit of the groundstation application. * **/ -class QGCApplication : public QApplication +class QGCApplication : public +#ifdef __mobile__ + QGuiApplication // Native Qml based application +#else + QApplication // QtWidget based application +#endif { Q_OBJECT @@ -138,6 +143,12 @@ public slots: /// You can connect to this slot to show a critical message box from a different thread. void criticalMessageBoxOnMainThread(const QString& title, const QString& msg); + void showFlyView(void); + void showPlanView(void); + void showSetupView(void); + + void showWindowCloseMessage(void); + #ifndef __mobile__ /// Save the specified Flight Data Log void saveTempFlightDataLogOnMainThread(QString tempLogfile); @@ -166,6 +177,11 @@ public: /// @brief Intialize the application for normal application boot. Or in other words we are not going to run /// unit tests. Although public should only be called by main. bool _initForUnitTests(void); + + void _showSetupFirmware(void); + void _showSetupParameters(void); + void _showSetupSummary(void); + void _showSetupVehicleComponent(VehicleComponent* vehicleComponent); static QGCApplication* _app; ///< Our own singleton. Should be reference directly by qgcApp @@ -174,6 +190,11 @@ private slots: private: void _loadCurrentStyle(void); + QObject* _rootQmlObject(void); + +#ifdef __mobile__ + QQmlApplicationEngine* _qmlAppEngine; +#endif static const char* _settingsVersionKey; ///< Settings key which hold settings version static const char* _deleteAllSettingsKey; ///< If this settings key is set on boot, all settings will be deleted diff --git a/src/QmlControls/ParameterEditorController.cc b/src/QmlControls/ParameterEditorController.cc index 364e14c..6f441ec 100644 --- a/src/QmlControls/ParameterEditorController.cc +++ b/src/QmlControls/ParameterEditorController.cc @@ -26,12 +26,12 @@ #include "ParameterEditorController.h" #include "AutoPilotPluginManager.h" -#include "MainWindow.h" #include "QGCApplication.h" #ifndef __mobile__ #include "QGCFileDialog.h" #include "QGCMapRCToParamDialog.h" +#include "MainWindow.h" #endif /// @Brief Constructs a new ParameterEditorController Widget. This widget is used within the PX4VehicleConfig set of screens. diff --git a/src/QmlControls/QGroundControlQmlGlobal.cc b/src/QmlControls/QGroundControlQmlGlobal.cc index 5feb34a..67e6483 100644 --- a/src/QmlControls/QGroundControlQmlGlobal.cc +++ b/src/QmlControls/QGroundControlQmlGlobal.cc @@ -138,12 +138,6 @@ void QGroundControlQmlGlobal::setIsAudioMuted(bool muted) emit isAudioMutedChanged(muted); } -void QGroundControlQmlGlobal::setIsLowPowerMode(bool low) -{ - MainWindow::instance()->enableLowPowerMode(low); - emit isLowPowerModeChanged(low); -} - void QGroundControlQmlGlobal::setIsSaveLogPrompt(bool prompt) { qgcApp()->setPromptFlightDataSave(prompt); diff --git a/src/QmlControls/QGroundControlQmlGlobal.h b/src/QmlControls/QGroundControlQmlGlobal.h index d543698..ab7057f 100644 --- a/src/QmlControls/QGroundControlQmlGlobal.h +++ b/src/QmlControls/QGroundControlQmlGlobal.h @@ -30,7 +30,6 @@ #include <QObject> #include "QGCApplication.h" -#include "MainWindow.h" #include "LinkManager.h" #include "HomePositionManager.h" #include "FlightMapSettings.h" @@ -63,7 +62,6 @@ public: Q_PROPERTY(bool isAdvancedMode READ isAdvancedMode CONSTANT) ///< Global "Advance Mode" preference. Certain UI elements and features are different based on this. Q_PROPERTY(bool isDarkStyle READ isDarkStyle WRITE setIsDarkStyle NOTIFY isDarkStyleChanged) // TODO: Should be in ScreenTools? Q_PROPERTY(bool isAudioMuted READ isAudioMuted WRITE setIsAudioMuted NOTIFY isAudioMutedChanged) - Q_PROPERTY(bool isLowPowerMode READ isLowPowerMode WRITE setIsLowPowerMode NOTIFY isLowPowerModeChanged) Q_PROPERTY(bool isSaveLogPrompt READ isSaveLogPrompt WRITE setIsSaveLogPrompt NOTIFY isSaveLogPromptChanged) Q_PROPERTY(bool isSaveLogPromptNotArmed READ isSaveLogPromptNotArmed WRITE setIsSaveLogPromptNotArmed NOTIFY isSaveLogPromptNotArmedChanged) Q_PROPERTY(bool isHeartBeatEnabled READ isHeartBeatEnabled WRITE setIsHeartBeatEnabled NOTIFY isHeartBeatEnabledChanged) @@ -99,7 +97,6 @@ public: bool isDarkStyle () { return qgcApp()->styleIsDark(); } bool isAudioMuted () { return qgcApp()->toolbox()->audioOutput()->isMuted(); } - bool isLowPowerMode () { return MainWindow::instance()->lowPowerModeEnabled(); } bool isSaveLogPrompt () { return qgcApp()->promptFlightDataSave(); } bool isSaveLogPromptNotArmed () { return qgcApp()->promptFlightDataSaveNotArmed(); } bool isHeartBeatEnabled () { return qgcApp()->toolbox()->mavlinkProtocol()->heartbeatsEnabled(); } @@ -112,7 +109,6 @@ public: void setIsDarkStyle (bool dark); void setIsAudioMuted (bool muted); - void setIsLowPowerMode (bool low); void setIsSaveLogPrompt (bool prompt); void setIsSaveLogPromptNotArmed (bool prompt); void setIsHeartBeatEnabled (bool enable); @@ -123,7 +119,6 @@ public: signals: void isDarkStyleChanged (bool dark); void isAudioMutedChanged (bool muted); - void isLowPowerModeChanged (bool lowPower); void isSaveLogPromptChanged (bool prompt); void isSaveLogPromptNotArmedChanged (bool prompt); void isHeartBeatEnabledChanged (bool enabled); diff --git a/src/QmlControls/ScreenToolsController.cc b/src/QmlControls/ScreenToolsController.cc index 9380bf7..9717284 100644 --- a/src/QmlControls/ScreenToolsController.cc +++ b/src/QmlControls/ScreenToolsController.cc @@ -25,7 +25,6 @@ /// @author Gus Grubba <mavlink@grubba.com> #include "ScreenToolsController.h" -#include "MainWindow.h" #ifdef Q_OS_WIN const double ScreenToolsController::_defaultFontPixelSizeRatio = 1.0; diff --git a/src/VehicleSetup/SetupViewTest.cc b/src/VehicleSetup/SetupViewTest.cc index 649d9a3..5da316b 100644 --- a/src/VehicleSetup/SetupViewTest.cc +++ b/src/VehicleSetup/SetupViewTest.cc @@ -39,25 +39,25 @@ void SetupViewTest::_clickThrough_test(void) _createMainWindow(); // Switch to the Setup view - _mainWindow->showSetupView(); + qgcApp()->showSetupView(); QTest::qWait(1000); // Click through fixed buttons qDebug() << "Showing firmware"; - _mainWindow->showSetupFirmware(); + qgcApp()->_showSetupFirmware(); QTest::qWait(1000); qDebug() << "Showing parameters"; - _mainWindow->showSetupParameters(); + qgcApp()->_showSetupParameters(); QTest::qWait(1000); qDebug() << "Showing summary"; - _mainWindow->showSetupSummary(); + qgcApp()->_showSetupSummary(); QTest::qWait(1000); const QVariantList& components = autopilot->vehicleComponents(); foreach(QVariant varComponent, components) { VehicleComponent* component = qobject_cast<VehicleComponent*>(qvariant_cast<QObject *>(varComponent)); qDebug() << "Showing" << component->name(); - _mainWindow->showSetupVehicleComponent(component); + qgcApp()->_showSetupVehicleComponent(component); QTest::qWait(1000); } diff --git a/src/comm/LinkManager.cc b/src/comm/LinkManager.cc index 0e12c74..a023ad5 100644 --- a/src/comm/LinkManager.cc +++ b/src/comm/LinkManager.cc @@ -38,7 +38,6 @@ This file is part of the QGROUNDCONTROL project #endif #include "LinkManager.h" -#include "MainWindow.h" #include "QGCApplication.h" #include "QGCApplication.h" #include "UDPLink.h" @@ -189,14 +188,11 @@ void LinkManager::_addLink(LinkInterface* link) emit newLink(link); } - // MainWindow may be around when doing things like running unit tests - if (MainWindow::instance()) { - connect(link, &LinkInterface::communicationError, _app, &QGCApplication::criticalMessageBoxOnMainThread); - } + connect(link, &LinkInterface::communicationError, _app, &QGCApplication::criticalMessageBoxOnMainThread); + connect(link, &LinkInterface::bytesReceived, _mavlinkProtocol, &MAVLinkProtocol::receiveBytes); + connect(link, &LinkInterface::connected, _mavlinkProtocol, &MAVLinkProtocol::linkConnected); + connect(link, &LinkInterface::disconnected, _mavlinkProtocol, &MAVLinkProtocol::linkDisconnected); - connect(link, &LinkInterface::bytesReceived, _mavlinkProtocol, &MAVLinkProtocol::receiveBytes); - connect(link, &LinkInterface::connected, _mavlinkProtocol, &MAVLinkProtocol::linkConnected); - connect(link, &LinkInterface::disconnected, _mavlinkProtocol, &MAVLinkProtocol::linkDisconnected); _mavlinkProtocol->resetMetadataForLink(link); connect(link, &LinkInterface::connected, this, &LinkManager::_linkConnected); diff --git a/src/comm/LinkManager.h b/src/comm/LinkManager.h index ff1b1a8..473a206 100644 --- a/src/comm/LinkManager.h +++ b/src/comm/LinkManager.h @@ -169,7 +169,7 @@ public: void _addLink(LinkInterface* link); // Called to signal app shutdown. Disconnects all links while turning off auto-connect. - void shutdown(void); + Q_INVOKABLE void shutdown(void); #ifdef QT_DEBUG // Only used by unit test tp restart after a shutdown diff --git a/src/main.cc b/src/main.cc index 12ab581..d377c9d 100644 --- a/src/main.cc +++ b/src/main.cc @@ -34,7 +34,6 @@ This file is part of the QGROUNDCONTROL project #include <QProcessEnvironment> #include "QGCApplication.h" -#include "MainWindow.h" #ifndef __mobile__ #include "QGCSerialPortInfo.h" diff --git a/src/ui/MainWindow.cc b/src/ui/MainWindow.cc index 39089fb..b577618 100644 --- a/src/ui/MainWindow.cc +++ b/src/ui/MainWindow.cc @@ -159,7 +159,7 @@ MainWindow::MainWindow() _mainQmlWidgetHolder->setVisible(true); _mainQmlWidgetHolder->setContextPropertyObject("controller", this); - _mainQmlWidgetHolder->setSource(QUrl::fromUserInput("qrc:qml/MainWindow.qml")); + _mainQmlWidgetHolder->setSource(QUrl::fromUserInput("qrc:qml/MainWindowHybrid.qml")); // Image provider QQuickImageProvider* pImgProvider = dynamic_cast<QQuickImageProvider*>(qgcApp()->toolbox()->imageProvider()); @@ -436,7 +436,7 @@ void MainWindow::closeEvent(QCloseEvent *event) { // Disallow window close if there are active connections if (qgcApp()->toolbox()->multiVehicleManager()->vehicles()->count()) { - emit showWindowCloseMessage(); + qgcApp()->showWindowCloseMessage(); event->ignore(); return; } @@ -548,12 +548,12 @@ void MainWindow::connectCommonActions() connect(_ui.actionSettings, SIGNAL(triggered()), this, SLOT(showSettings())); // Views actions - connect(_ui.actionFlight, &QAction::triggered, this, &MainWindow::showFlyView); - connect(_ui.actionPlan, &QAction::triggered, this, &MainWindow::showPlanView); - connect(_ui.actionSetup, &QAction::triggered, this, &MainWindow::showSetupView); - connect(_ui.actionFlight, &QAction::triggered, this, &MainWindow::handleActiveViewActionState); - connect(_ui.actionPlan, &QAction::triggered, this, &MainWindow::handleActiveViewActionState); - connect(_ui.actionSetup, &QAction::triggered, this, &MainWindow::handleActiveViewActionState); + connect(_ui.actionFlight, &QAction::triggered, qgcApp(), &QGCApplication::showFlyView); + connect(_ui.actionPlan, &QAction::triggered, qgcApp(), &QGCApplication::showPlanView); + connect(_ui.actionSetup, &QAction::triggered, qgcApp(), &QGCApplication::showSetupView); + connect(_ui.actionFlight, &QAction::triggered, this, &MainWindow::handleActiveViewActionState); + connect(_ui.actionPlan, &QAction::triggered, this, &MainWindow::handleActiveViewActionState); + connect(_ui.actionSetup, &QAction::triggered, this, &MainWindow::handleActiveViewActionState); // Connect internal actions connect(qgcApp()->toolbox()->multiVehicleManager(), &MultiVehicleManager::vehicleAdded, this, &MainWindow::_vehicleAdded); @@ -670,7 +670,7 @@ void MainWindow::_storeVisibleWidgetsSettings(void) } #endif -void MainWindow::showMessage(const QString message) +QObject* MainWindow::rootQmlObject(void) { - emit showCriticalMessage(message); + return _mainQmlWidgetHolder->getRootObject(); } diff --git a/src/ui/MainWindow.h b/src/ui/MainWindow.h index 6f9b103..4077f05 100644 --- a/src/ui/MainWindow.h +++ b/src/ui/MainWindow.h @@ -31,6 +31,10 @@ This file is part of the QGROUNDCONTROL project #ifndef _MAINWINDOW_H_ #define _MAINWINDOW_H_ +#ifdef __mobile__ +#error Should not be include in mobile build +#endif + #include <QMainWindow> #include <QStatusBar> #include <QStackedWidget> @@ -91,12 +95,12 @@ public: /// @brief Saves the last used connection void saveLastUsedConnection(const QString connection); - /// @brief Show message in lower message window - void showMessage(const QString message); - // Called from MainWindow.qml when the user accepts the window close dialog Q_INVOKABLE void acceptWindowClose(void); + /// @return Root qml object of main window QML + QObject* rootQmlObject(void); + public slots: #ifndef __mobile__ void showSettings(); @@ -140,20 +144,6 @@ protected slots: void handleActiveViewActionState(bool triggered); signals: - // Signals the Qml to show the specified view - void showFlyView(void); - void showPlanView(void); - void showSetupView(void); - - void showCriticalMessage(const QString& message); - void showWindowCloseMessage(void); - - // These are used for unit testing - void showSetupFirmware(void); - void showSetupParameters(void); - void showSetupSummary(void); - void showSetupVehicleComponent(VehicleComponent* vehicleComponent); - void initStatusChanged(const QString& message, int alignment, const QColor &color); /** Emitted when any value changes from any source */ void valueChanged(const int uasId, const QString& name, const QString& unit, const QVariant& value, const quint64 msec); @@ -173,6 +163,7 @@ public: return logPlayer; } #endif + protected: void connectCommonActions(); diff --git a/src/ui/MainWindow.qml b/src/ui/MainWindow.qml deleted file mode 100644 index 1c373d4..0000000 --- a/src/ui/MainWindow.qml +++ /dev/null @@ -1,424 +0,0 @@ -/*===================================================================== - -QGroundControl Open Source Ground Control Station - -(c) 2009, 2015 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/>. - -======================================================================*/ - -import QtQuick 2.5 -import QtQuick.Controls 1.2 -import QtQuick.Dialogs 1.2 -import QtPositioning 5.2 - -import QGroundControl 1.0 -import QGroundControl.Palette 1.0 -import QGroundControl.Controls 1.0 -import QGroundControl.FlightDisplay 1.0 -import QGroundControl.ScreenTools 1.0 -import QGroundControl.MultiVehicleManager 1.0 - -/// Qml for MainWindow -Item { - id: mainWindow - - readonly property string _planViewSource: "MissionEditor.qml" - readonly property string _setupViewSource: "SetupView.qml" - - QGCPalette { id: __qgcPal; colorGroupEnabled: true } - - property real tbHeight: ScreenTools.isMobile ? (ScreenTools.isTinyScreen ? (mainWindow.width * 0.0666) : (mainWindow.width * 0.05)) : ScreenTools.defaultFontPixelSize * 4 - property int tbCellHeight: tbHeight * 0.75 - property real tbSpacing: ScreenTools.isMobile ? width * 0.00824 : 9.54 - property real tbButtonWidth: tbCellHeight * 1.35 - property real availableHeight: height - tbHeight - property real menuButtonWidth: (tbButtonWidth * 2) + (tbSpacing * 4) + 1 - - property var defaultPosition: QtPositioning.coordinate(37.803784, -122.462276) - property var tabletPosition: defaultPosition - - property var currentPopUp: null - property real currentCenterX: 0 - property var activeVehicle: multiVehicleManager.activeVehicle - property string formatedMessage: activeVehicle ? activeVehicle.formatedMessage : "" - - Connections { - - target: controller - - onShowFlyView: { - if(currentPopUp) { - currentPopUp.close() - } - flightView.visible = true - setupViewLoader.visible = false - planViewLoader.visible = false - } - - onShowPlanView: { - if(currentPopUp) { - currentPopUp.close() - } - if (planViewLoader.source != _planViewSource) { - planViewLoader.source = _planViewSource - } - flightView.visible = false - setupViewLoader.visible = false - planViewLoader.visible = true - } - - onShowSetupView: { - if(currentPopUp) { - currentPopUp.close() - } - if (setupViewLoader.source != _setupViewSource) { - setupViewLoader.source = _setupViewSource - } - flightView.visible = false - setupViewLoader.visible = true - planViewLoader.visible = false - } - - onShowCriticalMessage: showCriticalMessage(message) - - onShowWindowCloseMessage: windowCloseDialog.open() - - // The following are use for unit testing only - - onShowSetupFirmware: setupViewLoader.item.showFirmwarePanel() - onShowSetupParameters: setupViewLoader.item.showParametersPanel() - onShowSetupSummary: setupViewLoader.item.showSummaryPanel() - onShowSetupVehicleComponent: setupViewLoader.item.showVehicleComponentPanel(vehicleComponent) - } - - //-- Detect tablet position - PositionSource { - id: positionSource - updateInterval: 1000 - active: false - onPositionChanged: { - if(positionSource.valid) { - if(positionSource.position.coordinate.latitude) { - if(Math.abs(positionSource.position.coordinate.latitude) > 0.001) { - if(positionSource.position.coordinate.longitude) { - if(Math.abs(positionSource.position.coordinate.longitude) > 0.001) { - tabletPosition = positionSource.position.coordinate - } - } - } - } - } - positionSource.stop() - } - } - - property var messageQueue: [] - - function showCriticalMessage(message) { - if(criticalMmessageArea.visible) { - messageQueue.push(message) - } else { - criticalMessageText.text = message - criticalMmessageArea.visible = true - mainWindow.setMapInteractive(false) - } - } - - function showLeftMenu() { - if(!leftPanel.visible && !leftPanel.item.animateShowDialog.running) { - leftPanel.visible = true - leftPanel.item.animateShowDialog.start() - } else if(leftPanel.visible && !leftPanel.item.animateShowDialog.running) { - //-- If open, toggle it closed - hideLeftMenu() - } - } - - function hideLeftMenu() { - if(leftPanel.visible && !leftPanel.item.animateHideDialog.running) { - leftPanel.item.animateHideDialog.start() - } - } - - function setMapInteractive(enabled) { - flightView.interactive = enabled - } - - onFormatedMessageChanged: { - if(messageArea.visible) { - messageText.append(formatedMessage) - //-- Hack to scroll down - messageFlick.flick(0,-500) - } - } - - function showMessageArea() { - if(currentPopUp) { - currentPopUp.close() - } - if(multiVehicleManager.activeVehicleAvailable) { - messageText.text = activeVehicle.formatedMessages - //-- Hack to scroll to last message - for (var i = 0; i < activeVehicle.messageCount; i++) - messageFlick.flick(0,-5000) - activeVehicle.resetMessages() - } else { - messageText.text = "No Messages" - } - currentPopUp = messageArea - messageArea.visible = true - mainWindow.setMapInteractive(false) - } - - function showPopUp(dropItem, centerX) { - if(currentPopUp) { - currentPopUp.close() - } - indicatorDropdown.centerX = centerX - indicatorDropdown.sourceComponent = dropItem - indicatorDropdown.visible = true - currentPopUp = indicatorDropdown - } - - MessageDialog { - id: windowCloseDialog - title: "QGroundControl close" - text: "There are still active connections to vehicles. Do you want to disconnect these before closing?" - standardButtons: StandardButton.Yes | StandardButton.Cancel - modality: Qt.ApplicationModal - visible: false - - onYes: controller.acceptWindowClose() - } - - //-- Left Settings Menu - Loader { - id: leftPanel - anchors.fill: mainWindow - visible: false - z: QGroundControl.zOrderTopMost + 100 - } - - //-- Main UI - - MainToolBar { - id: toolBar - height: tbHeight - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - mainWindow: mainWindow - opaqueBackground: leftPanel.visible - isBackgroundDark: flightView.isBackgroundDark - z: QGroundControl.zOrderTopMost - Component.onCompleted: { - leftPanel.source = "MainWindowLeftPanel.qml" - } - } - - FlightDisplayView { - id: flightView - anchors.fill: parent - availableHeight: mainWindow.availableHeight - visible: true - Component.onCompleted: { - positionSource.start() - } - } - - Loader { - id: planViewLoader - anchors.fill: parent - visible: false - } - - Loader { - id: setupViewLoader - anchors.fill: parent - visible: false - } - - //------------------------------------------------------------------------- - //-- Dismiss Pop Up Messages - MouseArea { - visible: currentPopUp != null - enabled: currentPopUp != null - anchors.fill: parent - onClicked: { - currentPopUp.close() - } - } - - //------------------------------------------------------------------------- - //-- Indicator Drop Down Info - Loader { - id: indicatorDropdown - visible: false - property real centerX: 0 - function close() { - sourceComponent = null - mainWindow.currentPopUp = null - } - } - - //------------------------------------------------------------------------- - //-- System Message Area - Rectangle { - id: messageArea - - function close() { - currentPopUp = null - messageText.text = "" - mainWindow.setMapInteractive(true) - messageArea.visible = false - } - - width: mainWindow.width * 0.5 - height: mainWindow.height * 0.5 - color: Qt.rgba(0,0,0,0.8) - visible: false - radius: ScreenTools.defaultFontPixelHeight * 0.5 - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: parent.top - anchors.topMargin: tbHeight + ScreenTools.defaultFontPixelHeight - Flickable { - id: messageFlick - anchors.margins: ScreenTools.defaultFontPixelHeight - anchors.fill: parent - contentHeight: messageText.height - contentWidth: messageText.width - boundsBehavior: Flickable.StopAtBounds - pixelAligned: true - clip: true - TextEdit { - id: messageText - readOnly: true - textFormat: TextEdit.RichText - color: "white" - } - } - //-- Dismiss System Message - Image { - anchors.margins: ScreenTools.defaultFontPixelHeight - anchors.top: parent.top - anchors.right: parent.right - width: ScreenTools.defaultFontPixelHeight * 1.5 - height: ScreenTools.defaultFontPixelHeight * 1.5 - source: "/res/XDelete.svg" - fillMode: Image.PreserveAspectFit - mipmap: true - smooth: true - MouseArea { - anchors.fill: parent - onClicked: { - messageArea.close() - } - } - } - } - //------------------------------------------------------------------------- - //-- Critical Message Area - Rectangle { - id: criticalMmessageArea - - function close() { - //-- Are there messages in the waiting queue? - if(mainWindow.messageQueue.length) { - criticalMessageText.text = "" - //-- Show all messages in queue - for (var i = 0; i < mainWindow.messageQueue.length; i++) { - criticalMessageText.append(mainWindow.messageQueue[i]) - } - //-- Clear it - mainWindow.messageQueue = [] - } else { - criticalMessageText.text = "" - mainWindow.setMapInteractive(true) - criticalMmessageArea.visible = false - } - } - - width: mainWindow.width * 0.55 - height: ScreenTools.defaultFontPixelHeight * ScreenTools.fontHRatio * 6 - color: Qt.rgba(0,0,0,0.8) - visible: false - radius: ScreenTools.defaultFontPixelHeight * 0.5 - anchors.horizontalCenter: parent.horizontalCenter - anchors.bottom: parent.bottom - anchors.bottomMargin: ScreenTools.defaultFontPixelHeight - Flickable { - id: criticalMessageFlick - anchors.margins: ScreenTools.defaultFontPixelHeight - anchors.fill: parent - contentHeight: criticalMessageText.height - contentWidth: criticalMessageText.width - boundsBehavior: Flickable.StopAtBounds - pixelAligned: true - clip: true - TextEdit { - id: criticalMessageText - width: criticalMmessageArea.width - criticalClose.width - (ScreenTools.defaultFontPixelHeight * 2) - anchors.left: parent.left - readOnly: true - textFormat: TextEdit.RichText - font.weight: Font.DemiBold - wrapMode: TextEdit.WordWrap - color: "#fdfd3b" - } - } - //-- Dismiss Critical Message - Image { - id: criticalClose - anchors.margins: ScreenTools.defaultFontPixelHeight - anchors.top: parent.top - anchors.right: parent.right - width: ScreenTools.defaultFontPixelHeight * 1.5 - height: ScreenTools.defaultFontPixelHeight * 1.5 - source: "/res/XDelete.svg" - fillMode: Image.PreserveAspectFit - mipmap: true - smooth: true - MouseArea { - anchors.fill: parent - onClicked: { - criticalMmessageArea.close() - } - } - } - //-- More text below indicator - Image { - anchors.margins: ScreenTools.defaultFontPixelHeight - anchors.bottom: parent.bottom - anchors.right: parent.right - width: ScreenTools.defaultFontPixelHeight * 1.5 - height: ScreenTools.defaultFontPixelHeight * 1.5 - source: "/res/ArrowDown.svg" - fillMode: Image.PreserveAspectFit - mipmap: true - smooth: true - visible: criticalMessageText.lineCount > 5 - MouseArea { - anchors.fill: parent - onClicked: { - criticalMessageFlick.flick(0,-500) - } - } - } - } - -} diff --git a/src/ui/MainWindowHybrid.qml b/src/ui/MainWindowHybrid.qml new file mode 100644 index 0000000..aa8b206 --- /dev/null +++ b/src/ui/MainWindowHybrid.qml @@ -0,0 +1,75 @@ +/*===================================================================== + +QGroundControl Open Source Ground Control Station + +(c) 2009, 2015 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/>. + +======================================================================*/ + +import QtQuick 2.5 +import QtQuick.Controls 1.2 + +import QGroundControl.Controls 1.0 + +/// Native QML top level window +Item { + function showFlyView() { + mainWindowInner.item.showFlyView() + } + + function showPlanView() { + mainWindowInner.item.showPlanView() + } + + function showSetupView() { + mainWindowInner.item.showSetupView() + } + + function showWindowCloseMessage() { + mainWindowInner.item.showWindowCloseMessage() + } + + // The following are use for unit testing only + + function showSetupFirmware() { + mainWindowInner.item.showSetupFirmware() + } + + function showSetupParameters() { + mainWindowInner.item.showSetupParameters() + } + + function showSetupSummary() { + mainWindowInner.item.showSetupSummary() + } + + function showSetupVehicleComponent(vehicleComponent) { + mainWindowInner.item.showSetupVehicleComponent(vehicleComponent) + } + + function showMessage(message) { + mainWindowInner.item.showMessage(message) + } + + Loader { + id: mainWindowInner + anchors.fill: parent + source: "MainWindowInner.qml" + } +} + diff --git a/src/ui/MainWindowInner.qml b/src/ui/MainWindowInner.qml new file mode 100644 index 0000000..40ed423 --- /dev/null +++ b/src/ui/MainWindowInner.qml @@ -0,0 +1,438 @@ +/*===================================================================== + +QGroundControl Open Source Ground Control Station + +(c) 2009, 2015 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/>. + +======================================================================*/ + +import QtQuick 2.5 +import QtQuick.Controls 1.2 +import QtQuick.Dialogs 1.2 +import QtPositioning 5.2 + +import QGroundControl 1.0 +import QGroundControl.Palette 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.FlightDisplay 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.MultiVehicleManager 1.0 + +/// Inner common QML for MainWindow +Item { + id: mainWindow + + readonly property string _planViewSource: "MissionEditor.qml" + readonly property string _setupViewSource: "SetupView.qml" + + QGCPalette { id: __qgcPal; colorGroupEnabled: true } + + property real tbHeight: ScreenTools.isMobile ? (ScreenTools.isTinyScreen ? (mainWindow.width * 0.0666) : (mainWindow.width * 0.05)) : ScreenTools.defaultFontPixelSize * 4 + property int tbCellHeight: tbHeight * 0.75 + property real tbSpacing: ScreenTools.isMobile ? width * 0.00824 : 9.54 + property real tbButtonWidth: tbCellHeight * 1.35 + property real availableHeight: height - tbHeight + property real menuButtonWidth: (tbButtonWidth * 2) + (tbSpacing * 4) + 1 + + property var defaultPosition: QtPositioning.coordinate(37.803784, -122.462276) + property var tabletPosition: defaultPosition + + property var currentPopUp: null + property real currentCenterX: 0 + property var activeVehicle: multiVehicleManager.activeVehicle + property string formatedMessage: activeVehicle ? activeVehicle.formatedMessage : "" + + function showFlyView() { + if(currentPopUp) { + currentPopUp.close() + } + flightView.visible = true + setupViewLoader.visible = false + planViewLoader.visible = false + toolbar.checkFlyButton() + } + + function showPlanView() { + if(currentPopUp) { + currentPopUp.close() + } + if (planViewLoader.source != _planViewSource) { + planViewLoader.source = _planViewSource + } + flightView.visible = false + setupViewLoader.visible = false + planViewLoader.visible = true + toolBar.checkPlanButton() + } + + function showSetupView() { + if(currentPopUp) { + currentPopUp.close() + } + if (setupViewLoader.source != _setupViewSource) { + setupViewLoader.source = _setupViewSource + } + flightView.visible = false + setupViewLoader.visible = true + planViewLoader.visible = false + toolBar.checkSetupButton() + } + + function showWindowCloseMessage() { + windowCloseDialog.open() + } + + // The following are use for unit testing only + + function showSetupFirmware() { + setupViewLoader.item.showFirmwarePanel() + } + + function showSetupParameters() { + setupViewLoader.item.showParametersPanel() + } + + function showSetupSummary() { + setupViewLoader.item.showSummaryPanel() + } + + function showSetupVehicleComponent(vehicleComponent) { + setupViewLoader.item.showVehicleComponentPanel(vehicleComponent) + } + + //-- Detect tablet position + PositionSource { + id: positionSource + updateInterval: 1000 + active: false + onPositionChanged: { + if(positionSource.valid) { + if(positionSource.position.coordinate.latitude) { + if(Math.abs(positionSource.position.coordinate.latitude) > 0.001) { + if(positionSource.position.coordinate.longitude) { + if(Math.abs(positionSource.position.coordinate.longitude) > 0.001) { + tabletPosition = positionSource.position.coordinate + } + } + } + } + } + positionSource.stop() + } + } + + property var messageQueue: [] + + function showMessage(message) { + if(criticalMmessageArea.visible) { + messageQueue.push(message) + } else { + criticalMessageText.text = message + criticalMmessageArea.visible = true + mainWindow.setMapInteractive(false) + } + } + + function showLeftMenu() { + if(!leftPanel.visible && !leftPanel.item.animateShowDialog.running) { + leftPanel.visible = true + leftPanel.item.animateShowDialog.start() + } else if(leftPanel.visible && !leftPanel.item.animateShowDialog.running) { + //-- If open, toggle it closed + hideLeftMenu() + } + } + + function hideLeftMenu() { + if(leftPanel.visible && !leftPanel.item.animateHideDialog.running) { + leftPanel.item.animateHideDialog.start() + } + } + + function setMapInteractive(enabled) { + flightView.interactive = enabled + } + + onFormatedMessageChanged: { + if(messageArea.visible) { + messageText.append(formatedMessage) + //-- Hack to scroll down + messageFlick.flick(0,-500) + } + } + + function showMessageArea() { + if(currentPopUp) { + currentPopUp.close() + } + if(multiVehicleManager.activeVehicleAvailable) { + messageText.text = activeVehicle.formatedMessages + //-- Hack to scroll to last message + for (var i = 0; i < activeVehicle.messageCount; i++) + messageFlick.flick(0,-5000) + activeVehicle.resetMessages() + } else { + messageText.text = "No Messages" + } + currentPopUp = messageArea + messageArea.visible = true + mainWindow.setMapInteractive(false) + } + + function showPopUp(dropItem, centerX) { + if(currentPopUp) { + currentPopUp.close() + } + indicatorDropdown.centerX = centerX + indicatorDropdown.sourceComponent = dropItem + indicatorDropdown.visible = true + currentPopUp = indicatorDropdown + } + + MessageDialog { + id: windowCloseDialog + title: "QGroundControl close" + text: "There are still active connections to vehicles. Do you want to disconnect these before closing?" + standardButtons: StandardButton.Yes | StandardButton.Cancel + modality: Qt.ApplicationModal + visible: false + + onYes: controller.acceptWindowClose() + } + + //-- Left Settings Menu + Loader { + id: leftPanel + anchors.fill: parent + visible: false + z: QGroundControl.zOrderTopMost + 100 + } + + //-- Main UI + + MainToolBar { + id: toolBar + height: tbHeight + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + mainWindow: mainWindow + opaqueBackground: leftPanel.visible + isBackgroundDark: flightView.isBackgroundDark + z: QGroundControl.zOrderTopMost + + Component.onCompleted: { + leftPanel.source = "MainWindowLeftPanel.qml" + } + + onShowSetupView: mainWindow.showSetupView() + onShowPlanView: mainWindow.showPlanView() + onShowFlyView: mainWindow.showFlyView() + } + + FlightDisplayView { + id: flightView + anchors.fill: parent + availableHeight: mainWindow.availableHeight + visible: true + Component.onCompleted: { + positionSource.start() + } + } + + Loader { + id: planViewLoader + anchors.fill: parent + visible: false + } + + Loader { + id: setupViewLoader + anchors.fill: parent + visible: false + } + + //------------------------------------------------------------------------- + //-- Dismiss Pop Up Messages + MouseArea { + visible: currentPopUp != null + enabled: currentPopUp != null + anchors.fill: parent + onClicked: { + currentPopUp.close() + } + } + + //------------------------------------------------------------------------- + //-- Indicator Drop Down Info + Loader { + id: indicatorDropdown + visible: false + property real centerX: 0 + function close() { + sourceComponent = null + mainWindow.currentPopUp = null + } + } + + //------------------------------------------------------------------------- + //-- System Message Area + Rectangle { + id: messageArea + + function close() { + currentPopUp = null + messageText.text = "" + mainWindow.setMapInteractive(true) + messageArea.visible = false + } + + width: mainWindow.width * 0.5 + height: mainWindow.height * 0.5 + color: Qt.rgba(0,0,0,0.8) + visible: false + radius: ScreenTools.defaultFontPixelHeight * 0.5 + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: parent.top + anchors.topMargin: tbHeight + ScreenTools.defaultFontPixelHeight + Flickable { + id: messageFlick + anchors.margins: ScreenTools.defaultFontPixelHeight + anchors.fill: parent + contentHeight: messageText.height + contentWidth: messageText.width + boundsBehavior: Flickable.StopAtBounds + pixelAligned: true + clip: true + TextEdit { + id: messageText + readOnly: true + textFormat: TextEdit.RichText + color: "white" + } + } + //-- Dismiss System Message + Image { + anchors.margins: ScreenTools.defaultFontPixelHeight + anchors.top: parent.top + anchors.right: parent.right + width: ScreenTools.defaultFontPixelHeight * 1.5 + height: ScreenTools.defaultFontPixelHeight * 1.5 + source: "/res/XDelete.svg" + fillMode: Image.PreserveAspectFit + mipmap: true + smooth: true + MouseArea { + anchors.fill: parent + onClicked: { + messageArea.close() + } + } + } + } + //------------------------------------------------------------------------- + //-- Critical Message Area + Rectangle { + id: criticalMmessageArea + + function close() { + //-- Are there messages in the waiting queue? + if(mainWindow.messageQueue.length) { + criticalMessageText.text = "" + //-- Show all messages in queue + for (var i = 0; i < mainWindow.messageQueue.length; i++) { + criticalMessageText.append(mainWindow.messageQueue[i]) + } + //-- Clear it + mainWindow.messageQueue = [] + } else { + criticalMessageText.text = "" + mainWindow.setMapInteractive(true) + criticalMmessageArea.visible = false + } + } + + width: mainWindow.width * 0.55 + height: ScreenTools.defaultFontPixelHeight * ScreenTools.fontHRatio * 6 + color: Qt.rgba(0,0,0,0.8) + visible: false + radius: ScreenTools.defaultFontPixelHeight * 0.5 + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: parent.bottom + anchors.bottomMargin: ScreenTools.defaultFontPixelHeight + Flickable { + id: criticalMessageFlick + anchors.margins: ScreenTools.defaultFontPixelHeight + anchors.fill: parent + contentHeight: criticalMessageText.height + contentWidth: criticalMessageText.width + boundsBehavior: Flickable.StopAtBounds + pixelAligned: true + clip: true + TextEdit { + id: criticalMessageText + width: criticalMmessageArea.width - criticalClose.width - (ScreenTools.defaultFontPixelHeight * 2) + anchors.left: parent.left + readOnly: true + textFormat: TextEdit.RichText + font.weight: Font.DemiBold + wrapMode: TextEdit.WordWrap + color: "#fdfd3b" + } + } + //-- Dismiss Critical Message + Image { + id: criticalClose + anchors.margins: ScreenTools.defaultFontPixelHeight + anchors.top: parent.top + anchors.right: parent.right + width: ScreenTools.defaultFontPixelHeight * 1.5 + height: ScreenTools.defaultFontPixelHeight * 1.5 + source: "/res/XDelete.svg" + fillMode: Image.PreserveAspectFit + mipmap: true + smooth: true + MouseArea { + anchors.fill: parent + onClicked: { + criticalMmessageArea.close() + } + } + } + //-- More text below indicator + Image { + anchors.margins: ScreenTools.defaultFontPixelHeight + anchors.bottom: parent.bottom + anchors.right: parent.right + width: ScreenTools.defaultFontPixelHeight * 1.5 + height: ScreenTools.defaultFontPixelHeight * 1.5 + source: "/res/ArrowDown.svg" + fillMode: Image.PreserveAspectFit + mipmap: true + smooth: true + visible: criticalMessageText.lineCount > 5 + MouseArea { + anchors.fill: parent + onClicked: { + criticalMessageFlick.flick(0,-500) + } + } + } + } +} + diff --git a/src/ui/MainWindowNative.qml b/src/ui/MainWindowNative.qml new file mode 100644 index 0000000..26399ab --- /dev/null +++ b/src/ui/MainWindowNative.qml @@ -0,0 +1,90 @@ +/*===================================================================== + +QGroundControl Open Source Ground Control Station + +(c) 2009, 2015 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/>. + +======================================================================*/ + +import QtQuick 2.5 +import QtQuick.Window 2.2 + +import QGroundControl 1.0 + +/// Native QML top level window +Window { + visible: true + + onClosing: { + // Disallow window close if there are active connections + if (QGroundControl.multiVehicleManager.activeVehicle) { + showWindowCloseMessage() + close.accepted = false + return + } + + // We still need to shutdown LinkManager even though no active connections so that we don't get any + // more auto-connect links during shutdown. + QGroundControl.linkManager.shutdown(); + } + + function showFlyView() { + mainWindowInner.item.showFlyView() + } + + function showPlanView() { + mainWindowInner.item.showPlanView() + } + + function showSetupView() { + mainWindowInner.item.showSetupView() + } + + function showWindowCloseMessage() { + mainWindowInner.item.showWindowCloseMessage() + } + + // The following are use for unit testing only + + function showSetupFirmware() { + mainWindowInner.item.showSetupFirmware() + } + + function showSetupParameters() { + mainWindowInner.item.showSetupParameters() + } + + function showSetupSummary() { + mainWindowInner.item.showSetupSummary() + } + + function showSetupVehicleComponent(vehicleComponent) { + mainWindowInner.showSetupVehicleComponent(vehicleComponent) + } + + function showMessage(message) { + mainWindowInner.item.showMessage(message) + } + + Loader { + id: mainWindowInner + anchors.fill: parent + source: "MainWindowInner.qml" + } +} + diff --git a/src/ui/preferences/GeneralSettings.qml b/src/ui/preferences/GeneralSettings.qml index 5ad4f90..d4a9218 100644 --- a/src/ui/preferences/GeneralSettings.qml +++ b/src/ui/preferences/GeneralSettings.qml @@ -81,15 +81,6 @@ Rectangle { } } //----------------------------------------------------------------- - //-- Low power mode - QGCCheckBox { - text: "Enable low power mode" - checked: QGroundControl.isLowPowerMode - onClicked: { - QGroundControl.isLowPowerMode = checked - } - } - //----------------------------------------------------------------- //-- Prompt Save Log QGCCheckBox { id: promptSaveLog diff --git a/src/ui/toolbar/MainToolBar.qml b/src/ui/toolbar/MainToolBar.qml index 37b9756..ab65895 100644 --- a/src/ui/toolbar/MainToolBar.qml +++ b/src/ui/toolbar/MainToolBar.qml @@ -145,8 +145,24 @@ Rectangle { readonly property var colorBlue: "#636efe" readonly property var colorWhite: "#ffffff" + signal showSetupView() + signal showPlanView() + signal showFlyView() + MainToolBarController { id: _controller } + function checkSetupButton() { + setupButton.checked = true + } + + function checkPlanButton() { + planButton.checked = true + } + + function checkFlyButton() { + flyButton.checked = true + } + function getBatteryColor() { if(activeVehicle) { if(activeVehicle.batteryPercent > 75) { @@ -193,13 +209,6 @@ Rectangle { flyButton.checked = true } - Connections { - target: controller - onShowFlyView: { flyButton.checked = true } - onShowPlanView: { planButton.checked = true } - onShowSetupView:{ setupButton.checked = true } - } - //--------------------------------------------- // GPS Info Component { @@ -496,9 +505,7 @@ Rectangle { height: mainWindow.tbCellHeight exclusiveGroup: mainActionGroup source: "/qmlimages/Gears.svg" - onClicked: { - _controller.onSetupView(); - } + onClicked: toolBar.showSetupView() } Rectangle { @@ -513,9 +520,7 @@ Rectangle { height: mainWindow.tbCellHeight exclusiveGroup: mainActionGroup source: "/qmlimages/Plan.svg" - onClicked: { - _controller.onPlanView(); - } + onClicked: toolBar.showPlanView() } Rectangle { @@ -530,9 +535,7 @@ Rectangle { height: mainWindow.tbCellHeight exclusiveGroup: mainActionGroup source: "/qmlimages/PaperPlane.svg" - onClicked: { - _controller.onFlyView(); - } + onClicked: toolBar.showFlyView() } Rectangle { diff --git a/src/ui/toolbar/MainToolBarController.cc b/src/ui/toolbar/MainToolBarController.cc index bab5ff6..5af18e7 100644 --- a/src/ui/toolbar/MainToolBarController.cc +++ b/src/ui/toolbar/MainToolBarController.cc @@ -32,7 +32,6 @@ This file is part of the QGROUNDCONTROL project #include "MainToolBarController.h" #include "ScreenToolsController.h" -#include "MainWindow.h" #include "UASMessageView.h" #include "UASMessageHandler.h" #include "QGCApplication.h" @@ -60,21 +59,6 @@ MainToolBarController::~MainToolBarController() } -void MainToolBarController::onSetupView() -{ - MainWindow::instance()->showSetupView(); -} - -void MainToolBarController::onPlanView() -{ - MainWindow::instance()->showPlanView(); -} - -void MainToolBarController::onFlyView() -{ - MainWindow::instance()->showFlyView(); -} - void MainToolBarController::_activeVehicleChanged(Vehicle* vehicle) { // Disconnect the previous one (if any) diff --git a/src/ui/toolbar/MainToolBarController.h b/src/ui/toolbar/MainToolBarController.h index 9977eac..6b6bc55 100644 --- a/src/ui/toolbar/MainToolBarController.h +++ b/src/ui/toolbar/MainToolBarController.h @@ -50,10 +50,6 @@ public: MainToolBarController(QObject* parent = NULL); ~MainToolBarController(); - Q_INVOKABLE void onSetupView(); - Q_INVOKABLE void onPlanView(); - Q_INVOKABLE void onFlyView(); - Q_PROPERTY(double height MEMBER _toolbarHeight NOTIFY heightChanged) Q_PROPERTY(float progressBarValue MEMBER _progressBarValue NOTIFY progressBarValueChanged) Q_PROPERTY(int telemetryRRSSI READ telemetryRRSSI NOTIFY telemetryRRSSIChanged)