Commit 7e110aa4 authored by Gus Grubba's avatar Gus Grubba

Merge pull request #2329 from dogmaphobic/serialSettings

Serial settings (QML)
parents e6f5eb34 e7b87f33
......@@ -45,6 +45,7 @@ LinkConfiguration::LinkConfiguration(const QString& name)
: _link(NULL)
, _name(name)
, _dynamic(false)
, _autoConnect(false)
{
_name = name;
if (_name.isEmpty()) {
......@@ -57,6 +58,7 @@ LinkConfiguration::LinkConfiguration(LinkConfiguration* copy)
_link = copy->link();
_name = copy->name();
_dynamic = copy->isDynamic();
_autoConnect= copy->isAutoConnect();
Q_ASSERT(!_name.isEmpty());
}
......@@ -66,6 +68,7 @@ void LinkConfiguration::copyFrom(LinkConfiguration* source)
_link = source->link();
_name = source->name();
_dynamic = source->isDynamic();
_autoConnect= source->isAutoConnect();
}
/*!
......
......@@ -40,9 +40,11 @@ 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(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)
// Property accessors
......@@ -77,10 +79,22 @@ public:
*/
bool isDynamic() { return _dynamic; }
/*!
*
* Is this an Auto Connect configuration?
* @return True if this is an Auto Connect configuration (connects automatically at boot time).
*/
bool isAutoConnect() { return _autoConnect; }
/*!
* Set if this is this a dynamic configuration. (decided at runtime)
*/
void setDynamic(bool dynamic = true) { _dynamic = dynamic; }
void setDynamic(bool dynamic = true) { _dynamic = dynamic; emit dynamicChanged(); }
/*!
* Set if this is this an Auto Connect configuration.
*/
void setAutoConnect(bool autoc = true) { _autoConnect = autoc; emit autoConnectChanged(); }
/// Virtual Methods
......@@ -152,14 +166,17 @@ public:
static LinkConfiguration* duplicateSettings(LinkConfiguration *source);
signals:
void nameChanged(const QString& name);
void linkChanged(LinkInterface* link);
void nameChanged (const QString& name);
void linkChanged (LinkInterface* link);
void dynamicChanged ();
void autoConnectChanged ();
protected:
LinkInterface* _link; ///< Link currently using this configuration (if any)
private:
QString _name;
bool _dynamic; ///< A connection added automatically and not persistent (unless it's edited).
bool _dynamic; ///< A connection added automatically and not persistent (unless it's edited).
bool _autoConnect; ///< This connection is started automatically at boot
};
#endif // LINKCONFIGURATION_H
......@@ -300,17 +300,17 @@ void LinkManager::saveLinkConfigurationList()
{
QSettings settings;
settings.remove(LinkConfiguration::settingsRoot());
for (int i=0; i<_linkConfigurations.count(); i++) {
int trueCount = 0;
for (int i = 0; i < _linkConfigurations.count(); i++) {
LinkConfiguration* linkConfig = _linkConfigurations.value<LinkConfiguration*>(i);
if (linkConfig) {
if(!linkConfig->isDynamic())
{
QString root = LinkConfiguration::settingsRoot();
root += QString("/Link%1").arg(i);
root += QString("/Link%1").arg(trueCount++);
settings.setValue(root + "/name", linkConfig->name());
settings.setValue(root + "/type", linkConfig->type());
settings.setValue(root + "/auto", linkConfig->isAutoConnect());
// Have the instance save its own values
linkConfig->saveSettings(settings, root);
}
......@@ -318,17 +318,18 @@ void LinkManager::saveLinkConfigurationList()
qWarning() << "Internal error";
}
}
QString root(LinkConfiguration::settingsRoot());
settings.setValue(root + "/count", _linkConfigurations.count());
emit linkConfigurationChanged();
settings.setValue(root + "/count", trueCount);
emit linkConfigurationsChanged();
}
void LinkManager::loadLinkConfigurationList()
{
bool linksChanged = false;
#ifdef QT_DEBUG
bool mockPresent = false;
#endif
QSettings settings;
// Is the group even there?
if(settings.contains(LinkConfiguration::settingsRoot() + "/count")) {
// Find out how many configurations we have
......@@ -338,12 +339,13 @@ void LinkManager::loadLinkConfigurationList()
root += QString("/Link%1").arg(i);
if(settings.contains(root + "/type")) {
int type = settings.value(root + "/type").toInt();
if(type < LinkConfiguration::TypeLast) {
if((LinkConfiguration::LinkType)type < LinkConfiguration::TypeLast) {
if(settings.contains(root + "/name")) {
QString name = settings.value(root + "/name").toString();
if(!name.isEmpty()) {
LinkConfiguration* pLink = NULL;
switch(type) {
bool autoConnect = settings.value(root + "/auto").toBool();
switch((LinkConfiguration::LinkType)type) {
#ifndef __ios__
case LinkConfiguration::TypeSerial:
pLink = (LinkConfiguration*)new SerialConfiguration(name);
......@@ -361,42 +363,48 @@ void LinkManager::loadLinkConfigurationList()
#ifdef QT_DEBUG
case LinkConfiguration::TypeMock:
pLink = (LinkConfiguration*)new MockConfiguration(name);
mockPresent = true;
break;
#endif
default:
case LinkConfiguration::TypeLast:
break;
}
if(pLink) {
// Have the instance load its own values
//-- Have the instance load its own values
pLink->setAutoConnect(autoConnect);
pLink->loadSettings(settings, root);
_linkConfigurations.append(pLink);
linksChanged = true;
}
} else {
qWarning() << "Link Configuration " << root << " has an empty name." ;
qWarning() << "Link Configuration" << root << "has an empty name." ;
}
} else {
qWarning() << "Link Configuration " << root << " has no name." ;
qWarning() << "Link Configuration" << root << "has no name." ;
}
} else {
qWarning() << "Link Configuration " << root << " an invalid type: " << type;
qWarning() << "Link Configuration" << root << "an invalid type: " << type;
}
} else {
qWarning() << "Link Configuration " << root << " has no type." ;
qWarning() << "Link Configuration" << root << "has no type." ;
}
}
}
// Debug buids always add MockLink automatically
// Debug buids always add MockLink automatically (if one is not already there)
#ifdef QT_DEBUG
MockConfiguration* pMock = new MockConfiguration("Mock Link PX4");
pMock->setDynamic(true);
_linkConfigurations.append(pMock);
linksChanged = true;
if(!mockPresent)
{
MockConfiguration* pMock = new MockConfiguration("Mock Link PX4");
pMock->setDynamic(true);
_linkConfigurations.append(pMock);
linksChanged = true;
}
#endif
if(linksChanged) {
emit linkConfigurationChanged();
emit linkConfigurationsChanged();
}
// Enable automatic Serial PX4/3DR Radio hunting
_configurationsLoaded = true;
}
......@@ -431,7 +439,6 @@ void LinkManager::_updateAutoConnectLinks(void)
bool foundUDP = false;
for (int i=0; i<_links.count(); i++) {
LinkConfiguration* linkConfig = _links.value<LinkInterface*>(i)->getLinkConfiguration();
if (linkConfig->type() == LinkConfiguration::TypeUdp && linkConfig->name() == _defaultUPDLinkName) {
foundUDP = true;
break;
......@@ -442,7 +449,9 @@ void LinkManager::_updateAutoConnectLinks(void)
UDPConfiguration* udpConfig = new UDPConfiguration(_defaultUPDLinkName);
udpConfig->setLocalPort(QGC_UDP_LOCAL_PORT);
udpConfig->setDynamic(true);
_linkConfigurations.append(udpConfig);
createConnectedLink(udpConfig);
emit linkConfigurationsChanged();
}
#ifndef __ios__
......@@ -517,9 +526,7 @@ void LinkManager::_updateAutoConnectLinks(void)
pSerialConfig->setBaud(boardType == QGCSerialPortInfo::BoardType3drRadio ? 57600 : 115200);
pSerialConfig->setDynamic(true);
pSerialConfig->setPortName(portInfo.systemLocation());
_autoconnectConfigurations.append(pSerialConfig);
createConnectedLink(pSerialConfig);
}
}
......@@ -530,7 +537,6 @@ void LinkManager::_updateAutoConnectLinks(void)
QList<LinkConfiguration*> _confToDelete;
for (int i=0; i<_autoconnectConfigurations.count(); i++) {
SerialConfiguration* linkConfig = _autoconnectConfigurations.value<SerialConfiguration*>(i);
if (linkConfig) {
if (!currentPorts.contains(linkConfig->portName())) {
// We don't remove links which are still connected even though at this point the cable may
......@@ -696,19 +702,36 @@ QStringList LinkManager::linkTypeStrings(void) const
return list;
}
QStringList LinkManager::serialPortStrings(void)
void LinkManager::_updateSerialPorts()
{
_commPortList.clear();
_commPortDisplayList.clear();
#ifndef __ios__
if(!_commPortList.size())
QList<QSerialPortInfo> portList = QSerialPortInfo::availablePorts();
foreach (const QSerialPortInfo &info, portList)
{
QList<QSerialPortInfo> portList = QSerialPortInfo::availablePorts();
foreach (const QSerialPortInfo &info, portList)
{
QString name = info.portName();
_commPortList += name;
}
QString port = info.systemLocation().trimmed();
_commPortList += port;
_commPortDisplayList += SerialConfiguration::cleanPortDisplayname(port);
}
#endif
}
QStringList LinkManager::serialPortStrings(void)
{
if(!_commPortDisplayList.size())
{
_updateSerialPorts();
}
return _commPortDisplayList;
}
QStringList LinkManager::serialPorts(void)
{
if(!_commPortList.size())
{
_updateSerialPorts();
}
return _commPortList;
}
......@@ -722,6 +745,110 @@ QStringList LinkManager::serialBaudRates(void)
#endif
}
bool LinkManager::endConfigurationEditing(LinkConfiguration* config, LinkConfiguration* editedConfig)
{
Q_ASSERT(config != NULL);
Q_ASSERT(editedConfig != NULL);
_fixUnnamed(editedConfig);
config->copyFrom(editedConfig);
saveLinkConfigurationList();
// Tell link about changes (if any)
config->updateSettings();
// Discard temporary duplicate
delete editedConfig;
return true;
}
bool LinkManager::endCreateConfiguration(LinkConfiguration* config)
{
Q_ASSERT(config != NULL);
_fixUnnamed(config);
_linkConfigurations.append(config);
saveLinkConfigurationList();
return true;
}
LinkConfiguration* LinkManager::createConfiguration(int type, const QString& name)
{
if((LinkConfiguration::LinkType)type == LinkConfiguration::TypeSerial)
_updateSerialPorts();
return LinkConfiguration::createSettings(type, name);
}
LinkConfiguration* LinkManager::startConfigurationEditing(LinkConfiguration* config)
{
Q_ASSERT(config != NULL);
if(config->type() == LinkConfiguration::TypeSerial)
_updateSerialPorts();
return LinkConfiguration::duplicateSettings(config);
}
void LinkManager::_fixUnnamed(LinkConfiguration* config)
{
Q_ASSERT(config != NULL);
//-- Check for "Unnamed"
if (config->name() == "Unnamed") {
switch(config->type()) {
#ifndef __ios__
case LinkConfiguration::TypeSerial: {
QString tname = dynamic_cast<SerialConfiguration*>(config)->portName();
#ifdef Q_OS_WIN32
tname.replace("\\\\.\\", "");
#else
tname.replace("/dev/cu.", "");
tname.replace("/dev/", "");
#endif
config->setName(QString("Serial Device on %1").arg(tname));
break;
}
#endif
case LinkConfiguration::TypeUdp:
config->setName(
QString("UDP Link on Port %1").arg(dynamic_cast<UDPConfiguration*>(config)->localPort()));
break;
case LinkConfiguration::TypeTcp: {
TCPConfiguration* tconfig = dynamic_cast<TCPConfiguration*>(config);
if(tconfig) {
config->setName(
QString("TCP Link %1:%2").arg(tconfig->address().toString()).arg((int)tconfig->port()));
}
}
break;
case LinkConfiguration::TypeLogReplay: {
LogReplayLinkConfiguration* tconfig = dynamic_cast<LogReplayLinkConfiguration*>(config);
if(tconfig) {
config->setName(QString("Log Replay %1").arg(tconfig->logFilenameShort()));
}
}
break;
#ifdef QT_DEBUG
case LinkConfiguration::TypeMock:
config->setName(
QString("Mock Link"));
break;
#endif
case LinkConfiguration::TypeLast:
default:
break;
}
}
}
void LinkManager::removeConfiguration(LinkConfiguration* config)
{
Q_ASSERT(config != NULL);
LinkInterface* iface = config->link();
if(iface) {
disconnectLink(iface);
}
// Remove configuration
_linkConfigurations.removeOne(config);
delete config;
// Save list
saveLinkConfigurationList();
}
bool LinkManager::isAutoconnectLink(LinkInterface* link)
{
return _autoconnectConfigurations.contains(link->getLinkConfiguration());
......
......@@ -80,15 +80,25 @@ public:
Q_PROPERTY(bool autoconnectPX4Flow READ autoconnectPX4Flow WRITE setAutoconnectPX4Flow NOTIFY autoconnectPX4FlowChanged)
/// LinkInterface Accessor
Q_PROPERTY(QmlObjectListModel* links READ links CONSTANT)
Q_PROPERTY(QmlObjectListModel* links READ links CONSTANT)
/// LinkConfiguration Accessor
Q_PROPERTY(QmlObjectListModel* linkConfigurations READ linkConfigurations CONSTANT)
Q_PROPERTY(QmlObjectListModel* linkConfigurations READ linkConfigurations NOTIFY linkConfigurationsChanged)
/// List of comm type strings
Q_PROPERTY(QStringList linkTypeStrings READ linkTypeStrings CONSTANT)
Q_PROPERTY(QStringList linkTypeStrings READ linkTypeStrings CONSTANT)
/// List of supported baud rates for serial links
Q_PROPERTY(QStringList serialBaudRates READ serialBaudRates CONSTANT)
Q_PROPERTY(QStringList serialBaudRates READ serialBaudRates CONSTANT)
/// List of comm ports display names
Q_PROPERTY(QStringList serialPortStrings READ serialPortStrings NOTIFY commPortStringsChanged)
/// List of comm ports
Q_PROPERTY(QStringList serialPortStrings READ serialPortStrings NOTIFY commPortStringsChanged)
Q_PROPERTY(QStringList serialPorts READ serialPorts NOTIFY commPortsChanged)
// Create/Edit Link Configuration
Q_INVOKABLE LinkConfiguration* createConfiguration (int type, const QString& name);
Q_INVOKABLE LinkConfiguration* startConfigurationEditing (LinkConfiguration* config);
Q_INVOKABLE void cancelConfigurationEditing (LinkConfiguration* config) { delete config; }
Q_INVOKABLE bool endConfigurationEditing (LinkConfiguration* config, LinkConfiguration* editedConfig);
Q_INVOKABLE bool endCreateConfiguration (LinkConfiguration* config);
Q_INVOKABLE void removeConfiguration (LinkConfiguration* config);
// Property accessors
......@@ -104,6 +114,7 @@ public:
QStringList linkTypeStrings (void) const;
QStringList serialBaudRates (void);
QStringList serialPortStrings (void);
QStringList serialPorts (void);
void setAutoconnectUDP (bool autoconnect);
void setAutoconnectPixhawk (bool autoconnect);
......@@ -189,8 +200,9 @@ signals:
// No longer hearing from any vehicles on this link.
void linkInactive(LinkInterface* link);
void linkConfigurationChanged();
void commPortStringsChanged();
void commPortsChanged();
void linkConfigurationsChanged();
private slots:
void _linkConnected(void);
......@@ -200,6 +212,8 @@ private slots:
private:
bool _connectionsSuspendedMsg(void);
void _updateAutoConnectLinks(void);
void _updateSerialPorts();
void _fixUnnamed(LinkConfiguration* config);
#ifndef __ios__
SerialConfiguration* _autoconnectConfigurationsContainsPort(const QString& portName);
......@@ -221,6 +235,7 @@ private:
QMap<QString, int> _autoconnectWaitList; ///< key: QGCSerialPortInfo.systemLocation, value: wait count
QStringList _commPortList;
QStringList _commPortDisplayList;
bool _autoconnectUDP;
bool _autoconnectPixhawk;
......
......@@ -400,12 +400,13 @@ SerialConfiguration::SerialConfiguration(const QString& name) : LinkConfiguratio
SerialConfiguration::SerialConfiguration(SerialConfiguration* copy) : LinkConfiguration(copy)
{
_baud = copy->baud();
_flowControl= copy->flowControl();
_parity = copy->parity();
_dataBits = copy->dataBits();
_stopBits = copy->stopBits();
_portName = copy->portName();
_baud = copy->baud();
_flowControl = copy->flowControl();
_parity = copy->parity();
_dataBits = copy->dataBits();
_stopBits = copy->stopBits();
_portName = copy->portName();
_portDisplayName = copy->portDisplayName();
}
void SerialConfiguration::copyFrom(LinkConfiguration *source)
......@@ -413,12 +414,13 @@ void SerialConfiguration::copyFrom(LinkConfiguration *source)
LinkConfiguration::copyFrom(source);
SerialConfiguration* ssource = dynamic_cast<SerialConfiguration*>(source);
Q_ASSERT(ssource != NULL);
_baud = ssource->baud();
_flowControl= ssource->flowControl();
_parity = ssource->parity();
_dataBits = ssource->dataBits();
_stopBits = ssource->stopBits();
_portName = ssource->portName();
_baud = ssource->baud();
_flowControl = ssource->flowControl();
_parity = ssource->parity();
_dataBits = ssource->dataBits();
_stopBits = ssource->stopBits();
_portName = ssource->portName();
_portDisplayName = ssource->portDisplayName();
}
void SerialConfiguration::updateSettings()
......@@ -462,30 +464,45 @@ void SerialConfiguration::setPortName(const QString& portName)
QString pname = portName.trimmed();
if (!pname.isEmpty() && pname != _portName) {
_portName = pname;
_portDisplayName = cleanPortDisplayname(pname);
}
}
QString SerialConfiguration::cleanPortDisplayname(const QString name)
{
QString pname = name.trimmed();
#ifdef Q_OS_WIN32
pname.replace("\\\\.\\", "");
#else
pname.replace("/dev/cu.", "");
pname.replace("/dev/", "");
#endif
return pname;
}
void SerialConfiguration::saveSettings(QSettings& settings, const QString& root)
{
settings.beginGroup(root);
settings.setValue("baud", _baud);
settings.setValue("dataBits", _dataBits);
settings.setValue("flowControl", _flowControl);
settings.setValue("stopBits", _stopBits);
settings.setValue("parity", _parity);
settings.setValue("portName", _portName);
settings.setValue("baud", _baud);
settings.setValue("dataBits", _dataBits);
settings.setValue("flowControl", _flowControl);
settings.setValue("stopBits", _stopBits);
settings.setValue("parity", _parity);
settings.setValue("portName", _portName);
settings.setValue("portDisplayName",_portDisplayName);
settings.endGroup();
}
void SerialConfiguration::loadSettings(QSettings& settings, const QString& root)
{
settings.beginGroup(root);
if(settings.contains("baud")) _baud = settings.value("baud").toInt();
if(settings.contains("dataBits")) _dataBits = settings.value("dataBits").toInt();
if(settings.contains("flowControl")) _flowControl = settings.value("flowControl").toInt();
if(settings.contains("stopBits")) _stopBits = settings.value("stopBits").toInt();
if(settings.contains("parity")) _parity = settings.value("parity").toInt();
if(settings.contains("portName")) _portName = settings.value("portName").toString();
if(settings.contains("baud")) _baud = settings.value("baud").toInt();
if(settings.contains("dataBits")) _dataBits = settings.value("dataBits").toInt();
if(settings.contains("flowControl")) _flowControl = settings.value("flowControl").toInt();
if(settings.contains("stopBits")) _stopBits = settings.value("stopBits").toInt();
if(settings.contains("parity")) _parity = settings.value("parity").toInt();
if(settings.contains("portName")) _portName = settings.value("portName").toString();
if(settings.contains("portDisplayName"))_portDisplayName= settings.value("portDisplayName").toString();
settings.endGroup();
}
......
......@@ -66,22 +66,32 @@ public:
SerialConfiguration(const QString& name);
SerialConfiguration(SerialConfiguration* copy);
Q_PROPERTY(int baud READ baud WRITE setBaud NOTIFY baudChanged)
Q_PROPERTY(int dataBits READ dataBits WRITE setDataBits NOTIFY dataBitsChanged)
Q_PROPERTY(int flowControl READ flowControl WRITE setFlowControl NOTIFY flowControlChanged)
Q_PROPERTY(int stopBits READ stopBits WRITE setStopBits NOTIFY stopBitsChanged)
Q_PROPERTY(int parity READ parity WRITE setParity NOTIFY parityChanged)
Q_PROPERTY(QString portName READ portName WRITE setPortName NOTIFY portNameChanged)
Q_PROPERTY(QString portDisplayName READ portDisplayName NOTIFY portDisplayNameChanged)
int baud() { return _baud; }
int dataBits() { return _dataBits; }
int flowControl() { return _flowControl; } ///< QSerialPort Enums
int stopBits() { return _stopBits; }
int parity() { return _parity; } ///< QSerialPort Enums
const QString portName() { return _portName; }
const QString portName () { return _portName; }
const QString portDisplayName () { return _portDisplayName; }
void setBaud (int baud);
void setDataBits (int databits);
void setFlowControl (int flowControl); ///< QSerialPort Enums
void setStopBits (int stopBits);
void setParity (int parity); ///< QSerialPort Enums
void setPortName (const QString& portName);
void setBaud (int baud);
void setDataBits (int databits);
void setFlowControl (int flowControl); ///< QSerialPort Enums
void setStopBits (int stopBits);
void setParity (int parity); ///< QSerialPort Enums
void setPortName (const QString& portName);
static QStringList supportedBaudRates();
static QString cleanPortDisplayname(const QString name);
/// From LinkConfiguration
LinkType type() { return LinkConfiguration::TypeSerial; }
......@@ -90,6 +100,15 @@ public:
void saveSettings(QSettings& settings, const QString& root);
void updateSettings();
signals:
void baudChanged ();
void dataBitsChanged ();
void flowControlChanged ();
void stopBitsChanged ();
void parityChanged ();
void portNameChanged ();
void portDisplayNameChanged ();
private:
static void _initBaudRates();
......@@ -100,9 +119,9 @@ private:
int _stopBits;
int _parity;
QString _portName;
QString _portDisplayName;
};
/**
* @brief The SerialLink class provides cross-platform access to serial links.
* It takes care of the link management and provides a common API to higher
......
......@@ -23,6 +23,7 @@
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.1
import QGroundControl 1.0
import QGroundControl.Controls 1.0
......@@ -92,7 +93,7 @@ Rectangle {
text: object.name
width: _linkRoot.width * 0.5
exclusiveGroup: linkGroup
anchors.horizontalCenter: parent.horizontalCenter
anchors.horizontalCenter: settingsColumn.horizontalCenter
onClicked: {
checked = true
_currentSelection = object
......@@ -111,8 +112,26 @@ Rectangle {
QGCButton {
width: ScreenTools.defaultFontPixelWidth * 10
text: "Delete"
enabled: _currentSelection && !_currentSelection.link
enabled: _currentSelection && !_currentSelection.dynamic
onClicked: {
if(_currentSelection)
deleteDialog.visible = true
}
MessageDialog {
id: deleteDialog
visible: false
icon: StandardIcon.Warning
standardButtons: StandardButton.Yes | StandardButton.No
title: "Remove Link Configuration"
text: _currentSelection ? "Remove " + _currentSelection.name + ". Is this really what you want?" : ""
onYes: {
if(_currentSelection)
QGroundControl.linkManager.removeConfiguration(_currentSelection)
deleteDialog.visible = false
}
onNo: {
deleteDialog.visible = false
}
}
}
QGCButton {
......@@ -154,6 +173,7 @@ Rectangle {
anchors.fill: parent
visible: false
property var linkConfig: null
property var editConfig: null
}
//---------------------------------------------
......@@ -163,6 +183,24 @@ Rectangle {
Rectangle {
color: __qgcPal.window
anchors.fill: parent
Component.onCompleted: {
// If editing, create copy for editing
if(linkConfig) {
editConfig = QGroundControl.linkManager.startConfigurationEditing(linkConfig)
} else {
// Create new link configuration
if(ScreenTools.isiOS)
editConfig = QGroundControl.linkManager.createConfiguration(LinkConfiguration.TypeUdp, "Unnamed")
else
editConfig = QGroundControl.linkManager.createConfiguration(LinkConfiguration.TypeSerial, "Unnamed")
}
}
Component.onDestruction: {
if(editConfig) {
QGroundControl.linkManager.cancelConfigurationEditing(editConfig)
editConfig = null
}
}
Flickable {
clip: true
anchors.top: parent.top
......@@ -199,7 +237,8 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter
}
QGCTextField {
text: linkConfig ? linkConfig.name : "Untitled"
id: nameField
text: editConfig ? editConfig.name : ""
width: _secondColumn
anchors.verticalCenter: parent.verticalCenter
}
......@@ -220,8 +259,17 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter
Component.onCompleted: {
if(linkConfig != null) {
if(linkConfig.linkType === LinkConfiguration.TypeSerial)
var index = linkConfig.linkType
if(index === LinkConfiguration.TypeSerial)
linkSettingLoader.sourceComponent = serialLinkSettings
if(index === LinkConfiguration.TypeUdp)
linkSettingLoader.sourceComponent = udpLinkSettings
if(index === LinkConfiguration.TypeTcp)
linkSettingLoader.sourceComponent = tcpLinkSettings
if(index === LinkConfiguration.TypeMock)
linkSettingLoader.sourceComponent = mockLinkSettings
if(index === LinkConfiguration.TypeLogReplay)
linkSettingLoader.sourceComponent = logLinkSettings
linkSettingLoader.visible = true
}
}
......@@ -235,7 +283,14 @@ Rectangle {
model: QGroundControl.linkManager.linkTypeStrings
anchors.verticalCenter: parent.verticalCenter
onActivated: {
if (index != -1) {
if (index != -1 && index !== editConfig.linkType) {
// Save current name
var name = editConfig.name
// Discard link configuration (old type)
QGroundControl.linkManager.cancelConfigurationEditing(editConfig)
// Create new link configuration
editConfig = QGroundControl.linkManager.createConfiguration(index, name)
// Load appropriate configuration panel
linkSettingLoader.sourceComponent = null
if(index === LinkConfiguration.TypeSerial)
linkSettingLoader.sourceComponent = serialLinkSettings
......@@ -252,12 +307,40 @@ Rectangle {
Component.onCompleted: {
if(linkConfig == null) {
linkTypeCombo.currentIndex = 0
linkSettingLoader.sourceComponent = serialLinkSettings
var index = editConfig.linkType
if(index === LinkConfiguration.TypeSerial)
linkSettingLoader.sourceComponent = serialLinkSettings
if(index === LinkConfiguration.TypeUdp)
linkSettingLoader.sourceComponent = udpLinkSettings
if(index === LinkConfiguration.TypeTcp)
linkSettingLoader.sourceComponent = tcpLinkSettings
if(index === LinkConfiguration.TypeMock)
linkSettingLoader.sourceComponent = mockLinkSettings
if(index === LinkConfiguration.TypeLogReplay)
linkSettingLoader.sourceComponent = logLinkSettings
linkSettingLoader.visible = true
}
}
}
}
Item {
height: ScreenTools.defaultFontPixelHeight * 0.5
width: parent.width
}
//-- Auto Connect
QGCCheckBox {
text: "Automatically Connect on Start"
checked: false
onCheckedChanged: {
if(editConfig) {
editConfig.autoConnect = checked
}
}
Component.onCompleted: {
if(editConfig)
checked = editConfig.autoConnect
}
}
Item {
height: ScreenTools.defaultFontPixelHeight
width: parent.width
......@@ -266,7 +349,7 @@ Rectangle {
id: linkSettingLoader
width: parent.width
visible: false
property var config: linkConfig
property var subEditConfig: editConfig
}
}
}
......@@ -279,7 +362,19 @@ Rectangle {
QGCButton {
width: ScreenTools.defaultFontPixelWidth * 10
text: "OK"
//-- TODO: For now, only allow Serial (the only one completed)
enabled: editConfig && editConfig.linkType === LinkConfiguration.TypeSerial
onClicked: {
// Save editting
editConfig.name = nameField.text
if(linkConfig) {
QGroundControl.linkManager.endConfigurationEditing(linkConfig, editConfig)
} else {
// If it was edited, it's no longer "dynamic"
editConfig.dynamic = false
QGroundControl.linkManager.endCreateConfiguration(editConfig)
}
editConfig = null
_linkRoot.closeCommSettings()
}
}
......@@ -287,6 +382,8 @@ Rectangle {
width: ScreenTools.defaultFontPixelWidth * 10
text: "Cancel"
onClicked: {
QGroundControl.linkManager.cancelConfigurationEditing(editConfig)
editConfig = null
_linkRoot.closeCommSettings()
}
}
......@@ -298,7 +395,7 @@ Rectangle {
Component {
id: serialLinkSettings
Column {
width: parent.width
width: serialLinkSettings.width
spacing: ScreenTools.defaultFontPixelHeight / 2
QGCLabel {
id: serialLabel
......@@ -327,10 +424,21 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter
onActivated: {
if (index != -1) {
subEditConfig.portName = QGroundControl.linkManager.serialPorts[index]
}
}
Component.onCompleted: {
if(config != null) {
if(subEditConfig != null) {
if(subEditConfig.portDisplayName === "")
subEditConfig.portName = QGroundControl.linkManager.serialPorts[0]
var index = commPortCombo.find(subEditConfig.portDisplayName)
if (index === -1) {
console.warn("Serial Port not present", subEditConfig.portName)
} else {
commPortCombo.currentIndex = index
}
} else {
commPortCombo.currentIndex = 0
}
}
}
......@@ -349,15 +457,16 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter
onActivated: {
if (index != -1) {
subEditConfig.baud = parseInt(QGroundControl.linkManager.serialBaudRates[index])
}
}
Component.onCompleted: {
var baud = "57600"
if(config != null) {
// Get baud from config
if(subEditConfig != null) {
baud = subEditConfig.baud.toString()
}
var index = baudCombo.find(baud)
if (index == -1) {
if (index === -1) {
console.warn("Baud rate name not in combo box", baud)
} else {
baudCombo.currentIndex = index
......@@ -365,6 +474,128 @@ Rectangle {
}
}
}
Item {
height: ScreenTools.defaultFontPixelHeight / 2
width: parent.width
}
//-----------------------------------------------------------------
//-- Advanced Serial Settings
QGCCheckBox {
id: showAdvanced
text: "Show Advanced Serial Settings"
}
Item {
height: ScreenTools.defaultFontPixelHeight / 2
width: parent.width
}
//-- Flow Control
QGCCheckBox {
text: "Enable Flow Control"
checked: subEditConfig ? subEditConfig.flowControl !== 0 : false
visible: showAdvanced.checked
onCheckedChanged: {
if(subEditConfig) {
subEditConfig.flowControl = checked ? 1 : 0
}
}
}
//-- Parity
Row {
spacing: ScreenTools.defaultFontPixelWidth
visible: showAdvanced.checked
QGCLabel {
text: "Parity:"
width: _firstColumn
anchors.verticalCenter: parent.verticalCenter
}
QGCComboBox {
id: parityCombo
width: _firstColumn
model: ["None", "Even", "Odd"]
anchors.verticalCenter: parent.verticalCenter
onActivated: {
if (index != -1) {
// Hard coded values from qserialport.h
if(index == 0)
subEditConfig.parity = 0
else if(index == 1)
subEditConfig.parity = 2
else
subEditConfig.parity = 3
}
}
Component.onCompleted: {
var index = 0
if(subEditConfig != null) {
index = subEditConfig.parity
}
if(index > 1) {
index = index - 2
}
parityCombo.currentIndex = index
}
}
}
//-- Data Bits
Row {
spacing: ScreenTools.defaultFontPixelWidth
visible: showAdvanced.checked
QGCLabel {
text: "Data Bits:"
width: _firstColumn
anchors.verticalCenter: parent.verticalCenter
}
QGCComboBox {
id: dataCombo
width: _firstColumn
model: ["5", "6", "7", "8"]
anchors.verticalCenter: parent.verticalCenter
onActivated: {
if (index != -1) {
subEditConfig.dataBits = index + 5
}
}
Component.onCompleted: {
var index = 3
if(subEditConfig != null) {
index = subEditConfig.parity - 5
if(index < 0)
index = 3
}
dataCombo.currentIndex = index
}
}
}
//-- Stop Bits
Row {
spacing: ScreenTools.defaultFontPixelWidth
visible: showAdvanced.checked
QGCLabel {
text: "Stop Bits:"
width: _firstColumn
anchors.verticalCenter: parent.verticalCenter
}
QGCComboBox {
id: stopCombo
width: _firstColumn
model: ["1", "2"]
anchors.verticalCenter: parent.verticalCenter
onActivated: {
if (index != -1) {
subEditConfig.stopBits = index + 1
}
}
Component.onCompleted: {
var index = 0
if(subEditConfig != null) {
index = subEditConfig.stopBits - 1
if(index < 0)
index = 0
}
stopCombo.currentIndex = index
}
}
}
}
}
//---------------------------------------------
......@@ -372,7 +603,7 @@ Rectangle {
Component {
id: udpLinkSettings
Column {
width: parent.width
width: udpLinkSettings.width
spacing: ScreenTools.defaultFontPixelHeight / 2
QGCLabel {
id: udpLabel
......@@ -408,7 +639,7 @@ Rectangle {
Component {
id: tcpLinkSettings
Column {
width: parent.width
width: tcpLinkSettings.width
spacing: ScreenTools.defaultFontPixelHeight / 2
QGCLabel {
id: tcpLabel
......@@ -452,7 +683,7 @@ Rectangle {
Component {
id: logLinkSettings
Column {
width: parent.width
width: logLinkSettings.width
spacing: ScreenTools.defaultFontPixelHeight / 2
QGCLabel {
text: "Log Replay Link Settings"
......@@ -471,7 +702,7 @@ Rectangle {
Component {
id: mockLinkSettings
Column {
width: parent.width
width: mockLinkSettings.width
spacing: ScreenTools.defaultFontPixelHeight / 2
QGCLabel {
text: "Mock Link Settings"
......
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