彻底改版2.0

This commit is contained in:
feiyangqingyun
2021-11-17 16:41:30 +08:00
parent a7f4347959
commit ebfd531a91
2622 changed files with 8915 additions and 7263 deletions

BIN
tool/0snap/base64helper.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

BIN
tool/0snap/comtool.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

BIN
tool/0snap/countcode.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

BIN
tool/0snap/emailtool.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

BIN
tool/0snap/keydemo.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
tool/0snap/keytool.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
tool/0snap/livedemo.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
tool/0snap/livetool.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

BIN
tool/0snap/moneytool.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
tool/0snap/netserver.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

BIN
tool/0snap/netserver2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 KiB

BIN
tool/0snap/nettool.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

BIN
tool/0snap/pngtool.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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_

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -0,0 +1,28 @@
#ifndef EMAILADDRESS_H
#define EMAILADDRESS_H
#include <QObject>
class EmailAddress : public QObject
{
Q_OBJECT
public:
EmailAddress();
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

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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");
}

View File

@@ -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

View File

@@ -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

View File

@@ -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.toLocal8Bit().toBase64());
}
QString Base64Helper::base64ToText(const QString &text)
{
return QString(QByteArray::fromBase64(text.toLocal8Bit()));
}

View File

@@ -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. Qt6对base64编码转换进行了重写效率提升至少200%。
*/
#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

View File

@@ -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

View File

@@ -0,0 +1,97 @@
#pragma execution_character_set("utf-8")
#include "frmbase64helper.h"
#include "ui_frmbase64helper.h"
#include "base64helper.h"
#include "qfiledialog.h"
#include "qelapsedtimer.h"
#include "qdebug.h"
frmBase64Helper::frmBase64Helper(QWidget *parent) : QWidget(parent), ui(new Ui::frmBase64Helper)
{
ui->setupUi(this);
}
frmBase64Helper::~frmBase64Helper()
{
delete ui;
}
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()
{
//计时
QElapsedTimer time;
time.start();
QString fileName = ui->txtFile->text().trimmed();
if (!fileName.isEmpty()) {
ui->txtBase64->setText(Base64Helper::imageToBase64(QImage(fileName)));
}
//统计用时
#if (QT_VERSION >= QT_VERSION_CHECK(4,8,0))
double elapsed = (double)time.nsecsElapsed() / 1000000;
#else
double elapsed = (double)time.elapsed();
#endif
QString strTime = QString::number(elapsed, 'f', 3);
qDebug() << QString("用时 %1 毫秒").arg(strTime);
}
void frmBase64Helper::on_btnBase64ToImage_clicked()
{
//计时
QElapsedTimer time;
time.start();
QString text = ui->txtBase64->toPlainText().trimmed();
if (!text.isEmpty()) {
QPixmap pix = QPixmap::fromImage(Base64Helper::base64ToImage(text));
pix = pix.scaled(ui->labImage->size() - QSize(4, 4), Qt::KeepAspectRatio);
ui->labImage->setPixmap(pix);
}
//统计用时
#if (QT_VERSION >= QT_VERSION_CHECK(4,8,0))
double elapsed = (double)time.nsecsElapsed() / 1000000;
#else
double elapsed = (double)time.elapsed();
#endif
QString strTime = QString::number(elapsed, 'f', 3);
qDebug() << QString("用时 %1 毫秒").arg(strTime);
}
void frmBase64Helper::on_btnTextToBase64_clicked()
{
QString text = ui->txtText->text().trimmed();
if (!text.isEmpty()) {
ui->txtBase64->setText(Base64Helper::textToBase64(text));
}
}
void frmBase64Helper::on_btnBase64ToText_clicked()
{
QString text = ui->txtBase64->toPlainText().trimmed();
if (!text.isEmpty()) {
ui->txtText->setText(Base64Helper::base64ToText(text));
}
}

View File

@@ -0,0 +1,30 @@
#ifndef FRMBASE64HELPER_H
#define FRMBASE64HELPER_H
#include <QWidget>
namespace Ui {
class frmBase64Helper;
}
class frmBase64Helper : public QWidget
{
Q_OBJECT
public:
explicit frmBase64Helper(QWidget *parent = 0);
~frmBase64Helper();
private:
Ui::frmBase64Helper *ui;
private slots:
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

View File

@@ -0,0 +1,139 @@
<?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" 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="3" column="0" colspan="4">
<widget class="QTextEdit" name="txtBase64"/>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,31 @@
#pragma execution_character_set("utf-8")
#include "frmbase64helper.h"
#include <QApplication>
#include <QTextCodec>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
a.setFont(QFont("Microsoft Yahei", 9));
#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编码互换");
w.show();
return a.exec();
}

11
tool/comtool/api/api.pri Normal file
View File

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

View File

@@ -0,0 +1,99 @@
#include "appconfig.h"
#include "quihelper.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 (!QUIHelper::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();
}

View File

@@ -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

View File

@@ -0,0 +1,122 @@
#include "appdata.h"
#include "quihelper.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(QUIHelper::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(QUIHelper::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(QUIHelper::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");
}
}

View File

@@ -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

View File

@@ -0,0 +1,420 @@
#include "quihelper.h"
int QUIHelper::getScreenIndex()
{
//需要对多个屏幕进行处理
int screenIndex = 0;
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
int screenCount = qApp->screens().count();
#else
int screenCount = qApp->desktop()->screenCount();
#endif
if (screenCount > 1) {
//找到当前鼠标所在屏幕
QPoint pos = QCursor::pos();
for (int i = 0; i < screenCount; ++i) {
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
if (qApp->screens().at(i)->geometry().contains(pos)) {
#else
if (qApp->desktop()->screenGeometry(i).contains(pos)) {
#endif
screenIndex = i;
break;
}
}
}
return screenIndex;
}
QRect QUIHelper::getScreenRect(bool available)
{
QRect rect;
int screenIndex = QUIHelper::getScreenIndex();
if (available) {
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
rect = qApp->screens().at(screenIndex)->availableGeometry();
#else
rect = qApp->desktop()->availableGeometry(screenIndex);
#endif
} else {
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
rect = qApp->screens().at(screenIndex)->geometry();
#else
rect = qApp->desktop()->screenGeometry(screenIndex);
#endif
}
return rect;
}
int QUIHelper::deskWidth()
{
return getScreenRect().width();
}
int QUIHelper::deskHeight()
{
return getScreenRect().height();
}
QWidget *QUIHelper::centerBaseForm = 0;
void QUIHelper::setFormInCenter(QWidget *form)
{
int formWidth = form->width();
int formHeight = form->height();
//如果=0表示采用系统桌面屏幕为参照
QRect rect;
if (centerBaseForm == 0) {
rect = getScreenRect();
} else {
rect = centerBaseForm->geometry();
}
int deskWidth = rect.width();
int deskHeight = rect.height();
QPoint movePoint(deskWidth / 2 - formWidth / 2 + rect.x(), deskHeight / 2 - formHeight / 2 + rect.y());
form->move(movePoint);
}
QString QUIHelper::appName()
{
//没有必要每次都获取,只有当变量为空时才去获取一次
static QString name;
if (name.isEmpty()) {
name = qApp->applicationFilePath();
//下面的方法主要为了过滤安卓的路径 lib程序名_armeabi-v7a
QStringList list = name.split("/");
name = list.at(list.count() - 1).split(".").at(0);
}
return name;
}
QString QUIHelper::appPath()
{
#ifdef Q_OS_ANDROID
//return QString("/sdcard/Android/%1").arg(appName());
return QString("/storage/emulated/0/%1").arg(appName());
#else
return qApp->applicationDirPath();
#endif
}
QString QUIHelper::getUuid()
{
QString uuid = QUuid::createUuid().toString();
uuid.replace("{", "");
uuid.replace("}", "");
return uuid;
}
void QUIHelper::initRand()
{
//初始化随机数种子
QTime t = QTime::currentTime();
srand(t.msec() + t.second() * 1000);
}
void QUIHelper::newDir(const QString &dirName)
{
QString strDir = dirName;
//如果路径中包含斜杠字符则说明是绝对路径
//linux系统路径字符带有 / windows系统 路径字符带有 :/
if (!strDir.startsWith("/") && !strDir.contains(":/")) {
strDir = QString("%1/%2").arg(QUIHelper::appPath()).arg(strDir);
}
QDir dir(strDir);
if (!dir.exists()) {
dir.mkpath(strDir);
}
}
void QUIHelper::sleep(int msec)
{
if (msec <= 0) {
return;
}
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
QThread::msleep(msec);
#else
QTime endTime = QTime::currentTime().addMSecs(msec);
while (QTime::currentTime() < endTime) {
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}
#endif
}
void QUIHelper::setStyle()
{
//打印下所有内置风格的名字
qDebug() << "Qt内置的样式" << QStyleFactory::keys();
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
qApp->setStyle(QStyleFactory::create("Fusion"));
#else
qApp->setStyle(QStyleFactory::create("Cleanlooks"));
#endif
//qApp->setPalette(QPalette("#FFFFFF"));
}
void QUIHelper::setFont(int fontSize)
{
QFont font;
font.setFamily("MicroSoft Yahei");
#ifdef Q_OS_ANDROID
font.setPixelSize(15);
#elif __arm__
font.setPixelSize(25);
#else
font.setPixelSize(fontSize);
#endif
#ifndef rk3399
qApp->setFont(font);
#endif
}
void QUIHelper::setCode(bool utf8)
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
//如果想要控制台打印信息中文正常就注释掉这个设置
if (utf8) {
QTextCodec *codec = QTextCodec::codecForName("utf-8");
QTextCodec::setCodecForLocale(codec);
}
#else
#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);
#endif
}
void QUIHelper::setTranslator(const QString &qmFile)
{
//过滤下不存在的就不用设置了
if (!QFile(qmFile).exists()) {
return;
}
QTranslator *translator = new QTranslator(qApp);
translator->load(qmFile);
qApp->installTranslator(translator);
}
void QUIHelper::initAll()
{
//初始化随机数种子
QUIHelper::initRand();
//设置样式风格
QUIHelper::setStyle();
//设置字体
QUIHelper::setFont(13);
//设置编码
QUIHelper::setCode();
//设置翻译文件支持多个
QUIHelper::setTranslator(":/qm/widgets.qm");
QUIHelper::setTranslator(":/qm/qt_zh_CN.qm");
QUIHelper::setTranslator(":/qm/designer_zh_CN.qm");
}
void QUIHelper::setFramelessForm(QWidget *widgetMain, bool tool, bool top, bool menu)
{
widgetMain->setProperty("form", true);
widgetMain->setProperty("canMove", true);
//根据设定逐个追加属性
#ifdef __arm__
widgetMain->setWindowFlags(Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint);
#else
widgetMain->setWindowFlags(Qt::FramelessWindowHint);
#endif
if (tool) {
widgetMain->setWindowFlags(widgetMain->windowFlags() | Qt::Tool);
}
if (top) {
widgetMain->setWindowFlags(widgetMain->windowFlags() | Qt::WindowStaysOnTopHint);
}
if (menu) {
//如果是其他系统比如neokylin会产生系统边框
#ifdef Q_OS_WIN
widgetMain->setWindowFlags(widgetMain->windowFlags() | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint);
#endif
}
}
int QUIHelper::showMessageBox(const QString &info, int type, int closeSec, bool exec)
{
int result = 0;
if (type == 0) {
showMessageBoxInfo(info, closeSec, exec);
} else if (type == 1) {
showMessageBoxError(info, closeSec, exec);
} else if (type == 2) {
result = showMessageBoxQuestion(info);
}
return result;
}
void QUIHelper::showMessageBoxInfo(const QString &info, int closeSec, bool exec)
{
QMessageBox box(QMessageBox::Information, "提示", info);
box.setStandardButtons(QMessageBox::Yes);
box.setButtonText(QMessageBox::Yes, QString("确 定"));
box.exec();
//QMessageBox::information(0, "提示", info, QMessageBox::Yes);
}
void QUIHelper::showMessageBoxError(const QString &info, int closeSec, bool exec)
{
QMessageBox box(QMessageBox::Critical, "错误", info);
box.setStandardButtons(QMessageBox::Yes);
box.setButtonText(QMessageBox::Yes, QString("确 定"));
box.exec();
//QMessageBox::critical(0, "错误", info, QMessageBox::Yes);
}
int QUIHelper::showMessageBoxQuestion(const QString &info)
{
QMessageBox box(QMessageBox::Question, "询问", info);
box.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
box.setButtonText(QMessageBox::Yes, QString("确 定"));
box.setButtonText(QMessageBox::No, QString("取 消"));
return box.exec();
//return QMessageBox::question(0, "询问", info, QMessageBox::Yes | QMessageBox::No);
}
QString QUIHelper::getXorEncryptDecrypt(const QString &value, char key)
{
//矫正范围外的数据
if (key < 0 || key >= 127) {
key = 127;
}
QString result = value;
int count = result.count();
for (int i = 0; i < count; i++) {
result[i] = QChar(result.at(i).toLatin1() ^ key);
}
return result;
}
uchar QUIHelper::getOrCode(const QByteArray &data)
{
int len = data.length();
uchar result = 0;
for (int i = 0; i < len; i++) {
result ^= data.at(i);
}
return result;
}
uchar QUIHelper::getCheckCode(const QByteArray &data)
{
int len = data.length();
uchar temp = 0;
for (uchar i = 0; i < len; i++) {
temp += data.at(i);
}
return temp % 256;
}
void QUIHelper::initTableView(QTableView *tableView, int rowHeight, bool headVisible, bool edit, bool stretchLast)
{
//取消自动换行
tableView->setWordWrap(false);
//超出文本不显示省略号
tableView->setTextElideMode(Qt::ElideNone);
//奇数偶数行颜色交替
tableView->setAlternatingRowColors(false);
//垂直表头是否可见
tableView->verticalHeader()->setVisible(headVisible);
//选中一行表头是否加粗
tableView->horizontalHeader()->setHighlightSections(false);
//最后一行拉伸填充
tableView->horizontalHeader()->setStretchLastSection(stretchLast);
//行标题最小宽度尺寸
tableView->horizontalHeader()->setMinimumSectionSize(0);
//行标题最小高度,等同于和默认行高一致
tableView->horizontalHeader()->setFixedHeight(rowHeight);
//默认行高
tableView->verticalHeader()->setDefaultSectionSize(rowHeight);
//选中时一行整体选中
tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
//只允许选择单个
tableView->setSelectionMode(QAbstractItemView::SingleSelection);
//表头不可单击
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
tableView->horizontalHeader()->setSectionsClickable(false);
#else
tableView->horizontalHeader()->setClickable(false);
#endif
//鼠标按下即进入编辑模式
if (edit) {
tableView->setEditTriggers(QAbstractItemView::CurrentChanged | QAbstractItemView::DoubleClicked);
} else {
tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
}
}
void QUIHelper::openFile(const QString &fileName, const QString &msg)
{
#ifdef __arm__
return;
#endif
if (fileName.isEmpty()) {
return;
}
if (QUIHelper::showMessageBoxQuestion(msg + "成功!确定现在就打开吗?") == QMessageBox::Yes) {
QString url = QString("file:///%1").arg(fileName);
QDesktopServices::openUrl(QUrl(url, QUrl::TolerantMode));
}
}
bool QUIHelper::checkIniFile(const QString &iniFile)
{
//如果配置文件大小为0,则以初始值继续运行,并生成配置文件
QFile file(iniFile);
if (file.size() == 0) {
return false;
}
//如果配置文件不完整,则以初始值继续运行,并生成配置文件
if (file.open(QFile::ReadOnly)) {
bool ok = true;
while (!file.atEnd()) {
QString line = file.readLine();
line.replace("\r", "");
line.replace("\n", "");
QStringList list = line.split("=");
if (list.count() == 2) {
if (list.at(1) == "") {
qDebug() << "ini node no value" << list.at(0);
ok = false;
break;
}
}
}
if (!ok) {
return false;
}
} else {
return false;
}
return true;
}

