diff --git a/src/FlightMap/MapItems/MissionItemIndicator.qml b/src/FlightMap/MapItems/MissionItemIndicator.qml index f3c58f3a69469720eb3e96933f5b9ac4bec93d02..a1e95f32dfabedc7a832f40fcff61f1d76b27aee 100644 --- a/src/FlightMap/MapItems/MissionItemIndicator.qml +++ b/src/FlightMap/MapItems/MissionItemIndicator.qml @@ -29,14 +29,15 @@ MapQuickItem { sourceItem: MissionItemIndexLabel { - id: _label - checked: _isCurrentItem - label: missionItem ? missionItem.abbreviation : "" - gimbalYaw: missionItem.missionGimbalYaw - vehicleYaw: missionItem.missionVehicleYaw - showGimbalYaw: !isNaN(missionItem.missionGimbalYaw) - highlightSelected: true - onClicked: _item.clicked() - property bool _isCurrentItem: missionItem ? missionItem.isCurrentItem : false + id: _label + checked: _isCurrentItem + label: missionItem ? missionItem.abbreviation : "" + gimbalYaw: missionItem.missionGimbalYaw + vehicleYaw: missionItem.missionVehicleYaw + showGimbalYaw: !isNaN(missionItem.missionGimbalYaw) + highlightSelected: true + onClicked: _item.clicked() + + property bool _isCurrentItem: missionItem ? missionItem.isCurrentItem || missionItem.hasCurrentChildItem : false } } diff --git a/src/MissionManager/MissionController.cc b/src/MissionManager/MissionController.cc index 4adb1dd1f3cb994afe5489914bd94e12bc13b9f9..48568e7815bbdb56598f37e55e7efe6f969b1564 100644 --- a/src/MissionManager/MissionController.cc +++ b/src/MissionManager/MissionController.cc @@ -1707,14 +1707,21 @@ void MissionController::_recalcChildItems(void) currentParentItem->childItems()->clear(); for (int i=1; i<_visualItems->count(); i++) { - VisualMissionItem* item = qobject_cast(_visualItems->get(i)); + VisualMissionItem* item = _visualItems->value(i); + + item->setParentItem(nullptr); + item->setHasCurrentChildItem(false); // Set up non-coordinate item child hierarchy if (item->specifiesCoordinate()) { item->childItems()->clear(); currentParentItem = item; } else if (item->isSimpleItem()) { + item->setParentItem(currentParentItem); currentParentItem->childItems()->append(item); + if (item->isCurrentItem()) { + currentParentItem->setHasCurrentChildItem(true); + } } } } @@ -2308,21 +2315,27 @@ void MissionController::setCurrentPlanViewSeqNum(int sequenceNumber, bool force) if (pVI->sequenceNumber() == sequenceNumber) { pVI->setIsCurrentItem(true); + pVI->setHasCurrentChildItem(false); + _currentPlanViewItem = pVI; _currentPlanViewSeqNum = sequenceNumber; _currentPlanViewVIIndex = viIndex; - if (pVI->specifiesCoordinate() && !pVI->isStandaloneCoordinate()) { - // Determine split segment used to display line split editing ui. - for (int j=viIndex-1; j>0; j--) { - VisualMissionItem* pPrev = qobject_cast(_visualItems->get(j)); - if (pPrev->specifiesCoordinate() && !pPrev->isStandaloneCoordinate()) { - VisualItemPair splitPair(pPrev, pVI); - if (_linesTable.contains(splitPair)) { - _splitSegment = _linesTable[splitPair]; + if (pVI->specifiesCoordinate()) { + if (!pVI->isStandaloneCoordinate()) { + // Determine split segment used to display line split editing ui. + for (int j=viIndex-1; j>0; j--) { + VisualMissionItem* pPrev = qobject_cast(_visualItems->get(j)); + if (pPrev->specifiesCoordinate() && !pPrev->isStandaloneCoordinate()) { + VisualItemPair splitPair(pPrev, pVI); + if (_linesTable.contains(splitPair)) { + _splitSegment = _linesTable[splitPair]; + } } } } + } else if (pVI->parentItem()) { + pVI->parentItem()->setHasCurrentChildItem(true); } } else { pVI->setIsCurrentItem(false); diff --git a/src/MissionManager/VisualMissionItem.cc b/src/MissionManager/VisualMissionItem.cc index 9141f349e0da31933535606abcec058e5d4556df..1d9a98cb8d3ca36ae9e6fb9dff35d8ab9e648337 100644 --- a/src/MissionManager/VisualMissionItem.cc +++ b/src/MissionManager/VisualMissionItem.cc @@ -26,21 +26,6 @@ VisualMissionItem::VisualMissionItem(Vehicle* vehicle, bool flyView, QObject* pa : QObject (parent) , _vehicle (vehicle) , _flyView (flyView) - , _isCurrentItem (false) - , _dirty (false) - , _homePositionSpecialCase (false) - , _terrainAltitude (qQNaN()) - , _altDifference (0.0) - , _altPercent (0.0) - , _terrainPercent (qQNaN()) - , _terrainCollision (false) - , _azimuth (0.0) - , _distance (0.0) - , _missionGimbalYaw (qQNaN()) - , _missionVehicleYaw (qQNaN()) - , _wizardMode (false) - , _lastLatTerrainQuery (0) - , _lastLonTerrainQuery (0) { _commonInit(); } @@ -49,16 +34,6 @@ VisualMissionItem::VisualMissionItem(const VisualMissionItem& other, bool flyVie : QObject (parent) , _vehicle (nullptr) , _flyView (flyView) - , _isCurrentItem (false) - , _dirty (false) - , _homePositionSpecialCase (false) - , _altDifference (0.0) - , _altPercent (0.0) - , _terrainPercent (qQNaN()) - , _terrainCollision (false) - , _azimuth (0.0) - , _distance (0.0) - , _wizardMode (false) { *this = other; @@ -106,6 +81,14 @@ void VisualMissionItem::setIsCurrentItem(bool isCurrentItem) } } +void VisualMissionItem::setHasCurrentChildItem(bool hasCurrentChildItem) +{ + if (_hasCurrentChildItem != hasCurrentChildItem) { + _hasCurrentChildItem = hasCurrentChildItem; + emit hasCurrentChildItemChanged(hasCurrentChildItem); + } +} + void VisualMissionItem::setDistance(double distance) { if (!qFuzzyCompare(_distance, distance)) { @@ -228,3 +211,11 @@ void VisualMissionItem::setWizardMode(bool wizardMode) emit wizardModeChanged(_wizardMode); } } + +void VisualMissionItem::setParentItem(VisualMissionItem* parentItem) +{ + if (_parentItem != parentItem) { + _parentItem = parentItem; + emit parentItemChanged(parentItem); + } +} diff --git a/src/MissionManager/VisualMissionItem.h b/src/MissionManager/VisualMissionItem.h index d83dee180ac1d017568b6fb2ad0d6756efbf94ad..6e9f33389eabcc9cfd87732ff0d4e4630ae8f743 100644 --- a/src/MissionManager/VisualMissionItem.h +++ b/src/MissionManager/VisualMissionItem.h @@ -47,38 +47,40 @@ public: }; Q_ENUM(ReadyForSaveState) - Q_PROPERTY(bool homePosition READ homePosition CONSTANT) ///< true: This item is being used as a home position indicator - Q_PROPERTY(QGeoCoordinate coordinate READ coordinate WRITE setCoordinate NOTIFY coordinateChanged) ///< This is the entry point for a waypoint line into the item. For a simple item it is also the location of the item - Q_PROPERTY(double terrainAltitude READ terrainAltitude NOTIFY terrainAltitudeChanged) ///< The altitude of terrain at the coordinate position, NaN if not known - Q_PROPERTY(bool coordinateHasRelativeAltitude READ coordinateHasRelativeAltitude NOTIFY coordinateHasRelativeAltitudeChanged) ///< true: coordinate.latitude is relative to home altitude - Q_PROPERTY(QGeoCoordinate exitCoordinate READ exitCoordinate NOTIFY exitCoordinateChanged) ///< This is the exit point for a waypoint line coming out of the item. - Q_PROPERTY(bool exitCoordinateHasRelativeAltitude READ exitCoordinateHasRelativeAltitude NOTIFY exitCoordinateHasRelativeAltitudeChanged) ///< true: coordinate.latitude is relative to home altitude - Q_PROPERTY(bool exitCoordinateSameAsEntry READ exitCoordinateSameAsEntry NOTIFY exitCoordinateSameAsEntryChanged) ///< true: exitCoordinate and coordinate are the same value - Q_PROPERTY(QString commandDescription READ commandDescription NOTIFY commandDescriptionChanged) - Q_PROPERTY(QString commandName READ commandName NOTIFY commandNameChanged) - Q_PROPERTY(QString abbreviation READ abbreviation NOTIFY abbreviationChanged) - Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged) ///< Item is dirty and requires save/send - Q_PROPERTY(bool isCurrentItem READ isCurrentItem WRITE setIsCurrentItem NOTIFY isCurrentItemChanged) - Q_PROPERTY(int sequenceNumber READ sequenceNumber WRITE setSequenceNumber NOTIFY sequenceNumberChanged) - Q_PROPERTY(int lastSequenceNumber READ lastSequenceNumber NOTIFY lastSequenceNumberChanged) - Q_PROPERTY(bool specifiesCoordinate READ specifiesCoordinate NOTIFY specifiesCoordinateChanged) ///< true: Item is associated with a coordinate position - Q_PROPERTY(bool isStandaloneCoordinate READ isStandaloneCoordinate NOTIFY isStandaloneCoordinateChanged) ///< true: Waypoint line does not go through item - Q_PROPERTY(bool specifiesAltitudeOnly READ specifiesAltitudeOnly NOTIFY specifiesAltitudeOnlyChanged) ///< true: Item has altitude only, no full coordinate - Q_PROPERTY(bool isSimpleItem READ isSimpleItem NOTIFY isSimpleItemChanged) ///< Simple or Complex MissionItem - Q_PROPERTY(bool isTakeoffItem READ isTakeoffItem NOTIFY isTakeoffItemChanged) ///< true: Takeoff item special case - Q_PROPERTY(QString editorQml MEMBER _editorQml CONSTANT) ///< Qml code for editing this item - Q_PROPERTY(QString mapVisualQML READ mapVisualQML CONSTANT) ///< QMl code for map visuals - Q_PROPERTY(QmlObjectListModel* childItems READ childItems CONSTANT) - Q_PROPERTY(double specifiedFlightSpeed READ specifiedFlightSpeed NOTIFY specifiedFlightSpeedChanged) ///< NaN if this item does not specify flight speed - Q_PROPERTY(double specifiedGimbalYaw READ specifiedGimbalYaw NOTIFY specifiedGimbalYawChanged) ///< Gimbal yaw, NaN for not specified - Q_PROPERTY(double specifiedGimbalPitch READ specifiedGimbalPitch NOTIFY specifiedGimbalPitchChanged) ///< Gimbal pitch, NaN for not specified - Q_PROPERTY(double missionGimbalYaw READ missionGimbalYaw NOTIFY missionGimbalYawChanged) ///< Current gimbal yaw state at this point in mission - Q_PROPERTY(double missionVehicleYaw READ missionVehicleYaw NOTIFY missionVehicleYawChanged) ///< Expected vehicle yaw at this point in mission - Q_PROPERTY(bool flyView READ flyView CONSTANT) - Q_PROPERTY(bool wizardMode READ wizardMode WRITE setWizardMode NOTIFY wizardModeChanged) - Q_PROPERTY(ReadyForSaveState readyForSaveState READ readyForSaveState NOTIFY readyForSaveStateChanged) - - Q_PROPERTY(QGCGeoBoundingCube* boundingCube READ boundingCube NOTIFY boundingCubeChanged) + Q_PROPERTY(bool homePosition READ homePosition CONSTANT) ///< true: This item is being used as a home position indicator + Q_PROPERTY(QGeoCoordinate coordinate READ coordinate WRITE setCoordinate NOTIFY coordinateChanged) ///< This is the entry point for a waypoint line into the item. For a simple item it is also the location of the item + Q_PROPERTY(double terrainAltitude READ terrainAltitude NOTIFY terrainAltitudeChanged) ///< The altitude of terrain at the coordinate position, NaN if not known + Q_PROPERTY(bool coordinateHasRelativeAltitude READ coordinateHasRelativeAltitude NOTIFY coordinateHasRelativeAltitudeChanged) ///< true: coordinate.latitude is relative to home altitude + Q_PROPERTY(QGeoCoordinate exitCoordinate READ exitCoordinate NOTIFY exitCoordinateChanged) ///< This is the exit point for a waypoint line coming out of the item. + Q_PROPERTY(bool exitCoordinateHasRelativeAltitude READ exitCoordinateHasRelativeAltitude NOTIFY exitCoordinateHasRelativeAltitudeChanged) ///< true: coordinate.latitude is relative to home altitude + Q_PROPERTY(bool exitCoordinateSameAsEntry READ exitCoordinateSameAsEntry NOTIFY exitCoordinateSameAsEntryChanged) ///< true: exitCoordinate and coordinate are the same value + Q_PROPERTY(QString commandDescription READ commandDescription NOTIFY commandDescriptionChanged) + Q_PROPERTY(QString commandName READ commandName NOTIFY commandNameChanged) + Q_PROPERTY(QString abbreviation READ abbreviation NOTIFY abbreviationChanged) + Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged) ///< Item is dirty and requires save/send + Q_PROPERTY(bool isCurrentItem READ isCurrentItem WRITE setIsCurrentItem NOTIFY isCurrentItemChanged) + Q_PROPERTY(bool hasCurrentChildItem READ hasCurrentChildItem WRITE setHasCurrentChildItem NOTIFY hasCurrentChildItemChanged) ///< true: On of this items children is current + Q_PROPERTY(int sequenceNumber READ sequenceNumber WRITE setSequenceNumber NOTIFY sequenceNumberChanged) + Q_PROPERTY(int lastSequenceNumber READ lastSequenceNumber NOTIFY lastSequenceNumberChanged) + Q_PROPERTY(bool specifiesCoordinate READ specifiesCoordinate NOTIFY specifiesCoordinateChanged) ///< true: Item is associated with a coordinate position + Q_PROPERTY(bool isStandaloneCoordinate READ isStandaloneCoordinate NOTIFY isStandaloneCoordinateChanged) ///< true: Waypoint line does not go through item + Q_PROPERTY(bool specifiesAltitudeOnly READ specifiesAltitudeOnly NOTIFY specifiesAltitudeOnlyChanged) ///< true: Item has altitude only, no full coordinate + Q_PROPERTY(bool isSimpleItem READ isSimpleItem NOTIFY isSimpleItemChanged) ///< Simple or Complex MissionItem + Q_PROPERTY(bool isTakeoffItem READ isTakeoffItem NOTIFY isTakeoffItemChanged) ///< true: Takeoff item special case + Q_PROPERTY(QString editorQml MEMBER _editorQml CONSTANT) ///< Qml code for editing this item + Q_PROPERTY(QString mapVisualQML READ mapVisualQML CONSTANT) ///< QMl code for map visuals + Q_PROPERTY(QmlObjectListModel* childItems READ childItems CONSTANT) + Q_PROPERTY(double specifiedFlightSpeed READ specifiedFlightSpeed NOTIFY specifiedFlightSpeedChanged) ///< NaN if this item does not specify flight speed + Q_PROPERTY(double specifiedGimbalYaw READ specifiedGimbalYaw NOTIFY specifiedGimbalYawChanged) ///< Gimbal yaw, NaN for not specified + Q_PROPERTY(double specifiedGimbalPitch READ specifiedGimbalPitch NOTIFY specifiedGimbalPitchChanged) ///< Gimbal pitch, NaN for not specified + Q_PROPERTY(double missionGimbalYaw READ missionGimbalYaw NOTIFY missionGimbalYawChanged) ///< Current gimbal yaw state at this point in mission + Q_PROPERTY(double missionVehicleYaw READ missionVehicleYaw NOTIFY missionVehicleYawChanged) ///< Expected vehicle yaw at this point in mission + Q_PROPERTY(bool flyView READ flyView CONSTANT) + Q_PROPERTY(bool wizardMode READ wizardMode WRITE setWizardMode NOTIFY wizardModeChanged) + Q_PROPERTY(ReadyForSaveState readyForSaveState READ readyForSaveState NOTIFY readyForSaveStateChanged) + Q_PROPERTY(VisualMissionItem* parentItem READ parentItem WRITE setParentItem NOTIFY parentItemChanged) + + Q_PROPERTY(QGCGeoBoundingCube* boundingCube READ boundingCube NOTIFY boundingCubeChanged) // The following properties are calculated/set by the MissionController recalc methods @@ -90,28 +92,32 @@ public: Q_PROPERTY(double distance READ distance WRITE setDistance NOTIFY distanceChanged) ///< Distance to previous waypoint // Property accesors - bool homePosition (void) const { return _homePositionSpecialCase; } - double altDifference (void) const { return _altDifference; } - double altPercent (void) const { return _altPercent; } - double terrainPercent (void) const { return _terrainPercent; } - bool terrainCollision(void) const { return _terrainCollision; } - double azimuth (void) const { return _azimuth; } - double distance (void) const { return _distance; } - bool isCurrentItem (void) const { return _isCurrentItem; } - double terrainAltitude (void) const { return _terrainAltitude; } - bool flyView (void) const { return _flyView; } - bool wizardMode (void) const { return _wizardMode; } + bool homePosition (void) const { return _homePositionSpecialCase; } + double altDifference (void) const { return _altDifference; } + double altPercent (void) const { return _altPercent; } + double terrainPercent (void) const { return _terrainPercent; } + bool terrainCollision (void) const { return _terrainCollision; } + double azimuth (void) const { return _azimuth; } + double distance (void) const { return _distance; } + bool isCurrentItem (void) const { return _isCurrentItem; } + bool hasCurrentChildItem (void) const { return _hasCurrentChildItem; } + double terrainAltitude (void) const { return _terrainAltitude; } + bool flyView (void) const { return _flyView; } + bool wizardMode (void) const { return _wizardMode; } + VisualMissionItem* parentItem(void) { return _parentItem; } QmlObjectListModel* childItems(void) { return &_childItems; } - void setIsCurrentItem (bool isCurrentItem); - void setAltDifference (double altDifference); - void setAltPercent (double altPercent); - void setTerrainPercent (double terrainPercent); - void setTerrainCollision(bool terrainCollision); - void setAzimuth (double azimuth); - void setDistance (double distance); - void setWizardMode (bool wizardMode); + void setIsCurrentItem (bool isCurrentItem); + void setHasCurrentChildItem (bool hasCurrentChildItem); + void setAltDifference (double altDifference); + void setAltPercent (double altPercent); + void setTerrainPercent (double terrainPercent); + void setTerrainCollision (bool terrainCollision); + void setAzimuth (double azimuth); + void setDistance (double distance); + void setWizardMode (bool wizardMode); + void setParentItem (VisualMissionItem* parentItem); void setHomePositionSpecialCase (bool homePositionSpecialCase) { _homePositionSpecialCase = homePositionSpecialCase; } @@ -194,6 +200,7 @@ signals: void dirtyChanged (bool dirty); void distanceChanged (double distance); void isCurrentItemChanged (bool isCurrentItem); + void hasCurrentChildItemChanged (bool hasCurrentChildItem); void sequenceNumberChanged (int sequenceNumber); void isSimpleItemChanged (bool isSimpleItem); void isTakeoffItemChanged (bool isTakeoffItem); @@ -211,6 +218,7 @@ signals: void boundingCubeChanged (void); void readyForSaveStateChanged (void); void wizardModeChanged (bool wizardMode); + void parentItemChanged (VisualMissionItem* parentItem); void coordinateHasRelativeAltitudeChanged (bool coordinateHasRelativeAltitude); void exitCoordinateHasRelativeAltitudeChanged (bool exitCoordinateHasRelativeAltitude); @@ -218,23 +226,25 @@ signals: protected: Vehicle* _vehicle; - bool _flyView; - bool _isCurrentItem; - bool _dirty; - bool _homePositionSpecialCase; ///< true: This item is being used as a ui home position indicator - double _terrainAltitude; ///< Altitude of terrain at coordinate position, NaN for not known - double _altDifference; ///< Difference in altitude from previous waypoint - double _altPercent; ///< Percent of total altitude change in mission - double _terrainPercent; ///< Percent of terrain altitude for coordinate - bool _terrainCollision; ///< true: item collides with terrain - double _azimuth; ///< Azimuth to previous waypoint - double _distance; ///< Distance to previous waypoint - QString _editorQml; ///< Qml resource for editing item - double _missionGimbalYaw; - double _missionVehicleYaw; - bool _wizardMode; ///< true: Item editor is showing wizard completion panel - - QGCGeoBoundingCube _boundingCube; ///< The bounding "cube" of this element. + bool _flyView = false; + bool _isCurrentItem = false; + bool _hasCurrentChildItem = false; + bool _dirty = false; + bool _homePositionSpecialCase = false; ///< true: This item is being used as a ui home position indicator + bool _wizardMode = false; ///< true: Item editor is showing wizard completion panel + double _terrainAltitude = qQNaN(); ///< Altitude of terrain at coordinate position, NaN for not known + double _altDifference = 0; ///< Difference in altitude from previous waypoint + double _altPercent = 0; ///< Percent of total altitude change in mission + double _terrainPercent = qQNaN(); ///< Percent of terrain altitude for coordinate + bool _terrainCollision = false; ///< true: item collides with terrain + double _azimuth = 0; ///< Azimuth to previous waypoint + double _distance = 0; ///< Distance to previous waypoint + QString _editorQml; ///< Qml resource for editing item + double _missionGimbalYaw = qQNaN(); + double _missionVehicleYaw = qQNaN(); + + VisualMissionItem* _parentItem = nullptr; + QGCGeoBoundingCube _boundingCube; ///< The bounding "cube" of this element. MissionController::MissionFlightStatus_t _missionFlightStatus; @@ -253,6 +263,6 @@ private: void _commonInit(void); QTimer _updateTerrainTimer; - double _lastLatTerrainQuery; - double _lastLonTerrainQuery; + double _lastLatTerrainQuery = 0; + double _lastLonTerrainQuery = 0; };