feat: 初始化tool模块代码

master
laixingyu 3 years ago
parent 0cf4e132af
commit 65b9ce4816

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

@ -0,0 +1,9 @@
HEADERS += \
$$PWD/qextserialport.h \
$$PWD/qextserialport_global.h \
$$PWD/qextserialport_p.h
SOURCES += $$PWD/qextserialport.cpp
win32:SOURCES += $$PWD/qextserialport_win.cpp
unix:SOURCES += $$PWD/qextserialport_unix.cpp

File diff suppressed because it is too large Load Diff

@ -0,0 +1,234 @@
/****************************************************************************
** Copyright (c) 2000-2003 Wayne Roth
** Copyright (c) 2004-2007 Stefan Sander
** Copyright (c) 2007 Michal Policht
** Copyright (c) 2008 Brandon Fosdick
** Copyright (c) 2009-2010 Liam Staskawicz
** Copyright (c) 2011 Debao Zhang
** All right reserved.
** Web: http://code.google.com/p/qextserialport/
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef _QEXTSERIALPORT_H_
#define _QEXTSERIALPORT_H_
#include <QtCore/QIODevice>
#include "qextserialport_global.h"
#ifdef Q_OS_UNIX
#include <termios.h>
#endif
/*line status constants*/
// ### QESP2.0 move to enum
#define LS_CTS 0x01
#define LS_DSR 0x02
#define LS_DCD 0x04
#define LS_RI 0x08
#define LS_RTS 0x10
#define LS_DTR 0x20
#define LS_ST 0x40
#define LS_SR 0x80
/*error constants*/
// ### QESP2.0 move to enum
#define E_NO_ERROR 0
#define E_INVALID_FD 1
#define E_NO_MEMORY 2
#define E_CAUGHT_NON_BLOCKED_SIGNAL 3
#define E_PORT_TIMEOUT 4
#define E_INVALID_DEVICE 5
#define E_BREAK_CONDITION 6
#define E_FRAMING_ERROR 7
#define E_IO_ERROR 8
#define E_BUFFER_OVERRUN 9
#define E_RECEIVE_OVERFLOW 10
#define E_RECEIVE_PARITY_ERROR 11
#define E_TRANSMIT_OVERFLOW 12
#define E_READ_FAILED 13
#define E_WRITE_FAILED 14
#define E_FILE_NOT_FOUND 15
#define E_PERMISSION_DENIED 16
#define E_AGAIN 17
enum BaudRateType {
#if defined(Q_OS_UNIX) || defined(qdoc)
BAUD50 = 50, //POSIX ONLY
BAUD75 = 75, //POSIX ONLY
BAUD134 = 134, //POSIX ONLY
BAUD150 = 150, //POSIX ONLY
BAUD200 = 200, //POSIX ONLY
BAUD1800 = 1800, //POSIX ONLY
# if defined(B76800) || defined(qdoc)
BAUD76800 = 76800, //POSIX ONLY
# endif
# if (defined(B230400) && defined(B4000000)) || defined(qdoc)
BAUD230400 = 230400, //POSIX ONLY
BAUD460800 = 460800, //POSIX ONLY
BAUD500000 = 500000, //POSIX ONLY
BAUD576000 = 576000, //POSIX ONLY
BAUD921600 = 921600, //POSIX ONLY
BAUD1000000 = 1000000, //POSIX ONLY
BAUD1152000 = 1152000, //POSIX ONLY
BAUD1500000 = 1500000, //POSIX ONLY
BAUD2000000 = 2000000, //POSIX ONLY
BAUD2500000 = 2500000, //POSIX ONLY
BAUD3000000 = 3000000, //POSIX ONLY
BAUD3500000 = 3500000, //POSIX ONLY
BAUD4000000 = 4000000, //POSIX ONLY
# endif
#endif //Q_OS_UNIX
#if defined(Q_OS_WIN) || defined(qdoc)
BAUD14400 = 14400, //WINDOWS ONLY
BAUD56000 = 56000, //WINDOWS ONLY
BAUD128000 = 128000, //WINDOWS ONLY
BAUD256000 = 256000, //WINDOWS ONLY
#endif //Q_OS_WIN
BAUD110 = 110,
BAUD300 = 300,
BAUD600 = 600,
BAUD1200 = 1200,
BAUD2400 = 2400,
BAUD4800 = 4800,
BAUD9600 = 9600,
BAUD19200 = 19200,
BAUD38400 = 38400,
BAUD57600 = 57600,
BAUD115200 = 115200
};
enum DataBitsType {
DATA_5 = 5,
DATA_6 = 6,
DATA_7 = 7,
DATA_8 = 8
};
enum ParityType {
PAR_NONE,
PAR_ODD,
PAR_EVEN,
#if defined(Q_OS_WIN) || defined(qdoc)
PAR_MARK, //WINDOWS ONLY
#endif
PAR_SPACE
};
enum StopBitsType {
STOP_1,
#if defined(Q_OS_WIN) || defined(qdoc)
STOP_1_5, //WINDOWS ONLY
#endif
STOP_2
};
enum FlowType {
FLOW_OFF,
FLOW_HARDWARE,
FLOW_XONXOFF
};
/**
* structure to contain port settings
*/
struct PortSettings {
BaudRateType BaudRate;
DataBitsType DataBits;
ParityType Parity;
StopBitsType StopBits;
FlowType FlowControl;
long Timeout_Millisec;
};
class QextSerialPortPrivate;
class QEXTSERIALPORT_EXPORT QextSerialPort: public QIODevice
{
Q_OBJECT
Q_DECLARE_PRIVATE(QextSerialPort)
Q_ENUMS(QueryMode)
Q_PROPERTY(QString portName READ portName WRITE setPortName)
Q_PROPERTY(QueryMode queryMode READ queryMode WRITE setQueryMode)
public:
enum QueryMode {
Polling,
EventDriven
};
explicit QextSerialPort(QueryMode mode = EventDriven, QObject *parent = 0);
explicit QextSerialPort(const QString &name, QueryMode mode = EventDriven, QObject *parent = 0);
explicit QextSerialPort(const PortSettings &s, QueryMode mode = EventDriven, QObject *parent = 0);
QextSerialPort(const QString &name, const PortSettings &s, QueryMode mode = EventDriven, QObject *parent = 0);
~QextSerialPort();
QString portName() const;
QueryMode queryMode() const;
BaudRateType baudRate() const;
DataBitsType dataBits() const;
ParityType parity() const;
StopBitsType stopBits() const;
FlowType flowControl() const;
bool open(OpenMode mode);
bool isSequential() const;
void close();
void flush();
qint64 bytesAvailable() const;
bool canReadLine() const;
QByteArray readAll();
ulong lastError() const;
ulong lineStatus();
QString errorString();
public Q_SLOTS:
void setPortName(const QString &name);
void setQueryMode(QueryMode mode);
void setBaudRate(BaudRateType);
void setDataBits(DataBitsType);
void setParity(ParityType);
void setStopBits(StopBitsType);
void setFlowControl(FlowType);
void setTimeout(long);
void setDtr(bool set = true);
void setRts(bool set = true);
Q_SIGNALS:
void dsrChanged(bool status);
protected:
qint64 readData(char *data, qint64 maxSize);
qint64 writeData(const char *data, qint64 maxSize);
private:
Q_DISABLE_COPY(QextSerialPort)
#ifdef Q_OS_WIN
Q_PRIVATE_SLOT(d_func(), void _q_onWinEvent(HANDLE))
#endif
Q_PRIVATE_SLOT(d_func(), void _q_canRead())
QextSerialPortPrivate *const d_ptr;
};
#endif

@ -0,0 +1,72 @@
/****************************************************************************
** Copyright (c) 2000-2003 Wayne Roth
** Copyright (c) 2004-2007 Stefan Sander
** Copyright (c) 2007 Michal Policht
** Copyright (c) 2008 Brandon Fosdick
** Copyright (c) 2009-2010 Liam Staskawicz
** Copyright (c) 2011 Debao Zhang
** All right reserved.
** Web: http://code.google.com/p/qextserialport/
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef QEXTSERIALPORT_GLOBAL_H
#define QEXTSERIALPORT_GLOBAL_H
#include <QtCore/QtGlobal>
#ifdef QEXTSERIALPORT_BUILD_SHARED
# define QEXTSERIALPORT_EXPORT Q_DECL_EXPORT
#elif defined(QEXTSERIALPORT_USING_SHARED)
# define QEXTSERIALPORT_EXPORT Q_DECL_IMPORT
#else
# define QEXTSERIALPORT_EXPORT
#endif
// ### for compatible with old version. should be removed in QESP 2.0
#ifdef _TTY_NOWARN_
# define QESP_NO_WARN
#endif
#ifdef _TTY_NOWARN_PORT_
# define QESP_NO_PORTABILITY_WARN
#endif
/*if all warning messages are turned off, flag portability warnings to be turned off as well*/
#ifdef QESP_NO_WARN
# define QESP_NO_PORTABILITY_WARN
#endif
/*macros for warning and debug messages*/
#ifdef QESP_NO_PORTABILITY_WARN
# define QESP_PORTABILITY_WARNING while (false)qWarning
#else
# define QESP_PORTABILITY_WARNING qWarning
#endif /*QESP_NOWARN_PORT*/
#ifdef QESP_NO_WARN
# define QESP_WARNING while (false)qWarning
#else
# define QESP_WARNING qWarning
#endif /*QESP_NOWARN*/
#endif // QEXTSERIALPORT_GLOBAL_H

@ -0,0 +1,277 @@
/****************************************************************************
** Copyright (c) 2000-2003 Wayne Roth
** Copyright (c) 2004-2007 Stefan Sander
** Copyright (c) 2007 Michal Policht
** Copyright (c) 2008 Brandon Fosdick
** Copyright (c) 2009-2010 Liam Staskawicz
** Copyright (c) 2011 Debao Zhang
** All right reserved.
** Web: http://code.google.com/p/qextserialport/
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef _QEXTSERIALPORT_P_H_
#define _QEXTSERIALPORT_P_H_
//
// W A R N I N G
// -------------
//
// This file is not part of the QESP API. It exists for the convenience
// of other QESP classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "qextserialport.h"
#include <QtCore/QReadWriteLock>
#ifdef Q_OS_UNIX
# include <termios.h>
#elif (defined Q_OS_WIN)
# include <QtCore/qt_windows.h>
#endif
#include <stdlib.h>
// This is QextSerialPort's read buffer, needed by posix system.
// ref: QRingBuffer & QIODevicePrivateLinearBuffer
class QextReadBuffer
{
public:
inline QextReadBuffer(size_t growth = 4096)
: len(0), first(0), buf(0), capacity(0), basicBlockSize(growth)
{
}
~QextReadBuffer()
{
delete buf;
}
inline void clear()
{
first = buf;
len = 0;
}
inline int size() const
{
return len;
}
inline bool isEmpty() const
{
return len == 0;
}
inline int read(char *target, int size)
{
int r = qMin(size, len);
if (r == 1) {
*target = *first;
--len;
++first;
} else {
memcpy(target, first, r);
len -= r;
first += r;
}
return r;
}
inline char *reserve(size_t size)
{
if ((first - buf) + len + size > capacity) {
size_t newCapacity = qMax(capacity, basicBlockSize);
while (newCapacity < len + size) {
newCapacity *= 2;
}
if (newCapacity > capacity) {
// allocate more space
char *newBuf = new char[newCapacity];
memmove(newBuf, first, len);
delete buf;
buf = newBuf;
capacity = newCapacity;
} else {
// shift any existing data to make space
memmove(buf, first, len);
}
first = buf;
}
char *writePtr = first + len;
len += (int)size;
return writePtr;
}
inline void chop(int size)
{
if (size >= len) {
clear();
} else {
len -= size;
}
}
inline void squeeze()
{
if (first != buf) {
memmove(buf, first, len);
first = buf;
}
size_t newCapacity = basicBlockSize;
while (newCapacity < size_t(len)) {
newCapacity *= 2;
}
if (newCapacity < capacity) {
char *tmp = static_cast<char *>(realloc(buf, newCapacity));
if (tmp) {
buf = tmp;
capacity = newCapacity;
}
}
}
inline QByteArray readAll()
{
char *f = first;
int l = len;
clear();
return QByteArray(f, l);
}
inline int readLine(char *target, int size)
{
int r = qMin(size, len);
char *eol = static_cast<char *>(memchr(first, '\n', r));
if (eol) {
r = 1 + (eol - first);
}
memcpy(target, first, r);
len -= r;
first += r;
return int(r);
}
inline bool canReadLine() const
{
return memchr(first, '\n', len);
}
private:
int len;
char *first;
char *buf;
size_t capacity;
size_t basicBlockSize;
};
class QWinEventNotifier;
class QReadWriteLock;
class QSocketNotifier;
class QextSerialPortPrivate
{
Q_DECLARE_PUBLIC(QextSerialPort)
public:
QextSerialPortPrivate(QextSerialPort *q);
~QextSerialPortPrivate();
enum DirtyFlagEnum {
DFE_BaudRate = 0x0001,
DFE_Parity = 0x0002,
DFE_StopBits = 0x0004,
DFE_DataBits = 0x0008,
DFE_Flow = 0x0010,
DFE_TimeOut = 0x0100,
DFE_ALL = 0x0fff,
DFE_Settings_Mask = 0x00ff //without TimeOut
};
mutable QReadWriteLock lock;
QString port;
PortSettings settings;
QextReadBuffer readBuffer;
int settingsDirtyFlags;
ulong lastErr;
QextSerialPort::QueryMode queryMode;
// platform specific members
#ifdef Q_OS_UNIX
int fd;
QSocketNotifier *readNotifier;
struct termios currentTermios;
struct termios oldTermios;
#elif (defined Q_OS_WIN)
HANDLE handle;
OVERLAPPED overlap;
COMMCONFIG commConfig;
COMMTIMEOUTS commTimeouts;
QWinEventNotifier *winEventNotifier;
DWORD eventMask;
QList<OVERLAPPED *> pendingWrites;
QReadWriteLock *bytesToWriteLock;
#endif
/*fill PortSettings*/
void setBaudRate(BaudRateType baudRate, bool update = true);
void setDataBits(DataBitsType dataBits, bool update = true);
void setParity(ParityType parity, bool update = true);
void setStopBits(StopBitsType stopbits, bool update = true);
void setFlowControl(FlowType flow, bool update = true);
void setTimeout(long millisec, bool update = true);
void setPortSettings(const PortSettings &settings, bool update = true);
void platformSpecificDestruct();
void platformSpecificInit();
void translateError(ulong error);
void updatePortSettings();
qint64 readData_sys(char *data, qint64 maxSize);
qint64 writeData_sys(const char *data, qint64 maxSize);
void setDtr_sys(bool set = true);
void setRts_sys(bool set = true);
bool open_sys(QIODevice::OpenMode mode);
bool close_sys();
bool flush_sys();
ulong lineStatus_sys();
qint64 bytesAvailable_sys() const;
#ifdef Q_OS_WIN
void _q_onWinEvent(HANDLE h);
#endif
void _q_canRead();
QextSerialPort *q_ptr;
};
#endif //_QEXTSERIALPORT_P_H_

