Commit 065d8daf authored by dogmaphobic's avatar dogmaphobic

Adding UDP, TCP and Log Replay Settings

parent 7e110aa4
......@@ -18,6 +18,7 @@
<file alias="FlightModesComponentSummary.qml">src/AutoPilotPlugins/PX4/FlightModesComponentSummary.qml</file>
<file alias="GeneralSettings.qml">src/ui/preferences/GeneralSettings.qml</file>
<file alias="LinkSettings.qml">src/ui/preferences/LinkSettings.qml</file>
<file alias="UdpSettings.qml">src/ui/preferences/UdpSettings.qml</file>
<file alias="JoystickConfig.qml">src/VehicleSetup/JoystickConfig.qml</file>
<file alias="MainToolBar.qml">src/ui/toolbar/MainToolBar.qml</file>
<file alias="MainWindow.qml">src/ui/MainWindow.qml</file>
......
......@@ -40,11 +40,12 @@ public:
LinkConfiguration(LinkConfiguration* copy);
virtual ~LinkConfiguration() {}
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
Q_PROPERTY(LinkInterface* link READ link WRITE setLink NOTIFY linkChanged)
Q_PROPERTY(LinkType linkType READ type CONSTANT)
Q_PROPERTY(bool dynamic READ isDynamic WRITE setDynamic NOTIFY dynamicChanged)
Q_PROPERTY(bool autoConnect READ isAutoConnect WRITE setAutoConnect NOTIFY autoConnectChanged)
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
Q_PROPERTY(LinkInterface* link READ link WRITE setLink NOTIFY linkChanged)
Q_PROPERTY(LinkType linkType READ type CONSTANT)
Q_PROPERTY(bool dynamic READ isDynamic WRITE setDynamic NOTIFY dynamicChanged)
Q_PROPERTY(bool autoConnect READ isAutoConnect WRITE setAutoConnect NOTIFY autoConnectChanged)
Q_PROPERTY(bool autoConnectAllowed READ isAutoConnectAllowed CONSTANT)
// Property accessors
......@@ -98,6 +99,13 @@ public:
/// Virtual Methods
/*!
*
* Is Auto Connect allowed for this type?
* @return True if this type can be set as an Auto Connect configuration
*/
virtual bool isAutoConnectAllowed() { return true; }
/*!
* @brief Connection type
*
......
......@@ -36,20 +36,26 @@ class LogReplayLinkConfiguration : public LinkConfiguration
Q_OBJECT
public:
Q_PROPERTY(QString fileName READ logFilename WRITE setLogFilename NOTIFY fileNameChanged)
LogReplayLinkConfiguration(const QString& name);
LogReplayLinkConfiguration(LogReplayLinkConfiguration* copy);
QString logFilename(void) { return _logFilename; }
void setLogFilename(const QString& logFilename) { _logFilename = logFilename; }
void setLogFilename(const QString& logFilename) { _logFilename = logFilename; emit fileNameChanged(); }
QString logFilenameShort(void);
// Virtuals from LinkConfiguration
virtual LinkType type() { return LinkConfiguration::TypeLogReplay; }
virtual void copyFrom(LinkConfiguration* source);
virtual void loadSettings(QSettings& settings, const QString& root);
virtual void saveSettings(QSettings& settings, const QString& root);
virtual void updateSettings();
LinkType type () { return LinkConfiguration::TypeLogReplay; }
void copyFrom (LinkConfiguration* source);
void loadSettings (QSettings& settings, const QString& root);
void saveSettings (QSettings& settings, const QString& root);
void updateSettings ();
bool isAutoConnectAllowed () { return false; }
signals:
void fileNameChanged();
private:
static const char* _logFilenameKey;
......
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
#include <QTimer>
......@@ -61,7 +61,7 @@ TCPLink::~TCPLink()
void TCPLink::run()
{
_hardwareConnect();
exec();
exec();
}
#ifdef TCPLINK_READWRITE_DEBUG
......@@ -126,14 +126,14 @@ void TCPLink::readBytes()
**/
void TCPLink::_disconnect(void)
{
quit();
wait();
quit();
wait();
if (_socket) {
_socketIsConnected = false;
_socket->deleteLater(); // Make sure delete happens on correct thread
_socket = NULL;
_socket->deleteLater(); // Make sure delete happens on correct thread
_socket = NULL;
emit disconnected();
}
}
}
/**
......@@ -143,11 +143,11 @@ void TCPLink::_disconnect(void)
**/
bool TCPLink::_connect(void)
{
if (isRunning())
{
quit();
wait();
}
if (isRunning())
{
quit();
wait();
}
start(HighPriority);
return true;
}
......@@ -155,7 +155,7 @@ bool TCPLink::_connect(void)
bool TCPLink::_hardwareConnect()
{
Q_ASSERT(_socket == NULL);
_socket = new QTcpSocket();
_socket = new QTcpSocket();
QSignalSpy errorSpy(_socket, SIGNAL(error(QAbstractSocket::SocketError)));
_socket->connectToHost(_config->address(), _config->port());
QObject::connect(_socket, SIGNAL(readyRead()), this, SLOT(readBytes()));
......@@ -268,6 +268,11 @@ void TCPConfiguration::setAddress(const QHostAddress& address)
_address = address;
}
void TCPConfiguration::setHost(const QString host)
{
_address = host;
}
void TCPConfiguration::saveSettings(QSettings& settings, const QString& root)
{
settings.beginGroup(root);
......
......@@ -56,6 +56,9 @@ class TCPConfiguration : public LinkConfiguration
public:
Q_PROPERTY(quint16 port READ port WRITE setPort NOTIFY portChanged)
Q_PROPERTY(QString host READ host WRITE setHost NOTIFY hostChanged)
/*!
* @brief Regular constructor
*
......@@ -94,6 +97,7 @@ public:
* @return Host address
*/
const QHostAddress& address () { return _address; }
const QString host () { return _address.toString(); }
/*!
* @brief Set the host address
......@@ -101,6 +105,7 @@ public:
* @param[in] address Host address
*/
void setAddress (const QHostAddress& address);
void setHost (const QString host);
/// From LinkConfiguration
LinkType type() { return LinkConfiguration::TypeTcp; }
......@@ -109,6 +114,10 @@ public:
void saveSettings(QSettings& settings, const QString& root);
void updateSettings();
signals:
void portChanged();
void hostChanged();
private:
QHostAddress _address;
quint16 _port;
......
......@@ -406,9 +406,9 @@ UDPConfiguration::UDPConfiguration(const QString& name) : LinkConfiguration(name
UDPConfiguration::UDPConfiguration(UDPConfiguration* source) : LinkConfiguration(source)
{
_localPort = source->localPort();
_hosts.clear();
QString host;
int port;
_hostList.clear();
if(source->firstHost(host, port)) {
do {
addHost(host, port);
......@@ -435,7 +435,7 @@ void UDPConfiguration::copyFrom(LinkConfiguration *source)
/**
* @param host Hostname in standard formatt, e.g. localhost:14551 or 192.168.1.1:14551
*/
void UDPConfiguration::addHost(const QString& host)
void UDPConfiguration::addHost(const QString host)
{
// Handle x.x.x.x:p
if (host.contains(":"))
......@@ -495,9 +495,10 @@ void UDPConfiguration::addHost(const QString& host, int port)
}
}
}
_updateHostList();
}
void UDPConfiguration::removeHost(const QString& host)
void UDPConfiguration::removeHost(const QString host)
{
QMutexLocker locker(&_confMutex);
QString tHost = host;
......@@ -512,6 +513,7 @@ void UDPConfiguration::removeHost(const QString& host)
} else {
qWarning() << "UDP:" << "Could not remove unknown host:" << host;
}
_updateHostList();
}
bool UDPConfiguration::firstHost(QString& host, int& port)
......@@ -579,6 +581,7 @@ void UDPConfiguration::loadSettings(QSettings& settings, const QString& root)
}
}
settings.endGroup();
_updateHostList();
}
void UDPConfiguration::updateSettings()
......@@ -590,3 +593,15 @@ void UDPConfiguration::updateSettings()
}
}
}
void UDPConfiguration::_updateHostList()
{
_hostList.clear();
QMap<QString, int>::const_iterator it = _hosts.begin();
while(it != _hosts.end()) {
QString host = QString("%1").arg(it.key()) + ":" + QString("%1").arg(it.value());
_hostList += host;
it++;
}
emit hostListChanged();
}
......@@ -56,6 +56,9 @@ class UDPConfiguration : public LinkConfiguration
public:
Q_PROPERTY(quint16 localPort READ localPort WRITE setLocalPort NOTIFY localPortChanged)
Q_PROPERTY(QStringList hostList READ hostList NOTIFY hostListChanged)
/*!
* @brief Regular constructor
*
......@@ -111,7 +114,7 @@ public:
*
* @param[in] host Host name in standard formatt, e.g. localhost:14551 or 192.168.1.1:14551
*/
void addHost (const QString& host);
Q_INVOKABLE void addHost (const QString host);
/*!
* @brief Add a target host
......@@ -126,7 +129,7 @@ public:
*
* @param[in] host Host name, e.g. localhost or 192.168.1.1
*/
void removeHost (const QString& host);
Q_INVOKABLE void removeHost (const QString host);
/*!
* @brief Set the UDP port we bind to
......@@ -135,6 +138,11 @@ public:
*/
void setLocalPort (quint16 port);
/*!
* @brief QML Interface
*/
QStringList hostList () { return _hostList; }
/// From LinkConfiguration
LinkType type() { return LinkConfiguration::TypeUdp; }
void copyFrom(LinkConfiguration* source);
......@@ -142,10 +150,18 @@ public:
void saveSettings(QSettings& settings, const QString& root);
void updateSettings();
signals:
void localPortChanged ();
void hostListChanged ();
private:
void _updateHostList ();
private:
QMutex _confMutex;
QMap<QString, int>::iterator _it;
QMap<QString, int> _hosts; ///< ("host", port)
QStringList _hostList; ///< Exposed to QML
quint16 _localPort;
};
......
......@@ -263,7 +263,7 @@ Rectangle {
if(index === LinkConfiguration.TypeSerial)
linkSettingLoader.sourceComponent = serialLinkSettings
if(index === LinkConfiguration.TypeUdp)
linkSettingLoader.sourceComponent = udpLinkSettings
linkSettingLoader.source = "UdpSettings.qml"
if(index === LinkConfiguration.TypeTcp)
linkSettingLoader.sourceComponent = tcpLinkSettings
if(index === LinkConfiguration.TypeMock)
......@@ -284,6 +284,10 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter
onActivated: {
if (index != -1 && index !== editConfig.linkType) {
// Destroy current panel
linkSettingLoader.sourceComponent = null
linkSettingLoader.source = ""
linkSettingLoader.visible = false
// Save current name
var name = editConfig.name
// Discard link configuration (old type)
......@@ -291,17 +295,17 @@ Rectangle {
// Create new link configuration
editConfig = QGroundControl.linkManager.createConfiguration(index, name)
// Load appropriate configuration panel
linkSettingLoader.sourceComponent = null
if(index === LinkConfiguration.TypeSerial)
linkSettingLoader.sourceComponent = serialLinkSettings
if(index === LinkConfiguration.TypeUdp)
linkSettingLoader.sourceComponent = udpLinkSettings
linkSettingLoader.source = "UdpSettings.qml"
if(index === LinkConfiguration.TypeTcp)
linkSettingLoader.sourceComponent = tcpLinkSettings
if(index === LinkConfiguration.TypeMock)
linkSettingLoader.sourceComponent = mockLinkSettings
if(index === LinkConfiguration.TypeLogReplay)
linkSettingLoader.sourceComponent = logLinkSettings
linkSettingLoader.visible = true
}
}
Component.onCompleted: {
......@@ -311,7 +315,7 @@ Rectangle {
if(index === LinkConfiguration.TypeSerial)
linkSettingLoader.sourceComponent = serialLinkSettings
if(index === LinkConfiguration.TypeUdp)
linkSettingLoader.sourceComponent = udpLinkSettings
linkSettingLoader.source = "UdpSettings.qml"
if(index === LinkConfiguration.TypeTcp)
linkSettingLoader.sourceComponent = tcpLinkSettings
if(index === LinkConfiguration.TypeMock)
......@@ -331,6 +335,7 @@ Rectangle {
QGCCheckBox {
text: "Automatically Connect on Start"
checked: false
enabled: editConfig ? editConfig.autoConnectAllowed : false
onCheckedChanged: {
if(editConfig) {
editConfig.autoConnect = checked
......@@ -362,8 +367,7 @@ Rectangle {
QGCButton {
width: ScreenTools.defaultFontPixelWidth * 10
text: "OK"
//-- TODO: For now, only allow Serial (the only one completed)
enabled: editConfig && editConfig.linkType === LinkConfiguration.TypeSerial
enabled: nameField.text !== ""
onClicked: {
// Save editting
editConfig.name = nameField.text
......@@ -599,42 +603,6 @@ Rectangle {
}
}
//---------------------------------------------
// UDP Link Settings
Component {
id: udpLinkSettings
Column {
width: udpLinkSettings.width
spacing: ScreenTools.defaultFontPixelHeight / 2
QGCLabel {
id: udpLabel
text: "UDP Link Settings"
}
Rectangle {
height: 1
width: udpLabel.width
color: qgcPal.button
}
Item {
height: ScreenTools.defaultFontPixelHeight / 2
width: parent.width
}
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel {
text: "Listening Port:"
width: _firstColumn
}
QGCLabel {
text: "14550"
width: _secondColumn
}
}
QGCLabel {
text: "Target Hosts:"
}
}
}
//---------------------------------------------
// TCP Link Settings
Component {
id: tcpLinkSettings
......@@ -657,23 +625,40 @@ Rectangle {
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel {
text: "TCP Port:"
text: "Host Address:"
width: _firstColumn
anchors.verticalCenter: parent.verticalCenter
}
QGCLabel {
text: "5760"
QGCTextField {
id: hostField
text: subEditConfig && subEditConfig.linkType === LinkConfiguration.TypeTcp ? subEditConfig.host : ""
width: _secondColumn
anchors.verticalCenter: parent.verticalCenter
onTextChanged: {
if(subEditConfig) {
subEditConfig.host = hostField.text
}
}
}
}
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel {
text: "Host Address:"
text: "TCP Port:"
width: _firstColumn
anchors.verticalCenter: parent.verticalCenter
}
QGCLabel {
text: "0.0.0.0"
width: _secondColumn
QGCTextField {
id: portField
text: subEditConfig && subEditConfig.linkType === LinkConfiguration.TypeTcp ? subEditConfig.port.toString() : ""
width: _firstColumn
inputMethodHints: Qt.ImhFormattedNumbersOnly
anchors.verticalCenter: parent.verticalCenter
onTextChanged: {
if(subEditConfig) {
subEditConfig.port = parseInt(portField.text)
}
}
}
}
}
......@@ -692,8 +677,46 @@ Rectangle {
height: ScreenTools.defaultFontPixelHeight / 2
width: parent.width
}
QGCButton {
text: "Select Log File"
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel {
text: "Log File:"
width: _firstColumn
anchors.verticalCenter: parent.verticalCenter
}
QGCTextField {
id: logField
text: subEditConfig && subEditConfig.linkType === LinkConfiguration.TypeMock ? subEditConfig.fileName : ""
width: _secondColumn
anchors.verticalCenter: parent.verticalCenter
onTextChanged: {
if(subEditConfig) {
subEditConfig.filename = logField.text
}
}
}
QGCButton {
text: "Browse"
onClicked: {
fileDialog.visible = true
}
}
}
FileDialog {
id: fileDialog
title: "Please choose a file"
folder: shortcuts.home
visible: false
selectExisting: true
onAccepted: {
if(subEditConfig) {
subEditConfig.fileName = fileDialog.fileUrl.toString().replace("file://", "")
}
fileDialog.visible = false
}
onRejected: {
fileDialog.visible = false
}
}
}
}
......
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.1
import QGroundControl 1.0
import QGroundControl.Controls 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Palette 1.0
Item {
id: _udpSetting
width: parent ? parent.width : 0
height: udpColumn.height
property var _currentHost: ""
Column {
id: udpColumn
spacing: ScreenTools.defaultFontPixelHeight / 2
ExclusiveGroup { id: linkGroup }
QGCPalette {
id: qgcPal
colorGroupEnabled: enabled
}
QGCLabel {
id: udpLabel
text: "UDP Link Settings"
}
Rectangle {
height: 1
width: udpLabel.width
color: qgcPal.button
}
Item {
height: ScreenTools.defaultFontPixelHeight / 2
width: parent.width
}
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel {
text: "Listening Port:"
width: _firstColumn
anchors.verticalCenter: parent.verticalCenter
}
QGCTextField {
id: portField
text: subEditConfig && subEditConfig.linkType === LinkConfiguration.TypeUdp ? subEditConfig.localPort.toString() : ""
focus: true
width: _firstColumn
inputMethodHints: Qt.ImhFormattedNumbersOnly
anchors.verticalCenter: parent.verticalCenter
onTextChanged: {
if(subEditConfig) {
subEditConfig.localPort = parseInt(portField.text)
}
}
}
}
Item {
height: ScreenTools.defaultFontPixelHeight / 2
width: parent.width
}
QGCLabel {
text: "Target Hosts:"
}
Item {
width: hostRow.width
height: hostRow.height
Row {
id: hostRow
spacing: ScreenTools.defaultFontPixelWidth
Item {
height: 1
width: _firstColumn
}
Column {
id: hostColumn
spacing: ScreenTools.defaultFontPixelHeight / 2
Rectangle {
height: 1
width: _secondColumn
color: qgcPal.button
visible: subEditConfig && subEditConfig.linkType === LinkConfiguration.TypeUdp && subEditConfig.hostList.length > 0
}
Repeater {
model: subEditConfig && subEditConfig.linkType === LinkConfiguration.TypeUdp ? subEditConfig.hostList : ""
delegate:
QGCButton {
text: modelData
width: _secondColumn
anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 2
exclusiveGroup: linkGroup
onClicked: {
checked = true
_udpSetting._currentHost = modelData
}
}
}
QGCTextField {
id: hostField
focus: true
visible: false
width: ScreenTools.defaultFontPixelWidth * 30
onEditingFinished: {
if(subEditConfig) {
if(hostField.text !== "") {
subEditConfig.addHost(hostField.text)
hostField.text = ""
}
hostField.visible = false
}
}
Keys.onReleased: {
if (event.key === Qt.Key_Escape) {
hostField.text = ""
hostField.visible = false
}
}
}
Rectangle {
height: 1
width: _secondColumn
color: qgcPal.button
}
Item {
height: ScreenTools.defaultFontPixelHeight / 2
width: parent.width
}
Item {
width: _secondColumn
height: udpButtonRow.height
Row {
id: udpButtonRow
spacing: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
QGCButton {
width: ScreenTools.defaultFontPixelWidth * 10
text: "Add"
onClicked: {
if(hostField.visible && hostField.text !== "") {
subEditConfig.addHost(hostField.text)
hostField.text = ""
hostField.visible = false
} else
hostField.visible = true
}
}
QGCButton {
width: ScreenTools.defaultFontPixelWidth * 10
enabled: _udpSetting._currentHost && _udpSetting._currentHost !== ""
text: "Remove"
onClicked: {
subEditConfig.removeHost(_udpSetting._currentHost)
}
}
}
}
}
}
}
}
}
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