View File

@@ -0,0 +1,70 @@
#ifndef QUIHELPER2_H
#define QUIHELPER2_H
#include "head.h"
class QUIHelper
{
public:
//获取当前鼠标所在屏幕索引+尺寸
static int getScreenIndex();
static QRect getScreenRect(bool available = true);
//获取桌面宽度高度+居中显示
static int deskWidth();
static int deskHeight();
//居中显示窗体
//定义标志位指定是以桌面为参照还是主程序界面为参照
static QWidget *centerBaseForm;
static void setFormInCenter(QWidget *form);
//程序文件名称+当前所在路径
static QString appName();
static QString appPath();
//获取uuid+初始化随机数种子+新建目录+延时
static QString getUuid();
static void initRand();
static void newDir(const QString &dirName);
static void sleep(int msec);
//设置样式+字体+编码+居中+翻译
static void setStyle();
static void setFont(int fontSize = 12);
static void setCode(bool utf8 = true);
static void setTranslator(const QString &qmFile);
//一次性设置所有
static void initAll();
//设置无边框
static void setFramelessForm(QWidget *widgetMain, bool tool = false, bool top = false, bool menu = true);
//弹出框
static int showMessageBox(const QString &info, int type = 0, int closeSec = 0, bool exec = false);
//弹出消息框
static void showMessageBoxInfo(const QString &info, int closeSec = 0, bool exec = false);
//弹出错误框
static void showMessageBoxError(const QString &info, int closeSec = 0, bool exec = false);
//弹出询问框
static int showMessageBoxQuestion(const QString &info);
//异或加密-只支持字符,如果是中文需要将其转换base64编码
static QString getXorEncryptDecrypt(const QString &value, char key);
//异或校验
static uchar getOrCode(const QByteArray &data);
//计算校验码
static uchar 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);
};
#endif // QUIHELPER2_H

View File

@@ -0,0 +1,450 @@
#include "quihelperdata.h"
#include "quihelper.h"
int QUIHelperData::strHexToDecimal(const QString &strHex)
{
bool ok;
return strHex.toInt(&ok, 16);
}
int QUIHelperData::strDecimalToDecimal(const QString &strDecimal)
{
bool ok;
return strDecimal.toInt(&ok, 10);
}
int QUIHelperData::strBinToDecimal(const QString &strBin)
{
bool ok;
return strBin.toInt(&ok, 2);
}
QString QUIHelperData::strHexToStrBin(const QString &strHex)
{
uchar decimal = strHexToDecimal(strHex);
QString bin = QString::number(decimal, 2);
uchar len = bin.length();
if (len < 8) {
for (int i = 0; i < 8 - len; i++) {
bin = "0" + bin;
}
}
return bin;
}
QString QUIHelperData::decimalToStrBin1(int decimal)
{
QString bin = QString::number(decimal, 2);
uchar len = bin.length();
if (len <= 8) {
for (int i = 0; i < 8 - len; i++) {
bin = "0" + bin;
}
}
return bin;
}
QString QUIHelperData::decimalToStrBin2(int decimal)
{
QString bin = QString::number(decimal, 2);
uchar len = bin.length();
if (len <= 16) {
for (int i = 0; i < 16 - len; i++) {
bin = "0" + bin;
}
}
return bin;
}
QString QUIHelperData::decimalToStrHex(int decimal)
{
QString temp = QString::number(decimal, 16);
if (temp.length() == 1) {
temp = "0" + temp;
}
return temp;
}
QByteArray QUIHelperData::intToByte(int data)
{
QByteArray result;
result.resize(4);
result[3] = (uchar)(0x000000ff & data);
result[2] = (uchar)((0x0000ff00 & data) >> 8);
result[1] = (uchar)((0x00ff0000 & data) >> 16);
result[0] = (uchar)((0xff000000 & data) >> 24);
return result;
}
QByteArray QUIHelperData::intToByteRec(int data)
{
QByteArray result;
result.resize(4);
result[0] = (uchar)(0x000000ff & data);
result[1] = (uchar)((0x0000ff00 & data) >> 8);
result[2] = (uchar)((0x00ff0000 & data) >> 16);
result[3] = (uchar)((0xff000000 & data) >> 24);
return result;
}
int QUIHelperData::byteToInt(const QByteArray &data)
{
int i = data.at(3) & 0x000000ff;
i |= ((data.at(2) << 8) & 0x0000ff00);
i |= ((data.at(1) << 16) & 0x00ff0000);
i |= ((data.at(0) << 24) & 0xff000000);
return i;
}
int QUIHelperData::byteToIntRec(const QByteArray &data)
{
int i = data.at(0) & 0x000000ff;
i |= ((data.at(1) << 8) & 0x0000ff00);
i |= ((data.at(2) << 16) & 0x00ff0000);
i |= ((data.at(3) << 24) & 0xff000000);
return i;
}
quint32 QUIHelperData::byteToUInt(const QByteArray &data)
{
quint32 i = data.at(3) & 0x000000ff;
i |= ((data.at(2) << 8) & 0x0000ff00);
i |= ((data.at(1) << 16) & 0x00ff0000);
i |= ((data.at(0) << 24) & 0xff000000);
return i;
}
quint32 QUIHelperData::byteToUIntRec(const QByteArray &data)
{
quint32 i = data.at(0) & 0x000000ff;
i |= ((data.at(1) << 8) & 0x0000ff00);
i |= ((data.at(2) << 16) & 0x00ff0000);
i |= ((data.at(3) << 24) & 0xff000000);
return i;
}
QByteArray QUIHelperData::ushortToByte(ushort data)
{
QByteArray result;
result.resize(2);
result[1] = (uchar)(0x000000ff & data);
result[0] = (uchar)((0x0000ff00 & data) >> 8);
return result;
}
QByteArray QUIHelperData::ushortToByteRec(ushort data)
{
QByteArray result;
result.resize(2);
result[0] = (uchar)(0x000000ff & data);
result[1] = (uchar)((0x0000ff00 & data) >> 8);
return result;
}
int QUIHelperData::byteToUShort(const QByteArray &data)
{
int i = data.at(1) & 0x000000FF;
i |= ((data.at(0) << 8) & 0x0000FF00);
if (i >= 32768) {
i = i - 65536;
}
return i;
}
int QUIHelperData::byteToUShortRec(const QByteArray &data)
{
int i = data.at(0) & 0x000000FF;
i |= ((data.at(1) << 8) & 0x0000FF00);
if (i >= 32768) {
i = i - 65536;
}
return i;
}
QString QUIHelperData::getValue(quint8 value)
{
QString result = QString::number(value);
if (result.length() <= 1) {
result = QString("0%1").arg(result);
}
return result;
}
QString QUIHelperData::getXorEncryptDecrypt(const QString &value, char key)
{
//矫正范围外的数据
if (key < 0 || key >= 127) {
key = 127;
}
QString result = value;
int count = result.count();
for (int i = 0; i < count; i++) {
result[i] = QChar(result.at(i).toLatin1() ^ key);
}
return result;
}
uchar QUIHelperData::getOrCode(const QByteArray &data)
{
int len = data.length();
uchar result = 0;
for (int i = 0; i < len; i++) {
result ^= data.at(i);
}
return result;
}
uchar QUIHelperData::getCheckCode(const QByteArray &data)
{
int len = data.length();
uchar temp = 0;
for (uchar i = 0; i < len; i++) {
temp += data.at(i);
}
return temp % 256;
}
//函数功能计算CRC16
//参数1*data 16位CRC校验数据
//参数2len 数据流长度
//参数3init 初始化值
//参数4table 16位CRC查找表
//正序CRC计算
quint16 QUIHelperData::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 QUIHelperData::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 QUIHelperData::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 QUIHelperData::getCrcCode(const QByteArray &data)
{
quint16 result = getModbus16((quint8 *)data.data(), data.length());
return QUIHelperData::ushortToByteRec(result);
}
static QMap<char, QString> listChar;
void QUIHelperData::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 QUIHelperData::byteArrayToAsciiStr(const QByteArray &data)
{
//先初始化字符表
initAscii();
QString temp;
int len = data.size();
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 QUIHelperData::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);
}
return buffer;
}
char QUIHelperData::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 QUIHelperData::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 QUIHelperData::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();
}

View File

@@ -0,0 +1,70 @@
#ifndef QUIHELPERDATA_H
#define QUIHELPERDATA_H
#include <QObject>
class QUIHelperData
{
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);
static QByteArray intToByteRec(int data);
//字节数组转int
static int byteToInt(const QByteArray &data);
static int byteToIntRec(const QByteArray &data);
static quint32 byteToUInt(const QByteArray &data);
static quint32 byteToUIntRec(const QByteArray &data);
//ushort转字节数组
static QByteArray ushortToByte(ushort data);
static QByteArray ushortToByteRec(ushort data);
//字节数组转ushort
static int byteToUShort(const QByteArray &data);
static int byteToUShortRec(const QByteArray &data);
//字符串补全
static QString getValue(quint8 value);
//异或加密-只支持字符,如果是中文需要将其转换base64编码
static QString getXorEncryptDecrypt(const QString &value, char key);
//异或校验
static uchar getOrCode(const QByteArray &data);
//计算校验码
static uchar getCheckCode(const QByteArray &data);
//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 // QUIHELPERDATA_H

23
tool/comtool/comtool.pro Normal file
View File

@@ -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)

View File

