Commit c2082c81 authored by Don Gagne's avatar Don Gagne

Merge pull request #1466 from dogmaphobic/connectionWork

Link Management Work
parents 36b702a8 5feeb517
......@@ -12,7 +12,7 @@
// If you need to make an incompatible changes to stored settings, bump this version number
// up by 1. This will caused store settings to be cleared on next boot.
#define QGC_SETTINGS_VERSION 5
#define QGC_SETTINGS_VERSION 6
#define QGC_APPLICATION_NAME "QGroundControl"
#define QGC_ORG_NAME "QGroundControl.org"
......
......@@ -40,6 +40,7 @@ This file is part of the QGROUNDCONTROL project
LinkConfiguration::LinkConfiguration(const QString& name)
: _preferred(false)
, _dynamic(false)
{
_link = NULL;
_name = name;
......@@ -48,18 +49,20 @@ LinkConfiguration::LinkConfiguration(const QString& name)
LinkConfiguration::LinkConfiguration(LinkConfiguration* copy)
{
_link = copy->getLink();
_name = copy->name();
_preferred = copy->isPreferred();
_link = copy->getLink();
_name = copy->name();
_preferred = copy->isPreferred();
_dynamic = copy->isDynamic();
Q_ASSERT(!_name.isEmpty());
}
void LinkConfiguration::copyFrom(LinkConfiguration* source)
{
Q_ASSERT(source != NULL);
_link = source->getLink();
_name = source->name();
_preferred = source->isPreferred();
_link = source->getLink();
_name = source->name();
_preferred = source->isPreferred();
_dynamic = source->isDynamic();
}
/*!
......
......@@ -97,6 +97,18 @@ public:
*/
void setPreferred(bool preferred = true) { _preferred = preferred; }
/*!
*
* Is this a dynamic configuration? (non persistent)
* @return True if this is an automatically added configuration.
*/
bool isDynamic() { return _dynamic; }
/*!
* Set if this is this a dynamic configuration. (decided at runtime)
*/
void setDynamic(bool dynamic = true) { _dynamic = dynamic; }
/// Virtual Methods
/*!
......@@ -171,6 +183,7 @@ protected:
private:
QString _name;
bool _preferred; ///< Determined internally if this is a preferred connection. It comes up first in the drop down box.
bool _dynamic; ///< A connection added automatically and not persistent (unless it's edited).
};
#endif // LINKCONFIGURATION_H
......@@ -325,19 +325,22 @@ void LinkManager::saveLinkConfigurationList()
{
QSettings settings;
settings.remove(LinkConfiguration::settingsRoot());
QString root(LinkConfiguration::settingsRoot());
settings.setValue(root + "/count", _linkConfigurations.count());
int index = 0;
foreach (LinkConfiguration* pLink, _linkConfigurations) {
Q_ASSERT(pLink != NULL);
root = LinkConfiguration::settingsRoot();
root += QString("/Link%1").arg(index++);
settings.setValue(root + "/name", pLink->name());
settings.setValue(root + "/type", pLink->type());
settings.setValue(root + "/preferred", pLink->isPreferred());
// Have the instance save its own values
pLink->saveSettings(settings, root);
if(!pLink->isDynamic())
{
QString root = LinkConfiguration::settingsRoot();
root += QString("/Link%1").arg(index++);
settings.setValue(root + "/name", pLink->name());
settings.setValue(root + "/type", pLink->type());
settings.setValue(root + "/preferred", pLink->isPreferred());
// Have the instance save its own values
pLink->saveSettings(settings, root);
}
}
QString root(LinkConfiguration::settingsRoot());
settings.setValue(root + "/count", index);
emit linkConfigurationChanged();
}
......@@ -427,6 +430,7 @@ void LinkManager::_updateConfigurationList(void)
return;
}
bool saveList = false;
QStringList currentPorts;
QList<QSerialPortInfo> portList = QSerialPortInfo::availablePorts();
// Iterate Comm Ports
foreach (QSerialPortInfo portInfo, portList) {
......@@ -439,6 +443,8 @@ void LinkManager::_updateConfigurationList(void)
qDebug() << "serialNumber: " << portInfo.serialNumber();
qDebug() << "vendorIdentifier: " << portInfo.vendorIdentifier();
#endif
// Save port name
currentPorts << portInfo.systemLocation();
// Is this a PX4?
if (portInfo.vendorIdentifier() == 9900) {
SerialConfiguration* pSerial = _findSerialConfiguration(portInfo.systemLocation());
......@@ -451,6 +457,7 @@ void LinkManager::_updateConfigurationList(void)
} else {
// Lets create a new Serial configuration automatically
pSerial = new SerialConfiguration(QString("Pixhawk on %1").arg(portInfo.portName().trimmed()));
pSerial->setDynamic(true);
pSerial->setPreferred(true);
pSerial->setBaud(115200);
pSerial->setPortName(portInfo.systemLocation());
......@@ -458,6 +465,45 @@ void LinkManager::_updateConfigurationList(void)
saveList = true;
}
}
// Is this an FTDI Chip? It could be a 3DR Modem
if (portInfo.vendorIdentifier() == 1027) {
SerialConfiguration* pSerial = _findSerialConfiguration(portInfo.systemLocation());
if (pSerial) {
//-- If this port is configured make sure it has the preferred flag set, unless someone else already has it set.
if(!pSerial->isPreferred() && !saveList) {
pSerial->setPreferred(true);
saveList = true;
}
} else {
// Lets create a new Serial configuration automatically (an assumption at best)
pSerial = new SerialConfiguration(QString("3DR Radio on %1").arg(portInfo.portName().trimmed()));
pSerial->setDynamic(true);
pSerial->setPreferred(true);
pSerial->setBaud(57600);
pSerial->setPortName(portInfo.systemLocation());
addLinkConfiguration(pSerial);
saveList = true;
}
}
}
// Now we go through the current configuration list and make sure any dynamic config has gone away
QList<LinkConfiguration*> _confToDelete;
foreach (LinkConfiguration* pLink, _linkConfigurations) {
Q_ASSERT(pLink != NULL);
// We only care about dynamic links
if(pLink->isDynamic()) {
if(pLink->type() == LinkConfiguration::TypeSerial) {
SerialConfiguration* pSerial = dynamic_cast<SerialConfiguration*>(pLink);
if(!currentPorts.contains(pSerial->portName())) {
_confToDelete.append(pSerial);
}
}
}
}
// Now remove all links that are gone
foreach (LinkConfiguration* pDelete, _confToDelete) {
removeLinkConfiguration(pDelete);
saveList = true;
}
// Save configuration list, which will also trigger a signal for the UI
if(saveList) {
......@@ -468,28 +514,24 @@ void LinkManager::_updateConfigurationList(void)
bool LinkManager::containsLink(LinkInterface* link)
{
bool found = false;
foreach (SharedLinkInterface sharedLink, _links) {
if (sharedLink.data() == link) {
found = true;
break;
}
}
return found;
}
bool LinkManager::anyConnectedLinks(void)
{
bool found = false;
foreach (SharedLinkInterface sharedLink, _links) {
if (sharedLink.data()->isConnected()) {
found = true;
break;
}
}
return found;
}
......@@ -500,7 +542,6 @@ SharedLinkInterface& LinkManager::sharedPointerForLink(LinkInterface* link)
return _links[i];
}
}
// This should never happen
Q_ASSERT(false);
return _nullSharedLink;
......
......@@ -215,21 +215,35 @@ bool SerialConfigurationWindow::setupPortList()
void SerialConfigurationWindow::enableFlowControl(bool flow)
{
_config->setFlowControl(flow ? QSerialPort::HardwareControl : QSerialPort::NoFlowControl);
//-- If this was dynamic, it's now edited and persistent
_config->setDynamic(false);
}
void SerialConfigurationWindow::setParityNone(bool accept)
{
if (accept) _config->setParity(QSerialPort::NoParity);
if (accept) {
_config->setParity(QSerialPort::NoParity);
//-- If this was dynamic, it's now edited and persistent
_config->setDynamic(false);
}
}
void SerialConfigurationWindow::setParityOdd(bool accept)
{
if (accept) _config->setParity(QSerialPort::OddParity);
if (accept) {
_config->setParity(QSerialPort::OddParity);
//-- If this was dynamic, it's now edited and persistent
_config->setDynamic(false);
}
}
void SerialConfigurationWindow::setParityEven(bool accept)
{
if (accept) _config->setParity(QSerialPort::EvenParity);
if (accept) {
_config->setParity(QSerialPort::EvenParity);
//-- If this was dynamic, it's now edited and persistent
_config->setDynamic(false);
}
}
void SerialConfigurationWindow::setPortName(int index)
......@@ -238,6 +252,8 @@ void SerialConfigurationWindow::setPortName(int index)
QString pname = _ui.portName->itemData(index).toString();
if (_config->portName() != pname) {
_config->setPortName(pname);
//-- If this was dynamic, it's now edited and persistent
_config->setDynamic(false);
}
}
......@@ -245,14 +261,20 @@ void SerialConfigurationWindow::setBaudRate(int index)
{
int baud = _ui.baudRate->itemData(index).toInt();
_config->setBaud(baud);
//-- If this was dynamic, it's now edited and persistent
_config->setDynamic(false);
}
void SerialConfigurationWindow::setDataBits(int bits)
{
_config->setDataBits(bits);
//-- If this was dynamic, it's now edited and persistent
_config->setDynamic(false);
}
void SerialConfigurationWindow::setStopBits(int bits)
{
_config->setStopBits(bits);
//-- If this was dynamic, it's now edited and persistent
_config->setDynamic(false);
}
......@@ -42,7 +42,6 @@ MainToolBar::MainToolBar(QWidget* parent)
, _currentView(ViewNone)
, _batteryVoltage(0.0)
, _batteryPercent(0.0)
, _linkSelected(false)
, _connectionCount(0)
, _systemArmed(false)
, _currentHeartbeatTimeout(0)
......@@ -152,60 +151,51 @@ void MainToolBar::onAnalyzeView()
MainWindow::instance()->loadAnalyzeView();
}
void MainToolBar::onConnect(QString conf)
void MainToolBar::onDisconnect(QString conf)
{
// If no connection, the role is "Connect"
if(_connectionCount == 0) {
// Connect Link
if(_currentConfig.isEmpty()) {
MainWindow::instance()->manageLinks();
} else {
// We don't want the combo box updating under our feet
LinkManager::instance()->suspendConfigurationUpdates(true);
// Create a link
LinkInterface* link = LinkManager::instance()->createConnectedLink(_currentConfig);
if(link) {
// Save last used connection
MainWindow::instance()->saveLastUsedConnection(_currentConfig);
if(conf.isEmpty()) {
// Disconnect Only Connected Link
int connectedCount = 0;
LinkInterface* connectedLink = NULL;
QList<LinkInterface*> links = LinkManager::instance()->getLinks();
foreach(LinkInterface* link, links) {
if (link->isConnected()) {
connectedCount++;
connectedLink = link;
}
LinkManager::instance()->suspendConfigurationUpdates(false);
}
Q_ASSERT(connectedCount == 1);
Q_ASSERT(_connectionCount == 1);
Q_ASSERT(connectedLink);
LinkManager::instance()->disconnectLink(connectedLink);
} else {
if(conf.isEmpty()) {
// Disconnect Only Connected Link
int connectedCount = 0;
LinkInterface* connectedLink = NULL;
QList<LinkInterface*> links = LinkManager::instance()->getLinks();
foreach(LinkInterface* link, links) {
if (link->isConnected()) {
connectedCount++;
connectedLink = link;
}
}
Q_ASSERT(connectedCount == 1);
Q_ASSERT(_connectionCount == 1);
Q_ASSERT(connectedLink);
LinkManager::instance()->disconnectLink(connectedLink);
} else {
// Disconnect Named Connected Link
QList<LinkInterface*> links = LinkManager::instance()->getLinks();
foreach(LinkInterface* link, links) {
if (link->isConnected()) {
if(link->getLinkConfiguration() && link->getLinkConfiguration()->name() == conf) {
LinkManager::instance()->disconnectLink(link);
}
// Disconnect Named Connected Link
QList<LinkInterface*> links = LinkManager::instance()->getLinks();
foreach(LinkInterface* link, links) {
if (link->isConnected()) {
if(link->getLinkConfiguration() && link->getLinkConfiguration()->name() == conf) {
LinkManager::instance()->disconnectLink(link);
}
}
}
}
}
void MainToolBar::onLinkConfigurationChanged(const QString& config)
void MainToolBar::onConnect(QString conf)
{
// User selected a link configuration from the combobox
if(_currentConfig != config) {
_currentConfig = config;
_linkSelected = true;
// Connect Link
if(conf.isEmpty()) {
MainWindow::instance()->manageLinks();
} else {
// We don't want the list updating under our feet
LinkManager::instance()->suspendConfigurationUpdates(true);
// Create a link
LinkInterface* link = LinkManager::instance()->createConnectedLink(conf);
if(link) {
// Save last used connection
MainWindow::instance()->saveLastUsedConnection(conf);
}
LinkManager::instance()->suspendConfigurationUpdates(false);
}
}
......@@ -378,16 +368,14 @@ void MainToolBar::_updateBatteryRemaining(UASInterface*, double voltage, double,
void MainToolBar::_updateConfigurations()
{
bool resetSelected = false;
QString selected = _currentConfig;
QStringList tmpList;
QList<LinkConfiguration*> configs = LinkManager::instance()->getLinkConfigurationList();
foreach(LinkConfiguration* conf, configs) {
if(conf) {
tmpList << conf->name();
if((!_linkSelected && conf->isPreferred()) || selected.isEmpty()) {
selected = conf->name();
resetSelected = true;
if(conf->isPreferred()) {
tmpList.insert(0,conf->name());
} else {
tmpList << conf->name();
}
}
}
......@@ -396,15 +384,6 @@ void MainToolBar::_updateConfigurations()
_linkConfigurations = tmpList;
emit configListChanged();
}
// Selection change?
if((selected != _currentConfig && _linkConfigurations.contains(selected)) ||
(selected.isEmpty())) {
_currentConfig = selected;
emit currentConfigChanged(_currentConfig);
}
if(resetSelected) {
_linkSelected = false;
}
}
void MainToolBar::_linkConnected(LinkInterface*)
......
......@@ -71,7 +71,7 @@ public:
Q_INVOKABLE void onFlyView();
Q_INVOKABLE void onAnalyzeView();
Q_INVOKABLE void onConnect(QString conf);
Q_INVOKABLE void onLinkConfigurationChanged(const QString& config);
Q_INVOKABLE void onDisconnect(QString conf);
Q_INVOKABLE void onEnterMessageArea(int x, int y);
Q_INVOKABLE QString getMavIconColor();
......@@ -86,7 +86,6 @@ public:
Q_PROPERTY(MessageType_t messageType MEMBER _currentMessageType NOTIFY messageTypeChanged)
Q_PROPERTY(int newMessageCount MEMBER _currentMessageCount NOTIFY newMessageCountChanged)
Q_PROPERTY(int messageCount MEMBER _messageCount NOTIFY messageCountChanged)
Q_PROPERTY(QString currentConfig MEMBER _currentConfig NOTIFY currentConfigChanged)
Q_PROPERTY(QString systemPixmap MEMBER _systemPixmap NOTIFY systemPixmapChanged)
Q_PROPERTY(int satelliteCount MEMBER _satelliteCount NOTIFY satelliteCountChanged)
Q_PROPERTY(QStringList connectedList MEMBER _connectedList NOTIFY connectedListChanged)
......@@ -160,8 +159,6 @@ private:
double _batteryVoltage;
double _batteryPercent;
QStringList _linkConfigurations;
QString _currentConfig;
bool _linkSelected;
int _connectionCount;
bool _systemArmed;
QString _currentState;
......
......@@ -472,32 +472,50 @@ Rectangle {
anchors.leftMargin: 10
anchors.rightMargin: 10
QGCComboBox {
id: configList
width: 200
visible: (mainToolBar.connectionCount === 0 && mainToolBar.configList.length > 0)
anchors.verticalCenter: parent.verticalCenter
model: mainToolBar.configList
onCurrentIndexChanged: {
mainToolBar.onLinkConfigurationChanged(mainToolBar.configList[currentIndex]);
}
Menu {
id: connectMenu
Component.onCompleted: {
mainToolBar.currentConfigChanged.connect(configList.onCurrentConfigChanged)
mainToolBar.configListChanged.connect(connectMenu.updateConnectionList);
connectMenu.updateConnectionList();
}
function onCurrentConfigChanged(config) {
var index = configList.find(config);
configList.currentIndex = index;
function addMenuEntry(name) {
var label = "Add Connection"
if(name !== "")
label = name;
var mItem = connectMenu.addItem(label);
var menuSlot = function() {mainToolBar.onConnect(name)};
mItem.triggered.connect(menuSlot);
}
function updateConnectionList() {
connectMenu.clear();
for(var i = 0; i < mainToolBar.configList.length; i++) {
connectMenu.addMenuEntry(mainToolBar.configList[i]);
}
if(mainToolBar.configList.length > 0) {
connectMenu.addSeparator();
}
// Add "Add Connection" to the list
connectMenu.addMenuEntry("");
}
}
QGCButton {
id: connectButton
width: 100
visible: (mainToolBar.connectionCount === 0 || mainToolBar.connectionCount === 1)
text: (mainToolBar.configList.length > 0) ? (mainToolBar.connectionCount === 0) ? qsTr("Connect") : qsTr("Disconnect") : qsTr("Add Link")
id: connectButton
width: 100
visible: mainToolBar.connectionCount === 0
text: qsTr("Connect")
menu: connectMenu
anchors.verticalCenter: parent.verticalCenter
}
QGCButton {
id: disconnectButton
width: 100
visible: mainToolBar.connectionCount === 1
text: qsTr("Disconnect")
anchors.verticalCenter: parent.verticalCenter
onClicked: {
mainToolBar.onConnect("");
mainToolBar.onDisconnect("");
}
}
......@@ -506,23 +524,26 @@ Rectangle {
Component.onCompleted: {
mainToolBar.connectedListChanged.connect(disconnectMenu.onConnectedListChanged)
}
function addMenuEntry(name) {
var mItem = disconnectMenu.addItem(name);
var menuSlot = function() {mainToolBar.onDisconnect(name)};
mItem.triggered.connect(menuSlot);
}
function onConnectedListChanged(conList) {
disconnectMenu.clear();
for(var i = 0; i < conList.length; i++) {
var mItem = disconnectMenu.addItem(conList[i]);
var menuSlot = function() {mainToolBar.onConnect(mItem.text)};
mItem.triggered.connect(menuSlot);
disconnectMenu.addMenuEntry(conList[i]);
}
}
}
QGCButton {
id: multidisconnectButton
width: 100
text: qsTr("Disconnect")
visible: (mainToolBar.connectionCount > 1)
id: multidisconnectButton
width: 100
text: "Disconnect"
visible: mainToolBar.connectionCount > 1
menu: disconnectMenu
anchors.verticalCenter: parent.verticalCenter
menu: disconnectMenu
}
}
......
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