@ -0,0 +1,559 @@
/****************************************************************************
** Copyright (c) 2000-2003 Wayne Roth
** Copyright (c) 2004-2007 Stefan Sander
** Copyright (c) 2007 Michal Policht
** Copyright (c) 2008 Brandon Fosdick
** Copyright (c) 2009-2010 Liam Staskawicz
** Copyright (c) 2011 Debao Zhang
** All right reserved.
** Web: http://code.google.com/p/qextserialport/
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "qextserialport.h"
#include "qextserialport_p.h"
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <QtCore/QMutexLocker>
#include <QtCore/QDebug>
#include <QtCore/QSocketNotifier>
void QextSerialPortPrivate::platformSpecificInit()
{
fd = 0;
readNotifier = 0;
}
/*!
Standard destructor.
*/
void QextSerialPortPrivate::platformSpecificDestruct()
{
}
static QString fullPortName(const QString &name)
{
if (name.startsWith(QLatin1Char('/'))) {
return name;
}
return QLatin1String("/dev/") + name;
}
bool QextSerialPortPrivate::open_sys(QIODevice::OpenMode mode)
{
Q_Q(QextSerialPort);
//note: linux 2.6.21 seems to ignore O_NDELAY flag
if ((fd = ::open(fullPortName(port).toLatin1() , O_RDWR | O_NOCTTY | O_NDELAY)) != -1) {
/*In the Private class, We can not call QIODevice::open()*/
q->setOpenMode(mode); // Flag the port as opened
::tcgetattr(fd, &oldTermios); // Save the old termios
currentTermios = oldTermios; // Make a working copy
::cfmakeraw(&currentTermios); // Enable raw access
/*set up other port settings*/
currentTermios.c_cflag |= CREAD | CLOCAL;
currentTermios.c_lflag &= (~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ISIG));
currentTermios.c_iflag &= (~(INPCK | IGNPAR | PARMRK | ISTRIP | ICRNL | IXANY));
currentTermios.c_oflag &= (~OPOST);
currentTermios.c_cc[VMIN] = 0;
#ifdef _POSIX_VDISABLE // Is a disable character available on this system?
// Some systems allow for per-device disable-characters, so get the
// proper value for the configured device
const long vdisable = ::fpathconf(fd, _PC_VDISABLE);
currentTermios.c_cc[VINTR] = vdisable;
currentTermios.c_cc[VQUIT] = vdisable;
currentTermios.c_cc[VSTART] = vdisable;
currentTermios.c_cc[VSTOP] = vdisable;
currentTermios.c_cc[VSUSP] = vdisable;
#endif //_POSIX_VDISABLE
settingsDirtyFlags = DFE_ALL;
updatePortSettings();
if (queryMode == QextSerialPort::EventDriven) {
readNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, q);
q->connect(readNotifier, SIGNAL(activated(int)), q, SLOT(_q_canRead()));
}
return true;
} else {
translateError(errno);
return false;
}
}
bool QextSerialPortPrivate::close_sys()
{
// Force a flush and then restore the original termios
flush_sys();
// Using both TCSAFLUSH and TCSANOW here discards any pending input
::tcsetattr(fd, TCSAFLUSH | TCSANOW, &oldTermios); // Restore termios
::close(fd);
if (readNotifier) {
delete readNotifier;
readNotifier = 0;
}
return true;
}
bool QextSerialPortPrivate::flush_sys()
{
::tcdrain(fd);
return true;
}
qint64 QextSerialPortPrivate::bytesAvailable_sys() const
{
int bytesQueued;
if (::ioctl(fd, FIONREAD, &bytesQueued) == -1) {
return (qint64) - 1;
}
return bytesQueued;
}
/*!
Translates a system-specific error code to a QextSerialPort error code. Used internally.
*/
void QextSerialPortPrivate::translateError(ulong error)
{
switch (error) {
case EBADF:
case ENOTTY:
lastErr = E_INVALID_FD;
break;
case EINTR:
lastErr = E_CAUGHT_NON_BLOCKED_SIGNAL;
break;
case ENOMEM:
lastErr = E_NO_MEMORY;
break;
case EACCES:
lastErr = E_PERMISSION_DENIED;
break;
case EAGAIN:
lastErr = E_AGAIN;
break;
}
}
void QextSerialPortPrivate::setDtr_sys(bool set)
{
int status;
::ioctl(fd, TIOCMGET, &status);
if (set) {
status |= TIOCM_DTR;
} else {
status &= ~TIOCM_DTR;
}
::ioctl(fd, TIOCMSET, &status);
}
void QextSerialPortPrivate::setRts_sys(bool set)
{
int status;
::ioctl(fd, TIOCMGET, &status);
if (set) {
status |= TIOCM_RTS;
} else {
status &= ~TIOCM_RTS;
}
::ioctl(fd, TIOCMSET, &status);
}
unsigned long QextSerialPortPrivate::lineStatus_sys()
{
unsigned long Status = 0, Temp = 0;
::ioctl(fd, TIOCMGET, &Temp);
if (Temp & TIOCM_CTS) {
Status |= LS_CTS;
}
if (Temp & TIOCM_DSR) {
Status |= LS_DSR;
}
if (Temp & TIOCM_RI) {
Status |= LS_RI;
}
if (Temp & TIOCM_CD) {
Status |= LS_DCD;
}
if (Temp & TIOCM_DTR) {
Status |= LS_DTR;
}
if (Temp & TIOCM_RTS) {
Status |= LS_RTS;
}
if (Temp & TIOCM_ST) {
Status |= LS_ST;
}
if (Temp & TIOCM_SR) {
Status |= LS_SR;
}
return Status;
}
/*!
Reads a block of data from the serial port. This function will read at most maxSize bytes from
the serial port and place them in the buffer pointed to by data. Return value is the number of
bytes actually read, or -1 on error.
\warning before calling this function ensure that serial port associated with this class
is currently open (use isOpen() function to check if port is open).
*/
qint64 QextSerialPortPrivate::readData_sys(char *data, qint64 maxSize)
{
int retVal = ::read(fd, data, maxSize);
if (retVal == -1) {
lastErr = E_READ_FAILED;
}
return retVal;
}
/*!
Writes a block of data to the serial port. This function will write maxSize bytes
from the buffer pointed to by data to the serial port. Return value is the number
of bytes actually written, or -1 on error.
\warning before calling this function ensure that serial port associated with this class
is currently open (use isOpen() function to check if port is open).
*/
qint64 QextSerialPortPrivate::writeData_sys(const char *data, qint64 maxSize)
{
int retVal = ::write(fd, data, maxSize);
if (retVal == -1) {
lastErr = E_WRITE_FAILED;
}
return (qint64)retVal;
}
static void setBaudRate2Termios(termios *config, int baudRate)
{
#ifdef CBAUD
config->c_cflag &= (~CBAUD);
config->c_cflag |= baudRate;
#else
::cfsetispeed(config, baudRate);
::cfsetospeed(config, baudRate);
#endif
}
/*
All the platform settings was performed in this function.
*/
void QextSerialPortPrivate::updatePortSettings()
{
if (!q_func()->isOpen() || !settingsDirtyFlags) {
return;
}
if (settingsDirtyFlags & DFE_BaudRate) {
switch (settings.BaudRate) {
case BAUD50:
setBaudRate2Termios(&currentTermios, B50);
break;
case BAUD75:
setBaudRate2Termios(&currentTermios, B75);
break;
case BAUD110:
setBaudRate2Termios(&currentTermios, B110);
break;
case BAUD134:
setBaudRate2Termios(&currentTermios, B134);
break;
case BAUD150:
setBaudRate2Termios(&currentTermios, B150);
break;
case BAUD200:
setBaudRate2Termios(&currentTermios, B200);
break;
case BAUD300:
setBaudRate2Termios(&currentTermios, B300);
break;
case BAUD600:
setBaudRate2Termios(&currentTermios, B600);
break;
case BAUD1200:
setBaudRate2Termios(&currentTermios, B1200);
break;
case BAUD1800:
setBaudRate2Termios(&currentTermios, B1800);
break;
case BAUD2400:
setBaudRate2Termios(&currentTermios, B2400);
break;
case BAUD4800:
setBaudRate2Termios(&currentTermios, B4800);
break;
case BAUD9600:
setBaudRate2Termios(&currentTermios, B9600);
break;
case BAUD19200:
setBaudRate2Termios(&currentTermios, B19200);
break;
case BAUD38400:
setBaudRate2Termios(&currentTermios, B38400);
break;
case BAUD57600:
setBaudRate2Termios(&currentTermios, B57600);
break;
#ifdef B76800
case BAUD76800:
setBaudRate2Termios(&currentTermios, B76800);
break;
#endif
case BAUD115200:
setBaudRate2Termios(&currentTermios, B115200);
break;
#if defined(B230400) && defined(B4000000)
case BAUD230400:
setBaudRate2Termios(&currentTermios, B230400);
break;
case BAUD460800:
setBaudRate2Termios(&currentTermios, B460800);
break;
case BAUD500000:
setBaudRate2Termios(&currentTermios, B500000);
break;
case BAUD576000:
setBaudRate2Termios(&currentTermios, B576000);
break;
case BAUD921600:
setBaudRate2Termios(&currentTermios, B921600);
break;
case BAUD1000000:
setBaudRate2Termios(&currentTermios, B1000000);
break;
case BAUD1152000:
setBaudRate2Termios(&currentTermios, B1152000);
break;
case BAUD1500000:
setBaudRate2Termios(&currentTermios, B1500000);
break;
case BAUD2000000:
setBaudRate2Termios(&currentTermios, B2000000);
break;
case BAUD2500000:
setBaudRate2Termios(&currentTermios, B2500000);
break;
case BAUD3000000:
setBaudRate2Termios(&currentTermios, B3000000);
break;
case BAUD3500000:
setBaudRate2Termios(&currentTermios, B3500000);
break;
case BAUD4000000:
setBaudRate2Termios(&currentTermios, B4000000);
break;
#endif
#ifdef Q_OS_MAC
default:
setBaudRate2Termios(&currentTermios, settings.BaudRate);
break;
#endif
}
}
if (settingsDirtyFlags & DFE_Parity) {
switch (settings.Parity) {
case PAR_SPACE:
/*space parity not directly supported - add an extra data bit to simulate it*/
settingsDirtyFlags |= DFE_DataBits;
break;
case PAR_NONE:
currentTermios.c_cflag &= (~PARENB);
break;
case PAR_EVEN:
currentTermios.c_cflag &= (~PARODD);
currentTermios.c_cflag |= PARENB;
break;
case PAR_ODD:
currentTermios.c_cflag |= (PARENB | PARODD);
break;
}
}
/*must after Parity settings*/
if (settingsDirtyFlags & DFE_DataBits) {
if (settings.Parity != PAR_SPACE) {
currentTermios.c_cflag &= (~CSIZE);
switch (settings.DataBits) {
case DATA_5:
currentTermios.c_cflag |= CS5;
break;
case DATA_6:
currentTermios.c_cflag |= CS6;
break;
case DATA_7:
currentTermios.c_cflag |= CS7;
break;
case DATA_8:
currentTermios.c_cflag |= CS8;
break;
}
} else {
/*space parity not directly supported - add an extra data bit to simulate it*/
currentTermios.c_cflag &= ~(PARENB | CSIZE);
switch (settings.DataBits) {
case DATA_5:
currentTermios.c_cflag |= CS6;
break;
case DATA_6:
currentTermios.c_cflag |= CS7;
break;
case DATA_7:
currentTermios.c_cflag |= CS8;
break;
case DATA_8:
/*this will never happen, put here to Suppress an warning*/
break;
}
}
}
if (settingsDirtyFlags & DFE_StopBits) {
switch (settings.StopBits) {
case STOP_1:
currentTermios.c_cflag &= (~CSTOPB);
break;
case STOP_2:
currentTermios.c_cflag |= CSTOPB;
break;
}
}
if (settingsDirtyFlags & DFE_Flow) {
switch (settings.FlowControl) {
case FLOW_OFF:
currentTermios.c_cflag &= (~CRTSCTS);
currentTermios.c_iflag &= (~(IXON | IXOFF | IXANY));
break;
case FLOW_XONXOFF:
/*software (XON/XOFF) flow control*/
currentTermios.c_cflag &= (~CRTSCTS);
currentTermios.c_iflag |= (IXON | IXOFF | IXANY);
break;
case FLOW_HARDWARE:
currentTermios.c_cflag |= CRTSCTS;
currentTermios.c_iflag &= (~(IXON | IXOFF | IXANY));
break;
}
}
/*if any thing in currentTermios changed, flush*/
if (settingsDirtyFlags & DFE_Settings_Mask) {
::tcsetattr(fd, TCSAFLUSH, &currentTermios);
}
if (settingsDirtyFlags & DFE_TimeOut) {
int millisec = settings.Timeout_Millisec;
if (millisec == -1) {
::fcntl(fd, F_SETFL, O_NDELAY);
} else {
//O_SYNC should enable blocking ::write()
//however this seems not working on Linux 2.6.21 (works on OpenBSD 4.2)
::fcntl(fd, F_SETFL, O_SYNC);
}
::tcgetattr(fd, &currentTermios);
currentTermios.c_cc[VTIME] = millisec / 100;
::tcsetattr(fd, TCSAFLUSH, &currentTermios);
}
settingsDirtyFlags = 0;
}

