diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc index 8b6ddc2f09d008c5606cfcee0cfcd82de14f5d6d..b01ecdd1ba452746e554dbd92e798d67459d697f 100644 --- a/qgroundcontrol.qrc +++ b/qgroundcontrol.qrc @@ -177,6 +177,7 @@ src/FlightMap/MapItems/MissionItemIndicator.qml src/FlightMap/MapItems/VehicleMapItem.qml src/FlightMap/MapItems/MissionItemView.qml + src/FlightMap/MapItems/MissionLineView.qml diff --git a/src/FlightDisplay/FlightDisplayView.qml b/src/FlightDisplay/FlightDisplayView.qml index 012c749781aca2dfcd1d7234e069d1e71476339f..847245c3cfde529ea0708698f8dc6de17d3314e6 100644 --- a/src/FlightDisplay/FlightDisplayView.qml +++ b/src/FlightDisplay/FlightDisplayView.qml @@ -52,7 +52,7 @@ Item { readonly property alias zOrderWidgets: flightMap.zOrderWidgets readonly property alias zOrderMapItems: flightMap.zOrderMapItems - property var __qgcPal: QGCPalette { colorGroupEnabled: enabled } + QGCPalette { id: qgcPal; colorGroupEnabled: enabled } property var _activeVehicle: multiVehicleManager.activeVehicle @@ -184,6 +184,12 @@ Item { zOrderMapItems: flightMap.zOrderMapItems } + // Add lines between waypoints + MissionLineView { + model: _missionController.waypointLines + zOrderMapItems: flightMap.zOrderMapItems + } + Loader { id: flightMapDelayLoader anchors.fill: parent diff --git a/src/FlightMap/MapItems/MissionItemView.qml b/src/FlightMap/MapItems/MissionItemView.qml index 13d143bc90a0f111b5f45d5923fc1c84b4218fa2..4d0264d754d265f8a54e45e0c4aed9953ee05f20 100644 --- a/src/FlightMap/MapItems/MissionItemView.qml +++ b/src/FlightMap/MapItems/MissionItemView.qml @@ -29,9 +29,7 @@ import QtPositioning 5.3 import QGroundControl 1.0 import QGroundControl.FlightMap 1.0 -import QGroundControl.ScreenTools 1.0 import QGroundControl.Controls 1.0 -import QGroundControl.Palette 1.0 /// The MissionItemView control is used to add Mission Item Indicators to a FlightMap. MapItemView { @@ -42,11 +40,11 @@ MapItemView { delegate: MissionItemIndicator { id: itemIndicator - label: object.sequenceNumber == 0 ? "H" : object.sequenceNumber + label: object.homePosition ? "H" : object.sequenceNumber isCurrentItem: object.isCurrentItem coordinate: object.coordinate z: zOrderMapItems - visible: object.specifiesCoordinate + visible: object.specifiesCoordinate && (!object.homePosition || object.homePositionValid) onClicked: setCurrentItem(object.sequenceNumber) diff --git a/src/FlightMap/MapItems/MissionLineView.qml b/src/FlightMap/MapItems/MissionLineView.qml new file mode 100644 index 0000000000000000000000000000000000000000..bbb078369938a40d52635b5af01566a762e6b436 --- /dev/null +++ b/src/FlightMap/MapItems/MissionLineView.qml @@ -0,0 +1,45 @@ +/*===================================================================== + +QGroundControl Open Source Ground Control Station + +(c) 2009, 2015 QGROUNDCONTROL PROJECT + +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 . + +======================================================================*/ + +import QtQuick 2.4 +import QtLocation 5.3 +import QtPositioning 5.3 + +import QGroundControl 1.0 +import QGroundControl.Palette 1.0 + +/// The MissionLineView control is used to add lines between mission items +MapItemView { + property real zOrderMapItems ///< Z order for indicator + + delegate: MapPolyline { + line.width: 3 + line.color: "#be781c" // Hack, can't get palette to work in here + z: zOrderMapItems - 1 // Under item indicators + + path: [ + { latitude: object.coordinate1.latitude, longitude: object.coordinate1.longitude }, + { latitude: object.coordinate2.latitude, longitude: object.coordinate2.longitude }, + ] + } +} diff --git a/src/FlightMap/qmldir b/src/FlightMap/qmldir index 44207c0948f709b0064fe8f2def0805434a503a9..0f3ae93de041b0c7f9a2fe1dea5f14cc045c2535 100644 --- a/src/FlightMap/qmldir +++ b/src/FlightMap/qmldir @@ -21,3 +21,4 @@ QGCSpeedWidget 1.0 QGCSpeedWidget.qml VehicleMapItem 1.0 VehicleMapItem.qml MissionItemIndicator 1.0 MissionItemIndicator.qml MissionItemView 1.0 MissionItemView.qml +MissionLineView 1.0 MissionLineView.qml diff --git a/src/MissionEditor/MissionEditor.qml b/src/MissionEditor/MissionEditor.qml index 912255dd21f878d28980c49affeb42bda312c8a5..2aeb0a99e449e93abdeaefd0ec87874706a4eb1f 100644 --- a/src/MissionEditor/MissionEditor.qml +++ b/src/MissionEditor/MissionEditor.qml @@ -69,9 +69,13 @@ QGCView { MissionEditorController { id: controller +/* + FIXME: autoSync is temporarily disconnected since it's still buggy + autoSync: QGroundControl.flightMapSettings.loadMapSetting(editorMap.mapName, _autoSyncKey, true) onAutoSyncChanged: QGroundControl.flightMapSettings.saveMapSetting(editorMap.mapName, _autoSyncKey, autoSync) +*/ onMissionItemsChanged: { updateHomePosition() @@ -98,6 +102,7 @@ QGCView { function updateHomePosition() { homePosition = liveHomePositionAvailable ? liveHomePosition : offlineHomePosition _missionItems.get(0).coordinate = homePosition + _missionItems.get(0).homePositionValid = true } Component.onCompleted: updateHomePosition() @@ -222,20 +227,9 @@ QGCView { } // Add lines between waypoints - MapItemView { - model: controller.waypointLines - - delegate: - MapPolyline { - line.width: 3 - line.color: qgcPal.mapButtonHighlight - z: editorMap.zOrderMapItems - 1 // Under item indicators - - path: [ - { latitude: object.coordinate1.latitude, longitude: object.coordinate1.longitude }, - { latitude: object.coordinate2.latitude, longitude: object.coordinate2.longitude }, - ] - } + MissionLineView { + model: controller.waypointLines + zOrderMapItems: editorMap.zOrderMapItems } // Mission Item Editor @@ -880,7 +874,7 @@ QGCView { } Row { - visible: autoSyncCheckBox.enabled && autoSyncCheckBox.checked + visible: true //autoSyncCheckBox.enabled && autoSyncCheckBox.checked spacing: ScreenTools.defaultFontPixelWidth QGCButton { @@ -925,6 +919,8 @@ QGCView { } } } +/* + FIXME: autoSync is temporarily disconnected since it's still buggy QGCLabel { id: autoSyncDisallowedLabel @@ -940,6 +936,7 @@ QGCView { onClicked: controller.autoSync = checked } +*/ } } } // QGCVIew diff --git a/src/MissionEditor/MissionEditorController.cc b/src/MissionEditor/MissionEditorController.cc index c623b8e631ebf26880805f8feba7be60c0ebd80d..240494737884a254d7ae92f124559428e9eddb47 100644 --- a/src/MissionEditor/MissionEditorController.cc +++ b/src/MissionEditor/MissionEditorController.cc @@ -290,8 +290,6 @@ void MissionEditorController::_recalcSequence(void) { MissionItem* currentParentItem = qobject_cast(_missionItems->get(0)); - currentParentItem->childItems()->clear(); - for (int i=0; i<_missionItems->count(); i++) { MissionItem* item = qobject_cast(_missionItems->get(i)); @@ -340,9 +338,7 @@ void MissionEditorController::_initAllMissionItems(void) _initMissionItem(qobject_cast(_missionItems->get(i))); } - _recalcSequence(); - _recalcChildItems(); - _recalcWaypointLines(); + _recalcAll(); emit missionItemsChanged(); emit canEditChanged(_canEdit); diff --git a/src/MissionItem.cc b/src/MissionItem.cc index 019cce1e84ba84e43bdca0e2a5cacb95a9fe5fc5..0d0943eaa7722a1f4d397f8671897e0a1b3e782c 100644 --- a/src/MissionItem.cc +++ b/src/MissionItem.cc @@ -90,8 +90,9 @@ MissionItem::MissionItem(QObject* parent, , _isCurrentItem(isCurrentItem) , _reachedTime(0) , _headingDegreesFact(NULL) - ,_dirty(false) + , _dirty(false) , _homePositionSpecialCase(false) + , _homePositionValid(false) { _latitudeFact = new Fact(0, "Latitude:", FactMetaData::valueTypeDouble, this); _longitudeFact = new Fact(0, "Longitude:", FactMetaData::valueTypeDouble, this); @@ -198,6 +199,7 @@ const MissionItem& MissionItem::operator=(const MissionItem& other) _altitudeRelativeToHomeFact = other._altitudeRelativeToHomeFact; _dirty = other._dirty; _homePositionSpecialCase = other._homePositionSpecialCase; + _homePositionValid = other._homePositionValid; *_latitudeFact = *other._latitudeFact; *_longitudeFact = *other._longitudeFact; @@ -915,3 +917,9 @@ void MissionItem::_headingDegreesFactChanged(QVariant value) { emit headingDegreesChanged(value.toDouble()); } + +void MissionItem::setHomePositionValid(bool homePositionValid) +{ + _homePositionValid = homePositionValid; + emit homePositionValidChanged(_homePositionValid); +} diff --git a/src/MissionItem.h b/src/MissionItem.h index 382c3d8c48c0ab44bd4717e6089667c878933f3e..91ef639affb7f0c7516cdf28bb4bd65e54427205 100644 --- a/src/MissionItem.h +++ b/src/MissionItem.h @@ -84,7 +84,13 @@ public: Q_PROPERTY(QmlObjectListModel* checkboxFacts READ checkboxFacts NOTIFY commandChanged) Q_PROPERTY(MavlinkQmlSingleton::Qml_MAV_CMD command READ command WRITE setCommand NOTIFY commandChanged) Q_PROPERTY(QmlObjectListModel* childItems READ childItems CONSTANT) + + /// true: this item is being used as a home position indicator + Q_PROPERTY(bool homePosition MEMBER _homePositionSpecialCase CONSTANT) + /// true: home position should be shown + Q_PROPERTY(bool homePositionValid READ homePositionValid WRITE setHomePositionValid NOTIFY homePositionValidChanged) + // Property accesors int sequenceNumber(void) const { return _sequenceNumber; } @@ -124,6 +130,9 @@ public: void setDirty(bool dirty); QmlObjectListModel* childItems(void) { return &_childItems; } + + bool homePositionValid(void) { return _homePositionValid; } + void setHomePositionValid(bool homePositionValid); // C++ only methods @@ -210,6 +219,7 @@ signals: void coordinateChanged(const QGeoCoordinate& coordinate); void headingDegreesChanged(double heading); void dirtyChanged(bool dirty); + void homePositionValidChanged(bool homePostionValid); /** @brief Announces a change to the waypoint data */ void changed(MissionItem* wp); @@ -290,6 +300,7 @@ private: bool _dirty; bool _homePositionSpecialCase; ///< true: this item is being used as a ui home position indicator + bool _homePositionValid; ///< true: home psition should be displayed /// This is used to reference any subsequent mission items which do not specify a coordinate. QmlObjectListModel _childItems; diff --git a/src/MissionManager/MissionController.cc b/src/MissionManager/MissionController.cc index 2214c9a198a8827ae971f4c03e84f5b59a247585..41da7139d062a5c2768dad7ff802137766556230 100644 --- a/src/MissionManager/MissionController.cc +++ b/src/MissionManager/MissionController.cc @@ -71,28 +71,32 @@ void MissionController::_newMissionItemsAvailable(void) void MissionController::_recalcWaypointLines(void) { - bool firstCoordinateItem = true; - MissionItem* lastCoordinateItem = qobject_cast(_missionItems->get(0)); - + int firstIndex = _homePositionValid ? 0 : 1; + _waypointLines.clear(); - - for (int i=1; i<_missionItems->count(); i++) { - MissionItem* item = qobject_cast(_missionItems->get(i)); - - if (item->specifiesCoordinate()) { - if (firstCoordinateItem) { - if (item->command() == MavlinkQmlSingleton::MAV_CMD_NAV_TAKEOFF) { - // The first coordinate we hit is a takeoff command so link back to home position - _waypointLines.append(new CoordinateVector(qobject_cast(_missionItems->get(0))->coordinate(), item->coordinate())); + + if (firstIndex < _missionItems->count()) { + bool firstCoordinateItem = true; + MissionItem* lastCoordinateItem = qobject_cast(_missionItems->get(firstIndex)); + + for (int i=firstIndex; i<_missionItems->count(); i++) { + MissionItem* item = qobject_cast(_missionItems->get(i)); + + if (item->specifiesCoordinate()) { + if (firstCoordinateItem) { + if (item->command() == MavlinkQmlSingleton::MAV_CMD_NAV_TAKEOFF && _homePositionValid) { + // The first coordinate we hit is a takeoff command so link back to home position if we have one + _waypointLines.append(new CoordinateVector(qobject_cast(_missionItems->get(0))->coordinate(), item->coordinate())); + } else { + // First coordiante is not a takeoff command, it does not link backwards to anything + } + firstCoordinateItem = false; } else { - // First coordiante is not a takeoff command, it does not link backwards to anything + // Subsequent coordinate items link to last coordinate item + _waypointLines.append(new CoordinateVector(lastCoordinateItem->coordinate(), item->coordinate())); } - firstCoordinateItem = false; - } else { - // Subsequent coordinate items link to last coordinate item - _waypointLines.append(new CoordinateVector(lastCoordinateItem->coordinate(), item->coordinate())); + lastCoordinateItem = item; } - lastCoordinateItem = item; } } @@ -102,25 +106,41 @@ void MissionController::_recalcWaypointLines(void) // This will update the child item hierarchy void MissionController::_recalcChildItems(void) { - MissionItem* currentParentItem = qobject_cast(_missionItems->get(0)); - - currentParentItem->childItems()->clear(); - - for (int i=1; i<_missionItems->count(); i++) { - MissionItem* item = qobject_cast(_missionItems->get(i)); - - // Set up non-coordinate item child hierarchy - if (item->specifiesCoordinate()) { - item->childItems()->clear(); - currentParentItem = item; - } else { - currentParentItem->childItems()->append(item); + int firstIndex = _homePositionValid ? 0 : 1; + + if (_missionItems->count() > firstIndex) { + MissionItem* currentParentItem = qobject_cast(_missionItems->get(firstIndex)); + + currentParentItem->childItems()->clear(); + + for (int i=firstIndex+1; i<_missionItems->count(); i++) { + MissionItem* item = qobject_cast(_missionItems->get(i)); + + // Set up non-coordinate item child hierarchy + if (item->specifiesCoordinate()) { + item->childItems()->clear(); + currentParentItem = item; + } else { + currentParentItem->childItems()->append(item); + } } } } +// This will update the sequence numbers to be sequential starting from 0 +void MissionController::_recalcSequence(void) +{ + for (int i=0; i<_missionItems->count(); i++) { + MissionItem* item = qobject_cast(_missionItems->get(i)); + + // Setup ascending sequence numbers + item->setSequenceNumber(i); + } +} + void MissionController::_recalcAll(void) { + _recalcSequence(); _recalcChildItems(); _recalcWaypointLines(); } @@ -131,11 +151,13 @@ void MissionController::_initAllMissionItems(void) // Add the home position item to the front MissionItem* homeItem = new MissionItem(this); homeItem->setHomePositionSpecialCase(true); + homeItem->setHomePositionValid(false); homeItem->setCommand(MavlinkQmlSingleton::MAV_CMD_NAV_WAYPOINT); + homeItem->setLatitude(47.3769); + homeItem->setLongitude(8.549444); _missionItems->insert(0, homeItem); - _recalcChildItems(); - _recalcWaypointLines(); + _recalcAll(); emit missionItemsChanged(); } @@ -156,3 +178,11 @@ void MissionController::_activeVehicleChanged(Vehicle* activeVehicle) _newMissionItemsAvailable(); } } + +void MissionController::setHomePositionValid(bool homePositionValid) +{ + _homePositionValid = homePositionValid; + qobject_cast(_missionItems->get(0))->setHomePositionValid(homePositionValid); + + emit homePositionValidChanged(_homePositionValid); +} diff --git a/src/MissionManager/MissionController.h b/src/MissionManager/MissionController.h index 776dbbfda59be2600cd91e91c92168fe37a41d19..43a96ae5db5f4bbc450b6159e15a68607860d349 100644 --- a/src/MissionManager/MissionController.h +++ b/src/MissionManager/MissionController.h @@ -40,21 +40,29 @@ public: Q_PROPERTY(QmlObjectListModel* missionItems READ missionItems NOTIFY missionItemsChanged) Q_PROPERTY(QmlObjectListModel* waypointLines READ waypointLines NOTIFY waypointLinesChanged) + + /// true: home position should be shown on map, false: home position not shown on map + Q_PROPERTY(bool homePositionValid READ homePositionValid WRITE setHomePositionValid NOTIFY homePositionValidChanged) // Property accessors QmlObjectListModel* missionItems(void) { return _missionItems; } QmlObjectListModel* waypointLines(void) { return &_waypointLines; } + bool homePositionValid(void) { return _homePositionValid; } + void setHomePositionValid(bool homPositionValid); + signals: void missionItemsChanged(void); void waypointLinesChanged(void); + void homePositionValidChanged(bool homePositionValid); private slots: void _newMissionItemsAvailable(); void _activeVehicleChanged(Vehicle* activeVehicle); private: + void _recalcSequence(void); void _recalcWaypointLines(void); void _recalcChildItems(void); void _recalcAll(void); @@ -64,6 +72,7 @@ private: QmlObjectListModel* _missionItems; QmlObjectListModel _waypointLines; Vehicle* _activeVehicle; + bool _homePositionValid; }; #endif