@@ -0,0 +1 @@
01 03 00 00 00 06 C5 C8;01 03 0C 00 01 00 01 00 00 00 01 00 01 00 01 37 DC

View File

@@ -0,0 +1,17 @@
16 FF 01 01 E0 E1
16 FF 01 01 E1 E2
16 01 02 DF BC 16 01 02 DF BC 16 01 02 DF BC 12 13 14 15
16 00 00 04 D0 F0 F1 65 C4
16 00 00 04 D0 05 AB 5A C4
16 01 10 02 F0 03 06 16 01 11 02 F0 03 06 16 01 12 02 F0 03 06 16 01 13 02 F0 03 06 16 01
14 02 F0 03 06 16 01 15 02 F0 03 06 16 01 16 02 F0 03 06
16 11 01 03 E8 01 10 0E
16 11 01 03 E8 01 12 10
16 11 01 03 E8 01 14 12
16 11 01 03 E8 01 15 13
DISARMEDALL
BURGLARY 012
BYPASS 012
DISARMED 012
16 00 01 01 D1 D3
16 01 11 11

View File

@@ -0,0 +1,8 @@
FORMS += \
$$PWD/frmcomtool.ui
HEADERS += \
$$PWD/frmcomtool.h
SOURCES += \
$$PWD/frmcomtool.cpp

View File

@@ -0,0 +1,588 @@
#include "frmcomtool.h"
#include "ui_frmcomtool.h"
#include "quihelper.h"
#include "quihelperdata.h"
frmComTool::frmComTool(QWidget *parent) : QWidget(parent), ui(new Ui::frmComTool)
{
ui->setupUi(this);
this->initForm();
this->initConfig();
QUIHelper::setFormInCenter(this);
}
frmComTool::~frmComTool()
{
delete ui;
}
void frmComTool::initForm()
{
comOk = false;
com = 0;
sleepTime = 10;
receiveCount = 0;
sendCount = 0;
isShow = true;
ui->cboxSendInterval->addItems(AppData::Intervals);
ui->cboxData->addItems(AppData::Datas);
//读取数据
timerRead = new QTimer(this);
timerRead->setInterval(100);
connect(timerRead, SIGNAL(timeout()), this, SLOT(readData()));
//发送数据
timerSend = new QTimer(this);
connect(timerSend, SIGNAL(timeout()), this, SLOT(sendData()));
connect(ui->btnSend, SIGNAL(clicked()), this, SLOT(sendData()));
//保存数据
timerSave = new QTimer(this);
connect(timerSave, SIGNAL(timeout()), this, SLOT(saveData()));
connect(ui->btnSave, SIGNAL(clicked()), this, SLOT(saveData()));
ui->tabWidget->setCurrentIndex(0);
changeEnable(false);
tcpOk = false;
socket = new QTcpSocket(this);
socket->abort();
connect(socket, SIGNAL(readyRead()), this, SLOT(readDataNet()));
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
connect(socket, SIGNAL(errorOccurred(QAbstractSocket::SocketError)), this, SLOT(readErrorNet()));
#else
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(readErrorNet()));
#endif
timerConnect = new QTimer(this);
connect(timerConnect, SIGNAL(timeout()), this, SLOT(connectNet()));
timerConnect->setInterval(3000);
timerConnect->start();
#ifdef __arm__
ui->widgetRight->setFixedWidth(280);
#endif
}
void frmComTool::initConfig()
{
QStringList comList;
for (int i = 1; i <= 20; i++) {
comList << QString("COM%1").arg(i);
}
comList << "ttyUSB0" << "ttyS0" << "ttyS1" << "ttyS2" << "ttyS3" << "ttyS4";
comList << "ttymxc1" << "ttymxc2" << "ttymxc3" << "ttymxc4";
comList << "ttySAC1" << "ttySAC2" << "ttySAC3" << "ttySAC4";
ui->cboxPortName->addItems(comList);
ui->cboxPortName->setCurrentIndex(ui->cboxPortName->findText(AppConfig::PortName));
connect(ui->cboxPortName, SIGNAL(currentIndexChanged(int)), this, SLOT(saveConfig()));
QStringList baudList;
baudList << "50" << "75" << "100" << "134" << "150" << "200" << "300" << "600" << "1200"
<< "1800" << "2400" << "4800" << "9600" << "14400" << "19200" << "38400"
<< "56000" << "57600" << "76800" << "115200" << "128000" << "256000";
ui->cboxBaudRate->addItems(baudList);
ui->cboxBaudRate->setCurrentIndex(ui->cboxBaudRate->findText(QString::number(AppConfig::BaudRate)));
connect(ui->cboxBaudRate, SIGNAL(currentIndexChanged(int)), this, SLOT(saveConfig()));
QStringList dataBitsList;
dataBitsList << "5" << "6" << "7" << "8";
ui->cboxDataBit->addItems(dataBitsList);
ui->cboxDataBit->setCurrentIndex(ui->cboxDataBit->findText(QString::number(AppConfig::DataBit)));
connect(ui->cboxDataBit, SIGNAL(currentIndexChanged(int)), this, SLOT(saveConfig()));
QStringList parityList;
parityList << "" << "" << "";
#ifdef Q_OS_WIN
parityList << "标志";
#endif
parityList << "空格";
ui->cboxParity->addItems(parityList);
ui->cboxParity->setCurrentIndex(ui->cboxParity->findText(AppConfig::Parity));
connect(ui->cboxParity, SIGNAL(currentIndexChanged(int)), this, SLOT(saveConfig()));
QStringList stopBitsList;
stopBitsList << "1";
#ifdef Q_OS_WIN
stopBitsList << "1.5";
#endif
stopBitsList << "2";
ui->cboxStopBit->addItems(stopBitsList);
ui->cboxStopBit->setCurrentIndex(ui->cboxStopBit->findText(QString::number(AppConfig::StopBit)));
connect(ui->cboxStopBit, SIGNAL(currentIndexChanged(int)), this, SLOT(saveConfig()));
ui->ckHexSend->setChecked(AppConfig::HexSend);
connect(ui->ckHexSend, SIGNAL(stateChanged(int)), this, SLOT(saveConfig()));
ui->ckHexReceive->setChecked(AppConfig::HexReceive);
connect(ui->ckHexReceive, SIGNAL(stateChanged(int)), this, SLOT(saveConfig()));
ui->ckDebug->setChecked(AppConfig::Debug);
connect(ui->ckDebug, SIGNAL(stateChanged(int)), this, SLOT(saveConfig()));
ui->ckAutoClear->setChecked(AppConfig::AutoClear);
connect(ui->ckAutoClear, SIGNAL(stateChanged(int)), this, SLOT(saveConfig()));
ui->ckAutoSend->setChecked(AppConfig::AutoSend);
connect(ui->ckAutoSend, SIGNAL(stateChanged(int)), this, SLOT(saveConfig()));
ui->ckAutoSave->setChecked(AppConfig::AutoSave);
connect(ui->ckAutoSave, SIGNAL(stateChanged(int)), this, SLOT(saveConfig()));
QStringList sendInterval;
QStringList saveInterval;
sendInterval << "100" << "300" << "500";
for (int i = 1000; i <= 10000; i = i + 1000) {
sendInterval << QString::number(i);
saveInterval << QString::number(i);
}
ui->cboxSendInterval->addItems(sendInterval);
ui->cboxSaveInterval->addItems(saveInterval);
ui->cboxSendInterval->setCurrentIndex(ui->cboxSendInterval->findText(QString::number(AppConfig::SendInterval)));
connect(ui->cboxSendInterval, SIGNAL(currentIndexChanged(int)), this, SLOT(saveConfig()));
ui->cboxSaveInterval->setCurrentIndex(ui->cboxSaveInterval->findText(QString::number(AppConfig::SaveInterval)));
connect(ui->cboxSaveInterval, SIGNAL(currentIndexChanged(int)), this, SLOT(saveConfig()));
timerSend->setInterval(AppConfig::SendInterval);
timerSave->setInterval(AppConfig::SaveInterval);
if (AppConfig::AutoSend) {
timerSend->start();
}
if (AppConfig::AutoSave) {
timerSave->start();
}
//串口转网络部分
ui->cboxMode->setCurrentIndex(ui->cboxMode->findText(AppConfig::Mode));
connect(ui->cboxMode, SIGNAL(currentIndexChanged(int)), this, SLOT(saveConfig()));
ui->txtServerIP->setText(AppConfig::ServerIP);
connect(ui->txtServerIP, SIGNAL(textChanged(QString)), this, SLOT(saveConfig()));
ui->txtServerPort->setText(QString::number(AppConfig::ServerPort));
connect(ui->txtServerPort, SIGNAL(textChanged(QString)), this, SLOT(saveConfig()));
ui->txtListenPort->setText(QString::number(AppConfig::ListenPort));
connect(ui->txtListenPort, SIGNAL(textChanged(QString)), this, SLOT(saveConfig()));
QStringList values;
values << "0" << "10" << "50";
for (int i = 100; i < 1000; i = i + 100) {
values << QString("%1").arg(i);
}
ui->cboxSleepTime->addItems(values);
ui->cboxSleepTime->setCurrentIndex(ui->cboxSleepTime->findText(QString::number(AppConfig::SleepTime)));
connect(ui->cboxSleepTime, SIGNAL(currentIndexChanged(int)), this, SLOT(saveConfig()));
ui->ckAutoConnect->setChecked(AppConfig::AutoConnect);
connect(ui->ckAutoConnect, SIGNAL(stateChanged(int)), this, SLOT(saveConfig()));
}
void frmComTool::saveConfig()
{
AppConfig::PortName = ui->cboxPortName->currentText();
AppConfig::BaudRate = ui->cboxBaudRate->currentText().toInt();
AppConfig::DataBit = ui->cboxDataBit->currentText().toInt();
AppConfig::Parity = ui->cboxParity->currentText();
AppConfig::StopBit = ui->cboxStopBit->currentText().toDouble();
AppConfig::HexSend = ui->ckHexSend->isChecked();
AppConfig::HexReceive = ui->ckHexReceive->isChecked();
AppConfig::Debug = ui->ckDebug->isChecked();
AppConfig::AutoClear = ui->ckAutoClear->isChecked();
AppConfig::AutoSend = ui->ckAutoSend->isChecked();
AppConfig::AutoSave = ui->ckAutoSave->isChecked();
int sendInterval = ui->cboxSendInterval->currentText().toInt();
if (sendInterval != AppConfig::SendInterval) {
AppConfig::SendInterval = sendInterval;
timerSend->setInterval(AppConfig::SendInterval);
}
int saveInterval = ui->cboxSaveInterval->currentText().toInt();
if (saveInterval != AppConfig::SaveInterval) {
AppConfig::SaveInterval = saveInterval;
timerSave->setInterval(AppConfig::SaveInterval);
}
AppConfig::Mode = ui->cboxMode->currentText();
AppConfig::ServerIP = ui->txtServerIP->text().trimmed();
AppConfig::ServerPort = ui->txtServerPort->text().toInt();
AppConfig::ListenPort = ui->txtListenPort->text().toInt();
AppConfig::SleepTime = ui->cboxSleepTime->currentText().toInt();
AppConfig::AutoConnect = ui->ckAutoConnect->isChecked();
AppConfig::writeConfig();
}
void frmComTool::changeEnable(bool b)
{
ui->cboxBaudRate->setEnabled(!b);
ui->cboxDataBit->setEnabled(!b);
ui->cboxParity->setEnabled(!b);
ui->cboxPortName->setEnabled(!b);
ui->cboxStopBit->setEnabled(!b);
ui->btnSend->setEnabled(b);
ui->ckAutoSend->setEnabled(b);
ui->ckAutoSave->setEnabled(b);
}
void frmComTool::append(int type, const QString &data, bool clear)
{
static int currentCount = 0;
static int maxCount = 100;
if (clear) {
ui->txtMain->clear();
currentCount = 0;
return;
}
if (currentCount >= maxCount) {
ui->txtMain->clear();
currentCount = 0;
}
if (!isShow) {
return;
}
//过滤回车换行符
QString strData = data;
strData = strData.replace("\r", "");
strData = strData.replace("\n", "");
//不同类型不同颜色显示
QString strType;
if (type == 0) {
strType = "串口发送 >>";
ui->txtMain->setTextColor(QColor("dodgerblue"));
} else if (type == 1) {
strType = "串口接收 <<";
ui->txtMain->setTextColor(QColor("red"));
} else if (type == 2) {
strType = "处理延时 >>";
ui->txtMain->setTextColor(QColor("gray"));
} else if (type == 3) {
strType = "正在校验 >>";
ui->txtMain->setTextColor(QColor("green"));
} else if (type == 4) {
strType = "网络发送 >>";
ui->txtMain->setTextColor(QColor(24, 189, 155));
} else if (type == 5) {
strType = "网络接收 <<";
ui->txtMain->setTextColor(QColor(255, 107, 107));
} else if (type == 6) {
strType = "提示信息 >>";
ui->txtMain->setTextColor(QColor(100, 184, 255));
}
strData = QString("时间[%1] %2 %3").arg(TIMEMS).arg(strType).arg(strData);
ui->txtMain->append(strData);
currentCount++;
}
void frmComTool::readData()
{
if (com->bytesAvailable() <= 0) {
return;
}
QUIHelper::sleep(sleepTime);
QByteArray data = com->readAll();
int dataLen = data.length();
if (dataLen <= 0) {
return;
}
if (isShow) {
QString buffer;
if (ui->ckHexReceive->isChecked()) {
buffer = QUIHelperData::byteArrayToHexStr(data);
} else {
//buffer = QUIHelperData::byteArrayToAsciiStr(data);
buffer = QString::fromLocal8Bit(data);
}
//启用调试则模拟调试数据
if (ui->ckDebug->isChecked()) {
int count = AppData::Keys.count();
for (int i = 0; i < count; i++) {
if (buffer.startsWith(AppData::Keys.at(i))) {
sendData(AppData::Values.at(i));
break;
}
}
}
append(1, buffer);
receiveCount = receiveCount + data.size();
ui->btnReceiveCount->setText(QString("接收 : %1 字节").arg(receiveCount));
//启用网络转发则调用网络发送数据
if (tcpOk) {
socket->write(data);
append(4, QString(buffer));
}
}
}
void frmComTool::sendData()
{
QString str = ui->cboxData->currentText();
if (str.isEmpty()) {
ui->cboxData->setFocus();
return;
}
sendData(str);
if (ui->ckAutoClear->isChecked()) {
ui->cboxData->setCurrentIndex(-1);
ui->cboxData->setFocus();
}
}
void frmComTool::sendData(QString data)
{
if (com == 0 || !com->isOpen()) {
return;
}
//短信猫调试
if (data.startsWith("AT")) {
data += "\r";
}
QByteArray buffer;
if (ui->ckHexSend->isChecked()) {
buffer = QUIHelperData::hexStrToByteArray(data);
} else {
buffer = QUIHelperData::asciiStrToByteArray(data);
}
com->write(buffer);
append(0, data);
sendCount = sendCount + buffer.size();
ui->btnSendCount->setText(QString("发送 : %1 字节").arg(sendCount));
}
void frmComTool::saveData()
{
QString tempData = ui->txtMain->toPlainText();
if (tempData == "") {
return;
}
QDateTime now = QDateTime::currentDateTime();
QString name = now.toString("yyyy-MM-dd-HH-mm-ss");
QString fileName = QString("%1/%2.txt").arg(QUIHelper::appPath()).arg(name);
QFile file(fileName);
file.open(QFile::WriteOnly | QIODevice::Text);
QTextStream out(&file);
out << tempData;
file.close();
on_btnClear_clicked();
}
void frmComTool::on_btnOpen_clicked()
{
if (ui->btnOpen->text() == "打开串口") {
com = new QextSerialPort(ui->cboxPortName->currentText(), QextSerialPort::Polling);
comOk = com->open(QIODevice::ReadWrite);
if (comOk) {
//清空缓冲区
com->flush();
//设置波特率
com->setBaudRate((BaudRateType)ui->cboxBaudRate->currentText().toInt());
//设置数据位
com->setDataBits((DataBitsType)ui->cboxDataBit->currentText().toInt());
//设置校验位
com->setParity((ParityType)ui->cboxParity->currentIndex());
//设置停止位
com->setStopBits((StopBitsType)ui->cboxStopBit->currentIndex());
com->setFlowControl(FLOW_OFF);
com->setTimeout(10);
changeEnable(true);
ui->btnOpen->setText("关闭串口");
timerRead->start();
}
} else {
timerRead->stop();
com->close();
com->deleteLater();
changeEnable(false);
ui->btnOpen->setText("打开串口");
on_btnClear_clicked();
comOk = false;
}
}
void frmComTool::on_btnSendCount_clicked()
{
sendCount = 0;
ui->btnSendCount->setText("发送 : 0 字节");
}
void frmComTool::on_btnReceiveCount_clicked()
{
receiveCount = 0;
ui->btnReceiveCount->setText("接收 : 0 字节");
}
void frmComTool::on_btnStopShow_clicked()
{
if (ui->btnStopShow->text() == "停止显示") {
isShow = false;
ui->btnStopShow->setText("开始显示");
} else {
isShow = true;
ui->btnStopShow->setText("停止显示");
}
}
void frmComTool::on_btnData_clicked()
{
QString fileName = QString("%1/%2").arg(QUIHelper::appPath()).arg("send.txt");
QFile file(fileName);
if (!file.exists()) {
return;
}
if (ui->btnData->text() == "管理数据") {
ui->txtMain->setReadOnly(false);
ui->txtMain->clear();
file.open(QFile::ReadOnly | QIODevice::Text);
QTextStream in(&file);
ui->txtMain->setText(in.readAll());
file.close();
ui->btnData->setText("保存数据");
} else {
ui->txtMain->setReadOnly(true);
file.open(QFile::WriteOnly | QIODevice::Text);
QTextStream out(&file);
out << ui->txtMain->toPlainText();
file.close();
ui->txtMain->clear();
ui->btnData->setText("管理数据");
AppData::readSendData();
}
}
void frmComTool::on_btnClear_clicked()
{
append(0, "", true);
}
void frmComTool::on_btnStart_clicked()
{
if (ui->btnStart->text() == "启动") {
if (AppConfig::ServerIP == "" || AppConfig::ServerPort == 0) {
append(6, "IP地址和远程端口不能为空");
return;
}
socket->connectToHost(AppConfig::ServerIP, AppConfig::ServerPort);
if (socket->waitForConnected(100)) {
ui->btnStart->setText("停止");
append(6, "连接服务器成功");
tcpOk = true;
}
} else {
socket->disconnectFromHost();
if (socket->state() == QAbstractSocket::UnconnectedState || socket->waitForDisconnected(100)) {
ui->btnStart->setText("启动");
append(6, "断开服务器成功");
tcpOk = false;
}
}
}
void frmComTool::on_ckAutoSend_stateChanged(int arg1)
{
if (arg1 == 0) {
ui->cboxSendInterval->setEnabled(false);
timerSend->stop();
} else {
ui->cboxSendInterval->setEnabled(true);
timerSend->start();
}
}
void frmComTool::on_ckAutoSave_stateChanged(int arg1)
{
if (arg1 == 0) {
ui->cboxSaveInterval->setEnabled(false);
timerSave->stop();
} else {
ui->cboxSaveInterval->setEnabled(true);
timerSave->start();
}
}
void frmComTool::connectNet()
{
if (!tcpOk && AppConfig::AutoConnect && ui->btnStart->text() == "启动") {
if (AppConfig::ServerIP != "" && AppConfig::ServerPort != 0) {
socket->connectToHost(AppConfig::ServerIP, AppConfig::ServerPort);
if (socket->waitForConnected(100)) {
ui->btnStart->setText("停止");
append(6, "连接服务器成功");
tcpOk = true;
}
}
}
}
void frmComTool::readDataNet()
{
if (socket->bytesAvailable() > 0) {
QUIHelper::sleep(AppConfig::SleepTime);
QByteArray data = socket->readAll();
QString buffer;
if (ui->ckHexReceive->isChecked()) {
buffer = QUIHelperData::byteArrayToHexStr(data);
} else {
buffer = QUIHelperData::byteArrayToAsciiStr(data);
}
append(5, buffer);
//将收到的网络数据转发给串口
if (comOk) {
com->write(data);
append(0, buffer);
}
}
}
void frmComTool::readErrorNet()
{
ui->btnStart->setText("启动");
append(6, QString("连接服务器失败,%1").arg(socket->errorString()));
socket->disconnectFromHost();
tcpOk = false;
}

