Commit 1dffdbf1 authored by DonLakeFlyer's avatar DonLakeFlyer

Waypoint now supports camera section

parent 2f1e631c
......@@ -449,6 +449,7 @@ HEADERS += \
src/JsonHelper.h \
src/LogCompressor.h \
src/MG.h \
src/MissionManager/CameraSection.h \
src/MissionManager/ComplexMissionItem.h \
src/MissionManager/FixedWingLandingComplexItem.h \
src/MissionManager/GeoFenceController.h \
......@@ -626,6 +627,7 @@ SOURCES += \
src/Joystick/JoystickManager.cc \
src/JsonHelper.cc \
src/LogCompressor.cc \
src/MissionManager/CameraSection.cc \
src/MissionManager/ComplexMissionItem.cc \
src/MissionManager/FixedWingLandingComplexItem.cc \
src/MissionManager/GeoFenceController.cc \
......
......@@ -49,6 +49,7 @@
<file alias="PX4FlowSensor.qml">src/VehicleSetup/PX4FlowSensor.qml</file>
<file alias="QGroundControl/Controls/AnalyzePage.qml">src/AnalyzeView/AnalyzePage.qml</file>
<file alias="QGroundControl/Controls/AppMessages.qml">src/QmlControls/AppMessages.qml</file>
<file alias="QGroundControl/Controls/CameraSection.qml">src/MissionEditor/CameraSection.qml</file>
<file alias="QGroundControl/Controls/ClickableColor.qml">src/QmlControls/ClickableColor.qml</file>
<file alias="QGroundControl/Controls/DropButton.qml">src/QmlControls/DropButton.qml</file>
<file alias="QGroundControl/Controls/ExclusiveGroupItem.qml">src/QmlControls/ExclusiveGroupItem.qml</file>
......@@ -192,6 +193,7 @@
<file alias="RallyPoint.FactMetaData.json">src/MissionManager/RallyPoint.FactMetaData.json</file>
<file alias="FWLandingPattern.FactMetaData.json">src/MissionManager/FWLandingPattern.FactMetaData.json</file>
<file alias="USBBoardInfo.json">src/comm/USBBoardInfo.json</file>
<file alias="CameraSection.FactMetaData.json">src/MissionManager/CameraSection.FactMetaData.json</file>
<file alias="MissionSettings.FactMetaData.json">src/MissionManager/MissionSettings.FactMetaData.json</file>
<file alias="Vehicle/VehicleFact.json">src/Vehicle/VehicleFact.json</file>
<file alias="Vehicle/BatteryFact.json">src/Vehicle/BatteryFact.json</file>
......
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.2
import QGroundControl 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Controls 1.0
import QGroundControl.FactControls 1.0
import QGroundControl.Palette 1.0
// Camera section for mission item editors
Column {
anchors.left: parent.left
anchors.right: parent.right
spacing: _margin
property alias exclusiveGroup: cameraSectionHeader.exclusiveGroup
property alias showSpacer: cameraSectionHeader.showSpacer
property alias checked: cameraSectionHeader.checked
property var _camera: missionItem.cameraSection
property real _fieldWidth: ScreenTools.defaultFontPixelWidth * 16
property real _margin: ScreenTools.defaultFontPixelWidth / 2
SectionHeader {
id: cameraSectionHeader
text: qsTr("Camera")
checked: false
}
Column {
anchors.left: parent.left
anchors.right: parent.right
spacing: _margin
visible: cameraSectionHeader.checked
FactComboBox {
id: cameraActionCombo
anchors.left: parent.left
anchors.right: parent.right
fact: _camera.cameraAction
indexModel: false
}
RowLayout {
anchors.left: parent.left
anchors.right: parent.right
spacing: ScreenTools.defaultFontPixelWidth
visible: cameraActionCombo.currentIndex == 1
QGCLabel {
text: qsTr("Time")
Layout.fillWidth: true
}
FactTextField {
fact: _camera.cameraPhotoIntervalTime
Layout.preferredWidth: _fieldWidth
}
}
RowLayout {
anchors.left: parent.left
anchors.right: parent.right
spacing: ScreenTools.defaultFontPixelWidth
visible: cameraActionCombo.currentIndex == 2
QGCLabel {
text: qsTr("Distance")
Layout.fillWidth: true
}
FactTextField {
fact: _camera.cameraPhotoIntervalDistance
Layout.preferredWidth: _fieldWidth
}
}
GridLayout {
anchors.left: parent.left
anchors.right: parent.right
columnSpacing: ScreenTools.defaultFontPixelWidth / 2
rowSpacing: 0
columns: 3
Item { width: 1; height: 1 }
QGCLabel { text: qsTr("Pitch") }
QGCLabel { text: qsTr("Yaw") }
QGCCheckBox {
id: gimbalCheckBox
text: qsTr("Gimbal")
checked: _camera.specifyGimbal
onClicked: _camera.specifyGimbal = checked
Layout.fillWidth: true
}
FactTextField {
fact: _camera.gimbalPitch
implicitWidth: ScreenTools.defaultFontPixelWidth * 9
enabled: gimbalCheckBox.checked
}
FactTextField {
fact: _camera.gimbalYaw
implicitWidth: ScreenTools.defaultFontPixelWidth * 9
enabled: gimbalCheckBox.checked
}
}
}
}
......@@ -579,7 +579,7 @@ QGCView {
spacing: _margin / 2
orientation: ListView.Vertical
model: missionController.visualItems
cacheBuffer: height * 2
cacheBuffer: Math.max(height * 2, 0)
clip: true
currentIndex: _currentMissionIndex
highlightMoveDuration: 250
......
......@@ -19,12 +19,6 @@ Rectangle {
visible: missionItem.isCurrentItem
radius: _radius
ExclusiveGroup {
id: sectionHeaderExclusiverGroup
}
property ExclusiveGroup sectionHeaderGroup: ScreenTools.isShortScreen ? sectionHeaderExclusiverGroup : null
Loader {
id: deferedload
active: valuesRect.visible
......@@ -64,7 +58,6 @@ Rectangle {
id: plannedHomePositionSection
text: qsTr("Planned Home Position")
showSpacer: false
exclusiveGroup: sectionHeaderGroup
}
Column {
......@@ -125,7 +118,6 @@ Rectangle {
text: qsTr("Vehicle Info")
visible: _multipleFirmware && _showOfflineEditingCombos
checked: false
exclusiveGroup: sectionHeaderGroup
}
GridLayout {
......@@ -183,7 +175,6 @@ Rectangle {
id: missionDefaultsSectionHeader
text: qsTr("Mission Defaults")
checked: false
exclusiveGroup: sectionHeaderGroup
}
Column {
......@@ -233,89 +224,8 @@ Rectangle {
*/
}
SectionHeader {
id: cameraSectionHeader
text: qsTr("Camera")
checked: false
exclusiveGroup: sectionHeaderGroup
}
Column {
anchors.left: parent.left
anchors.right: parent.right
spacing: _margin
visible: cameraSectionHeader.checked
FactComboBox {
id: cameraActionCombo
anchors.left: parent.left
anchors.right: parent.right
fact: missionItem.cameraAction
indexModel: false
}
RowLayout {
anchors.left: parent.left
anchors.right: parent.right
spacing: ScreenTools.defaultFontPixelWidth
visible: cameraActionCombo.currentIndex == 1
QGCLabel {
text: qsTr("Time")
Layout.fillWidth: true
}
FactTextField {
fact: missionItem.cameraPhotoIntervalTime
Layout.preferredWidth: _fieldWidth
}
}
RowLayout {
anchors.left: parent.left
anchors.right: parent.right
spacing: ScreenTools.defaultFontPixelWidth
visible: cameraActionCombo.currentIndex == 2
QGCLabel {
text: qsTr("Distance")
Layout.fillWidth: true
}
FactTextField {
fact: missionItem.cameraPhotoIntervalDistance
Layout.preferredWidth: _fieldWidth
}
}
GridLayout {
anchors.left: parent.left
anchors.right: parent.right
columnSpacing: 0
rowSpacing: 0
columns: 3
Item { width: 1; height: 1 }
QGCLabel { text: qsTr("Pitch") }
QGCLabel { text: qsTr("Yaw") }
QGCCheckBox {
id: gimbalCheckBox
text: qsTr("Gimbal")
checked: missionItem.specifyGimbal
onClicked: missionItem.specifyGimbal = checked
Layout.fillWidth: true
}
FactTextField {
fact: missionItem.gimbalPitch
implicitWidth: ScreenTools.defaultFontPixelWidth * 9
enabled: gimbalCheckBox.checked
}
FactTextField {
fact: missionItem.gimbalYaw
implicitWidth: ScreenTools.defaultFontPixelWidth * 9
enabled: gimbalCheckBox.checked
}
}
CameraSection {
checked: missionItem.cameraSection.settingsSpecified
}
QGCLabel {
......
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.2
import QtGraphicalEffects 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Palette 1.0
......@@ -41,10 +42,14 @@ QGCMouseArea {
id: label
Layout.fillWidth: true
Image {
QGCColoredImage {
id: image
width: label.height / 2
height: width
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
source: "/qmlimages/arrow-down.png"
color: qgcPal.text
visible: !_root.checked
}
}
......
......@@ -27,6 +27,7 @@ Rectangle {
anchors.left: valuesRect.left
anchors.right: valuesRect.right
anchors.top: valuesRect.top
sourceComponent: Component {
Item {
id: valuesItem
......@@ -114,6 +115,11 @@ Rectangle {
fact: object
}
}
CameraSection {
checked: missionItem.cameraSection.settingsSpecified
visible: missionItem.cameraSection.available
}
} // Column
} // Item
} // Component
......
[
{
"name": "CameraAction",
"shortDescription": "Specify whether the camera should take photos or video",
"type": "uint32",
"enumStrings": "Continue current action,Take photos (time),Take photos (distance),Take video",
"enumValues": "0,1,2,3",
"defaultValue": 0
},
{
"name": "CameraPhotoIntervalDistance",
"shortDescription": "Specify the distance between each photo",
"type": "double",
"units": "m",
"min": 0,
"decimalPlaces": 1,
"defaultValue": 1
},
{
"name": "CameraPhotoIntervalTime",
"shortDescription": "Specify the time between each photo",
"type": "uint32",
"units": "secs",
"min": 1,
"decimalPlaces": 0,
"defaultValue": 10
},
{
"name": "GimbalPitch",
"shortDescription": "Gimbal pitch rotation.",
"type": "double",
"units": "deg",
"min": 0.0,
"max": 360.0,
"decimalPlaces": 0,
"defaultValue": 0
},
{
"name": "GimbalYaw",
"shortDescription": "Gimbal yaw rotation.",
"type": "double",
"units": "deg",
"min": 0.0,
"max": 360.0,
"decimalPlaces": 0,
"defaultValue": 0
}
]
This diff is collapsed.
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#ifndef CameraSection_H
#define CameraSection_H
#include "ComplexMissionItem.h"
#include "MissionItem.h"
#include "Fact.h"
Q_DECLARE_LOGGING_CATEGORY(CameraSectionLog)
class CameraSection : public QObject
{
Q_OBJECT
public:
CameraSection(QObject* parent = NULL);
enum CameraAction {
CameraActionNone,
TakePhotosIntervalTime,
TakePhotoIntervalDistance,
TakeVideo
};
Q_ENUMS(CameraAction)
Q_PROPERTY(bool available READ available WRITE setAvailable NOTIFY availableChanged)
Q_PROPERTY(bool settingsSpecified MEMBER _settingsSpecified NOTIFY settingsSpecifiedChanged)
Q_PROPERTY(bool specifyGimbal READ specifyGimbal WRITE setSpecifyGimbal NOTIFY specifyGimbalChanged)
Q_PROPERTY(Fact* gimbalPitch READ gimbalPitch CONSTANT)
Q_PROPERTY(Fact* gimbalYaw READ gimbalYaw CONSTANT)
Q_PROPERTY(Fact* cameraAction READ cameraAction CONSTANT)
Q_PROPERTY(Fact* cameraPhotoIntervalTime READ cameraPhotoIntervalTime CONSTANT)
Q_PROPERTY(Fact* cameraPhotoIntervalDistance READ cameraPhotoIntervalDistance CONSTANT)
bool available (void) const { return _available; }
void setAvailable (bool available);
bool specifyGimbal (void) const { return _specifyGimbal; }
Fact* gimbalYaw (void) { return &_gimbalYawFact; }
Fact* gimbalPitch (void) { return &_gimbalPitchFact; }
Fact* cameraAction (void) { return &_cameraActionFact; }
Fact* cameraPhotoIntervalTime (void) { return &_cameraPhotoIntervalTimeFact; }
Fact* cameraPhotoIntervalDistance (void) { return &_cameraPhotoIntervalDistanceFact; }
/// Scans the loaded items for the section items
/// @param visualItems Item list
/// @param scanIndex Index to start scanning from
/// @return true: camera section found
bool scanForCameraSection(QmlObjectListModel* visualItems, int scanIndex);
/// Appends the mission items associated with this section
/// @param items List to append to
/// @param missionItemParent QObject parent for created MissionItems
/// @param nextSequenceNumber Sequence number for first item
void appendMissionItems(QList<MissionItem*>& items, QObject* missionItemParent, int nextSequenceNumber);
void setSpecifyGimbal (bool specifyGimbal);
bool dirty (void) const { return _dirty; }
void setDirty (bool dirty);
/// Returns the number of mission items represented by this section.
/// Signals: missionItemCountChanged on change
int missionItemCount(void) const;
signals:
void availableChanged (bool available);
void settingsSpecifiedChanged (bool settingsSpecified);
void dirtyChanged (bool dirty);
bool specifyGimbalChanged (bool specifyGimbal);
void missionItemCountChanged (int missionItemCount);
private slots:
void _setDirty(void);
void _setDirtyAndUpdateMissionItemCount(void);
private:
bool _available;
bool _settingsSpecified;
bool _specifyGimbal;
Fact _gimbalYawFact;
Fact _gimbalPitchFact;
Fact _cameraActionFact;
Fact _cameraPhotoIntervalDistanceFact;
Fact _cameraPhotoIntervalTimeFact;
bool _dirty;
static QMap<QString, FactMetaData*> _metaDataMap;
static const char* _gimbalPitchName;
static const char* _gimbalYawName;
static const char* _cameraActionName;
static const char* _cameraPhotoIntervalDistanceName;
static const char* _cameraPhotoIntervalTimeName;
};
#endif
......@@ -21,19 +21,11 @@ public:
const ComplexMissionItem& operator=(const ComplexMissionItem& other);
Q_PROPERTY(int lastSequenceNumber READ lastSequenceNumber NOTIFY lastSequenceNumberChanged)
Q_PROPERTY(double complexDistance READ complexDistance NOTIFY complexDistanceChanged)
/// @return The distance covered the complex mission item in meters.
virtual double complexDistance(void) const = 0;
/// @return The last sequence number used by this item. Takes into account child items of the complex item
virtual int lastSequenceNumber(void) const = 0;
/// Returns the mission items associated with the complex item. Caller is responsible for freeing. Calling
/// delete on returned QmlObjectListModel will free all memory including internal items.
virtual QmlObjectListModel* getMissionItems(void) const = 0;
/// Load the complex mission item from Json
/// @param complexObject Complex mission item json object
/// @param sequenceNumber Sequence number for first MISSION_ITEM in survey
......@@ -53,8 +45,7 @@ public:
static const char* jsonComplexItemTypeKey;
signals:
void lastSequenceNumberChanged (int lastSequenceNumber);
void complexDistanceChanged (double complexDistance);
void complexDistanceChanged(double complexDistance);
};
#endif
......@@ -105,7 +105,7 @@ void FixedWingLandingComplexItem::setDirty(bool dirty)
}
}
void FixedWingLandingComplexItem::save(QJsonArray& missionItems) const
void FixedWingLandingComplexItem::save(QJsonArray& missionItems)
{
QJsonObject saveObject;
......@@ -203,10 +203,8 @@ bool FixedWingLandingComplexItem::specifiesCoordinate(void) const
return true;
}
QmlObjectListModel* FixedWingLandingComplexItem::getMissionItems(void) const
void FixedWingLandingComplexItem::appendMissionItems(QList<MissionItem*>& items, QObject* missionItemParent)
{
QmlObjectListModel* pMissionItems = new QmlObjectListModel;
int seqNum = _sequenceNumber;
MissionItem* item = new MissionItem(seqNum++, // sequence number
......@@ -215,8 +213,8 @@ QmlObjectListModel* FixedWingLandingComplexItem::getMissionItems(void) const
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, // param 1-7
true, // autoContinue
false, // isCurrentItem
pMissionItems); // parent - allow delete on pMissionItems to delete everthing
pMissionItems->append(item);
missionItemParent);
items.append(item);
float loiterRadius = _loiterRadiusFact.rawValue().toDouble() * (_loiterClockwise ? 1.0 : -1.0);
item = new MissionItem(seqNum++,
......@@ -231,8 +229,8 @@ QmlObjectListModel* FixedWingLandingComplexItem::getMissionItems(void) const
_loiterAltitudeFact.rawValue().toDouble(),
true, // autoContinue
false, // isCurrentItem
pMissionItems); // parent - allow delete on pMissionItems to delete everthing
pMissionItems->append(item);
missionItemParent);
items.append(item);
item = new MissionItem(seqNum++,
MAV_CMD_NAV_LAND,
......@@ -243,10 +241,8 @@ QmlObjectListModel* FixedWingLandingComplexItem::getMissionItems(void) const
_landingAltitudeFact.rawValue().toDouble(),
true, // autoContinue
false, // isCurrentItem
pMissionItems); // parent - allow delete on pMissionItems to delete everthing
pMissionItems->append(item);
return pMissionItems;
missionItemParent);
items.append(item);
}
double FixedWingLandingComplexItem::complexDistance(void) const
......
......@@ -53,7 +53,6 @@ public:
double complexDistance (void) const final;
int lastSequenceNumber (void) const final;
QmlObjectListModel* getMissionItems (void) const final;
bool load (const QJsonObject& complexObject, int sequenceNumber, QString& errorString) final;
double greatestDistanceTo (const QGeoCoordinate &other) const final;
void setCruiseSpeed (double cruiseSpeed) final;
......@@ -72,6 +71,7 @@ public:
QGeoCoordinate exitCoordinate (void) const final { return _landingCoordinate; }
int sequenceNumber (void) const final { return _sequenceNumber; }
double flightSpeed (void) final { return std::numeric_limits<double>::quiet_NaN(); }
void appendMissionItems (QList<MissionItem*>& items, QObject* missionItemParent) final;
bool coordinateHasRelativeAltitude (void) const final { return true; }
bool exitCoordinateHasRelativeAltitude (void) const final { return true; }
......@@ -80,7 +80,7 @@ public:
void setDirty (bool dirty) final;
void setCoordinate (const QGeoCoordinate& coordinate) final { setLoiterCoordinate(coordinate); }
void setSequenceNumber (int sequenceNumber) final;
void save (QJsonArray& missionItems) const final;
void save (QJsonArray& missionItems) final;
static const char* jsonComplexItemTypeValue;
......
......@@ -32,6 +32,7 @@
"specifiesCoordinate": true,
"friendlyEdit": true,
"category": "Basic",
"cameraSection": true,
"param1": {
"label": "Hold",
"units": "secs",
......
......@@ -35,8 +35,10 @@ const char* MissionCommandUIInfo::_paramRemoveJsonKey = "paramRemove";
const char* MissionCommandUIInfo::_rawNameJsonKey = "rawName";
const char* MissionCommandUIInfo::_standaloneCoordinateJsonKey = "standaloneCoordinate";
const char* MissionCommandUIInfo::_specifiesCoordinateJsonKey = "specifiesCoordinate";
const char* MissionCommandUIInfo::_specifiesAltitudeOnlyJsonKey = "specifiesAltitudeOnly";
const char* MissionCommandUIInfo::_unitsJsonKey = "units";
const char* MissionCommandUIInfo::_commentJsonKey = "comment";
const char* MissionCommandUIInfo::_cameraSectionJsonKey = "cameraSection";
const char* MissionCommandUIInfo::_advancedCategory = "Advanced";
MissionCmdParamInfo::MissionCmdParamInfo(QObject* parent)
......@@ -143,7 +145,7 @@ bool MissionCommandUIInfo::isStandaloneCoordinate(void) const
}
}
bool MissionCommandUIInfo::specifiesCoordinate (void) const
bool MissionCommandUIInfo::specifiesCoordinate(void) const
{
if (_infoMap.contains(_specifiesCoordinateJsonKey)) {
return _infoMap[_specifiesCoordinateJsonKey].toBool();
......@@ -152,6 +154,24 @@ bool MissionCommandUIInfo::specifiesCoordinate (void) const
}
}
bool MissionCommandUIInfo::specifiesAltitudeOnly(void) const
{
if (_infoMap.contains(_specifiesAltitudeOnlyJsonKey)) {
return _infoMap[_specifiesAltitudeOnlyJsonKey].toBool();
} else {
return false;
}
}
bool MissionCommandUIInfo::cameraSection(void) const
{
if (_infoMap.contains(_cameraSectionJsonKey)) {
return _infoMap[_cameraSectionJsonKey].toBool();
} else {
return false;
}
}
void MissionCommandUIInfo::_overrideInfo(MissionCommandUIInfo* uiInfo)
{
// Override info values
......@@ -187,7 +207,7 @@ bool MissionCommandUIInfo::loadJsonInfo(const QJsonObject& jsonObject, bool requ
QStringList allKeys;
allKeys << _idJsonKey << _rawNameJsonKey << _friendlyNameJsonKey << _descriptionJsonKey << _standaloneCoordinateJsonKey << _specifiesCoordinateJsonKey
<<_friendlyEditJsonKey << _param1JsonKey << _param2JsonKey << _param3JsonKey << _param4JsonKey << _param5JsonKey << _param6JsonKey << _param7JsonKey
<< _paramRemoveJsonKey << _categoryJsonKey;
<< _paramRemoveJsonKey << _categoryJsonKey << _cameraSectionJsonKey<< _specifiesAltitudeOnlyJsonKey;
// Look for unknown keys in top level object
foreach (const QString& key, jsonObject.keys()) {
......@@ -219,7 +239,7 @@ bool MissionCommandUIInfo::loadJsonInfo(const QJsonObject& jsonObject, bool requ
QList<QJsonValue::Type> types;
types << QJsonValue::Double << QJsonValue::String << QJsonValue::String<< QJsonValue::String << QJsonValue::Bool << QJsonValue::Bool << QJsonValue::Bool
<< QJsonValue::Object << QJsonValue::Object << QJsonValue::Object << QJsonValue::Object << QJsonValue::Object << QJsonValue::Object << QJsonValue::Object
<< QJsonValue::String << QJsonValue::String;
<< QJsonValue::String << QJsonValue::String << QJsonValue::Bool << QJsonValue::Bool;
if (!JsonHelper::validateKeyTypes(jsonObject, allKeys, types, internalError)) {
errorString = _loadErrorString(internalError);
return false;
......@@ -247,9 +267,15 @@ bool MissionCommandUIInfo::loadJsonInfo(const QJsonObject& jsonObject, bool requ
if (jsonObject.contains(_specifiesCoordinateJsonKey)) {
_infoMap[_specifiesCoordinateJsonKey] = jsonObject.value(_specifiesCoordinateJsonKey).toVariant();
}
if (jsonObject.contains(_specifiesAltitudeOnlyJsonKey)) {
_infoMap[_specifiesAltitudeOnlyJsonKey] = jsonObject.value(_specifiesAltitudeOnlyJsonKey).toBool();
}
if (jsonObject.contains(_friendlyEditJsonKey)) {
_infoMap[_friendlyEditJsonKey] = jsonObject.value(_friendlyEditJsonKey).toVariant();
}
if (jsonObject.contains(_cameraSectionJsonKey)) {
_infoMap[_cameraSectionJsonKey] = jsonObject.value(_cameraSectionJsonKey).toVariant();
}
if (jsonObject.contains(_paramRemoveJsonKey)) {
QStringList indexList = jsonObject.value(_paramRemoveJsonKey).toString().split(QStringLiteral(","));
foreach (const QString& indexString, indexList) {
......
......@@ -90,8 +90,10 @@ private:
/// friendlyName string rawName Short description of command
/// description string Long description of command
/// specifiesCoordinate bool false true: Command specifies a lat/lon/alt coordinate
/// specifiesAltitudeOnly bool false true: Command specifies an altitude only (no coordinate)
/// standaloneCoordinate bool false true: Vehicle does not fly through coordinate associated with command (exampl: ROI)
/// friendlyEdit bool false true: Command supports friendly editing dialog, false: Command supports 'Show all values" style editing only
/// cameraSection bool false true: Camera section of additional settings is added to editor
/// category string Advanced Category which this command belongs to
/// paramRemove string Used by an override to remove params, example: "1,3" will remove params 1 and 3 on the override
/// param[1-7] object MissionCommandParamInfo object
......@@ -112,7 +114,9 @@ public:
Q_PROPERTY(QString rawName READ rawName CONSTANT)
Q_PROPERTY(bool isStandaloneCoordinate READ isStandaloneCoordinate CONSTANT)
Q_PROPERTY(bool specifiesCoordinate READ specifiesCoordinate CONSTANT)
Q_PROPERTY(bool specifiesAltitudeOnly READ specifiesAltitudeOnly CONSTANT)
Q_PROPERTY(int command READ intCommand CONSTANT)
Q_PROPERTY(bool cameraSection READ cameraSection CONSTANT)
MAV_CMD command(void) const { return _command; }
int intCommand(void) const { return (int)_command; }
......@@ -124,6 +128,8 @@ public:
QString rawName (void) const;
bool isStandaloneCoordinate (void) const;
bool specifiesCoordinate (void) const;
bool specifiesAltitudeOnly (void) const;
bool cameraSection (void) const;
/// Load the data in the object from the specified json
/// @param jsonObject Json object to load from
......@@ -178,8 +184,10 @@ private:
static const char* _rawNameJsonKey;
static const char* _standaloneCoordinateJsonKey;
static const char* _specifiesCoordinateJsonKey;
static const char* _specifiesAltitudeOnlyJsonKey;
static const char* _unitsJsonKey;
static const char* _commentJsonKey;
static const char* _commentJsonKey;
static const char* _cameraSectionJsonKey;
static const char* _advancedCategory;
friend class MissionCommandTree;
......
......@@ -126,8 +126,7 @@ void MissionController::_newMissionItemsAvailableFromVehicle(void)
_missionItemsRequested = false;
if (_editMode) {
// Scan for mission settings
MissionSettingsComplexItem::scanForMissionSettings(_visualItems, _activeVehicle);
MissionController::_scanForAdditionalSettings(_visualItems, _activeVehicle);
}
_initAllVisualItems();
......@@ -159,16 +158,8 @@ void MissionController::sendItemsToVehicle(Vehicle* vehicle, QmlObjectListModel*
for (int i=0; i<visualMissionItems->count(); i++) {
VisualMissionItem* visualItem = qobject_cast<VisualMissionItem*>(visualMissionItems->get(i));
if (visualItem->isSimpleItem()) {
missionItems.append(new MissionItem(qobject_cast<SimpleMissionItem*>(visualItem)->missionItem()));
} else {
ComplexMissionItem* complexItem = qobject_cast<ComplexMissionItem*>(visualItem);
QmlObjectListModel* complexMissionItems = complexItem->getMissionItems();
for (int j=0; j<complexMissionItems->count(); j++) {
missionItems.append(new MissionItem(*qobject_cast<MissionItem*>(complexMissionItems->get(j))));
}
complexMissionItems->deleteLater();
}
visualItem->appendMissionItems(missionItems, NULL);
}
vehicle->missionManager()->writeMissionItems(missionItems);
......@@ -185,13 +176,8 @@ int MissionController::_nextSequenceNumber(void)
qWarning() << "Internal error: Empty visual item list";
return 0;
} else {
VisualMissionItem* lastItem = qobject_cast<VisualMissionItem*>(_visualItems->get(_visualItems->count() - 1));
if (lastItem->isSimpleItem()) {
return lastItem->sequenceNumber() + 1;
} else {
return qobject_cast<ComplexMissionItem*>(lastItem)->lastSequenceNumber() + 1;
}
VisualMissionItem* lastItem = _visualItems->value<VisualMissionItem*>(_visualItems->count() - 1);
return lastItem->lastSequenceNumber() + 1;
}
}
......@@ -374,12 +360,11 @@ bool MissionController::_loadJsonMissionFileV1(Vehicle* vehicle, const QJsonObje
SimpleMissionItem* item = new SimpleMissionItem(vehicle, visualItems);
if (item->load(itemObject, itemObject["id"].toInt(), errorString)) {
qCDebug(MissionControllerLog) << "Json load: adding simple item expectedSequence:actualSequence" << nextSequenceNumber << item->sequenceNumber();
nextSequenceNumber = item->lastSequenceNumber() + 1;
visualItems->append(item);
} else {
return false;
}
nextSequenceNumber++;
}
} while (nextSimpleItemIndex < itemArray.count() || nextComplexItemIndex < surveyItems.count());
......@@ -465,7 +450,8 @@ bool MissionController::_loadJsonMissionFileV2(Vehicle* vehicle, const QJsonObje
if (itemType == VisualMissionItem::jsonTypeSimpleItemValue) {
qCDebug(MissionControllerLog) << "Loading MISSION_ITEM: nextSequenceNumber" << nextSequenceNumber;
SimpleMissionItem* simpleItem = new SimpleMissionItem(vehicle, visualItems);
if (simpleItem->load(itemObject, nextSequenceNumber++, errorString)) {
if (simpleItem->load(itemObject, nextSequenceNumber, errorString)) {
nextSequenceNumber = simpleItem->lastSequenceNumber() + 1;
visualItems->append(simpleItem);
} else {
return false;
......@@ -612,7 +598,7 @@ void MissionController::loadFromFile(const QString& filename)
_addMissionSettings(_activeVehicle, _visualItems, true /* addToCenter */);
}
MissionSettingsComplexItem::scanForMissionSettings(_visualItems, _activeVehicle);
MissionController::_scanForAdditionalSettings(_visualItems, _activeVehicle);
_initAllVisualItems();
}
......@@ -1062,16 +1048,8 @@ void MissionController::_recalcSequence(void)
for (int i=0; i<_visualItems->count(); i++) {
VisualMissionItem* item = qobject_cast<VisualMissionItem*>(_visualItems->get(i));
item->setSequenceNumber(sequenceNumber++);
if (!item->isSimpleItem()) {
ComplexMissionItem* complexItem = qobject_cast<ComplexMissionItem*>(item);
if (complexItem) {
sequenceNumber = complexItem->lastSequenceNumber() + 1;
} else {
qWarning() << "isSimpleItem == false, yet not ComplexMissionItem";
}
}
item->setSequenceNumber(sequenceNumber);
sequenceNumber = item->lastSequenceNumber() + 1;
}
}
......@@ -1158,6 +1136,7 @@ void MissionController::_initVisualItem(VisualMissionItem* visualItem)
connect(visualItem, &VisualMissionItem::coordinateHasRelativeAltitudeChanged, this, &MissionController::_recalcWaypointLines);
connect(visualItem, &VisualMissionItem::exitCoordinateHasRelativeAltitudeChanged, this, &MissionController::_recalcWaypointLines);
connect(visualItem, &VisualMissionItem::flightSpeedChanged, this, &MissionController::_recalcAltitudeRangeBearing);
connect(visualItem, &VisualMissionItem::lastSequenceNumberChanged, this, &MissionController::_recalcSequence);
if (visualItem->isSimpleItem()) {
// We need to track commandChanged on simple item since recalc has special handling for takeoff command
......@@ -1168,10 +1147,12 @@ void MissionController::_initVisualItem(VisualMissionItem* visualItem)
qWarning() << "isSimpleItem == true, yet not SimpleMissionItem";
}
} else {
// We need to track changes of lastSequenceNumber so we can recalc sequence numbers for subsequence items
ComplexMissionItem* complexItem = qobject_cast<ComplexMissionItem*>(visualItem);
connect(complexItem, &ComplexMissionItem::lastSequenceNumberChanged, this, &MissionController::_recalcSequence);
connect(complexItem, &ComplexMissionItem::complexDistanceChanged, this, &MissionController::_recalcAltitudeRangeBearing);
if (complexItem) {
connect(complexItem, &ComplexMissionItem::complexDistanceChanged, this, &MissionController::_recalcAltitudeRangeBearing);
} else {
qWarning() << "ComplexMissionItem not found";
}
}
}
......@@ -1472,7 +1453,7 @@ QString MissionController::fileExtension(void) const
return QGCApplication::missionFileExtension;
}
double MissionController::cruiseSpeed(void) const
double MissionController::cruiseSpeed(void) const
{
if (_activeVehicle) {
return _activeVehicle->cruiseSpeed();
......@@ -1481,7 +1462,7 @@ double MissionController::cruiseSpeed(void) const
}
}
double MissionController::hoverSpeed(void) const
double MissionController::hoverSpeed(void) const
{
if (_activeVehicle) {
return _activeVehicle->hoverSpeed();
......@@ -1489,3 +1470,27 @@ double MissionController::hoverSpeed(void) const
return 0.0f;
}
}
void MissionController::_scanForAdditionalSettings(QmlObjectListModel* visualItems, Vehicle* vehicle)
{
int scanIndex = 0;
while (scanIndex < visualItems->count()) {
VisualMissionItem* visualItem = visualItems->value<VisualMissionItem*>(scanIndex);
qCDebug(MissionControllerLog) << "MissionController::_scanForAdditionalSettings count:scanIndex" << visualItems->count() << scanIndex;
MissionSettingsComplexItem* settingsItem = qobject_cast<MissionSettingsComplexItem*>(visualItem);
if (settingsItem && settingsItem->scanForMissionSettings(visualItems, scanIndex, vehicle)) {
continue;
}
SimpleMissionItem* simpleItem = qobject_cast<SimpleMissionItem*>(visualItem);
if (simpleItem && simpleItem->cameraSection()->available()) {
scanIndex++;
simpleItem->scanForSections(visualItems, scanIndex, vehicle);
continue;
}
scanIndex++;
}
}
......@@ -160,6 +160,7 @@ private:
void _setMissionCruiseDistance(double missionCruiseDistance);
void _setMissionCruiseTime(double missionCruiseTime);
void _setMissionMaxTelemetry(double missionMaxTelemetry);
static void _scanForAdditionalSettings(QmlObjectListModel* visualItems, Vehicle* vehicle);
// Overrides from PlanElementController
void _activeVehicleBeingRemoved(void) final;
......
......@@ -29,52 +29,6 @@
"min": 0,
"decimalPlaces": 1
},
{
"name": "CameraAction",
"shortDescription": "Specify whether the camera should take photos or video",
"type": "uint32",
"enumStrings": "No camera action,Take photos (time),Take photos (distance),Take video",
"enumValues": "0,1,2,3",
"defaultValue": 0
},
{
"name": "CameraPhotoIntervalDistance",
"shortDescription": "Specify the distance between each photo",
"type": "double",
"units": "m",
"min": 0,
"decimalPlaces": 1,
"defaultValue": 1
},
{
"name": "CameraPhotoIntervalTime",
"shortDescription": "Specify the time between each photo",
"type": "uint32",
"units": "secs",
"min": 1,
"decimalPlaces": 0,
"defaultValue": 10
},
{
"name": "GimbalPitch",
"shortDescription": "Gimbal pitch rotation.",
"type": "double",
"units": "deg",
"min": 0.0,
"max": 360.0,
"decimalPlaces": 0,
"defaultValue": 0
},
{
"name": "GimbalYaw",
"shortDescription": "Gimbal yaw rotation.",
"type": "double",
"units": "deg",
"min": 0.0,
"max": 360.0,
"decimalPlaces": 0,
"defaultValue": 0
},
{
"name": "MissionEndAction",
"shortDescription": "The action to take when the mission completed.",
......
......@@ -14,6 +14,7 @@
#include "MissionItem.h"
#include "Fact.h"
#include "QGCLoggingCategory.h"
#include "CameraSection.h"
Q_DECLARE_LOGGING_CATEGORY(MissionSettingsComplexItemLog)
......@@ -32,51 +33,31 @@ public:
};
Q_ENUMS(MissionEndAction)
enum CameraAction {
CameraActionNone,
TakePhotosIntervalTime,
TakePhotoIntervalDistance,
TakeVideo
};
Q_ENUMS(CameraAction)
Q_PROPERTY(bool specifyMissionFlightSpeed READ specifyMissionFlightSpeed WRITE setSpecifyMissionFlightSpeed NOTIFY specifyMissionFlightSpeedChanged)
Q_PROPERTY(Fact* missionFlightSpeed READ missionFlightSpeed CONSTANT)
Q_PROPERTY(bool specifyGimbal READ specifyGimbal WRITE setSpecifyGimbal NOTIFY specifyGimbalChanged)
Q_PROPERTY(Fact* gimbalPitch READ gimbalPitch CONSTANT)
Q_PROPERTY(Fact* gimbalYaw READ gimbalYaw CONSTANT)
Q_PROPERTY(Fact* cameraAction READ cameraAction CONSTANT)
Q_PROPERTY(Fact* cameraPhotoIntervalTime READ cameraPhotoIntervalTime CONSTANT)
Q_PROPERTY(Fact* cameraPhotoIntervalDistance READ cameraPhotoIntervalDistance CONSTANT)
Q_PROPERTY(Fact* missionEndAction READ missionEndAction CONSTANT)
Q_PROPERTY(Fact* plannedHomePositionLatitude READ plannedHomePositionLatitude CONSTANT)
Q_PROPERTY(Fact* plannedHomePositionLongitude READ plannedHomePositionLongitude CONSTANT)
Q_PROPERTY(Fact* plannedHomePositionAltitude READ plannedHomePositionAltitude CONSTANT)
Q_PROPERTY(QObject* cameraSection READ cameraSection CONSTANT)
bool specifyMissionFlightSpeed (void) const { return _specifyMissionFlightSpeed; }
bool specifyGimbal (void) const { return _specifyGimbal; }
Fact* plannedHomePositionLatitude (void) { return &_plannedHomePositionLatitudeFact; }
Fact* plannedHomePositionLongitude(void) { return &_plannedHomePositionLongitudeFact; }
Fact* plannedHomePositionAltitude (void) { return &_plannedHomePositionAltitudeFact; }
Fact* missionFlightSpeed (void) { return &_missionFlightSpeedFact; }
Fact* gimbalYaw (void) { return &_gimbalYawFact; }
Fact* gimbalPitch (void) { return &_gimbalPitchFact; }
Fact* cameraAction (void) { return &_cameraActionFact; }
Fact* cameraPhotoIntervalTime (void) { return &_cameraPhotoIntervalTimeFact; }
Fact* cameraPhotoIntervalDistance (void) { return &_cameraPhotoIntervalDistanceFact; }
Fact* missionEndAction (void) { return &_missionEndActionFact; }
void setSpecifyMissionFlightSpeed (bool specifyMissionFlightSpeed);
void setSpecifyGimbal (bool specifyGimbal);
void setSpecifyMissionFlightSpeed(bool specifyMissionFlightSpeed);
QObject* cameraSection(void) { return &_cameraSection; }
/// Scans the loaded items for the settings items
static void scanForMissionSettings(QmlObjectListModel* visualItems, Vehicle* vehicle);
/// Scans the loaded items for settings items
static bool scanForMissionSettings(QmlObjectListModel* visualItems, int scanIndex, Vehicle* vehicl);
// Overrides from ComplexMissionItem
double complexDistance (void) const final;
int lastSequenceNumber (void) const final;
QmlObjectListModel* getMissionItems (void) const final;
bool load (const QJsonObject& complexObject, int sequenceNumber, QString& errorString) final;
double greatestDistanceTo (const QGeoCoordinate &other) const final;
void setCruiseSpeed (double cruiseSpeed) final;
......@@ -95,6 +76,7 @@ public:
QGeoCoordinate exitCoordinate (void) const final { return coordinate(); }
int sequenceNumber (void) const final { return _sequenceNumber; }
double flightSpeed (void) final { return std::numeric_limits<double>::quiet_NaN(); }
void appendMissionItems (QList<MissionItem*>& items, QObject* missionItemParent) final;
bool coordinateHasRelativeAltitude (void) const final { return true; }
bool exitCoordinateHasRelativeAltitude (void) const final { return true; }
......@@ -103,32 +85,27 @@ public:
void setDirty (bool dirty) final;
void setCoordinate (const QGeoCoordinate& coordinate) final;
void setSequenceNumber (int sequenceNumber) final;
void save (QJsonArray& missionItems) const final;
void save (QJsonArray& missionItems) final;
static const char* jsonComplexItemTypeValue;
signals:
bool specifyMissionFlightSpeedChanged (bool specifyMissionFlightSpeed);
bool specifyGimbalChanged (bool specifyGimbal);
bool specifyMissionFlightSpeedChanged(bool specifyMissionFlightSpeed);
private slots:
void _setDirtyAndUpdateLastSequenceNumber(void);
void _setDirtyAndUpdateCoordinate(void);
void _setDirty(void);
void _cameraSectionDirtyChanged(bool dirty);
private:
bool _specifyMissionFlightSpeed;
bool _specifyGimbal;
Fact _plannedHomePositionLatitudeFact;
Fact _plannedHomePositionLongitudeFact;
Fact _plannedHomePositionAltitudeFact;
Fact _missionFlightSpeedFact;
Fact _gimbalYawFact;
Fact _gimbalPitchFact;
Fact _cameraActionFact;
Fact _cameraPhotoIntervalDistanceFact;
Fact _cameraPhotoIntervalTimeFact;
Fact _missionEndActionFact;
bool _specifyMissionFlightSpeed;
Fact _plannedHomePositionLatitudeFact;
Fact _plannedHomePositionLongitudeFact;
Fact _plannedHomePositionAltitudeFact;
Fact _missionFlightSpeedFact;
Fact _missionEndActionFact;
CameraSection _cameraSection;
int _sequenceNumber;
bool _dirty;
......@@ -139,11 +116,6 @@ private:
static const char* _plannedHomePositionLongitudeName;
static const char* _plannedHomePositionAltitudeName;
static const char* _missionFlightSpeedName;
static const char* _gimbalPitchName;
static const char* _gimbalYawName;
static const char* _cameraActionName;
static const char* _cameraPhotoIntervalDistanceName;
static const char* _cameraPhotoIntervalTimeName;
static const char* _missionEndActionName;
};
......
......@@ -50,6 +50,8 @@ static const struct EnumInfo_s _rgMavFrameInfo[] = {
SimpleMissionItem::SimpleMissionItem(Vehicle* vehicle, QObject* parent)
: VisualMissionItem(vehicle, parent)
, _rawEdit(false)
, _dirty(false)
, _cameraSection(NULL)
, _commandTree(qgcApp()->toolbox()->missionCommandTree())
, _altitudeRelativeToHomeFact (0, "Altitude is relative to home", FactMetaData::valueTypeUint32)
, _supportedCommandFact (0, "Command:", FactMetaData::valueTypeUint32)
......@@ -69,10 +71,15 @@ SimpleMissionItem::SimpleMissionItem(Vehicle* vehicle, QObject* parent)
_setupMetaData();
_connectSignals();
_updateCameraSection();
setDefaultsForCommand();
connect(&_missionItem, &MissionItem::flightSpeedChanged, this, &SimpleMissionItem::flightSpeedChanged);
connect(this, &SimpleMissionItem::sequenceNumberChanged, this, &SimpleMissionItem::lastSequenceNumberChanged);
connect(this, &SimpleMissionItem::cameraSectionChanged, this, &SimpleMissionItem::_setDirtyFromSignal);
connect(this, &SimpleMissionItem::cameraSectionChanged, this, &SimpleMissionItem::_updateLastSequenceNumber);
}
SimpleMissionItem::SimpleMissionItem(Vehicle* vehicle, const MissionItem& missionItem, QObject* parent)
......@@ -80,6 +87,7 @@ SimpleMissionItem::SimpleMissionItem(Vehicle* vehicle, const MissionItem& missio
, _missionItem(missionItem)
, _rawEdit(false)
, _dirty(false)
, _cameraSection(NULL)
, _commandTree(qgcApp()->toolbox()->missionCommandTree())
, _altitudeRelativeToHomeFact (0, "Altitude is relative to home", FactMetaData::valueTypeUint32)
, _supportedCommandFact (0, "Command:", FactMetaData::valueTypeUint32)
......@@ -99,6 +107,7 @@ SimpleMissionItem::SimpleMissionItem(Vehicle* vehicle, const MissionItem& missio
_setupMetaData();
_connectSignals();
_updateCameraSection();
_syncFrameToAltitudeRelativeToHome();
}
......@@ -108,6 +117,7 @@ SimpleMissionItem::SimpleMissionItem(const SimpleMissionItem& other, QObject* pa
, _missionItem(other._vehicle)
, _rawEdit(false)
, _dirty(false)
, _cameraSection(NULL)
, _commandTree(qgcApp()->toolbox()->missionCommandTree())
, _altitudeRelativeToHomeFact (0, "Altitude is relative to home", FactMetaData::valueTypeUint32)
, _supportedCommandFact (0, "Command:", FactMetaData::valueTypeUint32)
......@@ -122,6 +132,7 @@ SimpleMissionItem::SimpleMissionItem(const SimpleMissionItem& other, QObject* pa
_setupMetaData();
_connectSignals();
_updateCameraSection();
*this = other;
}
......@@ -240,11 +251,19 @@ SimpleMissionItem::~SimpleMissionItem()
{
}
void SimpleMissionItem::save(QJsonArray& missionItems) const
void SimpleMissionItem::save(QJsonArray& missionItems)
{
QJsonObject itemObject;
_missionItem.save(itemObject);
missionItems.append(itemObject);
QList<MissionItem*> items;
appendMissionItems(items, this);
for (int i=0; i<items.count(); i++) {
MissionItem* item = items[i];
QJsonObject saveObject;
item->save(saveObject);
missionItems.append(saveObject);
item->deleteLater();
}
}
bool SimpleMissionItem::load(QTextStream &loadStream)
......@@ -489,13 +508,10 @@ void SimpleMissionItem::setRawEdit(bool rawEdit)
void SimpleMissionItem::setDirty(bool dirty)
{
if (!_homePositionSpecialCase || !dirty) {
// Home position never affects dirty bit
if (!_homePositionSpecialCase || (_dirty != dirty)) {
_dirty = dirty;
// We want to emit dirtyChanged even if _dirty didn't change. This can be handy signal for
// any value within the item changing.
emit dirtyChanged(_dirty);
_cameraSection->setDirty(false);
emit dirtyChanged(dirty);
}
}
......@@ -584,6 +600,7 @@ void SimpleMissionItem::setCommand(MavlinkQmlSingleton::Qml_MAV_CMD command)
{
if ((MAV_CMD)command != _missionItem.command()) {
_missionItem.setCommand((MAV_CMD)command);
_updateCameraSection();
}
}
......@@ -608,3 +625,64 @@ double SimpleMissionItem::flightSpeed(void)
{
return missionItem().flightSpeed();
}
void SimpleMissionItem::scanForSections(QmlObjectListModel* visualItems, int scanIndex, Vehicle* vehicle)
{
Q_UNUSED(vehicle);
qDebug() << "SimpleMissionItem::scanForSections" << scanIndex << _cameraSection->available();
if (_cameraSection->available()) {
bool sectionFound = _cameraSection->scanForCameraSection(visualItems, scanIndex);
qDebug() << sectionFound;
}
}
void SimpleMissionItem::_updateCameraSection(void)
{
if (_cameraSection) {
// Remove previous section
_cameraSection->deleteLater();
_cameraSection = NULL;
}
// Add new section
_cameraSection = new CameraSection(this);
const MissionCommandUIInfo* uiInfo = _commandTree->getUIInfo(_vehicle, (MAV_CMD)command());
if (uiInfo && uiInfo->cameraSection()) {
_cameraSection->setAvailable(true);
}
connect(_cameraSection, &CameraSection::dirtyChanged, this, &SimpleMissionItem::_cameraSectionDirtyChanged);
connect(_cameraSection, &CameraSection::availableChanged, this, &SimpleMissionItem::_updateLastSequenceNumber);
connect(_cameraSection, &CameraSection::missionItemCountChanged, this, &SimpleMissionItem::_updateLastSequenceNumber);
emit cameraSectionChanged(_cameraSection);
}
int SimpleMissionItem::lastSequenceNumber(void) const
{
return sequenceNumber() + (_cameraSection ? _cameraSection->missionItemCount() : 0);
}
void SimpleMissionItem::_updateLastSequenceNumber(void)
{
emit lastSequenceNumberChanged(lastSequenceNumber());
}
void SimpleMissionItem::_cameraSectionDirtyChanged(bool dirty)
{
if (dirty) {
setDirty(true);
}
}
void SimpleMissionItem::appendMissionItems(QList<MissionItem*>& items, QObject* missionItemParent)
{
int seqNum = sequenceNumber();
items.append(new MissionItem(missionItem(), missionItemParent));
seqNum++;
_cameraSection->appendMissionItems(items, missionItemParent, seqNum);
}
......@@ -14,6 +14,7 @@
#include "VisualMissionItem.h"
#include "MissionItem.h"
#include "MissionCommandTree.h"
#include "CameraSection.h"
/// A SimpleMissionItem is used to represent a single MissionItem to the ui.
class SimpleMissionItem : public VisualMissionItem
......@@ -35,18 +36,27 @@ public:
Q_PROPERTY(bool rawEdit READ rawEdit WRITE setRawEdit NOTIFY rawEditChanged) ///< true: raw item editing with all params
Q_PROPERTY(bool relativeAltitude READ relativeAltitude NOTIFY frameChanged)
/// Optional sections
Q_PROPERTY(QObject* cameraSection READ cameraSection NOTIFY cameraSectionChanged)
// These properties are used to display the editing ui
Q_PROPERTY(QmlObjectListModel* checkboxFacts READ checkboxFacts NOTIFY uiModelChanged)
Q_PROPERTY(QmlObjectListModel* comboboxFacts READ comboboxFacts NOTIFY uiModelChanged)
Q_PROPERTY(QmlObjectListModel* textFieldFacts READ textFieldFacts NOTIFY uiModelChanged)
/// Scans the loaded items for additional section settings
/// @param visualItems List of all visual items
/// @param scanIndex Index to start scanning from
/// @param vehicle Vehicle associated with this mission
void scanForSections(QmlObjectListModel* visualItems, int scanIndex, Vehicle* vehicle);
// Property accesors
QString category (void) const;
MavlinkQmlSingleton::Qml_MAV_CMD command(void) const { return (MavlinkQmlSingleton::Qml_MAV_CMD)_missionItem._commandFact.cookedValue().toInt(); }
bool friendlyEditAllowed (void) const;
bool rawEdit (void) const;
CameraSection* cameraSection (void) { return _cameraSection; }
QmlObjectListModel* textFieldFacts (void);
QmlObjectListModel* checkboxFacts (void);
......@@ -69,6 +79,7 @@ public:
bool relativeAltitude(void) { return _missionItem.frame() == MAV_FRAME_GLOBAL_RELATIVE_ALT; }
MissionItem& missionItem(void) { return _missionItem; }
const MissionItem& missionItem(void) const { return _missionItem; }
// Overrides from VisualMissionItem
......@@ -84,6 +95,7 @@ public:
int sequenceNumber (void) const final { return _missionItem.sequenceNumber(); }
double flightSpeed (void) final;
QString mapVisualQML (void) const final { return QStringLiteral("SimpleItemMapVisual.qml"); }
void appendMissionItems (QList<MissionItem*>& items, QObject* missionItemParent) final;
bool coordinateHasRelativeAltitude (void) const final { return _missionItem.relativeAltitude(); }
bool exitCoordinateHasRelativeAltitude (void) const final { return coordinateHasRelativeAltitude(); }
......@@ -92,7 +104,8 @@ public:
void setDirty (bool dirty) final;
void setCoordinate (const QGeoCoordinate& coordinate) final;
void setSequenceNumber (int sequenceNumber) final;
void save (QJsonArray& missionItems) const final;
int lastSequenceNumber (void) const final;
void save (QJsonArray& missionItems) final;
public slots:
void setDefaultsForCommand(void);
......@@ -104,9 +117,11 @@ signals:
void headingDegreesChanged (double heading);
void rawEditChanged (bool rawEdit);
void uiModelChanged (void);
void cameraSectionChanged (QObject* cameraSection);
private slots:
void _setDirtyFromSignal(void);
void _cameraSectionDirtyChanged(bool dirty);
void _sendCommandChanged(void);
void _sendCoordinateChanged(void);
void _sendFrameChanged(void);
......@@ -114,17 +129,21 @@ private slots:
void _sendUiModelChanged(void);
void _syncAltitudeRelativeToHomeToFrame(const QVariant& value);
void _syncFrameToAltitudeRelativeToHome(void);
void _updateLastSequenceNumber(void);
private:
void _clearParamMetaData(void);
void _connectSignals(void);
void _setupMetaData(void);
void _updateCameraSection(void);
private:
MissionItem _missionItem;
bool _rawEdit;
bool _dirty;
CameraSection* _cameraSection;
MissionCommandTree* _commandTree;
Fact _altitudeRelativeToHomeFact;
......
......@@ -294,7 +294,7 @@ void SurveyMissionItem::setDirty(bool dirty)
}
}
void SurveyMissionItem::save(QJsonArray& missionItems) const
void SurveyMissionItem::save(QJsonArray& missionItems)
{
QJsonObject saveObject;
......@@ -822,11 +822,10 @@ void SurveyMissionItem::_gridGenerator(const QList<QPointF>& polygonPoints, QLi
}
}
QmlObjectListModel* SurveyMissionItem::getMissionItems(void) const
void SurveyMissionItem::appendMissionItems(QList<MissionItem*>& items, QObject* missionItemParent)
{
QmlObjectListModel* pMissionItems = new QmlObjectListModel;
int seqNum = _sequenceNumber;
for (int i=0; i<_gridPoints.count(); i++) {
QGeoCoordinate coord = _gridPoints[i].value<QGeoCoordinate>();
double altitude = _gridAltitudeFact.rawValue().toDouble();
......@@ -840,8 +839,8 @@ QmlObjectListModel* SurveyMissionItem::getMissionItems(void) const
altitude,
true, // autoContinue
false, // isCurrentItem
pMissionItems); // parent - allow delete on pMissionItems to delete everthing
pMissionItems->append(item);
missionItemParent);
items.append(item);
if (_cameraTriggerFact.rawValue().toBool() && i == 0) {
// Turn on camera
......@@ -852,8 +851,8 @@ QmlObjectListModel* SurveyMissionItem::getMissionItems(void) const
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, // param 2-7
true, // autoContinue
false, // isCurrentItem
pMissionItems); // parent - allow delete on pMissionItems to delete everthing
pMissionItems->append(item);
missionItemParent);
items.append(item);
}
}
......@@ -866,11 +865,9 @@ QmlObjectListModel* SurveyMissionItem::getMissionItems(void) const
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, // param 2-7
true, // autoContinue
false, // isCurrentItem
pMissionItems); // parent - allow delete on pMissionItems to delete everthing
pMissionItems->append(item);
missionItemParent);
items.append(item);
}
return pMissionItems;
}
void SurveyMissionItem::_cameraTriggerChanged(void)
......
......@@ -98,7 +98,6 @@ public:
double complexDistance (void) const final { return _surveyDistance; }
int lastSequenceNumber (void) const final;
QmlObjectListModel* getMissionItems (void) const final;
bool load (const QJsonObject& complexObject, int sequenceNumber, QString& errorString) final;
double greatestDistanceTo (const QGeoCoordinate &other) const final;
void setCruiseSpeed (double cruiseSpeed) final;
......@@ -118,6 +117,7 @@ public:
QGeoCoordinate exitCoordinate (void) const final { return _exitCoordinate; }
int sequenceNumber (void) const final { return _sequenceNumber; }
double flightSpeed (void) final { return std::numeric_limits<double>::quiet_NaN(); }
void appendMissionItems (QList<MissionItem*>& items, QObject* missionItemParent) final;
bool coordinateHasRelativeAltitude (void) const final { return _gridAltitudeRelativeFact.rawValue().toBool(); }
bool exitCoordinateHasRelativeAltitude (void) const final { return _gridAltitudeRelativeFact.rawValue().toBool(); }
......@@ -127,7 +127,7 @@ public:
void setCoordinate (const QGeoCoordinate& coordinate) final;
void setSequenceNumber (int sequenceNumber) final;
void setTurnaroundDist (double dist) { _turnaroundDistFact.setRawValue(dist); }
void save (QJsonArray& missionItems) const final;
void save (QJsonArray& missionItems) final;
static const char* jsonComplexItemTypeValue;
......
......@@ -27,6 +27,8 @@
#include "QmlObjectListModel.h"
#include "Vehicle.h"
class MissionItem;
// Abstract base class for all Simple and Complex visual mission objects.
class VisualMissionItem : public QObject
{
......@@ -132,14 +134,20 @@ public:
virtual void setDirty (bool dirty) = 0;
virtual void setCoordinate (const QGeoCoordinate& coordinate) = 0;
virtual void setSequenceNumber (int sequenceNumber) = 0;
virtual int lastSequenceNumber (void) const = 0;
/// Save the item(s) in Json format
/// @param missionItems Current set of mission items, new items should be appended to the end
virtual void save(QJsonArray& missionItems) const = 0;
virtual void save(QJsonArray& missionItems) = 0;
/// @return The QML resource file which contains the control which visualizes the item on the map.
virtual QString mapVisualQML(void) const = 0;
/// Returns the mission items associated with the complex item. Caller is responsible for freeing.
/// @param items List to append to
/// @param missionItemParent Parent object for newly created MissionItems
virtual void appendMissionItems(QList<MissionItem*>& items, QObject* missionItemParent) = 0;
static const char* jsonTypeKey; ///< Json file attribute which specifies the item type
static const char* jsonTypeSimpleItemValue; ///< Item type is MISSION_ITEM
static const char* jsonTypeComplexItemValue; ///< Item type is Complex Item
......@@ -162,6 +170,7 @@ signals:
void specifiesCoordinateChanged (void);
void isStandaloneCoordinateChanged (void);
void flightSpeedChanged (double flightSpeed);
void lastSequenceNumberChanged (int sequenceNumber);
void coordinateHasRelativeAltitudeChanged (bool coordinateHasRelativeAltitude);
void exitCoordinateHasRelativeAltitudeChanged (bool exitCoordinateHasRelativeAltitude);
......
......@@ -27,13 +27,15 @@ ComboBox {
border.color: control._qgcPal.buttonText
}
Image {
id: imageItem
source: "/qmlimages/arrow-down.png"
QGCColoredImage {
id: image
width: ScreenTools.defaultFontPixelHeight / 2
height: width
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: dropDownButtonWidth / 2
opacity: control.enabled ? 0.6 : 0.3
anchors.right: parent.right
anchors.rightMargin: dropDownButtonWidth / 2
source: "/qmlimages/arrow-down.png"
color: qgcPal.text
}
}
}
......
......@@ -2,6 +2,7 @@ Module QGroundControl.Controls
AnalyzePage 1.0 AnalyzePage.qml
AppMessages 1.0 AppMessages.qml
CameraSection 1.0 CameraSection.qml
ClickableColor 1.0 ClickableColor.qml
DropButton 1.0 DropButton.qml
DropPanel 1.0 DropPanel.qml
......
src/QmlControls/arrow-down.png

184 Bytes | W: | H:

src/QmlControls/arrow-down.png

169 Bytes | W: | H:

src/QmlControls/arrow-down.png
src/QmlControls/arrow-down.png
src/QmlControls/arrow-down.png
src/QmlControls/arrow-down.png
  • 2-up
  • Swipe
  • Onion skin
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment