diff options
author | Kai Koehne <kai.koehne@digia.com> | 2013-04-30 14:46:08 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-05-03 17:01:47 +0200 |
commit | 494c616951d41f2f394a7157f8970e14096f41b4 (patch) | |
tree | 9e42e9970b4b28809d97c0de94acc9fa7a81c54e /examples/serialport | |
parent | bcdeb589dd9d3b0ff7270d380d043b1882eefdc0 (diff) | |
download | qtserialport-494c616951d41f2f394a7157f8970e14096f41b4.tar.gz |
Fix examples directory layout
Move examples into a dedicated 'serialport' directory. This is
in line with what the other modules do, and makes sure that
the examples show up in a sensible place even for the 'combined'
source packages.
Task-number: QTBUG-30912
Change-Id: Iefa2b634df3d2eb34f655b34f6fb24a224b78869
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
Reviewed-by: Laszlo Papp <lpapp@kde.org>
Reviewed-by: Jerome Pasion <jerome.pasion@digia.com>
Diffstat (limited to 'examples/serialport')
49 files changed, 3978 insertions, 0 deletions
diff --git a/examples/serialport/blockingmaster/blockingmaster.pro b/examples/serialport/blockingmaster/blockingmaster.pro new file mode 100644 index 0000000..5f21cdb --- /dev/null +++ b/examples/serialport/blockingmaster/blockingmaster.pro @@ -0,0 +1,17 @@ +greaterThan(QT_MAJOR_VERSION, 4) { + QT += widgets serialport +} else { + include($$QTSERIALPORT_PROJECT_ROOT/src/serialport/qt4support/serialport.prf) +} + +TARGET = blockingmaster +TEMPLATE = app + +HEADERS += \ + dialog.h \ + masterthread.h + +SOURCES += \ + main.cpp \ + dialog.cpp \ + masterthread.cpp diff --git a/examples/serialport/blockingmaster/dialog.cpp b/examples/serialport/blockingmaster/dialog.cpp new file mode 100644 index 0000000..7cd04e0 --- /dev/null +++ b/examples/serialport/blockingmaster/dialog.cpp @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSerialPort 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "dialog.h" + +#include <QLabel> +#include <QLineEdit> +#include <QComboBox> +#include <QSpinBox> +#include <QPushButton> +#include <QGridLayout> + +#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"))) +{ + foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) + serialPortComboBox->addItem(info.portName()); + + waitResponseSpinBox->setRange(0, 10000); + waitResponseSpinBox->setValue(1000); + + QGridLayout *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); + setLayout(mainLayout); + + setWindowTitle(tr("Blocking Master")); + serialPortComboBox->setFocus(); + + connect(runButton, SIGNAL(clicked()), + this, SLOT(transaction())); + connect(&thread, SIGNAL(response(QString)), + this, SLOT(showResponse(QString))); + connect(&thread, SIGNAL(error(QString)), + this, SLOT(processError(QString))); + connect(&thread, SIGNAL(timeout(QString)), + this, SLOT(processTimeout(QString))); +} + +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()); +} + +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)); +} + +void Dialog::processError(const QString &s) +{ + setControlsEnabled(true); + statusLabel->setText(tr("Status: Not running, %1.").arg(s)); + 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.")); +} + +void Dialog::setControlsEnabled(bool enable) +{ + runButton->setEnabled(enable); + serialPortComboBox->setEnabled(enable); + waitResponseSpinBox->setEnabled(enable); + requestLineEdit->setEnabled(enable); +} diff --git a/examples/serialport/blockingmaster/dialog.h b/examples/serialport/blockingmaster/dialog.h new file mode 100644 index 0000000..14d1e56 --- /dev/null +++ b/examples/serialport/blockingmaster/dialog.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSerialPort 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DIALOG_H +#define DIALOG_H + +#include <QDialog> + +#include "masterthread.h" + +QT_BEGIN_NAMESPACE + +class QLabel; +class QLineEdit; +class QSpinBox; +class QPushButton; +class QComboBox; + +QT_END_NAMESPACE + +class Dialog : public QDialog +{ + Q_OBJECT + +public: + Dialog(QWidget *parent = 0); + +private slots: + void transaction(); + void showResponse(const QString &s); + void processError(const QString &s); + void processTimeout(const QString &s); + +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; + + MasterThread thread; +}; + +#endif // DIALOG_H diff --git a/examples/serialport/blockingmaster/main.cpp b/examples/serialport/blockingmaster/main.cpp new file mode 100644 index 0000000..fc2e334 --- /dev/null +++ b/examples/serialport/blockingmaster/main.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSerialPort 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QApplication> + +#include "dialog.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + Dialog dialog; + dialog.show(); + return app.exec(); +} diff --git a/examples/serialport/blockingmaster/masterthread.cpp b/examples/serialport/blockingmaster/masterthread.cpp new file mode 100644 index 0000000..061ddd6 --- /dev/null +++ b/examples/serialport/blockingmaster/masterthread.cpp @@ -0,0 +1,182 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSerialPort 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "masterthread.h" + +#include <QtSerialPort/QSerialPort> + +#include <QTime> + +QT_USE_NAMESPACE + +MasterThread::MasterThread(QObject *parent) + : QThread(parent), waitTimeout(0), quit(false) +{ +} + +//! [0] +MasterThread::~MasterThread() +{ + mutex.lock(); + quit = true; + cond.wakeOne(); + mutex.unlock(); + wait(); +} +//! [0] + +//! [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] + if (!isRunning()) + start(); + else + cond.wakeOne(); +} +//! [2] //! [3] + +//! [4] +void MasterThread::run() +{ + bool currentPortNameChanged = false; + + mutex.lock(); + //! [4] //! [5] + QString currentPortName; + if (currentPortName != portName) { + currentPortName = portName; + currentPortNameChanged = true; + } + + int currentWaitTimeout = waitTimeout; + QString currentRequest = request; + mutex.unlock(); + //! [5] //! [6] + QSerialPort serial; + + while (!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())); + return; + } + + if (!serial.setBaudRate(QSerialPort::Baud9600)) { + emit error(tr("Can't set baud rate 9600 baud to port %1, error code %2") + .arg(portName).arg(serial.error())); + return; + } + + if (!serial.setDataBits(QSerialPort::Data8)) { + emit error(tr("Can't set 8 data bits to port %1, error code %2") + .arg(portName).arg(serial.error())); + return; + } + + if (!serial.setParity(QSerialPort::NoParity)) { + emit error(tr("Can't set no patity to port %1, error code %2") + .arg(portName).arg(serial.error())); + return; + } + + if (!serial.setStopBits(QSerialPort::OneStop)) { + emit error(tr("Can't set 1 stop bit to port %1, error code %2") + .arg(portName).arg(serial.error())); + return; + } + + if (!serial.setFlowControl(QSerialPort::NoFlowControl)) { + emit error(tr("Can't set no flow control to port %1, error code %2") + .arg(portName).arg(serial.error())); + return; + } + } + //! [7] //! [8] + // write request + QByteArray requestData = currentRequest.toLocal8Bit(); + serial.write(requestData); + if (serial.waitForBytesWritten(waitTimeout)) { + //! [8] //! [10] + // read response + if (serial.waitForReadyRead(currentWaitTimeout)) { + QByteArray responseData = serial.readAll(); + while (serial.waitForReadyRead(10)) + responseData += serial.readAll(); + + QString response(responseData); + //! [12] + emit this->response(response); + //! [10] //! [11] //! [12] + } else { + emit timeout(tr("Wait read response timeout %1") + .arg(QTime::currentTime().toString())); + } + //! [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; + currentPortNameChanged = true; + } else { + currentPortNameChanged = false; + } + currentWaitTimeout = waitTimeout; + currentRequest = request; + mutex.unlock(); + } + //! [13] +} diff --git a/examples/serialport/blockingmaster/masterthread.h b/examples/serialport/blockingmaster/masterthread.h new file mode 100644 index 0000000..ebbd43d --- /dev/null +++ b/examples/serialport/blockingmaster/masterthread.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSerialPort 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MASTERTHREAD_H +#define MASTERTHREAD_H + +#include <QThread> +#include <QMutex> +#include <QWaitCondition> + +//! [0] +class MasterThread : public QThread +{ + Q_OBJECT + +public: + MasterThread(QObject *parent = 0); + ~MasterThread(); + + void transaction(const QString &portName, int waitTimeout, const QString &request); + void run(); + +signals: + void response(const QString &s); + void error(const QString &s); + void timeout(const QString &s); + +private: + QString portName; + QString request; + int waitTimeout; + QMutex mutex; + QWaitCondition cond; + bool quit; +}; +//! [0] + +#endif // MASTERTHREAD_H diff --git a/examples/serialport/blockingslave/blockingslave.pro b/examples/serialport/blockingslave/blockingslave.pro new file mode 100644 index 0000000..5a5fb78 --- /dev/null +++ b/examples/serialport/blockingslave/blockingslave.pro @@ -0,0 +1,17 @@ +greaterThan(QT_MAJOR_VERSION, 4) { + QT += widgets serialport +} else { + include($$QTSERIALPORT_PROJECT_ROOT/src/serialport/qt4support/serialport.prf) +} + +TARGET = blockingslave +TEMPLATE = app + +HEADERS += \ + dialog.h \ + slavethread.h + +SOURCES += \ + main.cpp \ + dialog.cpp \ + slavethread.cpp diff --git a/examples/serialport/blockingslave/dialog.cpp b/examples/serialport/blockingslave/dialog.cpp new file mode 100644 index 0000000..9bdbbf6 --- /dev/null +++ b/examples/serialport/blockingslave/dialog.cpp @@ -0,0 +1,139 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSerialPort 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "dialog.h" + +#include <QLabel> +#include <QLineEdit> +#include <QComboBox> +#include <QSpinBox> +#include <QPushButton> +#include <QGridLayout> + +#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"))) +{ + waitRequestSpinBox->setRange(0, 10000); + waitRequestSpinBox->setValue(10000); + + foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) + serialPortComboBox->addItem(info.portName()); + + QGridLayout *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); + setLayout(mainLayout); + + setWindowTitle(tr("Blocking Slave")); + serialPortComboBox->setFocus(); + + connect(runButton, SIGNAL(clicked()), + this, SLOT(startSlave())); + connect(&thread, SIGNAL(request(QString)), + this, SLOT(showRequest(QString))); + connect(&thread, SIGNAL(error(QString)), + this, SLOT(processError(QString))); + connect(&thread, SIGNAL(timeout(QString)), + this, SLOT(processTimeout(QString))); + + connect(serialPortComboBox, SIGNAL(currentIndexChanged(QString)), + this, SLOT(activateRunButton())); + connect(waitRequestSpinBox, SIGNAL(valueChanged(int)), + this, SLOT(activateRunButton())); + connect(responseLineEdit, SIGNAL(textChanged(QString)), + this, SLOT(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()); +} + +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())); +} + +void Dialog::processError(const QString &s) +{ + activateRunButton(); + statusLabel->setText(tr("Status: Not running, %1.").arg(s)); + trafficLabel->setText(tr("No traffic.")); +} + +void Dialog::processTimeout(const QString &s) +{ + statusLabel->setText(tr("Status: Running, %1.").arg(s)); + trafficLabel->setText(tr("No traffic.")); +} +void Dialog::activateRunButton() +{ + runButton->setEnabled(true); +} diff --git a/examples/serialport/blockingslave/dialog.h b/examples/serialport/blockingslave/dialog.h new file mode 100644 index 0000000..27056b2 --- /dev/null +++ b/examples/serialport/blockingslave/dialog.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSerialPort 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DIALOG_H +#define DIALOG_H + +#include <QDialog> + +#include "slavethread.h" + +QT_BEGIN_NAMESPACE + +class QLabel; +class QLineEdit; +class QComboBox; +class QSpinBox; +class QPushButton; + +QT_END_NAMESPACE + +class Dialog : public QDialog +{ + Q_OBJECT + +public: + Dialog(QWidget *parent = 0); + +private slots: + void startSlave(); + void showRequest(const QString &s); + void processError(const QString &s); + void processTimeout(const QString &s); + void activateRunButton(); + +private: + int transactionCount; + QLabel *serialPortLabel; + QComboBox *serialPortComboBox; + QLabel *waitRequestLabel; + QSpinBox *waitRequestSpinBox; + QLabel *responseLabel; + QLineEdit *responseLineEdit; + QLabel *trafficLabel; + QLabel *statusLabel; + QPushButton *runButton; + + SlaveThread thread; +}; + +#endif // DIALOG_H diff --git a/examples/serialport/blockingslave/main.cpp b/examples/serialport/blockingslave/main.cpp new file mode 100644 index 0000000..fc2e334 --- /dev/null +++ b/examples/serialport/blockingslave/main.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSerialPort 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QApplication> + +#include "dialog.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + Dialog dialog; + dialog.show(); + return app.exec(); +} diff --git a/examples/serialport/blockingslave/slavethread.cpp b/examples/serialport/blockingslave/slavethread.cpp new file mode 100644 index 0000000..a31db25 --- /dev/null +++ b/examples/serialport/blockingslave/slavethread.cpp @@ -0,0 +1,177 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSerialPort 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "slavethread.h" + +#include <QtSerialPort/QSerialPort> + +#include <QTime> + +QT_USE_NAMESPACE + +SlaveThread::SlaveThread(QObject *parent) + : QThread(parent), waitTimeout(0), quit(false) +{ +} +//! [0] +SlaveThread::~SlaveThread() +{ + mutex.lock(); + quit = true; + mutex.unlock(); + wait(); +} +//! [0] + +//! [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] + if (!isRunning()) + start(); +} +//! [2] //! [3] + +//! [4] +void SlaveThread::run() +{ + bool currentPortNameChanged = false; + + mutex.lock(); +//! [4] //! [5] + QString currentPortName; + if (currentPortName != portName) { + currentPortName = portName; + currentPortNameChanged = true; + } + + int currentWaitTimeout = waitTimeout; + QString currentRespone = response; + mutex.unlock(); +//! [5] //! [6] + QSerialPort serial; + + while (!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())); + return; + } + + if (!serial.setBaudRate(QSerialPort::Baud9600)) { + emit error(tr("Can't set baud rate 9600 baud to port %1, error code %2") + .arg(portName).arg(serial.error())); + return; + } + + if (!serial.setDataBits(QSerialPort::Data8)) { + emit error(tr("Can't set 8 data bits to port %1, error code %2") + .arg(portName).arg(serial.error())); + return; + } + + if (!serial.setParity(QSerialPort::NoParity)) { + emit error(tr("Can't set no patity to port %1, error code %2") + .arg(portName).arg(serial.error())); + return; + } + + if (!serial.setStopBits(QSerialPort::OneStop)) { + emit error(tr("Can't set 1 stop bit to port %1, error code %2") + .arg(portName).arg(serial.error())); + return; + } + + if (!serial.setFlowControl(QSerialPort::NoFlowControl)) { + emit error(tr("Can't set no flow control to port %1, error code %2") + .arg(portName).arg(serial.error())); + return; + } + } + + if (serial.waitForReadyRead(currentWaitTimeout)) { +//! [7] //! [8] + // read request + QByteArray requestData = serial.readAll(); + while (serial.waitForReadyRead(10)) + requestData += serial.readAll(); +//! [8] //! [10] + // write response + QByteArray responseData = currentRespone.toLocal8Bit(); + serial.write(responseData); + if (serial.waitForBytesWritten(waitTimeout)) { + QString request(requestData); +//! [12] + emit this->request(request); +//! [10] //! [11] //! [12] + } else { + emit timeout(tr("Wait write response timeout %1") + .arg(QTime::currentTime().toString())); + } +//! [9] //! [11] + } else { + emit timeout(tr("Wait read request timeout %1") + .arg(QTime::currentTime().toString())); + } +//! [9] //! [13] + mutex.lock(); + if (currentPortName != portName) { + currentPortName = portName; + currentPortNameChanged = true; + } else { + currentPortNameChanged = false; + } + currentWaitTimeout = waitTimeout; + currentRespone = response; + mutex.unlock(); + } +//! [13] +} diff --git a/examples/serialport/blockingslave/slavethread.h b/examples/serialport/blockingslave/slavethread.h new file mode 100644 index 0000000..9ba78b0 --- /dev/null +++ b/examples/serialport/blockingslave/slavethread.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSerialPort 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SLAVETHREAD_H +#define SLAVETHREAD_H + +#include <QThread> +#include <QMutex> +#include <QWaitCondition> + +//! [0] +class SlaveThread : public QThread +{ + Q_OBJECT + +public: + SlaveThread(QObject *parent = 0); + ~SlaveThread(); + + void startSlave(const QString &portName, int waitTimeout, const QString &response); + void run(); + +signals: + void request(const QString &s); + void error(const QString &s); + void timeout(const QString &s); + +private: + QString portName; + QString response; + int waitTimeout; + QMutex mutex; + bool quit; +}; +//! [0] + +#endif // SLAVETHREAD_H diff --git a/examples/serialport/cenumerator/cenumerator.pro b/examples/serialport/cenumerator/cenumerator.pro new file mode 100644 index 0000000..464e1d9 --- /dev/null +++ b/examples/serialport/cenumerator/cenumerator.pro @@ -0,0 +1,14 @@ +greaterThan(QT_MAJOR_VERSION, 4) { + QT += serialport +} else { + include($$QTSERIALPORT_PROJECT_ROOT/src/serialport/qt4support/serialport.prf) +} + +CONFIG += console +CONFIG -= app_bundle + +TARGET = cenumerator +TEMPLATE = app + +SOURCES += \ + main.cpp diff --git a/examples/serialport/cenumerator/main.cpp b/examples/serialport/cenumerator/main.cpp new file mode 100644 index 0000000..f55b92d --- /dev/null +++ b/examples/serialport/cenumerator/main.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSerialPort 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QTextStream> +#include <QCoreApplication> +#include <QtSerialPort/QSerialPortInfo> + +QT_USE_NAMESPACE + +int main(int argc, char *argv[]) +{ + QCoreApplication a(argc, argv); + QTextStream out(stdout); + QList<QSerialPortInfo> serialPortInfoList = QSerialPortInfo::availablePorts(); + + out << QObject::tr("Total number of ports available: ") << serialPortInfoList.count() << endl; + + foreach (const QSerialPortInfo &serialPortInfo, serialPortInfoList) { + out << endl + << QObject::tr("Port: ") << serialPortInfo.portName() << endl + << QObject::tr("Location: ") << serialPortInfo.systemLocation() << endl + << QObject::tr("Description: ") << serialPortInfo.description() << endl + << QObject::tr("Manufacturer: ") << serialPortInfo.manufacturer() << endl + << QObject::tr("Vendor Identifier: ") << (serialPortInfo.hasVendorIdentifier() ? QByteArray::number(serialPortInfo.vendorIdentifier(), 16) : QByteArray()) << endl + << QObject::tr("Product Identifier: ") << (serialPortInfo.hasProductIdentifier() ? QByteArray::number(serialPortInfo.productIdentifier(), 16) : QByteArray()) << endl + << QObject::tr("Busy: ") << (serialPortInfo.isBusy() ? QObject::tr("Yes") : QObject::tr("No")) << endl; + } + + return 0; +} diff --git a/examples/serialport/doc/blockingmaster.qdoc b/examples/serialport/doc/blockingmaster.qdoc new file mode 100644 index 0000000..40ac070 --- /dev/null +++ b/examples/serialport/doc/blockingmaster.qdoc @@ -0,0 +1,162 @@ +/**************************************************************************** +** +** Copyright (C) 2011 - 2012 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example blockingmaster + \title Blocking Master Example + \ingroup qtserialport-examples + + The Blocking Master example shows how to create a application for a + serial interface using QSerialPort's synchronous API in a non-GUI thread. + + \image blockingmaster-example.png Screenshot of the Blocking Master example + + QSerialPort supports two general programming approaches: + + \list + + \li \e{The asynchronous (non-blocking) approach.} Operations are scheduled + and performed when the control returns to Qt's event loop. QSerialPort emits + a signal when the operation is finished. For example, QSerialPort::write() + returns immediately. When the data is sent to the serial port, QSerialPort + emits \l{QSerialPort::bytesWritten()}{bytesWritten()}. + + \li \e{The synchronous (blocking) approach.} In non-GUI and multithreaded + applications, the \c waitFor...() functions can be called (i.e. + QSerialPort::waitReadyRead()) to suspend the calling thread until the + operation has completed. + + \endlist + + In this example, the synchronous approach is demonstrated. The + \l{terminal}{Simple Terminal} example illustrates the + asynchronous approach. + + The purpose of this example is to demonstrate a pattern that you can use + to simplify your serial programming code, without losing responsiveness + in your user interface. Use of Qt's blocking serial programming API often + leads to simpler code, but because of its blocking behavior, it should only + be used in non-GUI threads to prevent the user interface from freezing. + But contrary to what many think, using threads with QThread does not + necessarily add unmanagable complexity to your application. + + This application is a Master, that demonstrate the work paired with Slave + application \l{blockingslave}{Blocking Slave Example}. + + The Master application is initiate the transfer request via serial port to + the Slave application and wait for a response from it. + + We will start with the MasterThread class, which handles the serial + programming code. + + \snippet blockingmaster/masterthread.h 0 + + MasterThread is a QThread subclass that provides an API for scheduling + requests to Slave, and it has signals for delivering responses and reporting + errors. You can call transaction() to startup new master transaction with + desired request data and other parameters, and the result is delivered by + the response() signal. If any error occurs, the error() or timeout() signals + is emitted. + + It's important to notice that transaction() is called from the main, GUI + thread, but the request data and other parameters will be accessed from + MasterThread's thread. Because we will be reading and writing MasterThread's + data members from different threads concurrently, we use QMutex to + synchronize access. + + \snippet blockingmaster/masterthread.cpp 2 + + The transaction() function stores the serial port name, timeout and request + data, and we lock the mutex with QMutexLocker to protect this data. We then + start the thread, unless it is already running. We will come back to the + QWaitCondition::wakeOne() call later. + + \snippet blockingmaster/masterthread.cpp 4 + \snippet blockingmaster/masterthread.cpp 5 + + In the run() function, we start by acquiring the mutex lock, fetching the + serial port name, timeout and request data from the member data, and then + releasing the lock again. The case that we are protecting ourselves against + is that \c transaction() could be called at the same time as we are fetching + this data. QString is \l reentrant but \e not \l{thread-safe}, and we must + also avoid the unlikely risk of reading the serial port name from one request, + and timeout or request data of another. And as you might have guessed, + MasterThread can only handle one request at a time. + + The QSerialPort object we construct on stack into run() function before loop + enter: + + \snippet blockingmaster/masterthread.cpp 6 + + This allows us once to create an object, while running loop, and also means + that all the methods of the object will be executed in the context of the + run() thread. + + In the loop, we check for changed or not the name of serial port for the + current transaction. And if the name is changed then re-open and re-configure + the serial port. + + \snippet blockingmaster/masterthread.cpp 7 + + The loop will continue creating request data, write to serial port and wait + until all data is transferred. + + \snippet blockingmaster/masterthread.cpp 8 + + \warning The method waitForBytesWritten() should be used after each write() + call for the blocking approach, because it processes all the I/O routines + instead of Qt event-loop. + + The timeout() signal is emitted if error occurs when transferring data. + + \snippet blockingmaster/masterthread.cpp 9 + + After a successful request, we start wait until response and try read it. + + \snippet blockingmaster/masterthread.cpp 10 + + \warning The method waitForReadyRead() should be used before each read() + call for the blocking approach, because it processes all the I/O routines + instead of Qt event-loop. + + The timeout() signal is emitted if error occurs when receiving data. + + \snippet blockingmaster/masterthread.cpp 11 + + After a successful transaction is emitted response() signal containing the + data received from the Slave application: + + \snippet blockingmaster/masterthread.cpp 12 + + Next, the thread goes to sleep until the next transaction is appear. On + waking, the thread re-reads the new data of members and run loop from the + beginning. + + \snippet blockingmaster/masterthread.cpp 13 + + \sa {Simple Terminal Example}, {Blocking Slave Example} +*/ diff --git a/examples/serialport/doc/blockingslave.qdoc b/examples/serialport/doc/blockingslave.qdoc new file mode 100644 index 0000000..4b835d9 --- /dev/null +++ b/examples/serialport/doc/blockingslave.qdoc @@ -0,0 +1,164 @@ +/**************************************************************************** +** +** Copyright (C) 2011 - 2012 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example blockingslave + \title Blocking Slave Example + \ingroup qtserialport-examples + + The Blocking Slave example shows how to create a application for a + serial interface using QSerialPort's synchronous API in a non-GUI thread. + + \image blockingslave-example.png Screenshot of the Blocking Slave example + + QSerialPort supports two general programming approaches: + + \list + + \li \e{The asynchronous (non-blocking) approach.} Operations are scheduled + and performed when the control returns to Qt's event loop. QSerialPort emits + a signal when the operation is finished. For example, QSerialPort::write() + returns immediately. When the data is sent to the serial port, QSerialPort + emits \l{QSerialPort::bytesWritten()}{bytesWritten()}. + + \li \e{The synchronous (blocking) approach.} In non-GUI and multithreaded + applications, the \c waitFor...() functions can be called (i.e. + QSerialPort::waitReadyRead()) to suspend the calling thread until the + operation has completed. + + \endlist + + In this example, the synchronous approach is demonstrated. The + \l{slave}{Slave Example} example illustrates the asynchronous approach. + + The purpose of this example is to demonstrate a pattern that you can use + to simplify your serial programming code, without losing responsiveness + in your user interface. Use of Qt's blocking serial programming API often + leads to simpler code, but because of its blocking behavior, it should only + be used in non-GUI threads to prevent the user interface from freezing. + But contrary to what many think, using threads with QThread does not + necessarily add unmanagable complexity to your application. + + This application is a Slave, that demonstrate the work paired with Master + application \l{blockingmaster}{Blocking Master Example}. + + The Slave application is receives the request via serial port from + the Master application and send a response to it. + + We will start with the SlaveThread class, which handles the serial + programming code. + + \snippet blockingslave/slavethread.h 0 + + SlaveThread is a QThread subclass that provides an API for receive requests + from Master, and it has signals for delivering responses and reporting + errors. + + You should be call startSlave() to startup Slave application. This method + transfers to the SlaveThread desired parameters for configure and startup + the serial interface. When SlaveThread received from Master any request then + emitted the request() signal. If any error occurs, the error() or timeout() + signals is emitted. + + It's important to notice that startSlave() is called from the main, GUI + thread, but the response data and other parameters will be accessed from + SlaveThread's thread. Because we will be reading and writing SlaveThread's + data members from different threads concurrently, we use QMutex to + synchronize access. + + \snippet blockingslave/slavethread.cpp 2 + + The startSlave() function stores the serial port name, timeout and response + data, and we lock the mutex with QMutexLocker to protect this data. We then + start the thread, unless it is already running. We will come back to the + QWaitCondition::wakeOne() call later. + + \snippet blockingslave/slavethread.cpp 4 + \snippet blockingslave/slavethread.cpp 5 + + In the run() function, we start by acquiring the mutex lock, fetching the + serial port name, timeout and response data from the member data, and then + releasing the lock again. The case that we are protecting ourselves against + is that \c startSlave() could be called at the same time as we are fetching + this data. QString is \l reentrant but \e not \l{thread-safe}, and we must + also avoid the unlikely risk of reading the serial port name from one startup, + call and timeout or response data of another. And as you might have guessed, + SlaveThread can only handle one startup at a time. + + The QSerialPort object we construct on stack into run() function before loop + enter: + + \snippet blockingslave/slavethread.cpp 6 + + This allows us once to create an object, while running loop, and also means + that all the methods of the object will be executed in the context of the + run() thread. + + In the loop, we check for changed or not the name of serial port for the + current startup. And if the name is changed then re-open and re-configure + the serial port. + + \snippet blockingslave/slavethread.cpp 7 + + The loop will continue wait for reading request data: + + \snippet blockingslave/slavethread.cpp 8 + + \warning The method waitForReadyRead() should be used before each read() + call for the blocking approach, because it processes all the I/O routines + instead of Qt event-loop. + + The timeout() signal is emitted if error occurs when reading data. + + \snippet blockingslave/slavethread.cpp 9 + + After a successful read, we try send response and wait completion of the + transfer: + + \snippet blockingslave/slavethread.cpp 10 + + \warning The method waitForBytesWritten() should be used after each write() + call for the blocking approach, because it processes all the I/O routines + instead of Qt event-loop. + + The timeout() signal is emitted if error occurs when writing data. + + \snippet blockingslave/slavethread.cpp 11 + + After a successful writing is emitted request() signal containing the + data received from the Master application: + + \snippet blockingslave/slavethread.cpp 12 + + Next, the thread goes to re-reads the current parameters for serial interface, + because they can be updated when new startSlave() and run loop from the + beginning. + + \snippet blockingslave/slavethread.cpp 13 + + \sa {Simple Terminal Example}, {Blocking Master Example} +*/ diff --git a/examples/serialport/doc/cenumerator.qdoc b/examples/serialport/doc/cenumerator.qdoc new file mode 100644 index 0000000..0766931 --- /dev/null +++ b/examples/serialport/doc/cenumerator.qdoc @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example cenumerator + \title Command Line Enumerator Example + \ingroup qtserialport-examples + + The Command Line Enumerator example shows how to use the class + QSerialPortInfo for getting information about serial devices that are present + in the system. + + \image cenumerator-example.png Screenshot of the Command Line Enumerator + example + + This command line example displays information about serial ports in a + console, provided by the class QSerialPortInfo. + + For getting information about the available ports, use the static method + \l{QSerialPortInfo::availablePorts()}{availablePorts()}. +*/ diff --git a/examples/serialport/doc/enumerator.qdoc b/examples/serialport/doc/enumerator.qdoc new file mode 100644 index 0000000..0847d8a --- /dev/null +++ b/examples/serialport/doc/enumerator.qdoc @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2011 - 2012 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example enumerator + \title Enumerator Example + \ingroup qtserialport-examples + + The Enumerator example shows how to use the class QSerialPortInfo for + getting information about serial devices that are present in the system. + + \image enumerator-example.png Screenshot of the Enumerator example + + This GUI example displays information about serial ports in a widget, + provided by the class QSerialPortInfo. + + For getting information about the available ports, use the static method + \l{QSerialPortInfo::availablePorts()}{availablePorts()}. +*/ diff --git a/examples/serialport/doc/terminal.qdoc b/examples/serialport/doc/terminal.qdoc new file mode 100644 index 0000000..b432390 --- /dev/null +++ b/examples/serialport/doc/terminal.qdoc @@ -0,0 +1,144 @@ +/**************************************************************************** +** +** Copyright (C) 2011 - 2012 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example terminal + \title Terminal Example + \ingroup qtserialport-examples + + The Terminal example shows how to create a terminal for a simple serial + interface by using Qt Serial Port. + + \image terminal-example.png Screenshot of the Terminal example + + This example shows the main features of the QSerialPort class, like + configuration, I/O implementation and so forth. Also, the class + QSerialPortInfo is invoked to display information about the serial ports + available in the system. + + QSerialPort supports two general programming approaches: + + \list + + \li \e{The asynchronous (non-blocking) approach.} Operations are scheduled + and performed when the control returns to Qt's event loop. QSerialPort emits + a signal when the operation is finished. For example, QSerialPort::write() + returns immediately. When the data is sent to the serial port, QSerialPort + emits \l{QSerialPort::bytesWritten()}{bytesWritten()}. + + \li \e{The synchronous (blocking) approach.} In non-GUI and multithreaded + applications, the \c waitFor...() functions can be called (i.e. + QSerialPort::waitReadyRead()) to suspend the calling thread until the + operation has completed. + + \endlist + + In this example, the asynchronous approach is demonstrated. + + Our example contains some GUI widgets: + + \list + + \li \l{terminal/mainwindow.cpp}{MainWindow} - is the main application + window that contains all the working logic for the serial port programming, + including configuration, I/O processing and so forth, while inheriting the + QMainWindow. + + \li \l{terminal/console.cpp}{Console} - is the central widget of the + main window, displaying the transmitted or received data. The widget is + derived from the QPlainTextEdit class. + + \li \l{terminal/settingsdialog.cpp}{SettingsDialog} - is a dialog + for configuring the serial port, as well as for displaying the available + serial ports and information about them. + + \endlist + + The serial port is instantiated in the \l{terminal/mainwindow.cpp}{MainWindow} + constructor. The main widget is passed as the parent, so the object deletion + happens automatically according to the the parent and child mechanism in Qt: + + \snippet terminal/mainwindow.cpp 0 + \dots + \snippet terminal/mainwindow.cpp 1 + + The only QSerialPort signal invoked in this example is + QSerialPort::readyRead(), which shows that new data has been received and + hence available: + + \dots + \snippet terminal/mainwindow.cpp 2 + \dots + \snippet terminal/mainwindow.cpp 3 + + Clicking on the \b{Connect} button invokes the \c openSerialPort() slot: + + \snippet terminal/mainwindow.cpp 4 + + In this slot, the settings are read from \l{terminal/settingsdialog.cpp} + {SettingsDialog} and an attempt is made to open and initialize the serial + port accordingly. If successful, the status bar displays a message that the + opening was successful with the given configuration; otherwise, a messagebox + is displayed with the appropriate error code and message. If the serial port + settings have never been called + \l{terminal/settingsdialog.cpp}{SettingsDialog}, then the terminal + attempts to open the port with the default settings: 9600 8N1. + + Clicking on the \b{Disconnect} button invokes the \c closeSerialPort() + slot: + + \snippet terminal/mainwindow.cpp 5 + + In this case, handled by the closure of the serial port. + + Typing characters in the console invokes the \c writeData() slot: + + \snippet terminal/mainwindow.cpp 6 + + This slot sends the characters typed in the given + \l{terminal/console.cpp}{Console} widget to the serial port. + + When the serial port receives new data, the signal + \l{QTcpSocket::readyRead()}{readyRead()} is emitted, and that signal is + connected to the \c MainWindow::readData() slot: + + \snippet terminal/mainwindow.cpp 7 + + This slot reads the data from the serial port and displays that in the + \l{terminal/console.cpp}{Console} widget. + + Clicking on the \b{Configure} button invokes the \c show() slot which + belongs to the \l{terminal/settingsdialog.cpp}{SettingsDialog} + widget. + + This method displays the \l{terminal/settingsdialog.cpp}{SettingsDialog} + in which the user can choose the desired serial port, see the information + about the selected port, and set the desired parameters of the given serial + port. + + \sa {Blocking Simple Terminal Example} +*/ diff --git a/examples/serialport/enumerator/enumerator.pro b/examples/serialport/enumerator/enumerator.pro new file mode 100644 index 0000000..21233a8 --- /dev/null +++ b/examples/serialport/enumerator/enumerator.pro @@ -0,0 +1,11 @@ +greaterThan(QT_MAJOR_VERSION, 4) { + QT += widgets serialport +} else { + include($$QTSERIALPORT_PROJECT_ROOT/src/serialport/qt4support/serialport.prf) +} + +TARGET = enumerator +TEMPLATE = app + +SOURCES += \ + main.cpp diff --git a/examples/serialport/enumerator/main.cpp b/examples/serialport/enumerator/main.cpp new file mode 100644 index 0000000..9e34d38 --- /dev/null +++ b/examples/serialport/enumerator/main.cpp @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> +** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSerialPort 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QApplication> +#include <QWidget> +#include <QVBoxLayout> +#include <QLabel> +#include <QtSerialPort/QSerialPortInfo> + +QT_USE_NAMESPACE + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + + QWidget w; + w.setWindowTitle(QObject::tr("Info about all available serial ports.")); + QVBoxLayout *layout = new QVBoxLayout; + + foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) { + QString s = QObject::tr("Port: ") + info.portName() + "\n" + + QObject::tr("Location: ") + info.systemLocation() + "\n" + + QObject::tr("Description: ") + info.description() + "\n" + + QObject::tr("Manufacturer: ") + info.manufacturer() + "\n" + + QObject::tr("Vendor Identifier: ") + (info.hasVendorIdentifier() ? QString::number(info.vendorIdentifier(), 16) : QString()) + "\n" + + QObject::tr("Product Identifier: ") + (info.hasProductIdentifier() ?QString::number(info.productIdentifier(), 16) : QString()) + "\n" + + QObject::tr("Busy: ") + (info.isBusy() ? QObject::tr("Yes") : QObject::tr("No")) + "\n"; + + QLabel *label = new QLabel(s); + layout->addWidget(label); + } + + w.setLayout(layout); + w.show(); + + return a.exec(); +} diff --git a/examples/serialport/examples.qdoc b/examples/serialport/examples.qdoc new file mode 100644 index 0000000..f7dbbf9 --- /dev/null +++ b/examples/serialport/examples.qdoc @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2011-2012 Denis Shienkov <denis.shienkov@gmail.com> +** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \module QtSerialPort + \title Examples + \page examples.html + \previouspage Building and usage + \contentspage {Examples} {Contents} + + \list + \li \l blockingmaster + \li \l blockingslave + \li \l cenumerator + \li \l enumerator + \li \l terminal + \endlist +*/ diff --git a/examples/serialport/master/dialog.cpp b/examples/serialport/master/dialog.cpp new file mode 100644 index 0000000..e3a4b66 --- /dev/null +++ b/examples/serialport/master/dialog.cpp @@ -0,0 +1,178 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSerialPort 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "dialog.h" + +#include <QLabel> +#include <QLineEdit> +#include <QComboBox> +#include <QSpinBox> +#include <QPushButton> +#include <QGridLayout> + +#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"))) +{ + foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) + serialPortComboBox->addItem(info.portName()); + + waitResponseSpinBox->setRange(0, 10000); + waitResponseSpinBox->setValue(100); + + QGridLayout *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); + setLayout(mainLayout); + + setWindowTitle(tr("Master")); + serialPortComboBox->setFocus(); + + timer.setSingleShot(true); + + connect(runButton, SIGNAL(clicked()), + this, SLOT(sendRequest())); + connect(&serial, SIGNAL(readyRead()), + this, SLOT(readResponse())); + connect(&timer, SIGNAL(timeout()), + this, SLOT(processTimeout())); +} + +void Dialog::sendRequest() +{ + if (serial.portName() != serialPortComboBox->currentText()) { + serial.close(); + serial.setPortName(serialPortComboBox->currentText()); + + if (!serial.open(QIODevice::ReadWrite)) { + processError(tr("Can't open %1, error code %2") + .arg(serial.portName()).arg(serial.error())); + return; + } + + if (!serial.setBaudRate(QSerialPort::Baud9600)) { + processError(tr("Can't set rate 9600 baud to port %1, error code %2") + .arg(serial.portName()).arg(serial.error())); + return; + } + + if (!serial.setDataBits(QSerialPort::Data8)) { + processError(tr("Can't set 8 data bits to port %1, error code %2") + .arg(serial.portName()).arg(serial.error())); + return; + } + + if (!serial.setParity(QSerialPort::NoParity)) { + processError(tr("Can't set no patity to port %1, error code %2") + .arg(serial.portName()).arg(serial.error())); + return; + } + + if (!serial.setStopBits(QSerialPort::OneStop)) { + processError(tr("Can't set 1 stop bit to port %1, error code %2") + .arg(serial.portName()).arg(serial.error())); + return; + } + + if (!serial.setFlowControl(QSerialPort::NoFlowControl)) { + processError(tr("Can't set no flow control to port %1, error code %2") + .arg(serial.portName()).arg(serial.error())); + return; + } + } + + setControlsEnabled(false); + statusLabel->setText(tr("Status: Running, connected to port %1.") + .arg(serialPortComboBox->currentText())); + + serial.write(requestLineEdit->text().toLocal8Bit()); + timer.start(waitResponseSpinBox->value()); +} + +void Dialog::readResponse() +{ + response.append(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(); +} + +void Dialog::processError(const QString &error) +{ + setControlsEnabled(true); + statusLabel->setText(tr("Status: Not running, %1.").arg(error)); + trafficLabel->setText(tr("No traffic.")); +} + +void Dialog::setControlsEnabled(bool enable) +{ + runButton->setEnabled(enable); + serialPortComboBox->setEnabled(enable); + waitResponseSpinBox->setEnabled(enable); + requestLineEdit->setEnabled(enable); +} diff --git a/examples/serialport/master/dialog.h b/examples/serialport/master/dialog.h new file mode 100644 index 0000000..c1ec416 --- /dev/null +++ b/examples/serialport/master/dialog.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSerialPort 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DIALOG_H +#define DIALOG_H + +#include <QDialog> +#include <QTimer> + +#include <QtSerialPort/QSerialPort> + +QT_USE_NAMESPACE + +QT_BEGIN_NAMESPACE + +class QLabel; +class QLineEdit; +class QSpinBox; +class QPushButton; +class QComboBox; + +QT_END_NAMESPACE + +class Dialog : public QDialog +{ + Q_OBJECT + +public: + Dialog(QWidget *parent = 0); + +private slots: + void sendRequest(); + void readResponse(); + void processTimeout(); + +private: + void setControlsEnabled(bool enable); + 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; + + QSerialPort serial; + QByteArray response; + QTimer timer; +}; + +#endif // DIALOG_H diff --git a/examples/serialport/master/main.cpp b/examples/serialport/master/main.cpp new file mode 100644 index 0000000..fc2e334 --- /dev/null +++ b/examples/serialport/master/main.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSerialPort 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QApplication> + +#include "dialog.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + Dialog dialog; + dialog.show(); + return app.exec(); +} diff --git a/examples/serialport/master/master.pro b/examples/serialport/master/master.pro new file mode 100644 index 0000000..977de6c --- /dev/null +++ b/examples/serialport/master/master.pro @@ -0,0 +1,15 @@ +greaterThan(QT_MAJOR_VERSION, 4) { + QT += widgets serialport +} else { + include($$QTSERIALPORT_PROJECT_ROOT/src/serialport/qt4support/serialport.prf) +} + +TARGET = master +TEMPLATE = app + +HEADERS += \ + dialog.h + +SOURCES += \ + main.cpp \ + dialog.cpp diff --git a/examples/serialport/serialport.pro b/examples/serialport/serialport.pro new file mode 100644 index 0000000..32e50b2 --- /dev/null +++ b/examples/serialport/serialport.pro @@ -0,0 +1,8 @@ +TEMPLATE = subdirs +CONFIG += ordered +SUBDIRS = cenumerator +greaterThan(QT_MAJOR_VERSION, 4) { + !isEmpty(QT.widgets.name):SUBDIRS += enumerator terminal blockingmaster blockingslave +} else { + SUBDIRS += enumerator terminal blockingmaster blockingslave master slave +} diff --git a/examples/serialport/slave/dialog.cpp b/examples/serialport/slave/dialog.cpp new file mode 100644 index 0000000..06a2a15 --- /dev/null +++ b/examples/serialport/slave/dialog.cpp @@ -0,0 +1,182 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSerialPort 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "dialog.h" + +#include <QLabel> +#include <QLineEdit> +#include <QComboBox> +#include <QSpinBox> +#include <QPushButton> +#include <QGridLayout> + +#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"))) +{ + waitRequestSpinBox->setRange(0, 10000); + waitRequestSpinBox->setValue(20); + + foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) + serialPortComboBox->addItem(info.portName()); + + QGridLayout *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); + setLayout(mainLayout); + + setWindowTitle(tr("Slave")); + serialPortComboBox->setFocus(); + + timer.setSingleShot(true); + + connect(runButton, SIGNAL(clicked()), + this, SLOT(startSlave())); + connect(&serial, SIGNAL(readyRead()), + this, SLOT(readRequest())); + connect(&timer, SIGNAL(timeout()), + this, SLOT(processTimeout())); + + connect(serialPortComboBox, SIGNAL(currentIndexChanged(QString)), + this, SLOT(activateRunButton())); + connect(waitRequestSpinBox, SIGNAL(valueChanged(int)), + this, SLOT(activateRunButton())); + connect(responseLineEdit, SIGNAL(textChanged(QString)), + this, SLOT(activateRunButton())); +} + +void Dialog::startSlave() +{ + if (serial.portName() != serialPortComboBox->currentText()) { + serial.close(); + serial.setPortName(serialPortComboBox->currentText()); + + if (!serial.open(QIODevice::ReadWrite)) { + processError(tr("Can't open %1, error code %2") + .arg(serial.portName()).arg(serial.error())); + return; + } + + if (!serial.setBaudRate(QSerialPort::Baud9600)) { + processError(tr("Can't set baud rate 9600 baud to port %1, error code %2") + .arg(serial.portName()).arg(serial.error())); + return; + } + + if (!serial.setDataBits(QSerialPort::Data8)) { + processError(tr("Can't set 8 data bits to port %1, error code %2") + .arg(serial.portName()).arg(serial.error())); + return; + } + + if (!serial.setParity(QSerialPort::NoParity)) { + processError(tr("Can't set no patity to port %1, error code %2") + .arg(serial.portName()).arg(serial.error())); + return; + } + + if (!serial.setStopBits(QSerialPort::OneStop)) { + processError(tr("Can't set 1 stop bit to port %1, error code %2") + .arg(serial.portName()).arg(serial.error())); + return; + } + + if (!serial.setFlowControl(QSerialPort::NoFlowControl)) { + processError(tr("Can't set no flow control to port %1, error code %2") + .arg(serial.portName()).arg(serial.error())); + return; + } + } + + runButton->setEnabled(false); + statusLabel->setText(tr("Status: Running, connected to port %1.") + .arg(serialPortComboBox->currentText())); +} + +void Dialog::readRequest() +{ + if (!timer.isActive()) + timer.start(waitRequestSpinBox->value()); + request.append(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(); +} + +void Dialog::activateRunButton() +{ + runButton->setEnabled(true); +} + +void Dialog::processError(const QString &s) +{ + activateRunButton(); + statusLabel->setText(tr("Status: Not running, %1.").arg(s)); + trafficLabel->setText(tr("No traffic.")); +} diff --git a/examples/serialport/slave/dialog.h b/examples/serialport/slave/dialog.h new file mode 100644 index 0000000..6aafb2b --- /dev/null +++ b/examples/serialport/slave/dialog.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSerialPort 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DIALOG_H +#define DIALOG_H + +#include <QDialog> +#include <QTimer> + +#include <QtSerialPort/QSerialPort> + +QT_USE_NAMESPACE + +QT_BEGIN_NAMESPACE + +class QLabel; +class QLineEdit; +class QComboBox; +class QSpinBox; +class QPushButton; + +QT_END_NAMESPACE + +class Dialog : public QDialog +{ + Q_OBJECT + +public: + Dialog(QWidget *parent = 0); + +private slots: + void startSlave(); + void readRequest(); + void processTimeout(); + void activateRunButton(); + +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; + + QSerialPort serial; + QByteArray request; + QTimer timer; +}; + +#endif // DIALOG_H diff --git a/examples/serialport/slave/main.cpp b/examples/serialport/slave/main.cpp new file mode 100644 index 0000000..fc2e334 --- /dev/null +++ b/examples/serialport/slave/main.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSerialPort 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QApplication> + +#include "dialog.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + Dialog dialog; + dialog.show(); + return app.exec(); +} diff --git a/examples/serialport/slave/slave.pro b/examples/serialport/slave/slave.pro new file mode 100644 index 0000000..df996ac --- /dev/null +++ b/examples/serialport/slave/slave.pro @@ -0,0 +1,15 @@ +greaterThan(QT_MAJOR_VERSION, 4) { + QT += widgets serialport +} else { + include($$QTSERIALPORT_PROJECT_ROOT/src/serialport/qt4support/serialport.prf) +} + +TARGET = slave +TEMPLATE = app + +HEADERS += \ + dialog.h + +SOURCES += \ + main.cpp \ + dialog.cpp diff --git a/examples/serialport/slave/slavethread.cpp b/examples/serialport/slave/slavethread.cpp new file mode 100644 index 0000000..a0177ff --- /dev/null +++ b/examples/serialport/slave/slavethread.cpp @@ -0,0 +1,167 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSerialPort 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "slavethread.h" + +#include <QtSerialPort/QSerialPort> + +#include <QTime> + +QT_USE_NAMESPACE + +SlaveThread::SlaveThread(QObject *parent) + : QThread(parent), waitTimeout(0), quit(false) +{ +} + +SlaveThread::~SlaveThread() +{ + mutex.lock(); + quit = true; + mutex.unlock(); + wait(); +} + +void SlaveThread::startSlave(const QString &portName, int waitTimeout, const QString &response) +{ + QMutexLocker locker(&mutex); + this->portName = portName; + this->waitTimeout = waitTimeout; + this->response = response; + + if (!isRunning()) + start(); +} + +void SlaveThread::run() +{ + bool currentPortNameChanged = false; + + mutex.lock(); + QString currentPortName; + if (currentPortName != portName) { + currentPortName = portName; + currentPortNameChanged = true; + } + + int currentWaitTimeout = waitTimeout; + QString currentRespone = response; + mutex.unlock(); + + QSerialPort serial; + + while (!quit) { + + 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())); + return; + } + + if (!serial.setBaudRate(QSerialPort::Baud9600)) { + emit error(tr("Can't set baud rate 9600 baud to port %1, error code %2") + .arg(portName).arg(serial.error())); + return; + } + + if (!serial.setDataBits(QSerialPort::Data8)) { + emit error(tr("Can't set 8 data bits to port %1, error code %2") + .arg(portName).arg(serial.error())); + return; + } + + if (!serial.setParity(QSerialPort::NoParity)) { + emit error(tr("Can't set no patity to port %1, error code %2") + .arg(portName).arg(serial.error())); + return; + } + + if (!serial.setStopBits(QSerialPort::OneStop)) { + emit error(tr("Can't set 1 stop bit to port %1, error code %2") + .arg(portName).arg(serial.error())); + return; + } + + if (!serial.setFlowControl(QSerialPort::NoFlowControl)) { + emit error(tr("Can't set no flow control to port %1, error code %2") + .arg(portName).arg(serial.error())); + return; + } + } + + if (serial.waitForReadyRead(currentWaitTimeout)) { + + // read all request + QByteArray requestData = serial.readAll(); + while (serial.waitForReadyRead(10)) + requestData += serial.readAll(); + + // write all response + QByteArray responseData = currentRespone.toLocal8Bit(); + serial.write(responseData); + if (serial.waitForBytesWritten(waitTimeout)) { + QString request(requestData); + emit this->request(request); + } else { + emit timeout(tr("Wait write response timeout %1") + .arg(QTime::currentTime().toString())); + } + } else { + emit timeout(tr("Wait read request timeout %1") + .arg(QTime::currentTime().toString())); + } + + mutex.lock(); + if (currentPortName != portName) { + currentPortName = portName; + currentPortNameChanged = true; + } else { + currentPortNameChanged = false; + } + currentWaitTimeout = waitTimeout; + currentRespone = response; + mutex.unlock(); + } +} diff --git a/examples/serialport/slave/slavethread.h b/examples/serialport/slave/slavethread.h new file mode 100644 index 0000000..3ed1e0c --- /dev/null +++ b/examples/serialport/slave/slavethread.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSerialPort 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SLAVETHREAD_H +#define SLAVETHREAD_H + +#include <QThread> +#include <QMutex> +#include <QWaitCondition> + +class SlaveThread : public QThread +{ + Q_OBJECT + +public: + SlaveThread(QObject *parent = 0); + ~SlaveThread(); + + void startSlave(const QString &portName, int waitTimeout, const QString &response); + void run(); + +signals: + void request(const QString &s); + void error(const QString &s); + void timeout(const QString &s); + +private: + QString portName; + QString response; + int waitTimeout; + QMutex mutex; + bool quit; +}; + +#endif // SLAVETHREAD_H diff --git a/examples/serialport/terminal/console.cpp b/examples/serialport/terminal/console.cpp new file mode 100644 index 0000000..7f3f891 --- /dev/null +++ b/examples/serialport/terminal/console.cpp @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> +** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSerialPort 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "console.h" + +#include <QScrollBar> + +#include <QtCore/QDebug> + +Console::Console(QWidget *parent) + : QPlainTextEdit(parent) + , localEchoEnabled(false) +{ + 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)); + + QScrollBar *bar = verticalScrollBar(); + bar->setValue(bar->maximum()); +} + +void Console::setLocalEchoEnabled(bool set) +{ + localEchoEnabled = set; +} + +void Console::keyPressEvent(QKeyEvent *e) +{ + switch (e->key()) { + case Qt::Key_Backspace: + case Qt::Key_Left: + case Qt::Key_Right: + case Qt::Key_Up: + case Qt::Key_Down: + // skip processing + break; + default: + if (localEchoEnabled) + QPlainTextEdit::keyPressEvent(e); + emit getData(e->text().toLocal8Bit()); + } +} + +void Console::mousePressEvent(QMouseEvent *e) +{ + Q_UNUSED(e) + setFocus(); +} + +void Console::mouseDoubleClickEvent(QMouseEvent *e) +{ + Q_UNUSED(e) +} + +void Console::contextMenuEvent(QContextMenuEvent *e) +{ + Q_UNUSED(e) +} diff --git a/examples/serialport/terminal/console.h b/examples/serialport/terminal/console.h new file mode 100644 index 0000000..9b5ba1f --- /dev/null +++ b/examples/serialport/terminal/console.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> +** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSerialPort 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CONSOLE_H +#define CONSOLE_H + +#include <QPlainTextEdit> + +class Console : public QPlainTextEdit +{ + Q_OBJECT + +signals: + void getData(const QByteArray &data); + +public: + explicit Console(QWidget *parent = 0); + + void putData(const QByteArray &data); + + void setLocalEchoEnabled(bool set); + +protected: + virtual void keyPressEvent(QKeyEvent *e); + virtual void mousePressEvent(QMouseEvent *e); + virtual void mouseDoubleClickEvent(QMouseEvent *e); + virtual void contextMenuEvent(QContextMenuEvent *e); + +private: + bool localEchoEnabled; + +}; + +#endif // CONSOLE_H diff --git a/examples/serialport/terminal/images/application-exit.png b/examples/serialport/terminal/images/application-exit.png Binary files differnew file mode 100644 index 0000000..32be6b3 --- /dev/null +++ b/examples/serialport/terminal/images/application-exit.png diff --git a/examples/serialport/terminal/images/clear.png b/examples/serialport/terminal/images/clear.png Binary files differnew file mode 100644 index 0000000..aa612f1 --- /dev/null +++ b/examples/serialport/terminal/images/clear.png diff --git a/examples/serialport/terminal/images/connect.png b/examples/serialport/terminal/images/connect.png Binary files differnew file mode 100644 index 0000000..dd5a51e --- /dev/null +++ b/examples/serialport/terminal/images/connect.png diff --git a/examples/serialport/terminal/images/disconnect.png b/examples/serialport/terminal/images/disconnect.png Binary files differnew file mode 100644 index 0000000..fd58f7a --- /dev/null +++ b/examples/serialport/terminal/images/disconnect.png diff --git a/examples/serialport/terminal/images/settings.png b/examples/serialport/terminal/images/settings.png Binary files differnew file mode 100644 index 0000000..3d1042e --- /dev/null +++ b/examples/serialport/terminal/images/settings.png diff --git a/examples/serialport/terminal/main.cpp b/examples/serialport/terminal/main.cpp new file mode 100644 index 0000000..e356519 --- /dev/null +++ b/examples/serialport/terminal/main.cpp @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> +** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSerialPort 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QApplication> + +#include "mainwindow.h" + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow w; + w.show(); + return a.exec(); +} diff --git a/examples/serialport/terminal/mainwindow.cpp b/examples/serialport/terminal/mainwindow.cpp new file mode 100644 index 0000000..47864a2 --- /dev/null +++ b/examples/serialport/terminal/mainwindow.cpp @@ -0,0 +1,179 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> +** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSerialPort 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mainwindow.h" +#include "ui_mainwindow.h" +#include "console.h" +#include "settingsdialog.h" + +#include <QMessageBox> +#include <QtSerialPort/QSerialPort> + +//! [0] +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow) +{ +//! [0] + ui->setupUi(this); + console = new Console; + console->setEnabled(false); + setCentralWidget(console); +//! [1] + serial = new QSerialPort(this); +//! [1] + settings = new SettingsDialog; + + ui->actionConnect->setEnabled(true); + ui->actionDisconnect->setEnabled(false); + ui->actionQuit->setEnabled(true); + ui->actionConfigure->setEnabled(true); + + initActionsConnections(); + + connect(serial, SIGNAL(error(QSerialPort::SerialPortError)), this, + SLOT(handleError(QSerialPort::SerialPortError))); + +//! [2] + connect(serial, SIGNAL(readyRead()), this, SLOT(readData())); +//! [2] + connect(console, SIGNAL(getData(QByteArray)), this, SLOT(writeData(QByteArray))); +//! [3] +} +//! [3] + +MainWindow::~MainWindow() +{ + delete settings; + delete ui; +} + +//! [4] +void MainWindow::openSerialPort() +{ + SettingsDialog::Settings p = settings->settings(); + serial->setPortName(p.name); + if (serial->open(QIODevice::ReadWrite)) { + if (serial->setBaudRate(p.baudRate) + && serial->setDataBits(p.dataBits) + && serial->setParity(p.parity) + && serial->setStopBits(p.stopBits) + && serial->setFlowControl(p.flowControl)) { + + console->setEnabled(true); + console->setLocalEchoEnabled(p.localEchoEnabled); + ui->actionConnect->setEnabled(false); + ui->actionDisconnect->setEnabled(true); + ui->actionConfigure->setEnabled(false); + ui->statusBar->showMessage(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 { + serial->close(); + QMessageBox::critical(this, tr("Error"), serial->errorString()); + + ui->statusBar->showMessage(tr("Open error")); + } + } else { + QMessageBox::critical(this, tr("Error"), serial->errorString()); + + ui->statusBar->showMessage(tr("Configure error")); + } +} +//! [4] + +//! [5] +void MainWindow::closeSerialPort() +{ + serial->close(); + console->setEnabled(false); + ui->actionConnect->setEnabled(true); + ui->actionDisconnect->setEnabled(false); + ui->actionConfigure->setEnabled(true); + ui->statusBar->showMessage(tr("Disconnected")); +} +//! [5] + +void MainWindow::about() +{ + QMessageBox::about(this, tr("About Simple Terminal"), + tr("The <b>Simple Terminal</b> example demonstrates how to " + "use the Qt Serial Port module in modern GUI applications " + "using Qt, with a menu bar, toolbars, and a status bar.")); +} + +//! [6] +void MainWindow::writeData(const QByteArray &data) +{ + serial->write(data); +} +//! [6] + +//! [7] +void MainWindow::readData() +{ + QByteArray data = serial->readAll(); + console->putData(data); +} +//! [7] + +//! [8] +void MainWindow::handleError(QSerialPort::SerialPortError error) +{ + if (error == QSerialPort::ResourceError) { + QMessageBox::critical(this, tr("Critical Error"), serial->errorString()); + closeSerialPort(); + } +} +//! [8] + +void MainWindow::initActionsConnections() +{ + connect(ui->actionConnect, SIGNAL(triggered()), this, SLOT(openSerialPort())); + connect(ui->actionDisconnect, SIGNAL(triggered()), this, SLOT(closeSerialPort())); + connect(ui->actionQuit, SIGNAL(triggered()), this, SLOT(close())); + connect(ui->actionConfigure, SIGNAL(triggered()), settings, SLOT(show())); + connect(ui->actionClear, SIGNAL(triggered()), console, SLOT(clear())); + connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(about())); + connect(ui->actionAboutQt, SIGNAL(triggered()), qApp, SLOT(aboutQt())); +} diff --git a/examples/serialport/terminal/mainwindow.h b/examples/serialport/terminal/mainwindow.h new file mode 100644 index 0000000..1be7f89 --- /dev/null +++ b/examples/serialport/terminal/mainwindow.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> +** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSerialPort 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include <QtCore/QtGlobal> + +#include <QMainWindow> + +#include <QtSerialPort/QSerialPort> + +QT_BEGIN_NAMESPACE + +namespace Ui { +class MainWindow; +} + +QT_END_NAMESPACE + +class Console; +class SettingsDialog; + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); + +private slots: + void openSerialPort(); + void closeSerialPort(); + void about(); + void writeData(const QByteArray &data); + void readData(); + + void handleError(QSerialPort::SerialPortError error); + +private: + void initActionsConnections(); + +private: + Ui::MainWindow *ui; + Console *console; + SettingsDialog *settings; + QSerialPort *serial; +}; + +#endif // MAINWINDOW_H diff --git a/examples/serialport/terminal/mainwindow.ui b/examples/serialport/terminal/mainwindow.ui new file mode 100644 index 0000000..452fdd5 --- /dev/null +++ b/examples/serialport/terminal/mainwindow.ui @@ -0,0 +1,162 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>MainWindow</class> + <widget class="QMainWindow" name="MainWindow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>300</height> + </rect> + </property> + <property name="windowTitle"> + <string>Simple Terminal</string> + </property> + <widget class="QWidget" name="centralWidget"> + <layout class="QVBoxLayout" name="verticalLayout"/> + </widget> + <widget class="QMenuBar" name="menuBar"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>19</height> + </rect> + </property> + <widget class="QMenu" name="menuCalls"> + <property name="title"> + <string>Calls</string> + </property> + <addaction name="actionConnect"/> + <addaction name="actionDisconnect"/> + <addaction name="separator"/> + <addaction name="actionQuit"/> + </widget> + <widget class="QMenu" name="menuTools"> + <property name="title"> + <string>Tools</string> + </property> + <addaction name="actionConfigure"/> + <addaction name="actionClear"/> + </widget> + <widget class="QMenu" name="menuHelp"> + <property name="title"> + <string>Help</string> + </property> + <addaction name="actionAbout"/> + <addaction name="actionAboutQt"/> + </widget> + <addaction name="menuCalls"/> + <addaction name="menuTools"/> + <addaction name="menuHelp"/> + </widget> + <widget class="QToolBar" name="mainToolBar"> + <attribute name="toolBarArea"> + <enum>TopToolBarArea</enum> + </attribute> + <attribute name="toolBarBreak"> + <bool>false</bool> + </attribute> + <addaction name="actionConnect"/> + <addaction name="actionDisconnect"/> + <addaction name="actionConfigure"/> + <addaction name="actionClear"/> + </widget> + <widget class="QStatusBar" name="statusBar"/> + <action name="actionAbout"> + <property name="text"> + <string>&About</string> + </property> + <property name="toolTip"> + <string>About program</string> + </property> + <property name="shortcut"> + <string>Alt+A</string> + </property> + </action> + <action name="actionAboutQt"> + <property name="text"> + <string>About Qt</string> + </property> + </action> + <action name="actionConnect"> + <property name="icon"> + <iconset resource="terminal.qrc"> + <normaloff>:/images/connect.png</normaloff>:/images/connect.png</iconset> + </property> + <property name="text"> + <string>C&onnect</string> + </property> + <property name="toolTip"> + <string>Connect to serial port</string> + </property> + <property name="shortcut"> + <string>Ctrl+O</string> + </property> + </action> + <action name="actionDisconnect"> + <property name="icon"> + <iconset resource="terminal.qrc"> + <normaloff>:/images/disconnect.png</normaloff>:/images/disconnect.png</iconset> + </property> + <property name="text"> + <string>&Disconnect</string> + </property> + <property name="toolTip"> + <string>Disconnect from serial port</string> + </property> + <property name="shortcut"> + <string>Ctrl+D</string> + </property> + </action> + <action name="actionConfigure"> + <property name="icon"> + <iconset resource="terminal.qrc"> + <normaloff>:/images/settings.png</normaloff>:/images/settings.png</iconset> + </property> + <property name="text"> + <string>&Configure</string> + </property> + <property name="toolTip"> + <string>Configure serial port</string> + </property> + <property name="shortcut"> + <string>Alt+C</string> + </property> + </action> + <action name="actionClear"> + <property name="icon"> + <iconset resource="terminal.qrc"> + <normaloff>:/images/clear.png</normaloff>:/images/clear.png</iconset> + </property> + <property name="text"> + <string>C&lear</string> + </property> + <property name="toolTip"> + <string>Clear data</string> + </property> + <property name="shortcut"> + <string>Alt+L</string> + </property> + </action> + <action name="actionQuit"> + <property name="icon"> + <iconset resource="terminal.qrc"> + <normaloff>:/images/application-exit.png</normaloff>:/images/application-exit.png</iconset> + </property> + <property name="text"> + <string>&Quit</string> + </property> + <property name="shortcut"> + <string>Ctrl+Q</string> + </property> + </action> + </widget> + <layoutdefault spacing="6" margin="11"/> + <resources> + <include location="terminal.qrc"/> + </resources> + <connections/> +</ui> diff --git a/examples/serialport/terminal/settingsdialog.cpp b/examples/serialport/terminal/settingsdialog.cpp new file mode 100644 index 0000000..65f6b87 --- /dev/null +++ b/examples/serialport/terminal/settingsdialog.cpp @@ -0,0 +1,204 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> +** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSerialPort 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "settingsdialog.h" +#include "ui_settingsdialog.h" + +#include <QtSerialPort/QSerialPortInfo> +#include <QIntValidator> +#include <QLineEdit> + +QT_USE_NAMESPACE + +SettingsDialog::SettingsDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::SettingsDialog) +{ + ui->setupUi(this); + + intValidator = new QIntValidator(0, 4000000, this); + + ui->baudRateBox->setInsertPolicy(QComboBox::NoInsert); + + connect(ui->applyButton, SIGNAL(clicked()), + this, SLOT(apply())); + connect(ui->serialPortInfoListBox, SIGNAL(currentIndexChanged(int)), + this, SLOT(showPortInfo(int))); + connect(ui->baudRateBox, SIGNAL(currentIndexChanged(int)), + this, SLOT(checkCustomBaudRatePolicy(int))); + + fillPortsParameters(); + fillPortsInfo(); + + updateSettings(); +} + +SettingsDialog::~SettingsDialog() +{ + delete ui; +} + +SettingsDialog::Settings SettingsDialog::settings() const +{ + return currentSettings; +} + +void SettingsDialog::showPortInfo(int idx) +{ + if (idx != -1) { + QStringList list = ui->serialPortInfoListBox->itemData(idx).toStringList(); + ui->descriptionLabel->setText(tr("Description: %1").arg(list.at(1))); + ui->manufacturerLabel->setText(tr("Manufacturer: %1").arg(list.at(2))); + ui->locationLabel->setText(tr("Location: %1").arg(list.at(3))); + ui->vidLabel->setText(tr("Vendor Identifier: %1").arg(list.at(4))); + ui->pidLabel->setText(tr("Product Identifier: %1").arg(list.at(5))); + } +} + +void SettingsDialog::apply() +{ + updateSettings(); + hide(); +} + +void SettingsDialog::checkCustomBaudRatePolicy(int idx) +{ + bool isCustomBaudRate = !ui->baudRateBox->itemData(idx).isValid(); + ui->baudRateBox->setEditable(isCustomBaudRate); + if (isCustomBaudRate) { + ui->baudRateBox->clearEditText(); + QLineEdit *edit = ui->baudRateBox->lineEdit(); + edit->setValidator(intValidator); + } +} + +void SettingsDialog::fillPortsParameters() +{ + // fill baud rate (is not the entire list of available values, + // desired values??, add your independently) + ui->baudRateBox->addItem(QLatin1String("9600"), QSerialPort::Baud9600); + ui->baudRateBox->addItem(QLatin1String("19200"), QSerialPort::Baud19200); + ui->baudRateBox->addItem(QLatin1String("38400"), QSerialPort::Baud38400); + ui->baudRateBox->addItem(QLatin1String("115200"), QSerialPort::Baud115200); + ui->baudRateBox->addItem(QLatin1String("Custom")); + + // fill data bits + ui->dataBitsBox->addItem(QLatin1String("5"), QSerialPort::Data5); + ui->dataBitsBox->addItem(QLatin1String("6"), QSerialPort::Data6); + ui->dataBitsBox->addItem(QLatin1String("7"), QSerialPort::Data7); + ui->dataBitsBox->addItem(QLatin1String("8"), QSerialPort::Data8); + ui->dataBitsBox->setCurrentIndex(3); + + // fill parity + ui->parityBox->addItem(QLatin1String("None"), QSerialPort::NoParity); + ui->parityBox->addItem(QLatin1String("Even"), QSerialPort::EvenParity); + ui->parityBox->addItem(QLatin1String("Odd"), QSerialPort::OddParity); + ui->parityBox->addItem(QLatin1String("Mark"), QSerialPort::MarkParity); + ui->parityBox->addItem(QLatin1String("Space"), QSerialPort::SpaceParity); + + // fill stop bits + ui->stopBitsBox->addItem(QLatin1String("1"), QSerialPort::OneStop); +#ifdef Q_OS_WIN + ui->stopBitsBox->addItem(QLatin1String("1.5"), QSerialPort::OneAndHalfStop); +#endif + ui->stopBitsBox->addItem(QLatin1String("2"), QSerialPort::TwoStop); + + // fill flow control + ui->flowControlBox->addItem(QLatin1String("None"), QSerialPort::NoFlowControl); + ui->flowControlBox->addItem(QLatin1String("RTS/CTS"), QSerialPort::HardwareControl); + ui->flowControlBox->addItem(QLatin1String("XON/XOFF"), QSerialPort::SoftwareControl); +} + +void SettingsDialog::fillPortsInfo() +{ + ui->serialPortInfoListBox->clear(); + foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) { + QStringList list; + list << info.portName() + << info.description() + << info.manufacturer() + << info.systemLocation() + << (info.vendorIdentifier() ? QString::number(info.vendorIdentifier(), 16) : QString()) + << (info.productIdentifier() ? QString::number(info.productIdentifier(), 16) : QString()); + + ui->serialPortInfoListBox->addItem(list.first(), list); + } +} + +void SettingsDialog::updateSettings() +{ + currentSettings.name = ui->serialPortInfoListBox->currentText(); + + // Baud Rate + if (ui->baudRateBox->currentIndex() == 4) { + // custom baud rate + currentSettings.baudRate = ui->baudRateBox->currentText().toInt(); + } else { + // standard baud rate + currentSettings.baudRate = static_cast<QSerialPort::BaudRate>( + ui->baudRateBox->itemData(ui->baudRateBox->currentIndex()).toInt()); + } + currentSettings.stringBaudRate = QString::number(currentSettings.baudRate); + + // Data bits + currentSettings.dataBits = static_cast<QSerialPort::DataBits>( + ui->dataBitsBox->itemData(ui->dataBitsBox->currentIndex()).toInt()); + currentSettings.stringDataBits = ui->dataBitsBox->currentText(); + + // Parity + currentSettings.parity = static_cast<QSerialPort::Parity>( + ui->parityBox->itemData(ui->parityBox->currentIndex()).toInt()); + currentSettings.stringParity = ui->parityBox->currentText(); + + // Stop bits + currentSettings.stopBits = static_cast<QSerialPort::StopBits>( + ui->stopBitsBox->itemData(ui->stopBitsBox->currentIndex()).toInt()); + currentSettings.stringStopBits = ui->stopBitsBox->currentText(); + + // Flow control + currentSettings.flowControl = static_cast<QSerialPort::FlowControl>( + ui->flowControlBox->itemData(ui->flowControlBox->currentIndex()).toInt()); + currentSettings.stringFlowControl = ui->flowControlBox->currentText(); + + // Additional options + currentSettings.localEchoEnabled = ui->localEchoCheckBox->isChecked(); +} diff --git a/examples/serialport/terminal/settingsdialog.h b/examples/serialport/terminal/settingsdialog.h new file mode 100644 index 0000000..ff8f8b6 --- /dev/null +++ b/examples/serialport/terminal/settingsdialog.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> +** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSerialPort 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SETTINGSDIALOG_H +#define SETTINGSDIALOG_H + +#include <QDialog> +#include <QtSerialPort/QSerialPort> + +QT_USE_NAMESPACE + +QT_BEGIN_NAMESPACE + +namespace Ui { +class SettingsDialog; +} + +class QIntValidator; + +QT_END_NAMESPACE + +class SettingsDialog : public QDialog +{ + Q_OBJECT + +public: + struct Settings { + QString name; + qint32 baudRate; + QString stringBaudRate; + QSerialPort::DataBits dataBits; + QString stringDataBits; + QSerialPort::Parity parity; + QString stringParity; + QSerialPort::StopBits stopBits; + QString stringStopBits; + QSerialPort::FlowControl flowControl; + QString stringFlowControl; + bool localEchoEnabled; + }; + + explicit SettingsDialog(QWidget *parent = 0); + ~SettingsDialog(); + + Settings settings() const; + +private slots: + void showPortInfo(int idx); + void apply(); + void checkCustomBaudRatePolicy(int idx); + +private: + void fillPortsParameters(); + void fillPortsInfo(); + void updateSettings(); + +private: + Ui::SettingsDialog *ui; + Settings currentSettings; + QIntValidator *intValidator; +}; + +#endif // SETTINGSDIALOG_H diff --git a/examples/serialport/terminal/settingsdialog.ui b/examples/serialport/terminal/settingsdialog.ui new file mode 100644 index 0000000..28c1211 --- /dev/null +++ b/examples/serialport/terminal/settingsdialog.ui @@ -0,0 +1,170 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>SettingsDialog</class> + <widget class="QDialog" name="SettingsDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>281</width> + <height>262</height> + </rect> + </property> + <property name="windowTitle"> + <string>Settings</string> + </property> + <layout class="QGridLayout" name="gridLayout_3"> + <item row="0" column="1"> + <widget class="QGroupBox" name="parametersBox"> + <property name="title"> + <string>Select Parameters</string> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="0" column="0"> + <widget class="QLabel" name="baudRateLabel"> + <property name="text"> + <string>BaudRate:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QComboBox" name="baudRateBox"/> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="dataBitsLabel"> + <property name="text"> + <string>Data bits:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QComboBox" name="dataBitsBox"/> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="parityLabel"> + <property name="text"> + <string>Parity:</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QComboBox" name="parityBox"/> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="stopBitsLabel"> + <property name="text"> + <string>Stop bits:</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QComboBox" name="stopBitsBox"/> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="flowControlLabel"> + <property name="text"> + <string>Flow control:</string> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QComboBox" name="flowControlBox"/> + </item> + </layout> + </widget> + </item> + <item row="0" column="0"> + <widget class="QGroupBox" name="selectBox"> + <property name="title"> + <string>Select Serial Port</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QComboBox" name="serialPortInfoListBox"/> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="descriptionLabel"> + <property name="text"> + <string>Description:</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="manufacturerLabel"> + <property name="text"> + <string>Manufacturer:</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="locationLabel"> + <property name="text"> + <string>Location:</string> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="vidLabel"> + <property name="text"> + <string>Vendor ID:</string> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QLabel" name="pidLabel"> + <property name="text"> + <string>Product ID:</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item row="2" column="0" colspan="2"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>96</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="applyButton"> + <property name="text"> + <string>Apply</string> + </property> + </widget> + </item> + </layout> + </item> + <item row="1" column="0" colspan="2"> + <widget class="QGroupBox" name="additionalOptionsGroupBox"> + <property name="title"> + <string>Additional options</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QCheckBox" name="localEchoCheckBox"> + <property name="text"> + <string>Local echo</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/examples/serialport/terminal/terminal.pro b/examples/serialport/terminal/terminal.pro new file mode 100644 index 0000000..0a5b545 --- /dev/null +++ b/examples/serialport/terminal/terminal.pro @@ -0,0 +1,26 @@ +greaterThan(QT_MAJOR_VERSION, 4) { + QT += widgets serialport +} else { + include($$QTSERIALPORT_PROJECT_ROOT/src/serialport/qt4support/serialport.prf) +} + +TARGET = terminal +TEMPLATE = app + +SOURCES += \ + main.cpp \ + mainwindow.cpp \ + settingsdialog.cpp \ + console.cpp + +HEADERS += \ + mainwindow.h \ + settingsdialog.h \ + console.h + +FORMS += \ + mainwindow.ui \ + settingsdialog.ui + +RESOURCES += \ + terminal.qrc diff --git a/examples/serialport/terminal/terminal.qrc b/examples/serialport/terminal/terminal.qrc new file mode 100644 index 0000000..0b49879 --- /dev/null +++ b/examples/serialport/terminal/terminal.qrc @@ -0,0 +1,9 @@ +<RCC> + <qresource prefix="/"> + <file>images/connect.png</file> + <file>images/disconnect.png</file> + <file>images/application-exit.png</file> + <file>images/settings.png</file> + <file>images/clear.png</file> + </qresource> +</RCC> |