Unverified Commit 51c774e5 authored by Daniel Agar's avatar Daniel Agar Committed by GitHub

cmake fix build and delete obsolete files

parent 5ac6c722
......@@ -181,6 +181,7 @@ set(QGC_RESOURCES
HackFileDialog.qrc
qgcresources.qrc
qgroundcontrol.qrc
qgcimages.qrc
src/FirmwarePlugin/APM/APMResources.qrc
src/FirmwarePlugin/PX4/PX4Resources.qrc
......
......@@ -72,8 +72,8 @@ add_library(qgc
KMLFileHelper.cc
LogCompressor.cc
main.cc
QGC.cc
QGCApplication.cc
QGC.cc
QGCComboBox.cc
QGCDockWidget.cc
QGCFileDownload.cc
......@@ -81,21 +81,15 @@ add_library(qgc
QGCLoggingCategory.cc
QGCMapPalette.cc
QGCPalette.cc
QGCQFileDialog.cc
QGCQGeoCoordinate.cc
QGCQmlWidgetHolder.cpp
QGCQuickWidget.cc
QGCTemporaryFile.cc
QGCToolbox.cc
RunGuard.cc
ShapeFileHelper.cc
SHPFileHelper.cc
TerrainTile.cc
UTM.cpp
# UI
QGCQmlWidgetHolder.ui
QGCQmlWidgetHolder.h
UTM.cpp
)
set_source_files_properties(QGCApplication.cc PROPERTIES COMPILE_DEFINITIONS GIT_VERSION="${git_tag}")
......@@ -176,3 +170,4 @@ target_include_directories(qgc
${CMAKE_CURRENT_BINARY_DIR}/qgc_autogen/include # HACK: AUTOUIC paths not inheriting?
${CMAKE_CURRENT_BINARY_DIR}/qgc_autogen/include_Debug
)
......@@ -9,7 +9,6 @@ add_library(QmlControls
QGCImageProvider.cc
QGroundControlQmlGlobal.cc
QmlObjectListModel.cc
QmlTestWidget.cc
RCChannelMonitorController.cc
ScreenToolsController.cc
)
......
/****************************************************************************
*
* (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.
*
****************************************************************************/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#include "QmlTestWidget.h"
#include <QColorDialog>
QmlTestWidget::QmlTestWidget(void)
: QGCQmlWidgetHolder(QString(), NULL, NULL)
{
setAttribute(Qt::WA_DeleteOnClose);
resize(900, 500);
setVisible(true);
setContextPropertyObject("controller", this);
setSource(QUrl::fromUserInput("qrc:qml/QmlTest.qml"));
}
void QmlTestWidget::showColorDialog(QQuickItem* item)
{
Q_UNUSED(item)
QColorDialog colorDialog(this);
connect(&colorDialog, &QColorDialog::colorSelected, this, &QmlTestWidget::_colorSelected);
colorDialog.open();
}
void QmlTestWidget::_colorSelected(const QColor & color)
{
Q_UNUSED(color);
}
/****************************************************************************
*
* (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.
*
****************************************************************************/
#ifndef QmlTestWidget_h
#define QmlTestWidget_h
/// @file
/// @author Don Gagne <don@thegagnes.com>
#include "QGCQmlWidgetHolder.h"
/// This is used to create widgets which are implemented in QML.
class QmlTestWidget : public QGCQmlWidgetHolder
{
Q_OBJECT
public:
QmlTestWidget(void);
Q_INVOKABLE void showColorDialog(QQuickItem* item);
private slots:
void _colorSelected(const QColor & color);
};
#endif
......@@ -4,6 +4,7 @@ add_library(Settings
AppSettings.cc
AutoConnectSettings.cc
BrandImageSettings.cc
FirmwareUpgradeSettings.cc
FlightMapSettings.cc
FlyViewSettings.cc
OfflineMapsSettings.cc
......
add_library(ViewWidgets
CustomCommandWidget.cc
CustomCommandWidgetController.cc
ViewWidgetController.cc
)
......
/****************************************************************************
*
* (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 "CustomCommandWidget.h"
CustomCommandWidget::CustomCommandWidget(const QString& title, QAction* action, QWidget *parent) :
QGCQmlWidgetHolder(title, action, parent)
{
Q_UNUSED(title);
Q_UNUSED(action);
setSource(QUrl::fromUserInput("qrc:/qml/CustomCommandWidget.qml"));
loadSettings();
}
/****************************************************************************
*
* (c) 2009-2018 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.
*
****************************************************************************/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#pragma once
#include "QGCQmlWidgetHolder.h"
class CustomCommandWidget : public QGCQmlWidgetHolder
{
Q_OBJECT
public:
CustomCommandWidget(const QString& title, QAction* action, QWidget *parent = 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 "CustomCommandWidgetController.h"
#include "MultiVehicleManager.h"
#include "QGCMAVLink.h"
#include "QGCQFileDialog.h"
#include "UAS.h"
#include "QGCApplication.h"
#include <QSettings>
#include <QUrl>
const char* CustomCommandWidgetController::_settingsKey = "CustomCommand.QmlFile";
CustomCommandWidgetController::CustomCommandWidgetController(void) :
_vehicle(NULL)
{
if(qgcApp()->toolbox()->multiVehicleManager()->activeVehicle()) {
_vehicle = qgcApp()->toolbox()->multiVehicleManager()->activeVehicle();
}
QSettings settings;
_customQmlFile = settings.value(_settingsKey).toString();
}
void CustomCommandWidgetController::sendCommand(int commandId, QVariant componentId, QVariant confirm, QVariant param1, QVariant param2, QVariant param3, QVariant param4, QVariant param5, QVariant param6, QVariant param7)
{
Q_UNUSED(confirm);
if(_vehicle) {
_vehicle->sendMavCommand(componentId.toInt(),
(MAV_CMD)commandId,
true, // show error if fails
param1.toFloat(), param2.toFloat(), param3.toFloat(), param4.toFloat(), param5.toFloat(), param6.toFloat(), param7.toFloat());
}
}
void CustomCommandWidgetController::selectQmlFile(void)
{
QSettings settings;
QString qmlFile = QGCQFileDialog::getOpenFileName(NULL, tr("Select custom Qml file"), QString(), tr("Qml files (*.qml)"));
if (qmlFile.isEmpty()) {
_customQmlFile.clear();
settings.remove(_settingsKey);
} else {
QUrl url = QUrl::fromLocalFile(qmlFile);
_customQmlFile = url.toString();
settings.setValue(_settingsKey, _customQmlFile);
}
emit customQmlFileChanged(_customQmlFile);
}
void CustomCommandWidgetController::clearQmlFile(void)
{
_customQmlFile.clear();
QSettings settings;
settings.remove(_settingsKey);
emit customQmlFileChanged(_customQmlFile);
}
......@@ -16,7 +16,6 @@ add_library(comm
LogReplayLink.cc
MavlinkMessagesTimer.cc
MAVLinkProtocol.cc
QGCFlightGearLink.cc
QGCJSBSimLink.cc
QGCMAVLink.cc
QGCSerialPortInfo.cc
......@@ -30,7 +29,6 @@ add_library(comm
# HEADERS
# shouldn't be listed here, but aren't named properly for AUTOMOC
QGCFlightGearLink.h
QGCHilLink.h
QGCJSBSimLink.h
)
......
This diff is collapsed.
/****************************************************************************
*
* (c) 2009-2018 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.
*
****************************************************************************/
/**
* @file
* @brief UDP connection (server) for unmanned vehicles
* @author Lorenz Meier <mavteam@student.ethz.ch>
*
*/
#pragma once
#include <QString>
#include <QList>
#include <QMap>
#include <QMutex>
#include <QUdpSocket>
#include <QTimer>
#include <QProcess>
#include "LinkInterface.h"
#include "QGCConfig.h"
#include "UASInterface.h"
#include "QGCHilLink.h"
#include "QGCHilFlightGearConfiguration.h"
#include "Vehicle.h"
class QGCFlightGearLink : public QGCHilLink
{
Q_OBJECT
public:
QGCFlightGearLink(Vehicle* vehicle, QString startupArguments, QString remoteHost=QString("127.0.0.1:49000"), QHostAddress host = QHostAddress::Any, quint16 port = 49005);
~QGCFlightGearLink();
bool isConnected();
qint64 bytesAvailable();
int getPort() const {
return port;
}
/**
* @brief The human readable port name
*/
QString getName();
/**
* @brief Get remote host and port
* @return string in format <host>:<port>
*/
QString getRemoteHost();
QString getVersion()
{
return QString("FlightGear %1").arg(flightGearVersion);
}
int getAirFrameIndex()
{
return -1;
}
bool sensorHilEnabled() {
return _sensorHilEnabled;
}
void sensorHilEnabled(bool sensorHilEnabled) {
_sensorHilEnabled = sensorHilEnabled;
}
static bool parseUIArguments(QString uiArgs, QStringList& argList);
void run();
signals:
void showCriticalMessageFromThread(const QString& title, const QString& message);
public slots:
// void setAddress(QString address);
void setPort(int port);
/** @brief Add a new host to broadcast messages to */
void setRemoteHost(const QString& host);
/** @brief Send new control states to the simulation */
void updateControls(quint64 time, float rollAilerons, float pitchElevator, float yawRudder, float throttle, quint8 systemMode, quint8 navMode);
/** @brief Set the simulator version as text string */
void setVersion(const QString& version)
{
Q_UNUSED(version);
}
void selectAirframe(const QString& airframe)
{
Q_UNUSED(airframe);
}
void enableSensorHIL(bool enable) {
if (enable != _sensorHilEnabled)
_sensorHilEnabled = enable;
emit sensorHilChanged(enable);
}
void readBytes();
private slots:
/**
* @brief Write a number of bytes to the interface.
*
* @param data Pointer to the data byte array
* @param size The size of the bytes array
**/
void _writeBytes(const QByteArray data);
public slots:
bool connectSimulation();
bool disconnectSimulation();
void setStartupArguments(QString startupArguments);
void setBarometerOffset(float barometerOffsetkPa);
void processError(QProcess::ProcessError err);
protected:
void setName(QString name);
private slots:
void _printFgfsOutput(void);
void _printFgfsError(void);
private:
static bool _findUIArgument(const QStringList& uiArgList, const QString& argLabel, QString& argValue);
Vehicle* _vehicle;
QString _fgProcessName; ///< FlightGear process to start
QString _fgProcessWorkingDirPath; ///< Working directory to start FG process in, empty for none
QStringList _fgArgList; ///< Arguments passed to FlightGear process
QUdpSocket* _udpCommSocket; ///< UDP communication sockect between FG and QGC
QProcess* _fgProcess; ///< FlightGear process
QString _fgProtocolFileFullyQualified; ///< Fully qualified file name for protocol file
QString name;
QHostAddress host;
QHostAddress currentHost;
quint16 currentPort;
quint16 port;
int id;
bool connectState;
unsigned int flightGearVersion;
QString startupArguments;
bool _sensorHilEnabled;
float barometerOffsetkPa;
};
add_library(qgcunittest
FileDialogTest.cc
FileManagerTest.cc
FlightGearTest.cc
#FileDialogTest.cc
#FileManagerTest.cc
#FlightGearTest.cc
GeoTest.cc
LinkManagerTest.cc
MainWindowTest.cc
#MainWindowTest.cc
MavlinkLogTest.cc
MessageBoxTest.cc
#MessageBoxTest.cc
MultiSignalSpy.cc
RadioConfigTest.cc
#RadioConfigTest.cc
TCPLinkTest.cc
TCPLoopBackServer.cc
UnitTest.cc
......
add_library(ui
HILDockWidget.cc
linechart/ChartPlot.cc
linechart/IncrementalPlot.cc
linechart/LinechartPlot.cc
linechart/Linecharts.cc
linechart/LinechartWidget.cc
linechart/Scrollbar.cc
linechart/ScrollZoomer.cc
MainWindow.cc
MAVLinkDecoder.cc
MultiVehicleDockWidget.cc
QGCHilConfiguration.cc
QGCHilFlightGearConfiguration.cc
QGCHilJSBSimConfiguration.cc
QGCHilXPlaneConfiguration.cc
QGCMapRCToParamDialog.cpp
QGCMAVLinkLogPlayer.cc
QGCPluginHost.cc
QGCUASFileView.cc
QGCUASFileViewMulti.cc
uas/QGCUnconnectedInfoWidget.cc
# HEADERS
# shouldn't be listed here, but aren't named properly for AUTOMOC
QGCHilFlightGearConfiguration.h
QGCHilJSBSimConfiguration.h
MAVLinkDecoder.h
MultiVehicleDockWidget.h
QGCMapRCToParamDialog.h
QGCPluginHost.h
# UI
MainWindow.ui
MultiVehicleDockWidget.ui
QGCHilConfiguration.ui
QGCHilFlightGearConfiguration.ui
QGCHilJSBSimConfiguration.ui
QGCHilXPlaneConfiguration.ui
QGCMapRCToParamDialog.ui
QGCMAVLinkLogPlayer.ui
QGCPluginHost.ui
QGCUASFileView.ui
QGCUASFileViewMulti.ui
QMap3D.ui
uas/QGCUnconnectedInfoWidget.ui
)
target_link_libraries(ui
PUBLIC
qgc
PRIVATE
qwt
)
target_include_directories(ui
......
/****************************************************************************
*
* (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 "HILDockWidget.h"
#include "QGCHilConfiguration.h"
HILDockWidget::HILDockWidget(const QString& title, QAction* action, QWidget *parent)
: MultiVehicleDockWidget(title, action, parent)
{
init();
loadSettings();
}
HILDockWidget::~HILDockWidget()
{
}
QWidget* HILDockWidget::_newVehicleWidget(Vehicle* vehicle, QWidget* parent)
{
return new QGCHilConfiguration(vehicle, parent);
}
/****************************************************************************
*
* (c) 2009-2018 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.
*
****************************************************************************/
#pragma once
#include "MultiVehicleDockWidget.h"
class HILDockWidget : public MultiVehicleDockWidget
{
Q_OBJECT
public:
explicit HILDockWidget(const QString& title, QAction* action, QWidget *parent = 0);
~HILDockWidget();
protected:
// Override from MultiVehicleDockWidget
virtual QWidget* _newVehicleWidget(Vehicle* vehicle, QWidget* parent);
};
/****************************************************************************
*
* (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 <QSettings>
#include "QGCHilConfiguration.h"
#include "ui_QGCHilConfiguration.h"
#include "QGCHilFlightGearConfiguration.h"
#include "QGCHilJSBSimConfiguration.h"
#include "QGCHilXPlaneConfiguration.h"
#include "UAS.h"
QGCHilConfiguration::QGCHilConfiguration(Vehicle* vehicle, QWidget *parent)
: QWidget(parent)
, _vehicle(vehicle)
, ui(new Ui::QGCHilConfiguration)
{
ui->setupUi(this);
// XXX its quite wrong that this is implicitely a factory
// class, but this is something to clean up for later.
QSettings settings;
settings.beginGroup("QGC_HILCONFIG");
int i = settings.value("SIMULATOR_INDEX", -1).toInt();
if (i > 0) {
// ui->simComboBox->blockSignals(true);
ui->simComboBox->setCurrentIndex(i);
// ui->simComboBox->blockSignals(false);
on_simComboBox_currentIndexChanged(i);
}
settings.endGroup();
}
void QGCHilConfiguration::receiveStatusMessage(const QString& message)
{
ui->statusLabel->setText(message);
}
QGCHilConfiguration::~QGCHilConfiguration()
{
QSettings settings;
settings.beginGroup("QGC_HILCONFIG");
settings.setValue("SIMULATOR_INDEX", ui->simComboBox->currentIndex());
settings.endGroup();
delete ui;
}
void QGCHilConfiguration::setVersion(QString version)
{
Q_UNUSED(version);
}
void QGCHilConfiguration::on_simComboBox_currentIndexChanged(int index)
{
//clean up
QLayoutItem *child;
while ((child = ui->simulatorConfigurationLayout->takeAt(0)) != 0)
{
delete child->widget();
delete child;
}
if(1 == index)
{
// Ensure the sim exists and is disabled
_vehicle->uas()->enableHilFlightGear(false, "", true, this);
QGCHilFlightGearConfiguration* hfgconf = new QGCHilFlightGearConfiguration(_vehicle, this);
hfgconf->show();
ui->simulatorConfigurationLayout->addWidget(hfgconf);
QGCFlightGearLink* fg = dynamic_cast<QGCFlightGearLink*>(_vehicle->uas()->getHILSimulation());
if (fg)
{
connect(fg, &QGCFlightGearLink::statusMessage, ui->statusLabel, &QLabel::setText);
}
}
else if (2 == index || 3 == index)
{
// Ensure the sim exists and is disabled
_vehicle->uas()->enableHilXPlane(false);
QGCHilXPlaneConfiguration* hxpconf = new QGCHilXPlaneConfiguration(_vehicle->uas()->getHILSimulation(), this);
hxpconf->show();
ui->simulatorConfigurationLayout->addWidget(hxpconf);
// Select correct version of XPlane
QGCXPlaneLink* xplane = dynamic_cast<QGCXPlaneLink*>(_vehicle->uas()->getHILSimulation());
if (xplane)
{
xplane->setVersion((index == 2) ? 10 : 9);
connect(xplane, &QGCXPlaneLink::statusMessage, ui->statusLabel, &QLabel::setText);
}
}
// Disabling JSB Sim since its not well maintained,
// but as refactoring is pending we're not ditching the code yet
// else if (4)
// {
// // Ensure the sim exists and is disabled
// _vehicle->uas()->enableHilJSBSim(false, "");
// QGCHilJSBSimConfiguration* hfgconf = new QGCHilJSBSimConfiguration(_vehicle, this);
// hfgconf->show();
// ui->simulatorConfigurationLayout->addWidget(hfgconf);
// QGCJSBSimLink* jsb = dynamic_cast<QGCJSBSimLink*>(_vehicle->uas()->getHILSimulation());
// if (jsb)
// {
// connect(jsb, SIGNAL(statusMessage(QString)), ui->statusLabel, SLOT(setText(QString)));
// }
// }
}
/****************************************************************************
*
* (c) 2009-2018 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.
*
****************************************************************************/
#pragma once
#include <QWidget>
#include "Vehicle.h"
namespace Ui {
class QGCHilConfiguration;
}
class QGCHilConfiguration : public QWidget
{
Q_OBJECT
public:
QGCHilConfiguration(Vehicle* vehicle, QWidget *parent = 0);
~QGCHilConfiguration();
public slots:
/** @brief Receive status message */
void receiveStatusMessage(const QString& message);
void setVersion(QString version);
private slots:
void on_simComboBox_currentIndexChanged(int index);
private:
Vehicle* _vehicle;
Ui::QGCHilConfiguration *ui;
};
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QGCHilConfiguration</class>
<widget class="QWidget" name="QGCHilConfiguration">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>366</width>
<height>301</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>HIL Config</string>
</property>
<layout class="QGridLayout" name="gridLayout" rowstretch="1,100,1" columnstretch="40,0">
<item row="0" column="0">
<widget class="QLabel" name="simLabel">
<property name="text">
<string>Simulator</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="simComboBox">
<property name="editable">
<bool>true</bool>
</property>
<item>
<property name="text">
<string/>
</property>
</item>
<item>
<property name="text">
<string>FlightGear 3.0+</string>
</property>
</item>
<item>
<property name="text">
<string>X-Plane 10</string>
</property>
</item>
<item>
<property name="text">
<string>X-Plane 9</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0" colspan="2">
<layout class="QVBoxLayout" name="simulatorConfigurationLayout">
<property name="spacing">
<number>0</number>
</property>
</layout>
</item>
<item row="2" column="0" colspan="2">
<widget class="QLabel" name="statusLabel">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
#include "QGCHilFlightGearConfiguration.h"
#include "MainWindow.h"
#include "UAS.h"
#include <QMenu>
// Various settings groups and keys
const char* QGCHilFlightGearConfiguration::_settingsGroup = "QGC_HILCONFIG_FLIGHTGEAR";
const char* QGCHilFlightGearConfiguration::_mavSettingsSubGroupFixedWing = "FIXED_WING";
const char* QGCHilFlightGearConfiguration::_mavSettingsSubGroupQuadRotor = "QUADROTOR";
const char* QGCHilFlightGearConfiguration::_aircraftKey = "AIRCRAFT";
const char* QGCHilFlightGearConfiguration::_optionsKey = "OPTIONS";
const char* QGCHilFlightGearConfiguration::_barometerOffsetKey = "BARO_OFFSET";
const char* QGCHilFlightGearConfiguration::_sensorHilKey = "SENSOR_HIL";
// Default set of optional command line parameters. If FlightGear won't run HIL without it it should go into
// the QGCFlightGearLink code instead.
const char* QGCHilFlightGearConfiguration::_defaultOptions = "--roll=0 --pitch=0 --vc=0 --heading=300 --timeofday=noon --disable-hud-3d --disable-fullscreen --geometry=400x300 --disable-anti-alias-hud --wind=0@0 --turbulence=0.0 --disable-sound --disable-random-objects --disable-ai-traffic --shading-flat --fog-disable --disable-specular-highlight --disable-panel --disable-clouds --fdm=jsb --units-meters --enable-terrasync";
QGCHilFlightGearConfiguration::QGCHilFlightGearConfiguration(Vehicle* vehicle, QWidget *parent)
: QWidget(parent)
, _vehicle(vehicle)
, _mavSettingsSubGroup(NULL)
, _resetOptionsAction(tr("Reset to default options"), this)
{
_ui.setupUi(this);
QStringList items;
if (_vehicle->vehicleType() == MAV_TYPE_FIXED_WING)
{
/*items << "EasyStar";*/
items << "Rascal110-JSBSim";
/*items << "c172p";
items << "YardStik";
items << "Malolo1";*/
_mavSettingsSubGroup = _mavSettingsSubGroupFixedWing;
}
/*else if (_vehicle->vehicleType() == MAV_TYPE_QUADROTOR)
{
items << "arducopter";
_mavSettingsSubGroup = _mavSettingsSubGroupQuadRotor;
}*/
else
{
// FIXME: Should disable all input, won't work. Show error message in the status label thing.
items << "<aircraft>";
}
_ui.aircraftComboBox->addItems(items);
QSettings settings;
settings.beginGroup(_settingsGroup);
settings.beginGroup(_mavSettingsSubGroup);
QString aircraft = settings.value(_aircraftKey).toString();
QString options = settings.value(_optionsKey).toString();
QString baroOffset = settings.value(_barometerOffsetKey).toString();
bool sensorHil = settings.value(_sensorHilKey, QVariant(true)).toBool();
settings.endGroup();
settings.endGroup();
if (!aircraft.isEmpty()) {
int index = _ui.aircraftComboBox->findText(aircraft);
if (index != -1) {
_ui.aircraftComboBox->setCurrentIndex(index);
}
}
if (options.isEmpty()) {
options = _defaultOptions;
}
_ui.optionsPlainTextEdit->setPlainText(options);
_ui.barometerOffsetLineEdit->setText(baroOffset);
_ui.sensorHilCheckBox->setChecked(sensorHil);
// Provide an option on the context menu to reset the option back to default
_ui.optionsPlainTextEdit->setContextMenuPolicy(Qt::CustomContextMenu);
bool success = connect(&_resetOptionsAction, &QAction::triggered, this, &QGCHilFlightGearConfiguration::_setDefaultOptions);
Q_ASSERT(success);
success = connect(_ui.optionsPlainTextEdit, &QPlainTextEdit::customContextMenuRequested,
this, &QGCHilFlightGearConfiguration::_showContextMenu);
Q_ASSERT(success);
Q_UNUSED(success); // Silence release build unused variable warning
}
QGCHilFlightGearConfiguration::~QGCHilFlightGearConfiguration()
{
QString aircraft = _ui.aircraftComboBox->currentText();
QString options = _ui.optionsPlainTextEdit->toPlainText();
QString baroOffset = _ui.barometerOffsetLineEdit->text();
bool sensorHil = _ui.sensorHilCheckBox->isChecked();
QSettings settings;
settings.beginGroup(_settingsGroup);
settings.beginGroup(_mavSettingsSubGroup);
if (aircraft.isEmpty()) {
settings.remove(_aircraftKey);
} else {
settings.setValue(_aircraftKey, aircraft);
}
if (options.isEmpty() || options == _defaultOptions) {
settings.remove(_optionsKey);
} else {
settings.setValue(_optionsKey, options);
}
// Double QVariant is to convert from string to float. It will change to 0.0 if invalid.
settings.setValue(_barometerOffsetKey, QVariant(QVariant(baroOffset).toFloat()));
settings.setValue(_sensorHilKey, QVariant(sensorHil));
settings.endGroup();
settings.endGroup();
}
void QGCHilFlightGearConfiguration::on_startButton_clicked()
{
//XXX check validity of inputs
QString options = _ui.optionsPlainTextEdit->toPlainText();
options.append(" --aircraft=" + _ui.aircraftComboBox->currentText());
_vehicle->uas()->enableHilFlightGear(true, options, _ui.sensorHilCheckBox->isChecked(), this);
}
void QGCHilFlightGearConfiguration::on_stopButton_clicked()
{
_vehicle->uas()->stopHil();
}
void QGCHilFlightGearConfiguration::on_barometerOffsetLineEdit_textChanged(const QString& baroOffset)
{
emit barometerOffsetChanged(baroOffset.toFloat());
}
void QGCHilFlightGearConfiguration::_showContextMenu(const QPoint &pt)
{
QMenu* menu = _ui.optionsPlainTextEdit->createStandardContextMenu();
menu->addAction(&_resetOptionsAction);
menu->exec(_ui.optionsPlainTextEdit->mapToGlobal(pt));
delete menu;
}
void QGCHilFlightGearConfiguration::_setDefaultOptions(void)
{
_ui.optionsPlainTextEdit->setPlainText(_defaultOptions);
}
#pragma once
#include <QWidget>
#include "QGCHilLink.h"
#include "QGCFlightGearLink.h"
#include "Vehicle.h"
#include "ui_QGCHilFlightGearConfiguration.h"
namespace Ui {
class QGCHilFlightGearConfiguration;
}
class QGCHilFlightGearConfiguration : public QWidget
{
Q_OBJECT
public:
explicit QGCHilFlightGearConfiguration(Vehicle* vehicle, QWidget *parent = 0);
~QGCHilFlightGearConfiguration();
protected:
private slots:
void on_startButton_clicked();
void on_stopButton_clicked();
void on_barometerOffsetLineEdit_textChanged(const QString& baroOffset);
void _setDefaultOptions(void);
void _showContextMenu(const QPoint& pt);
private:
Vehicle* _vehicle;
Ui::QGCHilFlightGearConfiguration _ui;
static const char* _settingsGroup; /// Top level settings group
const char* _mavSettingsSubGroup; /// We maintain a settings sub group per mav type
static const char* _mavSettingsSubGroupFixedWing; /// Subgroup if mav type is MAV_TYPE_FIXED_WING
static const char* _mavSettingsSubGroupQuadRotor; /// Subgroup is mav type is MAV_TYPE_QUADROTOR
static const char* _aircraftKey; /// Settings key for aircraft selection
static const char* _optionsKey; /// Settings key for FlightGear cmd line options
static const char* _barometerOffsetKey; /// Settings key for barometer offset
static const char* _sensorHilKey; /// Settings key for Sensor Hil checkbox
static const char* _defaultOptions; /// Default set of FlightGEar command line options
QAction _resetOptionsAction; /// Context menu item to reset options to default
signals:
void barometerOffsetChanged(float barometerOffsetkPa);
};
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QGCHilFlightGearConfiguration</class>
<widget class="QWidget" name="QGCHilFlightGearConfiguration">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>237</width>
<height>209</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="margin">
<number>0</number>
</property>
<property name="spacing">
<number>6</number>
</property>
<item row="1" column="0" colspan="2">
<widget class="QComboBox" name="aircraftComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="optionsLabel">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Additional Options:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="aircraftPlaintextInfoLabel">
<property name="text">
<string>Airframe:</string>
</property>
</widget>
</item>
<item row="5" column="0" colspan="2">
<widget class="QPlainTextEdit" name="optionsPlainTextEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="plainText">
<string></string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QPushButton" name="startButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Start</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QPushButton" name="stopButton">
<property name="text">
<string>Stop</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="sensorHilCheckBox">
<property name="text">
<string>Sensor HIL</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="barometerOffsetLabel">
<property name="text">
<string>Barometer Offset [kPa]:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="barometerOffsetLineEdit">
<property name="text">
<string>0</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
#include "QGCHilJSBSimConfiguration.h"
#include "ui_QGCHilJSBSimConfiguration.h"
#include "MainWindow.h"
#include "UAS.h"
QGCHilJSBSimConfiguration::QGCHilJSBSimConfiguration(Vehicle* vehicle, QWidget *parent)
: QWidget(parent)
, _vehicle(vehicle)
, ui(new Ui::QGCHilJSBSimConfiguration)
{
ui->setupUi(this);
QStringList items = QStringList();
if (_vehicle->vehicleType() == MAV_TYPE_FIXED_WING)
{
items << "EasyStar";
items << "Rascal110-JSBSim";
items << "c172p";
items << "YardStik";
items << "Malolo1";
}
else if (_vehicle->vehicleType() == MAV_TYPE_QUADROTOR)
{
items << "arducopter";
}
else
{
items << "<aircraft>";
}
ui->aircraftComboBox->addItems(items);
}
QGCHilJSBSimConfiguration::~QGCHilJSBSimConfiguration()
{
delete ui;
}
void QGCHilJSBSimConfiguration::on_startButton_clicked()
{
//XXX check validity of inputs
QString options = ui->optionsPlainTextEdit->toPlainText();
options.append(" --script=" + ui->aircraftComboBox->currentText());
_vehicle->uas()->enableHilJSBSim(true, options);
}
void QGCHilJSBSimConfiguration::on_stopButton_clicked()
{
_vehicle->uas()->stopHil();
}
#pragma once
#include <QWidget>
#include "QGCHilLink.h"
#include "QGCFlightGearLink.h"
#include "Vehicle.h"
namespace Ui {
class QGCHilJSBSimConfiguration;
}
class QGCHilJSBSimConfiguration : public QWidget
{
Q_OBJECT
public:
explicit QGCHilJSBSimConfiguration(Vehicle* vehicle, QWidget *parent = 0);
~QGCHilJSBSimConfiguration();
private slots:
void on_startButton_clicked();
void on_stopButton_clicked();
private:
Vehicle* _vehicle;
Ui::QGCHilJSBSimConfiguration *ui;
};
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QGCHilJSBSimConfiguration</class>
<widget class="QWidget" name="QGCHilJSBSimConfiguration">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>237</width>
<height>204</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout" rowminimumheight="0,0,0,0,0,0,0,0">
<property name="margin">
<number>0</number>
</property>
<property name="spacing">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="aircraftPlaintextInfoLabel">
<property name="text">
<string>Airframe:</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QComboBox" name="aircraftComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="optionsLabel">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Additional Options:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QPlainTextEdit" name="optionsPlainTextEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="plainText">
<string>--in-air --roll=0 --pitch=0 --vc=90 --heading=300 --timeofday=noon --disable-hud-3d --disable-fullscreen --geometry=400x300 --disable-anti-alias-hud --wind=0@0 --turbulence=0.0 --prop:/sim/frame-rate-throttle-hz=30 --control=mouse --disable-intro-music --disable-sound --disable-random-objects --disable-ai-models --shading-flat --fog-disable --disable-specular-highlight --disable-random-objects --disable-panel --disable-clouds --fdm=jsb --units-meters --prop:/engines/engine/running=true</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QPushButton" name="startButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Start</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QPushButton" name="stopButton">
<property name="text">
<string>Stop</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
#include "QGCHilXPlaneConfiguration.h"
#include "ui_QGCHilXPlaneConfiguration.h"
#include "QGCXPlaneLink.h"
#include "QGCHilConfiguration.h"
QGCHilXPlaneConfiguration::QGCHilXPlaneConfiguration(QGCHilLink* link, QGCHilConfiguration *parent) :
QWidget(parent),
ui(new Ui::QGCHilXPlaneConfiguration)
{
ui->setupUi(this);
this->link = link;
connect(ui->startButton, &QPushButton::clicked, this, &QGCHilXPlaneConfiguration::toggleSimulation);
connect(ui->hostComboBox, static_cast<void (QComboBox::*)(const QString&)>(&QComboBox::activated),
link, &QGCHilLink::setRemoteHost);
connect(link, &QGCHilLink::remoteChanged, ui->hostComboBox, &QComboBox::setEditText);
connect(link, &QGCHilLink::statusMessage, parent, &QGCHilConfiguration::receiveStatusMessage);
// connect(mav->getHILSimulation(), SIGNAL(statusMessage(QString)), this, SLOT(receiveStatusMessage(QString)));
// connect(ui->simComboBox, SIGNAL(activated(QString)), mav->getHILSimulation(), SLOT(setVersion(QString)));
ui->startButton->setText(tr("Connect"));
QGCXPlaneLink* xplane = dynamic_cast<QGCXPlaneLink*>(link);
if (xplane)
{
// connect(ui->randomAttitudeButton, SIGNAL(clicked()), link, SLOT(setRandomAttitude()));
// connect(ui->randomPositionButton, SIGNAL(clicked()), link, SLOT(setRandomPosition()));
//ui->airframeComboBox->setCurrentIndex(link->getAirFrameIndex());
//connect(ui->airframeComboBox, SIGNAL(activated(QString)), link, SLOT(selectAirframe(QString)));
// XXX not implemented yet
//ui->airframeComboBox->hide();
ui->sensorHilCheckBox->setChecked(xplane->sensorHilEnabled());
ui->useHilActuatorControlsCheckBox->setChecked(true);
connect(xplane, &QGCXPlaneLink::sensorHilChanged, ui->sensorHilCheckBox, &QCheckBox::setChecked);
connect(ui->sensorHilCheckBox, &QCheckBox::clicked, xplane, &QGCXPlaneLink::enableSensorHIL);
connect(xplane, &QGCXPlaneLink::useHilActuatorControlsChanged, ui->useHilActuatorControlsCheckBox, &QCheckBox::setChecked);
connect(ui->useHilActuatorControlsCheckBox, &QCheckBox::clicked, xplane, &QGCXPlaneLink::enableHilActuatorControls);
connect(link, static_cast<void (QGCHilLink::*)(int)>(&QGCHilLink::versionChanged),
this, &QGCHilXPlaneConfiguration::setVersion);
}
ui->hostComboBox->clear();
ui->hostComboBox->addItem(link->getRemoteHost());
}
void QGCHilXPlaneConfiguration::setVersion(int version)
{
Q_UNUSED(version);
}
void QGCHilXPlaneConfiguration::toggleSimulation(bool connect)
{
if (!link) {
return;
}
Q_UNUSED(connect);
if (!link->isConnected())
{
link->setRemoteHost(ui->hostComboBox->currentText());
link->connectSimulation();
ui->startButton->setText(tr("Disconnect"));
}
else
{
link->disconnectSimulation();
ui->startButton->setText(tr("Connect"));
}
}
QGCHilXPlaneConfiguration::~QGCHilXPlaneConfiguration()
{
delete ui;
}
#pragma once
#include <QWidget>
#include "QGCHilLink.h"
class QGCHilConfiguration;
namespace Ui {
class QGCHilXPlaneConfiguration;
}
class QGCHilXPlaneConfiguration : public QWidget
{
Q_OBJECT
public:
explicit QGCHilXPlaneConfiguration(QGCHilLink* link, QGCHilConfiguration *parent = 0);
~QGCHilXPlaneConfiguration();
public slots:
/** @brief Start / stop simulation */
void toggleSimulation(bool connect);
/** @brief Set X-Plane version */
void setVersion(int version);
protected:
QGCHilLink* link;
private:
Ui::QGCHilXPlaneConfiguration *ui;
};
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QGCHilXPlaneConfiguration</class>
<widget class="QWidget" name="QGCHilXPlaneConfiguration">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>269</width>
<height>150</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0,0,0,0,0,0" columnstretch="20,0,0">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="1" column="1" colspan="2">
<widget class="QPushButton" name="startButton">
<property name="text">
<string>Start</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="hostLabel">
<property name="text">
<string>Host</string>
</property>
</widget>
</item>
<item row="7" column="0" colspan="3">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>1</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="0" colspan="3">
<widget class="QCheckBox" name="sensorHilCheckBox">
<property name="text">
<string>Enable sensor level HIL</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QComboBox" name="hostComboBox">
<property name="editable">
<bool>true</bool>
</property>
<item>
<property name="text">
<string>127.0.0.1:49000</string>
</property>
</item>
</widget>
</item>
<item row="4" column="0" colspan="3">
<widget class="QCheckBox" name="useHilActuatorControlsCheckBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Use newer actuator format</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
#include <QStandardPaths>
#include <QtEndian>
#include "MainWindow.h"
#ifndef NO_SERIAL_LINK
#include "SerialLink.h"
#endif
#include "QGCMAVLinkLogPlayer.h"
#include "QGC.h"
#include "ui_QGCMAVLinkLogPlayer.h"
#include "QGCApplication.h"
#include "SettingsManager.h"
#include "AppSettings.h"
#include "LinkManager.h"
#include "QGCQFileDialog.h"
#include "QGCMessageBox.h"
QGCMAVLinkLogPlayer::QGCMAVLinkLogPlayer(QWidget *parent)
: QWidget (parent)
, _replayLink (NULL)
, _lastCurrentTime (0)
, _ui (new Ui::QGCMAVLinkLogPlayer)
{
_ui->setupUi(this);
_ui->horizontalLayout->setAlignment(Qt::AlignTop);
// Setup buttons
connect(_ui->selectFileButton, &QPushButton::clicked, this, &QGCMAVLinkLogPlayer::_selectLogFileForPlayback);
connect(_ui->playButton, &QPushButton::clicked, this, &QGCMAVLinkLogPlayer::_playPauseToggle);
connect(_ui->positionSlider, &QSlider::valueChanged, this, &QGCMAVLinkLogPlayer::_setPlayheadFromSlider);
connect(_ui->positionSlider, &QSlider::sliderPressed, this, &QGCMAVLinkLogPlayer::_pause);
#if 0
// Speed slider is removed from 3.0 release. Too broken to fix.
connect(_ui->speedSlider, &QSlider::valueChanged, this, &QGCMAVLinkLogPlayer::_setAccelerationFromSlider);
_ui->speedSlider->setMinimum(-100);
_ui->speedSlider->setMaximum(100);
_ui->speedSlider->setValue(0);
#endif
_enablePlaybackControls(false);
_ui->positionSlider->setMinimum(0);
_ui->positionSlider->setMaximum(100);
}
QGCMAVLinkLogPlayer::~QGCMAVLinkLogPlayer()
{
delete _ui;
}
void QGCMAVLinkLogPlayer::_playPauseToggle(void)
{
if (_replayLink->isPlaying()) {
_pause();
} else {
_replayLink->play();
}
}
void QGCMAVLinkLogPlayer::_pause(void)
{
_replayLink->pause();
}
void QGCMAVLinkLogPlayer::_selectLogFileForPlayback(void)
{
// Disallow replay when any links are connected
if (qgcApp()->toolbox()->multiVehicleManager()->activeVehicle()) {
QGCMessageBox::information(tr("Log Replay"), tr("You must close all connections prior to replaying a log."));
return;
}
QString logFilename = QGCQFileDialog::getOpenFileName(
this,
tr("Load Telemetry Log File"),
qgcApp()->toolbox()->settingsManager()->appSettings()->telemetrySavePath(),
tr("MAVLink Log Files (*.tlog);;All Files (*)"));
if (logFilename.isEmpty()) {
return;
}
LogReplayLinkConfiguration* linkConfig = new LogReplayLinkConfiguration(QString("Log Replay"));
linkConfig->setLogFilename(logFilename);
linkConfig->setName(linkConfig->logFilenameShort());
_ui->logFileNameLabel->setText(linkConfig->logFilenameShort());
LinkManager* linkMgr = qgcApp()->toolbox()->linkManager();
SharedLinkConfigurationPointer sharedConfig = linkMgr->addConfiguration(linkConfig);
_replayLink = (LogReplayLink*)qgcApp()->toolbox()->linkManager()->createConnectedLink(sharedConfig);
connect(_replayLink, &LogReplayLink::logFileStats, this, &QGCMAVLinkLogPlayer::_logFileStats);
connect(_replayLink, &LogReplayLink::playbackStarted, this, &QGCMAVLinkLogPlayer::_playbackStarted);
connect(_replayLink, &LogReplayLink::playbackPaused, this, &QGCMAVLinkLogPlayer::_playbackPaused);
connect(_replayLink, &LogReplayLink::playbackPercentCompleteChanged, this, &QGCMAVLinkLogPlayer::_playbackPercentCompleteChanged);
connect(_replayLink, &LogReplayLink::currentLogTimeSecs, this, &QGCMAVLinkLogPlayer::_setCurrentLogTime);
connect(_replayLink, &LogReplayLink::disconnected, this, &QGCMAVLinkLogPlayer::_replayLinkDisconnected);
_ui->positionSlider->setValue(0);
#if 0
_ui->speedSlider->setValue(0);
#endif
}
void QGCMAVLinkLogPlayer::_playbackError(void)
{
_ui->logFileNameLabel->setText("Error");
_enablePlaybackControls(false);
}
QString QGCMAVLinkLogPlayer::_secondsToHMS(int seconds)
{
int secondsPart = seconds;
int minutesPart = secondsPart / 60;
int hoursPart = minutesPart / 60;
secondsPart -= 60 * minutesPart;
minutesPart -= 60 * hoursPart;
return QString("%1h:%2m:%3s").arg(hoursPart, 2).arg(minutesPart, 2).arg(secondsPart, 2);
}
/// Signalled from LogReplayLink once log file information is known
void QGCMAVLinkLogPlayer::_logFileStats(bool logTimestamped, ///< true: timestamped log
int logDurationSeconds, ///< Log duration
int binaryBaudRate) ///< Baud rate for non-timestamped log
{
Q_UNUSED(logTimestamped);
Q_UNUSED(binaryBaudRate);
qDebug() << "_logFileStats" << logDurationSeconds;
_logDurationSeconds = logDurationSeconds;
_ui->logLengthTime->setText(_secondsToHMS(logDurationSeconds));
}
/// Signalled from LogReplayLink when replay starts
void QGCMAVLinkLogPlayer::_playbackStarted(void)
{
_enablePlaybackControls(true);
_ui->playButton->setChecked(true);
_ui->playButton->setIcon(QIcon(":/res/Pause"));
}
/// Signalled from LogReplayLink when replay is paused
void QGCMAVLinkLogPlayer::_playbackPaused(void)
{
_ui->playButton->setIcon(QIcon(":/res/Play"));
_ui->playButton->setChecked(false);
}
void QGCMAVLinkLogPlayer::_playbackPercentCompleteChanged(int percentComplete)
{
_ui->positionSlider->blockSignals(true);
_ui->positionSlider->setValue(percentComplete);
_ui->positionSlider->blockSignals(false);
}
void QGCMAVLinkLogPlayer::_setPlayheadFromSlider(int value)
{
if (_replayLink) {
_replayLink->movePlayhead(value);
}
}
void QGCMAVLinkLogPlayer::_enablePlaybackControls(bool enabled)
{
_ui->playButton->setEnabled(enabled);
#if 0
_ui->speedSlider->setEnabled(enabled);
#endif
_ui->positionSlider->setEnabled(enabled);
}
#if 0
void QGCMAVLinkLogPlayer::_setAccelerationFromSlider(int value)
{
//qDebug() << value;
if (_replayLink) {
_replayLink->setAccelerationFactor(value);
}
// Factor: -100: 0.01x, 0: 1.0x, 100: 100x
float accelerationFactor;
if (value < 0) {
accelerationFactor = 0.01f;
value -= -100;
if (value > 0) {
accelerationFactor *= (float)value;
}
} else if (value > 0) {
accelerationFactor = 1.0f * (float)value;
} else {
accelerationFactor = 1.0f;
}
_ui->speedLabel->setText(QString("Speed: %1X").arg(accelerationFactor, 5, 'f', 2, '0'));
}
#endif
void QGCMAVLinkLogPlayer::_replayLinkDisconnected(void)
{
_enablePlaybackControls(false);
_replayLink = NULL;
}
void QGCMAVLinkLogPlayer::_setCurrentLogTime(int secs)
{
if (secs != _lastCurrentTime) {
_lastCurrentTime = secs;
_ui->logCurrentTime->setText(_secondsToHMS(secs));
}
}
#pragma once
#include <QWidget>
#include <QFile>
#include "MAVLinkProtocol.h"
#include "LinkInterface.h"
#include "LogReplayLink.h"
namespace Ui
{
class QGCMAVLinkLogPlayer;
}
/**
* @brief Replays MAVLink log files
*
* This class allows to replay MAVLink logs at varying speeds.
* captured flights can be replayed, shown to others and analyzed
* in-depth later on.
*/
class QGCMAVLinkLogPlayer : public QWidget
{
Q_OBJECT
public:
explicit QGCMAVLinkLogPlayer(QWidget *parent = 0);
~QGCMAVLinkLogPlayer();
private slots:
void _selectLogFileForPlayback(void);
void _playPauseToggle(void);
void _pause(void);
void _setPlayheadFromSlider(int value);
#if 0
void _setAccelerationFromSlider(int value);
#endif
void _logFileStats(bool logTimestamped, int logDurationSeconds, int binaryBaudRate);
void _playbackStarted(void);
void _playbackPaused(void);
void _playbackPercentCompleteChanged(int percentComplete);
void _playbackError(void);
void _replayLinkDisconnected(void);
void _setCurrentLogTime(int secs);
private:
void _finishPlayback(void);
QString _secondsToHMS(int seconds);
void _enablePlaybackControls(bool enabled);
LogReplayLink* _replayLink;
int _logDurationSeconds;
int _lastCurrentTime;
Ui::QGCMAVLinkLogPlayer* _ui;
};
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QGCMAVLinkLogPlayer</class>
<widget class="QWidget" name="QGCMAVLinkLogPlayer">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>948</width>
<height>38</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>12</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>4</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="logCurrentTime">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="playButton">
<property name="toolTip">
<string>Start to replay Flight Data</string>
</property>
<property name="statusTip">
<string>Start to replay Flight Data</string>
</property>
<property name="whatsThis">
<string>Start to replay Flight Data</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../qgcresources.qrc">
<normaloff>:/res/Play</normaloff>:/res/Play</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="timeLabel">
<property name="text">
<string>Time</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="positionSlider">
<property name="maximum">
<number>10000</number>
</property>
<property name="pageStep">
<number>100</number>
</property>
<property name="tracking">
<bool>true</bool>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="logFileNameLabel">
<property name="text">
<string>No Flight Data selected..</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="logLengthTime">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="selectFileButton">
<property name="toolTip">
<string>Select the Flight Data to replay</string>
</property>
<property name="statusTip">
<string>Select the Flight Data to replay</string>
</property>
<property name="whatsThis">
<string>Select the Flight Data to replay</string>
</property>
<property name="text">
<string>Replay Flight Data</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../../qgcresources.qrc"/>
</resources>
<connections/>
</ui>
/****************************************************************************
*
* (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 "QGCUASFileView.h"
#include "FileManager.h"
#include "QGCQFileDialog.h"
#include "UAS.h"
#include <QFileDialog>
#include <QDir>
#include <QDebug>
QGCUASFileView::QGCUASFileView(QWidget *parent, Vehicle* vehicle)
: QWidget(parent)
, _manager(vehicle->uas()->getFileManager())
, _currentCommand(commandNone)
{
_ui.setupUi(this);
if (vehicle->px4Firmware()) {
_ui.progressBar->reset();
// Connect UI signals
connect(_ui.listFilesButton, &QPushButton::clicked, this, &QGCUASFileView::_refreshTree);
connect(_ui.downloadButton, &QPushButton::clicked, this, &QGCUASFileView::_downloadFile);
connect(_ui.uploadButton, &QPushButton::clicked, this, &QGCUASFileView::_uploadFile);
connect(_ui.treeWidget, &QTreeWidget::currentItemChanged, this, &QGCUASFileView::_currentItemChanged);
// Connect signals from FileManager
connect(_manager, &FileManager::commandProgress, this, &QGCUASFileView::_commandProgress);
connect(_manager, &FileManager::commandComplete, this, &QGCUASFileView::_commandComplete);
connect(_manager, &FileManager::commandError, this, &QGCUASFileView::_commandError);
connect(_manager, &FileManager::listEntry, this, &QGCUASFileView::_listEntryReceived);
} else {
_setAllButtonsEnabled(false);
_ui.statusText->setText(QStringLiteral("Onboard Files not supported by this Vehicle"));
}
}
/// @brief Downloads the file currently selected in the tree view
void QGCUASFileView::_downloadFile(void)
{
if (_currentCommand != commandNone) {
qWarning() << QString("Download attempted while another command was in progress: _currentCommand(%1)").arg(_currentCommand);
return;
}
_ui.statusText->clear();
QString downloadToHere = QGCQFileDialog::getExistingDirectory(this,
tr("Download Directory"),
QDir::homePath(),
QGCQFileDialog::ShowDirsOnly | QGCQFileDialog::DontResolveSymlinks);
// And now download to this location
QString path;
QString downloadFilename;
QTreeWidgetItem* item = _ui.treeWidget->currentItem();
if (item && item->type() == _typeFile) {
do {
QString name = item->text(0).split("\t")[0]; // Strip off file sizes
// If this is the file name and not a directory keep track of the download file name
if (downloadFilename.isEmpty()) {
downloadFilename = name;
}
path.prepend("/" + name);
item = item->parent();
} while (item);
_setAllButtonsEnabled(false);
_currentCommand = commandDownload;
_ui.statusText->setText(tr("Downloading: %1").arg(downloadFilename));
_manager->streamPath(path, QDir(downloadToHere));
}
}
/// @brief uploads a file into the currently selected directory the tree view
void QGCUASFileView::_uploadFile(void)
{
if (_currentCommand != commandNone) {
qWarning() << QString("Upload attempted while another command was in progress: _currentCommand(%1)").arg(_currentCommand);
return;
}
_ui.statusText->clear();
// get and check directory from list view
QTreeWidgetItem* item = _ui.treeWidget->currentItem();
if (item && item->type() != _typeDir) {
return;
}
// Find complete path for upload directory
QString path;
do {
QString name = item->text(0).split("\t")[0]; // Strip off file sizes
path.prepend("/" + name);
item = item->parent();
} while (item);
QString uploadFromHere = QGCQFileDialog::getOpenFileName(this, tr("Upload File"), QDir::homePath());
_ui.statusText->setText(tr("Uploading: %1").arg(uploadFromHere));
qDebug() << "Upload: " << uploadFromHere << "to path" << path;
_setAllButtonsEnabled(false);
_currentCommand = commandUpload;
_manager->uploadPath(path, uploadFromHere);
}
/// @brief Called to update the progress of the download.
/// @param value Progress bar value
void QGCUASFileView::_commandProgress(int value)
{
_ui.progressBar->setValue(value);
}
/// @brief Called when an error occurs during a download.
/// @param msg Error message
void QGCUASFileView::_commandError(const QString& msg)
{
_setAllButtonsEnabled(true);
_currentCommand = commandNone;
_ui.statusText->setText(tr("Error: %1").arg(msg));
}
/// @brief Refreshes the directory list tree.
void QGCUASFileView::_refreshTree(void)
{
if (_currentCommand != commandNone) {
qWarning() << QString("List attempted while another command was in progress: _currentCommand(%1)").arg(_currentCommand);
return;
}
_ui.treeWidget->clear();
_ui.statusText->clear();
_walkIndexStack.clear();
_walkItemStack.clear();
_walkIndexStack.append(0);
_walkItemStack.append(_ui.treeWidget->invisibleRootItem());
_setAllButtonsEnabled(false);
_currentCommand = commandList;
_requestDirectoryList("/");
}
/// @brief Adds the specified directory entry to the tree view.
void QGCUASFileView::_listEntryReceived(const QString& entry)
{
if (_currentCommand != commandList) {
qWarning() << QString("List entry received while no list command in progress: _currentCommand(%1)").arg(_currentCommand);
return;
}
int type;
if (entry.startsWith("F")) {
type = _typeFile;
} else if (entry.startsWith("D")) {
type = _typeDir;
if (entry == "D." || entry == "D..") {
return;
}
} else {
Q_ASSERT(false);
return; // Silence maybe-unitialized on type
}
QTreeWidgetItem* item;
item = new QTreeWidgetItem(_walkItemStack.last(), type);
Q_CHECK_PTR(item);
item->setText(0, entry.right(entry.size() - 1));
}
/// @brief Called when a command completes successfully
void QGCUASFileView::_commandComplete(void)
{
QString statusText;
if (_currentCommand == commandDownload) {
_currentCommand = commandNone;
_setAllButtonsEnabled(true);
statusText = "Download complete";
} else if (_currentCommand == commandUpload) {
_currentCommand = commandNone;
_setAllButtonsEnabled(true);
statusText = "Upload complete";
} else if (_currentCommand == commandList) {
_listComplete();
}
_ui.statusText->setText(statusText);
_ui.progressBar->reset();
}
void QGCUASFileView::_listComplete(void)
{
// Walk the current items, traversing down into directories
Again:
int walkIndex = _walkIndexStack.last();
QTreeWidgetItem* parentItem = _walkItemStack.last();
QTreeWidgetItem* childItem = parentItem->child(walkIndex);
// Loop until we hit a directory
while (childItem && childItem->type() != _typeDir) {
// Move to next index at current level
_walkIndexStack.last() = ++walkIndex;
childItem = parentItem->child(walkIndex);
}
if (childItem) {
// Move to the next item for processing at this level
_walkIndexStack.last() = ++walkIndex;
// Push this new directory on the stack
_walkItemStack.append(childItem);
_walkIndexStack.append(0);
// Ask for the directory list
QString dir;
for (int i=1; i<_walkItemStack.count(); i++) {
QTreeWidgetItem* item = _walkItemStack[i];
dir.append("/" + item->text(0));
}
_requestDirectoryList(dir);
} else {
// We have run out of items at the this level, pop the stack and keep going at that level
_walkIndexStack.removeLast();
_walkItemStack.removeLast();
if (_walkIndexStack.count() != 0) {
goto Again;
} else {
_setAllButtonsEnabled(true);
_currentCommand = commandNone;
}
}
}
void QGCUASFileView::_currentItemChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous)
{
Q_UNUSED(previous);
_ui.downloadButton->setEnabled(current ? (current->type() == _typeFile) : false);
_ui.uploadButton->setEnabled(current ? (current->type() == _typeDir) : false);
}
void QGCUASFileView::_requestDirectoryList(const QString& dir)
{
_manager->listDirectory(dir);
}
void QGCUASFileView::_setAllButtonsEnabled(bool enabled)
{
_ui.treeWidget->setEnabled(enabled);
_ui.downloadButton->setEnabled(enabled);
_ui.listFilesButton->setEnabled(enabled);
_ui.uploadButton->setEnabled(enabled);
if (enabled) {
_currentItemChanged(_ui.treeWidget->currentItem(), NULL);
}
}
/****************************************************************************
*
* (c) 2009-2018 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.
*
****************************************************************************/
#pragma once
#include <QWidget>
#include <QTreeWidgetItem>
#include "Vehicle.h"
#include "uas/FileManager.h"
#include "ui_QGCUASFileView.h"
class QGCUASFileView : public QWidget
{
Q_OBJECT
public:
explicit QGCUASFileView(QWidget *parent, Vehicle* vehicle);
protected:
FileManager* _manager;
private slots:
void _listEntryReceived(const QString& entry);
void _refreshTree(void);
void _downloadFile(void);
void _uploadFile(void);
void _commandProgress(int value);
void _commandError(const QString& msg);
void _commandComplete(void);
void _currentItemChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous);
private:
void _listComplete(void);
void _requestDirectoryList(const QString& dir);
void _setAllButtonsEnabled(bool enabled);
static const int _typeFile = QTreeWidgetItem::UserType + 1;
static const int _typeDir = QTreeWidgetItem::UserType + 2;
static const int _typeError = QTreeWidgetItem::UserType + 3;
QList<int> _walkIndexStack;
QList<QTreeWidgetItem*> _walkItemStack;
Ui::QGCUASFileView _ui;
enum CommandState {
commandNone, ///< No command active
commandList, ///< List command active
commandDownload, ///< Download command active
commandUpload ///< Upload command active
};
CommandState _currentCommand; ///< Current active command
};
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QGCUASFileView</class>
<widget class="QWidget" name="QGCUASFileView">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>216</width>
<height>518</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="5" column="1">
<widget class="QPushButton" name="listFilesButton">
<property name="text">
<string>List Files</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="3">
<widget class="QProgressBar" name="progressBar">
<property name="value">
<number>24</number>
</property>
<property name="textVisible">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="0" colspan="3">
<widget class="QTreeWidget" name="treeWidget">
<property name="contextMenuPolicy">
<enum>Qt::NoContextMenu</enum>
</property>
<property name="headerHidden">
<bool>true</bool>
</property>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
</item>
<item row="5" column="2">
<widget class="QPushButton" name="downloadButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Download File</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="3">
<widget class="QLabel" name="statusText">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QPushButton" name="uploadButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Upload File</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
#include "QGCUASFileViewMulti.h"
#include "ui_QGCUASFileViewMulti.h"
#include "UASInterface.h"
#include "MultiVehicleManager.h"
#include "QGCUASFileView.h"
#include "QGCApplication.h"
QGCUASFileViewMulti::QGCUASFileViewMulti(const QString& title, QAction* action, QWidget *parent) :
QGCDockWidget(title, action, parent),
ui(new Ui::QGCUASFileViewMulti)
{
ui->setupUi(this);
setMinimumSize(600, 80);
connect(qgcApp()->toolbox()->multiVehicleManager(), &MultiVehicleManager::activeVehicleChanged, this, &QGCUASFileViewMulti::_activeVehicleChanged);
connect(qgcApp()->toolbox()->multiVehicleManager(), &MultiVehicleManager::vehicleAdded, this, &QGCUASFileViewMulti::_vehicleAdded);
connect(qgcApp()->toolbox()->multiVehicleManager(), &MultiVehicleManager::vehicleRemoved, this, &QGCUASFileViewMulti::_vehicleRemoved);
if (qgcApp()->toolbox()->multiVehicleManager()->activeVehicle()) {
_vehicleAdded(qgcApp()->toolbox()->multiVehicleManager()->activeVehicle());
_activeVehicleChanged(qgcApp()->toolbox()->multiVehicleManager()->activeVehicle());
}
loadSettings();
}
void QGCUASFileViewMulti::_vehicleRemoved(Vehicle* vehicle)
{
UAS* uas = vehicle->uas();
Q_ASSERT(uas);
QGCUASFileView* list = lists.value(uas, NULL);
if (list)
{
delete list;
lists.remove(uas);
}
}
void QGCUASFileViewMulti::_vehicleAdded(Vehicle* vehicle)
{
UAS* uas = vehicle->uas();
if (!lists.contains(uas)) {
QGCUASFileView* list = new QGCUASFileView(ui->stackedWidget, vehicle);
lists.insert(uas, list);
ui->stackedWidget->addWidget(list);
}
}
void QGCUASFileViewMulti::_activeVehicleChanged(Vehicle* vehicle)
{
if (vehicle) {
QGCUASFileView* list = lists.value(vehicle->uas(), NULL);
if (list) {
ui->stackedWidget->setCurrentWidget(list);
}
}
}
QGCUASFileViewMulti::~QGCUASFileViewMulti()
{
delete ui;
}
void QGCUASFileViewMulti::changeEvent(QEvent *e)
{
QWidget::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
ui->retranslateUi(this);
break;
default:
break;
}
}
#pragma once
#include <QMap>
#include "QGCDockWidget.h"
#include "QGCUASFileView.h"
#include "UAS.h"
namespace Ui
{
class QGCUASFileViewMulti;
}
class QGCUASFileViewMulti : public QGCDockWidget
{
Q_OBJECT
public:
explicit QGCUASFileViewMulti(const QString& title, QAction* action, QWidget *parent = 0);
~QGCUASFileViewMulti();
protected:
void changeEvent(QEvent *e);
QMap<UAS*, QGCUASFileView*> lists;
private slots:
void _vehicleAdded(Vehicle* vehicle);
void _vehicleRemoved(Vehicle* vehicle);
void _activeVehicleChanged(Vehicle* vehicle);
private:
Ui::QGCUASFileViewMulti *ui;
};
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QGCUASFileViewMulti</class>
<widget class="QWidget" name="QGCUASFileViewMulti">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>200</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Onboard Files</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QStackedWidget" name="stackedWidget"/>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
#include "ChartPlot.h"
#include "QGCApplication.h"
#include "SettingsManager.h"
const QColor ChartPlot::baseColors[numColors] = {
QColor(242, 255, 128),
QColor(70, 80, 242),
QColor(232, 33, 47),
QColor(116, 251, 110),
QColor(81, 183, 244),
QColor(234, 38, 107),
QColor(92, 247, 217),
QColor(151, 59, 239),
QColor(231, 72, 28),
QColor(236, 48, 221),
QColor(75, 133, 243),
QColor(203, 254, 121),
QColor(104, 64, 240),
QColor(200, 54, 238),
QColor(104, 250, 138),
QColor(235, 43, 165),
QColor(98, 248, 176),
QColor(161, 252, 116),
QColor(87, 231, 246),
QColor(230, 126, 23)
};
ChartPlot::ChartPlot(QWidget* parent):
QwtPlot(parent),
_nextColorIndex(0),
_symbolWidth(2.0f),
_curveWidth(2.0f),
_gridWidth(0.8f)
{
// Initialize the list of curves.
_curves = QMap<QString, QwtPlotCurve*>();
// Set the grid. The colorscheme was already set in generateColorScheme().
_grid = new QwtPlotGrid;
_grid->enableXMin(true);
_grid->attach(this);
_colors = QList<QColor>();
///> Color map for plots, includes 20 colors
///> Map will start from beginning when the first 20 colors are exceeded
for(int i = 0; i < numColors; ++i) {
_colors.append(baseColors[i]);
}
// Now that all objects have been initialized, color everything.
styleChanged(qgcApp()->toolbox()->settingsManager()->appSettings()->indoorPalette()->rawValue().toBool());
}
ChartPlot::~ChartPlot()
{
}
QColor ChartPlot::getNextColor()
{
if(_nextColorIndex >= _colors.count()) {
_nextColorIndex = 0;
}
return _colors[_nextColorIndex++];
}
QColor ChartPlot::getColorForCurve(const QString& id)
{
return _curves.value(id)->pen().color();
}
void ChartPlot::shuffleColors()
{
foreach(QwtPlotCurve* curve, _curves) {
if(curve->isVisible()) {
QPen pen(curve->pen());
pen.setColor(getNextColor());
curve->setPen(pen);
}
}
}
void ChartPlot::styleChanged(bool styleIsDark)
{
// Generate a new color list for curves and recolor them.
for(int i = 0; i < numColors; ++i) {
_colors[i] = styleIsDark ? baseColors[i].lighter(150) : baseColors[i].darker(150);
}
shuffleColors();
// Configure the rest of the UI colors based on the current theme.
if(styleIsDark) {
// Set canvas background
setCanvasBackground(QColor(0, 0, 0));
// Configure the plot grid.
_grid->setMinorPen(QPen(QColor(64, 64, 64), _gridWidth, Qt::SolidLine));
_grid->setMajorPen(QPen(QColor(96, 96, 96), _gridWidth, Qt::SolidLine));
} else {
// Set canvas background
setCanvasBackground(QColor(0xFF, 0xFF, 0xFF));
// Configure the plot grid.
_grid->setMinorPen(QPen(QColor(192, 192, 192), _gridWidth, Qt::SolidLine));
_grid->setMajorPen(QPen(QColor(128, 128, 128), _gridWidth, Qt::SolidLine));
}
// And finally refresh the widget to make sure all color changes are redrawn.
replot();
}
#pragma once
#include <qwt_plot.h>
#include <qwt_plot_grid.h>
#include <qwt_plot_curve.h>
#include "MainWindow.h"
#include "ScrollZoomer.h"
class ChartPlot : public QwtPlot
{
Q_OBJECT
public:
ChartPlot(QWidget *parent = NULL);
virtual ~ChartPlot();
/** @brief Get next color of color map */
QColor getNextColor();
/** @brief Get color for curve id */
QColor getColorForCurve(const QString &id);
/** @brief Reset color map */
void shuffleColors();
public slots:
/** @brief Generate coloring for this plot canvas based on current window theme */
void styleChanged(bool styleIsDark);
protected:
const static int numColors = 20;
const static QColor baseColors[numColors];
QList<QColor> _colors; ///< Colormap for curves
int _nextColorIndex; ///< Next index in color map
QMap<QString, QwtPlotCurve* > _curves; ///< Plot curves
QwtPlotGrid* _grid; ///< Plot grid
float _symbolWidth; ///< Width of curve symbols in pixels
float _curveWidth; ///< Width of curve lines in pixels
float _gridWidth; ///< Width of gridlines in pixels
};
This diff is collapsed.
/****************************************************************************
*
* (c) 2009-2018 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.
*
****************************************************************************/
/**
* @file
* @brief Defition of class IncrementalPlot
* @author Lorenz Meier <mavteam@student.ethz.ch>
*
*/
#pragma once
#include <QTimer>
#include <qwt_plot.h>
#include <qwt_legend.h>
#include <QMap>
#include "ChartPlot.h"
class QwtPlotCurve;
/**
* @brief Plot data container for growing data
*/
class CurveData
{
public:
CurveData();
void append(double *x, double *y, int count);
/** @brief The number of datasets held in the data structure */
int count() const;
/** @brief The reserved size of the data structure in units */
int size() const;
const double *x() const;
const double *y() const;
private:
int d_count;
QVector<double> d_x;
QVector<double> d_y;
};
/**
* @brief Incremental plotting widget
*
* This widget plots data incrementally when new data arrives.
* It will only repaint the minimum screen content necessary to avoid
* a too high CPU consumption. It auto-scales the plot to new data.
*/
class IncrementalPlot : public ChartPlot
{
Q_OBJECT
public:
/** @brief Create a new, empty incremental plot */
IncrementalPlot(QWidget *parent = NULL);
virtual ~IncrementalPlot();
/** @brief Get the state of the grid */
bool gridEnabled() const;
/** @brief Read out data from a curve */
int data(const QString &key, double* r_x, double* r_y, int maxSize);
public slots:
/** @brief Append one data point */
void appendData(const QString &key, double x, double y);
/** @brief Append multiple data points */
void appendData(const QString &key, double* x, double* y, int size);
/** @brief Reset the plot scaling to the default value */
void resetScaling();
/** @brief Update the plot scale based on current data/symmetric mode */
void updateScale();
/** @brief Remove all data from the plot and repaint */
void removeData();
/** @brief Show the plot legend */
void showLegend(bool show);
/** @brief Show the plot grid */
void showGrid(bool show);
/** @brief Set new plot style */
void setStyleText(const QString &style);
/** @brief Set symmetric axis scaling mode */
void setSymmetric(bool symmetric);
protected slots:
/** @brief Handle the click on a legend item */
void handleLegendClick(QwtPlotItem* item, bool on);
protected:
bool symmetric; ///< Enable symmetric plotting
QwtLegend* legend; ///< Plot legend
double xmin; ///< Minimum x value seen
double xmax; ///< Maximum x value seen
double ymin; ///< Minimum y value seen
double ymax; ///< Maximum y value seen
QString styleText; ///< Curve style set by setStyleText
private:
QMap<QString, CurveData* > d_data; ///< Data points
/** Helper function to apply styleText style to the given curve */
void updateStyle(QwtPlotCurve *curve);
};
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>linechart</class>
<widget class="QWidget" name="linechart">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1337</width>
<height>585</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>3</horstretch>
<verstretch>2</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>300</width>
<height>200</height>
</size>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item>
<widget class="QSplitter" name="splitter">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="midLineWidth">
<number>1</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="handleWidth">
<number>10</number>
</property>
<widget class="QWidget" name="curveGroupBox" native="true">
<layout class="QGridLayout" name="gridLayout" rowstretch="50,0,0,0">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item row="0" column="0">
<widget class="QScrollArea" name="curveListWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>60</width>
<height>150</height>
</size>
</property>
<property name="baseSize">
<size>
<width>60</width>
<height>150</height>
</size>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>879</width>
<height>462</height>
</rect>
</property>
</widget>
</widget>
</item>
<item row="3" column="0">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>4</number>
</property>
<item>
<widget class="QLineEdit" name="plotFilterLineEdit">
<property name="placeholderText">
<string>Filter... (Ctrl+F)</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="uasSelectionBox">
<item>
<property name="text">
<string>All MAVs</string>
</property>
</item>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0">
<property name="spacing">
<number>0</number>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>6</number>
</property>
<item>
<widget class="QCheckBox" name="shortNameCheckBox">
<property name="toolTip">
<string>Display only variable names in curve list</string>
</property>
<property name="text">
<string>Short names</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="showUnitsCheckBox">
<property name="toolTip">
<string>Display variable units in curve list</string>
</property>
<property name="whatsThis">
<string>Display variable units in curve list</string>
</property>
<property name="text">
<string>Show units</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="spacing">
<number>6</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</enum>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="recolorButton">
<property name="toolTip">
<string>Rotate color scheme for all curves</string>
</property>
<property name="text">
<string>Recolor</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="diagramGroupBox" native="true"/>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
This diff is collapsed.
/****************************************************************************
*
* (c) 2009-2018 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.
*
****************************************************************************/
/**
* @file
* @brief Plot of a Linechart
*
* @author Lorenz Meier <mavteam@student.ethz.ch>
*
*/
#pragma once
#define QUINT64_MIN Q_UINT64_C(0)
#define QUINT64_MAX Q_UINT64_C(18446744073709551615)
#include <QMap>
#include <QList>
#include <QMutex>
#include <QTime>
#include <QTimer>
#include <qwt_plot_panner.h>
#include <qwt_plot_curve.h>
#include <qwt_scale_draw.h>
#include <qwt_scale_widget.h>
#include <qwt_scale_engine.h>
#include <qwt_plot.h>
#include "ChartPlot.h"
#include "MG.h"
class TimeScaleDraw: public QwtScaleDraw
{
public:
virtual QwtText label(double v) const {
QDateTime time = MG::TIME::msecToQDateTime(static_cast<quint64>(v));
return time.toString("hh:mm:ss"); // was hh:mm:ss:zzz
// Show seconds since system startup
//return QString::number(static_cast<int>(v)/1000000);
}
};
/**
* @brief Data container
*/
class QwtPlotCurve;
/**
* @brief Container class for the time series data
*
**/
class TimeSeriesData
{
public:
TimeSeriesData(QwtPlot* plot, QString friendlyName = "data", quint64 plotInterval = 10000, quint64 maxInterval = 0, double zeroValue = 0);
~TimeSeriesData();
void append(quint64 ms, double value);
QwtScaleMap* getScaleMap();
int getCount() const;
int size() const;
const double* getX() const;
const double* getY() const;
const double* getPlotX() const;
const double* getPlotY() const;
int getPlotCount() const;
int getID();
QString getFriendlyName();
double getMinValue();
double getMaxValue();
double getZeroValue();
/** @brief Get the short-term mean */
double getMean();
/** @brief Get the short-term median */
double getMedian();
/** @brief Get the short-term variance */
double getVariance();
/** @brief Get the current value */
double getCurrentValue();
void setZeroValue(double zeroValue);
void setInterval(quint64 ms);
void setAverageWindowSize(int windowSize);
protected:
QwtPlot* plot;
quint64 startTime;
quint64 stopTime;
quint64 interval;
quint64 plotInterval;
quint64 maxInterval;
int id;
quint64 plotCount;
QString friendlyName;
double lastValue; ///< The last inserted value
double minValue; ///< The smallest value in the dataset
double maxValue; ///< The largest value in the dataset
double zeroValue; ///< The expected value in the dataset
QMutex dataMutex;
QwtScaleMap* scaleMap;
void updateScaleMap();
private:
quint64 count;
QVector<double> ms;
QVector<double> value;
double mean;
double median;
double variance;
unsigned int averageWindow;
QVector<double> outputMs;
QVector<double> outputValue;
};
/**
* @brief Time series plot
**/
class LinechartPlot : public ChartPlot
{
Q_OBJECT
public:
LinechartPlot(QWidget *parent = NULL, int plotid=0, quint64 interval = LinechartPlot::DEFAULT_PLOT_INTERVAL);
virtual ~LinechartPlot();
void setZeroValue(QString id, double zeroValue);
void removeAllData();
QList<QwtPlotCurve*> getCurves();
bool isVisible(QString id);
/** @brief Check if any curve is visible */
bool anyCurveVisible();
int getPlotId();
/** @brief Get the number of values to average over */
int getAverageWindow();
quint64 getMinTime();
quint64 getMaxTime();
quint64 getPlotInterval();
quint64 getDataInterval();
quint64 getWindowPosition();
/** @brief Get the short-term mean of a curve */
double getMean(QString id);
/** @brief Get the short-term median of a curve */
double getMedian(QString id);
/** @brief Get the short-term variance of a curve */
double getVariance(QString id);
/** @brief Get the last inserted value */
double getCurrentValue(QString id);
static const int SCALE_ABSOLUTE = 0;
static const int SCALE_BEST_FIT = 1;
static const int SCALE_LOGARITHMIC = 2;
static const int DEFAULT_REFRESH_RATE = 100; ///< The default refresh rate is 10 Hz / every 100 ms
static const int DEFAULT_PLOT_INTERVAL = 1000 * 8; ///< The default plot interval is 15 seconds
static const int DEFAULT_SCALE_INTERVAL = 1000 * 8;
public slots:
void setRefreshRate(int ms);
/**
* @brief Append data to the plot
*
* The new data point is appended to the curve with the id-String id. If the curve
* doesn't yet exist it is created and added to the plot.
*
* @param uasId id of originating UAS
* @param dataname unique string (also used to label the data)
* @param ms time measure of the data point, in milliseconds
* @param value value of the data point
*/
void appendData(QString dataname, quint64 ms, double value);
void hideCurve(QString id);
void showCurve(QString id);
/** @brief Enable auto-refreshing of plot */
void setActive(bool active);
// Functions referring to the currently active plot
void setVisibleById(QString id, bool visible);
/**
* @brief Set the color of a curve and its symbols.
*
* @param id The id-string of the curve
* @param color The newly assigned color
**/
void setCurveColor(QString id, QColor color);
/** @brief Enforce the use of the receive timestamp */
void enforceGroundTime(bool enforce);
/** @brief Check if the receive timestamp is enforced */
bool groundTime();
// General interaction
void setWindowPosition(quint64 end);
void setPlotInterval(int interval);
void setScaling(int scaling);
void setAutoScroll(bool active);
void paintRealtime();
/** @brief Set logarithmic plot y-axis scaling */
void setLogarithmicScaling();
/** @brief Set linear plot y-axis scaling */
void setLinearScaling();
/** @brief Set the number of values to average over */
void setAverageWindow(int windowSize);
void removeTimedOutCurves();
protected:
QMap<QString, TimeSeriesData*> data;
QMap<QString, QwtScaleMap*> scaleMaps;
QMap<QString, quint64> lastUpdate;
//static const quint64 MAX_STORAGE_INTERVAL = Q_UINT64_C(300000);
static const quint64 MAX_STORAGE_INTERVAL = Q_UINT64_C(0); ///< The maximum interval which is stored
// TODO CHECK THIS!!!
int scaling;
QwtScaleEngine* yScaleEngine;
quint64 minTime; ///< The smallest timestamp occurred so far
quint64 lastTime; ///< Last added timestamp
quint64 maxTime; ///< The biggest timestamp occurred so far
quint64 maxInterval;
quint64 storageInterval;
double maxValue;
double minValue;
double valueInterval;
int averageWindowSize; ///< Size of sliding average / sliding median
quint64 plotInterval;
quint64 plotPosition;
QTimer* updateTimer;
QMutex datalock;
QMutex windowLock;
quint64 timeScaleStep;
bool automaticScrollActive;
QTime lastMaxTimeAdded;
int plotid;
bool m_active; ///< Decides wether the plot is active or not
bool m_groundTime; ///< Enforce the use of the receive timestamp instead of the data timestamp
QTimer timeoutTimer;
// Methods
void addCurve(QString id);
void showEvent(QShowEvent* event);
void hideEvent(QHideEvent* event);
private:
TimeSeriesData* d_data;
QwtPlotCurve* d_curve;
signals:
/**
* @brief This signal is emitted when a new curve is added
*
* @param color The curve color in the diagram
**/
void curveAdded(QString idstring);
/**
* @brief This signal is emitted when a curve is removed
*
* @param name The id-string of the curve
**/
void curveRemoved(QString name);
/**
* @brief This signal is emitted when the plot window position changes
*
* @param position The position of the right edge of the window, in milliseconds
**/
void windowPositionChanged(quint64 position);
};
This diff is collapsed.
/****************************************************************************
*
* (c) 2009-2018 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.
*
****************************************************************************/
/**
* @file
* @brief Definition of Line chart plot widget
*
* @author Lorenz Meier <mavteam@student.ethz.ch>
* @author Thomas Gubler <thomasgubler@student.ethz.ch>
*/
#pragma once
#include <QGridLayout>
#include <QWidget>
#include <QFrame>
#include <QComboBox>
#include <QVBoxLayout>
#include <QCheckBox>
#include <QScrollBar>
#include <QSpinBox>
#include <QMap>
#include <QString>
#include <QAction>
#include <QIcon>
#include <QLabel>
#include <QReadWriteLock>
#include <QToolButton>
#include <QTimer>
#include <qwt_plot_curve.h>
#include "LinechartPlot.h"
#include "UASInterface.h"
#include "ui_Linechart.h"
#include "LogCompressor.h"
/**
* @brief The linechart widget allows to visualize different timeseries as lineplot.
* The display interval, the timeseries and the scaling can be changed interactively
**/
class LinechartWidget : public QWidget
{
Q_OBJECT
public:
LinechartWidget(int systemid, QWidget *parent = 0);
~LinechartWidget();
static const int MIN_TIME_SCROLLBAR_VALUE = 0; ///< The minimum scrollbar value
static const int MAX_TIME_SCROLLBAR_VALUE = 16383; ///< The maximum scrollbar value
public slots:
void addCurve(const QString& curve, const QString& unit);
void removeCurve(QString curve);
/** @brief Recolor all curves */
void recolor();
/** @brief Set short names for curves */
void setShortNames(bool enable);
/** @brief Append data to the given curve. */
void appendData(int uasId, const QString& curve, const QString& unit, const QVariant& value, quint64 usec);
/** @brief Hide curves which do not match the filter pattern */
void filterCurves(const QString &filter);
void toggleLogarithmicScaling(bool toggled);
void takeButtonClick(bool checked);
void setPlotWindowPosition(int scrollBarValue);
void setPlotWindowPosition(quint64 position);
void setPlotInterval(quint64 interval);
/** @brief Start automatic updates once visible */
void showEvent(QShowEvent* event);
/** @brief Stop automatic updates once hidden */
void hideEvent(QHideEvent* event);
void setActive(bool active);
/** @brief Select one MAV for curve display */
void selectActiveSystem(int mav);
/** @brief Set the number of values to average over */
void setAverageWindow(int windowSize);
/** @brief Start logging to file */
void startLogging();
/** @brief Stop logging to file */
void stopLogging();
/** @brief Refresh the view */
void refresh();
/** @brief Write the current configuration to disk */
void writeSettings();
/** @brief Read the current configuration from disk */
void readSettings();
/** @brief Select all curves */
void selectAllCurves(bool all);
/** @brief Sets the focus to the LineEdit for plot-filtering */
void setPlotFilterLineEditFocus();
private slots:
/** Called when the user changes the time scale combobox. */
void timeScaleChanged(int index);
/** @brief Toggles visibility of curve based on bool match if corresponding checkbox is not checked */
void filterCurve(const QString &key, bool match);
protected:
void addCurveToList(QString curve);
void removeCurveFromList(QString curve);
QToolButton* createButton(QWidget* parent);
void createCurveItem(QString curve);
void createLayout();
/** @brief Get the name for a curve key */
QString getCurveName(const QString& key, bool shortEnabled);
int sysid; ///< ID of the unmanned system this plot belongs to
LinechartPlot* activePlot; ///< Plot for this system
QReadWriteLock* curvesLock; ///< A lock (mutex) for the concurrent access on the curves
QReadWriteLock plotWindowLock; ///< A lock (mutex) for the concurrent access on the window position
int curveListIndex;
int curveListCounter; ///< Counter of curves in curve list
QMap<QString, QLabel*>* curveLabels; ///< References to the curve labels
QMap<QString, QLabel*> curveNameLabels; ///< References to the curve labels
QMap<QString, QString> curveNames; ///< Full curve names
QMap<QString, QLabel*>* curveMeans; ///< References to the curve means
QMap<QString, QLabel*>* curveMedians; ///< References to the curve medians
QMap<QString, QWidget*> curveUnits; ///< References to the curve units
QMap<QString, QLabel*>* curveVariances; ///< References to the curve variances
QMap<QString, int> intData; ///< Current values for integer-valued curves
QMap<QString, QWidget*> colorIcons; ///< Reference to color icons
QMap<QString, QCheckBox*> checkBoxes; ///< Reference to checkboxes
QWidget* curvesWidget; ///< The QWidget containing the curve selection button
QGridLayout* curvesWidgetLayout; ///< The layout for the curvesWidget QWidget
QScrollBar* scrollbar; ///< The plot window scroll bar
QSpinBox* averageSpinBox; ///< Spin box to setup average window filter size
QAction* addNewCurve; ///< Add curve candidate to the active curves
QComboBox *timeScaleCmb;
QToolButton* scalingLogButton;
QToolButton* logButton;
QPointer<QCheckBox> timeButton;
QFile* logFile;
unsigned int logindex;
bool logging;
quint64 logStartTime;
QTimer* updateTimer;
LogCompressor* compressor;
QCheckBox* selectAllCheckBox;
int selectedMAV; ///< The MAV for which plot items are accepted, -1 for all systems
quint64 lastTimestamp;
bool userGroundTimeSet;
bool autoGroundTimeSet;
static const int updateInterval = 1000; ///< Time between number updates, in milliseconds
static const int MAX_CURVE_MENUITEM_NUMBER = 8;
static const int PAGESTEP_TIME_SCROLLBAR_VALUE = (MAX_TIME_SCROLLBAR_VALUE - MIN_TIME_SCROLLBAR_VALUE) / 10;
private:
Ui::linechart ui;
void createActions();
signals:
/**
* @brief This signal is emitted if a curve is removed from the list
*
* @param curve The removed plot curve
**/
void curveRemoved(QString curve);
/**
* @brief This signal is emitted if a curve has been moved or added
*
* @param curve The moved or added curve
* @param position The x-position of the curve (The centerline)
**/
void curveSet(QString curve, int position);
/**
* @brief This signal is emitted to change the visibility of a curve
*
* @param curve The changed curve
* @pram visible The visibility
**/
void curveVisible(QString curve, bool visible);
void plotWindowPositionUpdated(quint64 position);
void plotWindowPositionUpdated(int position);
/** @brief This signal is emitted once a logfile has been finished writing */
void logfileWritten(QString fileName);
private slots:
void _filterTimeout(void);
void _restartFilterTimeout(void);
private:
QTimer _filterTimer;
};
#include <QShowEvent>
#include "Linecharts.h"
#include "MultiVehicleManager.h"
#include "MainWindow.h"
#include "UAS.h"
Linecharts::Linecharts(const QString& title, QAction* action, MAVLinkDecoder* decoder, QWidget *parent)
: MultiVehicleDockWidget(title, action, parent)
, _mavlinkDecoder(decoder)
{
init();
this->setVisible(false);
}
QWidget* Linecharts::_newVehicleWidget(Vehicle* vehicle, QWidget* parent)
{
LinechartWidget* widget = new LinechartWidget(vehicle->id(), parent);
// Connect valueChanged signals
connect(vehicle->uas(), &UAS::valueChanged, widget, &LinechartWidget::appendData);
// Connect decoder
connect(_mavlinkDecoder, &MAVLinkDecoder::valueChanged, widget, &LinechartWidget::appendData);
// Select system
widget->setActive(true);
return widget;
}
#pragma once
#include <QStackedWidget>
#include <QMap>
#include <QVector>
#include "LinechartWidget.h"
#include "Vehicle.h"
#include "MultiVehicleDockWidget.h"
#include "MAVLinkDecoder.h"
class Linecharts : public MultiVehicleDockWidget
{
Q_OBJECT
public:
explicit Linecharts(const QString& title, QAction* action, MAVLinkDecoder* decoder, QWidget *parent = 0);
signals:
/** @brief This signal is emitted once a logfile has been finished writing */
void logfileWritten(QString fileName);
void visibilityChanged(bool visible);
protected:
// Override from MultiVehicleDockWidget
virtual QWidget* _newVehicleWidget(Vehicle* vehicle, QWidget* parent);
private:
MAVLinkDecoder* _mavlinkDecoder;
};
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#pragma once
#include <qscrollbar.h>
class ScrollBar: public QScrollBar
{
Q_OBJECT
public:
ScrollBar(QWidget *parent = NULL);
ScrollBar(Qt::Orientation, QWidget *parent = NULL);
ScrollBar(double minBase, double maxBase,
Qt::Orientation o, QWidget *parent = NULL);
void setInverted(bool);
bool isInverted() const;
double minBaseValue() const;
double maxBaseValue() const;
double minSliderValue() const;
double maxSliderValue() const;
int extent() const;
signals:
void sliderMoved(Qt::Orientation, double, double);
void valueChanged(Qt::Orientation, double, double);
public slots:
virtual void setBase(double min, double max);
virtual void moveSlider(double min, double max);
protected:
void sliderRange(int value, double &min, double &max) const;
int mapToTick(double) const;
double mapFromTick(int) const;
private slots:
void catchValueChanged(int value);
void catchSliderMoved(int value);
private:
void init();
bool d_inverted;
double d_minBase;
double d_maxBase;
int d_baseTicks;
};
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