@ -0,0 +1,482 @@
/****************************************************************************
** Copyright (c) 2000-2003 Wayne Roth
** Copyright (c) 2004-2007 Stefan Sander
** Copyright (c) 2007 Michal Policht
** Copyright (c) 2008 Brandon Fosdick
** Copyright (c) 2009-2010 Liam Staskawicz
** Copyright (c) 2011 Debao Zhang
** All right reserved.
** Web: http://code.google.com/p/qextserialport/
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "qextserialport.h"
#include "qextserialport_p.h"
#include <QtCore/QThread>
#include <QtCore/QReadWriteLock>
#include <QtCore/QMutexLocker>
#include <QtCore/QDebug>
#include <QtCore/QMetaType>
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
#include <QtCore/QWinEventNotifier>
#else
#include <QtCore/private/qwineventnotifier_p.h>
#endif
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
#include <QtCore5Compat/QRegExp>
#else
#include <QtCore/QRegExp>
#endif
void QextSerialPortPrivate::platformSpecificInit()
{
handle = INVALID_HANDLE_VALUE;
ZeroMemory(&overlap, sizeof(OVERLAPPED));
overlap.hEvent = CreateEvent(NULL, true, false, NULL);
winEventNotifier = 0;
bytesToWriteLock = new QReadWriteLock;
}
void QextSerialPortPrivate::platformSpecificDestruct()
{
CloseHandle(overlap.hEvent);
delete bytesToWriteLock;
}
/*!
\internal
COM ports greater than 9 need \\.\ prepended
This is only need when open the port.
*/
static QString fullPortNameWin(const QString &name)
{
QRegExp rx(QLatin1String("^COM(\\d+)"));
QString fullName(name);
if (rx.indexIn(fullName) >= 0) {
fullName.prepend(QLatin1String("\\\\.\\"));
}
return fullName;
}
bool QextSerialPortPrivate::open_sys(QIODevice::OpenMode mode)
{
Q_Q(QextSerialPort);
DWORD confSize = sizeof(COMMCONFIG);
commConfig.dwSize = confSize;
DWORD dwFlagsAndAttributes = 0;
if (queryMode == QextSerialPort::EventDriven) {
dwFlagsAndAttributes += FILE_FLAG_OVERLAPPED;
}
/*open the port*/
handle = CreateFileW((wchar_t *)fullPortNameWin(port).utf16(), GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, dwFlagsAndAttributes, NULL);
if (handle != INVALID_HANDLE_VALUE) {
q->setOpenMode(mode);
/*configure port settings*/
GetCommConfig(handle, &commConfig, &confSize);
GetCommState(handle, &(commConfig.dcb));
/*set up parameters*/
commConfig.dcb.fBinary = TRUE;
commConfig.dcb.fInX = FALSE;
commConfig.dcb.fOutX = FALSE;
commConfig.dcb.fAbortOnError = FALSE;
commConfig.dcb.fNull = FALSE;
/* Dtr default to true. See Issue 122*/
commConfig.dcb.fDtrControl = TRUE;
/*flush all settings*/
settingsDirtyFlags = DFE_ALL;
updatePortSettings();
//init event driven approach
if (queryMode == QextSerialPort::EventDriven) {
if (!SetCommMask(handle, EV_TXEMPTY | EV_RXCHAR | EV_DSR)) {
QESP_WARNING() << "failed to set Comm Mask. Error code:" << GetLastError();
return false;
}
winEventNotifier = new QWinEventNotifier(overlap.hEvent, q);
qRegisterMetaType<HANDLE>("HANDLE");
q->connect(winEventNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_onWinEvent(HANDLE)), Qt::DirectConnection);
WaitCommEvent(handle, &eventMask, &overlap);
}
return true;
}
return false;
}
bool QextSerialPortPrivate::close_sys()
{
flush_sys();
CancelIo(handle);
if (CloseHandle(handle)) {
handle = INVALID_HANDLE_VALUE;
}
if (winEventNotifier) {
winEventNotifier->setEnabled(false);
winEventNotifier->deleteLater();
winEventNotifier = 0;
}
foreach (OVERLAPPED *o, pendingWrites) {
CloseHandle(o->hEvent);
delete o;
}
pendingWrites.clear();
return true;
}
bool QextSerialPortPrivate::flush_sys()
{
FlushFileBuffers(handle);
return true;
}
qint64 QextSerialPortPrivate::bytesAvailable_sys() const
{
DWORD Errors;
COMSTAT Status;
if (ClearCommError(handle, &Errors, &Status)) {
return Status.cbInQue;
}
return (qint64) - 1;
}
/*
Translates a system-specific error code to a QextSerialPort error code. Used internally.
*/
void QextSerialPortPrivate::translateError(ulong error)
{
if (error & CE_BREAK) {
lastErr = E_BREAK_CONDITION;
} else if (error & CE_FRAME) {
lastErr = E_FRAMING_ERROR;
} else if (error & CE_IOE) {
lastErr = E_IO_ERROR;
} else if (error & CE_MODE) {
lastErr = E_INVALID_FD;
} else if (error & CE_OVERRUN) {
lastErr = E_BUFFER_OVERRUN;
} else if (error & CE_RXPARITY) {
lastErr = E_RECEIVE_PARITY_ERROR;
} else if (error & CE_RXOVER) {
lastErr = E_RECEIVE_OVERFLOW;
} else if (error & CE_TXFULL) {
lastErr = E_TRANSMIT_OVERFLOW;
}
}
/*
Reads a block of data from the serial port. This function will read at most maxlen bytes from
the serial port and place them in the buffer pointed to by data. Return value is the number of
bytes actually read, or -1 on error.
\warning before calling this function ensure that serial port associated with this class
is currently open (use isOpen() function to check if port is open).
*/
qint64 QextSerialPortPrivate::readData_sys(char *data, qint64 maxSize)
{
DWORD bytesRead = 0;
bool failed = false;
if (queryMode == QextSerialPort::EventDriven) {
OVERLAPPED overlapRead;
ZeroMemory(&overlapRead, sizeof(OVERLAPPED));
if (!ReadFile(handle, (void *)data, (DWORD)maxSize, &bytesRead, &overlapRead)) {
if (GetLastError() == ERROR_IO_PENDING) {
GetOverlappedResult(handle, &overlapRead, &bytesRead, true);
} else {
failed = true;
}
}
} else if (!ReadFile(handle, (void *)data, (DWORD)maxSize, &bytesRead, NULL)) {
failed = true;
}
if (!failed) {
return (qint64)bytesRead;
}
lastErr = E_READ_FAILED;
return -1;
}
/*
Writes a block of data to the serial port. This function will write len bytes
from the buffer pointed to by data to the serial port. Return value is the number
of bytes actually written, or -1 on error.
\warning before calling this function ensure that serial port associated with this class
is currently open (use isOpen() function to check if port is open).
*/
qint64 QextSerialPortPrivate::writeData_sys(const char *data, qint64 maxSize)
{
DWORD bytesWritten = 0;
bool failed = false;
if (queryMode == QextSerialPort::EventDriven) {
OVERLAPPED *newOverlapWrite = new OVERLAPPED;
ZeroMemory(newOverlapWrite, sizeof(OVERLAPPED));
newOverlapWrite->hEvent = CreateEvent(NULL, true, false, NULL);
if (WriteFile(handle, (void *)data, (DWORD)maxSize, &bytesWritten, newOverlapWrite)) {
CloseHandle(newOverlapWrite->hEvent);
delete newOverlapWrite;
} else if (GetLastError() == ERROR_IO_PENDING) {
// writing asynchronously...not an error
QWriteLocker writelocker(bytesToWriteLock);
pendingWrites.append(newOverlapWrite);
} else {
QESP_WARNING() << "QextSerialPort write error:" << GetLastError();
failed = true;
if (!CancelIo(newOverlapWrite->hEvent)) {
QESP_WARNING("QextSerialPort: couldn't cancel IO");
}
if (!CloseHandle(newOverlapWrite->hEvent)) {
QESP_WARNING("QextSerialPort: couldn't close OVERLAPPED handle");
}
delete newOverlapWrite;
}
} else if (!WriteFile(handle, (void *)data, (DWORD)maxSize, &bytesWritten, NULL)) {
failed = true;
}
if (!failed) {
return (qint64)bytesWritten;
}
lastErr = E_WRITE_FAILED;
return -1;
}
void QextSerialPortPrivate::setDtr_sys(bool set)
{
EscapeCommFunction(handle, set ? SETDTR : CLRDTR);
}
void QextSerialPortPrivate::setRts_sys(bool set)
{
EscapeCommFunction(handle, set ? SETRTS : CLRRTS);
}
ulong QextSerialPortPrivate::lineStatus_sys(void)
{
unsigned long Status = 0, Temp = 0;
GetCommModemStatus(handle, &Temp);
if (Temp & MS_CTS_ON) {
Status |= LS_CTS;
}
if (Temp & MS_DSR_ON) {
Status |= LS_DSR;
}
if (Temp & MS_RING_ON) {
Status |= LS_RI;
}
if (Temp & MS_RLSD_ON) {
Status |= LS_DCD;
}
return Status;
}
/*
Triggered when there's activity on our HANDLE.
*/
void QextSerialPortPrivate::_q_onWinEvent(HANDLE h)
{
Q_Q(QextSerialPort);
if (h == overlap.hEvent) {
if (eventMask & EV_RXCHAR) {
if (q->sender() != q && bytesAvailable_sys() > 0) {
_q_canRead();
}
}
if (eventMask & EV_TXEMPTY) {
/*
A write completed. Run through the list of OVERLAPPED writes, and if
they completed successfully, take them off the list and delete them.
Otherwise, leave them on there so they can finish.
*/
qint64 totalBytesWritten = 0;
QList<OVERLAPPED *> overlapsToDelete;
foreach (OVERLAPPED *o, pendingWrites) {
DWORD numBytes = 0;
if (GetOverlappedResult(handle, o, &numBytes, false)) {
overlapsToDelete.append(o);
totalBytesWritten += numBytes;
} else if (GetLastError() != ERROR_IO_INCOMPLETE) {
overlapsToDelete.append(o);
QESP_WARNING() << "CommEvent overlapped write error:" << GetLastError();
}
}
if (q->sender() != q && totalBytesWritten > 0) {
QWriteLocker writelocker(bytesToWriteLock);
Q_EMIT q->bytesWritten(totalBytesWritten);
}
foreach (OVERLAPPED *o, overlapsToDelete) {
OVERLAPPED *toDelete = pendingWrites.takeAt(pendingWrites.indexOf(o));
CloseHandle(toDelete->hEvent);
delete toDelete;
}
}
if (eventMask & EV_DSR) {
if (lineStatus_sys() & LS_DSR) {
Q_EMIT q->dsrChanged(true);
} else {
Q_EMIT q->dsrChanged(false);
}
}
}
WaitCommEvent(handle, &eventMask, &overlap);
}
void QextSerialPortPrivate::updatePortSettings()
{
if (!q_ptr->isOpen() || !settingsDirtyFlags) {
return;
}
//fill struct : COMMCONFIG
if (settingsDirtyFlags & DFE_BaudRate) {
commConfig.dcb.BaudRate = settings.BaudRate;
}
if (settingsDirtyFlags & DFE_Parity) {
commConfig.dcb.Parity = (BYTE)settings.Parity;
commConfig.dcb.fParity = (settings.Parity == PAR_NONE) ? FALSE : TRUE;
}
if (settingsDirtyFlags & DFE_DataBits) {
commConfig.dcb.ByteSize = (BYTE)settings.DataBits;
}
if (settingsDirtyFlags & DFE_StopBits) {
switch (settings.StopBits) {
case STOP_1:
commConfig.dcb.StopBits = ONESTOPBIT;
break;
case STOP_1_5:
commConfig.dcb.StopBits = ONE5STOPBITS;
break;
case STOP_2:
commConfig.dcb.StopBits = TWOSTOPBITS;
break;
}
}
if (settingsDirtyFlags & DFE_Flow) {
switch (settings.FlowControl) {
/*no flow control*/
case FLOW_OFF:
commConfig.dcb.fOutxCtsFlow = FALSE;
commConfig.dcb.fRtsControl = RTS_CONTROL_DISABLE;
commConfig.dcb.fInX = FALSE;
commConfig.dcb.fOutX = FALSE;
break;
/*software (XON/XOFF) flow control*/
case FLOW_XONXOFF:
commConfig.dcb.fOutxCtsFlow = FALSE;
commConfig.dcb.fRtsControl = RTS_CONTROL_DISABLE;
commConfig.dcb.fInX = TRUE;
commConfig.dcb.fOutX = TRUE;
break;
/*hardware flow control*/
case FLOW_HARDWARE:
commConfig.dcb.fOutxCtsFlow = TRUE;
commConfig.dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
commConfig.dcb.fInX = FALSE;
commConfig.dcb.fOutX = FALSE;
break;
}
}
//fill struct : COMMTIMEOUTS
if (settingsDirtyFlags & DFE_TimeOut) {
if (queryMode != QextSerialPort::EventDriven) {
int millisec = settings.Timeout_Millisec;
if (millisec == -1) {
commTimeouts.ReadIntervalTimeout = MAXDWORD;
commTimeouts.ReadTotalTimeoutConstant = 0;
} else {
commTimeouts.ReadIntervalTimeout = millisec;
commTimeouts.ReadTotalTimeoutConstant = millisec;
}
commTimeouts.ReadTotalTimeoutMultiplier = 0;
commTimeouts.WriteTotalTimeoutMultiplier = millisec;
commTimeouts.WriteTotalTimeoutConstant = 0;
} else {
commTimeouts.ReadIntervalTimeout = MAXDWORD;
commTimeouts.ReadTotalTimeoutMultiplier = 0;
commTimeouts.ReadTotalTimeoutConstant = 0;
commTimeouts.WriteTotalTimeoutMultiplier = 0;
commTimeouts.WriteTotalTimeoutConstant = 0;
}
}
if (settingsDirtyFlags & DFE_Settings_Mask) {
SetCommConfig(handle, &commConfig, sizeof(COMMCONFIG));
}
if ((settingsDirtyFlags & DFE_TimeOut)) {
SetCommTimeouts(handle, &commTimeouts);
}
settingsDirtyFlags = 0;
}

@ -0,0 +1,28 @@
HEADERS += \
$$PWD/emailaddress.h \
$$PWD/mimeattachment.h \
$$PWD/mimecontentformatter.h \
$$PWD/mimefile.h \
$$PWD/mimehtml.h \
$$PWD/mimeinlinefile.h \
$$PWD/mimemessage.h \
$$PWD/mimemultipart.h \
$$PWD/mimepart.h \
$$PWD/mimetext.h \
$$PWD/quotedprintable.h \
$$PWD/smtpclient.h \
$$PWD/smtpmime.h
SOURCES += \
$$PWD/emailaddress.cpp \
$$PWD/mimeattachment.cpp \
$$PWD/mimecontentformatter.cpp \
$$PWD/mimefile.cpp \
$$PWD/mimehtml.cpp \
$$PWD/mimeinlinefile.cpp \
$$PWD/mimemessage.cpp \
$$PWD/mimemultipart.cpp \
$$PWD/mimepart.cpp \
$$PWD/mimetext.cpp \
$$PWD/quotedprintable.cpp \
$$PWD/smtpclient.cpp