View File

@@ -0,0 +1,68 @@
#ifndef FRMCOMTOOL_H
#define FRMCOMTOOL_H
#include <QWidget>
#include "qtcpsocket.h"
#include "qextserialport.h"
namespace Ui
{
class frmComTool;
}
class frmComTool : public QWidget
{
Q_OBJECT
public:
explicit frmComTool(QWidget *parent = 0);
~frmComTool();
private:
Ui::frmComTool *ui;
bool comOk; //串口是否打开
QextSerialPort *com; //串口通信对象
QTimer *timerRead; //定时读取串口数据
QTimer *timerSend; //定时发送串口数据
QTimer *timerSave; //定时保存串口数据
int sleepTime; //接收延时时间
int sendCount; //发送数据计数
int receiveCount; //接收数据计数
bool isShow; //是否显示数据
bool tcpOk; //网络是否正常
QTcpSocket *socket; //网络连接对象
QTimer *timerConnect; //定时器重连
private slots:
void initForm(); //初始化窗体数据
void initConfig(); //初始化配置文件
void saveConfig(); //保存配置文件
void readData(); //读取串口数据
void sendData(); //发送串口数据
void sendData(QString data);//发送串口数据带参数
void saveData(); //保存串口数据
void changeEnable(bool b); //改变状态
void append(int type, const QString &data, bool clear = false);
private slots:
void connectNet();
void readDataNet();
void readErrorNet();
private slots:
void on_btnOpen_clicked();
void on_btnStopShow_clicked();
void on_btnSendCount_clicked();
void on_btnReceiveCount_clicked();
void on_btnClear_clicked();
void on_btnData_clicked();
void on_btnStart_clicked();
void on_ckAutoSend_stateChanged(int arg1);
void on_ckAutoSave_stateChanged(int arg1);
};
#endif // FRMCOMTOOL_H

View File

@@ -0,0 +1,533 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>frmComTool</class>
<widget class="QWidget" name="frmComTool">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_6">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="QTextEdit" name="txtMain">
<property name="enabled">
<bool>true</bool>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1" rowspan="2">
<widget class="QWidget" name="widgetRight" native="true">
<property name="minimumSize">
<size>
<width>180</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>180</width>
<height>16777215</height>
</size>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QFrame" name="frameTop">
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="labPortName">
<property name="text">
<string>串口号</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="cboxPortName">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labBaudRate">
<property name="text">
<string>波特率</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="cboxBaudRate">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labDataBit">
<property name="text">
<string>数据位</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="cboxDataBit">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="labParity">
<property name="text">
<string>校验位</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="cboxParity">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="labStopBit">
<property name="text">
<string>停止位</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="cboxStopBit">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="5" column="0" colspan="2">
<widget class="QPushButton" name="btnOpen">
<property name="text">
<string>打开串口</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="tabPosition">
<enum>QTabWidget::South</enum>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>串口配置</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_5">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="QCheckBox" name="ckHexSend">
<property name="text">
<string>Hex发送</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="ckHexReceive">
<property name="text">
<string>Hex接收</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="ckDebug">
<property name="text">
<string>模拟设备</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="ckAutoClear">
<property name="text">
<string>自动清空</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QCheckBox" name="ckAutoSend">
<property name="text">
<string>自动发送</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="cboxSendInterval">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="ckAutoSave">
<property name="text">
<string>自动保存</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="cboxSaveInterval">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0" colspan="2">
<widget class="QPushButton" name="btnSendCount">
<property name="text">
<string>发送 : 0 字节</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QPushButton" name="btnReceiveCount">
<property name="text">
<string>接收 : 0 字节</string>
</property>
</widget>
</item>
<item row="5" column="0" colspan="2">
<widget class="QPushButton" name="btnStopShow">
<property name="text">
<string>停止显示</string>
</property>
</widget>
</item>
<item row="6" column="0" colspan="2">
<widget class="QPushButton" name="btnSave">
<property name="text">
<string>保存数据</string>
</property>
</widget>
</item>
<item row="7" column="0" colspan="2">
<widget class="QPushButton" name="btnData">
<property name="text">
<string>管理数据</string>
</property>
</widget>
</item>
<item row="8" column="0" colspan="2">
<widget class="QPushButton" name="btnClear">
<property name="text">
<string>清空数据</string>
</property>
</widget>
</item>
<item row="9" column="0" colspan="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>2</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>网络配置</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0" colspan="2">
<layout class="QGridLayout" name="gridLayout_4">
<item row="3" column="0">
<widget class="QLabel" name="labListenPort">
<property name="text">
<string>监听端口</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labServerIP">
<property name="text">
<string>远程地址</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="cboxSleepTime"/>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="txtServerIP">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labServerPort">
<property name="text">
<string>远程端口</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="txtServerPort">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="labSleepTime">
<property name="text">
<string>延时时间</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="txtListenPort"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="labMode">
<property name="text">
<string>转换模式</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="cboxMode">
<item>
<property name="text">
<string>Tcp_Client</string>
</property>
</item>
<item>
<property name="text">
<string>Tcp_Server</string>
</property>
</item>
<item>
<property name="text">
<string>Udp_Client</string>
</property>
</item>
<item>
<property name="text">
<string>Udp_Server</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item row="2" column="0" colspan="2">
<widget class="QPushButton" name="btnStart">
<property name="text">
<string>启动</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>59</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0" colspan="2">
<widget class="QCheckBox" name="ckAutoConnect">
<property name="text">
<string>自动重连网络</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QWidget" name="widget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QComboBox" name="cboxData">
<property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="editable">
<bool>true</bool>
</property>
<property name="duplicatesEnabled">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnSend">
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>发送</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

