Commit d3ad49f3 authored by Don Gagne's avatar Don Gagne

Moving more things off of MainWindow

Moving methods from MainWindow to QGCApplication so that more things
can run without a window. Helpful for testing.
parent d2cc809e
......@@ -27,6 +27,9 @@ This file is part of the QGROUNDCONTROL project
*
*/
#include "LogCompressor.h"
#include "QGCApplication.h"
#include <QFile>
#include <QFileInfo>
#include <QDir>
......@@ -34,8 +37,6 @@ This file is part of the QGROUNDCONTROL project
#include <QStringList>
#include <QFileInfo>
#include <QList>
#include "LogCompressor.h"
#include <QDebug>
/**
......@@ -50,6 +51,7 @@ LogCompressor::LogCompressor(QString logFileName, QString outFileName, QString d
delimiter(delimiter),
holeFillingEnabled(true)
{
connect(this, &LogCompressor::logProcessingCriticalError, qgcApp(), &QGCApplication::criticalMessageBoxOnMainThread);
}
void LogCompressor::run()
......@@ -57,7 +59,7 @@ void LogCompressor::run()
// Verify that the input file is useable
QFile infile(logFileName);
if (!infile.exists() || !infile.open(QIODevice::ReadOnly | QIODevice::Text)) {
emit logProcessingStatusChanged(tr("Log Compressor: Cannot start/compress log file, since input file %1 is not readable").arg(QFileInfo(infile.fileName()).absoluteFilePath()));
_signalCriticalError(tr("Log Compressor: Cannot start/compress log file, since input file %1 is not readable").arg(QFileInfo(infile.fileName()).absoluteFilePath()));
return;
}
......@@ -74,7 +76,7 @@ void LogCompressor::run()
// Verify that the output file is useable
QFile outTmpFile(outFileName);
if (!outTmpFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
emit logProcessingStatusChanged(tr("Log Compressor: Cannot start/compress log file, since output file %1 is not writable").arg(QFileInfo(outTmpFile.fileName()).absoluteFilePath()));
_signalCriticalError(tr("Log Compressor: Cannot start/compress log file, since output file %1 is not writable").arg(QFileInfo(outTmpFile.fileName()).absoluteFilePath()));
return;
}
......@@ -112,7 +114,7 @@ void LogCompressor::run()
headerLine = headerLine.replace(".", "");
outTmpFile.write(headerLine.toLocal8Bit());
emit logProcessingStatusChanged(tr("Log compressor: Dataset contains dimensions: ") + headerLine);
_signalCriticalError(tr("Log compressor: Dataset contains dimensions: ") + headerLine);
// Template list stores a list for populating with data as it's parsed from messages.
QStringList templateList;
......@@ -191,11 +193,8 @@ void LogCompressor::run()
// We're now done with the source file
infile.close();
emit logProcessingStatusChanged(tr("Log Compressor: Writing output to file %1").arg(QFileInfo(outFileName).absoluteFilePath()));
// Clean up and update the status before we return.
currentDataLine = 0;
emit logProcessingStatusChanged(tr("Log compressor: Finished processing file: %1").arg(outFileName));
emit finishedFile(outFileName);
running = false;
}
......@@ -219,3 +218,9 @@ int LogCompressor::getCurrentLine()
{
return currentDataLine;
}
void LogCompressor::_signalCriticalError(const QString& msg)
{
emit logProcessingCriticalError(tr("Log Compressor"), msg);
}
......@@ -24,15 +24,18 @@ protected:
bool holeFillingEnabled; ///< Enables the filling of holes in the dataset with the previous value (or NaN if none exists)
signals:
/** @brief This signal is emitted when there is a change in the status of the parsing algorithm. For instance if an error is encountered.
* @param status A status message
*/
void logProcessingStatusChanged(QString status);
/** @brief This signal is emitted once a logfile has been finished writing
* @param fileName The name of the output (CSV) file
*/
void finishedFile(QString fileName);
/// This signal is connected to QGCApplication::showCriticalMessage to show critical errors which come from the thread.
/// There is no need for clients to connect to this signal.
void logProcessingCriticalError(const QString& title, const QString& msg);
private:
void _signalCriticalError(const QString& msg);
};
#endif // LOGCOMPRESSOR_H
\ No newline at end of file
......@@ -56,6 +56,7 @@
#include "UASManager.h"
#include "AutoPilotPluginManager.h"
#include "QGCTemporaryFile.h"
#include "QGCFileDialog.h"
#ifdef QGC_RTLAB_ENABLED
#include "OpalLink.h"
......@@ -313,6 +314,10 @@ bool QGCApplication::_initForNormalAppBoot(void)
}
}
// Now that main window is upcheck for lost log files
connect(this, &QGCApplication::checkForLostLogFiles, MAVLinkProtocol::instance(), &MAVLinkProtocol::checkForLostLogFiles);
emit checkForLostLogFiles();
return true;
}
......@@ -482,3 +487,30 @@ void QGCApplication::_destroySingletons(void)
LinkManager::_deleteSingleton();
GAudioOutput::_deleteSingleton();
}
void QGCApplication::informationMessageBoxOnMainThread(const QString& title, const QString& msg)
{
QGCMessageBox::information(title, msg);
}
void QGCApplication::warningMessageBoxOnMainThread(const QString& title, const QString& msg)
{
QGCMessageBox::warning(title, msg);
}
void QGCApplication::criticalMessageBoxOnMainThread(const QString& title, const QString& msg)
{
QGCMessageBox::critical(title, msg);
}
void QGCApplication::saveTempFlightDataLogOnMainThread(QString tempLogfile)
{
QString saveFilename = QGCFileDialog::getSaveFileName(MainWindow::instance(),
tr("Select file to save Flight Data Log"),
qgcApp()->mavlinkLogFilesLocation(),
tr("Flight Data Log (*.mavlink)"));
if (!saveFilename.isEmpty()) {
QFile::copy(tempLogfile, saveFilename);
}
QFile::remove(tempLogfile);
}
......@@ -87,7 +87,27 @@ public:
/// @brief Returns truee if unit test are being run
bool runningUnitTests(void) { return _runningUnitTests; }
public slots:
/// You can connect to this slot to show an information message box from a different thread.
void informationMessageBoxOnMainThread(const QString& title, const QString& msg);
/// You can connect to this slot to show a warning message box from a different thread.
void warningMessageBoxOnMainThread(const QString& title, const QString& msg);
/// You can connect to this slot to show a critical message box from a different thread.
void criticalMessageBoxOnMainThread(const QString& title, const QString& msg);
/// Save the specified Flight Data Log
void saveTempFlightDataLogOnMainThread(QString tempLogfile);
signals:
/// This is connected to MAVLinkProtocol::checkForLostLogFiles. We signal this to ourselves to call the slot
/// on the MAVLinkProtocol thread;
void checkForLostLogFiles(void);
public:
// Although public, these methods are internal and should only be called by UnitTest code
/// @brief Perform initialize which is common to both normal application running and unit tests.
/// Although public should only be called by main.
void _initCommon(void);
......
......@@ -108,6 +108,8 @@ void QGCFileDialog::_validate(QString* selectedFilter, Options& options)
// You can't use QGCFileDialog if QGCApplication is not created yet.
Q_ASSERT(qgcApp());
Q_ASSERT_X(QThread::currentThread() == qgcApp()->thread(), "Threading issue", "QGCFileDialog can only be called from main thread");
// Support for selectedFilter is not yet implemented through the unit test framework
Q_UNUSED(selectedFilter);
Q_ASSERT(selectedFilter == NULL);
......
......@@ -92,10 +92,15 @@ private:
// You can't use QGCMessageBox if QGCApplication is not created yet.
Q_ASSERT(qgcApp());
Q_ASSERT_X(QThread::currentThread() == qgcApp()->thread(), "Threading issue", "QGCMessageBox can only be called from main thread");
parent = _validateParameters(buttons, &defaultButton, parent);
if (MainWindow::instance()) {
MainWindow::instance()->hideSplashScreen();
if (parent == NULL) {
parent = MainWindow::instance();
}
}
#ifdef QT_DEBUG
......
......@@ -192,7 +192,7 @@ signals:
void nameChanged(QString name);
/** @brief Communication error occured */
void communicationError(const QString& linkname, const QString& error);
void communicationError(const QString& title, const QString& error);
void communicationUpdate(const QString& linkname, const QString& text);
......
......@@ -76,7 +76,7 @@ void LinkManager::addLink(LinkInterface* link)
// MainWindow may be around when doing things like running unit tests
if (MainWindow::instance()) {
connect(link, SIGNAL(communicationError(QString,QString)), MainWindow::instance(), SLOT(showCriticalMessage(QString,QString)), Qt::QueuedConnection);
connect(link, &LinkInterface::communicationError, qgcApp(), &QGCApplication::criticalMessageBoxOnMainThread);
}
MAVLinkProtocol* mavlink = MAVLinkProtocol::instance();
......
......@@ -56,8 +56,6 @@ MAVLinkProtocol::MAVLinkProtocol(QObject* parent) :
_logSuspendError(false),
_logSuspendReplay(false),
_tempLogFile(QString("%2.%3").arg(_tempLogFileTemplate).arg(_logFileExtension)),
_protocolStatusMessageConnected(false),
_saveTempFlightDataLogConnected(false),
_linkMgr(LinkManager::instance()),
_heartbeatRate(MAVLINK_HEARTBEAT_DEFAULT_RATE),
_heartbeatsEnabled(true)
......@@ -83,6 +81,9 @@ MAVLinkProtocol::MAVLinkProtocol(QObject* parent) :
connect(&_heartbeatTimer, &QTimer::timeout, this, &MAVLinkProtocol::sendHeartbeat);
_heartbeatTimer.start(1000/_heartbeatRate);
connect(this, &MAVLinkProtocol::protocolStatusMessage, qgcApp(), &QGCApplication::criticalMessageBoxOnMainThread);
connect(this, &MAVLinkProtocol::saveTempFlightDataLog, qgcApp(), &QGCApplication::saveTempFlightDataLogOnMainThread);
emit versionCheckChanged(m_enable_version_check);
}
......@@ -233,7 +234,10 @@ void MAVLinkProtocol::receiveBytes(LinkInterface* link, QByteArray b)
warnedUser = true;
// Obviously the user tries to use a 0.9 autopilot
// with QGroundControl built for version 1.0
emit protocolStatusMessage("MAVLink Version or Baud Rate Mismatch", "Your MAVLink device seems to use the deprecated version 0.9, while QGroundControl only supports version 1.0+. Please upgrade the MAVLink version of your autopilot. If your autopilot is using version 1.0, check if the baud rates of QGroundControl and your autopilot are the same.");
emit protocolStatusMessage(tr("MAVLink Protocol"), tr("There is a MAVLink Version or Baud Rate Mismatch. "
"Your MAVLink device seems to use the deprecated version 0.9, while QGroundControl only supports version 1.0+. "
"Please upgrade the MAVLink version of your autopilot. "
"If your autopilot is using version 1.0, check if the baud rates of QGroundControl and your autopilot are the same."));
}
if (decodeState == 0 && !decodedFirstPacket)
......@@ -250,7 +254,8 @@ void MAVLinkProtocol::receiveBytes(LinkInterface* link, QByteArray b)
else
{
warnedUserNonMavlink = true;
emit protocolStatusMessage("MAVLink Baud Rate Mismatch", "Please check if the baud rates of QGroundControl and your autopilot are the same.");
emit protocolStatusMessage(tr("MAVLink Protocol"), tr("There is a MAVLink Version or Baud Rate Mismatch. "
"Please check if the baud rates of QGroundControl and your autopilot are the same."));
}
}
}
......@@ -303,7 +308,7 @@ void MAVLinkProtocol::receiveBytes(LinkInterface* link, QByteArray b)
if(_tempLogFile.write(b) != len)
{
// If there's an error logging data, raise an alert and stop logging.
emit protocolStatusMessage(tr("MAVLink Logging failed"), tr("Could not write to file %1, logging disabled.").arg(_tempLogFile.fileName()));
emit protocolStatusMessage(tr("MAVLink Protocol"), tr("MAVLink Logging failed. Could not write to file %1, logging disabled.").arg(_tempLogFile.fileName()));
_stopLogging();
_logSuspendError = true;
}
......@@ -327,7 +332,7 @@ void MAVLinkProtocol::receiveBytes(LinkInterface* link, QByteArray b)
// Check if the UAS has the same id like this system
if (message.sysid == getSystemId())
{
emit protocolStatusMessage(tr("SYSTEM ID CONFLICT!"), tr("Warning: A second system is using the same system id (%1)").arg(getSystemId()));
emit protocolStatusMessage(tr("MAVLink Protocol"), tr("Warning: A second system is using the same system id (%1)").arg(getSystemId()));
}
// Create a new UAS based on the heartbeat received
......@@ -347,8 +352,9 @@ void MAVLinkProtocol::receiveBytes(LinkInterface* link, QByteArray b)
// Bring up dialog to inform user
if (!versionMismatchIgnore)
{
emit protocolStatusMessage(tr("The MAVLink protocol version on the MAV and QGroundControl mismatch!"),
tr("It is unsafe to use different MAVLink versions. QGroundControl therefore refuses to connect to system %1, which sends MAVLink version %2 (QGroundControl uses version %3).").arg(message.sysid).arg(heartbeat.mavlink_version).arg(MAVLINK_VERSION));
emit protocolStatusMessage(tr("MAVLink Protocol"), tr("The MAVLink protocol version on the MAV and QGroundControl mismatch! "
"It is unsafe to use different MAVLink versions. "
"QGroundControl therefore refuses to connect to system %1, which sends MAVLink version %2 (QGroundControl uses version %3).").arg(message.sysid).arg(heartbeat.mavlink_version).arg(MAVLINK_VERSION));
versionMismatchIgnore = true;
}
......@@ -649,8 +655,8 @@ void MAVLinkProtocol::_startLogging(void)
if (!_logSuspendReplay) {
if (!_tempLogFile.open()) {
emit protocolStatusMessage(tr("Opening Flight Data file for writing failed"),
tr("Unable to write to %1. Please choose a different file location.").arg(_tempLogFile.fileName()));
emit protocolStatusMessage(tr("MAVLink Protocol"), tr("Opening Flight Data file for writing failed. "
"Unable to write to %1. Please choose a different file location.").arg(_tempLogFile.fileName()));
_closeLogFile();
_logSuspendError = true;
return;
......@@ -666,7 +672,7 @@ 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
if (_protocolStatusMessageConnected && _saveTempFlightDataLogConnected && qgcApp()->promptFlightDataSave()) {
if (qgcApp()->promptFlightDataSave()) {
emit saveTempFlightDataLog(_tempLogFile.fileName());
} else {
QFile::remove(_tempLogFile.fileName());
......@@ -674,28 +680,10 @@ void MAVLinkProtocol::_stopLogging(void)
}
}
/// @brief We override this virtual from QObject so that we can track when the
/// protocolStatusMessage and saveTempFlightDataLog signals are connected.
/// Once both are connected we can check for lost log files.
void MAVLinkProtocol::connectNotify(const QMetaMethod& signal)
{
if (signal == QMetaMethod::fromSignal(&MAVLinkProtocol::protocolStatusMessage)) {
_protocolStatusMessageConnected = true;
if (_saveTempFlightDataLogConnected) {
_checkLostLogFiles();
}
} else if (signal == QMetaMethod::fromSignal(&MAVLinkProtocol::saveTempFlightDataLog)) {
_saveTempFlightDataLogConnected = true;
if (_protocolStatusMessageConnected) {
_checkLostLogFiles();
}
}
}
/// @brief Checks the temp directory for log files which may have been left there.
/// This could happen if QGC crashes without the temp log file being saved.
/// Give the user an option to save these orphaned files.
void MAVLinkProtocol::_checkLostLogFiles(void)
void MAVLinkProtocol::checkForLostLogFiles(void)
{
QDir tempDir(QStandardPaths::writableLocation(QStandardPaths::TempLocation));
......
......@@ -205,11 +205,11 @@ public slots:
/// @brief Deletes any log files which are in the temp directory
static void deleteTempLogFiles(void);
/// Checks for lost log files
void checkForLostLogFiles(void);
protected:
// Override from QObject
virtual void connectNotify(const QMetaMethod& signal);
protected:
bool m_multiplexingEnabled; ///< Enable/disable packet multiplexing
bool m_authEnabled; ///< Enable authentication token broadcast
QString m_authKey; ///< Authentication key
......@@ -284,7 +284,6 @@ private:
bool _closeLogFile(void);
void _startLogging(void);
void _stopLogging(void);
void _checkLostLogFiles(void);
QList<LinkInterface*> _connectedLinks; ///< List of all links connected to protocol
......@@ -295,9 +294,6 @@ private:
static const char* _tempLogFileTemplate; ///< Template for temporary log file
static const char* _logFileExtension; ///< Extension for log files
bool _protocolStatusMessageConnected; ///< true: protocolStatusMessage signal has been connected
bool _saveTempFlightDataLogConnected; ///< true: saveTempFlightDataLog signal has been connected
LinkManager* _linkMgr;
QTimer _heartbeatTimer; ///< Timer to emit heartbeats
......
......@@ -41,7 +41,6 @@ This file is part of the QGROUNDCONTROL project
#include "QGCFlightGearLink.h"
#include "QGC.h"
#include "MainWindow.h"
#include "QGCFileDialog.h"
#include "QGCMessageBox.h"
......@@ -553,7 +552,7 @@ bool QGCFlightGearLink::parseUIArguments(QString uiArgs, QStringList& argList)
// We have a space that is finishing an argument
previousSpace = true;
if (inQuotedString) {
MainWindow::instance()->showCriticalMessage(tr("FlightGear Failed to Start"), tr("Mismatched quotes in specified command line options"));
QGCMessageBox::critical(tr("FlightGear HIL"), tr("FlightGear failed to start. There are mismatched quotes in specified command line options"));
return false;
}
if (!currentArg.isEmpty()) {
......@@ -643,7 +642,7 @@ bool QGCFlightGearLink::connectSimulation()
QStringList uiArgList;
bool mismatchedQuotes = parseUIArguments(startupArguments, uiArgList);
if (!mismatchedQuotes) {
MainWindow::instance()->showCriticalMessage(tr("FlightGear settings"), tr("Mismatched quotes in specified command line options"));
QGCMessageBox::critical(tr("FlightGear HIL"), tr("FlightGear failed to start. There are mismatched quotes in specified command line options"));
return false;
}
#ifdef DEBUG_FLIGHTGEAR_CONNECT
......@@ -798,7 +797,7 @@ bool QGCFlightGearLink::connectSimulation()
} else if (fgRootPath.isEmpty()) {
errMsg = tr("Unable to automatically determine --fg-root directory location. You will need to specify --fg-root=<directory> as an additional command line parameter from ui.");
}
MainWindow::instance()->showCriticalMessage(tr("FlightGear settings"), errMsg);
QGCMessageBox::critical(tr("FlightGear HIL"), errMsg);
return false;
}
......@@ -836,7 +835,7 @@ bool QGCFlightGearLink::connectSimulation()
// Setup and verify directory which contains QGC provided aircraft files
QString qgcAircraftDir(QApplication::applicationDirPath() + "/files/flightgear/Aircraft");
if (!QFileInfo(qgcAircraftDir).isDir()) {
MainWindow::instance()->showCriticalMessage(tr("Incorrect QGroundControl installation"), tr("Aircraft directory is missing: '%1'.").arg(qgcAircraftDir));
QGCMessageBox::critical(tr("FlightGear HIL"), tr("Incorrect QGroundControl installation. Aircraft directory is missing: '%1'.").arg(qgcAircraftDir));
return false;
}
_fgArgList += "--fg-aircraft=" + qgcAircraftDir;
......@@ -850,14 +849,14 @@ bool QGCFlightGearLink::connectSimulation()
// Verify directory where FlightGear stores communicaton protocols.
QDir fgProtocolDir(fgRootPath);
if (!fgProtocolDir.cd("Protocol")) {
MainWindow::instance()->showCriticalMessage(tr("Incorrect FlightGear setup"), tr("Protocol directory is missing: '%1'. Command line parameter for --fg-root may be set incorrectly.").arg(fgProtocolDir.path()));
QGCMessageBox::critical(tr("FlightGear HIL"), tr("Incorrect FlightGear setup. Protocol directory is missing: '%1'. Command line parameter for --fg-root may be set incorrectly.").arg(fgProtocolDir.path()));
return false;
}
// Verify directory which contains QGC provided FlightGear communication protocol files
QDir qgcProtocolDir(QApplication::applicationDirPath() + "/files/flightgear/Protocol/");
if (!qgcProtocolDir.isReadable()) {
MainWindow::instance()->showCriticalMessage(tr("Incorrect QGroundControl installation"), tr("Protocol directory is missing (%1).").arg(qgcProtocolDir.path()));
QGCMessageBox::critical(tr("FlightGear HIL"), tr("Incorrect QGroundControl installation. Protocol directory is missing (%1).").arg(qgcProtocolDir.path()));
return false;
}
......@@ -865,7 +864,7 @@ bool QGCFlightGearLink::connectSimulation()
QString fgProtocolXmlFile = fgProtocol + ".xml";
QString qgcProtocolFileFullyQualified = qgcProtocolDir.absoluteFilePath(fgProtocolXmlFile);
if (!QFileInfo(qgcProtocolFileFullyQualified).exists()) {
MainWindow::instance()->showCriticalMessage(tr("Incorrect QGroundControl installation"), tr("FlightGear protocol file missing: %1").arg(qgcProtocolFileFullyQualified));
QGCMessageBox::critical(tr("FlightGear HIL"), tr("Incorrect QGroundControl installation. FlightGear protocol file missing: %1").arg(qgcProtocolFileFullyQualified));
return false;
}
......
......@@ -33,11 +33,13 @@ This file is part of the QGROUNDCONTROL project
#include <QList>
#include <QDebug>
#include <QMutexLocker>
#include <QHostInfo>
#include <iostream>
#include "QGCJSBSimLink.h"
#include "QGC.h"
#include <QHostInfo>
#include "MainWindow.h"
#include "QGCMessageBox.h"
QGCJSBSimLink::QGCJSBSimLink(UASInterface* mav, QString startupArguments, QString remoteHost, QHostAddress host, quint16 port) :
socket(NULL),
......@@ -122,14 +124,14 @@ void QGCJSBSimLink::run()
QFileInfo executable(processJSB);
if (!executable.isExecutable())
{
MainWindow::instance()->showCriticalMessage(tr("JSBSim Failed to Start"), tr("JSBSim was not found at %1").arg(processJSB));
QGCMessageBox::critical("JSBSim", tr("JSBSim failed to start. JSBSim was not found at %1").arg(processJSB));
sane = false;
}
QFileInfo root(rootJSB);
if (!root.isDir())
{
MainWindow::instance()->showCriticalMessage(tr("JSBSim Failed to Start"), tr("JSBSim data directory was not found at %1").arg(rootJSB));
QGCMessageBox::critical("JSBSim", tr("JSBSim failed to start. JSBSim data directory was not found at %1").arg(rootJSB));
sane = false;
}
......@@ -167,28 +169,33 @@ void QGCJSBSimLink::setPort(int port)
void QGCJSBSimLink::processError(QProcess::ProcessError err)
{
switch(err)
{
case QProcess::FailedToStart:
MainWindow::instance()->showCriticalMessage(tr("JSBSim Failed to Start"), tr("Please check if the path and command is correct"));
break;
case QProcess::Crashed:
MainWindow::instance()->showCriticalMessage(tr("JSBSim Crashed"), tr("This is a FlightGear-related problem. Please upgrade FlightGear"));
break;
case QProcess::Timedout:
MainWindow::instance()->showCriticalMessage(tr("JSBSim Start Timed Out"), tr("Please check if the path and command is correct"));
break;
case QProcess::WriteError:
MainWindow::instance()->showCriticalMessage(tr("Could not Communicate with JSBSim"), tr("Please check if the path and command is correct"));
break;
case QProcess::ReadError:
MainWindow::instance()->showCriticalMessage(tr("Could not Communicate with JSBSim"), tr("Please check if the path and command is correct"));
break;
case QProcess::UnknownError:
default:
MainWindow::instance()->showCriticalMessage(tr("JSBSim Error"), tr("Please check if the path and command is correct."));
break;
QString msg;
switch(err) {
case QProcess::FailedToStart:
msg = tr("JSBSim Failed to start. Please check if the path and command is correct");
break;
case QProcess::Crashed:
msg = tr("JSBSim crashed. This is a JSBSim-related problem, check for JSBSim upgrade.");
break;
case QProcess::Timedout:
msg = tr("JSBSim start timed out. Please check if the path and command is correct");
break;
case QProcess::ReadError:
case QProcess::WriteError:
msg = tr("Could not communicate with JSBSim. Please check if the path and command are correct");
break;
case QProcess::UnknownError:
default:
msg = tr("JSBSim error occurred. Please check if the path and command is correct.");
break;
}
QGCMessageBox::critical("JSBSim HIL", msg);
}
/**
......
......@@ -39,7 +39,7 @@ This file is part of the QGROUNDCONTROL project
#include <QHostInfo>
#include "UAS.h"
#include "UASInterface.h"
#include "MainWindow.h"
#include "QGCMessageBox.h"
QGCXPlaneLink::QGCXPlaneLink(UASInterface* mav, QString remoteHost, QHostAddress localHost, quint16 localPort) :
mav(mav),
......@@ -270,28 +270,34 @@ void QGCXPlaneLink::setPort(int localPort)
void QGCXPlaneLink::processError(QProcess::ProcessError err)
{
switch(err)
{
case QProcess::FailedToStart:
MainWindow::instance()->showCriticalMessage(tr("X-Plane Failed to Start"), tr("Please check if the path and command is correct"));
break;
case QProcess::Crashed:
MainWindow::instance()->showCriticalMessage(tr("X-Plane Crashed"), tr("This is a X-Plane-related problem. Please upgrade X-Plane"));
break;
case QProcess::Timedout:
MainWindow::instance()->showCriticalMessage(tr("X-Plane Start Timed Out"), tr("Please check if the path and command is correct"));
break;
case QProcess::WriteError:
MainWindow::instance()->showCriticalMessage(tr("Could not Communicate with X-Plane"), tr("Please check if the path and command is correct"));
break;
case QProcess::ReadError:
MainWindow::instance()->showCriticalMessage(tr("Could not Communicate with X-Plane"), tr("Please check if the path and command is correct"));
break;
case QProcess::UnknownError:
default:
MainWindow::instance()->showCriticalMessage(tr("X-Plane Error"), tr("Please check if the path and command is correct."));
break;
QString msg;
switch(err) {
case QProcess::FailedToStart:
msg = tr("X-Plane Failed to start. Please check if the path and command is correct");
break;
case QProcess::Crashed:
msg = tr("X-Plane crashed. This is an X-Plane-related problem, check for X-Plane upgrade.");
break;
case QProcess::Timedout:
msg = tr("X-Plane start timed out. Please check if the path and command is correct");
break;
case QProcess::ReadError:
case QProcess::WriteError:
msg = tr("Could not communicate with X-Plane. Please check if the path and command are correct");
break;
case QProcess::UnknownError:
default:
msg = tr("X-Plane error occurred. Please check if the path and command is correct.");
break;
}
QGCMessageBox::critical(tr("X-Plane HIL"), msg);
}
QString QGCXPlaneLink::getRemoteHost()
......
......@@ -208,7 +208,7 @@ void SerialLink::run()
if (m_port) {
err = m_port->errorString();
}
emit communicationError(getName(),"Error connecting: " + err);
_emitLinkError("Error connecting: " + err);
return;
}
......@@ -348,7 +348,7 @@ void SerialLink::writeBytes(const char* data, qint64 size)
m_writeMutex.unlock();
} else {
// Error occured
emit communicationError(getName(), tr("Could not send data - link %1 is disconnected!").arg(getName()));
_emitLinkError(tr("Could not send data - link %1 is disconnected!").arg(getName()));
}
}
......@@ -902,3 +902,10 @@ void SerialLink::_rerouteDisconnected(void)
{
emit disconnected();
}
void SerialLink::_emitLinkError(const QString& errorMsg)
{
QString msg("Error on link %1. %2");
emit communicationError(tr("Link Error"), msg.arg(getName()).arg(errorMsg));
}
\ No newline at end of file
......@@ -170,6 +170,8 @@ private:
// From LinkInterface
virtual bool _connect(void);
virtual bool _disconnect(void);
void _emitLinkError(const QString& errorMsg);
volatile bool m_stopp;
volatile bool m_reqReset;
......
......@@ -232,7 +232,7 @@ bool TCPLink::_hardwareConnect(void)
// Whether a failed connection emits an error signal or not is platform specific.
// So in cases where it is not emitted, we emit one ourselves.
if (errorSpy.count() == 0) {
emit communicationError(getName(), "Connection failed");
emit communicationError(tr("Link Error"), QString("Error on link %1. Connection failed").arg(getName()));
}
delete _socket;
_socket = NULL;
......@@ -248,7 +248,7 @@ bool TCPLink::_hardwareConnect(void)
void TCPLink::_socketError(QAbstractSocket::SocketError socketError)
{
Q_UNUSED(socketError);
emit communicationError(getName(), "Error on socket: " + _socket->errorString());
emit communicationError(tr("Link Error"), QString("Error on link %1. Error on socket: %2.").arg(getName()).arg(_socket->errorString()));
}
/**
......
......@@ -204,7 +204,7 @@ void XbeeLink::writeBytes(const char *bytes, qint64 length) // TO DO: delete th
else
{
_disconnect();
emit communicationError(this->getName(), tr("Could not send data - link %1 is disconnected!").arg(this->getName()));
emit communicationError(tr("Link Error"), QString("Error on link: %1. Could not send data - link is disconnected!").arg(getName()));
}
}
......
......@@ -30,6 +30,7 @@
#include "MainWindow.h"
#include "MockLink.h"
#include "QGCTemporaryFile.h"
#include "QGCApplication.h"
UT_REGISTER_TEST(MavlinkLogTest)
......@@ -82,20 +83,18 @@ void MavlinkLogTest::_bootLogDetectionCancel_test(void)
{
// Create a fake mavlink log
_createTempLogFile(false);
// We should get a message box, followed by a getSaveFileName dialog.
setExpectedMessageBox(QMessageBox::Ok);
setExpectedFileDialog(getSaveFileName, QStringList());
MainWindow* mainWindow = MainWindow::_create(NULL, MainWindow::CUSTOM_MODE_PX4);
Q_CHECK_PTR(mainWindow);
// Kick the protocol to check for lost log files and wait for signals to move through
connect(this, &MavlinkLogTest::checkForLostLogFiles, MAVLinkProtocol::instance(), &MAVLinkProtocol::checkForLostLogFiles);
emit checkForLostLogFiles();
QTest::qWait(1000);
checkExpectedMessageBox();
checkExpectedFileDialog();
mainWindow->close();
delete mainWindow;
}
void MavlinkLogTest::_bootLogDetectionSave_test(void)
......@@ -109,18 +108,16 @@ void MavlinkLogTest::_bootLogDetectionSave_test(void)
QString logSaveFile(logSaveDir.filePath(_saveLogFilename));
setExpectedFileDialog(getSaveFileName, QStringList(logSaveFile));
MainWindow* mainWindow = MainWindow::_create(NULL, MainWindow::CUSTOM_MODE_PX4);
Q_CHECK_PTR(mainWindow);
// Kick the protocol to check for lost log files and wait for signals to move through
connect(this, &MavlinkLogTest::checkForLostLogFiles, MAVLinkProtocol::instance(), &MAVLinkProtocol::checkForLostLogFiles);
emit checkForLostLogFiles();
QTest::qWait(1000);
checkExpectedMessageBox();
checkExpectedFileDialog();
// Make sure the file is there and delete it
QCOMPARE(logSaveDir.remove(_saveLogFilename), true);
mainWindow->close();
delete mainWindow;
}
void MavlinkLogTest::_bootLogDetectionZeroLength_test(void)
......@@ -128,20 +125,16 @@ void MavlinkLogTest::_bootLogDetectionZeroLength_test(void)
// Create a fake empty mavlink log
_createTempLogFile(true);
// Zero length log files should not generate any additional UI pop-ups. It should just be deleted silently.
MainWindow* mainWindow = MainWindow::_create(NULL, MainWindow::CUSTOM_MODE_PX4);
Q_CHECK_PTR(mainWindow);
mainWindow->close();
// Kick the protocol to check for lost log files and wait for signals to move through
connect(this, &MavlinkLogTest::checkForLostLogFiles, MAVLinkProtocol::instance(), &MAVLinkProtocol::checkForLostLogFiles);
emit checkForLostLogFiles();
QTest::qWait(1000);
delete mainWindow;
// Zero length log files should not generate any additional UI pop-ups. It should just be deleted silently.
}
void MavlinkLogTest::_connectLog_test(void)
{
MainWindow* mainWindow = MainWindow::_create(NULL, MainWindow::CUSTOM_MODE_PX4);
Q_CHECK_PTR(mainWindow);
LinkManager* linkMgr = LinkManager::instance();
Q_CHECK_PTR(linkMgr);
......@@ -163,10 +156,6 @@ void MavlinkLogTest::_connectLog_test(void)
// Make sure the file is there and delete it
QCOMPARE(logSaveDir.remove(_saveLogFilename), true);
// MainWindow deletes itself on close
mainWindow->close();
QTest::qWait(1000); // Need to allow signals to move between threads to shutdown MainWindow
}
void MavlinkLogTest::_deleteTempLogFiles_test(void)
......
......@@ -48,6 +48,9 @@ private slots:
void _connectLog_test(void);
void _deleteTempLogFiles_test(void);
signals:
void checkForLostLogFiles(void);
private:
void _createTempLogFile(bool zeroLength);
......
......@@ -33,7 +33,7 @@ This file is part of the QGROUNDCONTROL project
#include "UAS.h"
#include "mavlink_types.h"
#include "UASManager.h"
#include "MainWindow.h"
#include "QGCMessageBox.h"
#define PROTOCOL_TIMEOUT_MS 2000 ///< maximum time to wait for pending messages until timeout
#define PROTOCOL_DELAY_MS 20 ///< minimum delay between sent messages
......@@ -50,8 +50,6 @@ UASWaypointManager::UASWaypointManager(UAS* _uas)
currentWaypointEditable(),
protocol_timer(this)
{
_offlineEditingModeTitle = tr("OFFLINE Waypoint Editing Mode");
_offlineEditingModeMessage = tr("You are in offline editing mode. Make sure to save your mission to a file before connecting to a system - you will need to load the file into the system, the offline list will be cleared on connect.");
if (uas)
......@@ -433,8 +431,9 @@ void UASWaypointManager::addWaypointEditable(Waypoint *wp, bool enforceFirstActi
if (wp)
{
// Check if this is the first waypoint in an offline list
if (waypointsEditable.count() == 0 && uas == NULL)
MainWindow::instance()->showCriticalMessage(_offlineEditingModeTitle, _offlineEditingModeMessage);
if (waypointsEditable.count() == 0 && uas == NULL) {
QGCMessageBox::critical(tr("Waypoint Manager"), _offlineEditingModeMessage);
}
wp->setId(waypointsEditable.count());
if (enforceFirstActive && waypointsEditable.count() == 0)
......@@ -456,8 +455,9 @@ void UASWaypointManager::addWaypointEditable(Waypoint *wp, bool enforceFirstActi
Waypoint* UASWaypointManager::createWaypoint(bool enforceFirstActive)
{
// Check if this is the first waypoint in an offline list
if (waypointsEditable.count() == 0 && uas == NULL)
MainWindow::instance()->showCriticalMessage(_offlineEditingModeTitle, _offlineEditingModeMessage);
if (waypointsEditable.count() == 0 && uas == NULL) {
QGCMessageBox::critical(tr("Waypoint Manager"), _offlineEditingModeMessage);
}
Waypoint* wp = new Waypoint();
wp->setId(waypointsEditable.count());
......
......@@ -190,7 +190,6 @@ private:
// XXX export to settings
static const float defaultAltitudeHomeOffset; ///< Altitude offset in meters from home for new waypoints
QString _offlineEditingModeTitle;
QString _offlineEditingModeMessage;
};
......
......@@ -128,10 +128,7 @@ MainWindow::MainWindow(QSplashScreen* splashScreen, enum MainWindow::CUSTOM_MODE
}
connect(menuActionHelper, SIGNAL(needToShowDockWidget(QString,bool)),SLOT(showDockWidget(QString,bool)));
connect(MAVLinkProtocol::instance(), SIGNAL(protocolStatusMessage(const QString&, const QString&)), this, SLOT(showCriticalMessage(const QString&, const QString&)));
connect(MAVLinkProtocol::instance(), SIGNAL(saveTempFlightDataLog(QString)), this, SLOT(_saveTempFlightDataLog(QString)));
loadSettings();
emit initStatusChanged(tr("Loading style"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
......@@ -931,7 +928,6 @@ void MainWindow::loadCustomWidgetsFromDefaults(const QString& systemType, const
{
qDebug() << "No default custom widgets for system " << systemType << "autopilot" << autopilotType << " found";
qDebug() << "Tried with path: " << defaultsDir;
showStatusMessage(tr("Did not find any custom widgets in %1").arg(defaultsDir));
}
// Load all custom widgets found in the AP folder
......@@ -943,7 +939,6 @@ void MainWindow::loadCustomWidgetsFromDefaults(const QString& systemType, const
// Will only be loaded if not already a custom widget with
// the same name is present
loadCustomWidget(defaultsDir+"/"+file, true);
showStatusMessage(tr("Loaded custom widget %1").arg(defaultsDir+"/"+file));
}
}
}
......@@ -1105,40 +1100,6 @@ bool MainWindow::loadStyle(QGC_MAINWINDOW_STYLE style)
return success;
}
/**
* The status message will be overwritten if a new message is posted to this function
*
* @param status message text
* @param timeout how long the status should be displayed
*/
void MainWindow::showStatusMessage(const QString& status, int timeout)
{
statusBar()->showMessage(status, timeout);
}
/**
* The status message will be overwritten if a new message is posted to this function.
* it will be automatically hidden after 5 seconds.
*
* @param status message text
*/
void MainWindow::showStatusMessage(const QString& status)
{
statusBar()->showMessage(status, 20000);
}
void MainWindow::showCriticalMessage(const QString& title, const QString& message)
{
qDebug() << "Critical" << title << message;
QGCMessageBox::critical(title, message);
}
void MainWindow::showInfoMessage(const QString& title, const QString& message)
{
qDebug() << "Information" << title << message;
QGCMessageBox::information(title, message);
}
/**
* @brief Create all actions associated to the main window
*
......@@ -1741,19 +1702,6 @@ bool MainWindow::dockWidgetTitleBarsEnabled() const
return menuActionHelper->dockWidgetTitleBarsEnabled();
}
/// @brief Save the specified Flight Data Log
void MainWindow::_saveTempFlightDataLog(QString tempLogfile)
{
QString saveFilename = QGCFileDialog::getSaveFileName(this,
tr("Select file to save Flight Data Log"),
qgcApp()->mavlinkLogFilesLocation(),
tr("Flight Data Log (*.mavlink)"));
if (!saveFilename.isEmpty()) {
QFile::copy(tempLogfile, saveFilename);
}
QFile::remove(tempLogfile);
}
/// @brief Hides the spash screen if it is currently being shown
void MainWindow::hideSplashScreen(void)
{
......
......@@ -161,15 +161,6 @@ public:
void hideSplashScreen(void);
public slots:
/** @brief Shows a status message on the bottom status bar */
void showStatusMessage(const QString& status, int timeout);
/** @brief Shows a status message on the bottom status bar */
void showStatusMessage(const QString& status);
/** @brief Shows a critical message as popup or as widget */
void showCriticalMessage(const QString& title, const QString& message);
/** @brief Shows an info message as popup or as widget */
void showInfoMessage(const QString& title, const QString& message);
/** @brief Show the application settings */
void showSettings();
/** @brief Add a communication link */
......@@ -452,7 +443,6 @@ protected:
CUSTOM_MODE customMode;
private slots:
void _saveTempFlightDataLog(QString tempLogfile);
void _addLinkMenu(LinkInterface* link);
private:
......
......@@ -42,7 +42,6 @@ This file is part of the QGROUNDCONTROL project
#include "QGCDataPlot2D.h"
#include "ui_QGCDataPlot2D.h"
#include "MG.h"
#include "MainWindow.h"
#include "QGCFileDialog.h"
#include "QGCMessageBox.h"
......@@ -304,7 +303,6 @@ void QGCDataPlot2D::loadRawLog(QString file, QString xAxisName, QString yAxisFil
// Postprocess log file
logFile = new QTemporaryFile("qt_qgc_temp_log.XXXXXX.csv");
compressor = new LogCompressor(file, logFile->fileName());
connect(compressor, SIGNAL(logProcessingStatusChanged(QString)), MainWindow::instance(), SLOT(showStatusMessage(QString)));
connect(compressor, SIGNAL(finishedFile(QString)), this, SLOT(loadFile(QString)));
compressor->startCompression();
}
......
......@@ -9,6 +9,7 @@
#include "QGCApplication.h"
#include "LinkManager.h"
#include "QGCFileDialog.h"
#include "QGCMessageBox.h"
QGCMAVLinkLogPlayer::QGCMAVLinkLogPlayer(MAVLinkProtocol* mavlink, QWidget *parent) :
QWidget(parent),
......@@ -257,7 +258,7 @@ void QGCMAVLinkLogPlayer::_selectLogFileForPlayback(void)
}
if (foundConnection) {
MainWindow::instance()->showInfoMessage(tr("Log Replay"), tr("You must close all connections prior to replaying a log."));
QGCMessageBox::information(tr("Log Replay"), tr("You must close all connections prior to replaying a log."));
return;
}
......@@ -313,7 +314,7 @@ bool QGCMAVLinkLogPlayer::loadLogFile(const QString& file)
// Now load the new file.
logFile.setFileName(file);
if (!logFile.open(QFile::ReadOnly)) {
MainWindow::instance()->showCriticalMessage(tr("The selected file is unreadable"), tr("Please make sure that the file %1 is readable or select a different file").arg(file));
QGCMessageBox::critical(tr("Log Replay"), tr("The selected file is unreadable. Please make sure that the file %1 is readable or select a different file").arg(file));
_playbackError();
return false;
}
......@@ -354,7 +355,7 @@ bool QGCMAVLinkLogPlayer::loadLogFile(const QString& file)
}
if (endtime == starttime) {
MainWindow::instance()->showCriticalMessage(tr("The selected file is corrupt"), tr("No valid timestamps were found at the end of the file.").arg(file));
QGCMessageBox::critical(tr("Log Replay"), tr("The selected file is corrupt. No valid timestamps were found at the end of the file.").arg(file));
_playbackError();
return false;
}
......@@ -631,7 +632,6 @@ void QGCMAVLinkLogPlayer::_finishPlayback(void)
QString status = tr("Flight Data replay complete");
ui->logStatsLabel->setText(status);
MainWindow::instance()->showStatusMessage(status);
// Note that we explicitly set the slider to 100%, as it may not hit that by itself depending on log file size.
updatePositionSliderUi(100.0f);
......
......@@ -48,7 +48,6 @@ This file is part of the PIXHAWK project
#include "LinechartWidget.h"
#include "LinechartPlot.h"
#include "LogCompressor.h"
#include "MainWindow.h"
#include "QGC.h"
#include "MG.h"
#include "QGCFileDialog.h"
......@@ -488,7 +487,6 @@ void LinechartWidget::stopLogging()
// Postprocess log file
compressor = new LogCompressor(logFile->fileName(), logFile->fileName());
connect(compressor, SIGNAL(finishedFile(QString)), this, SIGNAL(logfileWritten(QString)));
connect(compressor, SIGNAL(logProcessingStatusChanged(QString)), MainWindow::instance(), SLOT(showStatusMessage(QString)));
QMessageBox::StandardButton button = QGCMessageBox::question(tr("Starting Log Compression"),
tr("Should empty fields (e.g. due to packet drops) be filled with the previous value of the same variable (zero order hold)?"),
......
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