From 42c113161095983446d047d71e68bee93cde85de Mon Sep 17 00:00:00 2001 From: Don Gagne Date: Mon, 7 Mar 2016 13:19:14 -0800 Subject: [PATCH] New QGCMobileFileDialog - Convert mission load/save to it - Allow parameter load/save on mobile --- qgroundcontrol.pro | 2 + qgroundcontrol.qrc | 5 +- src/MissionEditor/MissionEditor.qml | 46 ++---- src/MissionManager/MissionController.cc | 55 +------- src/MissionManager/MissionController.h | 11 +- src/QGCApplication.cc | 50 ++++--- src/QGCApplication.h | 4 + src/QGCMobileFileDialogController.cc | 73 ++++++++++ src/QGCMobileFileDialogController.h | 49 +++++++ src/QmlControls/ParameterEditor.qml | 58 ++++++-- src/QmlControls/ParameterEditorController.cc | 54 +++---- src/QmlControls/ParameterEditorController.h | 8 +- src/QmlControls/QGCLabel.qml | 1 - src/QmlControls/QGCMobileFileDialog.qml | 133 ++++++++++++++++++ .../QGroundControl.Controls.qmldir | 1 + src/QmlControls/QGroundControlQmlGlobal.h | 8 ++ 16 files changed, 402 insertions(+), 156 deletions(-) create mode 100644 src/QGCMobileFileDialogController.cc create mode 100644 src/QGCMobileFileDialogController.h create mode 100644 src/QmlControls/QGCMobileFileDialog.qml diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index 222329fda..569526cdc 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -269,6 +269,7 @@ HEADERS += \ src/QGCGeo.h \ src/QGCLoggingCategory.h \ src/QGCMapPalette.h \ + src/QGCMobileFileDialogController.h \ src/QGCPalette.h \ src/QGCQmlWidgetHolder.h \ src/QGCQuickWidget.h \ @@ -397,6 +398,7 @@ SOURCES += \ src/QGCFileDownload.cc \ src/QGCLoggingCategory.cc \ src/QGCMapPalette.cc \ + src/QGCMobileFileDialogController.cc \ src/QGCPalette.cc \ src/QGCQuickWidget.cc \ src/QGCQmlWidgetHolder.cpp \ diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc index e553d7f62..3bee5c348 100644 --- a/qgroundcontrol.qrc +++ b/qgroundcontrol.qrc @@ -64,13 +64,14 @@ src/QmlControls/QGCButton.qml src/QmlControls/QGCCheckBox.qml src/QmlControls/QGCColoredImage.qml + src/QmlControls/QGCComboBox.qml src/QmlControls/QGCFlickable.qml - src/QmlControls/QGCPipable.qml src/QmlControls/QGCFlickableVerticalIndicator.qml src/QmlControls/QGCFlickableHorizontalIndicator.qml - src/QmlControls/QGCComboBox.qml src/QmlControls/QGCLabel.qml + src/QmlControls/QGCMobileFileDialog.qml src/QmlControls/QGCMovableItem.qml + src/QmlControls/QGCPipable.qml src/QmlControls/QGCRadioButton.qml src/QmlControls/QGCTextField.qml src/QmlControls/QGCToolBarButton.qml diff --git a/src/MissionEditor/MissionEditor.qml b/src/MissionEditor/MissionEditor.qml index 96d7a279d..9b9a86732 100644 --- a/src/MissionEditor/MissionEditor.qml +++ b/src/MissionEditor/MissionEditor.qml @@ -92,7 +92,7 @@ QGCView { if (ScreenTools.isMobile) { _root.showDialog(mobileFilePicker, "Select Mission File", _root.showDialogDefaultWidth, StandardButton.Yes | StandardButton.Cancel) } else { - controller.loadMissionFromFile() + controller.loadMissionFromFilePicker() fitViewportToMissionItems() } } @@ -191,23 +191,13 @@ QGCView { Component { id: mobileFilePicker - QGCViewDialog { - ListView { - anchors.margins: _margin - anchors.fill: parent - spacing: _margin / 2 - orientation: ListView.Vertical - model: controller.getMobileMissionFiles() - - delegate: QGCButton { - text: modelData + QGCMobileFileDialog { + openDialog: true + fileExtension: QGroundControl.missionFileExtension - onClicked: { - hideDialog() - controller.loadMobileMissionFromFile(modelData) - fitViewportToMissionItems() - } - } + onFilenameReturned: { + controller.loadMissionFromFile(filename) + fitViewportToMissionItems() } } } @@ -215,24 +205,12 @@ QGCView { Component { id: mobileFileSaver - QGCViewDialog { - function accept() { - hideDialog() - controller.saveMobileMissionToFile(filenameTextField.text) - } - - Column { - anchors.left: parent.left - anchors.right: parent.right - spacing: ScreenTools.defaultFontPixelHeight + QGCMobileFileDialog { + openDialog: false + fileExtension: QGroundControl.missionFileExtension - QGCLabel { - text: "File name:" - } - - QGCTextField { - id: filenameTextField - } + onFilenameReturned: { + controller.saveMissionToFile(filename) } } } diff --git a/src/MissionManager/MissionController.cc b/src/MissionManager/MissionController.cc index 12d0c4606..ecbbfc5a9 100644 --- a/src/MissionManager/MissionController.cc +++ b/src/MissionManager/MissionController.cc @@ -422,7 +422,7 @@ bool MissionController::_loadTextMissionFile(QTextStream& stream, QmlObjectListM return true; } -void MissionController::_loadMissionFromFile(const QString& filename) +void MissionController::loadMissionFromFile(const QString& filename) { QString errorString; @@ -482,7 +482,7 @@ void MissionController::_loadMissionFromFile(const QString& filename) _initAllVisualItems(); } -void MissionController::loadMissionFromFile(void) +void MissionController::loadMissionFromFilePicker(void) { #ifndef __mobile__ QString filename = QGCFileDialog::getOpenFileName(NULL, "Select Mission File to load", QString(), "Mission file (*.mission);;All Files (*.*)"); @@ -490,11 +490,11 @@ void MissionController::loadMissionFromFile(void) if (filename.isEmpty()) { return; } - _loadMissionFromFile(filename); + loadMissionFromFile(filename); #endif } -void MissionController::_saveMissionToFile(const QString& filename) +void MissionController::saveMissionToFile(const QString& filename) { qDebug() << filename; @@ -504,7 +504,7 @@ void MissionController::_saveMissionToFile(const QString& filename) QString missionFilename = filename; if (!QFileInfo(filename).fileName().contains(".")) { - missionFilename += ".mission"; + missionFilename += QString(".%1").arg(QGCApplication::missionFileExtension); } QFile file(missionFilename); @@ -566,7 +566,7 @@ void MissionController::_saveMissionToFile(const QString& filename) _visualItems->setDirty(false); } -void MissionController::saveMissionToFile(void) +void MissionController::saveMissionToFilePicker(void) { #ifndef __mobile__ QString filename = QGCFileDialog::getSaveFileName(NULL, "Select file to save mission to", QString(), "Mission file (*.mission);;All Files (*.*)"); @@ -574,31 +574,10 @@ void MissionController::saveMissionToFile(void) if (filename.isEmpty()) { return; } - _saveMissionToFile(filename); + saveMissionToFile(filename); #endif } -void MissionController::saveMobileMissionToFile(const QString& filename) -{ - QStringList docDirs = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation); - if (docDirs.count() <= 0) { - qWarning() << "No Documents location"; - return; - } - - _saveMissionToFile(docDirs.at(0) + QDir::separator() + filename); -} - -void MissionController::loadMobileMissionFromFile(const QString& filename) -{ - QStringList docDirs = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation); - if (docDirs.count() <= 0) { - qWarning() << "No Documents location"; - return; - } - _loadMissionFromFile(docDirs.at(0) + QDir::separator() + filename); -} - void MissionController::_calcPrevWaypointValues(double homeAlt, VisualMissionItem* currentItem, VisualMissionItem* prevItem, double* azimuth, double* distance, double* altDifference) { QGeoCoordinate currentCoord = currentItem->coordinate(); @@ -1109,26 +1088,6 @@ void MissionController::_currentMissionItemChanged(int sequenceNumber) } } -QStringList MissionController::getMobileMissionFiles(void) -{ - QStringList missionFiles; - - QStringList docDirs = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation); - if (docDirs.count() <= 0) { - qWarning() << "No Documents location"; - return QStringList(); - } - QDir missionDir = docDirs.at(0); - - QFileInfoList missionFileInfoList = missionDir.entryInfoList(QStringList(QStringLiteral("*.mission")), QDir::Files, QDir::Name); - - foreach (const QFileInfo& missionFileInfo, missionFileInfoList) { - missionFiles << missionFileInfo.baseName() + ".mission"; - } - - return missionFiles; -} - bool MissionController::syncInProgress(void) { if (_activeVehicle) { diff --git a/src/MissionManager/MissionController.h b/src/MissionManager/MissionController.h index 34956ec9a..2d6f6d29a 100644 --- a/src/MissionManager/MissionController.h +++ b/src/MissionManager/MissionController.h @@ -51,13 +51,12 @@ public: Q_INVOKABLE void start(bool editMode); Q_INVOKABLE void getMissionItems(void); Q_INVOKABLE void sendMissionItems(void); - Q_INVOKABLE void loadMissionFromFile(void); - Q_INVOKABLE void saveMissionToFile(void); - Q_INVOKABLE void loadMobileMissionFromFile(const QString& file); - Q_INVOKABLE void saveMobileMissionToFile(const QString& file); + Q_INVOKABLE void loadMissionFromFilePicker(void); + Q_INVOKABLE void loadMissionFromFile(const QString& filename); + Q_INVOKABLE void saveMissionToFilePicker(void); + Q_INVOKABLE void saveMissionToFile(const QString& filename); Q_INVOKABLE void removeMissionItem(int index); Q_INVOKABLE void removeAllMissionItems(void); - Q_INVOKABLE QStringList getMobileMissionFiles(void); /// Add a new simple mission item to the list /// @param i: index to insert at @@ -119,8 +118,6 @@ private: double _normalizeLon(double lon); bool _loadJsonMissionFile(const QByteArray& bytes, QmlObjectListModel* visualItems, QmlObjectListModel* complexItems, QString& errorString); bool _loadTextMissionFile(QTextStream& stream, QmlObjectListModel* visualItems, QString& errorString); - void _loadMissionFromFile(const QString& file); - void _saveMissionToFile(const QString& file); int _nextSequenceNumber(void); private: diff --git a/src/QGCApplication.cc b/src/QGCApplication.cc index 42816fbe3..a05f40dca 100644 --- a/src/QGCApplication.cc +++ b/src/QGCApplication.cc @@ -71,6 +71,7 @@ #include "RadioComponentController.h" #include "ESP8266ComponentController.h" #include "ScreenToolsController.h" +#include "QGCMobileFileDialogController.h" #include "AutoPilotPlugin.h" #include "VehicleComponent.h" #include "FirmwarePluginManager.h" @@ -125,6 +126,10 @@ QGCApplication* QGCApplication::_app = NULL; +const char* QGCApplication::parameterFileExtension = "params"; +const char* QGCApplication::missionFileExtension = "mission"; +const char* QGCApplication::telemetryFileExtension = "tlog"; + const char* QGCApplication::_deleteAllSettingsKey = "DeleteAllSettingsNextBoot"; const char* QGCApplication::_settingsVersionKey = "SettingsVersion"; const char* QGCApplication::_promptFlightDataSave = "PromptFLightDataSave"; @@ -449,6 +454,7 @@ void QGCApplication::_initCommon(void) qmlRegisterType ("QGroundControl.Controllers", 1, 0, "MissionController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "FlightDisplayViewController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "ValuesWidgetController"); + qmlRegisterType ("QGroundControl.Controllers", 1, 0, "QGCMobileFileDialogController"); #ifndef __mobile__ qmlRegisterType ("QGroundControl.Controllers", 1, 0, "ViewWidgetController"); @@ -462,28 +468,6 @@ void QGCApplication::_initCommon(void) qmlRegisterSingletonType ("QGroundControl", 1, 0, "QGroundControl", qgroundcontrolQmlGlobalSingletonFactory); qmlRegisterSingletonType ("QGroundControl.ScreenToolsController", 1, 0, "ScreenToolsController", screenToolsControllerSingletonFactory); qmlRegisterSingletonType ("QGroundControl.Mavlink", 1, 0, "Mavlink", mavlinkQmlSingletonFactory); - - // Show user an upgrade message if the settings version has been bumped up - bool settingsUpgraded = false; - if (settings.contains(_settingsVersionKey)) { - if (settings.value(_settingsVersionKey).toInt() != QGC_SETTINGS_VERSION) { - settingsUpgraded = true; - } - } else if (settings.allKeys().count()) { - // Settings version key is missing and there are settings. This is an upgrade scenario. - settingsUpgraded = true; - } else { - settings.setValue(_settingsVersionKey, QGC_SETTINGS_VERSION); - } - - if (settingsUpgraded) { - settings.clear(); - settings.setValue(_settingsVersionKey, QGC_SETTINGS_VERSION); - showMessage("The format for QGroundControl saved settings has been modified. " - "Your saved settings have been reset to defaults."); - } - - settings.sync(); } bool QGCApplication::_initForNormalAppBoot(void) @@ -515,6 +499,28 @@ bool QGCApplication::_initForNormalAppBoot(void) // Load known link configurations toolbox()->linkManager()->loadLinkConfigurationList(); + // Show user an upgrade message if the settings version has been bumped up + bool settingsUpgraded = false; + if (settings.contains(_settingsVersionKey)) { + if (settings.value(_settingsVersionKey).toInt() != QGC_SETTINGS_VERSION) { + settingsUpgraded = true; + } + } else if (settings.allKeys().count()) { + // Settings version key is missing and there are settings. This is an upgrade scenario. + settingsUpgraded = true; + } else { + settings.setValue(_settingsVersionKey, QGC_SETTINGS_VERSION); + } + + if (settingsUpgraded) { + settings.clear(); + settings.setValue(_settingsVersionKey, QGC_SETTINGS_VERSION); + showMessage("The format for QGroundControl saved settings has been modified. " + "Your saved settings have been reset to defaults."); + } + + settings.sync(); + return true; } diff --git a/src/QGCApplication.h b/src/QGCApplication.h index e645e6247..de5ed9653 100644 --- a/src/QGCApplication.h +++ b/src/QGCApplication.h @@ -78,6 +78,10 @@ public: QGCApplication(int &argc, char* argv[], bool unitTesting); ~QGCApplication(); + static const char* parameterFileExtension; + static const char* missionFileExtension; + static const char* telemetryFileExtension; + /// @brief Sets the persistent flag to delete all settings the next time QGroundControl is started. void deleteAllSettingsNextBoot(void); diff --git a/src/QGCMobileFileDialogController.cc b/src/QGCMobileFileDialogController.cc new file mode 100644 index 000000000..8ad210307 --- /dev/null +++ b/src/QGCMobileFileDialogController.cc @@ -0,0 +1,73 @@ +/*===================================================================== + +QGroundControl Open Source Ground Control Station + +(c) 2009, 2015 QGROUNDCONTROL PROJECT + +This file is part of the QGROUNDCONTROL project + + QGROUNDCONTROL is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + QGROUNDCONTROL is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with QGROUNDCONTROL. If not, see . + +======================================================================*/ + +#include "QGCMobileFileDialogController.h" + +#include +#include +#include + +QStringList QGCMobileFileDialogController::getFiles(const QString& fileExtension) +{ + QStringList files; + + QStringList docDirs = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation); + if (docDirs.count() <= 0) { + qWarning() << "No Documents location"; + return QStringList(); + } + QDir fileDir = docDirs.at(0); + + QFileInfoList fileInfoList = fileDir.entryInfoList(QStringList(QString("*.%1").arg(fileExtension)), QDir::Files, QDir::Name); + + foreach (const QFileInfo& fileInfo, fileInfoList) { + files << fileInfo.baseName() + QStringLiteral(".") + fileExtension; + } + + return files; +} + +QString QGCMobileFileDialogController::fullPath(const QString& filename, const QString& fileExtension) +{ + QStringList docDirs = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation); + if (docDirs.count() <= 0) { + qWarning() << "No Documents location"; + return filename; + } + + QString fixedFilename(filename); + QString correctExtension = QString(".%1").arg(fileExtension); + if (!filename.endsWith(correctExtension)) { + fixedFilename += correctExtension; + } + + QString fullPath = docDirs.at(0) + QDir::separator() + fixedFilename; + qDebug() << fullPath; + return fullPath; +} + +bool QGCMobileFileDialogController::fileExists(const QString& filename, const QString& fileExtension) +{ + QFile file(fullPath(filename, fileExtension)); + return file.exists(); +} diff --git a/src/QGCMobileFileDialogController.h b/src/QGCMobileFileDialogController.h new file mode 100644 index 000000000..62268bf9e --- /dev/null +++ b/src/QGCMobileFileDialogController.h @@ -0,0 +1,49 @@ +/*===================================================================== + +QGroundControl Open Source Ground Control Station + +(c) 2009, 2015 QGROUNDCONTROL PROJECT + +This file is part of the QGROUNDCONTROL project + + QGROUNDCONTROL is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + QGROUNDCONTROL is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with QGROUNDCONTROL. If not, see . + +======================================================================*/ + +#ifndef QGCMobileFileDialogController_H +#define QGCMobileFileDialogController_H + +#include + +class QGCMobileFileDialogController : public QObject +{ + Q_OBJECT + +public: + /// Return all file in Documents location which match the specified extension + Q_INVOKABLE QStringList getFiles(const QString& fileExtension); + + /// Return the full path for specified file in the Documents location + /// @param filename File name, not fully qualified, may not have extension + /// @param fileExtension Expected file extension, added if needed + Q_INVOKABLE QString fullPath(const QString& filename, const QString& fileExtension); + + /// Check for file existance + /// @param filename File name, not fully qualified, may not have extension + /// @param fileExtension Expected file extension, added if needed + /// @return true: File exists at Documents location + Q_INVOKABLE bool fileExists(const QString& filename, const QString& fileExtension); +}; + +#endif diff --git a/src/QmlControls/ParameterEditor.qml b/src/QmlControls/ParameterEditor.qml index 9bc04f63c..d2ce7fc7b 100644 --- a/src/QmlControls/ParameterEditor.qml +++ b/src/QmlControls/ParameterEditor.qml @@ -24,17 +24,17 @@ /// @file /// @author Don Gagne -import QtQuick 2.3 -import QtQuick.Controls 1.3 -import QtQuick.Controls.Styles 1.2 -import QtQuick.Dialogs 1.2 +import QtQuick 2.5 +import QtQuick.Controls 1.3 +import QtQuick.Dialogs 1.2 -import QGroundControl.Controls 1.0 -import QGroundControl.Palette 1.0 -import QGroundControl.ScreenTools 1.0 -import QGroundControl.Controllers 1.0 -import QGroundControl.FactSystem 1.0 -import QGroundControl.FactControls 1.0 +import QGroundControl 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.Palette 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Controllers 1.0 +import QGroundControl.FactSystem 1.0 +import QGroundControl.FactControls 1.0 QGCView { id: qgcView @@ -123,16 +123,26 @@ QGCView { text: "Search..." onTriggered: showDialog(searchDialogComponent, "Parameter Search", qgcView.showDialogDefaultWidth, StandardButton.Reset | StandardButton.Apply) } - MenuSeparator { visible: !ScreenTools.isMobile } + MenuSeparator { } MenuItem { text: "Load from file..." - onTriggered: controller.loadFromFile() - visible: !ScreenTools.isMobile + onTriggered: { + if (ScreenTools.isMobile) { + qgcView.showDialog(mobileFilePicker, "Select Parameter File", qgcView.showDialogDefaultWidth, StandardButton.Yes | StandardButton.Cancel) + } else { + controller.loadFromFilePicker() + } + } } MenuItem { text: "Save to file..." - onTriggered: controller.saveToFile() - visible: !ScreenTools.isMobile + onTriggered: { + if (ScreenTools.isMobile) { + qgcView.showDialog(mobileFileSaver, "Save Parameter File", qgcView.showDialogDefaultWidth, StandardButton.Save | StandardButton.Cancel) + } else { + controller.saveToFilePicker() + } + } } MenuSeparator { visible: _showRCToParam } MenuItem { @@ -375,4 +385,22 @@ QGCView { } } + Component { + id: mobileFilePicker + + QGCMobileFileDialog { + fileExtension: QGroundControl.parameterFileExtension + onFilenameReturned: controller.loadFromFile(filename) + } + } + + Component { + id: mobileFileSaver + + QGCMobileFileDialog { + openDialog: false + fileExtension: QGroundControl.parameterFileExtension + onFilenameReturned: controller.saveToFile(filename) + } + } } // QGCView diff --git a/src/QmlControls/ParameterEditorController.cc b/src/QmlControls/ParameterEditorController.cc index 31f8652a3..028067ebe 100644 --- a/src/QmlControls/ParameterEditorController.cc +++ b/src/QmlControls/ParameterEditorController.cc @@ -95,27 +95,18 @@ void ParameterEditorController::clearRCToParam(void) _uas->unsetRCToParameterMap(); } -void ParameterEditorController::saveToFile(void) +void ParameterEditorController::saveToFile(const QString& filename) { -#ifndef __mobile__ if (!_autopilot) { qWarning() << "Internal error _autopilot==NULL"; return; } - QString msgTitle("Save Parameters"); - - QString fileName = QGCFileDialog::getSaveFileName(NULL, - msgTitle, - QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), - "Parameter Files (*.params)", - "params", - true); - if (!fileName.isEmpty()) { - QFile file(fileName); + if (!filename.isEmpty()) { + QFile file(filename); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { - qgcApp()->showMessage("Unable to create file"); + qgcApp()->showMessage(QString("Unable to create file: %1").arg(filename)); return; } @@ -123,12 +114,23 @@ void ParameterEditorController::saveToFile(void) _autopilot->writeParametersToStream(stream); file.close(); } -#endif } -void ParameterEditorController::loadFromFile(void) +void ParameterEditorController::saveToFilePicker(void) { #ifndef __mobile__ + QString fileName = QGCFileDialog::getSaveFileName(NULL, + "Save Parameters", + QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), + "Parameter Files (*.params)", + "params", + true); + saveToFile(fileName); +#endif +} + +void ParameterEditorController::loadFromFile(const QString& filename) +{ QString errors; if (!_autopilot) { @@ -136,17 +138,11 @@ void ParameterEditorController::loadFromFile(void) return; } - QString msgTitle("Load Parameters"); - - QString fileName = QGCFileDialog::getOpenFileName(NULL, - msgTitle, - QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), - "Parameter Files (*.params);;All Files (*)"); - if (!fileName.isEmpty()) { - QFile file(fileName); + if (!filename.isEmpty()) { + QFile file(filename); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - qgcApp()->showMessage("Unable to open file"); + qgcApp()->showMessage(QString("Unable to open file: %1").arg(filename)); return; } @@ -158,6 +154,16 @@ void ParameterEditorController::loadFromFile(void) emit showErrorMessage(errors); } } +} + +void ParameterEditorController::loadFromFilePicker(void) +{ +#ifndef __mobile__ + QString fileName = QGCFileDialog::getOpenFileName(NULL, + "Load Parameters", + QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), + "Parameter Files (*.params);;All Files (*)"); + loadFromFile(fileName); #endif } diff --git a/src/QmlControls/ParameterEditorController.h b/src/QmlControls/ParameterEditorController.h index a1db2225e..0c751c081 100644 --- a/src/QmlControls/ParameterEditorController.h +++ b/src/QmlControls/ParameterEditorController.h @@ -49,9 +49,11 @@ public: Q_INVOKABLE QStringList searchParametersForComponent(int componentId, const QString& searchText, bool searchInName, bool searchInDescriptions); Q_INVOKABLE void clearRCToParam(void); - Q_INVOKABLE void saveToFile(void); - Q_INVOKABLE void loadFromFile(void); - Q_INVOKABLE void refresh(void); + Q_INVOKABLE void saveToFilePicker(void); + Q_INVOKABLE void loadFromFilePicker(void); + Q_INVOKABLE void saveToFile(const QString& filename); + Q_INVOKABLE void loadFromFile(const QString& filename); + Q_INVOKABLE void refresh(void); Q_INVOKABLE void resetAllToDefaults(void); Q_INVOKABLE void setRCToParam(const QString& paramName); diff --git a/src/QmlControls/QGCLabel.qml b/src/QmlControls/QGCLabel.qml index 2e266d81d..070e7c7ba 100644 --- a/src/QmlControls/QGCLabel.qml +++ b/src/QmlControls/QGCLabel.qml @@ -11,7 +11,6 @@ Text { property bool enabled: true font.pixelSize: ScreenTools.defaultFontPixelSize - fontSizeMode: Text.HorizontalFit color: __qgcPal.text antialiasing: true } diff --git a/src/QmlControls/QGCMobileFileDialog.qml b/src/QmlControls/QGCMobileFileDialog.qml new file mode 100644 index 000000000..70d947c35 --- /dev/null +++ b/src/QmlControls/QGCMobileFileDialog.qml @@ -0,0 +1,133 @@ +/*===================================================================== + +QGroundControl Open Source Ground Control Station + +(c) 2009, 2015 QGROUNDCONTROL PROJECT + +This file is part of the QGROUNDCONTROL project + + QGROUNDCONTROL is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + QGROUNDCONTROL is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with QGROUNDCONTROL. If not, see . + +======================================================================*/ + +import QtQuick 2.5 +import QtQuick.Controls 1.3 +import QtQuick.Dialogs 1.2 + +import QGroundControl 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.Controllers 1.0 +import QGroundControl.Palette 1.0 + +/// Simple file picker for mobile +QGCViewDialog { + property bool openDialog: true ///< true: Show file open dialog, false: show file save dialog + property string fileExtension ///< File extension for file listing + + signal filenameReturned(string filename) + + readonly property real _margins: ScreenTools.defaultFontPixelHeight / 2 + + function accept() { + if (!openDialog) { + if (!dialogLoader.item.replaceMessageShown) { + if (controller.fileExists(dialogLoader.item.filename, fileExtension)) { + dialogLoader.item.replaceMessageShown = true + return + } + } + filenameReturned(controller.fullPath(dialogLoader.item.filename, fileExtension)) + } + hideDialog() + } + + QGCMobileFileDialogController { id: controller } + QGCPalette { id: qgcPal; colorGroupEnabled: true } + + Loader { + id: dialogLoader + anchors.fill: parent + sourceComponent: openDialog ? openDialogComponent : saveDialogComponent + } + + Component { + id: saveDialogComponent + + Column { + anchors.left: parent.left + anchors.right: parent.right + spacing: ScreenTools.defaultFontPixelHeight + + property alias filename: filenameTextField.text + property alias replaceMessageShown: replaceMessage.visible + + QGCLabel { + text: "File name:" + } + + QGCTextField { + id: filenameTextField + onTextChanged: replaceMessage.visible = false + } + + QGCLabel { + anchors.left: parent.left + anchors.right: parent.right + wrapMode: Text.WordWrap + text: "File names must end with ." + fileExtension + " file extension. If missing it will be added." + } + + QGCLabel { + id: replaceMessage + anchors.left: parent.left + anchors.right: parent.right + wrapMode: Text.WordWrap + text: "The file " + filename + " exists. Click Save again to replace it." + visible: false + color: qgcPal.warningText + } + } + } + + Component { + id: openDialogComponent + + Item { + anchors.margins: _margins + anchors.fill: parent + + ListView { + anchors.fill: parent + spacing: _margins / 2 + orientation: ListView.Vertical + model: controller.getFiles(fileExtension) + + delegate: QGCButton { + text: modelData + + onClicked: { + hideDialog() + filenameReturned(controller.fullPath(modelData, fileExtension)) + } + } + } + + QGCLabel { + text: "No files" + visible: controller.getFiles(fileExtension).length == 0 + } + } + } +} diff --git a/src/QmlControls/QGroundControl.Controls.qmldir b/src/QmlControls/QGroundControl.Controls.qmldir index 05526e6b6..9cb83400b 100644 --- a/src/QmlControls/QGroundControl.Controls.qmldir +++ b/src/QmlControls/QGroundControl.Controls.qmldir @@ -20,6 +20,7 @@ QGCColoredImage 1.0 QGCColoredImage.qml QGCComboBox 1.0 QGCComboBox.qml QGCFlickable 1.0 QGCFlickable.qml QGCLabel 1.0 QGCLabel.qml +QGCMobileFileDialog 1.0 QGCMobileFileDialog.qml QGCMovableItem 1.0 QGCMovableItem.qml QGCPipable 1.0 QGCPipable.qml QGCRadioButton 1.0 QGCRadioButton.qml diff --git a/src/QmlControls/QGroundControlQmlGlobal.h b/src/QmlControls/QGroundControlQmlGlobal.h index 77234f5ca..ae9e925b1 100644 --- a/src/QmlControls/QGroundControlQmlGlobal.h +++ b/src/QmlControls/QGroundControlQmlGlobal.h @@ -80,6 +80,10 @@ public: Q_PROPERTY(QGeoCoordinate flightMapPosition MEMBER _flightMapPosition NOTIFY flightMapPositionChanged) Q_PROPERTY(int flightMapZoom MEMBER _flightMapZoom NOTIFY flightMapZoomChanged) + Q_PROPERTY(QString parameterFileExtension READ parameterFileExtension CONSTANT) + Q_PROPERTY(QString missionFileExtension READ missionFileExtension CONSTANT) + Q_PROPERTY(QString telemetryFileExtension READ telemetryFileExtension CONSTANT) + /// @ return: true: experimental survey ip code is turned on Q_PROPERTY(bool experimentalSurvey READ experimentalSurvey WRITE setExperimentalSurvey NOTIFY experimentalSurveyChanged) @@ -140,6 +144,10 @@ public: bool experimentalSurvey(void) const; void setExperimentalSurvey(bool experimentalSurvey); + QString parameterFileExtension(void) const { return QGCApplication::parameterFileExtension; } + QString missionFileExtension(void) const { return QGCApplication::missionFileExtension; } + QString telemetryFileExtension(void) const { return QGCApplication::telemetryFileExtension; } + // Overrides from QGCTool virtual void setToolbox(QGCToolbox* toolbox); -- 2.22.0