@ -0,0 +1,31 @@
#include "emailaddress.h"
EmailAddress::EmailAddress(const QString &address, const QString &name)
{
this->address = address;
this->name = name;
}
EmailAddress::~EmailAddress()
{
}
void EmailAddress::setName(const QString &name)
{
this->name = name;
}
void EmailAddress::setAddress(const QString &address)
{
this->address = address;
}
const QString &EmailAddress::getName() const
{
return name;
}
const QString &EmailAddress::getAddress() const
{
return address;
}

@ -0,0 +1,25 @@
#ifndef EMAILADDRESS_H
#define EMAILADDRESS_H
#include <QObject>
class EmailAddress : public QObject
{
Q_OBJECT
public:
EmailAddress(const QString &address, const QString &name = "");
~EmailAddress();
void setName(const QString &name);
void setAddress(const QString &address);
const QString &getName() const;
const QString &getAddress() const;
private:
QString name;
QString address;
};
#endif // EMAILADDRESS_H

@ -0,0 +1,17 @@
#include "mimeattachment.h"
#include <QFileInfo>
MimeAttachment::MimeAttachment(QFile *file)
: MimeFile(file)
{
}
MimeAttachment::~MimeAttachment()
{
}
void MimeAttachment::prepare()
{
this->header += "Content-disposition: attachment\r\n";
MimeFile::prepare();
}

@ -0,0 +1,20 @@
#ifndef MIMEATTACHMENT_H
#define MIMEATTACHMENT_H
#include <QFile>
#include "mimepart.h"
#include "mimefile.h"
class MimeAttachment : public MimeFile
{
Q_OBJECT
public:
MimeAttachment(QFile *file);
~MimeAttachment();
protected:
virtual void prepare();
};
#endif // MIMEATTACHMENT_H

@ -0,0 +1,51 @@
#include "mimecontentformatter.h"
MimeContentFormatter::MimeContentFormatter(int max_length) :
max_length(max_length)
{}
QString MimeContentFormatter::format(const QString &content, bool quotedPrintable) const
{
QString out;
int chars = 0;
for (int i = 0; i < content.length() ; ++i) {
chars++;
if (!quotedPrintable) {
if (chars > max_length) {
out.append("\r\n");
chars = 1;
}
} else {
if (content.at(i) == '\n') { // new line
out.append(content.at(i));
chars = 0;
continue;
}
if ((chars > max_length - 1)
|| ((content.at(i) == '=') && (chars > max_length - 3))) {
out.append('=');
out.append("\r\n");
chars = 1;
}
}
out.append(content.at(i));
}
return out;
}
void MimeContentFormatter::setMaxLength(int l)
{
max_length = l;
}
int MimeContentFormatter::getMaxLength() const
{
return max_length;
}

@ -0,0 +1,23 @@
#ifndef MIMECONTENTFORMATTER_H
#define MIMECONTENTFORMATTER_H
#include <QObject>
#include <QByteArray>
class MimeContentFormatter : public QObject
{
Q_OBJECT
public:
MimeContentFormatter(int max_length = 76);
void setMaxLength(int l);
int getMaxLength() const;
QString format(const QString &content, bool quotedPrintable = false) const;
protected:
int max_length;
};
#endif // MIMECONTENTFORMATTER_H

@ -0,0 +1,23 @@
#include "mimefile.h"
#include <QFileInfo>
MimeFile::MimeFile(QFile *file)
{
this->file = file;
this->cType = "application/octet-stream";
this->cName = QFileInfo(*file).fileName();
this->cEncoding = Base64;
}
MimeFile::~MimeFile()
{
delete file;
}
void MimeFile::prepare()
{
file->open(QIODevice::ReadOnly);
this->content = file->readAll();
file->close();
MimePart::prepare();
}

@ -0,0 +1,21 @@
#ifndef MIMEFILE_H
#define MIMEFILE_H
#include "mimepart.h"
#include <QFile>
class MimeFile : public MimePart
{
Q_OBJECT
public:
MimeFile(QFile *f);
~MimeFile();
protected:
QFile *file;
virtual void prepare();
};
#endif // MIMEFILE_H

@ -0,0 +1,23 @@
#include "mimehtml.h"
MimeHtml::MimeHtml(const QString &html) : MimeText(html)
{
this->cType = "text/html";
}
MimeHtml::~MimeHtml() {}
void MimeHtml::setHtml(const QString &html)
{
this->text = html;
}
const QString &MimeHtml::getHtml() const
{
return text;
}
void MimeHtml::prepare()
{
MimeText::prepare();
}

@ -0,0 +1,21 @@
#ifndef MIMEHTML_H
#define MIMEHTML_H
#include "mimetext.h"
class MimeHtml : public MimeText
{
Q_OBJECT
public:
MimeHtml(const QString &html = "");
~MimeHtml();
void setHtml(const QString &html);
const QString &getHtml() const;
protected:
virtual void prepare();
};
#endif // MIMEHTML_H

@ -0,0 +1,15 @@
#include "mimeinlinefile.h"
MimeInlineFile::MimeInlineFile(QFile *f)
: MimeFile(f)
{
}
MimeInlineFile::~MimeInlineFile()
{}
void MimeInlineFile::prepare()
{
this->header += "Content-Disposition: inline\r\n";
MimeFile::prepare();
}

@ -0,0 +1,18 @@
#ifndef MIMEINLINEFILE_H
#define MIMEINLINEFILE_H
#include "mimefile.h"
class MimeInlineFile : public MimeFile
{
public:
MimeInlineFile(QFile *f);
~MimeInlineFile();
protected:
virtual void prepare();
};
#endif // MIMEINLINEFILE_H

@ -0,0 +1,223 @@
#include "mimemessage.h"
#include <QDateTime>
#include "quotedprintable.h"
#include <typeinfo>
MimeMessage::MimeMessage(bool createAutoMimeContent) :
hEncoding(MimePart::_8Bit)
{
if (createAutoMimeContent) {
this->content = new MimeMultiPart();
}
}
MimeMessage::~MimeMessage()
{
}
MimePart &MimeMessage::getContent()
{
return *content;
}
void MimeMessage::setContent(MimePart *content)
{
this->content = content;
}
void MimeMessage::setSender(EmailAddress *e)
{
this->sender = e;
}
void MimeMessage::addRecipient(EmailAddress *rcpt, RecipientType type)
{
switch (type) {
case To:
recipientsTo << rcpt;
break;
case Cc:
recipientsCc << rcpt;
break;
case Bcc:
recipientsBcc << rcpt;
break;
}
}
void MimeMessage::addTo(EmailAddress *rcpt)
{
this->recipientsTo << rcpt;
}
void MimeMessage::addCc(EmailAddress *rcpt)
{
this->recipientsCc << rcpt;
}
void MimeMessage::addBcc(EmailAddress *rcpt)
{
this->recipientsBcc << rcpt;
}
void MimeMessage::setSubject(const QString &subject)
{
this->subject = subject;
}
void MimeMessage::addPart(MimePart *part)
{
if (typeid(*content) == typeid(MimeMultiPart)) {
((MimeMultiPart *) content)->addPart(part);
};
}
void MimeMessage::setHeaderEncoding(MimePart::Encoding hEnc)
{
this->hEncoding = hEnc;
}
const EmailAddress &MimeMessage::getSender() const
{
return *sender;
}
const QList<EmailAddress *> &MimeMessage::getRecipients(RecipientType type) const
{
switch (type) {
default:
case To:
return recipientsTo;
case Cc:
return recipientsCc;
case Bcc:
return recipientsBcc;
}
}
const QString &MimeMessage::getSubject() const
{
return subject;
}
const QList<MimePart *> &MimeMessage::getParts() const
{
if (typeid(*content) == typeid(MimeMultiPart)) {
return ((MimeMultiPart *) content)->getParts();
} else {
QList<MimePart *> *res = new QList<MimePart *>();
res->append(content);
return *res;
}
}
QString MimeMessage::toString()
{
QString mime;
mime = "From:";
QByteArray name = sender->getName().toUtf8();
if (name != "") {
switch (hEncoding) {
case MimePart::Base64:
mime += " =?utf-8?B?" + QByteArray().append(name).toBase64() + "?=";
break;
case MimePart::QuotedPrintable:
mime += " =?utf-8?Q?" + QuotedPrintable::encode(QByteArray().append(name)).replace(' ', "_").replace(':', "=3A") + "?=";
break;
default:
mime += " " + name;
}
}
mime += " <" + sender->getAddress() + ">\r\n";
mime += "To:";
QList<EmailAddress *>::iterator it;
int i;
for (i = 0, it = recipientsTo.begin(); it != recipientsTo.end(); ++it, ++i) {
if (i != 0) {
mime += ",";
}
QByteArray name = (*it)->getName().toUtf8();
if (name != "") {
switch (hEncoding) {
case MimePart::Base64:
mime += " =?utf-8?B?" + QByteArray().append(name).toBase64() + "?=";
break;
case MimePart::QuotedPrintable:
mime += " =?utf-8?Q?" + QuotedPrintable::encode(QByteArray().append(name)).replace(' ', "_").replace(':', "=3A") + "?=";
break;
default:
mime += " " + name;
}
}
mime += " <" + (*it)->getAddress() + ">";
}
mime += "\r\n";
if (recipientsCc.size() != 0) {
mime += "Cc:";
}
for (i = 0, it = recipientsCc.begin(); it != recipientsCc.end(); ++it, ++i) {
if (i != 0) {
mime += ",";
}
QByteArray name = (*it)->getName().toUtf8();
if (name != "") {
switch (hEncoding) {
case MimePart::Base64:
mime += " =?utf-8?B?" + QByteArray().append(name).toBase64() + "?=";
break;
case MimePart::QuotedPrintable:
mime += " =?utf-8?Q?" + QuotedPrintable::encode(QByteArray().append(name)).replace(' ', "_").replace(':', "=3A") + "?=";
break;
default:
mime += " " + name;
}
}
mime += " <" + (*it)->getAddress() + ">";
}
if (recipientsCc.size() != 0) {
mime += "\r\n";
}
mime += "Subject: ";
switch (hEncoding) {
case MimePart::Base64:
mime += "=?utf-8?B?" + QByteArray().append(subject.toUtf8()).toBase64() + "?=";
break;
case MimePart::QuotedPrintable:
mime += "=?utf-8?Q?" + QuotedPrintable::encode(QByteArray().append(subject.toUtf8())).replace(' ', "_").replace(':', "=3A") + "?=";
break;
default:
mime += subject;
}
mime += "\r\n";
mime += "MIME-Version: 1.0\r\n";
mime += content->toString();
return mime;
}

@ -0,0 +1,54 @@
#ifndef MIMEMESSAGE_H
#define MIMEMESSAGE_H
#include "mimepart.h"
#include "mimemultipart.h"
#include "emailaddress.h"
#include <QList>
class MimeMessage : public QObject
{
public:
enum RecipientType {
To, // primary
Cc, // carbon copy
Bcc // blind carbon copy
};
MimeMessage(bool createAutoMimeConent = true);
~MimeMessage();
void setSender(EmailAddress *e);
void addRecipient(EmailAddress *rcpt, RecipientType type = To);
void addTo(EmailAddress *rcpt);
void addCc(EmailAddress *rcpt);
void addBcc(EmailAddress *rcpt);
void setSubject(const QString &subject);
void addPart(MimePart *part);
void setHeaderEncoding(MimePart::Encoding);
const EmailAddress &getSender() const;
const QList<EmailAddress *> &getRecipients(RecipientType type = To) const;
const QString &getSubject() const;
const QList<MimePart *> &getParts() const;
MimePart &getContent();
void setContent(MimePart *content);
virtual QString toString();
protected:
EmailAddress *sender;
QList<EmailAddress *> recipientsTo, recipientsCc, recipientsBcc;
QString subject;
MimePart *content;
MimePart::Encoding hEncoding;
};
#endif // MIMEMESSAGE_H

@ -0,0 +1,66 @@
#include "mimemultipart.h"
#include "stdlib.h"
#include <QTime>
#include <QCryptographicHash>
const QString MULTI_PART_NAMES[] = {
"multipart/mixed", // Mixed
"multipart/digest", // Digest
"multipart/alternative", // Alternative
"multipart/related", // Related
"multipart/report", // Report
"multipart/signed", // Signed
"multipart/encrypted" // Encrypted
};
MimeMultiPart::MimeMultiPart(MultiPartType type)
{
this->type = type;
this->cType = MULTI_PART_NAMES[this->type];
this->cEncoding = _8Bit;
QCryptographicHash md5(QCryptographicHash::Md5);
md5.addData(QByteArray().append(rand()));
cBoundary = md5.result().toHex();
}
MimeMultiPart::~MimeMultiPart()
{
}
void MimeMultiPart::addPart(MimePart *part)
{
parts.append(part);
}
const QList<MimePart *> &MimeMultiPart::getParts() const
{
return parts;
}
void MimeMultiPart::prepare()
{
QList<MimePart *>::iterator it;
content = "";
for (it = parts.begin(); it != parts.end(); it++) {
content += "--" + cBoundary.toUtf8() + "\r\n";
(*it)->prepare();
content += (*it)->toString().toUtf8();
};
content += "--" + cBoundary.toUtf8() + "--\r\n";
MimePart::prepare();
}
void MimeMultiPart::setMimeType(const MultiPartType type)
{
this->type = type;
this->cType = MULTI_PART_NAMES[type];
}
MimeMultiPart::MultiPartType MimeMultiPart::getMimeType() const
{
return type;
}

@ -0,0 +1,37 @@
#ifndef MIMEMULTIPART_H
#define MIMEMULTIPART_H
#include "mimepart.h"
class MimeMultiPart : public MimePart
{
Q_OBJECT
public:
enum MultiPartType {
Mixed = 0, // RFC 2046, section 5.1.3
Digest = 1, // RFC 2046, section 5.1.5
Alternative = 2, // RFC 2046, section 5.1.4
Related = 3, // RFC 2387
Report = 4, // RFC 6522
Signed = 5, // RFC 1847, section 2.1
Encrypted = 6 // RFC 1847, section 2.2
};
MimeMultiPart(const MultiPartType type = Related);
~MimeMultiPart();
void setMimeType(const MultiPartType type);
MultiPartType getMimeType() const;
const QList<MimePart *> &getParts() const;
void addPart(MimePart *part);
virtual void prepare();
protected:
QList<MimePart *> parts;
MultiPartType type;
};
#endif // MIMEMULTIPART_H