18
tool/comtool/head.h Normal file
View File

@@ -0,0 +1,18 @@
#include <QtCore>
#include <QtGui>
#include <QtNetwork>
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
#include <QtWidgets>
#endif
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
#include <QtCore5Compat>
#endif
#pragma execution_character_set("utf-8")
#define TIMEMS qPrintable(QTime::currentTime().toString("HH:mm:ss zzz"))
#define STRDATETIME qPrintable(QDateTime::currentDateTime().toString("yyyy-MM-dd-HH-mm-ss"))
#include "appconfig.h"
#include "appdata.h"

26
tool/comtool/main.cpp Normal file
View File

@@ -0,0 +1,26 @@
#include "frmcomtool.h"
#include "quihelper.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
a.setWindowIcon(QIcon(":/main.ico"));
//设置编码以及加载中文翻译文件
QUIHelper::initAll();
//读取配置文件
AppConfig::ConfigFile = QString("%1/%2.ini").arg(QUIHelper::appPath()).arg(QUIHelper::appName());
AppConfig::readConfig();
AppData::Intervals << "1" << "10" << "20" << "50" << "100" << "200" << "300" << "500" << "1000" << "1500" << "2000" << "3000" << "5000" << "10000";
AppData::readSendData();
AppData::readDeviceData();
frmComTool w;
w.setWindowTitle("串口调试助手 V2022 (QQ: 517216493 WX: feiyangqingyun)");
w.resize(900, 650);
QUIHelper::setFormInCenter(&w);
w.show();
return a.exec();
}

BIN
tool/comtool/qrc/main.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

View File

@@ -0,0 +1,7 @@
<RCC>
<qresource prefix="/">
<file>main.ico</file>
<file>qm/qt_zh_CN.qm</file>
<file>qm/widgets.qm</file>
</qresource>
</RCC>

1
tool/comtool/qrc/main.rc Normal file
View File

@@ -0,0 +1 @@
IDI_ICON1 ICON DISCARDABLE "main.ico"

Binary file not shown.

Binary file not shown.

18
tool/comtool/readme.md Normal file
View File

@@ -0,0 +1,18 @@
**<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
1. ֧<><D6A7>16<31><36><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݷ<EFBFBD><DDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ա<EFBFBD>
2. ֧<><D6A7>windows<77><73>COM9<4D><39><EFBFBD>ϵĴ<CFB5><C4B4><EFBFBD>ͨ<EFBFBD>š<EFBFBD>
3. ʵʱ<CAB5><CAB1>ʾ<EFBFBD>շ<EFBFBD><D5B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽڴ<D6BD>С<EFBFBD>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD><EFBFBD>״̬<D7B4><CCAC>
4. ֧<><D6A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>qt<71><EFBFBD><E6B1BE><EFBFBD>ײ<EFBFBD>4.7.0 <20><> 6.1<EFBFBD><EFBFBD>
5. ֧<>ִ<EFBFBD><D6B4><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>շ<EFBFBD><D5B7><EFBFBD>
**<EFBFBD>߼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
1. <20><><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD><C9B9><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>͵<EFBFBD><CDB5><EFBFBD><EFBFBD>ݣ<EFBFBD>ÿ<EFBFBD><C3BF>ֻҪ<D6BB><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD>ݼ<EFBFBD><DDBC>ɣ<EFBFBD><C9A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݡ<EFBFBD>
2. <20><>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD>ݣ<EFBFBD><DDA3><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E6BFAA>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD>ݡ<EFBFBD><DDA1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD>úõ<C3BA>ָ<EFBFBD><D6B8>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD>õĻظ<C4BB>ָ<EFBFBD><EFBFBD><EEA1A3><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD>յ<EFBFBD>0x16 0x00 0xFF 0x01<30><31>Ҫ<EFBFBD>ظ<EFBFBD>0x16 0x00 0xFE 0x01<30><31><EFBFBD><EFBFBD>ֻ<EFBFBD><D6BB>Ҫ<EFBFBD><D2AA>SendData.txt<78><74><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>16 00 FF 01:16 00 FE 01<30><31><EFBFBD>ɡ<EFBFBD>
3. <20>ɶ<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݺͱ<DDBA><CDB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD><DDB5>ı<EFBFBD><C4B1>ļ<EFBFBD>:<3A><>Ĭ<EFBFBD>ϼ<EFBFBD><CFBC><EFBFBD>5<EFBFBD><35><EFBFBD>ӣ<EFBFBD><D3A3>ɸ<EFBFBD><C9B8>ļ<EFBFBD><C4BC><EFBFBD>ʱ<EFBFBD>
4. <20>ڲ<EFBFBD><DAB2>Ͻ<EFBFBD><CFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD><CDA3>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E9BFB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><DDA3><EFBFBD>̨<EFBFBD><CCA8>Ȼ<EFBFBD><C8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD><DDB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>رմ<D8B1><D5B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѽ<EFBFBD><D1BD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݡ<EFBFBD>
5. ÿ<><C3BF><EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݶ<EFBFBD><DDB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><DDA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѽڵģ<DAB5><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
6. һ<><D2BB>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><E6B4A6><EFBFBD><EFBFBD><EBA3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><E0A3AC><EFBFBD><EFBFBD>XP/WIN7/UBUNTU/ARMLINUXϵͳ<CFB5>³ɹ<C2B3><C9B9><EFBFBD><EFBFBD><EFBFBD><EBB2A2><EFBFBD>С<EFBFBD>
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><EFBFBD>**
1. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>뽫Դ<EBBDAB><D4B4><EFBFBD>µ<EFBFBD>fileĿ¼<C4BF>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>Ƶ<EFBFBD><C6B5><EFBFBD>ִ<EFBFBD><D6B4><EFBFBD>ļ<EFBFBD>ͬһĿ¼<C4BF><C2BC>
2. <20><><EFBFBD><EFBFBD><EFBFBD>и<EFBFBD><D0B8>õĽ<C3B5><C4BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD>лл<D0BB><D0BB>

View File

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

View File

