diff --git a/UnitTest.qrc b/UnitTest.qrc index 3332cf87698fa45ef6d3034f368cea05b7861e57..7d46cc26966de43e37a3f4f0c5bb4216b4098838 100644 --- a/UnitTest.qrc +++ b/UnitTest.qrc @@ -1,5 +1,6 @@ <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> diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index 382aca4f55422ad2692dd802386b2b595aa08b0d..f3132401b2180be9a9f4a69405dd8a6d1dc6c523 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -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 \ diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc index bc33589594d877d8f964a40dd76e43c52efb279f..c21e6d84aee18804b64e7994db2dab4b7ca604a8 100644 --- a/qgroundcontrol.qrc +++ b/qgroundcontrol.qrc @@ -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> diff --git a/src/MissionManager/MissionCommandTree.cc b/src/MissionManager/MissionCommandTree.cc index 42254c31e4324f8acb921f2319c3892ef85b6a34..9513a047929d29b28725a04ac3783457f26c6ead 100644 --- a/src/MissionManager/MissionCommandTree.cc +++ b/src/MissionManager/MissionCommandTree.cc @@ -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 diff --git a/src/MissionManager/MissionControllerTest.cc b/src/MissionManager/MissionControllerTest.cc index 13f91037bff9a92dcde94c7cc2b9aac804d735cc..c1bcdfc5c4b6c4bd7da7c8d5135ae31bd66e49c4 100644 --- a/src/MissionManager/MissionControllerTest.cc +++ b/src/MissionManager/MissionControllerTest.cc @@ -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); + } + + } +} diff --git a/src/MissionManager/MissionControllerTest.h b/src/MissionManager/MissionControllerTest.h index b92d9d9285df6c86acca26e6fb4effc2e7ab6091..101c20482dc9841926c97cd2a804bc96aa69323a 100644 --- a/src/MissionManager/MissionControllerTest.h +++ b/src/MissionManager/MissionControllerTest.h @@ -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); diff --git a/src/MissionManager/PlanMasterController.cc b/src/MissionManager/PlanMasterController.cc index 4e6807023d763b176183f5e5ba5220ae975a20fd..0d97b1f854b49fdd310f348bc7a2f144755db858 100644 --- a/src/MissionManager/PlanMasterController.cc +++ b/src/MissionManager/PlanMasterController.cc @@ -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; } diff --git a/src/MissionManager/PlanMasterControllerTest.cc b/src/MissionManager/PlanMasterControllerTest.cc index f52b5340083f1635a9c4ef4572ed9d14906de9ff..c27162bc3443dcfdef59d70111c33a05bda21ec4 100644 --- a/src/MissionManager/PlanMasterControllerTest.cc +++ b/src/MissionManager/PlanMasterControllerTest.cc @@ -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); } diff --git a/src/MissionManager/SimpleMissionItem.cc b/src/MissionManager/SimpleMissionItem.cc index 4372d5599c348613418f16cec87427337a8ba3a1..4f144450d732b9a81d59f092c0e5db05a14aadaa 100644 --- a/src/MissionManager/SimpleMissionItem.cc +++ b/src/MissionManager/SimpleMissionItem.cc @@ -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 diff --git a/src/MissionManager/UnitTest/SectionTest.plan b/src/MissionManager/UnitTest/SectionTest.plan new file mode 100644 index 0000000000000000000000000000000000000000..c98f6a31d72c796516a1f7df6679f95b7012814f --- /dev/null +++ b/src/MissionManager/UnitTest/SectionTest.plan @@ -0,0 +1,119 @@ +{ + "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 +} diff --git a/src/PlanView/MissionSettingsEditor.qml b/src/PlanView/MissionSettingsEditor.qml index 643810bbfe2e1dea8366bcd32bd69f76e7774d90..2e3544f4e87b7871efdd59ea0dd3dfe9a3cebfb8 100644 --- a/src/PlanView/MissionSettingsEditor.qml +++ b/src/PlanView/MissionSettingsEditor.qml @@ -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 } } diff --git a/src/QGCApplication.cc b/src/QGCApplication.cc index f7a9f17d320024b3a6d5835ff6aa6a27fc629bd7..f390a864a16905dacecf530cdaab241e7d70c6db 100644 --- a/src/QGCApplication.cc +++ b/src/QGCApplication.cc @@ -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"); diff --git a/src/QmlControls/FileButton.qml b/src/QmlControls/FileButton.qml new file mode 100644 index 0000000000000000000000000000000000000000..1ebd67ebaefa72407ebf45193ce806bb6336b521 --- /dev/null +++ b/src/QmlControls/FileButton.qml @@ -0,0 +1,64 @@ +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() + } +} diff --git a/src/QmlControls/QFileDialogController.cc b/src/QmlControls/QFileDialogController.cc deleted file mode 100644 index a536cbf4a66e8f2578e2cd58f71a53d17e65273c..0000000000000000000000000000000000000000 --- a/src/QmlControls/QFileDialogController.cc +++ /dev/null @@ -1,56 +0,0 @@ -/**************************************************************************** - * - * (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. - * - ****************************************************************************/ - - -#include "QFileDialogController.h" - -#include <QStandardPaths> -#include <QDebug> -#include <QDir> - -QGC_LOGGING_CATEGORY(QFileDialogControllerLog, "QFileDialogControllerLog") - -QStringList QFileDialogController::getFiles(const QString& directoryPath, const QString& fileExtension) -{ - qCDebug(QFileDialogControllerLog) << "getFiles" << directoryPath << fileExtension; - QStringList files; - - QDir fileDir(directoryPath); - - QFileInfoList fileInfoList = fileDir.entryInfoList(QStringList(QString("*.%1").arg(fileExtension)), QDir::Files, QDir::Name); - - foreach (const QFileInfo& fileInfo, fileInfoList) { - qCDebug(QFileDialogControllerLog) << "getFiles found" << fileInfo.baseName(); - files << fileInfo.baseName(); - } - - return files; -} - -QString QFileDialogController::filenameWithExtension(const QString& filename, const QString& fileExtension) -{ - QString filenameWithExtension(filename); - - QString correctExtension = QString(".%1").arg(fileExtension); - if (!filenameWithExtension.endsWith(correctExtension)) { - filenameWithExtension += correctExtension; - } - - return filenameWithExtension; -} - -bool QFileDialogController::fileExists(const QString& filename) -{ - return QFile(filename).exists(); -} - -QString QFileDialogController::fullyQualifiedFilename(const QString& directoryPath, const QString& filename, const QString& fileExtension) -{ - return directoryPath + QStringLiteral("/") + filenameWithExtension(filename, fileExtension); -} diff --git a/src/QmlControls/QGCFileDialog.qml b/src/QmlControls/QGCFileDialog.qml index 5ef9432add7e6cf66fd192bb8041dc4ccbbfbe4c..c10dbcf13d53ab6c894f6ecb2c3a2bee8bf87b47 100644 --- a/src/QmlControls/QGCFileDialog.qml +++ b/src/QmlControls/QGCFileDialog.qml @@ -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); + } + } + } + } } } } diff --git a/src/QmlControls/QGCFileDialogController.cc b/src/QmlControls/QGCFileDialogController.cc new file mode 100644 index 0000000000000000000000000000000000000000..89ead9bb11adbe76b34d8c330c3616d6cca30206 --- /dev/null +++ b/src/QmlControls/QGCFileDialogController.cc @@ -0,0 +1,66 @@ +/**************************************************************************** + * + * (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. + * + ****************************************************************************/ + + +#include "QGCFileDialogController.h" + +#include <QStandardPaths> +#include <QDebug> +#include <QDir> + +QGC_LOGGING_CATEGORY(QGCFileDialogControllerLog, "QGCFileDialogControllerLog") + +QStringList QGCFileDialogController::getFiles(const QString& directoryPath, const QStringList& fileExtensions) +{ + qCDebug(QGCFileDialogControllerLog) << "getFiles" << directoryPath << fileExtensions; + QStringList files; + + QDir fileDir(directoryPath); + + 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(QGCFileDialogControllerLog) << "getFiles found" << fileInfo.fileName(); + files << fileInfo.fileName(); + } + + return files; +} + +QString QGCFileDialogController::filenameWithExtension(const QString& filename, const QString& fileExtension) +{ + QString filenameWithExtension(filename); + + QString correctExtension = QString(".%1").arg(fileExtension); + if (!filenameWithExtension.endsWith(correctExtension)) { + filenameWithExtension += correctExtension; + } + + return filenameWithExtension; +} + +bool QGCFileDialogController::fileExists(const QString& filename) +{ + return QFile(filename).exists(); +} + +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); +} diff --git a/src/QmlControls/QFileDialogController.h b/src/QmlControls/QGCFileDialogController.h similarity index 78% rename from src/QmlControls/QFileDialogController.h rename to src/QmlControls/QGCFileDialogController.h index 59948dc7e3d433e424782ac3d7264c260646edfd..76a815453519c049c4ce56fdddf9565d4e5c50bb 100644 --- a/src/QmlControls/QFileDialogController.h +++ b/src/QmlControls/QGCFileDialogController.h @@ -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(); } }; diff --git a/src/QmlControls/QGroundControl.Controls.qmldir b/src/QmlControls/QGroundControl.Controls.qmldir index 813cd7436176c1e7da8b6a2033a5ee2c91d9c61b..8f3050ffbe523e5cdcd228119c1ddc24eb166e50 100644 --- a/src/QmlControls/QGroundControl.Controls.qmldir +++ b/src/QmlControls/QGroundControl.Controls.qmldir @@ -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