diff --git a/.travis.yml b/.travis.yml index 46ca93a54fe0b6a3acd50f99860338bd14f865e0..0ba09acd99d63cbaff991caa5fcb566784e9f06e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -115,15 +115,15 @@ install: # osx dependencies: qt, gstreamer, gstreamer-devel - if [ "${SPEC}" = "macx-clang" ]; then - wget https://s3-us-west-2.amazonaws.com/qgroundcontrol/dependencies/Qt5.8.0-mac-clang-min.tar.bz2 && - tar jxf Qt5.8.0-mac-clang-min.tar.bz2 -C /tmp && + wget https://s3-us-west-2.amazonaws.com/qgroundcontrol/dependencies/Qt5.7.1-mac-clang-min.tar.bz2 && + tar jxf Qt5.7.1-mac-clang-min.tar.bz2 -C /tmp && wget https://s3-us-west-2.amazonaws.com/qgroundcontrol/dependencies/gstreamer-1.0-1.5.2-x86_64.pkg && sudo installer -verboseR -pkg gstreamer-1.0-1.5.2-x86_64.pkg -target / && wget https://s3-us-west-2.amazonaws.com/qgroundcontrol/dependencies/gstreamer-1.0-devel-1.5.2-x86_64.pkg && sudo installer -verboseR -pkg gstreamer-1.0-devel-1.5.2-x86_64.pkg -target / && wget https://s3-us-west-2.amazonaws.com/qgroundcontrol/dependencies/osx-gstreamer.tar.bz2 && sudo tar jxf osx-gstreamer.tar.bz2 -C /Library/Frameworks && - export QT_DIR=Qt5.8-mac-clang/5.8/clang_64 && + export QT_DIR=Qt5.7-mac-clang/5.7/clang_64 && export QT_QPA_PLATFORM_PLUGIN_PATH=/tmp/$QT_DIR/plugins && export QML2_IMPORT_PATH=/tmp/$QT_DIR/qml && export PATH=/tmp/$QT_DIR/bin:$PATH diff --git a/src/MissionManager/MissionController.cc b/src/MissionManager/MissionController.cc index cd14bbc8e019689d7df5e2e70b462e6e67801491..2ddaaaba7af19b529d4c8d9e837485a5271dccb8 100644 --- a/src/MissionManager/MissionController.cc +++ b/src/MissionManager/MissionController.cc @@ -647,30 +647,6 @@ void MissionController::loadFromFile(const QString& filename) MissionController::_scanForAdditionalSettings(_visualItems, _activeVehicle); _initAllVisualItems(); - - // Split the filename into directory and filename - - QString filenameOnly = filename; - int lastSepIndex = filename.lastIndexOf(QStringLiteral("/")); - if (lastSepIndex != -1) { - filenameOnly = filename.right(filename.length() - lastSepIndex - 1); - } - QString directoryOnly = filename.left(filename.length() - filenameOnly.length() - 1); - - QString extension = AppSettings::missionFileExtension; - if (filenameOnly.endsWith("." + extension)) { - filenameOnly = filenameOnly.left(filenameOnly.length() - extension.length() - 1); - } - - _settingsItem->missionName()->setRawValue(filenameOnly); - if (directoryOnly == qgcApp()->toolbox()->settingsManager()->appSettings()->missionSavePath()) { - QString emptyString; - _settingsItem->setLoadedMissionDirectory(emptyString); - } else { - _settingsItem->setLoadedMissionDirectory(directoryOnly); - } - _settingsItem->setExistingMission(true); - sendToVehicle(); } @@ -1235,7 +1211,7 @@ void MissionController::_initAllVisualItems(void) _recalcAll(); - connect(_visualItems, &QmlObjectListModel::dirtyChanged, this, &MissionController::dirtyChanged); + connect(_visualItems, &QmlObjectListModel::dirtyChanged, this, &MissionController::_visualItemsDirtyChanged); connect(_visualItems, &QmlObjectListModel::countChanged, this, &MissionController::_updateContainsItems); emit visualItemsChanged(); @@ -1250,7 +1226,7 @@ void MissionController::_deinitAllVisualItems(void) _deinitVisualItem(qobject_cast(_visualItems->get(i))); } - disconnect(_visualItems, &QmlObjectListModel::dirtyChanged, this, &MissionController::dirtyChanged); + disconnect(_visualItems, &QmlObjectListModel::dirtyChanged, this, &MissionController::_visualItemsDirtyChanged); disconnect(_visualItems, &QmlObjectListModel::countChanged, this, &MissionController::_updateContainsItems); } @@ -1605,46 +1581,16 @@ bool MissionController::missionInProgress(void) const return _visualItems && _visualItems->count() > 1 && (!_visualItems->value(0)->isCurrentItem() && !_visualItems->value(1)->isCurrentItem()); } -void MissionController::save(void) -{ - // Save to file if the mission is named - - QString missionDir = _settingsItem->loadedMissionDirectory(); - if (missionDir.isEmpty()) { - missionDir = _appSettings->missionSavePath(); - } - - bool savedToFile = false; - QString missionName = _settingsItem->missionName()->rawValue().toString(); - if (!missionDir.isEmpty() && !missionName.isEmpty()) { - savedToFile = true; - saveToFile(missionDir + "/" + missionName); - } - - _settingsItem->setExistingMission(savedToFile); -} - -void MissionController::saveAndSend(void) +void MissionController::_visualItemsDirtyChanged(bool dirty) { - // Send to vehicle if we are connected - if (!_activeVehicle->isOfflineEditingVehicle()) { - sendToVehicle(); + if (dirty) { + if (_visualItems->count() > 1) { + emit dirtyChanged(true); + } else { + // This was a change to mission settings with no other mission items added + _visualItems->setDirty(false); + } + } else { + emit dirtyChanged(false); } } - -void MissionController::clearMission(void) -{ - // We need to save the mission information around removeAll all since it delete/recreates settings item - QString missionName = _settingsItem->missionName()->rawValue().toString(); - QString loadedMissionDirectory = _settingsItem->loadedMissionDirectory(); - bool existingMission = _settingsItem->existingMission(); - removeAll(); - _settingsItem->missionName()->setRawValue(missionName); - _settingsItem->setLoadedMissionDirectory(loadedMissionDirectory); - _settingsItem->setExistingMission(existingMission); -} - -void MissionController::closeMission(void) -{ - removeAll(); -} diff --git a/src/MissionManager/MissionController.h b/src/MissionManager/MissionController.h index b53c0f0dd66d6c6acc2bbad4fbaef8aa8942ad0b..5de84f9dc345baf35a968681e05d789c2a6f443e 100644 --- a/src/MissionManager/MissionController.h +++ b/src/MissionManager/MissionController.h @@ -89,18 +89,6 @@ public: /// Sends the mission items to the specified vehicle static void sendItemsToVehicle(Vehicle* vehicle, QmlObjectListModel* visualMissionItems); - /// Saves the mission to file - Q_INVOKABLE void save(void); - - /// Save and to file and send to vehicle if possible - Q_INVOKABLE void saveAndSend(void); - - /// Removes all items from the mission - Q_INVOKABLE void clearMission(void); - - /// Closes the mission, saving and sending as needed before closing - Q_INVOKABLE void closeMission(void); - // Overrides from PlanElementController void start (bool editMode) final; void startStaticActiveVehicle (Vehicle* vehicle) final; @@ -155,6 +143,7 @@ private slots: void _recalcWaypointLines(void); void _recalcMissionFlightStatus(void); void _updateContainsItems(void); + void _visualItemsDirtyChanged(bool dirty); private: void _init(void); diff --git a/src/MissionManager/MissionSettings.FactMetaData.json b/src/MissionManager/MissionSettings.FactMetaData.json index ee2ca017cc4ed4379820fe102c7a3f1062c71777..906947f05fcb006c05006ebde834a3b4b012ff95 100644 --- a/src/MissionManager/MissionSettings.FactMetaData.json +++ b/src/MissionManager/MissionSettings.FactMetaData.json @@ -22,11 +22,5 @@ "enumStrings": "No action on mission end,Loiter after mission end,RTL after mission end", "enumValues": "0,1,2", "defaultValue": 0 -}, -{ - "name": "MissionName", - "shortDescription": "Name for the mission.", - "type": "string", - "defaultValue": "" } ] diff --git a/src/MissionManager/MissionSettingsItem.cc b/src/MissionManager/MissionSettingsItem.cc index f00af40fabb1e7ef094a9ec572b7e8475f7e65b1..4fcc9d8513efe25184e4be72db6fc36faae5e2fe 100644 --- a/src/MissionManager/MissionSettingsItem.cc +++ b/src/MissionManager/MissionSettingsItem.cc @@ -23,7 +23,6 @@ QGC_LOGGING_CATEGORY(MissionSettingsComplexItemLog, "MissionSettingsComplexItemL const char* MissionSettingsItem::jsonComplexItemTypeValue = "MissionSettings"; -const char* MissionSettingsItem::_missionNameName = "MissionName"; const char* MissionSettingsItem::_plannedHomePositionAltitudeName = "PlannedHomePositionAltitude"; const char* MissionSettingsItem::_missionFlightSpeedName = "FlightSpeed"; const char* MissionSettingsItem::_missionEndActionName = "MissionEndAction"; @@ -32,9 +31,7 @@ QMap MissionSettingsItem::_metaDataMap; MissionSettingsItem::MissionSettingsItem(Vehicle* vehicle, QObject* parent) : ComplexMissionItem(vehicle, parent) - , _existingMission(false) , _specifyMissionFlightSpeed(false) - , _missionNameFact (0, _missionNameName, FactMetaData::valueTypeString) , _plannedHomePositionAltitudeFact (0, _plannedHomePositionAltitudeName, FactMetaData::valueTypeDouble) , _missionFlightSpeedFact (0, _missionFlightSpeedName, FactMetaData::valueTypeDouble) , _missionEndActionFact (0, _missionEndActionName, FactMetaData::valueTypeUint32) @@ -47,12 +44,10 @@ MissionSettingsItem::MissionSettingsItem(Vehicle* vehicle, QObject* parent) _metaDataMap = FactMetaData::createMapFromJsonFile(QStringLiteral(":/json/MissionSettings.FactMetaData.json"), NULL /* metaDataParent */); } - _missionNameFact.setMetaData (_metaDataMap[_missionNameName]); _plannedHomePositionAltitudeFact.setMetaData (_metaDataMap[_plannedHomePositionAltitudeName]); _missionFlightSpeedFact.setMetaData (_metaDataMap[_missionFlightSpeedName]); _missionEndActionFact.setMetaData (_metaDataMap[_missionEndActionName]); - _missionNameFact.setRawValue (_missionNameFact.rawDefaultValue()); _plannedHomePositionAltitudeFact.setRawValue (_plannedHomePositionAltitudeFact.rawDefaultValue()); _missionEndActionFact.setRawValue (_missionEndActionFact.rawDefaultValue()); @@ -63,8 +58,8 @@ MissionSettingsItem::MissionSettingsItem(Vehicle* vehicle, QObject* parent) setHomePositionSpecialCase(true); - connect(this, &MissionSettingsItem::specifyMissionFlightSpeedChanged, this, &MissionSettingsItem::_setDirtyAndUpdateLastSequenceNumber); - connect(&_cameraSection, &CameraSection::missionItemCountChanged, this, &MissionSettingsItem::_setDirtyAndUpdateLastSequenceNumber); + connect(this, &MissionSettingsItem::specifyMissionFlightSpeedChanged, this, &MissionSettingsItem::_setDirtyAndUpdateLastSequenceNumber); + connect(&_cameraSection, &CameraSection::missionItemCountChanged, this, &MissionSettingsItem::_setDirtyAndUpdateLastSequenceNumber); connect(&_plannedHomePositionAltitudeFact, &Fact::valueChanged, this, &MissionSettingsItem::_setDirty); connect(&_plannedHomePositionAltitudeFact, &Fact::valueChanged, this, &MissionSettingsItem::_updateAltitudeInCoordinate); @@ -411,19 +406,3 @@ void MissionSettingsItem::_updateAltitudeInCoordinate(QVariant value) emit exitCoordinateChanged(_plannedHomePositionCoordinate); } } - -void MissionSettingsItem::setExistingMission(bool existingMission) -{ - if (existingMission != _existingMission) { - _existingMission = existingMission; - emit existingMissionChanged(existingMission ); - } -} - -void MissionSettingsItem::setLoadedMissionDirectory(QString& loadedMissionDirectory) -{ - if (_loadedMissionDirectory != loadedMissionDirectory) { - _loadedMissionDirectory = loadedMissionDirectory; - emit loadedMissionDirectoryChanged(loadedMissionDirectory); - } -} diff --git a/src/MissionManager/MissionSettingsItem.h b/src/MissionManager/MissionSettingsItem.h index 7333e46ff29db557ed102ff94e36d962be20eb3b..d6d200b1b3e789fcbc7ef719f6decf9fba35fceb 100644 --- a/src/MissionManager/MissionSettingsItem.h +++ b/src/MissionManager/MissionSettingsItem.h @@ -32,24 +32,18 @@ public: }; Q_ENUMS(MissionEndAction) - Q_PROPERTY(Fact* missionName READ missionName CONSTANT) - Q_PROPERTY(QString loadedMissionDirectory READ loadedMissionDirectory WRITE setLoadedMissionDirectory NOTIFY loadedMissionDirectoryChanged) - Q_PROPERTY(bool existingMission READ existingMission WRITE setExistingMission NOTIFY existingMissionChanged) Q_PROPERTY(bool specifyMissionFlightSpeed READ specifyMissionFlightSpeed WRITE setSpecifyMissionFlightSpeed NOTIFY specifyMissionFlightSpeedChanged) Q_PROPERTY(Fact* missionFlightSpeed READ missionFlightSpeed CONSTANT) Q_PROPERTY(Fact* missionEndAction READ missionEndAction CONSTANT) Q_PROPERTY(Fact* plannedHomePositionAltitude READ plannedHomePositionAltitude CONSTANT) Q_PROPERTY(QObject* cameraSection READ cameraSection CONSTANT) - Fact* missionName (void) { return &_missionNameFact; } Fact* plannedHomePositionAltitude (void) { return &_plannedHomePositionAltitudeFact; } Fact* missionFlightSpeed (void) { return &_missionFlightSpeedFact; } Fact* missionEndAction (void) { return &_missionEndActionFact; } bool specifyMissionFlightSpeed (void) const { return _specifyMissionFlightSpeed; } - bool existingMission (void) const { return _existingMission; } void setSpecifyMissionFlightSpeed(bool specifyMissionFlightSpeed); - void setExistingMission(bool existingMission); QObject* cameraSection(void) { return &_cameraSection; } /// Scans the loaded items for settings items @@ -62,10 +56,6 @@ public: /// @return true: Mission end action was added bool addMissionEndAction(QList& items, int seqNum, QObject* missionItemParent); - // Returns the directory the misiosn was loaded from. Empty string is laoded from normal savePath. - QString loadedMissionDirectory(void) const { return _loadedMissionDirectory; } - void setLoadedMissionDirectory(QString& loadedMissionDirectory); - // Overrides from ComplexMissionItem double complexDistance (void) const final; @@ -104,8 +94,6 @@ public: signals: void specifyMissionFlightSpeedChanged(bool specifyMissionFlightSpeed); - void existingMissionChanged(bool existingMission); - void loadedMissionDirectoryChanged(QString& loadedMissionDirectory); private slots: void _setDirtyAndUpdateLastSequenceNumber (void); @@ -114,14 +102,11 @@ private slots: void _updateAltitudeInCoordinate (QVariant value); private: - bool _existingMission; bool _specifyMissionFlightSpeed; QGeoCoordinate _plannedHomePositionCoordinate; // Does not include altitde - Fact _missionNameFact; Fact _plannedHomePositionAltitudeFact; Fact _missionFlightSpeedFact; Fact _missionEndActionFact; - QString _loadedMissionDirectory; CameraSection _cameraSection; int _sequenceNumber; @@ -129,7 +114,6 @@ private: static QMap _metaDataMap; - static const char* _missionNameName; static const char* _plannedHomePositionAltitudeName; static const char* _missionFlightSpeedName; static const char* _missionEndActionName; diff --git a/src/MissionManager/SimpleMissionItem.cc b/src/MissionManager/SimpleMissionItem.cc index f59759e1f11f0b0c357fd298e27610aab1b09d22..4be427d181f4b4272defa4d2179ec67b33d53d99 100644 --- a/src/MissionManager/SimpleMissionItem.cc +++ b/src/MissionManager/SimpleMissionItem.cc @@ -51,6 +51,7 @@ SimpleMissionItem::SimpleMissionItem(Vehicle* vehicle, QObject* parent) : VisualMissionItem(vehicle, parent) , _rawEdit(false) , _dirty(false) + , _ignoreDirtyChangeSignals(false) , _cameraSection(NULL) , _commandTree(qgcApp()->toolbox()->missionCommandTree()) , _altitudeRelativeToHomeFact (0, "Altitude is relative to home", FactMetaData::valueTypeUint32) @@ -87,6 +88,7 @@ SimpleMissionItem::SimpleMissionItem(Vehicle* vehicle, const MissionItem& missio , _missionItem(missionItem) , _rawEdit(false) , _dirty(false) + , _ignoreDirtyChangeSignals(false) , _cameraSection(NULL) , _commandTree(qgcApp()->toolbox()->missionCommandTree()) , _altitudeRelativeToHomeFact (0, "Altitude is relative to home", FactMetaData::valueTypeUint32) @@ -117,6 +119,7 @@ SimpleMissionItem::SimpleMissionItem(const SimpleMissionItem& other, QObject* pa , _missionItem(other._vehicle) , _rawEdit(false) , _dirty(false) + , _ignoreDirtyChangeSignals(false) , _cameraSection(NULL) , _commandTree(qgcApp()->toolbox()->missionCommandTree()) , _altitudeRelativeToHomeFact (0, "Altitude is relative to home", FactMetaData::valueTypeUint32) @@ -390,6 +393,8 @@ QmlObjectListModel* SimpleMissionItem::textFieldFacts(void) _missionItem._param7Fact.setMetaData(_defaultParamMetaData); model->append(&_missionItem._param7Fact); } else { + _ignoreDirtyChangeSignals = true; + _clearParamMetaData(); MAV_CMD command; @@ -425,6 +430,8 @@ QmlObjectListModel* SimpleMissionItem::textFieldFacts(void) _missionItem._param7Fact.setMetaData(_altitudeMetaData); model->append(&_missionItem._param7Fact); } + + _ignoreDirtyChangeSignals = false; } return model; @@ -524,7 +531,9 @@ void SimpleMissionItem::setDirty(bool dirty) void SimpleMissionItem::_setDirtyFromSignal(void) { - setDirty(true); + if (!_ignoreDirtyChangeSignals) { + setDirty(true); + } } void SimpleMissionItem::_sendCoordinateChanged(void) diff --git a/src/MissionManager/SimpleMissionItem.h b/src/MissionManager/SimpleMissionItem.h index 47e459dd94d184c088708e142f7d32f518b1a641..7dcea5f4ac17b22c260fe1c069a52a279d4bf935 100644 --- a/src/MissionManager/SimpleMissionItem.h +++ b/src/MissionManager/SimpleMissionItem.h @@ -143,6 +143,7 @@ private: MissionItem _missionItem; bool _rawEdit; bool _dirty; + bool _ignoreDirtyChangeSignals; CameraSection* _cameraSection; diff --git a/src/PlanView/MissionSettingsEditor.qml b/src/PlanView/MissionSettingsEditor.qml index 206ac45919ff723d57fbd992be013cdef33bb91d..2957ab9f4314c56a74a830094ddbff505cf15e7f 100644 --- a/src/PlanView/MissionSettingsEditor.qml +++ b/src/PlanView/MissionSettingsEditor.qml @@ -31,10 +31,6 @@ Rectangle { property bool _mobile: ScreenTools.isMobile property var _savePath: QGroundControl.settingsManager.appSettings.missionSavePath property var _fileExtension: QGroundControl.settingsManager.appSettings.missionFileExtension - property bool _newMissionAlreadyExists: false - property bool _noMissionName: missionItem.missionName.valueString === "" - property bool _showMissionList: _noMissionItemsAdded && (_noMissionName || _newMissionAlreadyExists) - property bool _existingMissionLoaded: missionItem.existingMission property var _appSettings: QGroundControl.settingsManager.appSettings readonly property string _firmwareLabel: qsTr("Firmware") @@ -43,16 +39,6 @@ Rectangle { QGCPalette { id: qgcPal } QFileDialogController { id: fileController } - Connections { - target: missionItem.missionName - - onRawValueChanged: { - if (!_existingMissionLoaded) { - _newMissionAlreadyExists = !_noMissionName && fileController.fileExists(_savePath + "/" + missionItem.missionName.valueString + "." + _fileExtension) - } - } - } - Loader { id: deferedload active: valuesRect.visible @@ -74,140 +60,16 @@ Rectangle { anchors.top: parent.top spacing: _margin - QGCLabel { - text: qsTr("Mission name") - font.pointSize: ScreenTools.smallFontPointSize - } - - FactTextField { - anchors.left: parent.left - anchors.right: parent.right - fact: missionItem.missionName - visible: !_existingMissionLoaded - } - - QGCLabel { - text: missionItem.missionName.valueString - visible: _existingMissionLoaded - } - - QGCLabel { - text: qsTr("Mission already exists") - font.pointSize: ScreenTools.smallFontPointSize - color: qgcPal.warningText - visible: !_existingMissionLoaded && _newMissionAlreadyExists - } - - FactCheckBox { - id: automaticUploadCheckbox - text: qsTr("Automatically upload on exit") - fact: _appSettings.automaticMissionUpload - } - - RowLayout { - anchors.left: parent.left - anchors.right: parent.right - - QGCButton { - text: qsTr("Remove All") - visible: !_noMissionItemsAdded - Layout.fillWidth: true - onClicked: missionController.clearMission() - } - - QGCButton { - text: qsTr("New Mission") - visible: !_noMissionItemsAdded - Layout.fillWidth: true - onClicked: missionController.closeMission() - } - } - Loader { anchors.left: parent.left anchors.right: parent.right - sourceComponent: _showMissionList ? missionList : missionSettings + sourceComponent: missionSettings } } // Column } // Item } // Component } // Loader - Component { - id: missionList - - QGCFlickable { - anchors.left: parent.left - anchors.right: parent.right - height: missionColumn.height - - Column { - id: missionColumn - anchors.left: parent.left - anchors.right: parent.right - spacing: _margin - - SectionHeader { - text: qsTr("Load Mission") - showSpacer: false - } - - RowLayout { - anchors.left: parent.left - anchors.right: parent.right - - QGCButton { - text: qsTr("From Vehicle") - visible: !_offlineEditing - Layout.fillWidth: true - onClicked: missionController.loadFromVehicle() - } - - QGCButton { - text: qsTr("Browse") - Layout.fillWidth: true - onClicked: fileDialog.openForLoad() - - QGCFileDialog { - id: fileDialog - qgcView: rootQgcView - title: qsTr("Select mission file") - selectExisting: true - folder: _appSettings.missionSavePath - fileExtension: _appSettings.missionFileExtension - nameFilters: [ qsTr("Mission Files (*.%1)").arg(fileExtension) , qsTr("All Files (*.*)") ] - - onAcceptedForLoad: { - missionController.loadFromFile(file) - fileDialog.close() - } - } - } - } - - QGCLabel { - text: qsTr("No mission files") - visible: missionRepeater.model.length === 0 - } - - Repeater { - id: missionRepeater - model: fileController.getFiles(_savePath, _fileExtension); - - QGCButton { - anchors.left: parent.left - anchors.right: parent.right - text: modelData - - onClicked: { - missionController.loadFromFile(fileController.fullyQualifiedFilename(_savePath, modelData, _fileExtension)) - } - } - } - } - } - } - Component { id: missionSettings diff --git a/src/PlanView/PlanToolBar.qml b/src/PlanView/PlanToolBar.qml index 75d7d3c88e8146b18d1226da0d555195474501c7..cae259cc1f17e4faa49b7d3b2aa16ebb8468bba6 100644 --- a/src/PlanView/PlanToolBar.qml +++ b/src/PlanView/PlanToolBar.qml @@ -89,7 +89,7 @@ Rectangle { onClicked: { checked = false - if (missionController.saveOnSwitch()) { + if (missionController.uploadOnSwitch()) { showFlyView() } } @@ -178,9 +178,10 @@ Rectangle { anchors.rightMargin: _margins anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter - text: qsTr("Upload") - visible: _manualUpload && missionController.dirty - onClicked: missionController.uploadFromToolbar() + text: missionController.dirty ? qsTr("Upload Required") : qsTr("Upload") + enabled: _activeVehicle + visible: _manualUpload + onClicked: missionController.upload() } } diff --git a/src/PlanView/PlanView.qml b/src/PlanView/PlanView.qml index 41ce30804d73e968a37debb5a3d70f2bdc6c797f..9e1cfa3b478c72613f6f0b075e2e3fc97931a32f 100644 --- a/src/PlanView/PlanView.qml +++ b/src/PlanView/PlanView.qml @@ -19,6 +19,7 @@ import QGroundControl 1.0 import QGroundControl.FlightMap 1.0 import QGroundControl.ScreenTools 1.0 import QGroundControl.Controls 1.0 +import QGroundControl.FactControls 1.0 import QGroundControl.Palette 1.0 import QGroundControl.Mavlink 1.0 import QGroundControl.Controllers 1.0 @@ -28,9 +29,7 @@ import QGroundControl.Controllers 1.0 QGCView { id: _qgcView viewPanel: panel - - // zOrder comes from the Loader in MainWindow.qml - z: QGroundControl.zOrderTopMost + z: QGroundControl.zOrderTopMost readonly property int _decimalPlaces: 8 readonly property real _horizontalMargin: ScreenTools.defaultFontPixelWidth / 2 @@ -50,6 +49,7 @@ QGCView { property bool _singleComplexItem: missionController.complexMissionItemNames.length === 1 property real _toolbarHeight: _qgcView.height - ScreenTools.availableHeight property int _editingLayer: _layerMission + property bool _autoSync: QGroundControl.settingsManager.appSettings.automaticMissionUpload.rawValue != 0 /// The controller which should be called for load/save, send to/from vehicle calls property var _syncDropDownController: missionController @@ -105,30 +105,29 @@ QGCView { setCurrentItem(0) } + function _denyUpload() { + if (_activeVehicle && _activeVehicle.armed && _activeVehicle.flightMode === _activeVehicle.missionFlightMode) { + _qgcView.showMessage(qsTr("Mission Upload"), qsTr("Your vehicle is currently flying a mission. Upload is not allowed."), StandardButton.Ok) + return true + } else { + return false + } + } + // Users is switching away from Plan View - function saveOnSwitch() { - if (missionController.dirty) { - save() - if (_activeVehicle.armed) { - _qgcView.showDialog(confirmSendToActiveVehicleAndSwitchView, qsTr("Mission Upload"), _qgcView.showDialogDefaultWidth, StandardButton.Yes | StandardButton.No) - return false - } else { + function uploadOnSwitch() { + if (missionController.dirty && _autoSync) { + if (!_denyUpload()) { sendToVehicle() } } return true } - // User clicked upload button in plan toolbar - function uploadFromToolbar() { - if (missionController.dirty) { - save() - if (_activeVehicle.armed) { - _qgcView.showDialog(confirmSendToActiveVehicle, qsTr("Mission Upload"), _qgcView.showDialogDefaultWidth, StandardButton.Yes | StandardButton.No) - } else { + function upload() { + if (!_denyUpload()) { sendToVehicle() } - } } function loadFromSelectedFile() { @@ -339,17 +338,11 @@ QGCView { QGCViewPanel { id: panel - height: ScreenTools.availableHeight - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.right: parent.right + anchors.fill: parent FlightMap { id: editorMap - height: _qgcView.height - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.right: parent.right//rightPanel.left + anchors.fill: parent mapName: "MissionEditor" // This is the center rectangle of the map which is not obscured by tools @@ -528,13 +521,15 @@ QGCView { color: qgcPal.window title: qsTr("Plan") z: QGroundControl.zOrderWidgets - buttonVisible: [ true, true, true, _showZoom, _showZoom ] + showAlternateIcon: [ false, false, !_autoSync && _syncDropDownController.dirty, false, false, false ] + rotateImage: [ false, false, _syncDropDownController.syncInProgress, false, false, false ] + animateImage: [ false, false, !_autoSync && _syncDropDownController.dirty, false, false, false ] + buttonEnabled: [ true, true, !_syncDropDownController.syncInProgress, true, true, true ] + buttonVisible: [ true, true, true, true, _showZoom, _showZoom ] maxHeight: mapScale.y - toolStrip.y property bool _showZoom: !ScreenTools.isMobile - property bool mySingleComplexItem: _singleComplexItem - model: [ { name: "Waypoint", @@ -546,6 +541,12 @@ QGCView { iconSource: "/qmlimages/MapDrawShape.svg", dropPanelComponent: _singleComplexItem ? undefined : patternDropPanel }, + { + name: "Sync", + iconSource: "/qmlimages/MapSync.svg", + alternateIconSource: "/qmlimages/MapSyncChanged.svg", + dropPanelComponent: syncDropPanel + }, { name: "Center", iconSource: "/qmlimages/MapCenter.svg", @@ -571,10 +572,10 @@ QGCView { addComplexItem(missionController.complexMissionItemNames[0]) } break - case 3: + case 5: editorMap.zoomLevel += 0.5 break - case 4: + case 6: editorMap.zoomLevel -= 0.5 break } @@ -609,9 +610,9 @@ QGCView { // Right pane for mission editing controls Rectangle { id: rightPanel - anchors.top: parent.top anchors.bottom: parent.bottom anchors.right: parent.right + height: ScreenTools.availableHeight width: _rightPanelWidth color: qgcPal.window opacity: 0.95 @@ -796,6 +797,19 @@ QGCView { } } + + + Component { + id: geoFenceEditorComponent + + GeoFenceEditor { + availableWidth: _rightPanelWidth + availableHeight: ScreenTools.availableHeight + myGeoFenceController: geoFenceController + flightMap: editorMap + } + } + //- ToolStrip DropPanel Components Component { @@ -832,44 +846,90 @@ QGCView { } Component { - id: geoFenceEditorComponent - - GeoFenceEditor { - availableWidth: _rightPanelWidth - availableHeight: ScreenTools.availableHeight - myGeoFenceController: geoFenceController - flightMap: editorMap - } - } + id: syncDropPanel - Component { - id: confirmSendToActiveVehicleAndSwitchView + Column { + id: columnHolder + spacing: _margin - QGCViewMessage { - message: _armedVehicleUploadPrompt + property string _overwriteText: (_editingLayer == _layerMission) ? qsTr("Mission overwrite") : ((_editingLayer == _layerGeoFence) ? qsTr("GeoFence overwrite") : qsTr("Rally Points overwrite")) - function accept() { - missionController.sendToVehicle() - toolbar.showFlyView() - hideDialog() + QGCLabel { + width: sendSaveGrid.width + wrapMode: Text.WordWrap + text: _syncDropDownController.dirty ? + qsTr("You have unsaved changes. You should upload to your vehicle, or save to a file:") : + qsTr("Sync:") } - function reject() { - toolbar.showFlyView() - hideDialog() - } - } - } + GridLayout { + id: sendSaveGrid + columns: 2 + anchors.margins: _margin + rowSpacing: _margin + columnSpacing: ScreenTools.defaultFontPixelWidth - Component { - id: confirmSendToActiveVehicle + QGCButton { + text: qsTr("Upload") + Layout.fillWidth: true + enabled: _activeVehicle && !_syncDropDownController.syncInProgress + onClicked: { + dropPanel.hide() + _syncDropDownController.upload() + } + } - QGCViewMessage { - message: _armedVehicleUploadPrompt + QGCButton { + text: qsTr("Download") + Layout.fillWidth: true + enabled: _activeVehicle && !_syncDropDownController.syncInProgress + onClicked: { + dropPanel.hide() + if (_syncDropDownController.dirty) { + _qgcView.showDialog(syncLoadFromVehicleOverwrite, columnHolder._overwriteText, _qgcView.showDialogDefaultWidth, StandardButton.Yes | StandardButton.Cancel) + } else { + _syncDropDownController.loadFromVehicle() + } + } + } - function accept() { - missionController.sendToVehicle() - hideDialog() + QGCButton { + text: qsTr("Save To File...") + Layout.fillWidth: true + enabled: !_syncDropDownController.syncInProgress + onClicked: { + dropPanel.hide() + _syncDropDownController.saveToSelectedFile() + } + } + + QGCButton { + text: qsTr("Load From File...") + Layout.fillWidth: true + enabled: !_syncDropDownController.syncInProgress + onClicked: { + dropPanel.hide() + if (_syncDropDownController.dirty) { + _qgcView.showDialog(syncLoadFromFileOverwrite, columnHolder._overwriteText, _qgcView.showDialogDefaultWidth, StandardButton.Yes | StandardButton.Cancel) + } else { + _syncDropDownController.loadFromSelectedFile() + } + } + } + + QGCButton { + text: qsTr("Remove All") + Layout.fillWidth: true + onClicked: { + dropPanel.hide() + _qgcView.showDialog(removeAllPromptDialog, qsTr("Remove all"), _qgcView.showDialogDefaultWidth, StandardButton.Yes | StandardButton.No) + } + } + } + + FactCheckBox { + text: qsTr("Automatic upload to vehicle") + fact: QGroundControl.settingsManager.appSettings.automaticMissionUpload } } }