@@ -0,0 +1,279 @@
#pragma execution_character_set("utf-8")
#include "frmcountcode.h"
#include "ui_frmcountcode.h"
#include "qfile.h"
#include "qtextstream.h"
#include "qfiledialog.h"
#include "qfileinfo.h"
#include "qdebug.h"
frmCountCode::frmCountCode(QWidget *parent) : QWidget(parent), ui(new Ui::frmCountCode)
{
ui->setupUi(this);
this->initForm();
on_btnClear_clicked();
}
frmCountCode::~frmCountCode()
{
delete ui;
}
void frmCountCode::initForm()
{
QStringList headText;
headText << "文件名" << "类型" << "大小" << "总行数" << "代码行数" << "注释行数" << "空白行数" << "路径";
QList<int> columnWidth;
columnWidth << 130 << 50 << 70 << 80 << 70 << 70 << 70 << 150;
int columnCount = headText.count();
ui->tableWidget->setColumnCount(columnCount);
ui->tableWidget->setHorizontalHeaderLabels(headText);
ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui->tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
ui->tableWidget->verticalHeader()->setVisible(false);
ui->tableWidget->horizontalHeader()->setStretchLastSection(true);
ui->tableWidget->horizontalHeader()->setHighlightSections(false);
ui->tableWidget->verticalHeader()->setDefaultSectionSize(20);
ui->tableWidget->verticalHeader()->setHighlightSections(false);
for (int i = 0; i < columnCount; i++) {
ui->tableWidget->setColumnWidth(i, columnWidth.at(i));
}
//设置前景色
ui->txtCount->setStyleSheet("color:#17A086;");
ui->txtSize->setStyleSheet("color:#CA5AA6;");
ui->txtRow->setStyleSheet("color:#CD1B19;");
ui->txtCode->setStyleSheet("color:#22A3A9;");
ui->txtNote->setStyleSheet("color:#D64D54;");
ui->txtBlank->setStyleSheet("color:#A279C5;");
//设置字体加粗
QFont font;
font.setBold(true);
if (font.pointSize() > 0) {
font.setPointSize(font.pointSize() + 1);
} else {
font.setPixelSize(font.pixelSize() + 2);
}
ui->txtCount->setFont(font);
ui->txtSize->setFont(font);
ui->txtRow->setFont(font);
ui->txtCode->setFont(font);
ui->txtNote->setFont(font);
ui->txtBlank->setFont(font);
#if (QT_VERSION > QT_VERSION_CHECK(4,7,0))
ui->txtFilter->setPlaceholderText("中间空格隔开,例如 *.h *.cpp *.c");
#endif
}
bool frmCountCode::checkFile(const QString &fileName)
{
if (fileName.startsWith("moc_") || fileName.startsWith("ui_") || fileName.startsWith("qrc_")) {
return false;
}
QFileInfo file(fileName);
QString suffix = "*." + file.suffix();
QString filter = ui->txtFilter->text().trimmed();
QStringList filters = filter.split(" ");
return filters.contains(suffix);
}
void frmCountCode::countCode(const QString &filePath)
{
QDir dir(filePath);
QFileInfoList fileInfos = dir.entryInfoList();
foreach (QFileInfo fileInfo, fileInfos) {
QString fileName = fileInfo.fileName();
if (fileInfo.isFile()) {
if (checkFile(fileName)) {
listFile << fileInfo.filePath();
}
} else {
if (fileName == "." || fileName == "..") {
continue;
}
//递归找出文件
countCode(fileInfo.absoluteFilePath());
}
}
}
void frmCountCode::countCode(const QStringList &files)
{
int lineCode;
int lineBlank;
int lineNotes;
int count = files.count();
on_btnClear_clicked();
ui->tableWidget->setRowCount(count);
quint32 totalLines = 0;
quint32 totalBytes = 0;
quint32 totalCodes = 0;
quint32 totalNotes = 0;
quint32 totalBlanks = 0;
for (int i = 0; i < count; i++) {
QFileInfo fileInfo(files.at(i));
countCode(fileInfo.filePath(), lineCode, lineBlank, lineNotes);
int lineAll = lineCode + lineBlank + lineNotes;
QTableWidgetItem *itemName = new QTableWidgetItem;
itemName->setText(fileInfo.fileName());
QTableWidgetItem *itemSuffix = new QTableWidgetItem;
itemSuffix->setText(fileInfo.suffix());
QTableWidgetItem *itemSize = new QTableWidgetItem;
itemSize->setText(QString::number(fileInfo.size()));
QTableWidgetItem *itemLine = new QTableWidgetItem;
itemLine->setText(QString::number(lineAll));
QTableWidgetItem *itemCode = new QTableWidgetItem;
itemCode->setText(QString::number(lineCode));
QTableWidgetItem *itemNote = new QTableWidgetItem;
itemNote->setText(QString::number(lineNotes));
QTableWidgetItem *itemBlank = new QTableWidgetItem;
itemBlank->setText(QString::number(lineBlank));
QTableWidgetItem *itemPath = new QTableWidgetItem;
itemPath->setText(fileInfo.filePath());
itemSuffix->setTextAlignment(Qt::AlignCenter);
itemSize->setTextAlignment(Qt::AlignCenter);
itemLine->setTextAlignment(Qt::AlignCenter);
itemCode->setTextAlignment(Qt::AlignCenter);
itemNote->setTextAlignment(Qt::AlignCenter);
itemBlank->setTextAlignment(Qt::AlignCenter);
ui->tableWidget->setItem(i, 0, itemName);
ui->tableWidget->setItem(i, 1, itemSuffix);
ui->tableWidget->setItem(i, 2, itemSize);
ui->tableWidget->setItem(i, 3, itemLine);
ui->tableWidget->setItem(i, 4, itemCode);
ui->tableWidget->setItem(i, 5, itemNote);
ui->tableWidget->setItem(i, 6, itemBlank);
ui->tableWidget->setItem(i, 7, itemPath);
totalBytes += fileInfo.size();
totalLines += lineAll;
totalCodes += lineCode;
totalNotes += lineNotes;
totalBlanks += lineBlank;
if (i % 100 == 0) {
qApp->processEvents();
}
}
//显示统计结果
listFile.clear();
ui->txtCount->setText(QString::number(count));
ui->txtSize->setText(QString::number(totalBytes));
ui->txtRow->setText(QString::number(totalLines));
ui->txtCode->setText(QString::number(totalCodes));
ui->txtNote->setText(QString::number(totalNotes));
ui->txtBlank->setText(QString::number(totalBlanks));
//计算百分比
double percent = 0.0;
//代码行所占百分比
percent = ((double)totalCodes / totalLines) * 100;
ui->labPercentCode->setText(QString("%1%").arg(percent, 5, 'f', 2, QChar(' ')));
//注释行所占百分比
percent = ((double)totalNotes / totalLines) * 100;
ui->labPercentNote->setText(QString("%1%").arg(percent, 5, 'f', 2, QChar(' ')));
//空行所占百分比
percent = ((double)totalBlanks / totalLines) * 100;
ui->labPercentBlank->setText(QString("%1%").arg(percent, 5, 'f', 2, QChar(' ')));
}
void frmCountCode::countCode(const QString &fileName, int &lineCode, int &lineBlank, int &lineNotes)
{
lineCode = lineBlank = lineNotes = 0;
QFile file(fileName);
if (file.open(QFile::ReadOnly)) {
QTextStream out(&file);
QString line;
bool isNote = false;
while (!out.atEnd()) {
line = out.readLine();
//移除前面的空行
if (line.startsWith(" ")) {
line.remove(" ");
}
//判断当前行是否是注释
if (line.startsWith("/*")) {
isNote = true;
}
//注释部分
if (isNote) {
lineNotes++;
} else {
if (line.startsWith("//")) { //注释行
lineNotes++;
} else if (line.isEmpty()) { //空白行
lineBlank++;
} else { //代码行
lineCode++;
}
}
//注释结束
if (line.endsWith("*/")) {
isNote = false;
}
}
}
}
void frmCountCode::on_btnOpenFile_clicked()
{
QString filter = QString("代码文件(%1)").arg(ui->txtFilter->text().trimmed());
QStringList files = QFileDialog::getOpenFileNames(this, "选择文件", "./", filter);
if (files.size() > 0) {
ui->txtFile->setText(files.join("|"));
countCode(files);
}
}
void frmCountCode::on_btnOpenPath_clicked()
{
QString path = QFileDialog::getExistingDirectory(this, "选择目录", "./", QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
if (!path.isEmpty()) {
ui->txtPath->setText(path);
listFile.clear();
countCode(path);
countCode(listFile);
}
}
void frmCountCode::on_btnClear_clicked()
{
ui->txtCount->setText("0");
ui->txtSize->setText("0");
ui->txtRow->setText("0");
ui->txtCode->setText("0");
ui->txtNote->setText("0");
ui->txtBlank->setText("0");
ui->labPercentCode->setText("0%");
ui->labPercentNote->setText("0%");
ui->labPercentBlank->setText("0%");
ui->tableWidget->setRowCount(0);
}

View File

@@ -0,0 +1,35 @@
#ifndef FRMCOUNTCODE_H
#define FRMCOUNTCODE_H
#include <QWidget>
namespace Ui {
class frmCountCode;
}
class frmCountCode : public QWidget
{
Q_OBJECT
public:
explicit frmCountCode(QWidget *parent = 0);
~frmCountCode();
private:
Ui::frmCountCode *ui;
QStringList listFile;
private:
void initForm();
bool checkFile(const QString &fileName);
void countCode(const QString &filePath);
void countCode(const QStringList &files);
void countCode(const QString &fileName, int &lineCode, int &lineBlank, int &lineNotes);
private slots:
void on_btnOpenFile_clicked();
void on_btnOpenPath_clicked();
void on_btnClear_clicked();
};
#endif // FRMCOUNTCODE_H

View File

@@ -0,0 +1,411 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>frmCountCode</class>
<widget class="QWidget" name="frmCountCode">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QTableWidget" name="tableWidget"/>
</item>
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0" rowspan="3">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="3">
<widget class="QLineEdit" name="txtCode">
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="txtRow">
<property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLineEdit" name="txtNote">
<property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QLineEdit" name="txtBlank">
<property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="txtCount">
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QLabel" name="labPercentCode">
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</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="2" column="2">
<widget class="QLabel" name="labBlank">
<property name="text">
<string>空白行数</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="txtSize">
<property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="5">
<widget class="QLabel" name="labFilter">
<property name="text">
<string>过滤</string>
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="QLabel" name="labFile">
<property name="text">
<string>文件</string>
</property>
</widget>
</item>
<item row="1" column="6">
<widget class="QLineEdit" name="txtPath">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="6">
<widget class="QLineEdit" name="txtFile">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="5">
<widget class="QLabel" name="labPath">
<property name="text">
<string>目录</string>
</property>
</widget>
</item>
<item row="2" column="6">
<widget class="QLineEdit" name="txtFilter">
<property name="text">
<string>*.h *.cpp *.c *.cs *.java *.js</string>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QLabel" name="labPercentNote">
<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="2" column="4">
<widget class="QLabel" name="labPercentBlank">
<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="0" column="0">
<widget class="QLabel" name="labCount">
<property name="text">
<string>文件数</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="labCode">
<property name="text">
<string>代码行数</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="labNote">
<property name="text">
<string>注释行数</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labSize">
<property name="text">
<string>字节数</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labRow">
<property name="text">
<string>总行数</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="btnOpenFile">
<property name="text">
<string>打开文件</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="btnOpenPath">
<property name="text">
<string>打开目录</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="btnClear">
<property name="text">
<string>清空结果</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
<action name="actionOpen">
<property name="icon">
<iconset>
<normaloff>:/images/toolbar/ic_files.png</normaloff>:/images/toolbar/ic_files.png</iconset>
</property>
<property name="text">
<string>选择文件</string>
</property>
<property name="shortcut">
<string>Ctrl+O</string>
</property>
</action>
<action name="actionOpenDir">
<property name="icon">
<iconset>
<normaloff>:/images/toolbar/ic_folder.png</normaloff>:/images/toolbar/ic_folder.png</iconset>
</property>
<property name="text">
<string>选择目录</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+O</string>
</property>
</action>
<action name="actionAbout">
<property name="icon">
<iconset>
<normaloff>:/images/toolbar/ic_about.png</normaloff>:/images/toolbar/ic_about.png</iconset>
</property>
<property name="text">
<string>关于</string>
</property>
</action>
<action name="actionClearModel">
<property name="icon">
<iconset>
<normaloff>:/images/toolbar/ic_clean.png</normaloff>:/images/toolbar/ic_clean.png</iconset>
</property>
<property name="text">
<string>清空列表</string>
</property>
</action>
<action name="actionClearModelLine">
<property name="icon">
<iconset>
<normaloff>:/images/toolbar/ic_delete.png</normaloff>:/images/toolbar/ic_delete.png</iconset>
</property>
<property name="text">
<string>删除选中行</string>
</property>
</action>
<action name="actionChinese">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>中文</string>
</property>
</action>
<action name="actionEnglish">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>English</string>
</property>
</action>
<action name="actionUTF8">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>UTF8</string>
</property>
</action>
<action name="actionGB18030">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>GB18030</string>
</property>
</action>
<action name="actionQuit">
<property name="text">
<string>退出</string>
</property>
<property name="shortcut">
<string>Ctrl+Q</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<tabstops>
<tabstop>btnOpenFile</tabstop>
<tabstop>btnOpenPath</tabstop>
<tabstop>btnClear</tabstop>
<tabstop>tableWidget</tabstop>
<tabstop>txtCount</tabstop>
<tabstop>txtSize</tabstop>
<tabstop>txtRow</tabstop>
<tabstop>txtCode</tabstop>
<tabstop>txtNote</tabstop>
<tabstop>txtBlank</tabstop>
<tabstop>txtFile</tabstop>
<tabstop>txtPath</tabstop>
<tabstop>txtFilter</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

31
tool/countcode/main.cpp Normal file
View File

@@ -0,0 +1,31 @@
#pragma execution_character_set("utf-8")
#include "frmcountcode.h"
#include <QApplication>
#include <QTextCodec>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
a.setFont(QFont("Microsoft Yahei", 9));
#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
frmCountCode w;
w.setWindowTitle("代码行数统计");
w.show();
return a.exec();
}

View File

@@ -0,0 +1,17 @@
QT += core gui network
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
greaterThan(QT_MAJOR_VERSION, 5): QT += core5compat
TARGET = emailtool
TEMPLATE = app
DESTDIR = $$PWD/../bin
CONFIG += warn_off
SOURCES += main.cpp
SOURCES += frmemailtool.cpp sendemailthread.cpp
HEADERS += frmemailtool.h sendemailthread.h
FORMS += frmemailtool.ui
INCLUDEPATH += $$PWD
INCLUDEPATH += $$PWD/../3rd_smtpclient
include ($$PWD/../3rd_smtpclient/3rd_smtpclient.pri)

View File

@@ -0,0 +1,104 @@
#pragma execution_character_set("utf-8")
#include "frmemailtool.h"
#include "ui_frmemailtool.h"
#include "qfiledialog.h"
#include "qmessagebox.h"
#include "sendemailthread.h"
frmEmailTool::frmEmailTool(QWidget *parent) : QWidget(parent), ui(new Ui::frmEmailTool)
{
ui->setupUi(this);
this->initForm();
}
frmEmailTool::~frmEmailTool()
{
delete ui;
}
void frmEmailTool::initForm()
{
ui->cboxServer->setCurrentIndex(1);
connect(SendEmailThread::Instance(), SIGNAL(receiveEmailResult(QString)),
this, SLOT(receiveEmailResult(QString)));
SendEmailThread::Instance()->start();
}
void frmEmailTool::on_btnSend_clicked()
{
if (!check()) {
return;
}
SendEmailThread::Instance()->setEmailTitle(ui->txtTitle->text());
SendEmailThread::Instance()->setSendEmailAddr(ui->txtSenderAddr->text());
SendEmailThread::Instance()->setSendEmailPwd(ui->txtSenderPwd->text());
SendEmailThread::Instance()->setReceiveEmailAddr(ui->txtReceiverAddr->text());
//设置好上述配置后,以后只要调用Append方法即可发送邮件
SendEmailThread::Instance()->append(ui->txtContent->toHtml(), ui->txtFileName->text());
}
void frmEmailTool::on_btnSelect_clicked()
{
QFileDialog dialog(this);
dialog.setFileMode(QFileDialog::ExistingFiles);
if (dialog.exec()) {
ui->txtFileName->clear();
QStringList files = dialog.selectedFiles();
ui->txtFileName->setText(files.join(";"));
}
}
bool frmEmailTool::check()
{
if (ui->txtSenderAddr->text() == "") {
QMessageBox::critical(this, "错误", "用户名不能为空!");
ui->txtSenderAddr->setFocus();
return false;
}
if (ui->txtSenderPwd->text() == "") {
QMessageBox::critical(this, "错误", "用户密码不能为空!");
ui->txtSenderPwd->setFocus();
return false;
}
if (ui->txtSenderAddr->text() == "") {
QMessageBox::critical(this, "错误", "发件人不能为空!");
ui->txtSenderAddr->setFocus();
return false;
}
if (ui->txtReceiverAddr->text() == "") {
QMessageBox::critical(this, "错误", "收件人不能为空!");
ui->txtReceiverAddr->setFocus();
return false;
}
if (ui->txtTitle->text() == "") {
QMessageBox::critical(this, "错误", "邮件标题不能为空!");
ui->txtTitle->setFocus();
return false;
}
return true;
}
void frmEmailTool::on_cboxServer_currentIndexChanged(int index)
{
if (index == 2) {
ui->cboxPort->setCurrentIndex(1);
ui->ckSSL->setChecked(true);
} else {
ui->cboxPort->setCurrentIndex(0);
ui->ckSSL->setChecked(false);
}
}
void frmEmailTool::receiveEmailResult(QString result)
{
QMessageBox::information(this, "提示", result);
}

View File

@@ -0,0 +1,35 @@
#ifndef FRMEMAILTOOL_H
#define FRMEMAILTOOL_H
#include <QWidget>
namespace Ui
{
class frmEmailTool;
}
class frmEmailTool : public QWidget
{
Q_OBJECT
public:
explicit frmEmailTool(QWidget *parent = 0);
~frmEmailTool();
private:
Ui::frmEmailTool *ui;
private:
bool check();
private slots:
void initForm();
void receiveEmailResult(QString result);
private slots:
void on_btnSend_clicked();
void on_btnSelect_clicked();
void on_cboxServer_currentIndexChanged(int index);
};
#endif // FRMEMAILTOOL_H