@ -0,0 +1,171 @@
#include "mimepart.h"
#include "quotedprintable.h"
MimePart::MimePart()
{
cEncoding = _7Bit;
prepared = false;
cBoundary = "";
}
MimePart::~MimePart()
{
return;
}
void MimePart::setContent(const QByteArray &content)
{
this->content = content;
}
void MimePart::setHeader(const QString &header)
{
this->header = header;
}
void MimePart::addHeaderLine(const QString &line)
{
this->header += line + "\r\n";
}
const QString &MimePart::getHeader() const
{
return header;
}
const QByteArray &MimePart::getContent() const
{
return content;
}
void MimePart::setContentId(const QString &cId)
{
this->cId = cId;
}
const QString &MimePart::getContentId() const
{
return this->cId;
}
void MimePart::setContentName(const QString &cName)
{
this->cName = cName;
}
const QString &MimePart::getContentName() const
{
return this->cName;
}
void MimePart::setContentType(const QString &cType)
{
this->cType = cType;
}
const QString &MimePart::getContentType() const
{
return this->cType;
}
void MimePart::setCharset(const QString &charset)
{
this->cCharset = charset;
}
const QString &MimePart::getCharset() const
{
return this->cCharset;
}
void MimePart::setEncoding(Encoding enc)
{
this->cEncoding = enc;
}
MimePart::Encoding MimePart::getEncoding() const
{
return this->cEncoding;
}
MimeContentFormatter &MimePart::getContentFormatter()
{
return this->formatter;
}
QString MimePart::toString()
{
if (!prepared) {
prepare();
}
return mimeString;
}
void MimePart::prepare()
{
mimeString = QString();
mimeString.append("Content-Type: ").append(cType);
if (cName != "") {
mimeString.append("; name=\"").append(cName).append("\"");
}
if (cCharset != "") {
mimeString.append("; charset=").append(cCharset);
}
if (cBoundary != "") {
mimeString.append("; boundary=").append(cBoundary);
}
mimeString.append("\r\n");
mimeString.append("Content-Transfer-Encoding: ");
switch (cEncoding) {
case _7Bit:
mimeString.append("7bit\r\n");
break;
case _8Bit:
mimeString.append("8bit\r\n");
break;
case Base64:
mimeString.append("base64\r\n");
break;
case QuotedPrintable:
mimeString.append("quoted-printable\r\n");
break;
}
if (cId.toInt() != 0) {
mimeString.append("Content-ID: <").append(cId).append(">\r\n");
}
mimeString.append(header).append("\r\n");
switch (cEncoding) {
case _7Bit:
mimeString.append(QString(content).toLatin1());
break;
case _8Bit:
mimeString.append(content);
break;
case Base64:
mimeString.append(formatter.format(content.toBase64()));
break;
case QuotedPrintable:
mimeString.append(formatter.format(QuotedPrintable::encode(content), true));
break;
}
mimeString.append("\r\n");
prepared = true;
}

@ -0,0 +1,67 @@
#ifndef MIMEPART_H
#define MIMEPART_H
#include <QObject>
#include "mimecontentformatter.h"
class MimePart : public QObject
{
Q_OBJECT
public:
enum Encoding {
_7Bit,
_8Bit,
Base64,
QuotedPrintable
};
MimePart();
~MimePart();
const QString &getHeader() const;
const QByteArray &getContent() const;
void setContent(const QByteArray &content);
void setHeader(const QString &header);
void addHeaderLine(const QString &line);
void setContentId(const QString &cId);
const QString &getContentId() const;
void setContentName(const QString &cName);
const QString &getContentName() const;
void setContentType(const QString &cType);
const QString &getContentType() const;
void setCharset(const QString &charset);
const QString &getCharset() const;
void setEncoding(Encoding enc);
Encoding getEncoding() const;
MimeContentFormatter &getContentFormatter();
virtual QString toString();
virtual void prepare();
protected:
QString header;
QByteArray content;
QString cId;
QString cName;
QString cType;
QString cCharset;
QString cBoundary;
Encoding cEncoding;
QString mimeString;
bool prepared;
MimeContentFormatter formatter;
};
#endif // MIMEPART_H

@ -0,0 +1,28 @@
#include "mimetext.h"
MimeText::MimeText(const QString &txt)
{
this->text = txt;
this->cType = "text/plain";
this->cCharset = "utf-8";
this->cEncoding = _8Bit;
}
MimeText::~MimeText() { }
void MimeText::setText(const QString &text)
{
this->text = text;
}
const QString &MimeText::getText() const
{
return text;
}
void MimeText::prepare()
{
this->content.clear();
this->content.append(text.toUtf8());
MimePart::prepare();
}

@ -0,0 +1,22 @@
#ifndef MIMETEXT_H
#define MIMETEXT_H
#include "mimepart.h"
class MimeText : public MimePart
{
public:
MimeText(const QString &text = "");
~MimeText();
void setText(const QString &text);
const QString &getText() const;
protected:
QString text;
void prepare();
};
#endif // MIMETEXT_H

@ -0,0 +1,43 @@
#include "quotedprintable.h"
QString &QuotedPrintable::encode(const QByteArray &input)
{
QString *output = new QString();
char byte;
const char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
for (int i = 0; i < input.length() ; ++i) {
byte = input.at(i);
if ((byte == 0x20) || ((byte >= 33) && (byte <= 126) && (byte != 61))) {
output->append(byte);
} else {
output->append('=');
output->append(hex[((byte >> 4) & 0x0F)]);
output->append(hex[(byte & 0x0F)]);
}
}
return *output;
}
QByteArray &QuotedPrintable::decode(const QString &input)
{
// 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F
const int hexVal[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15};
QByteArray *output = new QByteArray();
for (int i = 0; i < input.length(); ++i) {
if (input.at(i).toLatin1() == '=') {
int index = ++i;
output->append((hexVal[input.at(index).toLatin1() - '0'] << 4) + hexVal[input.at(++i).toLatin1() - '0']);
} else {
output->append(input.at(i).toLatin1());
}
}
return *output;
}

@ -0,0 +1,19 @@
#ifndef QUOTEDPRINTABLE_H
#define QUOTEDPRINTABLE_H
#include <QObject>
#include <QByteArray>
class QuotedPrintable : public QObject
{
Q_OBJECT
public:
static QString &encode(const QByteArray &input);
static QByteArray &decode(const QString &input);
private:
QuotedPrintable();
};
#endif // QUOTEDPRINTABLE_H

@ -0,0 +1,390 @@
#include "smtpclient.h"
SmtpClient::SmtpClient(const QString &host, int port, ConnectionType connectionType) :
name("localhost"),
authMethod(AuthPlain),
connectionTimeout(5000),
responseTimeout(5000)
{
setConnectionType(connectionType);
this->host = host;
this->port = port;
}
SmtpClient::~SmtpClient() {}
void SmtpClient::setUser(const QString &user)
{
this->user = user;
}
void SmtpClient::setPassword(const QString &password)
{
this->password = password;
}
void SmtpClient::setAuthMethod(AuthMethod method)
{
this->authMethod = method;
}
void SmtpClient::setHost(QString &host)
{
this->host = host;
}
void SmtpClient::setPort(int port)
{
this->port = port;
}
void SmtpClient::setConnectionType(ConnectionType ct)
{
this->connectionType = ct;
switch (connectionType) {
case TcpConnection:
socket = new QTcpSocket(this);
break;
#ifdef ssl
case SslConnection:
case TlsConnection:
socket = new QSslSocket(this);
#endif
}
}
const QString &SmtpClient::getHost() const
{
return this->host;
}
const QString &SmtpClient::getUser() const
{
return this->user;
}
const QString &SmtpClient::getPassword() const
{
return this->password;
}
SmtpClient::AuthMethod SmtpClient::getAuthMethod() const
{
return this->authMethod;
}
int SmtpClient::getPort() const
{
return this->port;
}
SmtpClient::ConnectionType SmtpClient::getConnectionType() const
{
return connectionType;
}
const QString &SmtpClient::getName() const
{
return this->name;
}
void SmtpClient::setName(const QString &name)
{
this->name = name;
}
const QString &SmtpClient::getResponseText() const
{
return responseText;
}
int SmtpClient::getResponseCode() const
{
return responseCode;
}
QTcpSocket *SmtpClient::getSocket()
{
return socket;
}
int SmtpClient::getConnectionTimeout() const
{
return connectionTimeout;
}
void SmtpClient::setConnectionTimeout(int msec)
{
connectionTimeout = msec;
}
int SmtpClient::getResponseTimeout() const
{
return responseTimeout;
}
void SmtpClient::setResponseTimeout(int msec)
{
responseTimeout = msec;
}
bool SmtpClient::connectToHost()
{
switch (connectionType) {
case TlsConnection:
case TcpConnection:
socket->connectToHost(host, port);
break;
#ifdef ssl
case SslConnection:
((QSslSocket *) socket)->connectToHostEncrypted(host, port);
break;
#endif
}
if (!socket->waitForConnected(connectionTimeout)) {
emit smtpError(ConnectionTimeoutError);
return false;
}
try {
// Wait for the server's response
waitForResponse();
// If the response code is not 220 (Service ready)
// means that is something wrong with the server
if (responseCode != 220) {
emit smtpError(ServerError);
return false;
}
// Send a EHLO/HELO message to the server
// The client's first command must be EHLO/HELO
sendMessage("EHLO " + name);
// Wait for the server's response
waitForResponse();
// The response code needs to be 250.
if (responseCode != 250) {
emit smtpError(ServerError);
return false;
}
if (connectionType == TlsConnection) {
// send a request to start TLS handshake
sendMessage("STARTTLS");
// Wait for the server's response
waitForResponse();
// The response code needs to be 220.
if (responseCode != 220) {
emit smtpError(ServerError);
return false;
};
#ifdef ssl
((QSslSocket *) socket)->startClientEncryption();
if (!((QSslSocket *) socket)->waitForEncrypted(connectionTimeout)) {
qDebug() << ((QSslSocket *) socket)->errorString();
emit smtpError(ConnectionTimeoutError);
return false;
}
#endif
// Send ELHO one more time
sendMessage("EHLO " + name);
// Wait for the server's response
waitForResponse();
// The response code needs to be 250.
if (responseCode != 250) {
emit smtpError(ServerError);
return false;
}
}
} catch (ResponseTimeoutException) {
return false;
}
return true;
}
bool SmtpClient::login()
{
return login(user, password, authMethod);
}
bool SmtpClient::login(const QString &user, const QString &password, AuthMethod method)
{
try {
if (method == AuthPlain) {
// Sending command: AUTH PLAIN base64('\0' + username + '\0' + password)
sendMessage("AUTH PLAIN " + QByteArray().append((char) 0).append(user.toUtf8()).append((char) 0).append(password.toUtf8()).toBase64());
// Wait for the server's response
waitForResponse();
// If the response is not 235 then the authentication was faild
if (responseCode != 235) {
emit smtpError(AuthenticationFailedError);
return false;
}
} else if (method == AuthLogin) {
// Sending command: AUTH LOGIN
sendMessage("AUTH LOGIN");
// Wait for 334 response code
waitForResponse();
if (responseCode != 334) {
emit smtpError(AuthenticationFailedError);
return false;
}
// Send the username in base64
sendMessage(QByteArray().append(user.toUtf8()).toBase64());
// Wait for 334
waitForResponse();
if (responseCode != 334) {
emit smtpError(AuthenticationFailedError);
return false;
}
// Send the password in base64
sendMessage(QByteArray().append(password.toUtf8()).toBase64());
// Wait for the server's responce
waitForResponse();
// If the response is not 235 then the authentication was faild
if (responseCode != 235) {
emit smtpError(AuthenticationFailedError);
return false;
}
}
} catch (ResponseTimeoutException e) {
// Responce Timeout exceeded
emit smtpError(AuthenticationFailedError);
return false;
}
return true;
}
bool SmtpClient::sendMail(MimeMessage &email)
{
try {
// Send the MAIL command with the sender
sendMessage("MAIL FROM: <" + email.getSender().getAddress() + ">");
waitForResponse();
if (responseCode != 250) {
return false;
}
// Send RCPT command for each recipient
QList<EmailAddress *>::const_iterator it, itEnd;
// To (primary recipients)
for (it = email.getRecipients().begin(), itEnd = email.getRecipients().end();
it != itEnd; ++it) {
sendMessage("RCPT TO: <" + (*it)->getAddress() + ">");
waitForResponse();
if (responseCode != 250) {
return false;
}
}
// Cc (carbon copy)
for (it = email.getRecipients(MimeMessage::Cc).begin(), itEnd = email.getRecipients(MimeMessage::Cc).end();
it != itEnd; ++it) {
sendMessage("RCPT TO: <" + (*it)->getAddress() + ">");
waitForResponse();
if (responseCode != 250) {
return false;
}
}
// Bcc (blind carbon copy)
for (it = email.getRecipients(MimeMessage::Bcc).begin(), itEnd = email.getRecipients(MimeMessage::Bcc).end();
it != itEnd; ++it) {
sendMessage("RCPT TO: <" + (*it)->getAddress() + ">");
waitForResponse();
if (responseCode != 250) {
return false;
}
}
// Send DATA command
sendMessage("DATA");
waitForResponse();
if (responseCode != 354) {
return false;
}
sendMessage(email.toString());
// Send \r\n.\r\n to end the mail data
sendMessage(".");
waitForResponse();
if (responseCode != 250) {
return false;
}
} catch (ResponseTimeoutException) {
return false;
}
return true;
}
void SmtpClient::quit()
{
sendMessage("QUIT");
}
void SmtpClient::waitForResponse()
{
do {
if (!socket->waitForReadyRead(responseTimeout)) {
emit smtpError(ResponseTimeoutError);
throw ResponseTimeoutException();
}
while (socket->canReadLine()) {
// Save the server's response
responseText = socket->readLine();
// Extract the respose code from the server's responce (first 3 digits)
responseCode = responseText.left(3).toInt();
if (responseCode / 100 == 4) {
emit smtpError(ServerError);
}
if (responseCode / 100 == 5) {
emit smtpError(ClientError);
}
if (responseText.at(3) == ' ') {
return;
}
}
} while (true);
}
void SmtpClient::sendMessage(const QString &text)
{
socket->write(text.toUtf8() + "\r\n");
}

