diff options
45 files changed, 1333 insertions, 923 deletions
diff --git a/.qmake.conf b/.qmake.conf index 2108ac6..138038d 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -1,3 +1,3 @@ load(qt_build_config) -MODULE_VERSION = 5.9.3 +MODULE_VERSION = 5.10.0 diff --git a/dist/changes-5.10.0 b/dist/changes-5.10.0 new file mode 100644 index 0000000..20264d1 --- /dev/null +++ b/dist/changes-5.10.0 @@ -0,0 +1,28 @@ +Qt 5.10 introduces many new features and improvements as well as bugfixes +over the 5.9.x series. For more details, refer to the online documentation +included in this distribution. The documentation is also available online: + +http://doc.qt.io/qt-5/index.html + +The Qt version 5.10 series is binary compatible with the 5.10.x series. +Applications compiled for 5.9 will continue to run with 5.10. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + +https://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Qt 5.10.0 Changes * +**************************************************************************** + + - [QTBUG-60652] Updated the examples according to good coding practices + and current conventions. + + - QSerialPort: + * Increased the internal buffer chunk size to improve performance. + * Fixed build on Android with the API level more than 21. + * Improved read performance when the buffer size is limited. diff --git a/examples/serialport/blockingmaster/dialog.cpp b/examples/serialport/blockingmaster/dialog.cpp index 08403c3..2617da7 100644 --- a/examples/serialport/blockingmaster/dialog.cpp +++ b/examples/serialport/blockingmaster/dialog.cpp @@ -50,95 +50,93 @@ #include "dialog.h" +#include <QComboBox> +#include <QGridLayout> #include <QLabel> #include <QLineEdit> -#include <QComboBox> -#include <QSpinBox> #include <QPushButton> -#include <QGridLayout> - -#include <QtSerialPort/QSerialPortInfo> - -QT_USE_NAMESPACE +#include <QSerialPortInfo> +#include <QSpinBox> -Dialog::Dialog(QWidget *parent) - : QDialog(parent) - , transactionCount(0) - , serialPortLabel(new QLabel(tr("Serial port:"))) - , serialPortComboBox(new QComboBox()) - , waitResponseLabel(new QLabel(tr("Wait response, msec:"))) - , waitResponseSpinBox(new QSpinBox()) - , requestLabel(new QLabel(tr("Request:"))) - , requestLineEdit(new QLineEdit(tr("Who are you?"))) - , trafficLabel(new QLabel(tr("No traffic."))) - , statusLabel(new QLabel(tr("Status: Not running."))) - , runButton(new QPushButton(tr("Start"))) +Dialog::Dialog(QWidget *parent) : + QDialog(parent), + m_serialPortLabel(new QLabel(tr("Serial port:"))), + m_serialPortComboBox(new QComboBox), + m_waitResponseLabel(new QLabel(tr("Wait response, msec:"))), + m_waitResponseSpinBox(new QSpinBox), + m_requestLabel(new QLabel(tr("Request:"))), + m_requestLineEdit(new QLineEdit(tr("Who are you?"))), + m_trafficLabel(new QLabel(tr("No traffic."))), + m_statusLabel(new QLabel(tr("Status: Not running."))), + m_runButton(new QPushButton(tr("Start"))) { const auto infos = QSerialPortInfo::availablePorts(); for (const QSerialPortInfo &info : infos) - serialPortComboBox->addItem(info.portName()); + m_serialPortComboBox->addItem(info.portName()); - waitResponseSpinBox->setRange(0, 10000); - waitResponseSpinBox->setValue(1000); + m_waitResponseSpinBox->setRange(0, 10000); + m_waitResponseSpinBox->setValue(1000); auto mainLayout = new QGridLayout; - mainLayout->addWidget(serialPortLabel, 0, 0); - mainLayout->addWidget(serialPortComboBox, 0, 1); - mainLayout->addWidget(waitResponseLabel, 1, 0); - mainLayout->addWidget(waitResponseSpinBox, 1, 1); - mainLayout->addWidget(runButton, 0, 2, 2, 1); - mainLayout->addWidget(requestLabel, 2, 0); - mainLayout->addWidget(requestLineEdit, 2, 1, 1, 3); - mainLayout->addWidget(trafficLabel, 3, 0, 1, 4); - mainLayout->addWidget(statusLabel, 4, 0, 1, 5); + mainLayout->addWidget(m_serialPortLabel, 0, 0); + mainLayout->addWidget(m_serialPortComboBox, 0, 1); + mainLayout->addWidget(m_waitResponseLabel, 1, 0); + mainLayout->addWidget(m_waitResponseSpinBox, 1, 1); + mainLayout->addWidget(m_runButton, 0, 2, 2, 1); + mainLayout->addWidget(m_requestLabel, 2, 0); + mainLayout->addWidget(m_requestLineEdit, 2, 1, 1, 3); + mainLayout->addWidget(m_trafficLabel, 3, 0, 1, 4); + mainLayout->addWidget(m_statusLabel, 4, 0, 1, 5); setLayout(mainLayout); setWindowTitle(tr("Blocking Master")); - serialPortComboBox->setFocus(); + m_serialPortComboBox->setFocus(); - connect(runButton, &QPushButton::clicked, this, &Dialog::transaction); - connect(&thread, &MasterThread::response, this, &Dialog::showResponse); - connect(&thread, &MasterThread::error, this, &Dialog::processError); - connect(&thread, &MasterThread::timeout, this, &Dialog::processTimeout); + connect(m_runButton, &QPushButton::clicked, this, &Dialog::transaction); + connect(&m_thread, &MasterThread::response, this, &Dialog::showResponse); + connect(&m_thread, &MasterThread::error, this, &Dialog::processError); + connect(&m_thread, &MasterThread::timeout, this, &Dialog::processTimeout); } void Dialog::transaction() { setControlsEnabled(false); - statusLabel->setText(tr("Status: Running, connected to port %1.") - .arg(serialPortComboBox->currentText())); - thread.transaction(serialPortComboBox->currentText(), - waitResponseSpinBox->value(), - requestLineEdit->text()); + m_statusLabel->setText(tr("Status: Running, connected to port %1.") + .arg(m_serialPortComboBox->currentText())); + m_thread.transaction(m_serialPortComboBox->currentText(), + m_waitResponseSpinBox->value(), + m_requestLineEdit->text()); } void Dialog::showResponse(const QString &s) { setControlsEnabled(true); - trafficLabel->setText(tr("Traffic, transaction #%1:" - "\n\r-request: %2" - "\n\r-response: %3") - .arg(++transactionCount).arg(requestLineEdit->text()).arg(s)); + m_trafficLabel->setText(tr("Traffic, transaction #%1:" + "\n\r-request: %2" + "\n\r-response: %3") + .arg(++m_transactionCount) + .arg(m_requestLineEdit->text()) + .arg(s)); } void Dialog::processError(const QString &s) { setControlsEnabled(true); - statusLabel->setText(tr("Status: Not running, %1.").arg(s)); - trafficLabel->setText(tr("No traffic.")); + m_statusLabel->setText(tr("Status: Not running, %1.").arg(s)); + m_trafficLabel->setText(tr("No traffic.")); } void Dialog::processTimeout(const QString &s) { setControlsEnabled(true); - statusLabel->setText(tr("Status: Running, %1.").arg(s)); - trafficLabel->setText(tr("No traffic.")); + m_statusLabel->setText(tr("Status: Running, %1.").arg(s)); + m_trafficLabel->setText(tr("No traffic.")); } void Dialog::setControlsEnabled(bool enable) { - runButton->setEnabled(enable); - serialPortComboBox->setEnabled(enable); - waitResponseSpinBox->setEnabled(enable); - requestLineEdit->setEnabled(enable); + m_runButton->setEnabled(enable); + m_serialPortComboBox->setEnabled(enable); + m_waitResponseSpinBox->setEnabled(enable); + m_requestLineEdit->setEnabled(enable); } diff --git a/examples/serialport/blockingmaster/dialog.h b/examples/serialport/blockingmaster/dialog.h index aff8177..8d997fa 100644 --- a/examples/serialport/blockingmaster/dialog.h +++ b/examples/serialport/blockingmaster/dialog.h @@ -51,10 +51,10 @@ #ifndef DIALOG_H #define DIALOG_H -#include <QDialog> - #include "masterthread.h" +#include <QDialog> + QT_BEGIN_NAMESPACE class QLabel; @@ -82,18 +82,18 @@ private: void setControlsEnabled(bool enable); private: - int transactionCount; - QLabel *serialPortLabel; - QComboBox *serialPortComboBox; - QLabel *waitResponseLabel; - QSpinBox *waitResponseSpinBox; - QLabel *requestLabel; - QLineEdit *requestLineEdit; - QLabel *trafficLabel; - QLabel *statusLabel; - QPushButton *runButton; + int m_transactionCount = 0; + QLabel *m_serialPortLabel = nullptr; + QComboBox *m_serialPortComboBox = nullptr; + QLabel *m_waitResponseLabel = nullptr; + QSpinBox *m_waitResponseSpinBox = nullptr; + QLabel *m_requestLabel = nullptr; + QLineEdit *m_requestLineEdit = nullptr; + QLabel *m_trafficLabel = nullptr; + QLabel *m_statusLabel = nullptr; + QPushButton *m_runButton = nullptr; - MasterThread thread; + MasterThread m_thread; }; #endif // DIALOG_H diff --git a/examples/serialport/blockingmaster/main.cpp b/examples/serialport/blockingmaster/main.cpp index cf4c421..8e68c73 100644 --- a/examples/serialport/blockingmaster/main.cpp +++ b/examples/serialport/blockingmaster/main.cpp @@ -48,10 +48,10 @@ ** ****************************************************************************/ -#include <QApplication> - #include "dialog.h" +#include <QApplication> + int main(int argc, char *argv[]) { QApplication app(argc, argv); diff --git a/examples/serialport/blockingmaster/masterthread.cpp b/examples/serialport/blockingmaster/masterthread.cpp index 5ad93fd..25aa848 100644 --- a/examples/serialport/blockingmaster/masterthread.cpp +++ b/examples/serialport/blockingmaster/masterthread.cpp @@ -50,24 +50,21 @@ #include "masterthread.h" -#include <QtSerialPort/QSerialPort> - +#include <QSerialPort> #include <QTime> -QT_USE_NAMESPACE - -MasterThread::MasterThread(QObject *parent) - : QThread(parent), waitTimeout(0), quit(false) +MasterThread::MasterThread(QObject *parent) : + QThread(parent) { } //! [0] MasterThread::~MasterThread() { - mutex.lock(); - quit = true; - cond.wakeOne(); - mutex.unlock(); + m_mutex.lock(); + m_quit = true; + m_cond.wakeOne(); + m_mutex.unlock(); wait(); } //! [0] @@ -75,16 +72,16 @@ MasterThread::~MasterThread() //! [1] //! [2] void MasterThread::transaction(const QString &portName, int waitTimeout, const QString &request) { - //! [1] - QMutexLocker locker(&mutex); - this->portName = portName; - this->waitTimeout = waitTimeout; - this->request = request; - //! [3] +//! [1] + const QMutexLocker locker(&m_mutex); + m_portName = portName; + m_waitTimeout = waitTimeout; + m_request = request; +//! [3] if (!isRunning()) start(); else - cond.wakeOne(); + m_cond.wakeOne(); } //! [2] //! [3] @@ -93,18 +90,18 @@ void MasterThread::run() { bool currentPortNameChanged = false; - mutex.lock(); - //! [4] //! [5] + m_mutex.lock(); +//! [4] //! [5] QString currentPortName; - if (currentPortName != portName) { - currentPortName = portName; + if (currentPortName != m_portName) { + currentPortName = m_portName; currentPortNameChanged = true; } - int currentWaitTimeout = waitTimeout; - QString currentRequest = request; - mutex.unlock(); - //! [5] //! [6] + int currentWaitTimeout = m_waitTimeout; + QString currentRequest = m_request; + m_mutex.unlock(); +//! [5] //! [6] QSerialPort serial; if (currentPortName.isEmpty()) { @@ -112,55 +109,55 @@ void MasterThread::run() return; } - while (!quit) { - //![6] //! [7] + while (!m_quit) { +//![6] //! [7] if (currentPortNameChanged) { serial.close(); serial.setPortName(currentPortName); if (!serial.open(QIODevice::ReadWrite)) { emit error(tr("Can't open %1, error code %2") - .arg(portName).arg(serial.error())); + .arg(m_portName).arg(serial.error())); return; } } - //! [7] //! [8] +//! [7] //! [8] // write request - QByteArray requestData = currentRequest.toLocal8Bit(); + const QByteArray requestData = currentRequest.toUtf8(); serial.write(requestData); - if (serial.waitForBytesWritten(waitTimeout)) { - //! [8] //! [10] + if (serial.waitForBytesWritten(m_waitTimeout)) { +//! [8] //! [10] // read response if (serial.waitForReadyRead(currentWaitTimeout)) { QByteArray responseData = serial.readAll(); while (serial.waitForReadyRead(10)) responseData += serial.readAll(); - QString response(responseData); - //! [12] + const QString response = QString::fromUtf8(responseData); +//! [12] emit this->response(response); - //! [10] //! [11] //! [12] +//! [10] //! [11] //! [12] } else { emit timeout(tr("Wait read response timeout %1") .arg(QTime::currentTime().toString())); } - //! [9] //! [11] +//! [9] //! [11] } else { emit timeout(tr("Wait write request timeout %1") .arg(QTime::currentTime().toString())); } - //! [9] //! [13] - mutex.lock(); - cond.wait(&mutex); - if (currentPortName != portName) { - currentPortName = portName; +//! [9] //! [13] + m_mutex.lock(); + m_cond.wait(&m_mutex); + if (currentPortName != m_portName) { + currentPortName = m_portName; currentPortNameChanged = true; } else { currentPortNameChanged = false; } - currentWaitTimeout = waitTimeout; - currentRequest = request; - mutex.unlock(); + currentWaitTimeout = m_waitTimeout; + currentRequest = m_request; + m_mutex.unlock(); } - //! [13] +//! [13] } diff --git a/examples/serialport/blockingmaster/masterthread.h b/examples/serialport/blockingmaster/masterthread.h index f23559f..9dc6048 100644 --- a/examples/serialport/blockingmaster/masterthread.h +++ b/examples/serialport/blockingmaster/masterthread.h @@ -51,8 +51,8 @@ #ifndef MASTERTHREAD_H #define MASTERTHREAD_H -#include <QThread> #include <QMutex> +#include <QThread> #include <QWaitCondition> //! [0] @@ -65,7 +65,6 @@ public: ~MasterThread(); void transaction(const QString &portName, int waitTimeout, const QString &request); - void run() Q_DECL_OVERRIDE; signals: void response(const QString &s); @@ -73,12 +72,14 @@ signals: void timeout(const QString &s); private: - QString portName; - QString request; - int waitTimeout; - QMutex mutex; - QWaitCondition cond; - bool quit; + void run() override; + + QString m_portName; + QString m_request; + int m_waitTimeout = 0; + QMutex m_mutex; + QWaitCondition m_cond; + bool m_quit = false; }; //! [0] diff --git a/examples/serialport/blockingslave/dialog.cpp b/examples/serialport/blockingslave/dialog.cpp index 3bfd419..1723086 100644 --- a/examples/serialport/blockingslave/dialog.cpp +++ b/examples/serialport/blockingslave/dialog.cpp @@ -50,95 +50,94 @@ #include "dialog.h" +#include <QComboBox> +#include <QGridLayout> #include <QLabel> #include <QLineEdit> -#include <QComboBox> -#include <QSpinBox> #include <QPushButton> -#include <QGridLayout> - -#include <QtSerialPort/QSerialPortInfo> - -QT_USE_NAMESPACE +#include <QSerialPortInfo> +#include <QSpinBox> -Dialog::Dialog(QWidget *parent) - : QDialog(parent) - , transactionCount(0) - , serialPortLabel(new QLabel(tr("Serial port:"))) - , serialPortComboBox(new QComboBox()) - , waitRequestLabel(new QLabel(tr("Wait request, msec:"))) - , waitRequestSpinBox(new QSpinBox()) - , responseLabel(new QLabel(tr("Response:"))) - , responseLineEdit(new QLineEdit(tr("Hello, I'm Slave."))) - , trafficLabel(new QLabel(tr("No traffic."))) - , statusLabel(new QLabel(tr("Status: Not running."))) - , runButton(new QPushButton(tr("Start"))) +Dialog::Dialog(QWidget *parent) : + QDialog(parent), + m_serialPortLabel(new QLabel(tr("Serial port:"))), + m_serialPortComboBox(new QComboBox), + m_waitRequestLabel(new QLabel(tr("Wait request, msec:"))), + m_waitRequestSpinBox(new QSpinBox), + m_responseLabel(new QLabel(tr("Response:"))), + m_responseLineEdit(new QLineEdit(tr("Hello, I'm Slave."))), + m_trafficLabel(new QLabel(tr("No traffic."))), + m_statusLabel(new QLabel(tr("Status: Not running."))), + m_runButton(new QPushButton(tr("Start"))) { - waitRequestSpinBox->setRange(0, 10000); - waitRequestSpinBox->setValue(10000); + m_waitRequestSpinBox->setRange(0, 10000); + m_waitRequestSpinBox->setValue(10000); const auto infos = QSerialPortInfo::availablePorts(); for (const QSerialPortInfo &info : infos) - serialPortComboBox->addItem(info.portName()); + m_serialPortComboBox->addItem(info.portName()); auto mainLayout = new QGridLayout; - mainLayout->addWidget(serialPortLabel, 0, 0); - mainLayout->addWidget(serialPortComboBox, 0, 1); - mainLayout->addWidget(waitRequestLabel, 1, 0); - mainLayout->addWidget(waitRequestSpinBox, 1, 1); - mainLayout->addWidget(runButton, 0, 2, 2, 1); - mainLayout->addWidget(responseLabel, 2, 0); - mainLayout->addWidget(responseLineEdit, 2, 1, 1, 3); - mainLayout->addWidget(trafficLabel, 3, 0, 1, 4); - mainLayout->addWidget(statusLabel, 4, 0, 1, 5); + mainLayout->addWidget(m_serialPortLabel, 0, 0); + mainLayout->addWidget(m_serialPortComboBox, 0, 1); + mainLayout->addWidget(m_waitRequestLabel, 1, 0); + mainLayout->addWidget(m_waitRequestSpinBox, 1, 1); + mainLayout->addWidget(m_runButton, 0, 2, 2, 1); + mainLayout->addWidget(m_responseLabel, 2, 0); + mainLayout->addWidget(m_responseLineEdit, 2, 1, 1, 3); + mainLayout->addWidget(m_trafficLabel, 3, 0, 1, 4); + mainLayout->addWidget(m_statusLabel, 4, 0, 1, 5); setLayout(mainLayout); setWindowTitle(tr("Blocking Slave")); - serialPortComboBox->setFocus(); + m_serialPortComboBox->setFocus(); - connect(runButton, &QPushButton::clicked, this, &Dialog::startSlave); - connect(&thread, &SlaveThread::request, this,&Dialog::showRequest); - connect(&thread, &SlaveThread::error, this, &Dialog::processError); - connect(&thread, &SlaveThread::timeout, this, &Dialog::processTimeout); + connect(m_runButton, &QPushButton::clicked, this, &Dialog::startSlave); + connect(&m_thread, &SlaveThread::request, this,&Dialog::showRequest); + connect(&m_thread, &SlaveThread::error, this, &Dialog::processError); + connect(&m_thread, &SlaveThread::timeout, this, &Dialog::processTimeout); - connect(serialPortComboBox, static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentIndexChanged), + connect(m_serialPortComboBox, QOverload<const QString &>::of(&QComboBox::currentIndexChanged), this, &Dialog::activateRunButton); - connect(waitRequestSpinBox, static_cast<void (QSpinBox::*)(const QString &)>(&QSpinBox::valueChanged), + connect(m_waitRequestSpinBox, QOverload<const QString &>::of(&QSpinBox::valueChanged), this, &Dialog::activateRunButton); - connect(responseLineEdit, &QLineEdit::textChanged, this, &Dialog::activateRunButton); + connect(m_responseLineEdit, &QLineEdit::textChanged, this, &Dialog::activateRunButton); } void Dialog::startSlave() { - runButton->setEnabled(false); - statusLabel->setText(tr("Status: Running, connected to port %1.") - .arg(serialPortComboBox->currentText())); - thread.startSlave(serialPortComboBox->currentText(), - waitRequestSpinBox->value(), - responseLineEdit->text()); + m_runButton->setEnabled(false); + m_statusLabel->setText(tr("Status: Running, connected to port %1.") + .arg(m_serialPortComboBox->currentText())); + m_thread.startSlave(m_serialPortComboBox->currentText(), + m_waitRequestSpinBox->value(), + m_responseLineEdit->text()); } void Dialog::showRequest(const QString &s) { - trafficLabel->setText(tr("Traffic, transaction #%1:" - "\n\r-request: %2" - "\n\r-response: %3") - .arg(++transactionCount).arg(s).arg(responseLineEdit->text())); + m_trafficLabel->setText(tr("Traffic, transaction #%1:" + "\n\r-request: %2" + "\n\r-response: %3") + .arg(++m_transactionCount) + .arg(s) + .arg(m_responseLineEdit->text())); } void Dialog::processError(const QString &s) { activateRunButton(); - statusLabel->setText(tr("Status: Not running, %1.").arg(s)); - trafficLabel->setText(tr("No traffic.")); + m_statusLabel->setText(tr("Status: Not running, %1.").arg(s)); + m_trafficLabel->setText(tr("No traffic.")); } void Dialog::processTimeout(const QString &s) { - statusLabel->setText(tr("Status: Running, %1.").arg(s)); - trafficLabel->setText(tr("No traffic.")); + m_statusLabel->setText(tr("Status: Running, %1.").arg(s)); + m_trafficLabel->setText(tr("No traffic.")); } + void Dialog::activateRunButton() { - runButton->setEnabled(true); + m_runButton->setEnabled(true); } diff --git a/examples/serialport/blockingslave/dialog.h b/examples/serialport/blockingslave/dialog.h index 0e59410..c8f80a6 100644 --- a/examples/serialport/blockingslave/dialog.h +++ b/examples/serialport/blockingslave/dialog.h @@ -51,10 +51,10 @@ #ifndef DIALOG_H #define DIALOG_H -#include <QDialog> - #include "slavethread.h" +#include <QDialog> + QT_BEGIN_NAMESPACE class QLabel; @@ -80,18 +80,18 @@ private slots: void activateRunButton(); private: - int transactionCount; - QLabel *serialPortLabel; - QComboBox *serialPortComboBox; - QLabel *waitRequestLabel; - QSpinBox *waitRequestSpinBox; - QLabel *responseLabel; - QLineEdit *responseLineEdit; - QLabel *trafficLabel; - QLabel *statusLabel; - QPushButton *runButton; + int m_transactionCount = 0; + QLabel *m_serialPortLabel = nullptr; + QComboBox *m_serialPortComboBox = nullptr; + QLabel *m_waitRequestLabel = nullptr; + QSpinBox *m_waitRequestSpinBox = nullptr; + QLabel *m_responseLabel = nullptr; + QLineEdit *m_responseLineEdit = nullptr; + QLabel *m_trafficLabel = nullptr; + QLabel *m_statusLabel = nullptr; + QPushButton *m_runButton = nullptr; - SlaveThread thread; + SlaveThread m_thread; }; #endif // DIALOG_H diff --git a/examples/serialport/blockingslave/main.cpp b/examples/serialport/blockingslave/main.cpp index cf4c421..8e68c73 100644 --- a/examples/serialport/blockingslave/main.cpp +++ b/examples/serialport/blockingslave/main.cpp @@ -48,10 +48,10 @@ ** ****************************************************************************/ -#include <QApplication> - #include "dialog.h" +#include <QApplication> + int main(int argc, char *argv[]) { QApplication app(argc, argv); diff --git a/examples/serialport/blockingslave/slavethread.cpp b/examples/serialport/blockingslave/slavethread.cpp index 66bfb19..85b010a 100644 --- a/examples/serialport/blockingslave/slavethread.cpp +++ b/examples/serialport/blockingslave/slavethread.cpp @@ -50,22 +50,20 @@ #include "slavethread.h" -#include <QtSerialPort/QSerialPort> - +#include <QSerialPort> #include <QTime> -QT_USE_NAMESPACE - -SlaveThread::SlaveThread(QObject *parent) - : QThread(parent), waitTimeout(0), quit(false) +SlaveThread::SlaveThread(QObject *parent) : + QThread(parent) { } + //! [0] SlaveThread::~SlaveThread() { - mutex.lock(); - quit = true; - mutex.unlock(); + m_mutex.lock(); + m_quit = true; + m_mutex.unlock(); wait(); } //! [0] @@ -73,12 +71,12 @@ SlaveThread::~SlaveThread() //! [1] //! [2] void SlaveThread::startSlave(const QString &portName, int waitTimeout, const QString &response) { -//! [1] - QMutexLocker locker(&mutex); - this->portName = portName; - this->waitTimeout = waitTimeout; - this->response = response; -//! [3] + //! [1] + const QMutexLocker locker(&m_mutex); + m_portName = portName; + m_waitTimeout = waitTimeout; + m_response = response; + //! [3] if (!isRunning()) start(); } @@ -89,21 +87,21 @@ void SlaveThread::run() { bool currentPortNameChanged = false; - mutex.lock(); + m_mutex.lock(); //! [4] //! [5] QString currentPortName; - if (currentPortName != portName) { - currentPortName = portName; + if (currentPortName != m_portName) { + currentPortName = m_portName; currentPortNameChanged = true; } - int currentWaitTimeout = waitTimeout; - QString currentRespone = response; - mutex.unlock(); + int currentWaitTimeout = m_waitTimeout; + QString currentRespone = m_response; + m_mutex.unlock(); //! [5] //! [6] QSerialPort serial; - while (!quit) { + while (!m_quit) { //![6] //! [7] if (currentPortNameChanged) { serial.close(); @@ -111,7 +109,7 @@ void SlaveThread::run() if (!serial.open(QIODevice::ReadWrite)) { emit error(tr("Can't open %1, error code %2") - .arg(portName).arg(serial.error())); + .arg(m_portName).arg(serial.error())); return; } } @@ -124,10 +122,10 @@ void SlaveThread::run() requestData += serial.readAll(); //! [8] //! [10] // write response - QByteArray responseData = currentRespone.toLocal8Bit(); + const QByteArray responseData = currentRespone.toUtf8(); serial.write(responseData); - if (serial.waitForBytesWritten(waitTimeout)) { - QString request(requestData); + if (serial.waitForBytesWritten(m_waitTimeout)) { + const QString request = QString::fromUtf8(requestData); //! [12] emit this->request(request); //! [10] //! [11] //! [12] @@ -141,16 +139,16 @@ void SlaveThread::run() .arg(QTime::currentTime().toString())); } //! [9] //! [13] - mutex.lock(); - if (currentPortName != portName) { - currentPortName = portName; + m_mutex.lock(); + if (currentPortName != m_portName) { + currentPortName = m_portName; currentPortNameChanged = true; } else { currentPortNameChanged = false; } - currentWaitTimeout = waitTimeout; - currentRespone = response; - mutex.unlock(); + currentWaitTimeout = m_waitTimeout; + currentRespone = m_response; + m_mutex.unlock(); } //! [13] } diff --git a/examples/serialport/blockingslave/slavethread.h b/examples/serialport/blockingslave/slavethread.h index 9a15e24..737e7cb 100644 --- a/examples/serialport/blockingslave/slavethread.h +++ b/examples/serialport/blockingslave/slavethread.h @@ -51,8 +51,8 @@ #ifndef SLAVETHREAD_H #define SLAVETHREAD_H -#include <QThread> #include <QMutex> +#include <QThread> #include <QWaitCondition> //! [0] @@ -65,7 +65,6 @@ public: ~SlaveThread(); void startSlave(const QString &portName, int waitTimeout, const QString &response); - void run() Q_DECL_OVERRIDE; signals: void request(const QString &s); @@ -73,11 +72,13 @@ signals: void timeout(const QString &s); private: - QString portName; - QString response; - int waitTimeout; - QMutex mutex; - bool quit; + void run() override; + + QString m_portName; + QString m_response; + int m_waitTimeout = 0; + QMutex m_mutex; + bool m_quit = false; }; //! [0] diff --git a/examples/serialport/cenumerator/main.cpp b/examples/serialport/cenumerator/main.cpp index f805021..af6d7e4 100644 --- a/examples/serialport/cenumerator/main.cpp +++ b/examples/serialport/cenumerator/main.cpp @@ -48,21 +48,19 @@ ** ****************************************************************************/ -#include <QTextStream> #include <QCoreApplication> -#include <QtSerialPort/QSerialPortInfo> - -QT_USE_NAMESPACE +#include <QSerialPortInfo> +#include <QTextStream> int main(int argc, char *argv[]) { - QCoreApplication a(argc, argv); + QCoreApplication coreApplication(argc, argv); QTextStream out(stdout); const auto serialPortInfos = QSerialPortInfo::availablePorts(); - out << QObject::tr("Total number of ports available: ") << serialPortInfos.count() << endl; + out << "Total number of ports available: " << serialPortInfos.count() << endl; - const QString blankString = QObject::tr("N/A"); + const QString blankString = "N/A"; QString description; QString manufacturer; QString serialNumber; @@ -72,14 +70,18 @@ int main(int argc, char *argv[]) manufacturer = serialPortInfo.manufacturer(); serialNumber = serialPortInfo.serialNumber(); out << endl - << QObject::tr("Port: ") << serialPortInfo.portName() << endl - << QObject::tr("Location: ") << serialPortInfo.systemLocation() << endl - << QObject::tr("Description: ") << (!description.isEmpty() ? description : blankString) << endl - << QObject::tr("Manufacturer: ") << (!manufacturer.isEmpty() ? manufacturer : blankString) << endl - << QObject::tr("Serial number: ") << (!serialNumber.isEmpty() ? serialNumber : blankString) << endl - << QObject::tr("Vendor Identifier: ") << (serialPortInfo.hasVendorIdentifier() ? QByteArray::number(serialPortInfo.vendorIdentifier(), 16) : blankString) << endl - << QObject::tr("Product Identifier: ") << (serialPortInfo.hasProductIdentifier() ? QByteArray::number(serialPortInfo.productIdentifier(), 16) : blankString) << endl - << QObject::tr("Busy: ") << (serialPortInfo.isBusy() ? QObject::tr("Yes") : QObject::tr("No")) << endl; + << "Port: " << serialPortInfo.portName() << endl + << "Location: " << serialPortInfo.systemLocation() << endl + << "Description: " << (!description.isEmpty() ? description : blankString) << endl + << "Manufacturer: " << (!manufacturer.isEmpty() ? manufacturer : blankString) << endl + << "Serial number: " << (!serialNumber.isEmpty() ? serialNumber : blankString) << endl + << "Vendor Identifier: " << (serialPortInfo.hasVendorIdentifier() + ? QByteArray::number(serialPortInfo.vendorIdentifier(), 16) + : blankString) << endl + << "Product Identifier: " << (serialPortInfo.hasProductIdentifier() + ? QByteArray::number(serialPortInfo.productIdentifier(), 16) + : blankString) << endl + << "Busy: " << (serialPortInfo.isBusy() ? "Yes" : "No") << endl; } return 0; diff --git a/examples/serialport/creaderasync/main.cpp b/examples/serialport/creaderasync/main.cpp index dd1f755..6c669ce 100644 --- a/examples/serialport/creaderasync/main.cpp +++ b/examples/serialport/creaderasync/main.cpp @@ -50,37 +50,39 @@ #include "serialportreader.h" -#include <QtSerialPort/QSerialPort> - -#include <QTextStream> #include <QCoreApplication> -#include <QFile> +#include <QSerialPort> #include <QStringList> - -QT_USE_NAMESPACE +#include <QTextStream> int main(int argc, char *argv[]) { QCoreApplication coreApplication(argc, argv); - int argumentCount = QCoreApplication::arguments().size(); - QStringList argumentList = QCoreApplication::arguments(); + const int argumentCount = QCoreApplication::arguments().size(); + const QStringList argumentList = QCoreApplication::arguments(); QTextStream standardOutput(stdout); if (argumentCount == 1) { - standardOutput << QObject::tr("Usage: %1 <serialportname> [baudrate]").arg(argumentList.first()) << endl; + standardOutput << QObject::tr("Usage: %1 <serialportname> [baudrate]") + .arg(argumentList.first()) + << endl; return 1; } QSerialPort serialPort; - QString serialPortName = argumentList.at(1); + const QString serialPortName = argumentList.at(1); serialPort.setPortName(serialPortName); - int serialPortBaudRate = (argumentCount > 2) ? argumentList.at(2).toInt() : QSerialPort::Baud9600; + const int serialPortBaudRate = (argumentCount > 2) + ? argumentList.at(2).toInt() : QSerialPort::Baud9600; serialPort.setBaudRate(serialPortBaudRate); if (!serialPort.open(QIODevice::ReadOnly)) { - standardOutput << QObject::tr("Failed to open port %1, error: %2").arg(serialPortName).arg(serialPort.errorString()) << endl; + standardOutput << QObject::tr("Failed to open port %1, error: %2") + .arg(serialPortName) + .arg(serialPort.errorString()) + << endl; return 1; } diff --git a/examples/serialport/creaderasync/serialportreader.cpp b/examples/serialport/creaderasync/serialportreader.cpp index f85dd8a..a701839 100644 --- a/examples/serialport/creaderasync/serialportreader.cpp +++ b/examples/serialport/creaderasync/serialportreader.cpp @@ -52,25 +52,18 @@ #include <QCoreApplication> -QT_USE_NAMESPACE - -SerialPortReader::SerialPortReader(QSerialPort *serialPort, QObject *parent) - : QObject(parent) - , m_serialPort(serialPort) - , m_standardOutput(stdout) +SerialPortReader::SerialPortReader(QSerialPort *serialPort, QObject *parent) : + QObject(parent), + m_serialPort(serialPort), + m_standardOutput(stdout) { connect(m_serialPort, &QSerialPort::readyRead, this, &SerialPortReader::handleReadyRead); - connect(m_serialPort, static_cast<void (QSerialPort::*)(QSerialPort::SerialPortError)>(&QSerialPort::error), - this, &SerialPortReader::handleError); + connect(m_serialPort, &QSerialPort::errorOccurred, this, &SerialPortReader::handleError); connect(&m_timer, &QTimer::timeout, this, &SerialPortReader::handleTimeout); m_timer.start(5000); } -SerialPortReader::~SerialPortReader() -{ -} - void SerialPortReader::handleReadyRead() { m_readData.append(m_serialPort->readAll()); @@ -82,9 +75,14 @@ void SerialPortReader::handleReadyRead() void SerialPortReader::handleTimeout() { if (m_readData.isEmpty()) { - m_standardOutput << QObject::tr("No data was currently available for reading from port %1").arg(m_serialPort->portName()) << endl; + m_standardOutput << QObject::tr("No data was currently available " + "for reading from port %1") + .arg(m_serialPort->portName()) + << endl; } else { - m_standardOutput << QObject::tr("Data successfully received from port %1").arg(m_serialPort->portName()) << endl; + m_standardOutput << QObject::tr("Data successfully received from port %1") + .arg(m_serialPort->portName()) + << endl; m_standardOutput << m_readData << endl; } @@ -94,7 +92,11 @@ void SerialPortReader::handleTimeout() void SerialPortReader::handleError(QSerialPort::SerialPortError serialPortError) { if (serialPortError == QSerialPort::ReadError) { - m_standardOutput << QObject::tr("An I/O error occurred while reading the data from port %1, error: %2").arg(m_serialPort->portName()).arg(m_serialPort->errorString()) << endl; + m_standardOutput << QObject::tr("An I/O error occurred while reading " + "the data from port %1, error: %2") + .arg(m_serialPort->portName()) + .arg(m_serialPort->errorString()) + << endl; QCoreApplication::exit(1); } } diff --git a/examples/serialport/creaderasync/serialportreader.h b/examples/serialport/creaderasync/serialportreader.h index 6698087..53074f1 100644 --- a/examples/serialport/creaderasync/serialportreader.h +++ b/examples/serialport/creaderasync/serialportreader.h @@ -51,14 +51,10 @@ #ifndef SERIALPORTREADER_H #define SERIALPORTREADER_H -#include <QtSerialPort/QSerialPort> - +#include <QByteArray> +#include <QSerialPort> #include <QTextStream> #include <QTimer> -#include <QByteArray> -#include <QObject> - -QT_USE_NAMESPACE QT_BEGIN_NAMESPACE @@ -70,7 +66,6 @@ class SerialPortReader : public QObject public: explicit SerialPortReader(QSerialPort *serialPort, QObject *parent = nullptr); - ~SerialPortReader(); private slots: void handleReadyRead(); @@ -78,10 +73,10 @@ private slots: void handleError(QSerialPort::SerialPortError error); private: - QSerialPort *m_serialPort; - QByteArray m_readData; + QSerialPort *m_serialPort = nullptr; + QByteArray m_readData; QTextStream m_standardOutput; - QTimer m_timer; + QTimer m_timer; }; -#endif +#endif // SERIALPORTREADER_H diff --git a/examples/serialport/creadersync/main.cpp b/examples/serialport/creadersync/main.cpp index c1bc08b..845a5fb 100644 --- a/examples/serialport/creadersync/main.cpp +++ b/examples/serialport/creadersync/main.cpp @@ -48,36 +48,36 @@ ** ****************************************************************************/ -#include <QtSerialPort/QSerialPort> - -#include <QTextStream> #include <QCoreApplication> +#include <QSerialPort> #include <QStringList> - -QT_USE_NAMESPACE +#include <QTextStream> int main(int argc, char *argv[]) { QCoreApplication coreApplication(argc, argv); - int argumentCount = QCoreApplication::arguments().size(); - QStringList argumentList = QCoreApplication::arguments(); + const int argumentCount = QCoreApplication::arguments().size(); + const QStringList argumentList = QCoreApplication::arguments(); QTextStream standardOutput(stdout); if (argumentCount == 1) { - standardOutput << QObject::tr("Usage: %1 <serialportname> [baudrate]").arg(argumentList.first()) << endl; + standardOutput << QObject::tr("Usage: %1 <serialportname> [baudrate]") + .arg(argumentList.first()) << endl; return 1; } QSerialPort serialPort; - QString serialPortName = argumentList.at(1); + const QString serialPortName = argumentList.at(1); serialPort.setPortName(serialPortName); - int serialPortBaudRate = (argumentCount > 2) ? argumentList.at(2).toInt() : QSerialPort::Baud9600; + const int serialPortBaudRate = (argumentCount > 2) + ? argumentList.at(2).toInt() : QSerialPort::Baud9600; serialPort.setBaudRate(serialPortBaudRate); if (!serialPort.open(QIODevice::ReadOnly)) { - standardOutput << QObject::tr("Failed to open port %1, error: %2").arg(serialPortName).arg(serialPort.error()) << endl; + standardOutput << QObject::tr("Failed to open port %1, error: %2") + .arg(serialPortName).arg(serialPort.error()) << endl; return 1; } @@ -86,14 +86,18 @@ int main(int argc, char *argv[]) readData.append(serialPort.readAll()); if (serialPort.error() == QSerialPort::ReadError) { - standardOutput << QObject::tr("Failed to read from port %1, error: %2").arg(serialPortName).arg(serialPort.errorString()) << endl; + standardOutput << QObject::tr("Failed to read from port %1, error: %2") + .arg(serialPortName).arg(serialPort.errorString()) << endl; return 1; } else if (serialPort.error() == QSerialPort::TimeoutError && readData.isEmpty()) { - standardOutput << QObject::tr("No data was currently available for reading from port %1").arg(serialPortName) << endl; + standardOutput << QObject::tr("No data was currently available" + " for reading from port %1") + .arg(serialPortName) << endl; return 0; } - standardOutput << QObject::tr("Data successfully received from port %1").arg(serialPortName) << endl; + standardOutput << QObject::tr("Data successfully received from port %1") + .arg(serialPortName) << endl; standardOutput << readData << endl; return 0; diff --git a/examples/serialport/cwriterasync/main.cpp b/examples/serialport/cwriterasync/main.cpp index 4ffb44b..4d65e0a 100644 --- a/examples/serialport/cwriterasync/main.cpp +++ b/examples/serialport/cwriterasync/main.cpp @@ -50,33 +50,32 @@ #include "serialportwriter.h" -#include <QtSerialPort/QSerialPort> - -#include <QTextStream> #include <QCoreApplication> #include <QFile> +#include <QSerialPort> #include <QStringList> - -QT_USE_NAMESPACE +#include <QTextStream> int main(int argc, char *argv[]) { QCoreApplication coreApplication(argc, argv); - int argumentCount = QCoreApplication::arguments().size(); - QStringList argumentList = QCoreApplication::arguments(); + const int argumentCount = QCoreApplication::arguments().size(); + const QStringList argumentList = QCoreApplication::arguments(); QTextStream standardOutput(stdout); if (argumentCount == 1) { - standardOutput << QObject::tr("Usage: %1 <serialportname> [baudrate]").arg(argumentList.first()) << endl; + standardOutput << QObject::tr("Usage: %1 <serialportname> [baudrate]") + .arg(argumentList.first()) << endl; return 1; } QSerialPort serialPort; - QString serialPortName = argumentList.at(1); + const QString serialPortName = argumentList.at(1); serialPort.setPortName(serialPortName); - int serialPortBaudRate = (argumentCount > 2) ? argumentList.at(2).toInt() : QSerialPort::Baud9600; + const int serialPortBaudRate = (argumentCount > 2) + ? argumentList.at(2).toInt() : QSerialPort::Baud9600; serialPort.setBaudRate(serialPortBaudRate); serialPort.open(QIODevice::WriteOnly); @@ -87,11 +86,14 @@ int main(int argc, char *argv[]) return 1; } - QByteArray writeData(dataFile.readAll()); + const QByteArray writeData(dataFile.readAll()); dataFile.close(); if (writeData.isEmpty()) { - standardOutput << QObject::tr("Either no data was currently available on the standard input for reading, or an error occurred for port %1, error: %2").arg(serialPortName).arg(serialPort.errorString()) << endl; + standardOutput << QObject::tr("Either no data was currently available on " + "the standard input for reading, " + "or an error occurred for port %1, error: %2") + .arg(serialPortName).arg(serialPort.errorString()) << endl; return 1; } diff --git a/examples/serialport/cwriterasync/serialportwriter.cpp b/examples/serialport/cwriterasync/serialportwriter.cpp index e940f3d..c2916bb 100644 --- a/examples/serialport/cwriterasync/serialportwriter.cpp +++ b/examples/serialport/cwriterasync/serialportwriter.cpp @@ -52,45 +52,47 @@ #include <QCoreApplication> -QT_USE_NAMESPACE - -SerialPortWriter::SerialPortWriter(QSerialPort *serialPort, QObject *parent) - : QObject(parent) - , m_serialPort(serialPort) - , m_standardOutput(stdout) - , m_bytesWritten(0) +SerialPortWriter::SerialPortWriter(QSerialPort *serialPort, QObject *parent) : + QObject(parent), + m_serialPort(serialPort), + m_standardOutput(stdout) { m_timer.setSingleShot(true); - connect(m_serialPort, &QSerialPort::bytesWritten, this, &SerialPortWriter::handleBytesWritten); - connect(m_serialPort, static_cast<void (QSerialPort::*)(QSerialPort::SerialPortError)>(&QSerialPort::error), + connect(m_serialPort, &QSerialPort::bytesWritten, + this, &SerialPortWriter::handleBytesWritten); + connect(m_serialPort, &QSerialPort::errorOccurred, this, &SerialPortWriter::handleError); connect(&m_timer, &QTimer::timeout, this, &SerialPortWriter::handleTimeout); } -SerialPortWriter::~SerialPortWriter() -{ -} - void SerialPortWriter::handleBytesWritten(qint64 bytes) { m_bytesWritten += bytes; if (m_bytesWritten == m_writeData.size()) { m_bytesWritten = 0; - m_standardOutput << QObject::tr("Data successfully sent to port %1").arg(m_serialPort->portName()) << endl; + m_standardOutput << QObject::tr("Data successfully sent to port %1") + .arg(m_serialPort->portName()) << endl; QCoreApplication::quit(); } } void SerialPortWriter::handleTimeout() { - m_standardOutput << QObject::tr("Operation timed out for port %1, error: %2").arg(m_serialPort->portName()).arg(m_serialPort->errorString()) << endl; + m_standardOutput << QObject::tr("Operation timed out for port %1, error: %2") + .arg(m_serialPort->portName()) + .arg(m_serialPort->errorString()) + << endl; QCoreApplication::exit(1); } void SerialPortWriter::handleError(QSerialPort::SerialPortError serialPortError) { if (serialPortError == QSerialPort::WriteError) { - m_standardOutput << QObject::tr("An I/O error occurred while writing the data to port %1, error: %2").arg(m_serialPort->portName()).arg(m_serialPort->errorString()) << endl; + m_standardOutput << QObject::tr("An I/O error occurred while writing" + " the data to port %1, error: %2") + .arg(m_serialPort->portName()) + .arg(m_serialPort->errorString()) + << endl; QCoreApplication::exit(1); } } @@ -99,13 +101,19 @@ void SerialPortWriter::write(const QByteArray &writeData) { m_writeData = writeData; - qint64 bytesWritten = m_serialPort->write(writeData); + const qint64 bytesWritten = m_serialPort->write(writeData); if (bytesWritten == -1) { - m_standardOutput << QObject::tr("Failed to write the data to port %1, error: %2").arg(m_serialPort->portName()).arg(m_serialPort->errorString()) << endl; + m_standardOutput << QObject::tr("Failed to write the data to port %1, error: %2") + .arg(m_serialPort->portName()) + .arg(m_serialPort->errorString()) + << endl; QCoreApplication::exit(1); } else if (bytesWritten != m_writeData.size()) { - m_standardOutput << QObject::tr("Failed to write all the data to port %1, error: %2").arg(m_serialPort->portName()).arg(m_serialPort->errorString()) << endl; + m_standardOutput << QObject::tr("Failed to write all the data to port %1, error: %2") + .arg(m_serialPort->portName()) + .arg(m_serialPort->errorString()) + << endl; QCoreApplication::exit(1); } diff --git a/examples/serialport/cwriterasync/serialportwriter.h b/examples/serialport/cwriterasync/serialportwriter.h index 9fd305f..1e94c0f 100644 --- a/examples/serialport/cwriterasync/serialportwriter.h +++ b/examples/serialport/cwriterasync/serialportwriter.h @@ -51,14 +51,11 @@ #ifndef SERIALPORTWRITER_H #define SERIALPORTWRITER_H -#include <QtSerialPort/QSerialPort> - -#include <QTextStream> -#include <QTimer> #include <QByteArray> #include <QObject> - -QT_USE_NAMESPACE +#include <QSerialPort> +#include <QTextStream> +#include <QTimer> QT_BEGIN_NAMESPACE @@ -70,8 +67,6 @@ class SerialPortWriter : public QObject public: explicit SerialPortWriter(QSerialPort *serialPort, QObject *parent = nullptr); - ~SerialPortWriter(); - void write(const QByteArray &writeData); private slots: @@ -80,11 +75,11 @@ private slots: void handleError(QSerialPort::SerialPortError error); private: - QSerialPort *m_serialPort; - QByteArray m_writeData; - QTextStream m_standardOutput; - qint64 m_bytesWritten; - QTimer m_timer; + QSerialPort *m_serialPort = nullptr; + QByteArray m_writeData; + QTextStream m_standardOutput; + qint64 m_bytesWritten = 0; + QTimer m_timer; }; -#endif +#endif // SERIALPORTWRITER_H diff --git a/examples/serialport/cwritersync/main.cpp b/examples/serialport/cwritersync/main.cpp index a134ed9..125c111 100644 --- a/examples/serialport/cwritersync/main.cpp +++ b/examples/serialport/cwritersync/main.cpp @@ -48,43 +48,45 @@ ** ****************************************************************************/ -#include <QtSerialPort/QSerialPort> - -#include <QTextStream> #include <QCoreApplication> #include <QFile> +#include <QSerialPort> #include <QStringList> - -QT_USE_NAMESPACE +#include <QTextStream> int main(int argc, char *argv[]) { QCoreApplication coreApplication(argc, argv); - int argumentCount = QCoreApplication::arguments().size(); - QStringList argumentList = QCoreApplication::arguments(); + const int argumentCount = QCoreApplication::arguments().size(); + const QStringList argumentList = QCoreApplication::arguments(); QTextStream standardOutput(stdout); if (argumentCount == 1) { - standardOutput << QObject::tr("Usage: %1 <serialportname> [baudrate]").arg(argumentList.first()) << endl; + standardOutput << QObject::tr("Usage: %1 <serialportname> [baudrate]") + .arg(argumentList.first()) << endl; return 1; } QSerialPort serialPort; - QString serialPortName = argumentList.at(1); + const QString serialPortName = argumentList.at(1); serialPort.setPortName(serialPortName); - int serialPortBaudRate = (argumentCount > 2) ? argumentList.at(2).toInt() : QSerialPort::Baud9600; + const int serialPortBaudRate = (argumentCount > 2) + ? argumentList.at(2).toInt() : QSerialPort::Baud9600; serialPort.setBaudRate(serialPortBaudRate); if (!serialPort.open(QIODevice::WriteOnly)) { - standardOutput << QObject::tr("Failed to open port %1, error: %2").arg(serialPortName).arg(serialPort.errorString()) << endl; + standardOutput << QObject::tr("Failed to open port %1, error: %2") + .arg(serialPortName).arg(serialPort.errorString()) + << endl; return 1; } QFile dataFile; if (!dataFile.open(stdin, QIODevice::ReadOnly)) { - standardOutput << QObject::tr("Failed to open stdin for reading") << endl; + standardOutput << QObject::tr("Failed to open stdin for reading") + << endl; return 1; } @@ -92,24 +94,32 @@ int main(int argc, char *argv[]) dataFile.close(); if (writeData.isEmpty()) { - standardOutput << QObject::tr("Either no data was currently available on the standard input for reading, or an error occurred for port %1, error: %2").arg(serialPortName).arg(serialPort.errorString()) << endl; + standardOutput << QObject::tr("Either no data was currently available on " + "the standard input for reading, or an error " + "occurred for port %1, error: %2") + .arg(serialPortName).arg(serialPort.errorString()) << endl; return 1; } - qint64 bytesWritten = serialPort.write(writeData); + const qint64 bytesWritten = serialPort.write(writeData); if (bytesWritten == -1) { - standardOutput << QObject::tr("Failed to write the data to port %1, error: %2").arg(serialPortName).arg(serialPort.errorString()) << endl; + standardOutput << QObject::tr("Failed to write the data to port %1, error: %2") + .arg(serialPortName).arg(serialPort.errorString()) << endl; return 1; } else if (bytesWritten != writeData.size()) { - standardOutput << QObject::tr("Failed to write all the data to port %1, error: %2").arg(serialPortName).arg(serialPort.errorString()) << endl; + standardOutput << QObject::tr("Failed to write all the data to port %1, error: %2") + .arg(serialPortName).arg(serialPort.errorString()) << endl; return 1; } else if (!serialPort.waitForBytesWritten(5000)) { - standardOutput << QObject::tr("Operation timed out or an error occurred for port %1, error: %2").arg(serialPortName).arg(serialPort.errorString()) << endl; + standardOutput << QObject::tr("Operation timed out or an error " + "occurred for port %1, error: %2") + .arg(serialPortName).arg(serialPort.errorString()) << endl; return 1; } - standardOutput << QObject::tr("Data successfully sent to port %1").arg(serialPortName) << endl; + standardOutput << QObject::tr("Data successfully sent to port %1") + .arg(serialPortName) << endl; return 0; } diff --git a/examples/serialport/enumerator/main.cpp b/examples/serialport/enumerator/main.cpp index d7622a2..fef1ce0 100644 --- a/examples/serialport/enumerator/main.cpp +++ b/examples/serialport/enumerator/main.cpp @@ -50,13 +50,11 @@ ****************************************************************************/ #include <QApplication> -#include <QWidget> -#include <QVBoxLayout> #include <QLabel> #include <QScrollArea> -#include <QtSerialPort/QSerialPortInfo> - -QT_USE_NAMESPACE +#include <QSerialPortInfo> +#include <QVBoxLayout> +#include <QWidget> int main(int argc, char *argv[]) { diff --git a/examples/serialport/master/dialog.cpp b/examples/serialport/master/dialog.cpp index 4bed08b..e12d837 100644 --- a/examples/serialport/master/dialog.cpp +++ b/examples/serialport/master/dialog.cpp @@ -50,106 +50,105 @@ #include "dialog.h" +#include <QComboBox> +#include <QGridLayout> #include <QLabel> #include <QLineEdit> -#include <QComboBox> -#include <QSpinBox> #include <QPushButton> -#include <QGridLayout> +#include <QSerialPortInfo> +#include <QSpinBox> -#include <QtSerialPort/QSerialPortInfo> - -QT_USE_NAMESPACE - -Dialog::Dialog(QWidget *parent) - : QDialog(parent) - , transactionCount(0) - , serialPortLabel(new QLabel(tr("Serial port:"))) - , serialPortComboBox(new QComboBox()) - , waitResponseLabel(new QLabel(tr("Wait response, msec:"))) - , waitResponseSpinBox(new QSpinBox()) - , requestLabel(new QLabel(tr("Request:"))) - , requestLineEdit(new QLineEdit(tr("Who are you?"))) - , trafficLabel(new QLabel(tr("No traffic."))) - , statusLabel(new QLabel(tr("Status: Not running."))) - , runButton(new QPushButton(tr("Start"))) +Dialog::Dialog(QWidget *parent) : + QDialog(parent), + m_transactionCount(0), + m_serialPortLabel(new QLabel(tr("Serial port:"))), + m_serialPortComboBox(new QComboBox), + m_waitResponseLabel(new QLabel(tr("Wait response, msec:"))), + m_waitResponseSpinBox(new QSpinBox), + m_requestLabel(new QLabel(tr("Request:"))), + m_requestLineEdit(new QLineEdit(tr("Who are you?"))), + m_trafficLabel(new QLabel(tr("No traffic."))), + m_statusLabel(new QLabel(tr("Status: Not running."))), + m_runButton(new QPushButton(tr("Start"))) { const auto infos = QSerialPortInfo::availablePorts(); for (const QSerialPortInfo &info : infos) - serialPortComboBox->addItem(info.portName()); + m_serialPortComboBox->addItem(info.portName()); - waitResponseSpinBox->setRange(0, 10000); - waitResponseSpinBox->setValue(100); + m_waitResponseSpinBox->setRange(0, 10000); + m_waitResponseSpinBox->setValue(100); auto mainLayout = new QGridLayout; - mainLayout->addWidget(serialPortLabel, 0, 0); - mainLayout->addWidget(serialPortComboBox, 0, 1); - mainLayout->addWidget(waitResponseLabel, 1, 0); - mainLayout->addWidget(waitResponseSpinBox, 1, 1); - mainLayout->addWidget(runButton, 0, 2, 2, 1); - mainLayout->addWidget(requestLabel, 2, 0); - mainLayout->addWidget(requestLineEdit, 2, 1, 1, 3); - mainLayout->addWidget(trafficLabel, 3, 0, 1, 4); - mainLayout->addWidget(statusLabel, 4, 0, 1, 5); + mainLayout->addWidget(m_serialPortLabel, 0, 0); + mainLayout->addWidget(m_serialPortComboBox, 0, 1); + mainLayout->addWidget(m_waitResponseLabel, 1, 0); + mainLayout->addWidget(m_waitResponseSpinBox, 1, 1); + mainLayout->addWidget(m_runButton, 0, 2, 2, 1); + mainLayout->addWidget(m_requestLabel, 2, 0); + mainLayout->addWidget(m_requestLineEdit, 2, 1, 1, 3); + mainLayout->addWidget(m_trafficLabel, 3, 0, 1, 4); + mainLayout->addWidget(m_statusLabel, 4, 0, 1, 5); setLayout(mainLayout); setWindowTitle(tr("Master")); - serialPortComboBox->setFocus(); + m_serialPortComboBox->setFocus(); - timer.setSingleShot(true); + m_timer.setSingleShot(true); - connect(runButton, &QPushButton::clicked, this, &Dialog::sendRequest); - connect(&serial, &QSerialPort::readyRead, this, &Dialog::readResponse); - connect(&timer, &QTimer::timeout, this, &Dialog::processTimeout); + connect(m_runButton, &QPushButton::clicked, this, &Dialog::sendRequest); + connect(&m_serial, &QSerialPort::readyRead, this, &Dialog::readResponse); + connect(&m_timer, &QTimer::timeout, this, &Dialog::processTimeout); } void Dialog::sendRequest() { - if (serial.portName() != serialPortComboBox->currentText()) { - serial.close(); - serial.setPortName(serialPortComboBox->currentText()); + if (m_serial.portName() != m_serialPortComboBox->currentText()) { + m_serial.close(); + m_serial.setPortName(m_serialPortComboBox->currentText()); - if (!serial.open(QIODevice::ReadWrite)) { + if (!m_serial.open(QIODevice::ReadWrite)) { processError(tr("Can't open %1, error code %2") - .arg(serial.portName()).arg(serial.error())); + .arg(m_serial.portName()).arg(m_serial.error())); return; } } setControlsEnabled(false); - statusLabel->setText(tr("Status: Running, connected to port %1.") - .arg(serialPortComboBox->currentText())); + m_statusLabel->setText(tr("Status: Running, connected to port %1.") + .arg(m_serialPortComboBox->currentText())); - serial.write(requestLineEdit->text().toLocal8Bit()); - timer.start(waitResponseSpinBox->value()); + m_serial.write(m_requestLineEdit->text().toUtf8()); + m_timer.start(m_waitResponseSpinBox->value()); } void Dialog::readResponse() { - response.append(serial.readAll()); + m_response.append(m_serial.readAll()); } void Dialog::processTimeout() { setControlsEnabled(true); - trafficLabel->setText(tr("Traffic, transaction #%1:" - "\n\r-request: %2" - "\n\r-response: %3") - .arg(++transactionCount).arg(requestLineEdit->text()).arg(QString(response))); - response.clear(); + m_trafficLabel->setText(tr("Traffic, transaction #%1:" + "\n\r-request: %2" + "\n\r-response: %3") + .arg(++m_transactionCount) + .arg(m_requestLineEdit->text()) + .arg(QString::fromUtf8(m_response))); + m_response.clear(); } void Dialog::processError(const QString &error) { setControlsEnabled(true); - statusLabel->setText(tr("Status: Not running, %1.").arg(error)); - trafficLabel->setText(tr("No traffic.")); + m_statusLabel->setText(tr("Status: Not running, %1.").arg(error)); + m_trafficLabel->setText(tr("No traffic.")); } void Dialog::setControlsEnabled(bool enable) { - runButton->setEnabled(enable); - serialPortComboBox->setEnabled(enable); - waitResponseSpinBox->setEnabled(enable); - requestLineEdit->setEnabled(enable); + m_runButton->setEnabled(enable); + m_serialPortComboBox->setEnabled(enable); + m_waitResponseSpinBox->setEnabled(enable); + m_requestLineEdit->setEnabled(enable); } diff --git a/examples/serialport/master/dialog.h b/examples/serialport/master/dialog.h index 0bc1241..2fb2e8e 100644 --- a/examples/serialport/master/dialog.h +++ b/examples/serialport/master/dialog.h @@ -52,12 +52,9 @@ #define DIALOG_H #include <QDialog> +#include <QSerialPort> #include <QTimer> -#include <QtSerialPort/QSerialPort> - -QT_USE_NAMESPACE - QT_BEGIN_NAMESPACE class QLabel; @@ -85,20 +82,20 @@ private: void processError(const QString &error); private: - int transactionCount; - QLabel *serialPortLabel; - QComboBox *serialPortComboBox; - QLabel *waitResponseLabel; - QSpinBox *waitResponseSpinBox; - QLabel *requestLabel; - QLineEdit *requestLineEdit; - QLabel *trafficLabel; - QLabel *statusLabel; - QPushButton *runButton; + int m_transactionCount = 0; + QLabel *m_serialPortLabel = nullptr; + QComboBox *m_serialPortComboBox = nullptr; + QLabel *m_waitResponseLabel = nullptr; + QSpinBox *m_waitResponseSpinBox = nullptr; + QLabel *m_requestLabel = nullptr; + QLineEdit *m_requestLineEdit = nullptr; + QLabel *m_trafficLabel = nullptr; + QLabel *m_statusLabel = nullptr; + QPushButton *m_runButton = nullptr; - QSerialPort serial; - QByteArray response; - QTimer timer; + QSerialPort m_serial; + QByteArray m_response; + QTimer m_timer; }; #endif // DIALOG_H diff --git a/examples/serialport/master/main.cpp b/examples/serialport/master/main.cpp index cf4c421..8e68c73 100644 --- a/examples/serialport/master/main.cpp +++ b/examples/serialport/master/main.cpp @@ -48,10 +48,10 @@ ** ****************************************************************************/ -#include <QApplication> - #include "dialog.h" +#include <QApplication> + int main(int argc, char *argv[]) { QApplication app(argc, argv); diff --git a/examples/serialport/slave/dialog.cpp b/examples/serialport/slave/dialog.cpp index d801052..eec7999 100644 --- a/examples/serialport/slave/dialog.cpp +++ b/examples/serialport/slave/dialog.cpp @@ -50,109 +50,106 @@ #include "dialog.h" +#include <QComboBox> +#include <QGridLayout> #include <QLabel> #include <QLineEdit> -#include <QComboBox> -#include <QSpinBox> #include <QPushButton> -#include <QGridLayout> +#include <QSerialPortInfo> +#include <QSpinBox> -#include <QtSerialPort/QSerialPortInfo> - -QT_USE_NAMESPACE - -Dialog::Dialog(QWidget *parent) - : QDialog(parent) - , transactionCount(0) - , serialPortLabel(new QLabel(tr("Serial port:"))) - , serialPortComboBox(new QComboBox()) - , waitRequestLabel(new QLabel(tr("Wait request, msec:"))) - , waitRequestSpinBox(new QSpinBox()) - , responseLabel(new QLabel(tr("Response:"))) - , responseLineEdit(new QLineEdit(tr("Hello, I'm Slave."))) - , trafficLabel(new QLabel(tr("No traffic."))) - , statusLabel(new QLabel(tr("Status: Not running."))) - , runButton(new QPushButton(tr("Start"))) +Dialog::Dialog(QWidget *parent) : + QDialog(parent), + m_serialPortLabel(new QLabel(tr("Serial port:"))), + m_serialPortComboBox(new QComboBox), + m_waitRequestLabel(new QLabel(tr("Wait request, msec:"))), + m_waitRequestSpinBox(new QSpinBox), + m_responseLabel(new QLabel(tr("Response:"))), + m_responseLineEdit(new QLineEdit(tr("Hello, I'm Slave."))), + m_trafficLabel(new QLabel(tr("No traffic."))), + m_statusLabel(new QLabel(tr("Status: Not running."))), + m_runButton(new QPushButton(tr("Start"))) { - waitRequestSpinBox->setRange(0, 10000); - waitRequestSpinBox->setValue(20); + m_waitRequestSpinBox->setRange(0, 10000); + m_waitRequestSpinBox->setValue(20); const auto infos = QSerialPortInfo::availablePorts(); for (const QSerialPortInfo &info : infos) - serialPortComboBox->addItem(info.portName()); + m_serialPortComboBox->addItem(info.portName()); auto mainLayout = new QGridLayout; - mainLayout->addWidget(serialPortLabel, 0, 0); - mainLayout->addWidget(serialPortComboBox, 0, 1); - mainLayout->addWidget(waitRequestLabel, 1, 0); - mainLayout->addWidget(waitRequestSpinBox, 1, 1); - mainLayout->addWidget(runButton, 0, 2, 2, 1); - mainLayout->addWidget(responseLabel, 2, 0); - mainLayout->addWidget(responseLineEdit, 2, 1, 1, 3); - mainLayout->addWidget(trafficLabel, 3, 0, 1, 4); - mainLayout->addWidget(statusLabel, 4, 0, 1, 5); + mainLayout->addWidget(m_serialPortLabel, 0, 0); + mainLayout->addWidget(m_serialPortComboBox, 0, 1); + mainLayout->addWidget(m_waitRequestLabel, 1, 0); + mainLayout->addWidget(m_waitRequestSpinBox, 1, 1); + mainLayout->addWidget(m_runButton, 0, 2, 2, 1); + mainLayout->addWidget(m_responseLabel, 2, 0); + mainLayout->addWidget(m_responseLineEdit, 2, 1, 1, 3); + mainLayout->addWidget(m_trafficLabel, 3, 0, 1, 4); + mainLayout->addWidget(m_statusLabel, 4, 0, 1, 5); setLayout(mainLayout); setWindowTitle(tr("Slave")); - serialPortComboBox->setFocus(); + m_serialPortComboBox->setFocus(); - timer.setSingleShot(true); + m_timer.setSingleShot(true); - connect(runButton, &QPushButton::clicked, this, &Dialog::startSlave); - connect(&serial, &QSerialPort::readyRead, this, &Dialog::readRequest); - connect(&timer, &QTimer::timeout, this, &Dialog::processTimeout); + connect(m_runButton, &QPushButton::clicked, this, &Dialog::startSlave); + connect(&m_serial, &QSerialPort::readyRead, this, &Dialog::readRequest); + connect(&m_timer, &QTimer::timeout, this, &Dialog::processTimeout); - connect(serialPortComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), + connect(m_serialPortComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &Dialog::activateRunButton); - connect(waitRequestSpinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), + connect(m_waitRequestSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &Dialog::activateRunButton); - connect(responseLineEdit, &QLineEdit::textChanged, this, &Dialog::activateRunButton); + connect(m_responseLineEdit, &QLineEdit::textChanged, this, &Dialog::activateRunButton); } void Dialog::startSlave() { - if (serial.portName() != serialPortComboBox->currentText()) { - serial.close(); - serial.setPortName(serialPortComboBox->currentText()); + if (m_serial.portName() != m_serialPortComboBox->currentText()) { + m_serial.close(); + m_serial.setPortName(m_serialPortComboBox->currentText()); - if (!serial.open(QIODevice::ReadWrite)) { + if (!m_serial.open(QIODevice::ReadWrite)) { processError(tr("Can't open %1, error code %2") - .arg(serial.portName()).arg(serial.error())); + .arg(m_serial.portName()).arg(m_serial.error())); return; } } - runButton->setEnabled(false); - statusLabel->setText(tr("Status: Running, connected to port %1.") - .arg(serialPortComboBox->currentText())); + m_runButton->setEnabled(false); + m_statusLabel->setText(tr("Status: Running, connected to port %1.") + .arg(m_serialPortComboBox->currentText())); } void Dialog::readRequest() { - if (!timer.isActive()) - timer.start(waitRequestSpinBox->value()); - request.append(serial.readAll()); + if (!m_timer.isActive()) + m_timer.start(m_waitRequestSpinBox->value()); + m_request.append(m_serial.readAll()); } void Dialog::processTimeout() { - serial.write(responseLineEdit->text().toLocal8Bit()); - - trafficLabel->setText(tr("Traffic, transaction #%1:" - "\n\r-request: %2" - "\n\r-response: %3") - .arg(++transactionCount).arg(QString(request)).arg(responseLineEdit->text())); - request.clear(); + m_serial.write(m_responseLineEdit->text().toUtf8()); + + m_trafficLabel->setText(tr("Traffic, transaction #%1:" + "\n\r-request: %2" + "\n\r-response: %3") + .arg(++m_transactionCount).arg(QString::fromUtf8(m_request)) + .arg(m_responseLineEdit->text())); + m_request.clear(); } void Dialog::activateRunButton() { - runButton->setEnabled(true); + m_runButton->setEnabled(true); } void Dialog::processError(const QString &s) { activateRunButton(); - statusLabel->setText(tr("Status: Not running, %1.").arg(s)); - trafficLabel->setText(tr("No traffic.")); + m_statusLabel->setText(tr("Status: Not running, %1.").arg(s)); + m_trafficLabel->setText(tr("No traffic.")); } diff --git a/examples/serialport/slave/dialog.h b/examples/serialport/slave/dialog.h index 0405cf8..13909c7 100644 --- a/examples/serialport/slave/dialog.h +++ b/examples/serialport/slave/dialog.h @@ -52,12 +52,9 @@ #define DIALOG_H #include <QDialog> +#include <QSerialPort> #include <QTimer> -#include <QtSerialPort/QSerialPort> - -QT_USE_NAMESPACE - QT_BEGIN_NAMESPACE class QLabel; @@ -85,20 +82,20 @@ private: void processError(const QString &s); private: - int transactionCount; - QLabel *serialPortLabel; - QComboBox *serialPortComboBox; - QLabel *waitRequestLabel; - QSpinBox *waitRequestSpinBox; - QLabel *responseLabel; - QLineEdit *responseLineEdit; - QLabel *trafficLabel; - QLabel *statusLabel; - QPushButton *runButton; + int m_transactionCount = 0; + QLabel *m_serialPortLabel = nullptr; + QComboBox *m_serialPortComboBox = nullptr; + QLabel *m_waitRequestLabel = nullptr; + QSpinBox *m_waitRequestSpinBox = nullptr; + QLabel *m_responseLabel = nullptr; + QLineEdit *m_responseLineEdit = nullptr; + QLabel *m_trafficLabel = nullptr; + QLabel *m_statusLabel = nullptr; + QPushButton *m_runButton = nullptr; - QSerialPort serial; - QByteArray request; - QTimer timer; + QSerialPort m_serial; + QByteArray m_request; + QTimer m_timer; }; #endif // DIALOG_H diff --git a/examples/serialport/slave/main.cpp b/examples/serialport/slave/main.cpp index cf4c421..8e68c73 100644 --- a/examples/serialport/slave/main.cpp +++ b/examples/serialport/slave/main.cpp @@ -48,10 +48,10 @@ ** ****************************************************************************/ -#include <QApplication> - #include "dialog.h" +#include <QApplication> + int main(int argc, char *argv[]) { QApplication app(argc, argv); diff --git a/examples/serialport/terminal/console.cpp b/examples/serialport/terminal/console.cpp index 4f8d580..d71c5c0 100644 --- a/examples/serialport/terminal/console.cpp +++ b/examples/serialport/terminal/console.cpp @@ -53,23 +53,19 @@ #include <QScrollBar> -#include <QtCore/QDebug> - -Console::Console(QWidget *parent) - : QPlainTextEdit(parent) - , localEchoEnabled(false) +Console::Console(QWidget *parent) : + QPlainTextEdit(parent) { document()->setMaximumBlockCount(100); QPalette p = palette(); p.setColor(QPalette::Base, Qt::black); p.setColor(QPalette::Text, Qt::green); setPalette(p); - } void Console::putData(const QByteArray &data) { - insertPlainText(QString(data)); + insertPlainText(data); QScrollBar *bar = verticalScrollBar(); bar->setValue(bar->maximum()); @@ -77,7 +73,7 @@ void Console::putData(const QByteArray &data) void Console::setLocalEchoEnabled(bool set) { - localEchoEnabled = set; + m_localEchoEnabled = set; } void Console::keyPressEvent(QKeyEvent *e) @@ -90,7 +86,7 @@ void Console::keyPressEvent(QKeyEvent *e) case Qt::Key_Down: break; default: - if (localEchoEnabled) + if (m_localEchoEnabled) QPlainTextEdit::keyPressEvent(e); emit getData(e->text().toLocal8Bit()); } diff --git a/examples/serialport/terminal/console.h b/examples/serialport/terminal/console.h index 0674ded..b9fe553 100644 --- a/examples/serialport/terminal/console.h +++ b/examples/serialport/terminal/console.h @@ -65,18 +65,16 @@ public: explicit Console(QWidget *parent = nullptr); void putData(const QByteArray &data); - void setLocalEchoEnabled(bool set); protected: - void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE; - void mousePressEvent(QMouseEvent *e) Q_DECL_OVERRIDE; - void mouseDoubleClickEvent(QMouseEvent *e) Q_DECL_OVERRIDE; - void contextMenuEvent(QContextMenuEvent *e) Q_DECL_OVERRIDE; + void keyPressEvent(QKeyEvent *e) override; + void mousePressEvent(QMouseEvent *e) override; + void mouseDoubleClickEvent(QMouseEvent *e) override; + void contextMenuEvent(QContextMenuEvent *e) override; private: - bool localEchoEnabled; - + bool m_localEchoEnabled = false; }; #endif // CONSOLE_H diff --git a/examples/serialport/terminal/main.cpp b/examples/serialport/terminal/main.cpp index ec64e37..a6e901a 100644 --- a/examples/serialport/terminal/main.cpp +++ b/examples/serialport/terminal/main.cpp @@ -49,10 +49,10 @@ ** ****************************************************************************/ -#include <QApplication> - #include "mainwindow.h" +#include <QApplication> + int main(int argc, char *argv[]) { QApplication a(argc, argv); diff --git a/examples/serialport/terminal/mainwindow.cpp b/examples/serialport/terminal/mainwindow.cpp index f6e86cc..e8ac9d7 100644 --- a/examples/serialport/terminal/mainwindow.cpp +++ b/examples/serialport/terminal/mainwindow.cpp @@ -54,73 +54,71 @@ #include "console.h" #include "settingsdialog.h" -#include <QMessageBox> #include <QLabel> -#include <QtSerialPort/QSerialPort> +#include <QMessageBox> //! [0] MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), - ui(new Ui::MainWindow) -{ -//! [0] - ui->setupUi(this); - console = new Console; - console->setEnabled(false); - setCentralWidget(console); + m_ui(new Ui::MainWindow), + m_status(new QLabel), + m_console(new Console), + m_settings(new SettingsDialog), //! [1] - serial = new QSerialPort(this); + m_serial(new QSerialPort(this)) //! [1] - settings = new SettingsDialog; +{ +//! [0] + m_ui->setupUi(this); + m_console->setEnabled(false); + setCentralWidget(m_console); - ui->actionConnect->setEnabled(true); - ui->actionDisconnect->setEnabled(false); - ui->actionQuit->setEnabled(true); - ui->actionConfigure->setEnabled(true); + m_ui->actionConnect->setEnabled(true); + m_ui->actionDisconnect->setEnabled(false); + m_ui->actionQuit->setEnabled(true); + m_ui->actionConfigure->setEnabled(true); - status = new QLabel; - ui->statusBar->addWidget(status); + m_ui->statusBar->addWidget(m_status); initActionsConnections(); - connect(serial, static_cast<void (QSerialPort::*)(QSerialPort::SerialPortError)>(&QSerialPort::error), - this, &MainWindow::handleError); + connect(m_serial, &QSerialPort::errorOccurred, this, &MainWindow::handleError); //! [2] - connect(serial, &QSerialPort::readyRead, this, &MainWindow::readData); + connect(m_serial, &QSerialPort::readyRead, this, &MainWindow::readData); //! [2] - connect(console, &Console::getData, this, &MainWindow::writeData); + connect(m_console, &Console::getData, this, &MainWindow::writeData); //! [3] } //! [3] MainWindow::~MainWindow() { - delete settings; - delete ui; + delete m_settings; + delete m_ui; } //! [4] void MainWindow::openSerialPort() { - SettingsDialog::Settings p = settings->settings(); - serial->setPortName(p.name); - serial->setBaudRate(p.baudRate); - serial->setDataBits(p.dataBits); - serial->setParity(p.parity); - serial->setStopBits(p.stopBits); - serial->setFlowControl(p.flowControl); - if (serial->open(QIODevice::ReadWrite)) { - console->setEnabled(true); - console->setLocalEchoEnabled(p.localEchoEnabled); - ui->actionConnect->setEnabled(false); - ui->actionDisconnect->setEnabled(true); - ui->actionConfigure->setEnabled(false); + const SettingsDialog::Settings p = m_settings->settings(); + m_serial->setPortName(p.name); + m_serial->setBaudRate(p.baudRate); + m_serial->setDataBits(p.dataBits); + m_serial->setParity(p.parity); + m_serial->setStopBits(p.stopBits); + m_serial->setFlowControl(p.flowControl); + if (m_serial->open(QIODevice::ReadWrite)) { + m_console->setEnabled(true); + m_console->setLocalEchoEnabled(p.localEchoEnabled); + m_ui->actionConnect->setEnabled(false); + m_ui->actionDisconnect->setEnabled(true); + m_ui->actionConfigure->setEnabled(false); showStatusMessage(tr("Connected to %1 : %2, %3, %4, %5, %6") .arg(p.name).arg(p.stringBaudRate).arg(p.stringDataBits) .arg(p.stringParity).arg(p.stringStopBits).arg(p.stringFlowControl)); } else { - QMessageBox::critical(this, tr("Error"), serial->errorString()); + QMessageBox::critical(this, tr("Error"), m_serial->errorString()); showStatusMessage(tr("Open error")); } @@ -130,12 +128,12 @@ void MainWindow::openSerialPort() //! [5] void MainWindow::closeSerialPort() { - if (serial->isOpen()) - serial->close(); - console->setEnabled(false); - ui->actionConnect->setEnabled(true); - ui->actionDisconnect->setEnabled(false); - ui->actionConfigure->setEnabled(true); + if (m_serial->isOpen()) + m_serial->close(); + m_console->setEnabled(false); + m_ui->actionConnect->setEnabled(true); + m_ui->actionDisconnect->setEnabled(false); + m_ui->actionConfigure->setEnabled(true); showStatusMessage(tr("Disconnected")); } //! [5] @@ -151,15 +149,15 @@ void MainWindow::about() //! [6] void MainWindow::writeData(const QByteArray &data) { - serial->write(data); + m_serial->write(data); } //! [6] //! [7] void MainWindow::readData() { - QByteArray data = serial->readAll(); - console->putData(data); + const QByteArray data = m_serial->readAll(); + m_console->putData(data); } //! [7] @@ -167,7 +165,7 @@ void MainWindow::readData() void MainWindow::handleError(QSerialPort::SerialPortError error) { if (error == QSerialPort::ResourceError) { - QMessageBox::critical(this, tr("Critical Error"), serial->errorString()); + QMessageBox::critical(this, tr("Critical Error"), m_serial->errorString()); closeSerialPort(); } } @@ -175,16 +173,16 @@ void MainWindow::handleError(QSerialPort::SerialPortError error) void MainWindow::initActionsConnections() { - connect(ui->actionConnect, &QAction::triggered, this, &MainWindow::openSerialPort); - connect(ui->actionDisconnect, &QAction::triggered, this, &MainWindow::closeSerialPort); - connect(ui->actionQuit, &QAction::triggered, this, &MainWindow::close); - connect(ui->actionConfigure, &QAction::triggered, settings, &SettingsDialog::show); - connect(ui->actionClear, &QAction::triggered, console, &Console::clear); - connect(ui->actionAbout, &QAction::triggered, this, &MainWindow::about); - connect(ui->actionAboutQt, &QAction::triggered, qApp, &QApplication::aboutQt); + connect(m_ui->actionConnect, &QAction::triggered, this, &MainWindow::openSerialPort); + connect(m_ui->actionDisconnect, &QAction::triggered, this, &MainWindow::closeSerialPort); + connect(m_ui->actionQuit, &QAction::triggered, this, &MainWindow::close); + connect(m_ui->actionConfigure, &QAction::triggered, m_settings, &SettingsDialog::show); + connect(m_ui->actionClear, &QAction::triggered, m_console, &Console::clear); + connect(m_ui->actionAbout, &QAction::triggered, this, &MainWindow::about); + connect(m_ui->actionAboutQt, &QAction::triggered, qApp, &QApplication::aboutQt); } void MainWindow::showStatusMessage(const QString &message) { - status->setText(message); + m_status->setText(message); } diff --git a/examples/serialport/terminal/mainwindow.h b/examples/serialport/terminal/mainwindow.h index b792895..eebae8c 100644 --- a/examples/serialport/terminal/mainwindow.h +++ b/examples/serialport/terminal/mainwindow.h @@ -52,11 +52,8 @@ #ifndef MAINWINDOW_H #define MAINWINDOW_H -#include <QtCore/QtGlobal> - #include <QMainWindow> - -#include <QtSerialPort/QSerialPort> +#include <QSerialPort> QT_BEGIN_NAMESPACE @@ -94,11 +91,11 @@ private: private: void showStatusMessage(const QString &message); - Ui::MainWindow *ui; - QLabel *status; - Console *console; - SettingsDialog *settings; - QSerialPort *serial; + Ui::MainWindow *m_ui = nullptr; + QLabel *m_status = nullptr; + Console *m_console = nullptr; + SettingsDialog *m_settings = nullptr; + QSerialPort *m_serial = nullptr; }; #endif // MAINWINDOW_H diff --git a/examples/serialport/terminal/settingsdialog.cpp b/examples/serialport/terminal/settingsdialog.cpp index f9b8605..4b16bf5 100644 --- a/examples/serialport/terminal/settingsdialog.cpp +++ b/examples/serialport/terminal/settingsdialog.cpp @@ -52,31 +52,28 @@ #include "settingsdialog.h" #include "ui_settingsdialog.h" -#include <QtSerialPort/QSerialPortInfo> #include <QIntValidator> #include <QLineEdit> - -QT_USE_NAMESPACE +#include <QSerialPortInfo> static const char blankString[] = QT_TRANSLATE_NOOP("SettingsDialog", "N/A"); SettingsDialog::SettingsDialog(QWidget *parent) : QDialog(parent), - ui(new Ui::SettingsDialog) + m_ui(new Ui::SettingsDialog), + m_intValidator(new QIntValidator(0, 4000000, this)) { - ui->setupUi(this); - - intValidator = new QIntValidator(0, 4000000, this); + m_ui->setupUi(this); - ui->baudRateBox->setInsertPolicy(QComboBox::NoInsert); + m_ui->baudRateBox->setInsertPolicy(QComboBox::NoInsert); - connect(ui->applyButton, &QPushButton::clicked, + connect(m_ui->applyButton, &QPushButton::clicked, this, &SettingsDialog::apply); - connect(ui->serialPortInfoListBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), + connect(m_ui->serialPortInfoListBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &SettingsDialog::showPortInfo); - connect(ui->baudRateBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), + connect(m_ui->baudRateBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &SettingsDialog::checkCustomBaudRatePolicy); - connect(ui->serialPortInfoListBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), + connect(m_ui->serialPortInfoListBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &SettingsDialog::checkCustomDevicePathPolicy); fillPortsParameters(); @@ -87,12 +84,12 @@ SettingsDialog::SettingsDialog(QWidget *parent) : SettingsDialog::~SettingsDialog() { - delete ui; + delete m_ui; } SettingsDialog::Settings SettingsDialog::settings() const { - return currentSettings; + return m_currentSettings; } void SettingsDialog::showPortInfo(int idx) @@ -100,13 +97,13 @@ void SettingsDialog::showPortInfo(int idx) if (idx == -1) return; - QStringList list = ui->serialPortInfoListBox->itemData(idx).toStringList(); - ui->descriptionLabel->setText(tr("Description: %1").arg(list.count() > 1 ? list.at(1) : tr(blankString))); - ui->manufacturerLabel->setText(tr("Manufacturer: %1").arg(list.count() > 2 ? list.at(2) : tr(blankString))); - ui->serialNumberLabel->setText(tr("Serial number: %1").arg(list.count() > 3 ? list.at(3) : tr(blankString))); - ui->locationLabel->setText(tr("Location: %1").arg(list.count() > 4 ? list.at(4) : tr(blankString))); - ui->vidLabel->setText(tr("Vendor Identifier: %1").arg(list.count() > 5 ? list.at(5) : tr(blankString))); - ui->pidLabel->setText(tr("Product Identifier: %1").arg(list.count() > 6 ? list.at(6) : tr(blankString))); + const QStringList list = m_ui->serialPortInfoListBox->itemData(idx).toStringList(); + m_ui->descriptionLabel->setText(tr("Description: %1").arg(list.count() > 1 ? list.at(1) : tr(blankString))); + m_ui->manufacturerLabel->setText(tr("Manufacturer: %1").arg(list.count() > 2 ? list.at(2) : tr(blankString))); + m_ui->serialNumberLabel->setText(tr("Serial number: %1").arg(list.count() > 3 ? list.at(3) : tr(blankString))); + m_ui->locationLabel->setText(tr("Location: %1").arg(list.count() > 4 ? list.at(4) : tr(blankString))); + m_ui->vidLabel->setText(tr("Vendor Identifier: %1").arg(list.count() > 5 ? list.at(5) : tr(blankString))); + m_ui->pidLabel->setText(tr("Product Identifier: %1").arg(list.count() > 6 ? list.at(6) : tr(blankString))); } void SettingsDialog::apply() @@ -117,57 +114,57 @@ void SettingsDialog::apply() void SettingsDialog::checkCustomBaudRatePolicy(int idx) { - bool isCustomBaudRate = !ui->baudRateBox->itemData(idx).isValid(); - ui->baudRateBox->setEditable(isCustomBaudRate); + const bool isCustomBaudRate = !m_ui->baudRateBox->itemData(idx).isValid(); + m_ui->baudRateBox->setEditable(isCustomBaudRate); if (isCustomBaudRate) { - ui->baudRateBox->clearEditText(); - QLineEdit *edit = ui->baudRateBox->lineEdit(); - edit->setValidator(intValidator); + m_ui->baudRateBox->clearEditText(); + QLineEdit *edit = m_ui->baudRateBox->lineEdit(); + edit->setValidator(m_intValidator); } } void SettingsDialog::checkCustomDevicePathPolicy(int idx) { - bool isCustomPath = !ui->serialPortInfoListBox->itemData(idx).isValid(); - ui->serialPortInfoListBox->setEditable(isCustomPath); + const bool isCustomPath = !m_ui->serialPortInfoListBox->itemData(idx).isValid(); + m_ui->serialPortInfoListBox->setEditable(isCustomPath); if (isCustomPath) - ui->serialPortInfoListBox->clearEditText(); + m_ui->serialPortInfoListBox->clearEditText(); } void SettingsDialog::fillPortsParameters() { - ui->baudRateBox->addItem(QStringLiteral("9600"), QSerialPort::Baud9600); - ui->baudRateBox->addItem(QStringLiteral("19200"), QSerialPort::Baud19200); - ui->baudRateBox->addItem(QStringLiteral("38400"), QSerialPort::Baud38400); - ui->baudRateBox->addItem(QStringLiteral("115200"), QSerialPort::Baud115200); - ui->baudRateBox->addItem(tr("Custom")); - - ui->dataBitsBox->addItem(QStringLiteral("5"), QSerialPort::Data5); - ui->dataBitsBox->addItem(QStringLiteral("6"), QSerialPort::Data6); - ui->dataBitsBox->addItem(QStringLiteral("7"), QSerialPort::Data7); - ui->dataBitsBox->addItem(QStringLiteral("8"), QSerialPort::Data8); - ui->dataBitsBox->setCurrentIndex(3); - - ui->parityBox->addItem(tr("None"), QSerialPort::NoParity); - ui->parityBox->addItem(tr("Even"), QSerialPort::EvenParity); - ui->parityBox->addItem(tr("Odd"), QSerialPort::OddParity); - ui->parityBox->addItem(tr("Mark"), QSerialPort::MarkParity); - ui->parityBox->addItem(tr("Space"), QSerialPort::SpaceParity); - - ui->stopBitsBox->addItem(QStringLiteral("1"), QSerialPort::OneStop); + m_ui->baudRateBox->addItem(QStringLiteral("9600"), QSerialPort::Baud9600); + m_ui->baudRateBox->addItem(QStringLiteral("19200"), QSerialPort::Baud19200); + m_ui->baudRateBox->addItem(QStringLiteral("38400"), QSerialPort::Baud38400); + m_ui->baudRateBox->addItem(QStringLiteral("115200"), QSerialPort::Baud115200); + m_ui->baudRateBox->addItem(tr("Custom")); + + m_ui->dataBitsBox->addItem(QStringLiteral("5"), QSerialPort::Data5); + m_ui->dataBitsBox->addItem(QStringLiteral("6"), QSerialPort::Data6); + m_ui->dataBitsBox->addItem(QStringLiteral("7"), QSerialPort::Data7); + m_ui->dataBitsBox->addItem(QStringLiteral("8"), QSerialPort::Data8); + m_ui->dataBitsBox->setCurrentIndex(3); + + m_ui->parityBox->addItem(tr("None"), QSerialPort::NoParity); + m_ui->parityBox->addItem(tr("Even"), QSerialPort::EvenParity); + m_ui->parityBox->addItem(tr("Odd"), QSerialPort::OddParity); + m_ui->parityBox->addItem(tr("Mark"), QSerialPort::MarkParity); + m_ui->parityBox->addItem(tr("Space"), QSerialPort::SpaceParity); + + m_ui->stopBitsBox->addItem(QStringLiteral("1"), QSerialPort::OneStop); #ifdef Q_OS_WIN - ui->stopBitsBox->addItem(tr("1.5"), QSerialPort::OneAndHalfStop); + m_ui->stopBitsBox->addItem(tr("1.5"), QSerialPort::OneAndHalfStop); #endif - ui->stopBitsBox->addItem(QStringLiteral("2"), QSerialPort::TwoStop); + m_ui->stopBitsBox->addItem(QStringLiteral("2"), QSerialPort::TwoStop); - ui->flowControlBox->addItem(tr("None"), QSerialPort::NoFlowControl); - ui->flowControlBox->addItem(tr("RTS/CTS"), QSerialPort::HardwareControl); - ui->flowControlBox->addItem(tr("XON/XOFF"), QSerialPort::SoftwareControl); + m_ui->flowControlBox->addItem(tr("None"), QSerialPort::NoFlowControl); + m_ui->flowControlBox->addItem(tr("RTS/CTS"), QSerialPort::HardwareControl); + m_ui->flowControlBox->addItem(tr("XON/XOFF"), QSerialPort::SoftwareControl); } void SettingsDialog::fillPortsInfo() { - ui->serialPortInfoListBox->clear(); + m_ui->serialPortInfoListBox->clear(); QString description; QString manufacturer; QString serialNumber; @@ -185,39 +182,39 @@ void SettingsDialog::fillPortsInfo() << (info.vendorIdentifier() ? QString::number(info.vendorIdentifier(), 16) : blankString) << (info.productIdentifier() ? QString::number(info.productIdentifier(), 16) : blankString); - ui->serialPortInfoListBox->addItem(list.first(), list); + m_ui->serialPortInfoListBox->addItem(list.first(), list); } - ui->serialPortInfoListBox->addItem(tr("Custom")); + m_ui->serialPortInfoListBox->addItem(tr("Custom")); } void SettingsDialog::updateSettings() { - currentSettings.name = ui->serialPortInfoListBox->currentText(); + m_currentSettings.name = m_ui->serialPortInfoListBox->currentText(); - if (ui->baudRateBox->currentIndex() == 4) { - currentSettings.baudRate = ui->baudRateBox->currentText().toInt(); + if (m_ui->baudRateBox->currentIndex() == 4) { + m_currentSettings.baudRate = m_ui->baudRateBox->currentText().toInt(); } else { - currentSettings.baudRate = static_cast<QSerialPort::BaudRate>( - ui->baudRateBox->itemData(ui->baudRateBox->currentIndex()).toInt()); + m_currentSettings.baudRate = static_cast<QSerialPort::BaudRate>( + m_ui->baudRateBox->itemData(m_ui->baudRateBox->currentIndex()).toInt()); } - currentSettings.stringBaudRate = QString::number(currentSettings.baudRate); + m_currentSettings.stringBaudRate = QString::number(m_currentSettings.baudRate); - currentSettings.dataBits = static_cast<QSerialPort::DataBits>( - ui->dataBitsBox->itemData(ui->dataBitsBox->currentIndex()).toInt()); - currentSettings.stringDataBits = ui->dataBitsBox->currentText(); + m_currentSettings.dataBits = static_cast<QSerialPort::DataBits>( + m_ui->dataBitsBox->itemData(m_ui->dataBitsBox->currentIndex()).toInt()); + m_currentSettings.stringDataBits = m_ui->dataBitsBox->currentText(); - currentSettings.parity = static_cast<QSerialPort::Parity>( - ui->parityBox->itemData(ui->parityBox->currentIndex()).toInt()); - currentSettings.stringParity = ui->parityBox->currentText(); + m_currentSettings.parity = static_cast<QSerialPort::Parity>( + m_ui->parityBox->itemData(m_ui->parityBox->currentIndex()).toInt()); + m_currentSettings.stringParity = m_ui->parityBox->currentText(); - currentSettings.stopBits = static_cast<QSerialPort::StopBits>( - ui->stopBitsBox->itemData(ui->stopBitsBox->currentIndex()).toInt()); - currentSettings.stringStopBits = ui->stopBitsBox->currentText(); + m_currentSettings.stopBits = static_cast<QSerialPort::StopBits>( + m_ui->stopBitsBox->itemData(m_ui->stopBitsBox->currentIndex()).toInt()); + m_currentSettings.stringStopBits = m_ui->stopBitsBox->currentText(); - currentSettings.flowControl = static_cast<QSerialPort::FlowControl>( - ui->flowControlBox->itemData(ui->flowControlBox->currentIndex()).toInt()); - currentSettings.stringFlowControl = ui->flowControlBox->currentText(); + m_currentSettings.flowControl = static_cast<QSerialPort::FlowControl>( + m_ui->flowControlBox->itemData(m_ui->flowControlBox->currentIndex()).toInt()); + m_currentSettings.stringFlowControl = m_ui->flowControlBox->currentText(); - currentSettings.localEchoEnabled = ui->localEchoCheckBox->isChecked(); + m_currentSettings.localEchoEnabled = m_ui->localEchoCheckBox->isChecked(); } diff --git a/examples/serialport/terminal/settingsdialog.h b/examples/serialport/terminal/settingsdialog.h index ea249c1..4c0cda1 100644 --- a/examples/serialport/terminal/settingsdialog.h +++ b/examples/serialport/terminal/settingsdialog.h @@ -53,9 +53,7 @@ #define SETTINGSDIALOG_H #include <QDialog> -#include <QtSerialPort/QSerialPort> - -QT_USE_NAMESPACE +#include <QSerialPort> QT_BEGIN_NAMESPACE @@ -104,9 +102,9 @@ private: void updateSettings(); private: - Ui::SettingsDialog *ui; - Settings currentSettings; - QIntValidator *intValidator; + Ui::SettingsDialog *m_ui = nullptr; + Settings m_currentSettings; + QIntValidator *m_intValidator = nullptr; }; #endif // SETTINGSDIALOG_H diff --git a/src/serialport/doc/src/index.qdoc b/src/serialport/doc/src/index.qdoc index 3b0f762..041188e 100644 --- a/src/serialport/doc/src/index.qdoc +++ b/src/serialport/doc/src/index.qdoc @@ -43,11 +43,18 @@ \li Pinout signal change notification. \endlist - To use these classes in your application, use the following include + To use the serial port in your application, add the following include statement: \code - #include <QtSerialPort/QtSerialPort> + #include <QSerialPort> + \endcode + + For information about available serial ports, use the following include + statement: + + \code + #include <QSerialPortInfo> \endcode To link against the module, add this line to your \l qmake \c diff --git a/src/serialport/doc/src/qtserialport-module.qdoc b/src/serialport/doc/src/qtserialport-module.qdoc index 325b780..6c153a0 100644 --- a/src/serialport/doc/src/qtserialport-module.qdoc +++ b/src/serialport/doc/src/qtserialport-module.qdoc @@ -32,11 +32,17 @@ \qtvariable serialport \brief List of C++ classes that enable access to a serial port. - To use these classes in your application, use the following include + To use QSerialPort in your application, add the following include statement: \code - #include <QtSerialPort/QtSerialPort> + #include <QSerialPort> + \endcode + + For QSerialPortInfo, use the following include statement: + + \code + #include <QSerialPortInfo> \endcode To link against the module, add this line to your \l qmake \c diff --git a/src/serialport/qserialport.cpp b/src/serialport/qserialport.cpp index 8ea5a48..3b88736 100644 --- a/src/serialport/qserialport.cpp +++ b/src/serialport/qserialport.cpp @@ -87,42 +87,12 @@ QSerialPortErrorInfo::QSerialPortErrorInfo(QSerialPort::SerialPortError newError } QSerialPortPrivate::QSerialPortPrivate() - : readBufferMaxSize(0) - , error(QSerialPort::NoError) - , inputBaudRate(9600) - , outputBaudRate(9600) - , dataBits(QSerialPort::Data8) - , parity(QSerialPort::NoParity) - , stopBits(QSerialPort::OneStop) - , flowControl(QSerialPort::NoFlowControl) -#if QT_DEPRECATED_SINCE(5,3) - , settingsRestoredOnClose(true) -#endif - , isBreakEnabled(false) #if defined(Q_OS_WIN32) - , handle(INVALID_HANDLE_VALUE) - , readChunkBuffer(ReadChunkSize, 0) - , communicationStarted(false) - , writeStarted(false) - , readStarted(false) - , notifier(0) - , startAsyncWriteTimer(0) - , originalEventMask(0) - , triggeredEventMask(0) -#elif defined(Q_OS_UNIX) - , descriptor(-1) - , readNotifier(0) - , writeNotifier(0) - , readPortNotifierCalled(false) - , readPortNotifierState(false) - , readPortNotifierStateSet(false) - , emittedReadyRead(false) - , emittedBytesWritten(false) - , pendingBytesWritten(0) - , writeSequenceStarted(false) + : readChunkBuffer(QSERIALPORT_BUFFERSIZE, 0) #endif { - writeBufferChunkSize = InitialBufferSize; + writeBufferChunkSize = QSERIALPORT_BUFFERSIZE; + readBufferChunkSize = QSERIALPORT_BUFFERSIZE; } void QSerialPortPrivate::setError(const QSerialPortErrorInfo &errorInfo) @@ -1244,10 +1214,9 @@ qint64 QSerialPort::readBufferSize() const void QSerialPort::setReadBufferSize(qint64 size) { Q_D(QSerialPort); - - if (d->readBufferMaxSize == size) - return; d->readBufferMaxSize = size; + if (isReadable()) + d->startAsyncRead(); } /*! @@ -1436,21 +1405,9 @@ qint64 QSerialPort::readData(char *data, qint64 maxSize) Q_UNUSED(data); Q_UNUSED(maxSize); -#if defined(Q_OS_WIN32) - // We need try to start async reading to read a remainder from a driver's queue - // in case we have a limited read buffer size. Because the read notification can - // be stalled since Windows do not re-triggered an EV_RXCHAR event if a driver's - // buffer has a remainder of data ready to read until a new data will be received. - Q_D(QSerialPort); - if (d->readBufferMaxSize || d->flowControl == QSerialPort::HardwareControl) - d->startAsyncRead(); -#elif defined(Q_OS_UNIX) - // We need try to re-trigger the read notification to read a remainder from a - // driver's queue in case we have a limited read buffer size. - Q_D(QSerialPort); - if (d->readBufferMaxSize && !d->isReadNotificationEnabled()) - d->setReadNotificationEnabled(true); -#endif + // In any case we need to start the notifications if they were + // disabled by the read handler. If enabled, next call does nothing. + d_func()->startAsyncRead(); // return 0 indicating there may be more data in the future return qint64(0); diff --git a/src/serialport/qserialport_p.h b/src/serialport/qserialport_p.h index 10fda34..b0955ae 100644 --- a/src/serialport/qserialport_p.h +++ b/src/serialport/qserialport_p.h @@ -56,6 +56,7 @@ #include "qserialport.h" #include <private/qiodevice_p.h> +#include <qdeadlinetimer.h> #if defined(Q_OS_WIN32) # include <qt_windows.h> @@ -97,9 +98,12 @@ struct serial_struct { # error Unsupported OS #endif +#ifndef QSERIALPORT_BUFFERSIZE +#define QSERIALPORT_BUFFERSIZE 32768 +#endif + QT_BEGIN_NAMESPACE -class QThread; class QWinOverlappedIoNotifier; class QTimer; class QSocketNotifier; @@ -113,7 +117,7 @@ class QSerialPortErrorInfo public: explicit QSerialPortErrorInfo(QSerialPort::SerialPortError newErrorCode = QSerialPort::UnknownError, const QString &newErrorString = QString()); - QSerialPort::SerialPortError errorCode; + QSerialPort::SerialPortError errorCode = QSerialPort::UnknownError; QString errorString; }; @@ -121,11 +125,6 @@ class QSerialPortPrivate : public QIODevicePrivate { Q_DECLARE_PUBLIC(QSerialPort) public: - enum IoConstants { - ReadChunkSize = 512, - InitialBufferSize = 16384 - }; - QSerialPortPrivate(); bool open(QIODevice::OpenMode mode); @@ -158,33 +157,32 @@ public: qint64 writeData(const char *data, qint64 maxSize); + bool initialize(QIODevice::OpenMode mode); + static QString portNameToSystemLocation(const QString &port); static QString portNameFromSystemLocation(const QString &location); -#if defined(Q_OS_UNIX) - static qint32 settingFromBaudRate(qint32 baudRate); -#endif - static QList<qint32> standardBaudRates(); - qint64 readBufferMaxSize; - QSerialPort::SerialPortError error; + qint64 readBufferMaxSize = 0; + QSerialPort::SerialPortError error = QSerialPort::NoError; QString systemLocation; - qint32 inputBaudRate; - qint32 outputBaudRate; - QSerialPort::DataBits dataBits; - QSerialPort::Parity parity; - QSerialPort::StopBits stopBits; - QSerialPort::FlowControl flowControl; - bool settingsRestoredOnClose; - bool isBreakEnabled; + qint32 inputBaudRate = QSerialPort::Baud9600; + qint32 outputBaudRate = QSerialPort::Baud9600; + QSerialPort::DataBits dataBits = QSerialPort::Data8; + QSerialPort::Parity parity = QSerialPort::NoParity; + QSerialPort::StopBits stopBits = QSerialPort::OneStop; + QSerialPort::FlowControl flowControl = QSerialPort::NoFlowControl; + bool settingsRestoredOnClose = true; + bool isBreakEnabled = false; + + bool startAsyncRead(); #if defined(Q_OS_WIN32) - bool initialize(); bool setDcb(DCB *dcb); bool getDcb(DCB *dcb); - OVERLAPPED *waitForNotified(int msecs); + OVERLAPPED *waitForNotified(QDeadlineTimer deadline); qint64 queuedBytesCount(QSerialPort::Direction direction) const; @@ -193,7 +191,6 @@ public: bool completeAsyncWrite(qint64 bytesTransferred); bool startAsyncCommunication(); - bool startAsyncRead(); bool _q_startAsyncWrite(); void _q_notified(DWORD numberOfBytes, DWORD errorCode, OVERLAPPED *overlapped); @@ -202,23 +199,23 @@ public: DCB restoredDcb; COMMTIMEOUTS currentCommTimeouts; COMMTIMEOUTS restoredCommTimeouts; - HANDLE handle; + HANDLE handle = INVALID_HANDLE_VALUE; QByteArray readChunkBuffer; QByteArray writeChunkBuffer; - bool communicationStarted; - bool writeStarted; - bool readStarted; - QWinOverlappedIoNotifier *notifier; - QTimer *startAsyncWriteTimer; + bool communicationStarted = false; + bool writeStarted = false; + bool readStarted = false; + QWinOverlappedIoNotifier *notifier = nullptr; + QTimer *startAsyncWriteTimer = nullptr; OVERLAPPED communicationOverlapped; OVERLAPPED readCompletionOverlapped; OVERLAPPED writeCompletionOverlapped; - DWORD originalEventMask; - DWORD triggeredEventMask; + DWORD triggeredEventMask = 0; #elif defined(Q_OS_UNIX) - bool initialize(QIODevice::OpenMode mode); + static qint32 settingFromBaudRate(qint32 baudRate); + bool setTermios(const termios *tio); bool getTermios(termios *tio); @@ -246,20 +243,20 @@ public: bool completeAsyncWrite(); struct termios restoredTermios; - int descriptor; + int descriptor = -1; - QSocketNotifier *readNotifier; - QSocketNotifier *writeNotifier; + QSocketNotifier *readNotifier = nullptr; + QSocketNotifier *writeNotifier = nullptr; - bool readPortNotifierCalled; - bool readPortNotifierState; - bool readPortNotifierStateSet; + bool readPortNotifierCalled = false; + bool readPortNotifierState = false; + bool readPortNotifierStateSet = false; - bool emittedReadyRead; - bool emittedBytesWritten; + bool emittedReadyRead = false; + bool emittedBytesWritten = false; - qint64 pendingBytesWritten; - bool writeSequenceStarted; + qint64 pendingBytesWritten = 0; + bool writeSequenceStarted = false; QScopedPointer<QLockFile> lockFileScopedPointer; diff --git a/src/serialport/qserialport_unix.cpp b/src/serialport/qserialport_unix.cpp index 4df1fcb..05db317 100644 --- a/src/serialport/qserialport_unix.cpp +++ b/src/serialport/qserialport_unix.cpp @@ -42,10 +42,17 @@ #include "qserialport_p.h" #include "qserialportinfo_p.h" +#include <QtCore/qelapsedtimer.h> +#include <QtCore/qmap.h> +#include <QtCore/qsocketnotifier.h> +#include <QtCore/qstandardpaths.h> + +#include <private/qcore_unix_p.h> + #include <errno.h> -#include <sys/time.h> -#include <sys/ioctl.h> #include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/time.h> #include <unistd.h> #ifdef Q_OS_OSX @@ -93,16 +100,6 @@ struct termios2 { #endif -#include <private/qcore_unix_p.h> - -#include <QtCore/qelapsedtimer.h> -#include <QtCore/qsocketnotifier.h> -#include <QtCore/qmap.h> - -#ifdef Q_OS_OSX -#include <QtCore/qstandardpaths.h> -#endif - QT_BEGIN_NAMESPACE QString serialPortLockFilePath(const QString &portName) @@ -118,12 +115,8 @@ QString serialPortLockFilePath(const QString &portName) << QStringLiteral("/run/lock") #ifdef Q_OS_ANDROID << QStringLiteral("/data/local/tmp") -#elif defined(Q_OS_OSX) - // This is the workaround to specify a temporary directory - // on OSX when running the App Sandbox feature. - << QStandardPaths::writableLocation(QStandardPaths::TempLocation); #endif - ; + << QStandardPaths::writableLocation(QStandardPaths::TempLocation); QString fileName = portName; fileName.replace(QLatin1Char('/'), QLatin1Char('_')); @@ -156,7 +149,7 @@ QString serialPortLockFilePath(const QString &portName) class ReadNotifier : public QSocketNotifier { public: - ReadNotifier(QSerialPortPrivate *d, QObject *parent) + explicit ReadNotifier(QSerialPortPrivate *d, QObject *parent) : QSocketNotifier(d->descriptor, QSocketNotifier::Read, parent) , dptr(d) { @@ -173,13 +166,13 @@ protected: } private: - QSerialPortPrivate *dptr; + QSerialPortPrivate * const dptr; }; class WriteNotifier : public QSocketNotifier { public: - WriteNotifier(QSerialPortPrivate *d, QObject *parent) + explicit WriteNotifier(QSerialPortPrivate *d, QObject *parent) : QSocketNotifier(d->descriptor, QSocketNotifier::Write, parent) , dptr(d) { @@ -196,7 +189,7 @@ protected: } private: - QSerialPortPrivate *dptr; + QSerialPortPrivate * const dptr; }; static inline void qt_set_common_props(termios *tio, QIODevice::OpenMode m) @@ -763,13 +756,19 @@ bool QSerialPortPrivate::setFlowControl(QSerialPort::FlowControl flowControl) return setTermios(&tio); } +bool QSerialPortPrivate::startAsyncRead() +{ + setReadNotificationEnabled(true); + return true; +} + bool QSerialPortPrivate::readNotification() { Q_Q(QSerialPort); // Always buffered, read data from the port into the read buffer qint64 newBytes = buffer.size(); - qint64 bytesToRead = ReadChunkSize; + qint64 bytesToRead = QSERIALPORT_BUFFERSIZE; if (readBufferMaxSize && bytesToRead > (readBufferMaxSize - buffer.size())) { bytesToRead = readBufferMaxSize - buffer.size(); @@ -798,10 +797,6 @@ bool QSerialPortPrivate::readNotification() newBytes = buffer.size() - newBytes; - // If read buffer is full, disable the read port notifier. - if (readBufferMaxSize && buffer.size() == readBufferMaxSize) - setReadNotificationEnabled(false); - // only emit readyRead() when not recursing, and only if there is data available const bool hasData = newBytes > 0; diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp index 87f9e7b..f90a7ef 100644 --- a/src/serialport/qserialport_win.cpp +++ b/src/serialport/qserialport_win.cpp @@ -40,12 +40,12 @@ ****************************************************************************/ #include "qserialport_p.h" +#include "qwinoverlappedionotifier_p.h" #include <QtCore/qcoreevent.h> #include <QtCore/qelapsedtimer.h> #include <QtCore/qvector.h> #include <QtCore/qtimer.h> -#include <private/qwinoverlappedionotifier_p.h> #include <algorithm> #ifndef CTL_CODE @@ -176,12 +176,9 @@ static inline void qt_set_flowcontrol(DCB *dcb, QSerialPort::FlowControl flowcon bool QSerialPortPrivate::open(QIODevice::OpenMode mode) { DWORD desiredAccess = 0; - originalEventMask = 0; - if (mode & QIODevice::ReadOnly) { + if (mode & QIODevice::ReadOnly) desiredAccess |= GENERIC_READ; - originalEventMask |= EV_RXCHAR; - } if (mode & QIODevice::WriteOnly) desiredAccess |= GENERIC_WRITE; @@ -193,7 +190,7 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode) return false; } - if (initialize()) + if (initialize(mode)) return true; ::CloseHandle(handle); @@ -347,18 +344,16 @@ bool QSerialPortPrivate::waitForReadyRead(int msecs) const qint64 initialReadBufferSize = buffer.size(); qint64 currentReadBufferSize = initialReadBufferSize; - QElapsedTimer stopWatch; - stopWatch.start(); + QDeadlineTimer deadline(msecs); do { - const OVERLAPPED *overlapped = waitForNotified( - qt_subtract_from_timeout(msecs, stopWatch.elapsed())); + const OVERLAPPED *overlapped = waitForNotified(deadline); if (!overlapped) return false; if (overlapped == &readCompletionOverlapped) { const qint64 readBytesForOneReadOperation = qint64(buffer.size()) - currentReadBufferSize; - if (readBytesForOneReadOperation == ReadChunkSize) { + if (readBytesForOneReadOperation == QSERIALPORT_BUFFERSIZE) { currentReadBufferSize = buffer.size(); } else if (readBytesForOneReadOperation == 0) { if (initialReadBufferSize != currentReadBufferSize) @@ -368,7 +363,7 @@ bool QSerialPortPrivate::waitForReadyRead(int msecs) } } - } while (msecs == -1 || qt_subtract_from_timeout(msecs, stopWatch.elapsed()) > 0); + } while (!deadline.hasExpired()); return false; } @@ -381,12 +376,10 @@ bool QSerialPortPrivate::waitForBytesWritten(int msecs) if (!writeStarted && !_q_startAsyncWrite()) return false; - QElapsedTimer stopWatch; - stopWatch.start(); + QDeadlineTimer deadline(msecs); for (;;) { - const OVERLAPPED *overlapped = waitForNotified( - qt_subtract_from_timeout(msecs, stopWatch.elapsed())); + const OVERLAPPED *overlapped = waitForNotified(deadline); if (!overlapped) return false; @@ -484,11 +477,10 @@ bool QSerialPortPrivate::completeAsyncRead(qint64 bytesTransferred) readStarted = false; bool result = true; - if (bytesTransferred == ReadChunkSize + if (bytesTransferred == QSERIALPORT_BUFFERSIZE || queuedBytesCount(QSerialPort::Input) > 0) { result = startAsyncRead(); - } else if (readBufferMaxSize == 0 - || readBufferMaxSize > buffer.size()) { + } else { result = startAsyncCommunication(); } @@ -541,7 +533,7 @@ bool QSerialPortPrivate::startAsyncRead() if (readStarted) return true; - qint64 bytesToRead = ReadChunkSize; + qint64 bytesToRead = QSERIALPORT_BUFFERSIZE; if (readBufferMaxSize && bytesToRead > (readBufferMaxSize - buffer.size())) { bytesToRead = readBufferMaxSize - buffer.size(); @@ -552,6 +544,8 @@ bool QSerialPortPrivate::startAsyncRead() } } + Q_ASSERT(int(bytesToRead) <= readChunkBuffer.size()); + ::ZeroMemory(&readCompletionOverlapped, sizeof(readCompletionOverlapped)); if (::ReadFile(handle, readChunkBuffer.data(), bytesToRead, nullptr, &readCompletionOverlapped)) { readStarted = true; @@ -638,9 +632,9 @@ qint64 QSerialPortPrivate::writeData(const char *data, qint64 maxSize) return maxSize; } -OVERLAPPED *QSerialPortPrivate::waitForNotified(int msecs) +OVERLAPPED *QSerialPortPrivate::waitForNotified(QDeadlineTimer deadline) { - OVERLAPPED *overlapped = notifier->waitForAnyNotified(msecs); + OVERLAPPED *overlapped = notifier->waitForAnyNotified(deadline); if (!overlapped) { setError(getSystemError(WAIT_TIMEOUT)); return nullptr; @@ -658,7 +652,7 @@ qint64 QSerialPortPrivate::queuedBytesCount(QSerialPort::Direction direction) co : ((direction == QSerialPort::Output) ? comstat.cbOutQue : -1); } -inline bool QSerialPortPrivate::initialize() +inline bool QSerialPortPrivate::initialize(QIODevice::OpenMode mode) { Q_Q(QSerialPort); @@ -691,20 +685,21 @@ inline bool QSerialPortPrivate::initialize() return false; } - if (!::SetCommMask(handle, originalEventMask)) { + const DWORD eventMask = (mode & QIODevice::ReadOnly) ? EV_RXCHAR : 0; + if (!::SetCommMask(handle, eventMask)) { setError(getSystemError()); return false; } + if ((eventMask & EV_RXCHAR) && !startAsyncCommunication()) + return false; + notifier = new QWinOverlappedIoNotifier(q); QObjectPrivate::connect(notifier, &QWinOverlappedIoNotifier::notified, this, &QSerialPortPrivate::_q_notified); notifier->setHandle(handle); notifier->setEnabled(true); - if ((originalEventMask & EV_RXCHAR) && !startAsyncCommunication()) - return false; - return true; } @@ -785,80 +780,16 @@ QSerialPortErrorInfo QSerialPortPrivate::getSystemError(int systemErrorCode) con } // This table contains standard values of baud rates that -// are defined in MSDN and/or in Win SDK file winbase.h - -static const QList<qint32> standardBaudRatePairList() -{ - - static const QList<qint32> standardBaudRatesTable = QList<qint32>() - - #ifdef CBR_110 - << CBR_110 - #endif - - #ifdef CBR_300 - << CBR_300 - #endif - - #ifdef CBR_600 - << CBR_600 - #endif - - #ifdef CBR_1200 - << CBR_1200 - #endif - - #ifdef CBR_2400 - << CBR_2400 - #endif - - #ifdef CBR_4800 - << CBR_4800 - #endif - - #ifdef CBR_9600 - << CBR_9600 - #endif - - #ifdef CBR_14400 - << CBR_14400 - #endif - - #ifdef CBR_19200 - << CBR_19200 - #endif - - #ifdef CBR_38400 - << CBR_38400 - #endif - - #ifdef CBR_56000 - << CBR_56000 - #endif - - #ifdef CBR_57600 - << CBR_57600 - #endif - - #ifdef CBR_115200 - << CBR_115200 - #endif - - #ifdef CBR_128000 - << CBR_128000 - #endif - - #ifdef CBR_256000 - << CBR_256000 - #endif - ; - - return standardBaudRatesTable; -}; - +// are defined in file winbase.h QList<qint32> QSerialPortPrivate::standardBaudRates() { - return standardBaudRatePairList(); + static const QList<qint32> baudRates = { + CBR_110, CBR_300, CBR_600, CBR_1200, CBR_2400, + CBR_4800, CBR_9600, CBR_14400, CBR_19200, CBR_38400, + CBR_56000, CBR_57600, CBR_115200, CBR_128000, CBR_256000 + }; + + return baudRates; } QSerialPort::Handle QSerialPort::handle() const diff --git a/src/serialport/qserialportinfo_p.h b/src/serialport/qserialportinfo_p.h index 483ff8c..405cc41 100644 --- a/src/serialport/qserialportinfo_p.h +++ b/src/serialport/qserialportinfo_p.h @@ -60,18 +60,6 @@ QT_BEGIN_NAMESPACE class Q_AUTOTEST_EXPORT QSerialPortInfoPrivate { public: - QSerialPortInfoPrivate() - : vendorIdentifier(0) - , productIdentifier(0) - , hasVendorIdentifier(false) - , hasProductIdentifier(false) - { - } - - ~QSerialPortInfoPrivate() - { - } - static QString portNameToSystemLocation(const QString &source); static QString portNameFromSystemLocation(const QString &source); @@ -81,11 +69,11 @@ public: QString manufacturer; QString serialNumber; - quint16 vendorIdentifier; - quint16 productIdentifier; + quint16 vendorIdentifier = 0; + quint16 productIdentifier = 0; - bool hasVendorIdentifier; - bool hasProductIdentifier; + bool hasVendorIdentifier = false; + bool hasProductIdentifier = false; }; class QSerialPortInfoPrivateDeleter diff --git a/src/serialport/qwinoverlappedionotifier.cpp b/src/serialport/qwinoverlappedionotifier.cpp new file mode 100644 index 0000000..dfae3b0 --- /dev/null +++ b/src/serialport/qwinoverlappedionotifier.cpp @@ -0,0 +1,420 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwinoverlappedionotifier_p.h" +#include <qdebug.h> +#include <qatomic.h> +#include <qelapsedtimer.h> +#include <qmutex.h> +#include <qpointer.h> +#include <qqueue.h> +#include <qset.h> +#include <qthread.h> +#include <qt_windows.h> +#include <private/qobject_p.h> +#include <private/qiodevice_p.h> + +QT_BEGIN_NAMESPACE + +/*! + \class QWinOverlappedIoNotifier + \inmodule QtCore + \brief The QWinOverlappedIoNotifier class provides support for overlapped I/O notifications on Windows. + \since 5.0 + \internal + + The QWinOverlappedIoNotifier class makes it possible to use efficient + overlapped (asynchronous) I/O notifications on Windows by using an + I/O completion port. + + Once you have obtained a file handle, you can use setHandle() to get + notifications for I/O operations. Whenever an I/O operation completes, + the notified() signal is emitted which will pass the number of transferred + bytes, the operation's error code and a pointer to the operation's + OVERLAPPED object to the receiver. + + Every handle that supports overlapped I/O can be used by + QWinOverlappedIoNotifier. That includes file handles, TCP sockets + and named pipes. + + Note that you must not use ReadFileEx() and WriteFileEx() together + with QWinOverlappedIoNotifier. They are not supported as they use a + different I/O notification mechanism. + + The hEvent member in the OVERLAPPED structure passed to ReadFile() + or WriteFile() is ignored and can be used for other purposes. + + \warning This class is only available on Windows. + + Due to peculiarities of the Windows I/O completion port API, users of + QWinOverlappedIoNotifier must pay attention to the following restrictions: + \list + \li File handles with a QWinOverlappedIoNotifer are assigned to an I/O + completion port until the handle is closed. It is impossible to + disassociate the file handle from the I/O completion port. + \li There can be only one QWinOverlappedIoNotifer per file handle. Creating + another QWinOverlappedIoNotifier for that file, even with a duplicated + handle, will fail. + \li Certain Windows API functions are unavailable for file handles that are + assigned to an I/O completion port. This includes the functions + \c{ReadFileEx} and \c{WriteFileEx}. + \endlist + See also the remarks in the MSDN documentation for the + \c{CreateIoCompletionPort} function. +*/ + +struct IOResult +{ + IOResult(DWORD n = 0, DWORD e = 0, OVERLAPPED *p = nullptr) + : numberOfBytes(n), errorCode(e), overlapped(p) + {} + + DWORD numberOfBytes = 0; + DWORD errorCode = 0; + OVERLAPPED *overlapped = nullptr; +}; + + +class QWinIoCompletionPort; + +class QWinOverlappedIoNotifierPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QWinOverlappedIoNotifier) +public: + OVERLAPPED *waitForAnyNotified(QDeadlineTimer deadline); + void notify(DWORD numberOfBytes, DWORD errorCode, OVERLAPPED *overlapped); + void _q_notified(); + OVERLAPPED *dispatchNextIoResult(); + + static QWinIoCompletionPort *iocp; + static HANDLE iocpInstanceLock; + static unsigned int iocpInstanceRefCount; + HANDLE hHandle = INVALID_HANDLE_VALUE; + HANDLE hSemaphore = nullptr; + HANDLE hResultsMutex = nullptr; + QAtomicInt waiting; + QQueue<IOResult> results; +}; + +QWinIoCompletionPort *QWinOverlappedIoNotifierPrivate::iocp = 0; +HANDLE QWinOverlappedIoNotifierPrivate::iocpInstanceLock = CreateMutex(NULL, FALSE, NULL); +unsigned int QWinOverlappedIoNotifierPrivate::iocpInstanceRefCount = 0; + + +class QWinIoCompletionPort : protected QThread +{ +public: + QWinIoCompletionPort() + : finishThreadKey(reinterpret_cast<ULONG_PTR>(this)), + drainQueueKey(reinterpret_cast<ULONG_PTR>(this + 1)) + { + setObjectName(QLatin1String("I/O completion port thread")); + HANDLE hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); + if (!hIOCP) { + qErrnoWarning("CreateIoCompletionPort failed."); + return; + } + hPort = hIOCP; + hQueueDrainedEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (!hQueueDrainedEvent) { + qErrnoWarning("CreateEvent failed."); + return; + } + } + + ~QWinIoCompletionPort() + { + PostQueuedCompletionStatus(hPort, 0, finishThreadKey, NULL); + QThread::wait(); + CloseHandle(hPort); + CloseHandle(hQueueDrainedEvent); + } + + void registerNotifier(QWinOverlappedIoNotifierPrivate *notifier) + { + const HANDLE hHandle = notifier->hHandle; + HANDLE hIOCP = CreateIoCompletionPort(hHandle, hPort, + reinterpret_cast<ULONG_PTR>(notifier), 0); + if (!hIOCP) { + qErrnoWarning("Can't associate file handle %x with I/O completion port.", hHandle); + return; + } + mutex.lock(); + notifiers += notifier; + mutex.unlock(); + if (!QThread::isRunning()) + QThread::start(); + } + + void unregisterNotifier(QWinOverlappedIoNotifierPrivate *notifier) + { + mutex.lock(); + notifiers.remove(notifier); + mutex.unlock(); + } + + void drainQueue() + { + QMutexLocker locker(&drainQueueMutex); + ResetEvent(hQueueDrainedEvent); + PostQueuedCompletionStatus(hPort, 0, drainQueueKey, NULL); + WaitForSingleObject(hQueueDrainedEvent, INFINITE); + } + + using QThread::isRunning; + +protected: + void run() + { + DWORD dwBytesRead = 0; + ULONG_PTR pulCompletionKey = 0; + OVERLAPPED *overlapped = nullptr; + DWORD msecs = INFINITE; + + forever { + BOOL success = GetQueuedCompletionStatus(hPort, + &dwBytesRead, + &pulCompletionKey, + &overlapped, + msecs); + + DWORD errorCode = success ? ERROR_SUCCESS : GetLastError(); + if (!success && !overlapped) { + if (!msecs) { + // Time out in drain mode. The completion status queue is empty. + msecs = INFINITE; + SetEvent(hQueueDrainedEvent); + continue; + } + qErrnoWarning(errorCode, "GetQueuedCompletionStatus failed."); + return; + } + + if (pulCompletionKey == finishThreadKey) + return; + if (pulCompletionKey == drainQueueKey) { + // Enter drain mode. + Q_ASSERT(msecs == INFINITE); + msecs = 0; + continue; + } + + QWinOverlappedIoNotifierPrivate *notifier + = reinterpret_cast<QWinOverlappedIoNotifierPrivate *>(pulCompletionKey); + mutex.lock(); + if (notifiers.contains(notifier)) + notifier->notify(dwBytesRead, errorCode, overlapped); + mutex.unlock(); + } + } + +private: + const ULONG_PTR finishThreadKey; + const ULONG_PTR drainQueueKey; + HANDLE hPort = INVALID_HANDLE_VALUE; + QSet<QWinOverlappedIoNotifierPrivate *> notifiers; + QMutex mutex; + QMutex drainQueueMutex; + HANDLE hQueueDrainedEvent = nullptr; +}; + + +QWinOverlappedIoNotifier::QWinOverlappedIoNotifier(QObject *parent) + : QObject(*new QWinOverlappedIoNotifierPrivate, parent) +{ + Q_D(QWinOverlappedIoNotifier); + WaitForSingleObject(d->iocpInstanceLock, INFINITE); + if (!d->iocp) + d->iocp = new QWinIoCompletionPort; + d->iocpInstanceRefCount++; + ReleaseMutex(d->iocpInstanceLock); + + d->hSemaphore = CreateSemaphore(NULL, 0, 255, NULL); + d->hResultsMutex = CreateMutex(NULL, FALSE, NULL); + connect(this, SIGNAL(_q_notify()), this, SLOT(_q_notified()), Qt::QueuedConnection); +} + +QWinOverlappedIoNotifier::~QWinOverlappedIoNotifier() +{ + Q_D(QWinOverlappedIoNotifier); + setEnabled(false); + CloseHandle(d->hResultsMutex); + CloseHandle(d->hSemaphore); + + WaitForSingleObject(d->iocpInstanceLock, INFINITE); + if (!--d->iocpInstanceRefCount) { + delete d->iocp; + d->iocp = 0; + } + ReleaseMutex(d->iocpInstanceLock); +} + +void QWinOverlappedIoNotifier::setHandle(Qt::HANDLE h) +{ + Q_D(QWinOverlappedIoNotifier); + d->hHandle = h; +} + +Qt::HANDLE QWinOverlappedIoNotifier::handle() const +{ + Q_D(const QWinOverlappedIoNotifier); + return d->hHandle; +} + +void QWinOverlappedIoNotifier::setEnabled(bool enabled) +{ + Q_D(QWinOverlappedIoNotifier); + if (enabled) + d->iocp->registerNotifier(d); + else + d->iocp->unregisterNotifier(d); +} + +OVERLAPPED *QWinOverlappedIoNotifierPrivate::waitForAnyNotified(QDeadlineTimer deadline) +{ + if (!iocp->isRunning()) { + qWarning("Called QWinOverlappedIoNotifier::waitForAnyNotified on inactive notifier."); + return 0; + } + + DWORD msecs = deadline.remainingTime(); + if (msecs == 0) + iocp->drainQueue(); + if (msecs == -1) + msecs = INFINITE; + + const DWORD wfso = WaitForSingleObject(hSemaphore, msecs); + switch (wfso) { + case WAIT_OBJECT_0: + return dispatchNextIoResult(); + case WAIT_TIMEOUT: + return 0; + default: + qErrnoWarning("QWinOverlappedIoNotifier::waitForAnyNotified: WaitForSingleObject failed."); + return 0; + } +} + +class QScopedAtomicIntIncrementor +{ +public: + QScopedAtomicIntIncrementor(QAtomicInt &i) + : m_int(i) + { + ++m_int; + } + + ~QScopedAtomicIntIncrementor() + { + --m_int; + } + +private: + QAtomicInt &m_int; +}; + +/*! + * Wait synchronously for any notified signal. + * + * The function returns a pointer to the OVERLAPPED object corresponding to the completed I/O + * operation. In case no I/O operation was completed during the \a msec timeout, this function + * returns a null pointer. + */ +OVERLAPPED *QWinOverlappedIoNotifier::waitForAnyNotified(QDeadlineTimer deadline) +{ + Q_D(QWinOverlappedIoNotifier); + QScopedAtomicIntIncrementor saii(d->waiting); + OVERLAPPED *result = d->waitForAnyNotified(deadline); + return result; +} + +/*! + * Wait synchronously for the notified signal. + * + * The function returns true if the notified signal was emitted for + * the I/O operation that corresponds to the OVERLAPPED object. + */ +bool QWinOverlappedIoNotifier::waitForNotified(QDeadlineTimer deadline, OVERLAPPED *overlapped) +{ + Q_D(QWinOverlappedIoNotifier); + QScopedAtomicIntIncrementor saii(d->waiting); + while (!deadline.hasExpired()) { + OVERLAPPED *triggeredOverlapped = waitForAnyNotified(deadline); + if (!triggeredOverlapped) + return false; + if (triggeredOverlapped == overlapped) + return true; + } + return false; +} + +/*! + * Note: This function runs in the I/O completion port thread. + */ +void QWinOverlappedIoNotifierPrivate::notify(DWORD numberOfBytes, DWORD errorCode, + OVERLAPPED *overlapped) +{ + Q_Q(QWinOverlappedIoNotifier); + WaitForSingleObject(hResultsMutex, INFINITE); + results.enqueue(IOResult(numberOfBytes, errorCode, overlapped)); + ReleaseMutex(hResultsMutex); + ReleaseSemaphore(hSemaphore, 1, NULL); + if (!waiting) + emit q->_q_notify(); +} + +void QWinOverlappedIoNotifierPrivate::_q_notified() +{ + if (WaitForSingleObject(hSemaphore, 0) == WAIT_OBJECT_0) + dispatchNextIoResult(); +} + +OVERLAPPED *QWinOverlappedIoNotifierPrivate::dispatchNextIoResult() +{ + Q_Q(QWinOverlappedIoNotifier); + WaitForSingleObject(hResultsMutex, INFINITE); + IOResult ioresult = results.dequeue(); + ReleaseMutex(hResultsMutex); + emit q->notified(ioresult.numberOfBytes, ioresult.errorCode, ioresult.overlapped); + return ioresult.overlapped; +} + +QT_END_NAMESPACE + +#include "moc_qwinoverlappedionotifier_p.cpp" diff --git a/src/serialport/qwinoverlappedionotifier_p.h b/src/serialport/qwinoverlappedionotifier_p.h new file mode 100644 index 0000000..9ee998b --- /dev/null +++ b/src/serialport/qwinoverlappedionotifier_p.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINOVERLAPPEDIONOTIFIER_P_H +#define QWINOVERLAPPEDIONOTIFIER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/private/qglobal_p.h> +#include <qobject.h> +#include <qdeadlinetimer.h> + +typedef struct _OVERLAPPED OVERLAPPED; + +QT_BEGIN_NAMESPACE + +class QWinOverlappedIoNotifierPrivate; + +class QWinOverlappedIoNotifier : public QObject +{ + Q_OBJECT + Q_DISABLE_COPY(QWinOverlappedIoNotifier) + Q_DECLARE_PRIVATE(QWinOverlappedIoNotifier) + Q_PRIVATE_SLOT(d_func(), void _q_notified()) + friend class QWinIoCompletionPort; +public: + QWinOverlappedIoNotifier(QObject *parent = 0); + ~QWinOverlappedIoNotifier(); + + void setHandle(Qt::HANDLE h); + Qt::HANDLE handle() const; + + void setEnabled(bool enabled); + OVERLAPPED *waitForAnyNotified(QDeadlineTimer deadline); + bool waitForNotified(QDeadlineTimer deadline, OVERLAPPED *overlapped); + +Q_SIGNALS: + void notified(quint32 numberOfBytes, quint32 errorCode, OVERLAPPED *overlapped); +#if !defined(Q_QDOC) + void _q_notify(); +#endif +}; + +QT_END_NAMESPACE + +#endif // QWINOVERLAPPEDIONOTIFIER_P_H diff --git a/src/serialport/serialport-lib.pri b/src/serialport/serialport-lib.pri index 9f83989..bb12df2 100644 --- a/src/serialport/serialport-lib.pri +++ b/src/serialport/serialport-lib.pri @@ -22,7 +22,11 @@ SOURCES += \ win32:!wince* { SOURCES += \ $$PWD/qserialport_win.cpp \ - $$PWD/qserialportinfo_win.cpp + $$PWD/qserialportinfo_win.cpp \ + $$PWD/qwinoverlappedionotifier.cpp + + PRIVATE_HEADERS += \ + $$PWD/qwinoverlappedionotifier_p.h LIBS_PRIVATE += -lsetupapi -ladvapi32 } |