diff --git a/src/FlightDisplay/FlightDisplayView.qml b/src/FlightDisplay/FlightDisplayView.qml index 9b56f0cc6a4fbfd0b1923d1190d2e756e2f3672c..37bceaf65c241e79e926b9595dfa0cb9fdb2bc45 100644 --- a/src/FlightDisplay/FlightDisplayView.qml +++ b/src/FlightDisplay/FlightDisplayView.qml @@ -41,6 +41,9 @@ import QGroundControl.Controllers 1.0 Item { id: root + property alias latitude: flightMap.latitude + property alias longitude: flightMap.longitude + // Top margin for all widgets. Used to prevent overlap with the toolbar property real topMargin: 0 @@ -110,7 +113,6 @@ Item { QGroundControl.flightMapSettings.saveMapSetting(flightMap.mapName, _showMapBackgroundKey, setBool(_showMap)) } - FlightMap { id: flightMap anchors.fill: parent @@ -122,6 +124,8 @@ Item { property var rootVehicleCoordinate: _vehicleCoordinate property bool rootLoadCompleted: false + property bool _followVehicle: true + onRootVehicleCoordinateChanged: updateMapPosition(false /* force */) Component.onCompleted: flightMapDelayLoader.source = "FlightDisplayViewDelayLoadInner.qml" @@ -132,9 +136,6 @@ Item { flightMap.longitude = root._vehicleCoordinate.longitude } } - - property bool _followVehicle: true - // Home position MissionItemIndicator { label: "H" @@ -188,6 +189,11 @@ Item { id: flightMapDelayLoader anchors.fill: parent } + + // Used to make pinch zoom work + MouseArea { + anchors.fill: parent + } } // Flight Map Loader { diff --git a/src/MissionEditor/MissionEditor.qml b/src/MissionEditor/MissionEditor.qml index 61bc1ba47012b568225d51d6add9d86fef0e1f09..5a72bccf42ab902af5a20dc31eeb24a55748d9c9 100644 --- a/src/MissionEditor/MissionEditor.qml +++ b/src/MissionEditor/MissionEditor.qml @@ -60,10 +60,10 @@ QGCView { property var _homePositionManager: QGroundControl.homePositionManager property string _homePositionName: _homePositionManager.homePositions.get(0).name - property var offlineHomePosition: _homePositionManager.homePositions.get(0).coordinate + //property var offlineHomePosition: _homePositionManager.homePositions.get(0).coordinate property var liveHomePosition: controller.liveHomePosition property var liveHomePositionAvailable: controller.liveHomePositionAvailable - property var homePosition: offlineHomePosition // live or offline depending on state + //property var homePosition: offlineHomePosition // live or offline depending on state property bool _syncNeeded: controller.missionItems.dirty property bool _syncInProgress: _activeVehicle ? _activeVehicle.missionManager.inProgress : false @@ -103,13 +103,14 @@ QGCView { } function updateHomePosition() { - homePosition = liveHomePositionAvailable ? liveHomePosition : offlineHomePosition - _missionItems.get(0).coordinate = homePosition - _missionItems.get(0).homePositionValid = true + if (liveHomePositionAvailable) { + _missionItems.get(0).coordinate = liveHomePosition + _missionItems.get(0).homePositionValid = true + } } Component.onCompleted: updateHomePosition() - onOfflineHomePositionChanged: updateHomePosition() + //onOfflineHomePositionChanged: updateHomePosition() onLiveHomePositionAvailableChanged: updateHomePosition() onLiveHomePositionChanged: updateHomePosition() @@ -124,11 +125,8 @@ QGCView { id: editorMap anchors.fill: parent mapName: "MissionEditor" - - Component.onCompleted: { - latitude = homePosition.latitude - longitude = homePosition.longitude - } + latitude: tabletPosition.latitude + longitude: tabletPosition.longitude readonly property real animationDuration: 500 @@ -161,8 +159,8 @@ QGCView { coordinate.latitude = coordinate.latitude.toFixed(_decimalPlaces) coordinate.longitude = coordinate.longitude.toFixed(_decimalPlaces) coordinate.altitude = coordinate.altitude.toFixed(_decimalPlaces) - if (homePositionManagerButton.checked) { - offlineHomePosition = coordinate + if (false /*homePositionManagerButton.checked*/) { + //offlineHomePosition = coordinate } else if (addMissionItemsButton.checked) { var index = controller.addMissionItem(coordinate) addMissionItemsButtonAutoOffTimer.start() @@ -240,7 +238,7 @@ QGCView { anchors.bottom: parent.bottom anchors.right: parent.right width: _rightPanelWidth - visible: !homePositionManagerButton.checked && _missionItems.count > 1 + visible: _missionItems.count > 1 opacity: _rightPanelOpacity z: QGroundControl.zOrderTopMost @@ -257,7 +255,8 @@ QGCView { MissionItemEditor { missionItem: object width: parent.width - readOnly: object.sequenceNumber == 0 && liveHomePositionAvailable + readOnly: object.sequenceNumber == 0 + visible: !readOnly || object.homePositionValid onClicked: setCurrentItem(object.sequenceNumber) @@ -281,6 +280,9 @@ QGCView { } } // Item - Mission Item editor +/* +Home Position Manager is commented out for now until a better implementation is completed + // Home Position Manager Rectangle { id: homePositionManager @@ -552,6 +554,7 @@ QGCView { } } // Column - Online view } // Item - Home Position Manager +*/ // Help Panel Rectangle { @@ -650,6 +653,9 @@ QGCView { "Delete the currently selected mission item." } + /* + Home Position Manager commented until more complete implementation is done + Image { id: homePositionManagerHelpIcon anchors.topMargin: ScreenTools.defaultFontPixelHeight @@ -672,11 +678,12 @@ QGCView { "When enabled, allows you to select/add/update flying field locations. " + "You can save multiple flying field locations for use while creating missions while you are not connected to your vehicle." } +*/ Image { id: mapCenterHelpIcon anchors.topMargin: ScreenTools.defaultFontPixelHeight - anchors.top: homePositionManagerHelpText.bottom + anchors.top: deleteHelpText.bottom width: ScreenTools.defaultFontPixelHeight * 3 fillMode: Image.PreserveAspectFit mipmap: true @@ -793,6 +800,9 @@ QGCView { } } + /* + Home Position Manager commented until more complete implementation is done + RoundButton { id: homePositionManagerButton anchors.margins: _margin @@ -802,12 +812,13 @@ QGCView { exclusiveGroup: _dropButtonsExclusiveGroup z: QGroundControl.zOrderWidgets } + */ DropButton { id: centerMapButton anchors.margins: _margin anchors.left: parent.left - anchors.top: homePositionManagerButton.bottom + anchors.top: deleteMissionItemButton.bottom dropDirection: dropRight buttonImage: "/qmlimages/MapCenter.svg" viewportMargins: ScreenTools.defaultFontPixelWidth / 2 @@ -822,11 +833,12 @@ QGCView { spacing: ScreenTools.defaultFontPixelWidth QGCButton { - text: "Home" + text: "Home" + enabled: liveHomePositionAvailable onClicked: { centerMapButton.hideDropDown() - editorMap.center = QtPositioning.coordinate(homePosition.latitude, homePosition.longitude) + editorMap.center = liveHomePosition } } diff --git a/src/comm/MockLink.cc b/src/comm/MockLink.cc index 9a62d9debb942bdb050b8138dd61be60e790bc45..4d3a1259efac58805282ce2db21b6ed412519a0f 100644 --- a/src/comm/MockLink.cc +++ b/src/comm/MockLink.cc @@ -71,7 +71,8 @@ float MockLink::_vehicleLatitude = 47.633033f; float MockLink::_vehicleLongitude = -122.08794f; float MockLink::_vehicleAltitude = 2.5f; -const char* MockConfiguration::_firmwareTypeKey = "FirmwareType"; +const char* MockConfiguration::_firmwareTypeKey = "FirmwareType"; +const char* MockConfiguration::_sendStatusTextKey = "SendStatusText"; MockLink::MockLink(MockConfiguration* config) : _missionItemHandler(this) @@ -85,10 +86,12 @@ MockLink::MockLink(MockConfiguration* config) , _mavState(MAV_STATE_STANDBY) , _autopilotType(MAV_AUTOPILOT_PX4) , _fileServer(NULL) + , _sendStatusText(false) { _config = config; if (_config) { _autopilotType = config->firmwareType(); + _sendStatusText = config->sendStatusText(); } union px4_custom_mode px4_cm; @@ -168,6 +171,10 @@ void MockLink::_run1HzTasks(void) if (_mavlinkStarted && _connected) { _sendHeartBeat(); _sendHomePosition(); + if (_sendStatusText) { + _sendStatusText = false; + _sendStatusTextMessages(); + } } } @@ -747,9 +754,42 @@ void MockLink::_sendGpsRawInt(void) respondWithMavlinkMessage(msg); } +void MockLink::_sendStatusTextMessages(void) +{ + struct StatusMessage { + MAV_SEVERITY severity; + const char* msg; + }; + + static const struct StatusMessage rgMessages[] = { + { MAV_SEVERITY_INFO, "#Testing audio output" }, + { MAV_SEVERITY_EMERGENCY, "Status text emergency" }, + { MAV_SEVERITY_ALERT, "Status text alert" }, + { MAV_SEVERITY_CRITICAL, "Status text critical" }, + { MAV_SEVERITY_ERROR, "Status text error" }, + { MAV_SEVERITY_WARNING, "Status text warning" }, + { MAV_SEVERITY_NOTICE, "Status text notice" }, + { MAV_SEVERITY_INFO, "Status text info" }, + { MAV_SEVERITY_DEBUG, "Status text debug" }, + }; + + for (size_t i=0; iseverity, + status->msg); + respondWithMavlinkMessage(msg); + } +} + MockConfiguration::MockConfiguration(const QString& name) : LinkConfiguration(name) , _firmwareType(MAV_AUTOPILOT_PX4) + , _sendStatusText(false) { } @@ -757,21 +797,29 @@ MockConfiguration::MockConfiguration(const QString& name) MockConfiguration::MockConfiguration(MockConfiguration* source) : LinkConfiguration(source) { - _firmwareType = source->_firmwareType; + _firmwareType = source->_firmwareType; + _sendStatusText = source->_sendStatusText; } void MockConfiguration::copyFrom(LinkConfiguration *source) { LinkConfiguration::copyFrom(source); MockConfiguration* usource = dynamic_cast(source); - Q_ASSERT(usource != NULL); - _firmwareType = usource->_firmwareType; + + if (!usource) { + qWarning() << "dynamic_cast failed" << source << usource; + return; + } + + _firmwareType = usource->_firmwareType; + _sendStatusText = usource->_sendStatusText; } void MockConfiguration::saveSettings(QSettings& settings, const QString& root) { settings.beginGroup(root); settings.setValue(_firmwareTypeKey, (int)_firmwareType); + settings.setValue(_sendStatusTextKey, _sendStatusText); settings.sync(); settings.endGroup(); } @@ -780,6 +828,7 @@ void MockConfiguration::loadSettings(QSettings& settings, const QString& root) { settings.beginGroup(root); _firmwareType = (MAV_AUTOPILOT)settings.value(_firmwareTypeKey, (int)MAV_AUTOPILOT_PX4).toInt(); + _sendStatusText = settings.value(_sendStatusTextKey, false).toBool(); settings.endGroup(); } @@ -789,7 +838,7 @@ void MockConfiguration::updateSettings() MockLink* ulink = dynamic_cast(_link); if (ulink) { // Restart connect not supported - Q_ASSERT(false); + qWarning() << "updateSettings not supported"; //ulink->_restartConnection(); } } diff --git a/src/comm/MockLink.h b/src/comm/MockLink.h index 9da4fe7b4c7bf28f887a0e4c67f922d34d81f152..1ee7b95887ecf27f7da1a5693c2415e7e232faa9 100644 --- a/src/comm/MockLink.h +++ b/src/comm/MockLink.h @@ -44,6 +44,10 @@ public: MAV_AUTOPILOT firmwareType(void) { return _firmwareType; } void setFirmwareType(MAV_AUTOPILOT firmwareType) { _firmwareType = firmwareType; } + /// @param sendStatusText true: mavlink status text messages will be sent for each severity, as well as voice output info message + void setSendStatusText(bool sendStatusText) { _sendStatusText = sendStatusText; } + bool sendStatusText(void) { return _sendStatusText; } + // Overrides from LinkConfiguration int type(void) { return LinkConfiguration::TypeMock; } void copyFrom(LinkConfiguration* source); @@ -52,9 +56,11 @@ public: void updateSettings(void); private: - MAV_AUTOPILOT _firmwareType; + MAV_AUTOPILOT _firmwareType; + bool _sendStatusText; static const char* _firmwareTypeKey; + static const char* _sendStatusTextKey; }; class MockLink : public LinkInterface @@ -70,6 +76,7 @@ public: int vehicleId(void) { return _vehicleSystemId; } MAV_AUTOPILOT getAutopilotType(void) { return _autopilotType; } void setAutopilotType(MAV_AUTOPILOT autopilot) { _autopilotType = autopilot; } + void setSendStatusText(bool sendStatusText) { _sendStatusText = sendStatusText; } void emitRemoteControlChannelRawChanged(int channel, uint16_t raw); /// Sends the specified mavlink message to QGC @@ -149,6 +156,7 @@ private: void _setParamFloatUnionIntoMap(int componentId, const QString& paramName, float paramFloat); void _sendHomePosition(void); void _sendGpsRawInt(void); + void _sendStatusTextMessages(void); MockLinkMissionItemHandler _missionItemHandler; @@ -173,6 +181,8 @@ private: MockLinkFileServer* _fileServer; + bool _sendStatusText; + static float _vehicleLatitude; static float _vehicleLongitude; static float _vehicleAltitude; diff --git a/src/ui/MainWindow.qml b/src/ui/MainWindow.qml index 15d4322fed92e65430a88bacb86434ea974c7732..9605b77da5f395fe941ebb9e2cece084ce4e92bb 100644 --- a/src/ui/MainWindow.qml +++ b/src/ui/MainWindow.qml @@ -82,6 +82,21 @@ Item { toolbarLoader.source = "MainToolBar.qml" } + // Detect tablet position + property var tabletPosition: QtPositioning.coordinate(37.803784, -122.462276) + PositionSource { + id: positionSource + updateInterval: 1000 + active: ScreenTools.isMobile + + onPositionChanged: { + tabletPosition = positionSource.position.coordinate + _root.latitude = tabletPosition.latitude + _root.longitude = tabletPosition.longitude + positionSource.active = false + } + } + Loader { id: toolbarLoader width: parent.width @@ -105,6 +120,8 @@ Item { anchors.top: toolbarLoader.bottom anchors.bottom: parent.bottom visible: false + + property var tabletPosition: _root.tabletPosition } Loader { @@ -114,5 +131,7 @@ Item { anchors.top: toolbarLoader.bottom anchors.bottom: parent.bottom visible: false + + property var tabletPosition: _root.tabletPosition } } diff --git a/src/ui/MockLinkConfiguration.cc b/src/ui/MockLinkConfiguration.cc index c6b3e477ceb91620d9f87445f1758c85e0614a57..3c8e05d2642e03ce26acbce43ca9b47082225fe6 100644 --- a/src/ui/MockLinkConfiguration.cc +++ b/src/ui/MockLinkConfiguration.cc @@ -43,9 +43,12 @@ MockLinkConfiguration::MockLinkConfiguration(MockConfiguration *config, QWidget break; } - connect(_ui->px4Radio, &QRadioButton::clicked, this, &MockLinkConfiguration::_px4RadioClicked); - connect(_ui->apmRadio, &QRadioButton::clicked, this, &MockLinkConfiguration::_apmRadioClicked); - connect(_ui->genericRadio, &QRadioButton::clicked, this, &MockLinkConfiguration::_genericRadioClicked); + _ui->sendStatusTextCheckBox->setChecked(config->sendStatusText()); + + connect(_ui->px4Radio, &QRadioButton::clicked, this, &MockLinkConfiguration::_px4RadioClicked); + connect(_ui->apmRadio, &QRadioButton::clicked, this, &MockLinkConfiguration::_apmRadioClicked); + connect(_ui->genericRadio, &QRadioButton::clicked, this, &MockLinkConfiguration::_genericRadioClicked); + connect(_ui->sendStatusTextCheckBox, &QCheckBox::clicked, this, &MockLinkConfiguration::_sendStatusTextClicked); } MockLinkConfiguration::~MockLinkConfiguration() @@ -73,3 +76,8 @@ void MockLinkConfiguration::_genericRadioClicked(bool checked) _config->setFirmwareType(MAV_AUTOPILOT_GENERIC); } } + +void MockLinkConfiguration::_sendStatusTextClicked(bool checked) +{ + _config->setSendStatusText(checked); +} diff --git a/src/ui/MockLinkConfiguration.h b/src/ui/MockLinkConfiguration.h index 34feb999f39f8493d14f5c6cf5578e004b7f3948..61e55db10dcee1a6d264861200cc6ed0eb0a86dc 100644 --- a/src/ui/MockLinkConfiguration.h +++ b/src/ui/MockLinkConfiguration.h @@ -44,6 +44,7 @@ private slots: void _px4RadioClicked(bool checked); void _apmRadioClicked(bool checked); void _genericRadioClicked(bool checked); + void _sendStatusTextClicked(bool checked); private: Ui::MockLinkConfiguration* _ui; diff --git a/src/ui/MockLinkConfiguration.ui b/src/ui/MockLinkConfiguration.ui index d54fbb091abbf227b45934cb6427718f0f3629eb..1519985366115e7d0c045bb3757888494da11d36 100644 --- a/src/ui/MockLinkConfiguration.ui +++ b/src/ui/MockLinkConfiguration.ui @@ -35,6 +35,13 @@ + + + + Send status text + voice + + +