/*
Copyright © 2015 Hasan Yavuz Özderya
This file is part of serialplot.
serialplot 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.
serialplot 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 serialplot. If not, see .
*/
#include "portcontrol.h"
#include "ui_portcontrol.h"
#include
#include
#include "utils.h"
PortControl::PortControl(QSerialPort* port, QWidget* parent) :
QWidget(parent),
ui(new Ui::PortControl)
{
ui->setupUi(this);
serialPort = port;
QObject::connect(ui->pbReloadPorts, &QPushButton::clicked,
this, &PortControl::loadPortList);
QObject::connect(ui->pbOpenPort, &QPushButton::clicked,
this, &PortControl::togglePort);
// TODO: port name coming from combobox is dirty, create a separate layer of signals
// that will sanitize this information
QObject::connect(ui->cbPortList,
SELECT::OVERLOAD_OF(&QComboBox::activated),
this, &PortControl::selectPort);
QObject::connect(ui->cbPortList,
SELECT::OVERLOAD_OF(&QComboBox::activated),
this, &PortControl::onPortNameChanged);
QObject::connect(ui->cbBaudRate,
SELECT::OVERLOAD_OF(&QComboBox::activated),
this, &PortControl::selectBaudRate);
// setup parity selection buttons
parityButtons.addButton(ui->rbNoParity, (int) QSerialPort::NoParity);
parityButtons.addButton(ui->rbEvenParity, (int) QSerialPort::EvenParity);
parityButtons.addButton(ui->rbOddParity, (int) QSerialPort::OddParity);
QObject::connect(&parityButtons,
SELECT::OVERLOAD_OF(&QButtonGroup::buttonClicked),
this, &PortControl::selectParity);
// setup data bits selection buttons
dataBitsButtons.addButton(ui->rb8Bits, (int) QSerialPort::Data8);
dataBitsButtons.addButton(ui->rb7Bits, (int) QSerialPort::Data7);
dataBitsButtons.addButton(ui->rb6Bits, (int) QSerialPort::Data6);
dataBitsButtons.addButton(ui->rb5Bits, (int) QSerialPort::Data5);
QObject::connect(&dataBitsButtons,
SELECT::OVERLOAD_OF(&QButtonGroup::buttonClicked),
this, &PortControl::selectDataBits);
// setup stop bits selection buttons
stopBitsButtons.addButton(ui->rb1StopBit, (int) QSerialPort::OneStop);
stopBitsButtons.addButton(ui->rb2StopBit, (int) QSerialPort::TwoStop);
QObject::connect(&stopBitsButtons,
SELECT::OVERLOAD_OF(&QButtonGroup::buttonClicked),
this, &PortControl::selectStopBits);
// setup flow control selection buttons
flowControlButtons.addButton(ui->rbNoFlowControl,
(int) QSerialPort::NoFlowControl);
flowControlButtons.addButton(ui->rbHardwareControl,
(int) QSerialPort::HardwareControl);
flowControlButtons.addButton(ui->rbSoftwareControl,
(int) QSerialPort::SoftwareControl);
QObject::connect(&flowControlButtons,
SELECT::OVERLOAD_OF(&QButtonGroup::buttonClicked),
this, &PortControl::selectFlowControl);
// init skip byte button
QObject::connect(ui->pbSkipByte, &QPushButton::clicked,
[this](){emit skipByteRequested();});
loadPortList();
loadBaudRateList();
ui->cbBaudRate->setCurrentIndex(ui->cbBaudRate->findText("9600"));
}
PortControl::~PortControl()
{
delete ui;
}
void PortControl::loadPortList()
{
QString currentSelection = ui->cbPortList->currentText();
ui->cbPortList->clear();
discoveredPorts.clear();
for (auto port : QSerialPortInfo::availablePorts())
{
QString pName = port.portName();
if (!port.description().isEmpty()) pName += QString(" ") + port.description();
if (port.hasProductIdentifier())
{
QString vID = QString("%1").arg(port.vendorIdentifier(), 4, 16, QChar('0'));
QString pID = QString("%1").arg(port.productIdentifier(), 4, 16, QChar('0'));
pName = pName + " [" + vID + ":" + pID + "]";
}
ui->cbPortList->addItem(pName);
discoveredPorts << port.portName();
}
ui->cbPortList->addItems(userEnteredPorts);
// find current selection in the new list, maybe it doesn't exist anymore?
int currentSelectionIndex = ui->cbPortList->findText(currentSelection);
if (currentSelectionIndex >= 0)
{
ui->cbPortList->setCurrentIndex(currentSelectionIndex);
}
else // our port doesn't exist anymore, close port if it's open
{
if (serialPort->isOpen()) togglePort();
}
}
void PortControl::loadBaudRateList()
{
ui->cbBaudRate->clear();
for (auto baudRate : QSerialPortInfo::standardBaudRates())
{
ui->cbBaudRate->addItem(QString::number(baudRate));
}
}
void PortControl::selectBaudRate(QString baudRate)
{
if (serialPort->isOpen())
{
if (!serialPort->setBaudRate(baudRate.toInt()))
{
qCritical() << "Can't set baud rate!";
}
else
{
qDebug() << "Baud rate changed to" << serialPort->baudRate();
}
}
}
void PortControl::selectParity(int parity)
{
if (serialPort->isOpen())
{
if(!serialPort->setParity((QSerialPort::Parity) parity))
{
qCritical() << "Can't set parity option!";
}
}
}
void PortControl::selectDataBits(int dataBits)
{
if (serialPort->isOpen())
{
if(!serialPort->setDataBits((QSerialPort::DataBits) dataBits))
{
qCritical() << "Can't set numer of data bits!";
}
}
}
void PortControl::selectStopBits(int stopBits)
{
if (serialPort->isOpen())
{
if(!serialPort->setStopBits((QSerialPort::StopBits) stopBits))
{
qCritical() << "Can't set number of stop bits!";
}
}
}
void PortControl::selectFlowControl(int flowControl)
{
if (serialPort->isOpen())
{
if(!serialPort->setFlowControl((QSerialPort::FlowControl) flowControl))
{
qCritical() << "Can't set flow control option!";
}
}
}
void PortControl::togglePort()
{
if (serialPort->isOpen())
{
serialPort->close();
qDebug() << "Closed port:" << serialPort->portName();
emit portToggled(false);
}
else
{
// port name may contain description
QString portName = ui->cbPortList->currentText().split(" ")[0];
serialPort->setPortName(portName);
// open port
if (serialPort->open(QIODevice::ReadWrite))
{
// set port settings
selectBaudRate(ui->cbBaudRate->currentText());
selectParity((QSerialPort::Parity) parityButtons.checkedId());
selectDataBits((QSerialPort::DataBits) dataBitsButtons.checkedId());
selectStopBits((QSerialPort::StopBits) stopBitsButtons.checkedId());
selectFlowControl((QSerialPort::FlowControl) flowControlButtons.checkedId());
qDebug() << "Opened port:" << serialPort->portName();
emit portToggled(true);
}
}
ui->pbOpenPort->setChecked(serialPort->isOpen());
}
void PortControl::selectPort(QString portName)
{
// portName may be coming from combobox
portName = portName.split(" ")[0];
// has selection actually changed
if (portName != serialPort->portName())
{
// if another port is already open, close it by toggling
if (serialPort->isOpen())
{
togglePort();
// open new selection by toggling
togglePort();
}
}
}
void PortControl::enableSkipByte(bool enabled)
{
ui->pbSkipByte->setDisabled(enabled);
}
void PortControl::onPortNameChanged(QString portName)
{
// was this a user entered name?
if(!discoveredPorts.contains(portName) &&
!userEnteredPorts.contains(portName))
{
userEnteredPorts << portName;
}
}