View File

@@ -0,0 +1,221 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>frmEmailTool</class>
<widget class="QWidget" name="frmEmailTool">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>764</width>
<height>578</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="4">
<widget class="QPushButton" name="btnSend">
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="text">
<string>发送</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QComboBox" name="cboxPort">
<item>
<property name="text">
<string>25</string>
</property>
</item>
<item>
<property name="text">
<string>465</string>
</property>
</item>
<item>
<property name="text">
<string>587</string>
</property>
</item>
</widget>
</item>
<item row="1" column="4">
<widget class="QCheckBox" name="ckSSL">
<property name="text">
<string>SSL</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="labPort">
<property name="text">
<string>服务端口</string>
</property>
</widget>
</item>
<item row="3" column="4">
<widget class="QPushButton" name="btnSelect">
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="text">
<string>浏览</string>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QLineEdit" name="txtReceiverAddr">
<property name="text">
<string>feiyangqingyun@163.com;517216493@qq.com</string>
</property>
</widget>
</item>
<item row="3" column="1" colspan="3">
<widget class="QLineEdit" name="txtFileName"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labTitle">
<property name="text">
<string>邮件标题</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="txtTitle">
<property name="text">
<string>测试邮件</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="cboxServer">
<item>
<property name="text">
<string>smtp.163.com</string>
</property>
</item>
<item>
<property name="text">
<string>smtp.126.com</string>
</property>
</item>
<item>
<property name="text">
<string>smtp.qq.com</string>
</property>
</item>
<item>
<property name="text">
<string>smt.sina.com</string>
</property>
</item>
<item>
<property name="text">
<string>smtp.sohu.com</string>
</property>
</item>
<item>
<property name="text">
<string>smtp.139.com</string>
</property>
</item>
<item>
<property name="text">
<string>smtp.189.com</string>
</property>
</item>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="labReceiverAddr">
<property name="text">
<string>收件地址</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="labFileName">
<property name="text">
<string>选择附件</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labServer">
<property name="text">
<string>服务地址</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="labSenderAddr">
<property name="text">
<string>用户名称</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="txtSenderAddr">
<property name="text">
<string>feiyangqingyun@126.com</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="labSenderPwd">
<property name="text">
<string>用户密码</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLineEdit" name="txtSenderPwd">
<property name="text">
<string/>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QTextBrowser" name="txtContent">
<property name="readOnly">
<bool>false</bool>
</property>
<property name="html">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'SimSun'; font-size:9.07563pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'宋体'; font-size:11pt;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot; font-family:'Times New Roman'; font-size:11pt;&quot;&gt;、最短的爱情哲理小说:“&lt;/span&gt;&lt;span style=&quot; font-family:'宋体'; font-size:11pt;&quot;&gt;你应该嫁给我啦?&lt;/span&gt;&lt;span style=&quot; font-family:'Times New Roman'; font-size:11pt;&quot;&gt;” “ &lt;/span&gt;&lt;span style=&quot; font-family:'宋体'; font-size:11pt;&quot;&gt;不&lt;/span&gt;&lt;span style=&quot; font-family:'Times New Roman'; font-size:11pt;&quot;&gt;” &lt;/span&gt;&lt;span style=&quot; font-family:'宋体'; font-size:11pt;&quot;&gt;于是他俩又继续幸福地生活在一起&lt;/span&gt;&lt;span style=&quot; font-family:'Times New Roman'; font-size:11pt;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot; font-family:'宋体'; font-size:11pt;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot; font-family:'Times New Roman'; font-size:11pt;&quot;&gt;、近年来中国最精彩的写实小说,全文八个字:&lt;/span&gt;&lt;span style=&quot; font-family:'Times New Roman'; font-size:16pt; font-weight:600; font-style:italic; color:#ff007f;&quot;&gt;此地钱多人傻速来&lt;/span&gt;&lt;span style=&quot; font-family:'Times New Roman'; font-size:11pt;&quot;&gt;  据说是发自杭州市宝石山下一出租房的汇款单上的简短附言,是该按摩女给家乡妹妹汇 款时随手涂鸦的,令无数专业作家汗颜!&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot; font-family:'宋体'; font-size:11pt;&quot;&gt;3&lt;/span&gt;&lt;span style=&quot; font-family:'Times New Roman'; font-size:11pt;&quot;&gt;、最短的幽默小说 《夜》 男:疼么?女:恩!男:算了?女:别!&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'宋体'; font-size:11pt;&quot;&gt;4&lt;/span&gt;&lt;span style=&quot; font-family:'Times New Roman'; font-size:11pt;&quot;&gt;、最短的荒诞小说:有一个面包走在街上,它觉得自己很饿,就把自己吃了。&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot; font-family:'宋体'; font-size:11pt;&quot;&gt;5&lt;/span&gt;&lt;span style=&quot; font-family:'Times New Roman'; font-size:11pt;&quot;&gt;、世界最短言情小说:他死的那天,孩子出生了。&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot; font-family:'宋体'; font-size:11pt;&quot;&gt;6&lt;/span&gt;&lt;span style=&quot; font-family:'Times New Roman'; font-size:11pt;&quot;&gt;、世界最短武侠小说:&lt;/span&gt;&lt;span style=&quot; font-family:'Times New Roman'; font-size:11pt; font-weight:600; color:#00aa00;&quot;&gt;高手被豆腐砸死了&lt;/span&gt;&lt;span style=&quot; font-family:'Times New Roman'; font-size:11pt;&quot;&gt;。&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot; font-family:'宋体'; font-size:11pt;&quot;&gt;7&lt;/span&gt;&lt;span style=&quot; font-family:'Times New Roman'; font-size:11pt;&quot;&gt;、世界最短科幻小说:最后一个地球人坐在家里,突然响起了敲门声。&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot; font-family:'宋体'; font-size:11pt;&quot;&gt;8&lt;/span&gt;&lt;span style=&quot; font-family:'Times New Roman'; font-size:11pt;&quot;&gt;、世界最短悬疑小说:生,死,生。&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot; font-family:'宋体'; font-size:11pt;&quot;&gt;9&lt;/span&gt;&lt;span style=&quot; font-family:'Times New Roman'; font-size:11pt;&quot;&gt;、世界最短推理小说:他死了,一定曾经活过。 &lt;br /&gt;1&lt;/span&gt;&lt;span style=&quot; font-family:'宋体'; font-size:11pt;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot; font-family:'Times New Roman'; font-size:11pt;&quot;&gt;、世界最短恐怖小说:惊醒,身边躺着自己的尸体。&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>txtSenderAddr</tabstop>
<tabstop>txtSenderPwd</tabstop>
<tabstop>cboxServer</tabstop>
<tabstop>cboxPort</tabstop>
<tabstop>ckSSL</tabstop>
<tabstop>txtTitle</tabstop>
<tabstop>txtReceiverAddr</tabstop>
<tabstop>btnSend</tabstop>
<tabstop>txtFileName</tabstop>
<tabstop>btnSelect</tabstop>
<tabstop>txtContent</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

31
tool/emailtool/main.cpp Normal file
View File

@@ -0,0 +1,31 @@
#pragma execution_character_set("utf-8")
#include "frmemailtool.h"
#include <QApplication>
#include <QTextCodec>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
a.setFont(QFont("Microsoft Yahei", 9));
#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
frmEmailTool w;
w.setWindowTitle("串口调试助手 V2021 (QQ: 517216493 WX: feiyangqingyun)");
w.show();
return a.exec();
}

View File

@@ -0,0 +1 @@
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><EFBFBD><EFBFBD><EFBFBD>163<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>126<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͷ˿ڶ<EFBFBD><EFBFBD><EFBFBD>25<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>SSLЭ<EFBFBD><EFBFBD><EFBFBD>QQ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>SSLЭ<EFBFBD><EFBFBD>˿<EFBFBD>Ϊ465<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>QQ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>͵Ļ<EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD>QQ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>н<EFBFBD>smtpЭ<EFBFBD>鿪ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͳ<EFBFBD><EFBFBD>ɹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Сʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD>QQ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ð<EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><EFBFBD>QQ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD>п<EFBFBD><EFBFBD><EFBFBD>SMTP<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>

View File

@@ -0,0 +1,150 @@
#include "sendemailthread.h"
#include "smtpmime.h"
#pragma execution_character_set("utf-8")
#define TIMEMS qPrintable(QTime::currentTime().toString("hh:mm:ss zzz"))
QScopedPointer<SendEmailThread> SendEmailThread::self;
SendEmailThread *SendEmailThread::Instance()
{
if (self.isNull()) {
static QMutex mutex;
QMutexLocker locker(&mutex);
if (self.isNull()) {
self.reset(new SendEmailThread);
}
}
return self.data();
}
SendEmailThread::SendEmailThread(QObject *parent) : QThread(parent)
{
stopped = false;
emialTitle = "邮件标题";
sendEmailAddr = "feiyangqingyun@126.com";
sendEmailPwd = "123456789";
receiveEmailAddr = "feiyangqingyun@163.com;517216493@qq.com";
contents.clear();
fileNames.clear();
}
SendEmailThread::~SendEmailThread()
{
this->stop();
this->wait(1000);
}
void SendEmailThread::run()
{
while (!stopped) {
int count = contents.count();
if (count > 0) {
mutex.lock();
QString content = contents.takeFirst();
QString fileName = fileNames.takeFirst();
mutex.unlock();
QString result;
QStringList list = sendEmailAddr.split("@");
QString tempSMTP = list.at(1).split(".").at(0);
int tempPort = 25;
//QQ邮箱端口号为465,必须启用SSL协议.
if (tempSMTP.toUpper() == "QQ") {
tempPort = 465;
}
SmtpClient smtp(QString("smtp.%1.com").arg(tempSMTP), tempPort, tempPort == 25 ? SmtpClient::TcpConnection : SmtpClient::SslConnection);
smtp.setUser(sendEmailAddr);
smtp.setPassword(sendEmailPwd);
//构建邮件主题,包含发件人收件人附件等.
MimeMessage message;
message.setSender(new EmailAddress(sendEmailAddr));
//逐个添加收件人
QStringList receiver = receiveEmailAddr.split(';');
for (int i = 0; i < receiver.size(); i++) {
message.addRecipient(new EmailAddress(receiver.at(i)));
}
//构建邮件标题
message.setSubject(emialTitle);
//构建邮件正文
MimeHtml text;
text.setHtml(content);
message.addPart(&text);
//构建附件-报警图像
if (fileName.length() > 0) {
QStringList attas = fileName.split(";");
foreach (QString tempAtta, attas) {
QFile *file = new QFile(tempAtta);
if (file->exists()) {
message.addPart(new MimeAttachment(file));
}
}
}
if (!smtp.connectToHost()) {
result = "邮件服务器连接失败";
} else {
if (!smtp.login()) {
result = "邮件用户登录失败";
} else {
if (!smtp.sendMail(message)) {
result = "邮件发送失败";
} else {
result = "邮件发送成功";
}
}
}
smtp.quit();
if (!result.isEmpty()) {
emit receiveEmailResult(result);
}
msleep(1000);
}
msleep(100);
}
stopped = false;
}
void SendEmailThread::stop()
{
stopped = true;
}
void SendEmailThread::setEmailTitle(const QString &emailTitle)
{
this->emialTitle = emailTitle;
}
void SendEmailThread::setSendEmailAddr(const QString &sendEmailAddr)
{
this->sendEmailAddr = sendEmailAddr;
}
void SendEmailThread::setSendEmailPwd(const QString &sendEmailPwd)
{
this->sendEmailPwd = sendEmailPwd;
}
void SendEmailThread::setReceiveEmailAddr(const QString &receiveEmailAddr)
{
this->receiveEmailAddr = receiveEmailAddr;
}
void SendEmailThread::append(const QString &content, const QString &fileName)
{
mutex.lock();
contents.append(content);
fileNames.append(fileName);
mutex.unlock();
}

View File

@@ -0,0 +1,44 @@
#ifndef SENDEMAILTHREAD_H
#define SENDEMAILTHREAD_H
#include <QThread>
#include <QMutex>
#include <QStringList>
class SendEmailThread : public QThread
{
Q_OBJECT
public:
static SendEmailThread *Instance();
explicit SendEmailThread(QObject *parent = 0);
~SendEmailThread();
protected:
void run();
private:
static QScopedPointer<SendEmailThread> self;
QMutex mutex;
volatile bool stopped;
QString emialTitle; //邮件标题
QString sendEmailAddr; //发件人邮箱
QString sendEmailPwd; //发件人密码
QString receiveEmailAddr; //收件人邮箱,可多个中间;隔开
QStringList contents; //正文内容
QStringList fileNames; //附件
signals:
void receiveEmailResult(const QString &result);
public slots:
void stop();
void setEmailTitle(const QString &emailTitle);
void setSendEmailAddr(const QString &sendEmailAddr);
void setSendEmailPwd(const QString &sendEmailPwd);
void setReceiveEmailAddr(const QString &receiveEmailAddr);
void append(const QString &content, const QString &fileName);
};
#endif // SENDEMAILTHREAD_H