@ -0,0 +1,103 @@
#ifndef SMTPCLIENT_H
#define SMTPCLIENT_H
#include <QtGui>
#include <QtNetwork>
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
#include <QtWidgets>
#endif
#include "mimemessage.h"
class SmtpClient : public QObject
{
Q_OBJECT
public:
enum AuthMethod {
AuthPlain,
AuthLogin
};
enum SmtpError {
ConnectionTimeoutError,
ResponseTimeoutError,
AuthenticationFailedError,
ServerError, // 4xx smtp error
ClientError // 5xx smtp error
};
enum ConnectionType {
TcpConnection,
SslConnection,
TlsConnection // STARTTLS
};
SmtpClient(const QString &host = "locahost", int port = 25, ConnectionType ct = TcpConnection);
~SmtpClient();
const QString &getHost() const;
void setHost(QString &host);
int getPort() const;
void setPort(int port);
const QString &getName() const;
void setName(const QString &name);
ConnectionType getConnectionType() const;
void setConnectionType(ConnectionType ct);
const QString &getUser() const;
void setUser(const QString &host);
const QString &getPassword() const;
void setPassword(const QString &password);
SmtpClient::AuthMethod getAuthMethod() const;
void setAuthMethod(AuthMethod method);
const QString &getResponseText() const;
int getResponseCode() const;
int getConnectionTimeout() const;
void setConnectionTimeout(int msec);
int getResponseTimeout() const;
void setResponseTimeout(int msec);
QTcpSocket *getSocket();
bool connectToHost();
bool login();
bool login(const QString &user, const QString &password, AuthMethod method = AuthLogin);
bool sendMail(MimeMessage &email);
void quit();
protected:
QTcpSocket *socket;
QString host;
int port;
ConnectionType connectionType;
QString name;
QString user;
QString password;
AuthMethod authMethod;
int connectionTimeout;
int responseTimeout;
QString responseText;
int responseCode;
class ResponseTimeoutException {};
void waitForResponse();
void sendMessage(const QString &text);
signals:
void smtpError(SmtpError e);
};
#endif // SMTPCLIENT_H

@ -0,0 +1,13 @@
#ifndef SMTPMIME_H
#define SMTPMIME_H
#include "smtpclient.h"
#include "mimepart.h"
#include "mimehtml.h"
#include "mimeattachment.h"
#include "mimemessage.h"
#include "mimetext.h"
#include "mimeinlinefile.h"
#include "mimefile.h"
#endif // SMTPMIME_H

@ -0,0 +1,41 @@
#include "base64helper.h"
#include "qbuffer.h"
#include "qdebug.h"
QString Base64Helper::imageToBase64(const QImage &image)
{
return QString(imageToBase64x(image));
}
QByteArray Base64Helper::imageToBase64x(const QImage &image)
{
//这个转换可能比较耗时建议在线程中执行
QByteArray data;
QBuffer buffer(&data);
image.save(&buffer, "JPG");
data = data.toBase64();
return data;
}
QImage Base64Helper::base64ToImage(const QString &data)
{
return base64ToImagex(data.toUtf8());
}
QImage Base64Helper::base64ToImagex(const QByteArray &data)
{
//这个转换可能比较耗时建议在线程中执行
QImage image;
image.loadFromData(QByteArray::fromBase64(data));
return image;
}
QString Base64Helper::textToBase64(const QString &text)
{
return QString(text.toUtf8().toBase64());
}
QString Base64Helper::base64ToText(const QString &text)
{
return QString(QByteArray::fromBase64(text.toUtf8()));
}

@ -0,0 +1,37 @@
#ifndef BASE64HELPER_H
#define BASE64HELPER_H
/**
* base64 :feiyangqingyun(QQ:517216493) 2016-12-16
* 1. base64
* 2. base64
* 3. base64
* 4. base64
* 5.
* 6. Qt6base64200%
*/
#include <QImage>
#ifdef quc
class Q_DECL_EXPORT Base64Helper
#else
class Base64Helper
#endif
{
public:
//图片转base64字符串
static QString imageToBase64(const QImage &image);
static QByteArray imageToBase64x(const QImage &image);
//base64字符串转图片
static QImage base64ToImage(const QString &data);
static QImage base64ToImagex(const QByteArray &data);
//字符串与base64互转
static QString textToBase64(const QString &text);
static QString base64ToText(const QString &text);
};
#endif // BASE64HELPER_H

@ -0,0 +1,19 @@
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
greaterThan(QT_MAJOR_VERSION, 5): QT += core5compat
TARGET = base64helper
TEMPLATE = app
DESTDIR = $$PWD/../bin
CONFIG += warn_off
SOURCES += main.cpp
SOURCES += frmbase64helper.cpp
SOURCES += base64helper.cpp
HEADERS += frmbase64helper.h
HEADERS += base64helper.h
FORMS += frmbase64helper.ui

@ -0,0 +1,104 @@
#pragma execution_character_set("utf-8")
#include "frmbase64helper.h"
#include "ui_frmbase64helper.h"
#include "base64helper.h"
#include "qfiledialog.h"
#include "qdebug.h"
frmBase64Helper::frmBase64Helper(QWidget *parent) : QWidget(parent), ui(new Ui::frmBase64Helper)
{
ui->setupUi(this);
}
frmBase64Helper::~frmBase64Helper()
{
delete ui;
}
void frmBase64Helper::showTime(qint64 size1, qint64 size2)
{
//统计用时
#if (QT_VERSION >= QT_VERSION_CHECK(4,8,0))
double elapsed = (double)timer.nsecsElapsed() / 1000000;
#else
double elapsed = (double)timer.elapsed();
#endif
QString time = QString::number(elapsed, 'f', 3);
ui->labInfo->setText(QString("用时: %1 毫秒 大小: %2 -> %3").arg(time).arg(size1).arg(size2));
}
void frmBase64Helper::on_btnOpen_clicked()
{
QString fileName = QFileDialog::getOpenFileName(this, "选择文件", "", "图片(*.png *.bmp *.jpg)");
if (!fileName.isEmpty()) {
ui->txtFile->setText(fileName);
QPixmap pix(fileName);
pix = pix.scaled(ui->labImage->size() - QSize(4, 4), Qt::KeepAspectRatio);
ui->labImage->setPixmap(pix);
}
}
void frmBase64Helper::on_btnClear_clicked()
{
ui->txtFile->clear();
ui->txtText->clear();
ui->txtBase64->clear();
ui->labImage->clear();
}
void frmBase64Helper::on_btnImageToBase64_clicked()
{
QString fileName = ui->txtFile->text().trimmed();
if (fileName.isEmpty()) {
return;
}
timer.restart();
QImage image(fileName);
QString text = Base64Helper::imageToBase64(image);
showTime(QFile(fileName).size(), text.size());
ui->txtBase64->setText(text);
}
void frmBase64Helper::on_btnBase64ToImage_clicked()
{
QString fileName = ui->txtFile->text().trimmed();
QString text = ui->txtBase64->toPlainText().trimmed();
if (text.isEmpty()) {
return;
}
timer.restart();
QImage image = Base64Helper::base64ToImage(text);
showTime(text.size(), QFile(fileName).size());
QPixmap pix = QPixmap::fromImage(image);
pix = pix.scaled(ui->labImage->size() - QSize(4, 4), Qt::KeepAspectRatio);
ui->labImage->setPixmap(pix);
}
void frmBase64Helper::on_btnTextToBase64_clicked()
{
QString text = ui->txtText->text().trimmed();
if (text.isEmpty()) {
return;
}
timer.restart();
QString result = Base64Helper::textToBase64(text);
showTime(text.size(), result.size());
ui->txtBase64->setText(result);
}
void frmBase64Helper::on_btnBase64ToText_clicked()
{
QString text = ui->txtBase64->toPlainText().trimmed();
if (text.isEmpty()) {
return;
}
timer.restart();
QString result = Base64Helper::base64ToText(text);
showTime(text.size(), result.size());
ui->txtText->setText(result);
}

@ -0,0 +1,35 @@
#ifndef FRMBASE64HELPER_H
#define FRMBASE64HELPER_H
#include <QWidget>
#include <QElapsedTimer>
namespace Ui {
class frmBase64Helper;
}
class frmBase64Helper : public QWidget
{
Q_OBJECT
public:
explicit frmBase64Helper(QWidget *parent = 0);
~frmBase64Helper();
private:
Ui::frmBase64Helper *ui;
QElapsedTimer timer;
private slots:
void showTime(qint64 size1, qint64 size2);
void on_btnOpen_clicked();
void on_btnClear_clicked();
void on_btnImageToBase64_clicked();
void on_btnBase64ToImage_clicked();
void on_btnTextToBase64_clicked();
void on_btnBase64ToText_clicked();
};
#endif // FRMBASE64HELPER_H

@ -0,0 +1,163 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>frmBase64Helper</class>
<widget class="QWidget" name="frmBase64Helper">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>Widget</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLineEdit" name="txtFile">
<property name="text">
<string>E:/myFile/美女图片/2.jpg</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="btnOpen">
<property name="minimumSize">
<size>
<width>120</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>打开文件</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="btnImageToBase64">
<property name="minimumSize">
<size>
<width>120</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>图片转base64</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="btnBase64ToImage">
<property name="minimumSize">
<size>
<width>120</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>base64转图片</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLineEdit" name="txtText">
<property name="text">
<string>游龙 feiyangqingyun QQ: 517216493</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="btnClear">
<property name="minimumSize">
<size>
<width>120</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>清空数据</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="btnTextToBase64">
<property name="minimumSize">
<size>
<width>120</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>文字转base64</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QPushButton" name="btnBase64ToText">
<property name="minimumSize">
<size>
<width>120</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>base64转文字</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labInfo">
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="3" column="0" colspan="4">
<widget class="QLabel" name="labImage">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="4" column="0" colspan="4">
<widget class="QTextEdit" name="txtBase64"/>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<tabstops>
<tabstop>txtFile</tabstop>
<tabstop>txtText</tabstop>
<tabstop>btnOpen</tabstop>
<tabstop>btnClear</tabstop>
<tabstop>btnImageToBase64</tabstop>
<tabstop>btnBase64ToImage</tabstop>
<tabstop>btnTextToBase64</tabstop>
<tabstop>btnBase64ToText</tabstop>
<tabstop>txtBase64</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

@ -0,0 +1,34 @@
#pragma execution_character_set("utf-8")
#include "frmbase64helper.h"
#include <QApplication>
#include <QTextCodec>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QFont font;
font.setFamily("Microsoft Yahei");
font.setPixelSize(13);
a.setFont(font);
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
QTextCodec *codec = QTextCodec::codecForName("gbk");
#else
QTextCodec *codec = QTextCodec::codecForName("utf-8");
#endif
QTextCodec::setCodecForLocale(codec);
QTextCodec::setCodecForCStrings(codec);
QTextCodec::setCodecForTr(codec);
#else
QTextCodec *codec = QTextCodec::codecForName("utf-8");
QTextCodec::setCodecForLocale(codec);
#endif
frmBase64Helper w;
w.setWindowTitle("图片文字base64编码互换 (QQ: 517216493 WX: feiyangqingyun)");
w.show();
return a.exec();
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -0,0 +1,22 @@
[ComConfig]
PortName=COM1
BaudRate=9600
DataBit=8
Parity=\x65e0
StopBit=1
HexSend=false
HexReceive=false
Debug=false
AutoClear=false
AutoSend=false
SendInterval=1000
AutoSave=false
SaveInterval=5000
[NetConfig]
Mode=Tcp_Client
ServerIP=127.0.0.1
ServerPort=6000
ListenPort=6000
SleepTime=100
AutoConnect=false

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -0,0 +1,11 @@
HEADERS += \
$$PWD/appconfig.h \
$$PWD/appdata.h \
$$PWD/qthelper.h \
$$PWD/qthelperdata.h
SOURCES += \
$$PWD/appconfig.cpp \
$$PWD/appdata.cpp \
$$PWD/qthelper.cpp \
$$PWD/qthelperdata.cpp

