Commit 635cccee authored by Don Gagne's avatar Don Gagne Committed by GitHub

Merge pull request #4743 from DonLakeFlyer/NoLogPrompt

Telemetry logs are now saved with generated file name
parents 1b54fd00 7791f55e
/****************************************************************************
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
......@@ -82,19 +82,19 @@
#include "SettingsManager.h"
#ifndef NO_SERIAL_LINK
#include "SerialLink.h"
#include "SerialLink.h"
#endif
#ifndef __mobile__
#include "QGCFileDialog.h"
#include "QGCMessageBox.h"
#include "FirmwareUpgradeController.h"
#include "MainWindow.h"
#include "GeoTagController.h"
#include "QGCFileDialog.h"
#include "QGCMessageBox.h"
#include "FirmwareUpgradeController.h"
#include "MainWindow.h"
#include "GeoTagController.h"
#endif
#ifdef QGC_RTLAB_ENABLED
#include "OpalLink.h"
#include "OpalLink.h"
#endif
#ifdef Q_OS_LINUX
......@@ -162,15 +162,15 @@ QGCApplication::QGCApplication(int &argc, char* argv[], bool unitTesting)
#ifdef __mobile__
: QGuiApplication(argc, argv)
, _qmlAppEngine(NULL)
#else
#else
: QApplication(argc, argv)
#endif
#endif
, _runningUnitTests(unitTesting)
, _fakeMobile(false)
, _settingsUpgraded(false)
#ifdef QT_DEBUG
#ifdef QT_DEBUG
, _testHighDPI(false)
#endif
#endif
, _toolbox(NULL)
, _bluetoothAvailable(false)
, _lastKnownHomePosition(37.803784, -122.462276, 0.0)
......@@ -237,9 +237,9 @@ QGCApplication::QGCApplication(int &argc, char* argv[], bool unitTesting)
{ "--clear-settings", &fClearSettingsOptions, NULL },
{ "--logging", &logging, &loggingOptions },
{ "--fake-mobile", &_fakeMobile, NULL },
#ifdef QT_DEBUG
#ifdef QT_DEBUG
{ "--test-high-dpi", &_testHighDPI, NULL },
#endif
#endif
// Add additional command line option flags here
};
......@@ -498,33 +498,67 @@ void QGCApplication::criticalMessageBoxOnMainThread(const QString& title, const
}
#ifndef __mobile__
void QGCApplication::saveTempFlightDataLogOnMainThread(QString tempLogfile)
void QGCApplication::saveTelemetryLogOnMainThread(QString tempLogfile)
{
bool saveError;
do{
saveError = false;
QString saveFilename = QGCFileDialog::getSaveFileName(
MainWindow::instance(),
tr("Save Flight Data Log"),
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation),
tr("Flight Data Log Files (*.mavlink)"),
"mavlink");
if (!saveFilename.isEmpty()) {
// if file exsits already, try to remove it first to overwrite it
if(QFile::exists(saveFilename) && !QFile::remove(saveFilename)){
// if the file cannot be removed, prompt user and ask new path
saveError = true;
QGCMessageBox::warning("File Error","Could not overwrite existing file.\nPlease provide a different file name to save to.");
} else if(!QFile::copy(tempLogfile, saveFilename)) {
// if file could not be copied, prompt user and ask new path
saveError = true;
QGCMessageBox::warning("File Error","Could not create file.\nPlease provide a different file name to save to.");
}
// The vehicle is gone now and we are shutting down so we need to use a message box for errors to hold shutdown and show the error
if (_checkTelemetrySavePath(true /* useMessageBox */)) {
QString saveDirPath = _toolbox->settingsManager()->appSettings()->telemetrySavePath()->rawValue().toString();
QDir saveDir(saveDirPath);
QString nameFormat("%1%2.mavlink");
QString dtFormat("yyyy-MMM-dd hh-mm-ss");
int tryIndex = 1;
QString saveFileName = nameFormat.arg(QDateTime::currentDateTime().toString(dtFormat)).arg("");
while (saveDir.exists(saveFileName)) {
saveFileName = nameFormat.arg(QDateTime::currentDateTime().toString(dtFormat)).arg(QStringLiteral(".%1").arg(tryIndex++));
}
QString saveFilePath = saveDir.absoluteFilePath(saveFileName);
QFile tempFile(tempLogfile);
if (!tempFile.copy(saveFilePath)) {
QGCMessageBox::warning(tr("Telemetry save error"), tr("Unable to save telemetry log. Error copying telemetry to '%1': '%2'.").arg(saveFilePath).arg(tempFile.errorString()));
}
} while(saveError); // if the file could not be overwritten, ask for new file
}
QFile::remove(tempLogfile);
}
void QGCApplication::checkTelemetrySavePathOnMainThread(void)
{
// This is called with an active vehicle so don't pop message boxes which holds ui thread
_checkTelemetrySavePath(false /* useMessageBox */);
}
bool QGCApplication::_checkTelemetrySavePath(bool useMessageBox)
{
QString errorTitle = tr("Telemetry save error");
QString saveDirPath = _toolbox->settingsManager()->appSettings()->telemetrySavePath()->rawValue().toString();
if (saveDirPath.isEmpty()) {
QString error = tr("Unable to save telemetry log. Telemetry save directory is not set.");
if (useMessageBox) {
QGCMessageBox::warning(errorTitle, error);
} else {
showMessage(error);
}
return false;
}
QDir saveDir(saveDirPath);
if (!saveDir.exists()) {
QString error = tr("Unable to save telemetry log. Telemetry save directory \"%1\" does not exist.").arg(saveDirPath);
if (useMessageBox) {
QGCMessageBox::warning(errorTitle, error);
} else {
showMessage(error);
}
return false;
}
return true;
}
#endif
void QGCApplication::_loadCurrentStyleSheet(void)
......
......@@ -116,8 +116,11 @@ public slots:
void qmlAttemptWindowClose(void);
#ifndef __mobile__
/// Save the specified Flight Data Log
void saveTempFlightDataLogOnMainThread(QString tempLogfile);
/// Save the specified telemetry Log
void saveTelemetryLogOnMainThread(QString tempLogfile);
/// Check that the telemetry save path is set correctly
void checkTelemetrySavePathOnMainThread(void);
#endif
signals:
......@@ -150,6 +153,8 @@ public:
/// Shutdown the application object
void _shutdown(void);
bool _checkTelemetrySavePath(bool useMessageBox);
private slots:
void _missingParamsDisplay(void);
......
......@@ -64,15 +64,15 @@
},
{
"name": "PromptFLightDataSave",
"shortDescription": "Prompt to save Flight Data Log after each flight",
"longDescription": "If this option is enabled you will be prompted to save Flight Data Log after each flight completes.",
"shortDescription": "Save telemetry Log after each flight",
"longDescription": "If this option is enabled a telemetry will be saved after each flight completes.",
"type": "bool",
"defaultValue": true
},
{
"name": "PromptFLightDataSaveNotArmed",
"shortDescription": "Prompt to save Flight Data Log even if vehicle was not armed",
"longDescription": "If this option is enabled you will be prompted to save Flight Data Log even if vehicle was never armed.",
"shortDescription": "Save telemetry log even if vehicle was not armed",
"longDescription": "If this option is enabled a telemtry log will be saved even if vehicle was never armed.",
"type": "bool",
"defaultValue": false
},
......@@ -114,5 +114,12 @@
"longDescription": "Show large compass on instrument panel",
"type": "bool",
"defaultValue": false
},
{
"name": "TelemetrySavePath",
"shortDescription": "Telemetry log save directory",
"longDescription": "The directory to which telemetry logs are automatically saved to.",
"type": "string",
"defaultValue": ""
}
]
......@@ -22,13 +22,14 @@ const char* AppSettings::offlineEditingHoverSpeedSettingsName = "Offline
const char* AppSettings::batteryPercentRemainingAnnounceSettingsName = "batteryPercentRemainingAnnounce";
const char* AppSettings::defaultMissionItemAltitudeSettingsName = "DefaultMissionItemAltitude";
const char* AppSettings::missionAutoLoadDirSettingsName = "MissionAutoLoadDir";
const char* AppSettings::promptFlightTelemetrySaveName = "PromptFLightDataSave";
const char* AppSettings::promptFlightTelemetrySaveNotArmedName = "PromptFLightDataSaveNotArmed";
const char* AppSettings::telemetrySaveName = "PromptFLightDataSave";
const char* AppSettings::telemetrySaveNotArmedName = "PromptFLightDataSaveNotArmed";
const char* AppSettings::audioMutedName = "AudioMuted";
const char* AppSettings::virtualJoystickName = "VirtualTabletJoystick";
const char* AppSettings::appFontPointSizeName = "BaseDeviceFontPointSize";
const char* AppSettings::indoorPaletteName = "StyleIsDark";
const char* AppSettings::showLargeCompassName = "ShowLargeCompass";
const char* AppSettings::telemetrySavePathName = "TelemetrySavePath";
AppSettings::AppSettings(QObject* parent)
: SettingsGroup(appSettingsGroupName, QString() /* root settings group */, parent)
......@@ -39,13 +40,14 @@ AppSettings::AppSettings(QObject* parent)
, _batteryPercentRemainingAnnounceFact(NULL)
, _defaultMissionItemAltitudeFact(NULL)
, _missionAutoLoadDirFact(NULL)
, _promptFlightTelemetrySaveFact(NULL)
, _promptFlightTelemetrySaveNotArmedFact(NULL)
, _telemetrySaveFact(NULL)
, _telemetrySaveNotArmedFact(NULL)
, _audioMutedFact(NULL)
, _virtualJoystickFact(NULL)
, _appFontPointSizeFact(NULL)
, _indoorPaletteFact(NULL)
, _showLargeCompassFact(NULL)
, _telemetrySavePathFact(NULL)
{
QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
qmlRegisterUncreatableType<AppSettings>("QGroundControl.SettingsManager", 1, 0, "AppSettings", "Reference only");
......@@ -113,22 +115,22 @@ Fact* AppSettings::missionAutoLoadDir(void)
return _missionAutoLoadDirFact;
}
Fact* AppSettings::promptFlightTelemetrySave(void)
Fact* AppSettings::telemetrySave(void)
{
if (!_promptFlightTelemetrySaveFact) {
_promptFlightTelemetrySaveFact = _createSettingsFact(promptFlightTelemetrySaveName);
if (!_telemetrySaveFact) {
_telemetrySaveFact = _createSettingsFact(telemetrySaveName);
}
return _promptFlightTelemetrySaveFact;
return _telemetrySaveFact;
}
Fact* AppSettings::promptFlightTelemetrySaveNotArmed(void)
Fact* AppSettings::telemetrySaveNotArmed(void)
{
if (!_promptFlightTelemetrySaveNotArmedFact) {
_promptFlightTelemetrySaveNotArmedFact = _createSettingsFact(promptFlightTelemetrySaveNotArmedName);
if (!_telemetrySaveNotArmedFact) {
_telemetrySaveNotArmedFact = _createSettingsFact(telemetrySaveNotArmedName);
}
return _promptFlightTelemetrySaveNotArmedFact;
return _telemetrySaveNotArmedFact;
}
Fact* AppSettings::audioMuted(void)
......@@ -183,3 +185,12 @@ Fact* AppSettings::showLargeCompass(void)
return _showLargeCompassFact;
}
Fact* AppSettings::telemetrySavePath(void)
{
if (!_telemetrySavePathFact) {
_telemetrySavePathFact = _createSettingsFact(telemetrySavePathName);
}
return _telemetrySavePathFact;
}
......@@ -26,13 +26,14 @@ public:
Q_PROPERTY(Fact* batteryPercentRemainingAnnounce READ batteryPercentRemainingAnnounce CONSTANT)
Q_PROPERTY(Fact* defaultMissionItemAltitude READ defaultMissionItemAltitude CONSTANT)
Q_PROPERTY(Fact* missionAutoLoadDir READ missionAutoLoadDir CONSTANT)
Q_PROPERTY(Fact* promptFlightTelemetrySave READ promptFlightTelemetrySave CONSTANT)
Q_PROPERTY(Fact* promptFlightTelemetrySaveNotArmed READ promptFlightTelemetrySaveNotArmed CONSTANT)
Q_PROPERTY(Fact* telemetrySave READ telemetrySave CONSTANT)
Q_PROPERTY(Fact* telemetrySaveNotArmed READ telemetrySaveNotArmed CONSTANT)
Q_PROPERTY(Fact* audioMuted READ audioMuted CONSTANT)
Q_PROPERTY(Fact* virtualJoystick READ virtualJoystick CONSTANT)
Q_PROPERTY(Fact* appFontPointSize READ appFontPointSize CONSTANT)
Q_PROPERTY(Fact* indoorPalette READ indoorPalette CONSTANT)
Q_PROPERTY(Fact* showLargeCompass READ showLargeCompass CONSTANT)
Q_PROPERTY(Fact* telemetrySavePath READ telemetrySavePath CONSTANT)
Fact* offlineEditingFirmwareType (void);
Fact* offlineEditingVehicleType (void);
......@@ -41,13 +42,14 @@ public:
Fact* batteryPercentRemainingAnnounce (void);
Fact* defaultMissionItemAltitude (void);
Fact* missionAutoLoadDir (void);
Fact* promptFlightTelemetrySave (void);
Fact* promptFlightTelemetrySaveNotArmed (void);
Fact* telemetrySave (void);
Fact* telemetrySaveNotArmed (void);
Fact* audioMuted (void);
Fact* virtualJoystick (void);
Fact* appFontPointSize (void);
Fact* indoorPalette (void);
Fact* showLargeCompass (void);
Fact* telemetrySavePath (void);
static const char* appSettingsGroupName;
......@@ -58,13 +60,14 @@ public:
static const char* batteryPercentRemainingAnnounceSettingsName;
static const char* defaultMissionItemAltitudeSettingsName;
static const char* missionAutoLoadDirSettingsName;
static const char* promptFlightTelemetrySaveName;
static const char* promptFlightTelemetrySaveNotArmedName;
static const char* telemetrySaveName;
static const char* telemetrySaveNotArmedName;
static const char* audioMutedName;
static const char* virtualJoystickName;
static const char* appFontPointSizeName;
static const char* indoorPaletteName;
static const char* showLargeCompassName;
static const char* telemetrySavePathName;
private slots:
void _indoorPaletteChanged(void);
......@@ -77,13 +80,14 @@ private:
SettingsFact* _batteryPercentRemainingAnnounceFact;
SettingsFact* _defaultMissionItemAltitudeFact;
SettingsFact* _missionAutoLoadDirFact;
SettingsFact* _promptFlightTelemetrySaveFact;
SettingsFact* _promptFlightTelemetrySaveNotArmedFact;
SettingsFact* _telemetrySaveFact;
SettingsFact* _telemetrySaveNotArmedFact;
SettingsFact* _audioMutedFact;
SettingsFact* _virtualJoystickFact;
SettingsFact* _appFontPointSizeFact;
SettingsFact* _indoorPaletteFact;
SettingsFact* _showLargeCompassFact;
SettingsFact* _telemetrySavePathFact;
};
#endif
......@@ -103,9 +103,10 @@ void MAVLinkProtocol::setToolbox(QGCToolbox *toolbox)
}
}
connect(this, &MAVLinkProtocol::protocolStatusMessage, _app, &QGCApplication::criticalMessageBoxOnMainThread);
connect(this, &MAVLinkProtocol::protocolStatusMessage, _app, &QGCApplication::criticalMessageBoxOnMainThread);
#ifndef __mobile__
connect(this, &MAVLinkProtocol::saveTempFlightDataLog, _app, &QGCApplication::saveTempFlightDataLogOnMainThread);
connect(this, &MAVLinkProtocol::saveTelemetryLog, _app, &QGCApplication::saveTelemetryLogOnMainThread);
connect(this, &MAVLinkProtocol::checkTelemetrySavePath, _app, &QGCApplication::checkTelemetrySavePathOnMainThread);
#endif
connect(_multiVehicleManager->vehicles(), &QmlObjectListModel::countChanged, this, &MAVLinkProtocol::_vehicleCountChanged);
......@@ -413,6 +414,7 @@ void MAVLinkProtocol::_startLogging(void)
}
qDebug() << "Temp log" << _tempLogFile.fileName();
emit checkTelemetrySavePath();
_logSuspendError = false;
}
......@@ -424,8 +426,8 @@ void MAVLinkProtocol::_stopLogging(void)
if (_closeLogFile()) {
// If the signals are not connected it means we are running a unit test. In that case just delete log files
SettingsManager* settingsManager = _app->toolbox()->settingsManager();
if ((_vehicleWasArmed || settingsManager->appSettings()->promptFlightTelemetrySaveNotArmed()->rawValue().toBool()) && settingsManager->appSettings()->promptFlightTelemetrySave()->rawValue().toBool()) {
emit saveTempFlightDataLog(_tempLogFile.fileName());
if ((_vehicleWasArmed || settingsManager->appSettings()->telemetrySaveNotArmed()->rawValue().toBool()) && settingsManager->appSettings()->telemetrySave()->rawValue().toBool()) {
emit saveTelemetryLog(_tempLogFile.fileName());
} else {
QFile::remove(_tempLogFile.fileName());
}
......@@ -452,12 +454,7 @@ void MAVLinkProtocol::checkForLostLogFiles(void)
continue;
}
// Give the user a chance to save the orphaned log file
emit protocolStatusMessage(tr("Found unsaved Flight Data"),
tr("This can happen if QGroundControl crashes during Flight Data collection. "
"If you want to save the unsaved Flight Data, select the file you want to save it to. "
"If you do not want to keep the Flight Data, select 'Cancel' on the next dialog."));
emit saveTempFlightDataLog(fileInfo.filePath());
emit saveTelemetryLog(fileInfo.filePath());
}
}
......
......@@ -158,8 +158,11 @@ signals:
void radioStatusChanged(LinkInterface* link, unsigned rxerrors, unsigned fixed, int rssi, int remrssi,
unsigned txbuf, unsigned noise, unsigned remnoise);
/// @brief Emitted when a temporary log file is ready for saving
void saveTempFlightDataLog(QString tempLogfile);
/// Emitted when a temporary telemetry log file is ready for saving
void saveTelemetryLog(QString tempLogfile);
/// Emitted when a telemetry log is started to save.
void checkTelemetrySavePath(void);
private slots:
void _vehicleCountChanged(int count);
......
......@@ -37,6 +37,8 @@ QGCView {
property Fact _appFontPointSize: QGroundControl.settingsManager.appSettings.appFontPointSize
property real _labelWidth: ScreenTools.defaultFontPixelWidth * 15
property real _editFieldWidth: ScreenTools.defaultFontPixelWidth * 30
property Fact _telemPath: QGroundControl.settingsManager.appSettings.telemetrySavePath
property Fact _videoPath: QGroundControl.settingsManager.videoSettings.videoSavePath
readonly property string _requiresRestart: qsTr("(Requires Restart)")
......@@ -205,26 +207,61 @@ QGCView {
property Fact _audioMuted: QGroundControl.settingsManager.appSettings.audioMuted
}
//-----------------------------------------------------------------
//-- Prompt Save Log
//-- Save telemetry log
FactCheckBox {
id: promptSaveLog
text: qsTr("Prompt to save Flight Data Log after each flight")
fact: _promptFlightTelemetrySave
visible: !ScreenTools.isMobile && _promptFlightTelemetrySave.visible
text: qsTr("Save telemetry log after each flight")
fact: _telemetrySave
visible: !ScreenTools.isMobile && _telemetrySave.visible
property Fact _promptFlightTelemetrySave: QGroundControl.settingsManager.appSettings.promptFlightTelemetrySave
property Fact _telemetrySave: QGroundControl.settingsManager.appSettings.telemetrySave
}
//-----------------------------------------------------------------
//-- Prompt Save even if not armed
//-- Save even if not armed
FactCheckBox {
text: qsTr("Prompt to save Flight Data Log even if vehicle was not armed")
fact: _promptFlightTelemetrySaveNotArmed
visible: !ScreenTools.isMobile && _promptFlightTelemetrySaveNotArmed.visible
text: qsTr("Save telemetry log even if vehicle was not armed")
fact: _telemetrySaveNotArmed
visible: !ScreenTools.isMobile && _telemetrySaveNotArmed.visible
enabled: promptSaveLog.checked
property Fact _promptFlightTelemetrySaveNotArmed: QGroundControl.settingsManager.appSettings.promptFlightTelemetrySaveNotArmed
property Fact _telemetrySaveNotArmed: QGroundControl.settingsManager.appSettings.telemetrySaveNotArmed
}
//-----------------------------------------------------------------
//-- Telemetry save path
Row {
spacing: ScreenTools.defaultFontPixelWidth
visible: QGroundControl.settingsManager.appSettings.telemetrySavePath.visible
QGCLabel {
anchors.baseline: telemBrowse.baseline
text: qsTr("Telemetry save path:")
enabled: promptSaveLog.checked
}
QGCLabel {
anchors.baseline: telemBrowse.baseline
text: _telemPath.value == "" ? qsTr("<not set>") : _telemPath.value
enabled: promptSaveLog.checked
}
QGCButton {
id: telemBrowse
text: "Browse"
enabled: promptSaveLog.checked
onClicked: telemDialog.visible = true
FileDialog {
id: telemDialog
title: "Choose a location to save telemetry files."
folder: "file://" + _telemPath.value
selectFolder: true
onAccepted: _telemPath.value = QGroundControl.urlToLocalFile(telemDialog.fileUrl)
}
}
}
//-----------------------------------------------------------------
//-- Clear settings
QGCCheckBox {
......@@ -329,7 +366,7 @@ QGCView {
FileDialog {
id: autoloadDirPicker
title: qsTr("Choose the location of mission file.")
folder: shortcuts.home
folder: "file://" + _autoLoadDir.value
selectFolder: true
onAccepted: _autoLoadDir.rawValue = QGroundControl.urlToLocalFile(autoloadDirPicker.fileUrl)
}
......@@ -529,26 +566,27 @@ QGCView {
Row {
spacing: ScreenTools.defaultFontPixelWidth
visible: QGroundControl.settingsManager.videoSettings.videoSavePath.visible && QGroundControl.videoManager.isGStreamer && QGroundControl.videoManager.recordingEnabled
QGCLabel {
anchors.baseline: pathField.baseline
text: qsTr("Save Path:")
width: _labelWidth
anchors.baseline: videoBrowse.baseline
text: qsTr("Save path:")
enabled: promptSaveLog.checked
}
FactTextField {
id: pathField
width: _editFieldWidth
fact: QGroundControl.settingsManager.videoSettings.videoSavePath
QGCLabel {
anchors.baseline: videoBrowse.baseline
text: _videoPath.value == "" ? qsTr("<not set>") : _videoPath.value
}
QGCButton {
id: videoBrowse
text: "Browse"
onClicked: videoLocationFileDialog.visible = true
onClicked: videoDialog.visible = true
FileDialog {
id: videoLocationFileDialog
id: videoDialog
title: "Choose a location to save video files."
folder: shortcuts.home
folder: "file://" + _videoPath.value
selectFolder: true
onAccepted: QGroundControl.settingsManager.videoSettings.videoSavePath.value = QGroundControl.urlToLocalFile(videoLocationFileDialog.fileUrl)
onAccepted: _videoPath.value = QGroundControl.urlToLocalFile(videoDialog.fileUrl)
}
}
}
......
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