122
tool/keydemo/appkey.cpp Normal file
View File

@@ -0,0 +1,122 @@
#include "appkey.h"
#include "qmutex.h"
#include "qfile.h"
#include "qtimer.h"
#include "qdatetime.h"
#include "qapplication.h"
#include "qmessagebox.h"
AppKey *AppKey::self = NULL;
AppKey *AppKey::Instance()
{
if (!self) {
QMutex mutex;
QMutexLocker locker(&mutex);
if (!self) {
self = new AppKey;
}
}
return self;
}
AppKey::AppKey(QObject *parent) : QObject(parent)
{
keyData = "";
keyUseDate = false;
keyDate = "2017-01-01";
keyUseRun = false;
keyRun = 1;
keyUseCount = false;
keyCount = 10;
timer = new QTimer(this);
timer->setInterval(1000);
connect(timer, SIGNAL(timeout()), this, SLOT(checkTime()));
startTime = QDateTime::currentDateTime();
}
void AppKey::start()
{
//判断密钥文件是否存在,不存在则从资源文件复制出来,同时需要设置文件写权限
QString keyName = qApp->applicationDirPath() + "/key.db";
QFile keyFile(keyName);
if (!keyFile.exists() || keyFile.size() == 0) {
QMessageBox::critical(0, "错误", "密钥文件丢失,请联系供应商!");
exit(0);
}
//读取密钥文件
keyFile.open(QFile::ReadOnly);
keyData = keyFile.readLine();
keyFile.close();
//将从注册码文件中的密文解密,与当前时间比较是否到期
keyData = getXorEncryptDecrypt(keyData, 110);
QStringList data = keyData.split("|");
if (data.count() != 6) {
QMessageBox::critical(0, "错误", "注册码文件已损坏,程序将自动关闭!");
exit(0);
}
keyUseDate = (data.at(0) == "1");
keyDate = data.at(1);
keyUseRun = (data.at(2) == "1");
keyRun = data.at(3).toInt();
keyUseCount = (data.at(4) == "1");
keyCount = data.at(5).toInt();
//如果启用了时间限制
if (keyUseDate) {
QString nowDate = QDate::currentDate().toString("yyyy-MM-dd");
if (nowDate > keyDate) {
QMessageBox::critical(0, "错误", "软件已到期,请联系供应商更新注册码!");
exit(0);
}
}
//如果启用了运行时间显示
if (keyUseRun) {
timer->start();
}
}
void AppKey::stop()
{
timer->stop();
}
void AppKey::checkTime()
{
//找出当前时间与首次启动时间比较
QDateTime now = QDateTime::currentDateTime();
if (startTime.secsTo(now) >= (keyRun * 60)) {
QMessageBox::critical(0, "错误", "试运行时间已到,请联系供应商更新注册码!");
exit(0);
}
}
QString AppKey::getXorEncryptDecrypt(const QString &data, char key)
{
//采用异或加密,也可以自行更改算法
QByteArray buffer = data.toLatin1();
int size = buffer.size();
for (int i = 0; i < size; i++) {
buffer[i] = buffer.at(i) ^ key;
}
return QLatin1String(buffer);
}
bool AppKey::checkCount(int count)
{
if (keyUseCount) {
if (count >= keyCount) {
QMessageBox::critical(0, "错误", "设备数量超过限制,请联系供应商更新注册码!");
return false;
}
}
return true;
}

40
tool/keydemo/appkey.h Normal file
View File

@@ -0,0 +1,40 @@
#ifndef APPKEY_H
#define APPKEY_H
#include <QObject>
#include <QDateTime>
class QTimer;
class AppKey : public QObject
{
Q_OBJECT
public:
static AppKey *Instance();
explicit AppKey(QObject *parent = 0);
private:
static AppKey *self;
QString keyData; //注册码密文
bool keyUseDate; //是否启用运行日期时间限制
QString keyDate; //到期时间字符串
bool keyUseRun; //是否启用可运行时间限制
int keyRun; //可运行时间
bool keyUseCount; //是否启用设备数量限制
int keyCount; //设备限制数量
QTimer *timer; //定时器判断是否运行超时
QDateTime startTime; //程序启动时间
private slots:
void checkTime();
QString getXorEncryptDecrypt(const QString &data, char key);
public slots:
void start();
void stop();
bool checkCount(int count);
};
#endif // APPKEY_H

22
tool/keydemo/frmmain.cpp Normal file
View File

@@ -0,0 +1,22 @@
#include "frmmain.h"
#include "ui_frmmain.h"
#include "appkey.h"
frmMain::frmMain(QWidget *parent) : QWidget(parent), ui(new Ui::frmMain)
{
ui->setupUi(this);
}
frmMain::~frmMain()
{
delete ui;
}
void frmMain::on_btnAdd_clicked()
{
QString name = ui->lineEdit->text().trimmed();
ui->listWidget->addItem(name);
//计算当前设备数量多少
AppKey::Instance()->checkCount(ui->listWidget->count());
}

25
tool/keydemo/frmmain.h Normal file
View File

@@ -0,0 +1,25 @@
#ifndef FRMMAIN_H
#define FRMMAIN_H
#include <QWidget>
namespace Ui {
class frmMain;
}
class frmMain : public QWidget
{
Q_OBJECT
public:
explicit frmMain(QWidget *parent = 0);
~frmMain();
private:
Ui::frmMain *ui;
private slots:
void on_btnAdd_clicked();
};
#endif // FRMMAIN_H

39
tool/keydemo/frmmain.ui Normal file
View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>frmMain</class>
<widget class="QWidget" name="frmMain">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>frmMain</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="2">
<widget class="QListWidget" name="listWidget"/>
</item>
<item row="1" column="0">
<widget class="QLineEdit" name="lineEdit">
<property name="text">
<string>测试设备</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="btnAdd">
<property name="text">
<string>添加</string>
</property>
</widget>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>

18
tool/keydemo/keydemo.pro Normal file
View File

@@ -0,0 +1,18 @@
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
greaterThan(QT_MAJOR_VERSION, 5): QT += core5compat
TARGET = keydemo
TEMPLATE = app
MOC_DIR = temp/moc
RCC_DIR = temp/rcc
UI_DIR = temp/ui
OBJECTS_DIR = temp/obj
DESTDIR = $$PWD/../bin
CONFIG += warn_off
SOURCES += main.cpp
SOURCES += frmmain.cpp appkey.cpp
HEADERS += frmmain.h appkey.h
FORMS += frmmain.ui

34
tool/keydemo/main.cpp Normal file
View File

@@ -0,0 +1,34 @@
#pragma execution_character_set("utf-8")
#include "frmmain.h"
#include "appkey.h"
#include <QApplication>
#include <QTextCodec>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
a.setFont(QFont("Microsoft Yahei", 9));
#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
//启动密钥服务类
AppKey::Instance()->start();
frmMain w;
w.setWindowTitle("密钥使用示例");
w.show();
return a.exec();
}

112
tool/keytool/frmmain.cpp Normal file
View File

@@ -0,0 +1,112 @@
#include "frmmain.h"
#include "ui_frmmain.h"
#include "qmessagebox.h"
#include "qfile.h"
#include "qprocess.h"
#include "qdebug.h"
frmMain::frmMain(QWidget *parent) : QWidget(parent), ui(new Ui::frmMain)
{
ui->setupUi(this);
this->initForm();
qDebug() << this->getCpuName() << this->getCpuId() << this->getDiskNum();
}
frmMain::~frmMain()
{
delete ui;
}
void frmMain::initForm()
{
QStringList min;
min << "1" << "5" << "10" << "20" << "30";
for (int i = 1; i <= 24; i++) {
min << QString::number(i * 60);
}
ui->cboxMin->addItems(min);
ui->cboxMin->setCurrentIndex(1);
ui->dateEdit->setDate(QDate::currentDate());
for (int i = 5; i <= 150; i = i + 5) {
ui->cboxCount->addItem(QString("%1").arg(i));
}
}
QString frmMain::getWMIC(const QString &cmd)
{
//获取cpu名称wmic cpu get Name
//获取cpu核心数wmic cpu get NumberOfCores
//获取cpu线程数wmic cpu get NumberOfLogicalProcessors
//查询cpu序列号wmic cpu get processorid
//查询主板序列号wmic baseboard get serialnumber
//查询BIOS序列号wmic bios get serialnumber
//查看硬盘wmic diskdrive get serialnumber
QProcess p;
p.start(cmd);
p.waitForFinished();
QString result = QString::fromLocal8Bit(p.readAllStandardOutput());
QStringList list = cmd.split(" ");
result = result.remove(list.last(), Qt::CaseInsensitive);
result = result.replace("\r", "");
result = result.replace("\n", "");
result = result.simplified();
return result;
}
QString frmMain::getCpuName()
{
return getWMIC("wmic cpu get name");
}
QString frmMain::getCpuId()
{
return getWMIC("wmic cpu get processorid");
}
QString frmMain::getDiskNum()
{
return getWMIC("wmic diskdrive where index=0 get serialnumber");
}
QString frmMain::getXorEncryptDecrypt(const QString &data, char key)
{
//采用异或加密,也可以自行更改算法
QByteArray buffer = data.toLatin1();
int size = buffer.size();
for (int i = 0; i < size; i++) {
buffer[i] = buffer.at(i) ^ key;
}
return QLatin1String(buffer);
}
void frmMain::on_btnOk_clicked()
{
bool useDate = ui->ckDate->isChecked();
bool useRun = ui->ckRun->isChecked();
bool useCount = ui->ckCount->isChecked();
if (!useDate && !useRun && !useCount) {
if (QMessageBox::question(this, "询问", "确定要生成没有任何限制的密钥吗?") != QMessageBox::Yes) {
return;
}
}
QString strDate = ui->dateEdit->date().toString("yyyy-MM-dd");
QString strRun = ui->cboxMin->currentText();
QString strCount = ui->cboxCount->currentText();
QString key = QString("%1|%2|%3|%4|%5|%6").arg(useDate).arg(strDate).arg(useRun).arg(strRun).arg(useCount).arg(strCount);
QFile file(QApplication::applicationDirPath() + "/key.db");
file.open(QFile::WriteOnly | QIODevice::Text);
file.write(getXorEncryptDecrypt(key, 110).toLatin1());
file.close();
QMessageBox::information(this, "提示", "生成密钥成功,将 key.db 文件拷贝到对应目录即可!");
}
void frmMain::on_btnClose_clicked()
{
this->close();
}

34
tool/keytool/frmmain.h Normal file
View File

@@ -0,0 +1,34 @@
#ifndef FRMMAIN_H
#define FRMMAIN_H
#include <QWidget>
namespace Ui {
class frmMain;
}
class frmMain : public QWidget
{
Q_OBJECT
public:
explicit frmMain(QWidget *parent = 0);
~frmMain();
private:
Ui::frmMain *ui;
private slots:
void initForm();
QString getWMIC(const QString &cmd);
QString getCpuName();
QString getCpuId();
QString getDiskNum();
QString getXorEncryptDecrypt(const QString &data, char key);
private slots:
void on_btnOk_clicked();
void on_btnClose_clicked();
};
#endif // FRMMAIN_H

156
tool/keytool/frmmain.ui Normal file
View File

@@ -0,0 +1,156 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>frmMain</class>
<widget class="QWidget" name="frmMain">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>334</width>
<height>129</height>
</rect>
</property>
<property name="windowTitle">
<string>frmMain</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1" rowspan="2" colspan="2">
<widget class="QDateEdit" name="dateEdit">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="displayFormat">
<string>yyyy年MM月dd日</string>
</property>
<property name="calendarPopup">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="3" rowspan="2">
<widget class="QPushButton" name="btnOk">
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>生成</string>
</property>
<property name="iconSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="ckDate">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>时间限制</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="ckCount">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>数量限制</string>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2">
<widget class="QComboBox" name="cboxCount">
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QPushButton" name="btnClose">
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>关闭</string>
</property>
<property name="iconSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="ckRun">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>运行限制</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="cboxMin">
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QLabel" name="label">
<property name="text">
<string>分钟自动关闭</string>
</property>
</widget>
</item>
<item row="4" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>24</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="4" rowspan="5">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>1</width>
<height>108</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>

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