@ -0,0 +1,99 @@
#include "appconfig.h"
#include "qthelper.h"
QString AppConfig::ConfigFile = "config.ini";
QString AppConfig::SendFileName = "send.txt";
QString AppConfig::DeviceFileName = "device.txt";
QString AppConfig::PortName = "COM1";
int AppConfig::BaudRate = 9600;
int AppConfig::DataBit = 8;
QString AppConfig::Parity = QString::fromUtf8("");
double AppConfig::StopBit = 1;
bool AppConfig::HexSend = false;
bool AppConfig::HexReceive = false;
bool AppConfig::Debug = false;
bool AppConfig::AutoClear = false;
bool AppConfig::AutoSend = false;
int AppConfig::SendInterval = 1000;
bool AppConfig::AutoSave = false;
int AppConfig::SaveInterval = 5000;
QString AppConfig::Mode = "Tcp_Client";
QString AppConfig::ServerIP = "127.0.0.1";
int AppConfig::ServerPort = 6000;
int AppConfig::ListenPort = 6000;
int AppConfig::SleepTime = 100;
bool AppConfig::AutoConnect = false;
void AppConfig::readConfig()
{
QSettings set(AppConfig::ConfigFile, QSettings::IniFormat);
set.beginGroup("ComConfig");
AppConfig::PortName = set.value("PortName", AppConfig::PortName).toString();
AppConfig::BaudRate = set.value("BaudRate", AppConfig::BaudRate).toInt();
AppConfig::DataBit = set.value("DataBit", AppConfig::DataBit).toInt();
AppConfig::Parity = set.value("Parity", AppConfig::Parity).toString();
AppConfig::StopBit = set.value("StopBit", AppConfig::StopBit).toInt();
AppConfig::HexSend = set.value("HexSend", AppConfig::HexSend).toBool();
AppConfig::HexReceive = set.value("HexReceive", AppConfig::HexReceive).toBool();
AppConfig::Debug = set.value("Debug", AppConfig::Debug).toBool();
AppConfig::AutoClear = set.value("AutoClear", AppConfig::AutoClear).toBool();
AppConfig::AutoSend = set.value("AutoSend", AppConfig::AutoSend).toBool();
AppConfig::SendInterval = set.value("SendInterval", AppConfig::SendInterval).toInt();
AppConfig::AutoSave = set.value("AutoSave", AppConfig::AutoSave).toBool();
AppConfig::SaveInterval = set.value("SaveInterval", AppConfig::SaveInterval).toInt();
set.endGroup();
set.beginGroup("NetConfig");
AppConfig::Mode = set.value("Mode", AppConfig::Mode).toString();
AppConfig::ServerIP = set.value("ServerIP", AppConfig::ServerIP).toString();
AppConfig::ServerPort = set.value("ServerPort", AppConfig::ServerPort).toInt();
AppConfig::ListenPort = set.value("ListenPort", AppConfig::ListenPort).toInt();
AppConfig::SleepTime = set.value("SleepTime", AppConfig::SleepTime).toInt();
AppConfig::AutoConnect = set.value("AutoConnect", AppConfig::AutoConnect).toBool();
set.endGroup();
//配置文件不存在或者不全则重新生成
if (!QtHelper::checkIniFile(AppConfig::ConfigFile)) {
writeConfig();
return;
}
}
void AppConfig::writeConfig()
{
QSettings set(AppConfig::ConfigFile, QSettings::IniFormat);
set.beginGroup("ComConfig");
set.setValue("PortName", AppConfig::PortName);
set.setValue("BaudRate", AppConfig::BaudRate);
set.setValue("DataBit", AppConfig::DataBit);
set.setValue("Parity", AppConfig::Parity);
set.setValue("StopBit", AppConfig::StopBit);
set.setValue("HexSend", AppConfig::HexSend);
set.setValue("HexReceive", AppConfig::HexReceive);
set.setValue("Debug", AppConfig::Debug);
set.setValue("AutoClear", AppConfig::AutoClear);
set.setValue("AutoSend", AppConfig::AutoSend);
set.setValue("SendInterval", AppConfig::SendInterval);
set.setValue("AutoSave", AppConfig::AutoSave);
set.setValue("SaveInterval", AppConfig::SaveInterval);
set.endGroup();
set.beginGroup("NetConfig");
set.setValue("Mode", AppConfig::Mode);
set.setValue("ServerIP", AppConfig::ServerIP);
set.setValue("ServerPort", AppConfig::ServerPort);
set.setValue("ListenPort", AppConfig::ListenPort);
set.setValue("SleepTime", AppConfig::SleepTime);
set.setValue("AutoConnect", AppConfig::AutoConnect);
set.endGroup();
}

@ -0,0 +1,41 @@
#ifndef APPCONFIG_H
#define APPCONFIG_H
#include "head.h"
class AppConfig
{
public:
static QString ConfigFile; //配置文件路径
static QString SendFileName; //发送配置文件名
static QString DeviceFileName; //模拟设备数据文件名
static QString PortName; //串口号
static int BaudRate; //波特率
static int DataBit; //数据位
static QString Parity; //校验位
static double StopBit; //停止位
static bool HexSend; //16进制发送
static bool HexReceive; //16进制接收
static bool Debug; //模拟设备
static bool AutoClear; //自动清空
static bool AutoSend; //自动发送
static int SendInterval; //自动发送间隔
static bool AutoSave; //自动保存
static int SaveInterval; //自动保存间隔
static QString Mode; //转换模式
static QString ServerIP; //服务器IP
static int ServerPort; //服务器端口
static int ListenPort; //监听端口
static int SleepTime; //延时时间
static bool AutoConnect; //自动重连
//读写配置参数
static void readConfig(); //读取配置参数
static void writeConfig(); //写入配置参数
};
#endif // APPCONFIG_H

@ -0,0 +1,122 @@
#include "appdata.h"
#include "qthelper.h"
QStringList AppData::Intervals = QStringList();
QStringList AppData::Datas = QStringList();
QStringList AppData::Keys = QStringList();
QStringList AppData::Values = QStringList();
QString AppData::SendFileName = "send.txt";
void AppData::readSendData()
{
//读取发送数据列表
AppData::Datas.clear();
QString fileName = QString("%1/%2").arg(QtHelper::appPath()).arg(AppData::SendFileName);
QFile file(fileName);
if (file.size() > 0 && file.open(QFile::ReadOnly | QIODevice::Text)) {
while (!file.atEnd()) {
QString line = file.readLine();
line = line.trimmed();
line = line.replace("\r", "");
line = line.replace("\n", "");
if (!line.isEmpty()) {
AppData::Datas.append(line);
}
}
file.close();
}
//没有的时候主动添加点免得太空
if (AppData::Datas.count() == 0) {
AppData::Datas << "16 FF 01 01 E0 E1" << "16 FF 01 01 E1 E2";
}
}
QString AppData::DeviceFileName = "device.txt";
void AppData::readDeviceData()
{
//读取转发数据列表
AppData::Keys.clear();
AppData::Values.clear();
QString fileName = QString("%1/%2").arg(QtHelper::appPath()).arg(AppData::DeviceFileName);
QFile file(fileName);
if (file.size() > 0 && file.open(QFile::ReadOnly | QIODevice::Text)) {
while (!file.atEnd()) {
QString line = file.readLine();
line = line.trimmed();
line = line.replace("\r", "");
line = line.replace("\n", "");
if (!line.isEmpty()) {
QStringList list = line.split(";");
QString key = list.at(0);
QString value;
for (int i = 1; i < list.count(); i++) {
value += QString("%1;").arg(list.at(i));
}
//去掉末尾分号
value = value.mid(0, value.length() - 1);
AppData::Keys.append(key);
AppData::Values.append(value);
}
}
file.close();
}
}
void AppData::saveData(const QString &data)
{
if (data.length() <= 0) {
return;
}
QString fileName = QString("%1/%2.txt").arg(QtHelper::appPath()).arg(STRDATETIME);
QFile file(fileName);
if (file.open(QFile::WriteOnly | QFile::Text)) {
file.write(data.toUtf8());
file.close();
}
}
void AppData::loadIP(QComboBox *cbox)
{
//获取本机所有IP
static QStringList ips;
if (ips.count() == 0) {
#ifdef emsdk
ips << "127.0.0.1";
#else
QList<QNetworkInterface> netInterfaces = QNetworkInterface::allInterfaces();
foreach (const QNetworkInterface &netInterface, netInterfaces) {
//移除虚拟机和抓包工具的虚拟网卡
QString humanReadableName = netInterface.humanReadableName().toLower();
if (humanReadableName.startsWith("vmware network adapter") || humanReadableName.startsWith("npcap loopback adapter")) {
continue;
}
//过滤当前网络接口
bool flag = (netInterface.flags() == (QNetworkInterface::IsUp | QNetworkInterface::IsRunning | QNetworkInterface::CanBroadcast | QNetworkInterface::CanMulticast));
if (flag) {
QList<QNetworkAddressEntry> addrs = netInterface.addressEntries();
foreach (QNetworkAddressEntry addr, addrs) {
//只取出IPV4的地址
if (addr.ip().protocol() == QAbstractSocket::IPv4Protocol) {
QString ip4 = addr.ip().toString();
if (ip4 != "127.0.0.1") {
ips << ip4;
}
}
}
}
}
#endif
}
cbox->clear();
cbox->addItems(ips);
if (!ips.contains("127.0.0.1")) {
cbox->addItem("127.0.0.1");
}
}

@ -0,0 +1,30 @@
#ifndef APPDATA_H
#define APPDATA_H
#include "head.h"
class AppData
{
public:
//全局变量
static QStringList Intervals;
static QStringList Datas;
static QStringList Keys;
static QStringList Values;
//读取发送数据列表
static QString SendFileName;
static void readSendData();
//读取转发数据列表
static QString DeviceFileName;
static void readDeviceData();
//保存数据到文件
static void saveData(const QString &data);
//添加网卡IP地址到下拉框
static void loadIP(QComboBox *cbox);
};
#endif // APPDATA_H

File diff suppressed because it is too large Load Diff

@ -0,0 +1,180 @@
#ifndef QTHELPER_H
#define QTHELPER_H
#include "head.h"
class QtHelper
{
public:
//获取所有屏幕区域/当前鼠标所在屏幕索引/区域尺寸/缩放系数
static QList<QRect> getScreenRects(bool available = true);
static int getScreenIndex();
static QRect getScreenRect(bool available = true);
static qreal getScreenRatio(bool devicePixel = false);
//矫正当前鼠标所在屏幕居中尺寸
static QRect checkCenterRect(QRect &rect, bool available = true);
//获取桌面宽度高度+居中显示
static int deskWidth();
static int deskHeight();
static QSize deskSize();
//居中显示窗体
//定义标志位指定是以桌面为参照还是主程序界面为参照
static QWidget *centerBaseForm;
static void setFormInCenter(QWidget *form);
static void showForm(QWidget *form);
//程序文件名称和当前所在路径
static QString appName();
static QString appPath();
//程序最前面获取应用程序路径和名称
static void getCurrentInfo(char *argv[], QString &path, QString &name);
//程序最前面读取配置文件节点的值
static QString getIniValue(const QString &fileName, const QString &key);
static QString getIniValue(char *argv[], const QString &key, const QString &dir = QString());
//获取本地网卡IP集合
static QStringList getLocalIPs();
//获取内置颜色集合
static QList<QColor> colors;
static QList<QColor> getColorList();
static QStringList getColorNames();
//随机获取颜色集合中的颜色
static QColor getRandColor();
//初始化随机数种子
static void initRand();
//获取随机小数
static float getRandFloat(float min, float max);
//获取随机数,指定最小值和最大值
static double getRandValue(int min, int max, bool contansMin = false, bool contansMax = false);
//获取范围值随机经纬度集合
static QStringList getRandPoint(int count, float mainLng, float mainLat, float dotLng, float dotLat);
//根据旧的范围值和值计算新的范围值对应的值
static int getRangeValue(int oldMin, int oldMax, int oldValue, int newMin, int newMax);
//获取uuid
static QString getUuid();
//校验目录
static void checkPath(const QString &dirName);
//通用延时函数(支持Qt4 Qt5 Qt6)
static void sleep(int msec, bool exec = true);
//检查程序是否已经运行
static void checkRun();
//设置Qt自带样式
static void setStyle();
//设置字体
static QFont addFont(const QString &fontFile, const QString &fontName);
static void setFont(int fontSize = 12);
//设置编码
static void setCode(bool utf8 = true);
//设置翻译文件
static void setTranslator(const QString &qmFile);
//动态设置权限
static bool checkPermission(const QString &permission);
//申请安卓权限
static void initAndroidPermission();
//一次性设置所有包括编码样式字体等
static void initAll(bool utf8 = true, bool style = true, int fontSize = 13);
//初始化main函数最前面执行的一段代码
static void initMain(bool desktopSettingsAware = false, bool use96Dpi = true, bool logCritical = true);
//初始化opengl类型(1=AA_UseDesktopOpenGL 2=AA_UseOpenGLES 3=AA_UseSoftwareOpenGL)
static void initOpenGL(quint8 type = 0, bool checkCardEnable = false, bool checkVirtualSystem = false);
//执行命令行返回执行结果
static QString doCmd(const QString &program, const QStringList &arguments, int timeout = 1000);
//获取显卡是否被禁用
static bool isVideoCardEnable();
//获取是否在虚拟机环境
static bool isVirtualSystem();
//插入消息
static QVector<int> msgTypes;
static QVector<QString> msgKeys;
static QVector<QColor> msgColors;
static QString appendMsg(QTextEdit *textEdit, int type, const QString &data,
int maxCount, int &currentCount,
bool clear = false, bool pause = false);
//设置无边框
static void setFramelessForm(QWidget *widgetMain, bool tool = false, bool top = false, bool menu = true);
//弹出框
static int showMessageBox(const QString &text, int type = 0, int closeSec = 0, bool exec = false);
//弹出消息框
static void showMessageBoxInfo(const QString &text, int closeSec = 0, bool exec = false);
//弹出错误框
static void showMessageBoxError(const QString &text, int closeSec = 0, bool exec = false);
//弹出询问框
static int showMessageBoxQuestion(const QString &text);
//为什么还要自定义对话框因为可控宽高和汉化对应文本等
//初始化对话框文本
static void initDialog(QFileDialog *dialog, const QString &title, const QString &acceptName,
const QString &dirName, bool native, int width, int height);
//拿到对话框结果
static QString getDialogResult(QFileDialog *dialog);
//选择文件对话框
static QString getOpenFileName(const QString &filter = QString(),
const QString &dirName = QString(),
const QString &fileName = QString(),
bool native = false, int width = 900, int height = 600);
//保存文件对话框
static QString getSaveFileName(const QString &filter = QString(),
const QString &dirName = QString(),
const QString &fileName = QString(),
bool native = false, int width = 900, int height = 600);
//选择目录对话框
static QString getExistingDirectory(const QString &dirName = QString(),
bool native = false, int width = 900, int height = 600);
//异或加密-只支持字符,如果是中文需要将其转换base64编码
static QString getXorEncryptDecrypt(const QString &value, char key);
//异或校验
static quint8 getOrCode(const QByteArray &data);
//计算校验码
static quint8 getCheckCode(const QByteArray &data);
//初始化表格
static void initTableView(QTableView *tableView, int rowHeight = 25,
bool headVisible = false, bool edit = false,
bool stretchLast = true);
//打开文件带提示框
static void openFile(const QString &fileName, const QString &msg);
//检查ini配置文件
static bool checkIniFile(const QString &iniFile);
//首尾截断字符串显示
static QString cutString(const QString &text, int len, int left, int right, bool file, const QString &mid = "...");
//传入图片尺寸和窗体区域及边框大小返回居中区域(scaleMode: 0-自动调整 1-等比缩放 2-拉伸填充)
static QRect getCenterRect(const QSize &imageSize, const QRect &widgetRect, int borderWidth = 2, int scaleMode = 0);
//传入图片尺寸和窗体尺寸及缩放策略返回合适尺寸(scaleMode: 0-自动调整 1-等比缩放 2-拉伸填充)
static void getScaledImage(QImage &image, const QSize &widgetSize, int scaleMode = 0, bool fast = true);
//毫秒数转时间 00:00
static QString getTimeString(qint64 time);
//用时时间转秒数
static QString getTimeString(QElapsedTimer timer);
//文件大小转 KB MB GB TB
static QString getSizeString(quint64 size);
//设置系统时间
static void setSystemDateTime(const QString &year, const QString &month, const QString &day,
const QString &hour, const QString &min, const QString &sec);
//设置开机自启动
static void runWithSystem(bool autoRun = true);
static void runWithSystem(const QString &fileName, const QString &filePath, bool autoRun = true);
//启动运行程序(已经在运行则不启动)
static void runBin(const QString &path, const QString &name);
};
#endif // QTHELPER_H

