Commit e9896fec authored by Don Gagne's avatar Don Gagne Committed by GitHub

Merge pull request #5308 from DonLakeFlyer/Fixes

Fixes: Camera Section visibility, mode file dialog support for delete
parents 590ea791 54331a19
<RCC>
<qresource prefix="/json/unittest">
<qresource prefix="/unittest">
<file alias="SectionTest.plan">src/MissionManager/UnitTest/SectionTest.plan</file>
<file alias="MavCmdInfoCommon.json">src/MissionManager/UnitTest/MavCmdInfoCommon.json</file>
<file alias="MavCmdInfoFixedWing.json">src/MissionManager/UnitTest/MavCmdInfoFixedWing.json</file>
<file alias="MavCmdInfoMultiRotor.json">src/MissionManager/UnitTest/MavCmdInfoMultiRotor.json</file>
......
......@@ -515,7 +515,7 @@ HEADERS += \
src/QmlControls/CoordinateVector.h \
src/QmlControls/MavlinkQmlSingleton.h \
src/QmlControls/ParameterEditorController.h \
src/QmlControls/QFileDialogController.h \
src/QmlControls/QGCFileDialogController.h \
src/QmlControls/QGCImageProvider.h \
src/QmlControls/QGroundControlQmlGlobal.h \
src/QmlControls/QmlObjectListModel.h \
......@@ -691,7 +691,7 @@ SOURCES += \
src/QmlControls/AppMessages.cc \
src/QmlControls/CoordinateVector.cc \
src/QmlControls/ParameterEditorController.cc \
src/QmlControls/QFileDialogController.cc \
src/QmlControls/QGCFileDialogController.cc \
src/QmlControls/QGCImageProvider.cc \
src/QmlControls/QGroundControlQmlGlobal.cc \
src/QmlControls/QmlObjectListModel.cc \
......
......@@ -55,6 +55,7 @@
<file alias="QGroundControl/Controls/DropButton.qml">src/QmlControls/DropButton.qml</file>
<file alias="QGroundControl/Controls/ExclusiveGroupItem.qml">src/QmlControls/ExclusiveGroupItem.qml</file>
<file alias="QGroundControl/Controls/FactSliderPanel.qml">src/QmlControls/FactSliderPanel.qml</file>
<file alias="QGroundControl/Controls/FileButton.qml">src/QmlControls/FileButton.qml</file>
<file alias="QGroundControl/Controls/FlightModeDropdown.qml">src/QmlControls/FlightModeDropdown.qml</file>
<file alias="QGroundControl/Controls/FlightModeMenu.qml">src/QmlControls/FlightModeMenu.qml</file>
<file alias="QGroundControl/Controls/FWLandingPatternMapVisual.qml">src/PlanView/FWLandingPatternMapVisual.qml</file>
......
......@@ -38,12 +38,12 @@ void MissionCommandTree::setToolbox(QGCToolbox* toolbox)
#ifdef UNITTEST_BUILD
if (_unitTest) {
// Load unit testing tree
_staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_GENERIC] = new MissionCommandList(":/json/unittest/MavCmdInfoCommon.json", true, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_FIXED_WING] = new MissionCommandList(":/json/unittest/MavCmdInfoFixedWing.json", false, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_QUADROTOR] = new MissionCommandList(":/json/unittest/MavCmdInfoMultiRotor.json", false, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_VTOL_QUADROTOR] = new MissionCommandList(":/json/unittest/MavCmdInfoVTOL.json", false, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_SUBMARINE] = new MissionCommandList(":/json/unittest/MavCmdInfoSub.json", false, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_GROUND_ROVER] = new MissionCommandList(":/json/unittest/MavCmdInfoRover.json", false, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_GENERIC] = new MissionCommandList(":/unittest/MavCmdInfoCommon.json", true, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_FIXED_WING] = new MissionCommandList(":/unittest/MavCmdInfoFixedWing.json", false, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_QUADROTOR] = new MissionCommandList(":/unittest/MavCmdInfoMultiRotor.json", false, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_VTOL_QUADROTOR] = new MissionCommandList(":/unittest/MavCmdInfoVTOL.json", false, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_SUBMARINE] = new MissionCommandList(":/unittest/MavCmdInfoSub.json", false, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_GROUND_ROVER] = new MissionCommandList(":/unittest/MavCmdInfoRover.json", false, this);
} else {
#endif
// Load all levels of hierarchy
......
......@@ -224,3 +224,27 @@ void MissionControllerTest::_testGimbalRecalc(void)
QCOMPARE(visualItem->missionGimbalYaw(), 0.0);
}
}
void MissionControllerTest::_testLoadJsonSectionAvailable(void)
{
_initForFirmwareType(MAV_AUTOPILOT_PX4);
_masterController->loadFromFile(":/unittest/SectionTest.plan");
QmlObjectListModel* visualItems = _missionController->visualItems();
QVERIFY(visualItems);
QCOMPARE(visualItems->count(), 5);
// Check that only waypoint items have camera and speed sections
for (int i=1; i<visualItems->count(); i++) {
SimpleMissionItem* item = visualItems->value<SimpleMissionItem*>(i);
QVERIFY(item);
if ((int)item->command() == MAV_CMD_NAV_WAYPOINT) {
QCOMPARE(item->cameraSection()->available(), true);
QCOMPARE(item->speedSection()->available(), true);
} else {
QCOMPARE(item->cameraSection()->available(), false);
QCOMPARE(item->speedSection()->available(), false);
}
}
}
......@@ -33,12 +33,13 @@ private slots:
void cleanup(void);
void _testGimbalRecalc(void);
private:
void _testLoadJsonSectionAvailable(void);
void _testEmptyVehicleAPM(void);
void _testEmptyVehiclePX4(void);
void _testAddWayppointAPM(void);
void _testAddWayppointPX4(void);
private:
#if 0
void _testOfflineToOnlineAPM(void);
void _testOfflineToOnlinePX4(void);
......
......@@ -246,6 +246,7 @@ void PlanMasterController::loadFromFile(const QString& filename)
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
errorString = file.errorString() + QStringLiteral(" ") + filename;
qgcApp()->showMessage(errorMessage.arg(errorString));
return;
}
......
......@@ -40,13 +40,13 @@ void PlanMasterControllerTest::cleanup(void)
void PlanMasterControllerTest::_testMissionFileLoad(void)
{
_masterController->loadFromFile(":/json/unittest/OldFileFormat.mission");
_masterController->loadFromFile(":/unittest/OldFileFormat.mission");
QCOMPARE(_masterController->missionController()->visualItems()->count(), 7);
}
void PlanMasterControllerTest::_testMissionPlannerFileLoad(void)
{
_masterController->loadFromFile(":/json/unittest/MissionPlanner.waypoints");
_masterController->loadFromFile(":/unittest/MissionPlanner.waypoints");
QCOMPARE(_masterController->missionController()->visualItems()->count(), 6);
}
......@@ -278,12 +278,20 @@ void SimpleMissionItem::save(QJsonArray& missionItems)
bool SimpleMissionItem::load(QTextStream &loadStream)
{
return _missionItem.load(loadStream);
bool success;
if ((success = _missionItem.load(loadStream))) {
_updateOptionalSections();
}
return success;
}
bool SimpleMissionItem::load(const QJsonObject& json, int sequenceNumber, QString& errorString)
{
return _missionItem.load(json, sequenceNumber, errorString);
bool success;
if ((success = _missionItem.load(json, sequenceNumber, errorString))) {
_updateOptionalSections();
}
return success;
}
bool SimpleMissionItem::isStandaloneCoordinate(void) const
......@@ -755,6 +763,7 @@ void SimpleMissionItem::_updateOptionalSections(void)
emit cameraSectionChanged(_cameraSection);
emit speedSectionChanged(_speedSection);
emit lastSequenceNumberChanged(lastSequenceNumber());
}
int SimpleMissionItem::lastSequenceNumber(void) const
......
{
"fileType": "Plan",
"geoFence": {
"polygon": [
],
"version": 1
},
"groundStation": "QGroundControl",
"mission": {
"cruiseSpeed": 15,
"firmwareType": 12,
"hoverSpeed": 5,
"items": [
{
"autoContinue": true,
"command": 22,
"coordinate": [
47.63311996,
-122.090763,
20
],
"doJumpId": 1,
"frame": 3,
"params": [
0,
0,
0,
null
],
"type": "SimpleItem"
},
{
"autoContinue": true,
"command": 16,
"coordinate": [
47.63369112,
-122.08925023,
20
],
"doJumpId": 2,
"frame": 3,
"params": [
0,
0,
0,
null
],
"type": "SimpleItem"
},
{
"autoContinue": true,
"command": 16,
"coordinate": [
47.63345253,
-122.08725467,
20
],
"doJumpId": 3,
"frame": 3,
"params": [
0,
0,
0,
null
],
"type": "SimpleItem"
},
{
"autoContinue": true,
"command": 205,
"coordinate": [
0,
0,
2
],
"doJumpId": 4,
"frame": 2,
"params": [
0,
0,
0,
0
],
"type": "SimpleItem"
},
{
"autoContinue": true,
"command": 16,
"coordinate": [
47.63261386,
-122.08661094,
20
],
"doJumpId": 5,
"frame": 3,
"params": [
0,
0,
0,
null
],
"type": "SimpleItem"
}
],
"plannedHomePosition": [
47.633389756176875,
-122.09076300000001,
20
],
"vehicleType": 2,
"version": 2
},
"rallyPoints": {
"points": [
],
"version": 1
},
"version": 1
}
......@@ -41,7 +41,7 @@ Rectangle {
readonly property string _vehicleLabel: qsTr("Vehicle")
QGCPalette { id: qgcPal }
QFileDialogController { id: fileController }
QGCFileDialogController { id: fileController }
Loader {
id: deferedload
......@@ -153,9 +153,10 @@ Rectangle {
spacing: _margin
visible: missionEndHeader.checked
FactCheckBox {
text: qsTr("Return To Launch")
fact: missionItem.missionEndRTL
QGCCheckBox {
text: qsTr("Return To Launch")
checked: missionItem.missionEndRTL
onClicked: missionItem.missionEndRTL = checked
}
}
......
......@@ -49,7 +49,7 @@
#include "CustomCommandWidgetController.h"
#include "ESP8266ComponentController.h"
#include "ScreenToolsController.h"
#include "QFileDialogController.h"
#include "QGCFileDialogController.h"
#include "RCChannelMonitorController.h"
#include "SyslinkComponentController.h"
#include "AutoPilotPlugin.h"
......@@ -363,16 +363,16 @@ void QGCApplication::_initCommon(void)
qmlRegisterUncreatableType<GeoFenceController> ("QGroundControl.Controllers", 1, 0, "GeoFenceController", "Reference only");
qmlRegisterUncreatableType<RallyPointController>("QGroundControl.Controllers", 1, 0, "RallyPointController", "Reference only");
qmlRegisterType<ParameterEditorController> ("QGroundControl.Controllers", 1, 0, "ParameterEditorController");
qmlRegisterType<ESP8266ComponentController> ("QGroundControl.Controllers", 1, 0, "ESP8266ComponentController");
qmlRegisterType<ScreenToolsController> ("QGroundControl.Controllers", 1, 0, "ScreenToolsController");
qmlRegisterType<PlanMasterController> ("QGroundControl.Controllers", 1, 0, "PlanElemementMasterController");
qmlRegisterType<ValuesWidgetController> ("QGroundControl.Controllers", 1, 0, "ValuesWidgetController");
qmlRegisterType<QFileDialogController> ("QGroundControl.Controllers", 1, 0, "QFileDialogController");
qmlRegisterType<RCChannelMonitorController> ("QGroundControl.Controllers", 1, 0, "RCChannelMonitorController");
qmlRegisterType<JoystickConfigController> ("QGroundControl.Controllers", 1, 0, "JoystickConfigController");
qmlRegisterType<LogDownloadController> ("QGroundControl.Controllers", 1, 0, "LogDownloadController");
qmlRegisterType<SyslinkComponentController> ("QGroundControl.Controllers", 1, 0, "SyslinkComponentController");
qmlRegisterType<ParameterEditorController> ("QGroundControl.Controllers", 1, 0, "ParameterEditorController");
qmlRegisterType<ESP8266ComponentController> ("QGroundControl.Controllers", 1, 0, "ESP8266ComponentController");
qmlRegisterType<ScreenToolsController> ("QGroundControl.Controllers", 1, 0, "ScreenToolsController");
qmlRegisterType<PlanMasterController> ("QGroundControl.Controllers", 1, 0, "PlanElemementMasterController");
qmlRegisterType<ValuesWidgetController> ("QGroundControl.Controllers", 1, 0, "ValuesWidgetController");
qmlRegisterType<QGCFileDialogController> ("QGroundControl.Controllers", 1, 0, "QGCFileDialogController");
qmlRegisterType<RCChannelMonitorController> ("QGroundControl.Controllers", 1, 0, "RCChannelMonitorController");
qmlRegisterType<JoystickConfigController> ("QGroundControl.Controllers", 1, 0, "JoystickConfigController");
qmlRegisterType<LogDownloadController> ("QGroundControl.Controllers", 1, 0, "LogDownloadController");
qmlRegisterType<SyslinkComponentController> ("QGroundControl.Controllers", 1, 0, "SyslinkComponentController");
#ifndef __mobile__
qmlRegisterType<ViewWidgetController> ("QGroundControl.Controllers", 1, 0, "ViewWidgetController");
qmlRegisterType<CustomCommandWidgetController> ("QGroundControl.Controllers", 1, 0, "CustomCommandWidgetController");
......
import QtQuick 2.3
import QtQuick.Controls 1.2
import QGroundControl.Palette 1.0
import QGroundControl.ScreenTools 1.0
/// File Button controls used by QGCFileDialog control
Rectangle {
implicitWidth: ScreenTools.implicitButtonWidth
implicitHeight: ScreenTools.implicitButtonHeight
color: highlight ? qgcPal.buttonHighlight : qgcPal.button
border.color: highlight ? qgcPal.buttonHighlightText : qgcPal.buttonText
property alias text: label.text
property bool highlight: false
signal clicked
signal hamburgerClicked
property real _margins: ScreenTools.defaultFontPixelWidth / 2
QGCPalette { id: qgcPal; colorGroupEnabled: enabled }
QGCLabel {
id: label
anchors.margins: _margins
anchors.left: parent.left
anchors.right: hamburger.left
anchors.top: parent.top
anchors.bottom: parent.bottom
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
color: highlight ? qgcPal.buttonHighlightText : qgcPal.buttonText
elide: Text.ElideRight
}
QGCColoredImage {
id: hamburger
anchors.rightMargin: _margins
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
width: _hamburgerSize
height: _hamburgerSize
sourceSize.height: _hamburgerSize
source: "qrc:/qmlimages/Hamburger.svg"
color: highlight ? qgcPal.buttonHighlightText : qgcPal.buttonText
property real _hamburgerSize: parent.height * 0.75
}
QGCMouseArea {
anchors.fill: parent
onClicked: parent.clicked()
}
QGCMouseArea {
anchors.leftMargin: -_margins * 2
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
anchors.left: hamburger.left
onClicked: parent.hamburgerClicked()
}
}
......@@ -17,16 +17,25 @@ Item {
property var qgcView
property string folder
property var nameFilters
property string fileExtension
property string fileExtension2
property string fileExtension // Primary file extension to search for
property string fileExtension2 // Secondary file extension to search for
property string title
property bool selectExisting
property bool selectFolder
property bool _openForLoad: true
property real _margins: ScreenTools.defaultFontPixelHeight / 2
property bool _mobile: ScreenTools.isMobile
property bool _openForLoad: true
property real _margins: ScreenTools.defaultFontPixelHeight / 2
property bool _mobile: ScreenTools.isMobile
property var _rgExtensions
Component.onCompleted: {
if (fileExtension2 === "") {
_rgExtensions = [ fileExtension ]
} else {
_rgExtensions = [ fileExtension, fileExtension2 ]
}
}
function openForLoad() {
_openForLoad = true
......@@ -54,7 +63,7 @@ Item {
signal acceptedForSave(string file)
signal rejected
QFileDialogController { id: controller }
QGCFileDialogController { id: controller }
QGCPalette { id: qgcPal; colorGroupEnabled: true }
FileDialog {
......@@ -92,9 +101,10 @@ Item {
Repeater {
id: fileList
model: controller.getFiles(folder, fileExtension)
model: controller.getFiles(folder, _rgExtensions)
QGCButton {
FileButton {
id: fileButton
anchors.left: parent.left
anchors.right: parent.right
text: modelData
......@@ -103,21 +113,27 @@ Item {
hideDialog()
_root.acceptedForLoad(controller.fullyQualifiedFilename(folder, modelData, fileExtension))
}
}
}
Repeater {
id: fileList2
model: fileExtension2 == "" ? [ ] : controller.getFiles(folder, fileExtension2)
onHamburgerClicked: {
highlight = true
hamburgerMenu.fileToDelete = controller.fullyQualifiedFilename(folder, modelData, fileExtension)
hamburgerMenu.popup()
}
QGCButton {
anchors.left: parent.left
anchors.right: parent.right
text: modelData
Menu {
id: hamburgerMenu
onClicked: {
hideDialog()
_root.acceptedForLoad(controller.fullyQualifiedFilename(folder, modelData, fileExtension2))
property string fileToDelete
onAboutToHide: {
fileButton.highlight = false
hideDialog()
}
MenuItem {
text: qsTr("Delete")
onTriggered: controller.deleteFile(hamburgerMenu.fileToDelete);
}
}
}
}
......@@ -197,9 +213,9 @@ Item {
}
Repeater {
model: controller.getFiles(folder, fileExtension)
model: controller.getFiles(folder, [ fileExtension ])
QGCButton {
FileButton {
anchors.left: parent.left
anchors.right: parent.right
text: modelData
......@@ -208,10 +224,30 @@ Item {
hideDialog()
_root.acceptedForSave(controller.fullyQualifiedFilename(folder, modelData, fileExtension))
}
}
}
onHamburgerClicked: {
highlight = true
hamburgerMenu.fileToDelete = controller.fullyQualifiedFilename(folder, modelData, fileExtension)
hamburgerMenu.popup()
}
Menu {
id: hamburgerMenu
property string fileToDelete
onAboutToHide: {
fileButton.highlight = false
hideDialog()
}
MenuItem {
text: qsTr("Delete")
onTriggered: controller.deleteFile(hamburgerMenu.fileToDelete);
}
}
}
}
}
}
}
......
......@@ -8,32 +8,37 @@
****************************************************************************/
#include "QFileDialogController.h"
#include "QGCFileDialogController.h"
#include <QStandardPaths>
#include <QDebug>
#include <QDir>
QGC_LOGGING_CATEGORY(QFileDialogControllerLog, "QFileDialogControllerLog")
QGC_LOGGING_CATEGORY(QGCFileDialogControllerLog, "QGCFileDialogControllerLog")
QStringList QFileDialogController::getFiles(const QString& directoryPath, const QString& fileExtension)
QStringList QGCFileDialogController::getFiles(const QString& directoryPath, const QStringList& fileExtensions)
{
qCDebug(QFileDialogControllerLog) << "getFiles" << directoryPath << fileExtension;
qCDebug(QGCFileDialogControllerLog) << "getFiles" << directoryPath << fileExtensions;
QStringList files;
QDir fileDir(directoryPath);
QFileInfoList fileInfoList = fileDir.entryInfoList(QStringList(QString("*.%1").arg(fileExtension)), QDir::Files, QDir::Name);
QStringList infoListExtensions;
foreach (const QString& extension, fileExtensions) {
infoListExtensions.append(QStringLiteral("*.%1").arg(extension));
}
QFileInfoList fileInfoList = fileDir.entryInfoList(infoListExtensions, QDir::Files, QDir::Name);
foreach (const QFileInfo& fileInfo, fileInfoList) {
qCDebug(QFileDialogControllerLog) << "getFiles found" << fileInfo.baseName();
files << fileInfo.baseName();
qCDebug(QGCFileDialogControllerLog) << "getFiles found" << fileInfo.fileName();
files << fileInfo.fileName();
}
return files;
}
QString QFileDialogController::filenameWithExtension(const QString& filename, const QString& fileExtension)
QString QGCFileDialogController::filenameWithExtension(const QString& filename, const QString& fileExtension)
{
QString filenameWithExtension(filename);
......@@ -45,12 +50,17 @@ QString QFileDialogController::filenameWithExtension(const QString& filename, co
return filenameWithExtension;
}
bool QFileDialogController::fileExists(const QString& filename)
bool QGCFileDialogController::fileExists(const QString& filename)
{
return QFile(filename).exists();
}
QString QFileDialogController::fullyQualifiedFilename(const QString& directoryPath, const QString& filename, const QString& fileExtension)
QString QGCFileDialogController::fullyQualifiedFilename(const QString& directoryPath, const QString& filename, const QString& fileExtension)
{
return directoryPath + QStringLiteral("/") + filenameWithExtension(filename, fileExtension);
}
void QGCFileDialogController::deleteFile(const QString& filename)
{
QFile::remove(filename);
}
......@@ -8,23 +8,23 @@
****************************************************************************/
#ifndef QFileDialogController_H
#define QFileDialogController_H
#ifndef QGCFileDialogController_H
#define QGCFileDialogController_H
#include <QObject>
#include <QUrl>
#include "QGCLoggingCategory.h"
Q_DECLARE_LOGGING_CATEGORY(QFileDialogControllerLog)
Q_DECLARE_LOGGING_CATEGORY(QGCFileDialogControllerLog)
class QFileDialogController : public QObject
class QGCFileDialogController : public QObject
{
Q_OBJECT
public:
/// Return all file in the specified path which match the specified extension
Q_INVOKABLE QStringList getFiles(const QString& directoryPath, const QString& fileExtension);
Q_INVOKABLE QStringList getFiles(const QString& directoryPath, const QStringList& fileExtensions);
/// Returns the specified file name with the extension added it needed
Q_INVOKABLE QString filenameWithExtension(const QString& filename, const QString& fileExtension);
......@@ -35,6 +35,9 @@ public:
/// Check for file existence of specified fully qualified file name
Q_INVOKABLE bool fileExists(const QString& filename);
/// Deletes the file specified by the fully qualified file name
Q_INVOKABLE void deleteFile(const QString& filename);
Q_INVOKABLE QString urlToLocalFile(QUrl url) { return url.toLocalFile(); }
};
......
......@@ -8,6 +8,7 @@ DropButton 1.0 DropButton.qml
DropPanel 1.0 DropPanel.qml
ExclusiveGroupItem 1.0 ExclusiveGroupItem.qml
FactSliderPanel 1.0 FactSliderPanel.qml
FileButton 1.0 FileButton.qml
FlightModeDropdown 1.0 FlightModeDropdown.qml
FlightModeMenu 1.0 FlightModeMenu.qml
GeoFenceEditor 1.0 GeoFenceEditor.qml
......
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