@ -0,0 +1,473 @@
#include "qthelperdata.h"
#include "qthelper.h"
int QtHelperData::strHexToDecimal(const QString &strHex)
{
bool ok;
return strHex.toInt(&ok, 16);
}
int QtHelperData::strDecimalToDecimal(const QString &strDecimal)
{
bool ok;
return strDecimal.toInt(&ok, 10);
}
int QtHelperData::strBinToDecimal(const QString &strBin)
{
bool ok;
return strBin.toInt(&ok, 2);
}
QString QtHelperData::strHexToStrBin(const QString &strHex)
{
quint8 decimal = strHexToDecimal(strHex);
QString bin = QString::number(decimal, 2);
quint8 len = bin.length();
if (len < 8) {
for (int i = 0; i < 8 - len; ++i) {
bin = "0" + bin;
}
}
return bin;
}
QString QtHelperData::decimalToStrBin1(int decimal)
{
QString bin = QString::number(decimal, 2);
quint8 len = bin.length();
if (len <= 8) {
for (int i = 0; i < 8 - len; ++i) {
bin = "0" + bin;
}
}
return bin;
}
QString QtHelperData::decimalToStrBin2(int decimal)
{
QString bin = QString::number(decimal, 2);
quint8 len = bin.length();
if (len <= 16) {
for (int i = 0; i < 16 - len; ++i) {
bin = "0" + bin;
}
}
return bin;
}
QString QtHelperData::decimalToStrHex(int decimal)
{
QString temp = QString::number(decimal, 16);
if (temp.length() == 1) {
temp = "0" + temp;
}
return temp;
}
QByteArray QtHelperData::intToByte(int data, bool reverse)
{
quint8 data1 = (quint8)(0x000000ff & data);
quint8 data2 = (quint8)((0x0000ff00 & data) >> 8);
quint8 data3 = (quint8)((0x00ff0000 & data) >> 16);
quint8 data4 = (quint8)((0xff000000 & data) >> 24);
QByteArray result;
result.resize(4);
if (reverse) {
result[0] = data1;
result[1] = data2;
result[2] = data3;
result[3] = data4;
} else {
result[0] = data4;
result[1] = data3;
result[2] = data2;
result[3] = data1;
}
return result;
}
int QtHelperData::byteToInt(const QByteArray &data, bool reverse)
{
int result = 0;
if (reverse) {
result = data.at(0) & 0x000000ff;
result |= ((data.at(1) << 8) & 0x0000ff00);
result |= ((data.at(2) << 16) & 0x00ff0000);
result |= ((data.at(3) << 24) & 0xff000000);
} else {
result = data.at(3) & 0x000000ff;
result |= ((data.at(2) << 8) & 0x0000ff00);
result |= ((data.at(1) << 16) & 0x00ff0000);
result |= ((data.at(0) << 24) & 0xff000000);
}
return result;
}
QByteArray QtHelperData::ushortToByte(int data, bool reverse)
{
quint8 data1 = (quint8)(0x000000ff & data);
quint8 data2 = (quint8)((0x0000ff00 & data) >> 8);
QByteArray result;
result.resize(2);
if (reverse) {
result[0] = data1;
result[1] = data2;
} else {
result[0] = data2;
result[1] = data1;
}
return result;
}
int QtHelperData::byteToShort(const QByteArray &data, bool reverse)
{
int result = 0;
if (reverse) {
result = data.at(0) & 0x000000ff;
result |= ((data.at(1) << 8) & 0x0000ff00);
} else {
result = data.at(1) & 0x000000ff;
result |= ((data.at(0) << 8) & 0x0000ff00);
}
if (result >= 32768) {
result = result - 65536;
}
return result;
}
QString QtHelperData::getValue(quint8 value)
{
QString result = QString::number(value);
if (result.length() <= 1) {
result = QString("0%1").arg(result);
}
return result;
}
QString QtHelperData::trimmed(const QString &text, int type)
{
QString temp = text;
QString pattern;
if (type == -1) {
pattern = "^ +\\s*";
} else if (type == 0) {
pattern = "\\s";
//temp.replace(" ", "");
} else if (type == 1) {
pattern = "\\s* +$";
} else if (type == 2) {
temp = temp.trimmed();
} else if (type == 3) {
temp = temp.simplified();
}
//调用正则表达式移除空格
if (!pattern.isEmpty()) {
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
temp.remove(QRegularExpression(pattern));
#else
temp.remove(QRegExp(pattern));
#endif
}
return temp;
}
QString QtHelperData::getXorEncryptDecrypt(const QString &value, char key)
{
//矫正范围外的数据
if (key < 0 || key >= 127) {
key = 127;
}
//大概从5.9版本输出的加密密码字符串前面会加上 @String 字符
QString result = value;
if (result.startsWith("@String")) {
result = result.mid(8, result.length() - 9);
}
for (int i = 0; i < result.length(); ++i) {
result[i] = QChar(result.at(i).toLatin1() ^ key);
}
return result;
}
quint8 QtHelperData::getOrCode(const QByteArray &data)
{
int len = data.length();
quint8 result = 0;
for (int i = 0; i < len; ++i) {
result ^= data.at(i);
}
return result;
}
quint8 QtHelperData::getCheckCode(const QByteArray &data)
{
int len = data.length();
quint8 temp = 0;
for (int i = 0; i < len; ++i) {
temp += data.at(i);
}
return temp % 256;
}
void QtHelperData::getFullData(QByteArray &buffer)
{
//计算校验码
quint8 checkCode = getCheckCode(buffer);
//尾部插入校验码
buffer.append(checkCode);
//头部插入固定帧头
buffer.insert(0, 0x16);
}
//函数功能计算CRC16
//参数1*data 16位CRC校验数据
//参数2len 数据流长度
//参数3init 初始化值
//参数4table 16位CRC查找表
//正序CRC计算
quint16 QtHelperData::getCrc16(quint8 *data, int len, quint16 init, const quint16 *table)
{
quint16 crc_16 = init;
quint8 temp;
while (len-- > 0) {
temp = crc_16 & 0xff;
crc_16 = (crc_16 >> 8) ^ table[(temp ^ *data++) & 0xff];
}
return crc_16;
}
//逆序CRC计算
quint16 QtHelperData::getCrc16Rec(quint8 *data, int len, quint16 init, const quint16 *table)
{
quint16 crc_16 = init;
quint8 temp;
while (len-- > 0) {
temp = crc_16 >> 8;
crc_16 = (crc_16 << 8) ^ table[(temp ^ *data++) & 0xff];
}
return crc_16;
}
//Modbus CRC16校验
quint16 QtHelperData::getModbus16(quint8 *data, int len)
{
//MODBUS CRC-16表 8005 逆序
const quint16 table_16[256] = {
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
};
return getCrc16(data, len, 0xFFFF, table_16);
}
//CRC16校验
QByteArray QtHelperData::getCrcCode(const QByteArray &data)
{
quint16 result = getModbus16((quint8 *)data.data(), data.length());
return QtHelperData::ushortToByte(result, true);
}
static QMap<char, QString> listChar;
void QtHelperData::initAscii()
{
//0x20为空格,空格以下都是不可见字符
if (listChar.count() == 0) {
listChar.insert(0, "\\NUL");
listChar.insert(1, "\\SOH");
listChar.insert(2, "\\STX");
listChar.insert(3, "\\ETX");
listChar.insert(4, "\\EOT");
listChar.insert(5, "\\ENQ");
listChar.insert(6, "\\ACK");
listChar.insert(7, "\\BEL");
listChar.insert(8, "\\BS");
listChar.insert(9, "\\HT");
listChar.insert(10, "\\LF");
listChar.insert(11, "\\VT");
listChar.insert(12, "\\FF");
listChar.insert(13, "\\CR");
listChar.insert(14, "\\SO");
listChar.insert(15, "\\SI");
listChar.insert(16, "\\DLE");
listChar.insert(17, "\\DC1");
listChar.insert(18, "\\DC2");
listChar.insert(19, "\\DC3");
listChar.insert(20, "\\DC4");
listChar.insert(21, "\\NAK");
listChar.insert(22, "\\SYN");
listChar.insert(23, "\\ETB");
listChar.insert(24, "\\CAN");
listChar.insert(25, "\\EM");
listChar.insert(26, "\\SUB");
listChar.insert(27, "\\ESC");
listChar.insert(28, "\\FS");
listChar.insert(29, "\\GS");
listChar.insert(30, "\\RS");
listChar.insert(31, "\\US");
listChar.insert(0x5C, "\\");
listChar.insert(0x7F, "\\DEL");
}
}
QString QtHelperData::byteArrayToAsciiStr(const QByteArray &data)
{
//先初始化字符表
initAscii();
QString temp;
int len = data.length();
for (int i = 0; i < len; ++i) {
char byte = data.at(i);
QString value = listChar.value(byte);
if (!value.isEmpty()) {
} else if (byte >= 0 && byte <= 0x7F) {
value = QString("%1").arg(byte);
} else {
value = decimalToStrHex((quint8)byte);
value = QString("\\x%1").arg(value.toUpper());
}
temp += value;
}
return temp.trimmed();
}
QByteArray QtHelperData::asciiStrToByteArray(const QString &data)
{
//先初始化字符表
initAscii();
QByteArray buffer;
QStringList list = data.split("\\");
int count = list.count();
for (int i = 1; i < count; ++i) {
QString str = list.at(i);
int key = 0;
if (str.contains("x")) {
key = strHexToDecimal(str.mid(1, 2));
} else {
key = listChar.key("\\" + str);
}
buffer.append(key);
}
//可能是纯字符串不带控制字符
if (buffer.length() == 0) {
buffer = data.toUtf8();
}
return buffer;
}
char QtHelperData::hexStrToChar(char data)
{
if ((data >= '0') && (data <= '9')) {
return data - 0x30;
} else if ((data >= 'A') && (data <= 'F')) {
return data - 'A' + 10;
} else if ((data >= 'a') && (data <= 'f')) {
return data - 'a' + 10;
} else {
return (-1);
}
}
QByteArray QtHelperData::hexStrToByteArray(const QString &data)
{
QByteArray senddata;
int hexdata, lowhexdata;
int hexdatalen = 0;
int len = data.length();
senddata.resize(len / 2);
char lstr, hstr;
for (int i = 0; i < len;) {
hstr = data.at(i).toLatin1();
if (hstr == ' ') {
i++;
continue;
}
i++;
if (i >= len) {
break;
}
lstr = data.at(i).toLatin1();
hexdata = hexStrToChar(hstr);
lowhexdata = hexStrToChar(lstr);
if ((hexdata == 16) || (lowhexdata == 16)) {
break;
} else {
hexdata = hexdata * 16 + lowhexdata;
}
i++;
senddata[hexdatalen] = (char)hexdata;
hexdatalen++;
}
senddata.resize(hexdatalen);
return senddata;
}
QString QtHelperData::byteArrayToHexStr(const QByteArray &data)
{
QString temp = "";
QString hex = data.toHex();
for (int i = 0; i < hex.length(); i = i + 2) {
temp += hex.mid(i, 2) + " ";
}
return temp.trimmed().toUpper();
}

@ -0,0 +1,65 @@
#ifndef QTHELPERDATA_H
#define QTHELPERDATA_H
#include <QObject>
class QtHelperData
{
public:
//16进制字符串转10进制
static int strHexToDecimal(const QString &strHex);
//10进制字符串转10进制
static int strDecimalToDecimal(const QString &strDecimal);
//2进制字符串转10进制
static int strBinToDecimal(const QString &strBin);
//16进制字符串转2进制字符串
static QString strHexToStrBin(const QString &strHex);
//10进制转2进制字符串一个字节
static QString decimalToStrBin1(int decimal);
//10进制转2进制字符串两个字节
static QString decimalToStrBin2(int decimal);
//10进制转16进制字符串,补零.
static QString decimalToStrHex(int decimal);
//int和字节数组互转
static QByteArray intToByte(int data, bool reverse = false);
static int byteToInt(const QByteArray &data, bool reverse = false);
//ushort和字节数组互转
static QByteArray ushortToByte(int data, bool reverse = false);
static int byteToShort(const QByteArray &data, bool reverse = false);
//字符串补全
static QString getValue(quint8 value);
//字符串去空格 -1=移除左侧空格 0=移除所有空格 1=移除右侧空格 2=移除首尾空格 3=首尾清除中间留一个空格
static QString trimmed(const QString &text, int type);
//异或加密-只支持字符,如果是中文需要将其转换base64编码
static QString getXorEncryptDecrypt(const QString &value, char key);
//异或校验
static quint8 getOrCode(const QByteArray &data);
//公司专用-计算校验码
static quint8 getCheckCode(const QByteArray &data);
//公司专用-加上桢头和校验码完整数据
static void getFullData(QByteArray &buffer);
//CRC校验
static quint16 getCrc16Rec(quint8 *data, int len, quint16 init, const quint16 *table);
static quint16 getCrc16(quint8 *data, int len, quint16 init, const quint16 *table);
static quint16 getModbus16(quint8 *data, int len);
static QByteArray getCrcCode(const QByteArray &data);
//字节数组与Ascii字符串互转
static void initAscii();
static QString byteArrayToAsciiStr(const QByteArray &data);
static QByteArray asciiStrToByteArray(const QString &data);
//16进制字符串与字节数组互转
static char hexStrToChar(char data);
static QByteArray hexStrToByteArray(const QString &data);
static QString byteArrayToHexStr(const QByteArray &data);
};
#endif // QTHELPERDATA_H

@ -0,0 +1,23 @@
QT += core gui network
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
greaterThan(QT_MAJOR_VERSION, 5): QT += core5compat
TARGET = comtool
TEMPLATE = app
DESTDIR = $$PWD/../bin
RC_FILE = qrc/main.rc
HEADERS += head.h
SOURCES += main.cpp
RESOURCES += qrc/main.qrc
CONFIG += warn_off
INCLUDEPATH += $$PWD
INCLUDEPATH += $$PWD/api
INCLUDEPATH += $$PWD/form
include ($$PWD/api/api.pri)
include ($$PWD/form/form.pri)
INCLUDEPATH += $$PWD/../3rd_qextserialport
include ($$PWD/../3rd_qextserialport/3rd_qextserialport.pri)

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save