1、恢复图像保存功能 恢复数据存储功能 恢复数据定时删除功能
parent
b305520fa0
commit
8231f97fdd
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -1 +0,0 @@
|
||||
0x80000106
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,3 +1,5 @@
|
||||
[ShowImg]
|
||||
Scale_Stand=0.28294005293337054
|
||||
Scale_Standard=0.2663824433072367
|
||||
Scale_Standard_1=0.1829515775204701
|
||||
Scale_Standard_2=0.2032795305783001
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 303 KiB |
Binary file not shown.
@ -1,235 +0,0 @@
|
||||
#include "CMySerialPort.h"
|
||||
#include <QtDebug>
|
||||
|
||||
CMySerialPort::CMySerialPort() :m_IsOpen(false), recving(0), m_recvnum(0), m_sendnum(0)
|
||||
{
|
||||
qRegisterMetaType<SComFrame>("SComFrame");//注册结构体SComFrame
|
||||
readThread = NULL;
|
||||
writeThread = NULL;
|
||||
m_serialPort = NULL;
|
||||
|
||||
stopped = false;
|
||||
m_serialPort = new QextSerialPort(QextSerialPort::Polling, this);
|
||||
m_serialPort->setTimeout(10);
|
||||
init();
|
||||
|
||||
readThread = new QMyThread(this);
|
||||
readThread->loadfunc(this, &CMySerialPort::readDatabyPort);
|
||||
readThread->start();
|
||||
writeThread = new QMyThread(this);
|
||||
writeThread->loadfunc(this, &CMySerialPort::WriteData2Port);
|
||||
writeThread->start();
|
||||
}
|
||||
|
||||
CMySerialPort::~CMySerialPort()
|
||||
{
|
||||
CloseCom();//关闭串口
|
||||
|
||||
if (readThread){
|
||||
if (readThread->isRunning()){
|
||||
readThread->stop();
|
||||
readThread->wait(50);
|
||||
readThread->quit();
|
||||
}
|
||||
delete readThread;
|
||||
readThread = NULL;
|
||||
}
|
||||
if (writeThread){
|
||||
if (writeThread->isRunning()){
|
||||
writeThread->stop();
|
||||
writeThread->wait(50);
|
||||
writeThread->quit();
|
||||
}
|
||||
delete writeThread;
|
||||
writeThread = NULL;
|
||||
}
|
||||
|
||||
if (m_serialPort){
|
||||
delete m_serialPort;
|
||||
m_serialPort = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool CMySerialPort::OpenCom(const QString &m_Comname, const QString &BaudRate /*= "38400"*/)
|
||||
{
|
||||
if (!m_serialPort)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (m_serialPort->isOpen())
|
||||
m_serialPort->close();
|
||||
|
||||
m_serialPort->setPortName(m_Comname);
|
||||
m_serialPort->setBaudRate((BaudRateType)BaudRate.toInt());//设置串口的波特率
|
||||
m_serialPort->setDataBits((DataBitsType)8); //设置串口的数据位
|
||||
m_serialPort->setParity((ParityType)0);
|
||||
m_serialPort->setStopBits((StopBitsType)1);
|
||||
m_serialPort->setFlowControl(FLOW_OFF);
|
||||
|
||||
if (m_serialPort->open(QIODevice::ReadWrite))
|
||||
{
|
||||
if (!this->m_IsOpen)
|
||||
{
|
||||
this->m_IsOpen = true;
|
||||
}
|
||||
stopped = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*关闭串口*/
|
||||
void CMySerialPort::CloseCom()
|
||||
{
|
||||
if (m_serialPort)
|
||||
{
|
||||
m_serialPort->close();
|
||||
m_serialPort->flush();
|
||||
}
|
||||
|
||||
stopped = true;
|
||||
this->m_IsOpen = false;
|
||||
cleanRxDataBuf();
|
||||
}
|
||||
|
||||
void CMySerialPort::readDatabyPort(void)
|
||||
{
|
||||
if (m_serialPort!=NULL)
|
||||
{
|
||||
if (!m_serialPort->isOpen())
|
||||
return;
|
||||
if (m_serialPort->bytesAvailable() <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
mMtLock.lock();
|
||||
QByteArray recvData = m_serialPort->readAll();
|
||||
requestData.append(recvData);//
|
||||
//int recvsize = recvData.size();
|
||||
emit(this->comRecive());
|
||||
emit(this->sendShowData(recvData));
|
||||
//emit(this->recvData(recvsize));
|
||||
mMtLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
bool CMySerialPort::getComState(void)
|
||||
{
|
||||
return this->m_IsOpen;
|
||||
}
|
||||
|
||||
bool CMySerialPort::init(void)
|
||||
{
|
||||
tx_event = false;
|
||||
this->TxData.clear();
|
||||
this->requestData.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMySerialPort::pullData2Tx(int size, quint8 *data)
|
||||
{
|
||||
QByteArray m_data;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
m_data.append(data[i]);
|
||||
}
|
||||
pullData2Tx(m_data);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMySerialPort::pullData2Tx(const QByteArray &data)
|
||||
{
|
||||
{
|
||||
m_sendnum++;
|
||||
emit(this->sendNum(m_sendnum));
|
||||
emit(this->CallBackPullData(data));
|
||||
}
|
||||
mWriteLock.lock();
|
||||
this->TxData.append(data, data.length());
|
||||
//tx_event = true;
|
||||
mWriteLock.unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
void CMySerialPort::WriteData2Port()
|
||||
{
|
||||
if (m_serialPort!=NULL)
|
||||
{
|
||||
if (m_serialPort->isOpen())
|
||||
{
|
||||
if (this->TxData.size() > 0)
|
||||
{
|
||||
mWriteLock.lock();
|
||||
QByteArray outData = this->TxData;
|
||||
int size = outData.size();
|
||||
m_serialPort->write(outData);
|
||||
Q_ASSERT(size <= TxData.size());
|
||||
TxData.remove(0, size);
|
||||
emit(this->sendData(size));
|
||||
mWriteLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int CMySerialPort::getRxDataSize(void)
|
||||
{
|
||||
return this->requestData.size();
|
||||
}
|
||||
|
||||
QByteArray CMySerialPort::getRxBufData(void)
|
||||
{
|
||||
return requestData;
|
||||
}
|
||||
|
||||
bool CMySerialPort::cleanRxDataBuf(void)
|
||||
{
|
||||
requestData.clear();
|
||||
m_recvnum = 0;
|
||||
m_sendnum = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMySerialPort::takeData(quint8 &data, int nLen /*= 1*/)
|
||||
{
|
||||
mMtLock.lock();
|
||||
bool bFlag = false;
|
||||
if (nLen <= getRxDataSize()) {
|
||||
QByteArray m_temp = requestData.left(nLen);
|
||||
char *temp = m_temp.data();
|
||||
if (temp)
|
||||
{
|
||||
data = (qint8)(*temp);
|
||||
requestData.remove(0, nLen);
|
||||
bFlag = true;
|
||||
}
|
||||
}
|
||||
mMtLock.unlock();
|
||||
return bFlag;
|
||||
}
|
||||
|
||||
bool CMySerialPort::takeData(QByteArray &data, int nLen /*= 1*/)
|
||||
{
|
||||
mMtLock.lock();
|
||||
bool bFlag = false;
|
||||
if (nLen <= getRxDataSize()) {
|
||||
data = requestData.left(nLen);
|
||||
requestData.remove(0, nLen);
|
||||
bFlag = true;
|
||||
}
|
||||
mMtLock.unlock();
|
||||
return bFlag;
|
||||
}
|
||||
|
||||
Q_SLOT void CMySerialPort::onSendData(QByteArray m_data)
|
||||
{
|
||||
if (m_serialPort)
|
||||
{
|
||||
if (m_serialPort->isOpen())
|
||||
{
|
||||
pullData2Tx(m_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,72 +0,0 @@
|
||||
#ifndef CSERIALTHREAD_H
|
||||
#define CSERIALTHREAD_H
|
||||
|
||||
#include <QTimer>
|
||||
#include <QtSerialPort/QSerialPort>
|
||||
#include <QtSerialPort/QSerialPortInfo>
|
||||
#include "qextserialport.h"
|
||||
#include "qmythread.h"
|
||||
#include "ctransform.h"
|
||||
#include <QMutex>
|
||||
#include "FastDelegate.h"
|
||||
|
||||
using namespace fastdelegate;
|
||||
class CMySerialPort :public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CMySerialPort();
|
||||
~CMySerialPort();
|
||||
public:
|
||||
void CloseCom();
|
||||
bool OpenCom(const QString &m_Comname, const QString &BaudRate = "38400");
|
||||
bool getComState(void);
|
||||
int getRxDataSize(void);
|
||||
QByteArray getRxBufData(void);
|
||||
bool takeData(QByteArray &data, int nLen /*= 1*/);//取出数据 自带删除功能
|
||||
bool takeData(quint8 &data, int nLen /*= 1*/);
|
||||
bool cleanRxDataBuf(void);
|
||||
bool init(void);
|
||||
bool pullData2Tx(const QByteArray &data);//裸数据发送
|
||||
bool pullData2Tx(int size, quint8 *data);
|
||||
|
||||
Q_SLOT void onSendData(QByteArray m_data);
|
||||
public:
|
||||
template <typename T, typename MemFnPtr>
|
||||
bool loadAnalysefunc(T *obj, MemFnPtr fuc)/*模板函数 不知道怎么使用*/
|
||||
{
|
||||
//_analysiseFun.bind(obj, fuc);
|
||||
return true;
|
||||
}
|
||||
signals:
|
||||
void comRecive();
|
||||
void recvData(int size);
|
||||
void sendData(int size);
|
||||
void sendNum(int num);
|
||||
void recvNum(int num);
|
||||
void sendShowData(QByteArray m_data);
|
||||
void CallBackPullData(QByteArray m_data);
|
||||
private:
|
||||
int m_recvnum;
|
||||
int m_sendnum;
|
||||
private:
|
||||
void readDatabyPort(void);//readthread
|
||||
void WriteData2Port(void);//writethread
|
||||
protected:
|
||||
QMyThread *readThread;
|
||||
QMyThread *writeThread;
|
||||
private:
|
||||
//FastDelegate1<SComFrame > _analysiseFun;//解析 委托
|
||||
QextSerialPort *m_serialPort;
|
||||
QByteArray requestData;
|
||||
QByteArray TxData;
|
||||
bool m_IsOpen;
|
||||
volatile bool stopped;
|
||||
volatile bool tx_event;
|
||||
volatile bool re_event;
|
||||
int recving;
|
||||
QMutex mWriteLock;
|
||||
QMutex mMtLock;
|
||||
};
|
||||
|
||||
#endif // CSERIALTHREAD_H
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,157 +0,0 @@
|
||||
#include "ctransform.h"
|
||||
|
||||
CTransform::CTransform(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CTransform::~CTransform()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QByteArray CTransform::HexStr2ByteArray(QString str)
|
||||
{
|
||||
QByteArray senddata;
|
||||
int hexdata, lowhexdata;
|
||||
int hexdatalen = 0;
|
||||
int len = str.length();
|
||||
senddata.resize(len / 2);
|
||||
char lstr, hstr;
|
||||
for (int i = 0; i < len;)
|
||||
{
|
||||
hstr = str[i].toLatin1();
|
||||
if (hstr == ' ')
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
if (i >= len)
|
||||
break;
|
||||
lstr = str[i].toLatin1();
|
||||
hexdata = ConvertHexChar(hstr);
|
||||
lowhexdata = ConvertHexChar(lstr);
|
||||
if ((hexdata == 16) || (lowhexdata == 16))
|
||||
break;
|
||||
else
|
||||
hexdata = hexdata * 16 + lowhexdata;
|
||||
i++;
|
||||
senddata[hexdatalen] = (char)hexdata;
|
||||
hexdatalen++;
|
||||
}
|
||||
senddata.resize(hexdatalen);
|
||||
return senddata;
|
||||
}
|
||||
|
||||
char CTransform::ConvertHexChar(char ch)
|
||||
{
|
||||
if ((ch >= '0') && (ch <= '9'))
|
||||
return ch - 0x30;
|
||||
else if ((ch >= 'A') && (ch <= 'F'))
|
||||
return ch - 'A' + 10;
|
||||
else if ((ch >= 'a') && (ch <= 'f'))
|
||||
return ch - 'a' + 10;
|
||||
else return (-1);
|
||||
}
|
||||
|
||||
QString CTransform::ByteArray2HexStr(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();
|
||||
}
|
||||
|
||||
int CTransform::StrHex2Decimal(QString strHex)
|
||||
{
|
||||
bool ok;
|
||||
return strHex.toInt(&ok, 16);
|
||||
}
|
||||
|
||||
int CTransform::StrDecimal2Decimal(QString strDecimal)
|
||||
{
|
||||
bool ok;
|
||||
return strDecimal.toInt(&ok, 10);
|
||||
}
|
||||
|
||||
int CTransform::StrBin2Decimal(QString strBin)
|
||||
{
|
||||
bool ok;
|
||||
return strBin.toInt(&ok, 2);
|
||||
}
|
||||
|
||||
QString CTransform::StrHex2StrBin(QString strHex)
|
||||
{
|
||||
uchar decimal = StrHex2Decimal(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 CTransform::Decimal2StrBin1(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 CTransform::Decimal2StrBin2(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;
|
||||
}
|
||||
|
||||
uchar CTransform::GetCheckCode(uchar data[], uchar len)
|
||||
{
|
||||
uchar temp = 0;
|
||||
|
||||
for (uchar i = 0; i < len; i++)
|
||||
{
|
||||
temp += data[i];
|
||||
}
|
||||
|
||||
return temp % 256;
|
||||
}
|
||||
|
||||
uchar CTransform::GetUChar(char data)
|
||||
{
|
||||
uchar temp;
|
||||
if (data > 127)
|
||||
{
|
||||
temp = data + 256;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp = data;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
@ -1,75 +0,0 @@
|
||||
#ifndef CTRANSFORM_H
|
||||
#define CTRANSFORM_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QByteArray>
|
||||
#include <QSettings>
|
||||
#include "framehead.h"
|
||||
|
||||
#define LP_FRAME_LEN 24
|
||||
#define LP_FRAME_HEAD_LEN 4
|
||||
#define LP_FRAME_BODY_LEN 20
|
||||
|
||||
struct STRsettings
|
||||
{
|
||||
int TabCourse;
|
||||
int BoutRateCourse;
|
||||
int ComCourse;
|
||||
QString ComName;
|
||||
QString BaudRate;
|
||||
};
|
||||
struct StytleFile
|
||||
{
|
||||
QString m_stytleFile;
|
||||
int nIndex;
|
||||
};
|
||||
enum Power
|
||||
{
|
||||
RootPower=0,
|
||||
UserPower
|
||||
};
|
||||
struct User
|
||||
{
|
||||
QString root;
|
||||
QString rootpwd;
|
||||
QString username;
|
||||
QString passwd;
|
||||
Power power;
|
||||
};
|
||||
struct Tab
|
||||
{
|
||||
bool m_tab1;
|
||||
bool m_tab2;
|
||||
bool m_tab3;
|
||||
bool m_tab4;
|
||||
bool m_tab5;
|
||||
bool m_tab6;
|
||||
bool m_tab7;
|
||||
bool m_tab8;
|
||||
bool m_tab9;
|
||||
bool m_tab10;
|
||||
};
|
||||
class CTransform : public QObject
|
||||
{
|
||||
//Q_OBJECT
|
||||
|
||||
public:
|
||||
CTransform(QObject *parent);
|
||||
~CTransform();
|
||||
public:
|
||||
QByteArray HexStr2ByteArray(QString str);//16进制字符串转字节数组
|
||||
QString ByteArray2HexStr(QByteArray data);//字节数组转16进制字符串
|
||||
int StrHex2Decimal(QString strHex);//16进制字符串转10进制
|
||||
int StrDecimal2Decimal(QString strDecimal);//10进制字符串转10进制
|
||||
int StrBin2Decimal(QString strBin);//2进制字符串转10进制
|
||||
QString StrHex2StrBin(QString strHex);//16进制字符串转2进制字符串
|
||||
QString Decimal2StrBin1(int decimal);//10进制转2进制字符串一个字节
|
||||
QString Decimal2StrBin2(int decimal);//10进制转2进制字符串两个字节
|
||||
uchar GetCheckCode(uchar data[], uchar len);//计算校验码
|
||||
uchar GetUChar(char data);//将溢出的char转为正确的uchar
|
||||
private:
|
||||
char ConvertHexChar(char ch);
|
||||
};
|
||||
|
||||
#endif // CTRANSFORM_H
|
||||
@ -1,33 +0,0 @@
|
||||
#ifndef __FRAMEHEAD_H__
|
||||
#define __FRAMEHEAD_H__
|
||||
#include <QString>
|
||||
|
||||
struct SComFrame
|
||||
{
|
||||
quint16 devicecode;
|
||||
quint16 totalnum;
|
||||
quint8 hdrlen;
|
||||
quint8 r_hdrlen;
|
||||
quint8 checksun;
|
||||
quint8 cmd;
|
||||
quint16 data1;
|
||||
quint16 data2;
|
||||
quint16 data3;
|
||||
quint16 data4;
|
||||
quint16 data5;
|
||||
quint16 data6;
|
||||
quint16 data7;
|
||||
quint16 data8;
|
||||
};
|
||||
struct MyMsg
|
||||
{
|
||||
int ID;
|
||||
QString m_windowsTitle;
|
||||
QString m_buttomTitle;
|
||||
SComFrame frame;
|
||||
};
|
||||
|
||||
|
||||
#endif // !__FRAMEHEAD_H__
|
||||
|
||||
|
||||
@ -1,99 +0,0 @@
|
||||
#ifndef MYHELPER_H
|
||||
#define MYHELPER_H
|
||||
|
||||
#include "QObject"
|
||||
#include "QString"
|
||||
#include "QByteArray"
|
||||
#include <QMutex>
|
||||
class MyHelper : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MyHelper(QObject *parent=0);
|
||||
~MyHelper();
|
||||
//字符串切割成16进制 用于显示
|
||||
static QByteArray QString2Hex(QString str)
|
||||
{
|
||||
QByteArray senddata;
|
||||
int hexdata, lowhexdata;
|
||||
int hexdatalen = 0;
|
||||
int len = str.length();
|
||||
senddata.resize(len / 2);
|
||||
char lstr, hstr;
|
||||
for (int i = 0; i < len;)
|
||||
{
|
||||
hstr = str[i].toLatin1();
|
||||
if (hstr == ' ')
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
if (i >= len)
|
||||
break;
|
||||
lstr = str[i].toLatin1();
|
||||
hexdata = ConvertHexChar(hstr);
|
||||
lowhexdata = ConvertHexChar(lstr);
|
||||
if ((hexdata == 16) || (lowhexdata == 16))
|
||||
break;
|
||||
else
|
||||
hexdata = hexdata * 16 + lowhexdata;
|
||||
i++;
|
||||
senddata[hexdatalen] = (char)hexdata;
|
||||
hexdatalen++;
|
||||
}
|
||||
senddata.resize(hexdatalen);
|
||||
return senddata;
|
||||
}
|
||||
//转换成16进制字符显示
|
||||
static char ConvertHexChar(char ch)
|
||||
{
|
||||
if ((ch >= '0') && (ch <= '9'))
|
||||
return ch - 0x30;
|
||||
else if ((ch >= 'A') && (ch <= 'F'))
|
||||
return ch - 'A' + 10;
|
||||
else if ((ch >= 'a') && (ch <= 'f'))
|
||||
return ch - 'a' + 10;
|
||||
else return (-1);
|
||||
}
|
||||
//把16进制的字符转换显示用的字符
|
||||
static QString char2Qstring(QByteArray *requesData)
|
||||
{
|
||||
char *buf = requesData->data();
|
||||
return QString(QLatin1String(buf));
|
||||
}
|
||||
//把字符转换16进制字符
|
||||
static QString char2Hex(QByteArray *requesData)
|
||||
{
|
||||
QString str = "";
|
||||
QString hex = requesData->toHex();
|
||||
for (int i = 0; i < hex.length(); i = i + 2)
|
||||
{
|
||||
str += hex.mid(i, 2) + " ";
|
||||
}
|
||||
return str.trimmed().toUpper();
|
||||
}
|
||||
//把int转换16进制字符 同时小写转换为大写
|
||||
static QString char2Hex(int requesData)
|
||||
{
|
||||
return QString::number(requesData,16).trimmed().toUpper();
|
||||
}
|
||||
private:
|
||||
//QFont iconFont;
|
||||
static MyHelper* _instance;
|
||||
public:
|
||||
static MyHelper *Instance()
|
||||
{
|
||||
static QMutex mutex;
|
||||
if (!_instance){
|
||||
QMutexLocker locker(&mutex);
|
||||
if (!_instance){
|
||||
_instance = new MyHelper;
|
||||
}
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // MYHELPER_H
|
||||
@ -1,981 +0,0 @@
|
||||
#include "qextserialport.h"
|
||||
#include "qextserialport_p.h"
|
||||
#include <stdio.h>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QReadLocker>
|
||||
#include <QtCore/QWriteLocker>
|
||||
|
||||
/*!
|
||||
\class PortSettings
|
||||
|
||||
\brief The PortSettings class contain port settings
|
||||
|
||||
Structure to contain port settings.
|
||||
|
||||
\code
|
||||
BaudRateType BaudRate;
|
||||
DataBitsType DataBits;
|
||||
ParityType Parity;
|
||||
StopBitsType StopBits;
|
||||
FlowType FlowControl;
|
||||
long Timeout_Millisec;
|
||||
\endcode
|
||||
*/
|
||||
|
||||
QextSerialPortPrivate::QextSerialPortPrivate(QextSerialPort *q)
|
||||
:lock(QReadWriteLock::Recursive), q_ptr(q)
|
||||
{
|
||||
lastErr = E_NO_ERROR;
|
||||
settings.BaudRate = BAUD9600;
|
||||
settings.Parity = PAR_NONE;
|
||||
settings.FlowControl = FLOW_OFF;
|
||||
settings.DataBits = DATA_8;
|
||||
settings.StopBits = STOP_1;
|
||||
settings.Timeout_Millisec = 10;
|
||||
settingsDirtyFlags = DFE_ALL;
|
||||
|
||||
platformSpecificInit();
|
||||
}
|
||||
|
||||
QextSerialPortPrivate::~QextSerialPortPrivate()
|
||||
{
|
||||
platformSpecificDestruct();
|
||||
}
|
||||
|
||||
void QextSerialPortPrivate::setBaudRate(BaudRateType baudRate, bool update)
|
||||
{
|
||||
switch (baudRate) {
|
||||
#ifdef Q_OS_WIN
|
||||
//Windows Special
|
||||
case BAUD14400:
|
||||
case BAUD56000:
|
||||
case BAUD128000:
|
||||
case BAUD256000:
|
||||
QESP_PORTABILITY_WARNING() << "QextSerialPort Portability Warning: POSIX does not support baudRate:" << baudRate;
|
||||
#elif defined(Q_OS_UNIX)
|
||||
//Unix Special
|
||||
case BAUD50:
|
||||
case BAUD75:
|
||||
case BAUD134:
|
||||
case BAUD150:
|
||||
case BAUD200:
|
||||
case BAUD1800:
|
||||
# ifdef B76800
|
||||
case BAUD76800:
|
||||
# endif
|
||||
# if defined(B230400) && defined(B4000000)
|
||||
case BAUD230400:
|
||||
case BAUD460800:
|
||||
case BAUD500000:
|
||||
case BAUD576000:
|
||||
case BAUD921600:
|
||||
case BAUD1000000:
|
||||
case BAUD1152000:
|
||||
case BAUD1500000:
|
||||
case BAUD2000000:
|
||||
case BAUD2500000:
|
||||
case BAUD3000000:
|
||||
case BAUD3500000:
|
||||
case BAUD4000000:
|
||||
# endif
|
||||
QESP_PORTABILITY_WARNING() << "QextSerialPort Portability Warning: Windows does not support baudRate:" << baudRate;
|
||||
#endif
|
||||
case BAUD110:
|
||||
case BAUD300:
|
||||
case BAUD600:
|
||||
case BAUD1200:
|
||||
case BAUD2400:
|
||||
case BAUD4800:
|
||||
case BAUD9600:
|
||||
case BAUD19200:
|
||||
case BAUD38400:
|
||||
case BAUD57600:
|
||||
case BAUD115200:
|
||||
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
|
||||
default:
|
||||
#endif
|
||||
settings.BaudRate = baudRate;
|
||||
settingsDirtyFlags |= DFE_BaudRate;
|
||||
if (update && q_func()->isOpen())
|
||||
updatePortSettings();
|
||||
break;
|
||||
#if !(defined(Q_OS_WIN) || defined(Q_OS_MAC))
|
||||
default:
|
||||
QESP_WARNING() << "QextSerialPort does not support baudRate:" << baudRate;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void QextSerialPortPrivate::setParity(ParityType parity, bool update)
|
||||
{
|
||||
switch (parity) {
|
||||
case PAR_SPACE:
|
||||
if (settings.DataBits == DATA_8) {
|
||||
#ifdef Q_OS_WIN
|
||||
QESP_PORTABILITY_WARNING("QextSerialPort Portability Warning: Space parity with 8 data bits is not supported by POSIX systems.");
|
||||
#else
|
||||
QESP_WARNING("Space parity with 8 data bits is not supported by POSIX systems.");
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
/*mark parity - WINDOWS ONLY*/
|
||||
case PAR_MARK:
|
||||
QESP_PORTABILITY_WARNING("QextSerialPort Portability Warning: Mark parity is not supported by POSIX systems");
|
||||
break;
|
||||
#endif
|
||||
|
||||
case PAR_NONE:
|
||||
case PAR_EVEN:
|
||||
case PAR_ODD:
|
||||
break;
|
||||
default:
|
||||
QESP_WARNING() << "QextSerialPort does not support Parity:" << parity;
|
||||
}
|
||||
|
||||
settings.Parity = parity;
|
||||
settingsDirtyFlags |= DFE_Parity;
|
||||
if (update && q_func()->isOpen())
|
||||
updatePortSettings();
|
||||
}
|
||||
|
||||
void QextSerialPortPrivate::setDataBits(DataBitsType dataBits, bool update)
|
||||
{
|
||||
switch (dataBits) {
|
||||
|
||||
case DATA_5:
|
||||
if (settings.StopBits == STOP_2) {
|
||||
QESP_WARNING("QextSerialPort: 5 Data bits cannot be used with 2 stop bits.");
|
||||
}
|
||||
else {
|
||||
settings.DataBits = dataBits;
|
||||
settingsDirtyFlags |= DFE_DataBits;
|
||||
}
|
||||
break;
|
||||
|
||||
case DATA_6:
|
||||
#ifdef Q_OS_WIN
|
||||
if (settings.StopBits == STOP_1_5) {
|
||||
QESP_WARNING("QextSerialPort: 6 Data bits cannot be used with 1.5 stop bits.");
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
settings.DataBits = dataBits;
|
||||
settingsDirtyFlags |= DFE_DataBits;
|
||||
}
|
||||
break;
|
||||
|
||||
case DATA_7:
|
||||
#ifdef Q_OS_WIN
|
||||
if (settings.StopBits == STOP_1_5) {
|
||||
QESP_WARNING("QextSerialPort: 7 Data bits cannot be used with 1.5 stop bits.");
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
settings.DataBits = dataBits;
|
||||
settingsDirtyFlags |= DFE_DataBits;
|
||||
}
|
||||
break;
|
||||
|
||||
case DATA_8:
|
||||
#ifdef Q_OS_WIN
|
||||
if (settings.StopBits == STOP_1_5) {
|
||||
QESP_WARNING("QextSerialPort: 8 Data bits cannot be used with 1.5 stop bits.");
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
settings.DataBits = dataBits;
|
||||
settingsDirtyFlags |= DFE_DataBits;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
QESP_WARNING() << "QextSerialPort does not support Data bits:" << dataBits;
|
||||
}
|
||||
if (update && q_func()->isOpen())
|
||||
updatePortSettings();
|
||||
}
|
||||
|
||||
void QextSerialPortPrivate::setStopBits(StopBitsType stopBits, bool update)
|
||||
{
|
||||
switch (stopBits) {
|
||||
|
||||
/*one stop bit*/
|
||||
case STOP_1:
|
||||
settings.StopBits = stopBits;
|
||||
settingsDirtyFlags |= DFE_StopBits;
|
||||
break;
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
/*1.5 stop bits*/
|
||||
case STOP_1_5:
|
||||
QESP_PORTABILITY_WARNING("QextSerialPort Portability Warning: 1.5 stop bit operation is not supported by POSIX.");
|
||||
if (settings.DataBits != DATA_5) {
|
||||
QESP_WARNING("QextSerialPort: 1.5 stop bits can only be used with 5 data bits");
|
||||
}
|
||||
else {
|
||||
settings.StopBits = stopBits;
|
||||
settingsDirtyFlags |= DFE_StopBits;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
/*two stop bits*/
|
||||
case STOP_2:
|
||||
if (settings.DataBits == DATA_5) {
|
||||
QESP_WARNING("QextSerialPort: 2 stop bits cannot be used with 5 data bits");
|
||||
}
|
||||
else {
|
||||
settings.StopBits = stopBits;
|
||||
settingsDirtyFlags |= DFE_StopBits;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
QESP_WARNING() << "QextSerialPort does not support stop bits: " << stopBits;
|
||||
}
|
||||
if (update && q_func()->isOpen())
|
||||
updatePortSettings();
|
||||
}
|
||||
|
||||
void QextSerialPortPrivate::setFlowControl(FlowType flow, bool update)
|
||||
{
|
||||
settings.FlowControl = flow;
|
||||
settingsDirtyFlags |= DFE_Flow;
|
||||
if (update && q_func()->isOpen())
|
||||
updatePortSettings();
|
||||
}
|
||||
|
||||
void QextSerialPortPrivate::setTimeout(long millisec, bool update)
|
||||
{
|
||||
settings.Timeout_Millisec = millisec;
|
||||
settingsDirtyFlags |= DFE_TimeOut;
|
||||
if (update && q_func()->isOpen())
|
||||
updatePortSettings();
|
||||
}
|
||||
|
||||
void QextSerialPortPrivate::setPortSettings(const PortSettings &settings, bool update)
|
||||
{
|
||||
setBaudRate(settings.BaudRate, false);
|
||||
setDataBits(settings.DataBits, false);
|
||||
setStopBits(settings.StopBits, false);
|
||||
setParity(settings.Parity, false);
|
||||
setFlowControl(settings.FlowControl, false);
|
||||
setTimeout(settings.Timeout_Millisec, false);
|
||||
settingsDirtyFlags = DFE_ALL;
|
||||
if (update && q_func()->isOpen())
|
||||
updatePortSettings();
|
||||
}
|
||||
|
||||
|
||||
void QextSerialPortPrivate::_q_canRead()
|
||||
{
|
||||
qint64 maxSize = bytesAvailable_sys();
|
||||
if (maxSize > 0) {
|
||||
char *writePtr = readBuffer.reserve(size_t(maxSize));
|
||||
qint64 bytesRead = readData_sys(writePtr, maxSize);
|
||||
if (bytesRead < maxSize)
|
||||
readBuffer.chop(maxSize - bytesRead);
|
||||
Q_Q(QextSerialPort);
|
||||
Q_EMIT q->readyRead();
|
||||
}
|
||||
}
|
||||
|
||||
/*! \class QextSerialPort
|
||||
|
||||
\brief The QextSerialPort class encapsulates a serial port on both POSIX and Windows systems.
|
||||
|
||||
\section1 Usage
|
||||
QextSerialPort offers both a polling and event driven API. Event driven
|
||||
is typically easier to use, since you never have to worry about checking
|
||||
for new data.
|
||||
|
||||
\bold Example
|
||||
\code
|
||||
QextSerialPort *port = new QextSerialPort("COM1");
|
||||
connect(port, SIGNAL(readyRead()), myClass, SLOT(onDataAvailable()));
|
||||
port->open();
|
||||
|
||||
void MyClass::onDataAvailable()
|
||||
{
|
||||
QByteArray data = port->readAll();
|
||||
processNewData(usbdata);
|
||||
}
|
||||
\endcode
|
||||
|
||||
\section1 Compatibility
|
||||
The user will be notified of errors and possible portability conflicts at run-time
|
||||
by default.
|
||||
|
||||
For example, if a application has used BAUD1800, when it is runing under unix, you
|
||||
will get following message.
|
||||
|
||||
\code
|
||||
QextSerialPort Portability Warning: Windows does not support baudRate:1800
|
||||
\endcode
|
||||
|
||||
This behavior can be turned off by defining macro QESP_NO_WARN (to turn off all warnings)
|
||||
or QESP_NO_PORTABILITY_WARN (to turn off portability warnings) in the project.
|
||||
|
||||
|
||||
\bold Author: Stefan Sander, Michal Policht, Brandon Fosdick, Liam Staskawicz, Debao Zhang
|
||||
*/
|
||||
|
||||
/*!
|
||||
\enum QextSerialPort::QueryMode
|
||||
|
||||
This enum type specifies query mode used in a serial port:
|
||||
|
||||
\value Polling
|
||||
asynchronously read and write
|
||||
\value EventDriven
|
||||
synchronously read and write
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QextSerialPort::dsrChanged(bool status)
|
||||
This signal is emitted whenever dsr line has changed its state. You may
|
||||
use this signal to check if device is connected.
|
||||
|
||||
\a status true when DSR signal is on, false otherwise.
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn QueryMode QextSerialPort::queryMode() const
|
||||
Get query mode.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Default constructor. Note that the name of the device used by a QextSerialPort is dependent on
|
||||
your OS. Possible naming conventions and their associated OS are:
|
||||
|
||||
\code
|
||||
|
||||
OS Constant Used By Naming Convention
|
||||
------------- ------------- ------------------------
|
||||
Q_OS_WIN Windows COM1, COM2
|
||||
Q_OS_IRIX SGI/IRIX /dev/ttyf1, /dev/ttyf2
|
||||
Q_OS_HPUX HP-UX /dev/tty1p0, /dev/tty2p0
|
||||
Q_OS_SOLARIS SunOS/Slaris /dev/ttya, /dev/ttyb
|
||||
Q_OS_OSF Digital UNIX /dev/tty01, /dev/tty02
|
||||
Q_OS_FREEBSD FreeBSD /dev/ttyd0, /dev/ttyd1
|
||||
Q_OS_OPENBSD OpenBSD /dev/tty00, /dev/tty01
|
||||
Q_OS_LINUX Linux /dev/ttyS0, /dev/ttyS1
|
||||
<none> /dev/ttyS0, /dev/ttyS1
|
||||
\endcode
|
||||
|
||||
This constructor assigns the device name to the name of the first port on the specified system.
|
||||
See the other constructors if you need to open a different port. Default \a mode is EventDriven.
|
||||
As a subclass of QObject, \a parent can be specified.
|
||||
*/
|
||||
|
||||
QextSerialPort::QextSerialPort(QextSerialPort::QueryMode mode, QObject *parent)
|
||||
: QIODevice(parent), d_ptr(new QextSerialPortPrivate(this))
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
setPortName(QLatin1String("COM1"));
|
||||
|
||||
#elif defined(Q_OS_IRIX)
|
||||
setPortName(QLatin1String("/dev/ttyf1"));
|
||||
|
||||
#elif defined(Q_OS_HPUX)
|
||||
setPortName(QLatin1String("/dev/tty1p0"));
|
||||
|
||||
#elif defined(Q_OS_SOLARIS)
|
||||
setPortName(QLatin1String("/dev/ttya"));
|
||||
|
||||
#elif defined(Q_OS_OSF) //formally DIGITAL UNIX
|
||||
setPortName(QLatin1String("/dev/tty01"));
|
||||
|
||||
#elif defined(Q_OS_FREEBSD)
|
||||
setPortName(QLatin1String("/dev/ttyd1"));
|
||||
|
||||
#elif defined(Q_OS_OPENBSD)
|
||||
setPortName(QLatin1String("/dev/tty00"));
|
||||
|
||||
#else
|
||||
setPortName(QLatin1String("/dev/ttyS0"));
|
||||
#endif
|
||||
setQueryMode(mode);
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs a serial port attached to the port specified by name.
|
||||
\a name is the name of the device, which is windowsystem-specific,
|
||||
e.g."COM1" or "/dev/ttyS0". \a mode
|
||||
*/
|
||||
QextSerialPort::QextSerialPort(const QString &name, QextSerialPort::QueryMode mode, QObject *parent)
|
||||
: QIODevice(parent), d_ptr(new QextSerialPortPrivate(this))
|
||||
{
|
||||
setQueryMode(mode);
|
||||
setPortName(name);
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs a port with default name and specified \a settings.
|
||||
*/
|
||||
QextSerialPort::QextSerialPort(const PortSettings &settings, QextSerialPort::QueryMode mode, QObject *parent)
|
||||
: QIODevice(parent), d_ptr(new QextSerialPortPrivate(this))
|
||||
{
|
||||
Q_D(QextSerialPort);
|
||||
setQueryMode(mode);
|
||||
d->setPortSettings(settings);
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs a port with specified \a name , \a mode and \a settings.
|
||||
*/
|
||||
QextSerialPort::QextSerialPort(const QString &name, const PortSettings &settings, QextSerialPort::QueryMode mode, QObject *parent)
|
||||
: QIODevice(parent), d_ptr(new QextSerialPortPrivate(this))
|
||||
{
|
||||
Q_D(QextSerialPort);
|
||||
setPortName(name);
|
||||
setQueryMode(mode);
|
||||
d->setPortSettings(settings);
|
||||
}
|
||||
|
||||
/*!
|
||||
Opens a serial port and sets its OpenMode to \a mode.
|
||||
Note that this function does not specify which device to open.
|
||||
Returns true if successful; otherwise returns false.This function has no effect
|
||||
if the port associated with the class is already open. The port is also
|
||||
configured to the current settings, as stored in the settings structure.
|
||||
*/
|
||||
bool QextSerialPort::open(OpenMode mode)
|
||||
{
|
||||
Q_D(QextSerialPort);
|
||||
QWriteLocker locker(&d->lock);
|
||||
if (mode != QIODevice::NotOpen && !isOpen())
|
||||
d->open_sys(mode);
|
||||
|
||||
return isOpen();
|
||||
}
|
||||
|
||||
|
||||
/*! \reimp
|
||||
Closes a serial port. This function has no effect if the serial port associated with the class
|
||||
is not currently open.
|
||||
*/
|
||||
void QextSerialPort::close()
|
||||
{
|
||||
Q_D(QextSerialPort);
|
||||
QWriteLocker locker(&d->lock);
|
||||
if (isOpen()) {
|
||||
// Be a good QIODevice and call QIODevice::close() before really close()
|
||||
// so the aboutToClose() signal is emitted at the proper time
|
||||
QIODevice::close(); // mark ourselves as closed
|
||||
d->close_sys();
|
||||
d->readBuffer.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Flushes all pending I/O to the serial port. This function has no effect if the serial port
|
||||
associated with the class is not currently open.
|
||||
*/
|
||||
void QextSerialPort::flush()
|
||||
{
|
||||
Q_D(QextSerialPort);
|
||||
QWriteLocker locker(&d->lock);
|
||||
if (isOpen())
|
||||
d->flush_sys();
|
||||
}
|
||||
|
||||
/*! \reimp
|
||||
Returns the number of bytes waiting in the port's receive queue. This function will return 0 if
|
||||
the port is not currently open, or -1 on error.
|
||||
*/
|
||||
qint64 QextSerialPort::bytesAvailable() const
|
||||
{
|
||||
QWriteLocker locker(&d_func()->lock);
|
||||
if (isOpen()) {
|
||||
qint64 bytes = d_func()->bytesAvailable_sys();
|
||||
if (bytes != -1) {
|
||||
return bytes + d_func()->readBuffer.size()
|
||||
+ QIODevice::bytesAvailable();
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! \reimp
|
||||
|
||||
*/
|
||||
bool QextSerialPort::canReadLine() const
|
||||
{
|
||||
QReadLocker locker(&d_func()->lock);
|
||||
return QIODevice::canReadLine() || d_func()->readBuffer.canReadLine();
|
||||
}
|
||||
|
||||
/*!
|
||||
* Set desired serial communication handling style. You may choose from polling
|
||||
* or event driven approach. This function does nothing when port is open; to
|
||||
* apply changes port must be reopened.
|
||||
*
|
||||
* In event driven approach read() and write() functions are acting
|
||||
* asynchronously. They return immediately and the operation is performed in
|
||||
* the background, so they doesn't freeze the calling thread.
|
||||
* To determine when operation is finished, QextSerialPort runs separate thread
|
||||
* and monitors serial port events. Whenever the event occurs, adequate signal
|
||||
* is emitted.
|
||||
*
|
||||
* When polling is set, read() and write() are acting synchronously. Signals are
|
||||
* not working in this mode and some functions may not be available. The advantage
|
||||
* of polling is that it generates less overhead due to lack of signals emissions
|
||||
* and it doesn't start separate thread to monitor events.
|
||||
*
|
||||
* Generally event driven approach is more capable and friendly, although some
|
||||
* applications may need as low overhead as possible and then polling comes.
|
||||
*
|
||||
* \a mode query mode.
|
||||
*/
|
||||
void QextSerialPort::setQueryMode(QueryMode mode)
|
||||
{
|
||||
Q_D(QextSerialPort);
|
||||
QWriteLocker locker(&d->lock);
|
||||
if (mode != d->queryMode) {
|
||||
d->queryMode = mode;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the \a name of the device associated with the object, e.g. "COM1", or "/dev/ttyS0".
|
||||
*/
|
||||
void QextSerialPort::setPortName(const QString &name)
|
||||
{
|
||||
Q_D(QextSerialPort);
|
||||
QWriteLocker locker(&d->lock);
|
||||
d->port = name;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the name set by setPortName().
|
||||
*/
|
||||
QString QextSerialPort::portName() const
|
||||
{
|
||||
QReadLocker locker(&d_func()->lock);
|
||||
return d_func()->port;
|
||||
}
|
||||
|
||||
QextSerialPort::QueryMode QextSerialPort::queryMode() const
|
||||
{
|
||||
QReadLocker locker(&d_func()->lock);
|
||||
return d_func()->queryMode;
|
||||
}
|
||||
|
||||
/*!
|
||||
Reads all available data from the device, and returns it as a QByteArray.
|
||||
This function has no way of reporting errors; returning an empty QByteArray()
|
||||
can mean either that no data was currently available for reading, or that an error occurred.
|
||||
*/
|
||||
QByteArray QextSerialPort::readAll()
|
||||
{
|
||||
int avail = this->bytesAvailable();
|
||||
return (avail > 0) ? this->read(avail) : QByteArray();
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the baud rate of the serial port. For a list of possible return values see
|
||||
the definition of the enum BaudRateType.
|
||||
*/
|
||||
BaudRateType QextSerialPort::baudRate() const
|
||||
{
|
||||
QReadLocker locker(&d_func()->lock);
|
||||
return d_func()->settings.BaudRate;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the number of data bits used by the port. For a list of possible values returned by
|
||||
this function, see the definition of the enum DataBitsType.
|
||||
*/
|
||||
DataBitsType QextSerialPort::dataBits() const
|
||||
{
|
||||
QReadLocker locker(&d_func()->lock);
|
||||
return d_func()->settings.DataBits;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the type of parity used by the port. For a list of possible values returned by
|
||||
this function, see the definition of the enum ParityType.
|
||||
*/
|
||||
ParityType QextSerialPort::parity() const
|
||||
{
|
||||
QReadLocker locker(&d_func()->lock);
|
||||
return d_func()->settings.Parity;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the number of stop bits used by the port. For a list of possible return values, see
|
||||
the definition of the enum StopBitsType.
|
||||
*/
|
||||
StopBitsType QextSerialPort::stopBits() const
|
||||
{
|
||||
QReadLocker locker(&d_func()->lock);
|
||||
return d_func()->settings.StopBits;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the type of flow control used by the port. For a list of possible values returned
|
||||
by this function, see the definition of the enum FlowType.
|
||||
*/
|
||||
FlowType QextSerialPort::flowControl() const
|
||||
{
|
||||
QReadLocker locker(&d_func()->lock);
|
||||
return d_func()->settings.FlowControl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
Returns true if device is sequential, otherwise returns false. Serial port is sequential device
|
||||
so this function always returns true. Check QIODevice::isSequential() documentation for more
|
||||
information.
|
||||
*/
|
||||
bool QextSerialPort::isSequential() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
Return the error number, or 0 if no error occurred.
|
||||
*/
|
||||
ulong QextSerialPort::lastError() const
|
||||
{
|
||||
QReadLocker locker(&d_func()->lock);
|
||||
return d_func()->lastErr;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the line status as stored by the port function. This function will retrieve the states
|
||||
of the following lines: DCD, CTS, DSR, and RI. On POSIX systems, the following additional lines
|
||||
can be monitored: DTR, RTS, Secondary TXD, and Secondary RXD. The value returned is an unsigned
|
||||
long with specific bits indicating which lines are high. The following constants should be used
|
||||
to examine the states of individual lines:
|
||||
|
||||
\code
|
||||
Mask Line
|
||||
------ ----
|
||||
LS_CTS CTS
|
||||
LS_DSR DSR
|
||||
LS_DCD DCD
|
||||
LS_RI RI
|
||||
LS_RTS RTS (POSIX only)
|
||||
LS_DTR DTR (POSIX only)
|
||||
LS_ST Secondary TXD (POSIX only)
|
||||
LS_SR Secondary RXD (POSIX only)
|
||||
\endcode
|
||||
|
||||
This function will return 0 if the port associated with the class is not currently open.
|
||||
*/
|
||||
unsigned long QextSerialPort::lineStatus()
|
||||
{
|
||||
Q_D(QextSerialPort);
|
||||
QWriteLocker locker(&d->lock);
|
||||
if (isOpen())
|
||||
return d->lineStatus_sys();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a human-readable description of the last device error that occurred.
|
||||
*/
|
||||
QString QextSerialPort::errorString()
|
||||
{
|
||||
Q_D(QextSerialPort);
|
||||
QReadLocker locker(&d->lock);
|
||||
switch (d->lastErr) {
|
||||
case E_NO_ERROR:
|
||||
return tr("No Error has occurred");
|
||||
case E_INVALID_FD:
|
||||
return tr("Invalid file descriptor (port was not opened correctly)");
|
||||
case E_NO_MEMORY:
|
||||
return tr("Unable to allocate memory tables (POSIX)");
|
||||
case E_CAUGHT_NON_BLOCKED_SIGNAL:
|
||||
return tr("Caught a non-blocked signal (POSIX)");
|
||||
case E_PORT_TIMEOUT:
|
||||
return tr("Operation timed out (POSIX)");
|
||||
case E_INVALID_DEVICE:
|
||||
return tr("The file opened by the port is not a valid device");
|
||||
case E_BREAK_CONDITION:
|
||||
return tr("The port detected a break condition");
|
||||
case E_FRAMING_ERROR:
|
||||
return tr("The port detected a framing error (usually caused by incorrect baud rate settings)");
|
||||
case E_IO_ERROR:
|
||||
return tr("There was an I/O error while communicating with the port");
|
||||
case E_BUFFER_OVERRUN:
|
||||
return tr("Character buffer overrun");
|
||||
case E_RECEIVE_OVERFLOW:
|
||||
return tr("Receive buffer overflow");
|
||||
case E_RECEIVE_PARITY_ERROR:
|
||||
return tr("The port detected a parity error in the received data");
|
||||
case E_TRANSMIT_OVERFLOW:
|
||||
return tr("Transmit buffer overflow");
|
||||
case E_READ_FAILED:
|
||||
return tr("General read operation failure");
|
||||
case E_WRITE_FAILED:
|
||||
return tr("General write operation failure");
|
||||
case E_FILE_NOT_FOUND:
|
||||
return tr("The %1 file doesn't exists").arg(this->portName());
|
||||
case E_PERMISSION_DENIED:
|
||||
return tr("Permission denied");
|
||||
case E_AGAIN:
|
||||
return tr("Device is already locked");
|
||||
default:
|
||||
return tr("Unknown error: %1").arg(d->lastErr);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Destructs the QextSerialPort object.
|
||||
*/
|
||||
QextSerialPort::~QextSerialPort()
|
||||
{
|
||||
if (isOpen()) {
|
||||
close();
|
||||
}
|
||||
delete d_ptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the flow control used by the port to \a flow. Possible values of flow are:
|
||||
\code
|
||||
FLOW_OFF No flow control
|
||||
FLOW_HARDWARE Hardware (RTS/CTS) flow control
|
||||
FLOW_XONXOFF Software (XON/XOFF) flow control
|
||||
\endcode
|
||||
*/
|
||||
void QextSerialPort::setFlowControl(FlowType flow)
|
||||
{
|
||||
Q_D(QextSerialPort);
|
||||
QWriteLocker locker(&d->lock);
|
||||
if (d->settings.FlowControl != flow)
|
||||
d->setFlowControl(flow, true);
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the parity associated with the serial port to \a parity. The possible values of parity are:
|
||||
\code
|
||||
PAR_SPACE Space Parity
|
||||
PAR_MARK Mark Parity
|
||||
PAR_NONE No Parity
|
||||
PAR_EVEN Even Parity
|
||||
PAR_ODD Odd Parity
|
||||
\endcode
|
||||
*/
|
||||
void QextSerialPort::setParity(ParityType parity)
|
||||
{
|
||||
Q_D(QextSerialPort);
|
||||
QWriteLocker locker(&d->lock);
|
||||
if (d->settings.Parity != parity)
|
||||
d->setParity(parity, true);
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the number of data bits used by the serial port to \a dataBits. Possible values of dataBits are:
|
||||
\code
|
||||
DATA_5 5 data bits
|
||||
DATA_6 6 data bits
|
||||
DATA_7 7 data bits
|
||||
DATA_8 8 data bits
|
||||
\endcode
|
||||
|
||||
\bold note:
|
||||
This function is subject to the following restrictions:
|
||||
\list
|
||||
\o 5 data bits cannot be used with 2 stop bits.
|
||||
\o 1.5 stop bits can only be used with 5 data bits.
|
||||
\o 8 data bits cannot be used with space parity on POSIX systems.
|
||||
\endlist
|
||||
*/
|
||||
void QextSerialPort::setDataBits(DataBitsType dataBits)
|
||||
{
|
||||
Q_D(QextSerialPort);
|
||||
QWriteLocker locker(&d->lock);
|
||||
if (d->settings.DataBits != dataBits)
|
||||
d->setDataBits(dataBits, true);
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the number of stop bits used by the serial port to \a stopBits. Possible values of stopBits are:
|
||||
\code
|
||||
STOP_1 1 stop bit
|
||||
STOP_1_5 1.5 stop bits
|
||||
STOP_2 2 stop bits
|
||||
\endcode
|
||||
|
||||
\bold note:
|
||||
This function is subject to the following restrictions:
|
||||
\list
|
||||
\o 2 stop bits cannot be used with 5 data bits.
|
||||
\o 1.5 stop bits cannot be used with 6 or more data bits.
|
||||
\o POSIX does not support 1.5 stop bits.
|
||||
\endlist
|
||||
*/
|
||||
void QextSerialPort::setStopBits(StopBitsType stopBits)
|
||||
{
|
||||
Q_D(QextSerialPort);
|
||||
QWriteLocker locker(&d->lock);
|
||||
if (d->settings.StopBits != stopBits)
|
||||
d->setStopBits(stopBits, true);
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the baud rate of the serial port to \a baudRate. Note that not all rates are applicable on
|
||||
all platforms. The following table shows translations of the various baud rate
|
||||
constants on Windows(including NT/2000) and POSIX platforms. Speeds marked with an *
|
||||
are speeds that are usable on both Windows and POSIX.
|
||||
\code
|
||||
|
||||
RATE Windows Speed POSIX Speed
|
||||
----------- ------------- -----------
|
||||
BAUD50 X 50
|
||||
BAUD75 X 75
|
||||
*BAUD110 110 110
|
||||
BAUD134 X 134.5
|
||||
BAUD150 X 150
|
||||
BAUD200 X 200
|
||||
*BAUD300 300 300
|
||||
*BAUD600 600 600
|
||||
*BAUD1200 1200 1200
|
||||
BAUD1800 X 1800
|
||||
*BAUD2400 2400 2400
|
||||
*BAUD4800 4800 4800
|
||||
*BAUD9600 9600 9600
|
||||
BAUD14400 14400 X
|
||||
*BAUD19200 19200 19200
|
||||
*BAUD38400 38400 38400
|
||||
BAUD56000 56000 X
|
||||
*BAUD57600 57600 57600
|
||||
BAUD76800 X 76800
|
||||
*BAUD115200 115200 115200
|
||||
BAUD128000 128000 X
|
||||
BAUD230400 X 230400
|
||||
BAUD256000 256000 X
|
||||
BAUD460800 X 460800
|
||||
BAUD500000 X 500000
|
||||
BAUD576000 X 576000
|
||||
BAUD921600 X 921600
|
||||
BAUD1000000 X 1000000
|
||||
BAUD1152000 X 1152000
|
||||
BAUD1500000 X 1500000
|
||||
BAUD2000000 X 2000000
|
||||
BAUD2500000 X 2500000
|
||||
BAUD3000000 X 3000000
|
||||
BAUD3500000 X 3500000
|
||||
BAUD4000000 X 4000000
|
||||
\endcode
|
||||
*/
|
||||
|
||||
void QextSerialPort::setBaudRate(BaudRateType baudRate)
|
||||
{
|
||||
Q_D(QextSerialPort);
|
||||
QWriteLocker locker(&d->lock);
|
||||
if (d->settings.BaudRate != baudRate)
|
||||
d->setBaudRate(baudRate, true);
|
||||
}
|
||||
|
||||
/*!
|
||||
For Unix:
|
||||
|
||||
Sets the read and write timeouts for the port to \a millisec milliseconds.
|
||||
Note that this is a per-character timeout, i.e. the port will wait this long for each
|
||||
individual character, not for the whole read operation. This timeout also applies to the
|
||||
bytesWaiting() function.
|
||||
|
||||
\bold note:
|
||||
POSIX does not support millisecond-level control for I/O timeout values. Any
|
||||
timeout set using this function will be set to the next lowest tenth of a second for
|
||||
the purposes of detecting read or write timeouts. For example a timeout of 550 milliseconds
|
||||
will be seen by the class as a timeout of 500 milliseconds for the purposes of reading and
|
||||
writing the port. However millisecond-level control is allowed by the select() system call,
|
||||
so for example a 550-millisecond timeout will be seen as 550 milliseconds on POSIX systems for
|
||||
the purpose of detecting available bytes in the read buffer.
|
||||
|
||||
For Windows:
|
||||
|
||||
Sets the read and write timeouts for the port to \a millisec milliseconds.
|
||||
Setting 0 indicates that timeouts are not used for read nor write operations;
|
||||
however read() and write() functions will still block. Set -1 to provide
|
||||
non-blocking behaviour (read() and write() will return immediately).
|
||||
|
||||
\bold note: this function does nothing in event driven mode.
|
||||
*/
|
||||
void QextSerialPort::setTimeout(long millisec)
|
||||
{
|
||||
Q_D(QextSerialPort);
|
||||
QWriteLocker locker(&d->lock);
|
||||
if (d->settings.Timeout_Millisec != millisec)
|
||||
d->setTimeout(millisec, true);
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets DTR line to the requested state (\a set default to high). This function will have no effect if
|
||||
the port associated with the class is not currently open.
|
||||
*/
|
||||
void QextSerialPort::setDtr(bool set)
|
||||
{
|
||||
Q_D(QextSerialPort);
|
||||
QWriteLocker locker(&d->lock);
|
||||
if (isOpen())
|
||||
d->setDtr_sys(set);
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets RTS line to the requested state \a set (high by default).
|
||||
This function will have no effect if
|
||||
the port associated with the class is not currently open.
|
||||
*/
|
||||
void QextSerialPort::setRts(bool set)
|
||||
{
|
||||
Q_D(QextSerialPort);
|
||||
QWriteLocker locker(&d->lock);
|
||||
if (isOpen())
|
||||
d->setRts_sys(set);
|
||||
}
|
||||
|
||||
/*! \reimp
|
||||
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 QextSerialPort::readData(char *data, qint64 maxSize)
|
||||
{
|
||||
Q_D(QextSerialPort);
|
||||
QWriteLocker locker(&d->lock);
|
||||
qint64 bytesFromBuffer = 0;
|
||||
if (!d->readBuffer.isEmpty()) {
|
||||
bytesFromBuffer = d->readBuffer.read(data, maxSize);
|
||||
if (bytesFromBuffer == maxSize)
|
||||
return bytesFromBuffer;
|
||||
}
|
||||
qint64 bytesFromDevice = d->readData_sys(data + bytesFromBuffer, maxSize - bytesFromBuffer);
|
||||
if (bytesFromDevice < 0) {
|
||||
return -1;
|
||||
}
|
||||
return bytesFromBuffer + bytesFromDevice;
|
||||
}
|
||||
|
||||
/*! \reimp
|
||||
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 QextSerialPort::writeData(const char *data, qint64 maxSize)
|
||||
{
|
||||
Q_D(QextSerialPort);
|
||||
QWriteLocker locker(&d->lock);
|
||||
return d->writeData_sys(data, maxSize);
|
||||
}
|
||||
|
||||
#include "moc_qextserialport.cpp"
|
||||
@ -1,208 +0,0 @@
|
||||
#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 = Polling, 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 // QEXTSERIALPORT_H
|
||||
@ -1,40 +0,0 @@
|
||||
#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
|
||||
@ -1,223 +0,0 @@
|
||||
#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_
|
||||
@ -1,391 +0,0 @@
|
||||
#include "qextserialport.h"
|
||||
#include "qextserialport_p.h"
|
||||
#include <QtCore/QThread>
|
||||
#include <QtCore/QReadWriteLock>
|
||||
#include <QtCore/QMutexLocker>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QRegExp>
|
||||
#include <QtCore/QMetaType>
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
||||
# include <QtCore/QWinEventNotifier>
|
||||
#else
|
||||
# include <QtCore/private/qwineventnotifier_p.h>
|
||||
#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 (fullName.contains(rx))
|
||||
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;
|
||||
}
|
||||
@ -1,72 +0,0 @@
|
||||
#pragma once
|
||||
#include "qstring.h"
|
||||
struct RasterST;
|
||||
struct RasterST//光栅数据结构体
|
||||
{
|
||||
double m_beilv;//光栅倍率 一格对应的毫米数
|
||||
double m_baseHight;//测量累加高度
|
||||
double mid_value;//中值大小
|
||||
int m_maxsize;//容器大小
|
||||
int m_lowNum;//最小值
|
||||
bool m_bool_beilv;
|
||||
bool m_bool_baseHight;
|
||||
bool m_bool_maxsize;
|
||||
bool m_bool_lowNum;
|
||||
bool m_bool_mid_value;
|
||||
RasterST(){
|
||||
m_beilv = 1.0;
|
||||
m_baseHight = 0;
|
||||
m_maxsize = 10;
|
||||
m_lowNum = 0;
|
||||
mid_value = 0.8;
|
||||
m_bool_baseHight = m_bool_beilv = m_bool_lowNum = m_bool_maxsize = m_bool_mid_value=false;
|
||||
};
|
||||
};
|
||||
struct RasterCom
|
||||
{
|
||||
QString m_ComName;
|
||||
QString m_Baute;
|
||||
bool m_UseRaster;
|
||||
RasterCom(){
|
||||
m_ComName = "COM3";
|
||||
m_Baute = "19200";
|
||||
m_UseRaster = false;
|
||||
}
|
||||
};
|
||||
enum emTySaveJsonType
|
||||
{
|
||||
EMTYPE_RASTER = 0,
|
||||
EMTYPE_COM
|
||||
};
|
||||
enum emTypeCtrolDevice{
|
||||
EMTYPE_OPENCOM=0,
|
||||
EMTYPE_CLOSECOM,
|
||||
EMTYPE_OPENERROR,
|
||||
EMTYPE_NOOPEN
|
||||
};
|
||||
class CRaster
|
||||
{
|
||||
public:
|
||||
CRaster(QString strPath);
|
||||
~CRaster();
|
||||
|
||||
void saveDefaultParam();
|
||||
public:
|
||||
double getThicknessValue() const;
|
||||
void addThicknessValue(double dValue);
|
||||
QList<double> getThicknessList() const;
|
||||
RasterST *getRasterSt() const;
|
||||
RasterCom *getRasterCom() const;
|
||||
bool readRasterJson();
|
||||
bool saveRasterJson(emTySaveJsonType emType);
|
||||
bool setRasterSt(RasterST *m_pRaster);
|
||||
QString getThicknessListStr();
|
||||
public:
|
||||
bool showRasterDlg();
|
||||
private:
|
||||
RasterST *m_pRasSt;
|
||||
RasterCom *m_pRasCom;
|
||||
class ThicknessVector *m_pThickness;
|
||||
QString m_strPath;
|
||||
};
|
||||
|
||||
@ -1,20 +0,0 @@
|
||||
#pragma once
|
||||
#include "qlist.h"
|
||||
class ThicknessVector
|
||||
{
|
||||
public:
|
||||
ThicknessVector();
|
||||
~ThicknessVector();
|
||||
void setRasterST(struct RasterST *m_pRaster);
|
||||
void addValue(double dValue);
|
||||
double getValue();
|
||||
QList<double> getList() const;
|
||||
private:
|
||||
double filterValue();
|
||||
|
||||
private:
|
||||
QList<double> m_lstThickness;
|
||||
int m_nObserveNum;
|
||||
struct RasterST *pRaster;
|
||||
};
|
||||
|
||||
@ -1,115 +0,0 @@
|
||||
#ifndef MUBAN_H
|
||||
#define MUBAN_H
|
||||
|
||||
#include <QtWidgets/QWidget>
|
||||
#include "RasterAnalysis.h"
|
||||
#include "qsimpletickergraph.h"
|
||||
#include "rastersdg20_global.h"
|
||||
#include "ui_Rester.h"
|
||||
class muban:public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
muban(QWidget *parent = 0);
|
||||
~muban();
|
||||
|
||||
void onStartSampling();
|
||||
void onStopSampling();
|
||||
Q_SLOT void ButtonClick();
|
||||
Q_SLOT void onTimer();
|
||||
Q_SLOT void onTimerCheckSys();
|
||||
Q_SLOT void onButtonClick(int state);
|
||||
Q_SLOT void onShowSys(QString,int);
|
||||
Q_SLOT void onShowValue(int);
|
||||
Q_SLOT void onSaveData();
|
||||
Q_SLOT void onScanDevice();
|
||||
Q_SLOT void onShowComState(QString, int);
|
||||
Q_SLOT void onShowThrenss(QString);
|
||||
Q_SLOT void onCtrolDevice();
|
||||
Q_SLOT void onShowMsgLabel(int nData, int nType);
|
||||
Q_SLOT void onAddData2Graph(int nData);
|
||||
|
||||
QString getSysState(quint8 nValue);
|
||||
|
||||
void setSetDiaParaFunc(SetDiaParaFunc func) { setfunc_ = func; };
|
||||
void setGetDiaParaFunc(GetDiaParaFunc func) { getfunc_ = func; };
|
||||
|
||||
void initUI();
|
||||
signals:
|
||||
void recvDataSignal(QByteArray);
|
||||
void sgShowSys(QString,int);
|
||||
void sgShowValue(int);
|
||||
void sgThress(int);
|
||||
void SignalByteData2Parent(QByteArray);
|
||||
void sgSaveData(int);
|
||||
void sgCtrolDevice(int);
|
||||
void sgShowMsgLabel(int nData, int nType);
|
||||
private:
|
||||
class QRasterAnalysis *Rasteranalysis;
|
||||
struct RasterST* m_pRaster;
|
||||
struct RasterCom* m_pRasterCom;
|
||||
private:
|
||||
virtual void changeEvent(QEvent *);
|
||||
void Appanalysis(Raster_ComFrame m_ComFrame);
|
||||
public slots:
|
||||
virtual void SlotRecvDataByParent(QByteArray m_data);
|
||||
virtual void SlotTxDataByParent(QByteArray m_data);
|
||||
|
||||
virtual void SlotRxNumByParent(int num);
|
||||
virtual void SlotTxNumByParent(int num);
|
||||
virtual void SlotRxSizeByParent(int num);
|
||||
virtual void SlotTxSizeByParent(int num);
|
||||
virtual void SlotGetPosByParent(QPoint point);
|
||||
void SetData2UI(struct RasterST *m_rastdata);
|
||||
void SetData2UI(struct RasterCom *m_rastdata);
|
||||
void GetDataFromUI(struct RasterST *m_rastdata);
|
||||
void GetDataFromUI(struct RasterCom *m_rastdata);
|
||||
public:
|
||||
Q_SLOT void onRecvThread(const QStringList &s);
|
||||
private:
|
||||
class QLineEdit *Raster_ShowlineEdit;
|
||||
class QLineEdit *Raster_ShowlineEdit_2;
|
||||
class QLineEdit *Raster_ShowlineEdit_3;
|
||||
class QTextBrowser *Raster_textBrowser;
|
||||
class QFrame *Raster_frame;
|
||||
class myChart1* m_chart;
|
||||
|
||||
class QTimer *m_timer{ NULL };
|
||||
class QTimer *m_timerChackSys{ NULL };
|
||||
class SWitchButton *m_switchbp{ NULL };
|
||||
class SWitchButton *m_switsybp{ NULL };
|
||||
|
||||
//Tab1
|
||||
class QDoubleSpinBox *doubleSpinBox_beilv;
|
||||
class QDoubleSpinBox *doubleSpinBox_baseheight;
|
||||
class QDoubleSpinBox *doubleSpinBox_min;
|
||||
class QDoubleSpinBox *doubleSpinBox_mid_value;
|
||||
class QSpinBox *SpinBox_max_size;
|
||||
|
||||
class QComboBox *Raster_ComBox;
|
||||
class QComboBox *Raster_Baute;
|
||||
class QPushButton *Raster_OpenDevice;
|
||||
class QPushButton *Raster_CloseDevice;
|
||||
class QCheckBox *Raster_checkBox;
|
||||
class QLabel *Raster_showState_lb;
|
||||
|
||||
class QTabWidget *m_tabWidget;
|
||||
|
||||
//tab2
|
||||
class QDoubleSpinBox *Raster_doubleSpinBox_K;
|
||||
class QDoubleSpinBox *Raster_doubleSpinBox_B;
|
||||
|
||||
Ui::Raster_Form ui;
|
||||
protected:
|
||||
bool bInsertData;
|
||||
class QSimpleTickerGraph *m_graph1;
|
||||
protected:
|
||||
virtual void closeEvent(QCloseEvent *event);
|
||||
virtual void showEvent(QShowEvent *event);
|
||||
private:
|
||||
SetDiaParaFunc setfunc_;
|
||||
GetDiaParaFunc getfunc_;
|
||||
};
|
||||
|
||||
#endif // MUBAN_H
|
||||
@ -1,50 +0,0 @@
|
||||
#ifndef _QMYTHREAD_H_
|
||||
#define _QMYTHREAD_H_
|
||||
|
||||
#include <QThread>
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include "FastDelegate.h"
|
||||
#include <QMutex>
|
||||
using namespace fastdelegate;
|
||||
|
||||
class QMyThread : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QMyThread(QObject *parent = 0, quint64 m_sleeptime=10);
|
||||
~QMyThread();
|
||||
|
||||
template <typename T,typename MemFnPtr>
|
||||
bool loadfunc(T *obj, MemFnPtr fuc)/*模板函数 不知道怎么使用*/
|
||||
{
|
||||
_actionFunc.bind(obj, fuc);
|
||||
stopped = false;
|
||||
return true;
|
||||
}
|
||||
bool loadfunc(void(*fn)())/*模板函数 不知道怎么使用*/
|
||||
{
|
||||
if (fn)
|
||||
_actionFunc.bind(fn);
|
||||
stopped = false;
|
||||
return true;
|
||||
}
|
||||
void stop();
|
||||
void setUser(bool m_userCtrol = false){ this->userCtrol = m_userCtrol; };
|
||||
bool WaitForSingle(quint8 m_sleep = 10);
|
||||
private:
|
||||
QMutex m_lock;
|
||||
bool userCtrol;
|
||||
volatile bool stopped;
|
||||
QString messageStr;
|
||||
FastDelegate0<> _actionFunc;
|
||||
bool m_stopsleep;
|
||||
quint64 m_sleeptime;
|
||||
private slots:
|
||||
void WaitSingleIn(bool m_signal);
|
||||
protected:
|
||||
void run();
|
||||
void runTsk();
|
||||
};
|
||||
#endif // QMYTHREAD_H
|
||||
@ -1,39 +0,0 @@
|
||||
#ifndef QFINDDEVICE_H
|
||||
#define QFINDDEVICE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
#include "QStringList"
|
||||
#include "QtSerialPort\QSerialPort"
|
||||
#include "qglobal.h"
|
||||
#include "QtSerialPort\QSerialPortInfo"
|
||||
|
||||
class QFindDevice : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QFindDevice(QObject *parent) {};
|
||||
~QFindDevice(){};
|
||||
void run() Q_DECL_OVERRIDE
|
||||
{
|
||||
QStringList strList;
|
||||
foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
|
||||
{
|
||||
QSerialPort serial;
|
||||
serial.setPort(info);
|
||||
{
|
||||
QString comportInfo = info.portName();
|
||||
strList.append(comportInfo);
|
||||
//Raster_ComBox->addItem(comportInfo);
|
||||
serial.close();
|
||||
}
|
||||
}
|
||||
emit(resultReady(strList));
|
||||
}
|
||||
private:
|
||||
signals:
|
||||
void resultReady(const QStringList &s);
|
||||
};
|
||||
|
||||
#endif // QFINDDEVICE_H
|
||||
@ -1,87 +0,0 @@
|
||||
#ifndef Q_SIMPLE_TICKET_GRAPH_H
|
||||
#define Q_SIMPLE_TICKET_GRAPH_H
|
||||
|
||||
#include <QtCore/QPair>
|
||||
#include <QtCore/QQueue>
|
||||
#include <QBrush>
|
||||
#include <QFont>
|
||||
#include <QPen>
|
||||
#include <QWidget>
|
||||
|
||||
class QSimpleTickerGraph : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QSimpleTickerGraph(QWidget *parent = 0);
|
||||
void paintEvent(QPaintEvent* pEvent);
|
||||
|
||||
// Data-related parameters
|
||||
QString units() const;
|
||||
void setUnits(const QString& unit);
|
||||
|
||||
QPair<double, double> range() const;
|
||||
void setRange(const QPair<double, double>& p);
|
||||
void setRange(double min, double max);
|
||||
|
||||
int pointWidth() const;
|
||||
void setPointWidth(int w);
|
||||
|
||||
QList<double> referencePoints() const;
|
||||
void setReferencePoints(const QList<double>& points);
|
||||
|
||||
// Style-related parameters
|
||||
QBrush backgroundBrush() const;
|
||||
void setBackgroundBrush(const QBrush& brush);
|
||||
|
||||
QPen gridPen() const;
|
||||
void setGridPen(const QPen& pen);
|
||||
|
||||
double gridPitch() const;
|
||||
void setGridPitch(double pitch);
|
||||
|
||||
QPen dataLinePen() const;
|
||||
void setDataLinePen(const QPen& pen);
|
||||
|
||||
QColor axisColor() const;
|
||||
void setAxisColor(const QColor& color);
|
||||
|
||||
QFont axisFont() const;
|
||||
void setAxisFont(const QFont& font);
|
||||
|
||||
QColor labelColor() const;
|
||||
void setLabelColor(const QColor& color);
|
||||
|
||||
QFont labelFont() const;
|
||||
void setLabelFont(const QFont& font);
|
||||
|
||||
// Adding/clearing data points
|
||||
void appendPoint(double point);
|
||||
void clear();
|
||||
|
||||
private:
|
||||
// Data points
|
||||
QQueue<double> mData;
|
||||
int mPointWidth;
|
||||
int mDataCount;
|
||||
QString mUnits;
|
||||
|
||||
// Reference points
|
||||
QList<double> mReferencePoints;
|
||||
|
||||
// Data range visible in graph
|
||||
double mMin;
|
||||
double mMax;
|
||||
|
||||
// Style
|
||||
QBrush mBackgroundBrush;
|
||||
QPen mGridPen;
|
||||
double mGridPitch;
|
||||
QPen mDataLinePen;
|
||||
QColor mAxisColor;
|
||||
QFont mAxisFont;
|
||||
QColor mLabelColor;
|
||||
QFont mLabelFont;
|
||||
};
|
||||
|
||||
#endif // Q_SIMPLE_TICKET_GRAPH_H
|
||||
@ -1,37 +0,0 @@
|
||||
#ifndef RASTERSDG20_H
|
||||
#define RASTERSDG20_H
|
||||
|
||||
#include "rastersdg20_global.h"
|
||||
|
||||
class RASTERSDG20_EXPORT RasterSDG20:public IRasterSDG20
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
RasterSDG20(const QString filepath);
|
||||
~RasterSDG20();
|
||||
virtual void onStartSampling();
|
||||
virtual void onShowWidget(QWidget* parent);
|
||||
virtual void addThicknessValue(double);
|
||||
virtual double getThicknessValue() const;
|
||||
virtual QString getThicknessValueStr() const;
|
||||
virtual double getDiameterValue();
|
||||
virtual void setSetDiaParaFunc(SetDiaParaFunc func);
|
||||
virtual void setGetDiaParaFunc(GetDiaParaFunc func);
|
||||
signals:
|
||||
void sgSendData(const QByteArray);
|
||||
void sgShowComState(QString, int);
|
||||
public:
|
||||
Q_SLOT void onRecvData(QByteArray);
|
||||
Q_SLOT void onRecvThress(int value);
|
||||
Q_SLOT void onSaveRaster(int ntype);
|
||||
Q_SLOT void onCtrolDevice(int nValue);
|
||||
private:
|
||||
class muban* m_pmuBan{ nullptr };
|
||||
class CMySerialPort* m_SerialPort{ nullptr };
|
||||
class CRaster *m_pRaster{ nullptr };
|
||||
|
||||
SetDiaParaFunc setfunc_;
|
||||
GetDiaParaFunc getfunc_;
|
||||
};
|
||||
|
||||
#endif // RASTERSDG20_H
|
||||
@ -1,38 +0,0 @@
|
||||
#ifndef RASTERSDG20_GLOBAL_H
|
||||
#define RASTERSDG20_GLOBAL_H
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
#include <QObject>
|
||||
#include <functional>
|
||||
|
||||
#ifdef RASTERSDG20_LIB
|
||||
# define RASTERSDG20_EXPORT Q_DECL_EXPORT
|
||||
#else
|
||||
# define RASTERSDG20_EXPORT Q_DECL_IMPORT
|
||||
#endif
|
||||
typedef struct tagDia2ThPara
|
||||
{
|
||||
float mk_{ 0.0 };
|
||||
float mb_{ 0.0 };
|
||||
}Dia2ThPara;
|
||||
typedef std::function<Dia2ThPara(void)> GetDiaParaFunc;
|
||||
typedef std::function<void(Dia2ThPara)> SetDiaParaFunc;
|
||||
class IRasterSDG20 :public QObject{
|
||||
Q_OBJECT
|
||||
public:
|
||||
IRasterSDG20(){/* pDetectState = NULL;*/ };
|
||||
virtual void onStartSampling() = 0;
|
||||
virtual void onShowWidget(QWidget* parent) = 0;
|
||||
virtual void addThicknessValue(double) = 0;
|
||||
virtual double getThicknessValue() const = 0;
|
||||
virtual QString getThicknessValueStr() const = 0;
|
||||
virtual double getDiameterValue() = 0;
|
||||
virtual void setSetDiaParaFunc(SetDiaParaFunc func) = 0;
|
||||
virtual void setGetDiaParaFunc(GetDiaParaFunc func) = 0;
|
||||
protected:
|
||||
};
|
||||
|
||||
extern "C" RASTERSDG20_EXPORT IRasterSDG20* RasterSDG20Create(const QString filepath);
|
||||
extern "C" RASTERSDG20_EXPORT void RasterSDG20Delete(IRasterSDG20* p);
|
||||
typedef IRasterSDG20* (*_RasterSDG20Create)(const QString);
|
||||
#endif // RASTERSDG20_GLOBAL_H
|
||||
@ -1,94 +0,0 @@
|
||||
#ifndef MYCHART1_H
|
||||
#define MYCHART1_H
|
||||
|
||||
#define TEXT_BOX_SPACE 5
|
||||
#define X_INCREMENT 5
|
||||
#define POINT_RADIUS 3
|
||||
|
||||
#include "QtWidgets/QWidget"
|
||||
#include "QtGui/QColor"
|
||||
#include "QMutex"
|
||||
class myChart1 : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit myChart1(QWidget *parent = 0);
|
||||
void clearVec(){ m_dataVec.clear(); };
|
||||
public slots:
|
||||
void addData(qreal data);
|
||||
|
||||
void setUseAntialiasing(bool use)
|
||||
{
|
||||
m_bUseAntialiasing=use;
|
||||
update();
|
||||
}
|
||||
|
||||
bool getUseAntialiasing() const
|
||||
{
|
||||
return m_bUseAntialiasing;
|
||||
}
|
||||
|
||||
void setHorizontalLineColor(const QColor& clr)
|
||||
{
|
||||
m_hLineClr=clr;
|
||||
update();
|
||||
}
|
||||
|
||||
void setShowPoint(bool show)
|
||||
{
|
||||
m_bShowPoint=show;
|
||||
update();
|
||||
}
|
||||
|
||||
void setTitle(const QString& str)
|
||||
{
|
||||
m_strTitle=str;
|
||||
update();
|
||||
}
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *);
|
||||
|
||||
void resizeEvent(QResizeEvent *)
|
||||
{
|
||||
updateVector();
|
||||
}
|
||||
|
||||
QSize sizeHint() const
|
||||
{
|
||||
return QSize(350,400);
|
||||
}
|
||||
|
||||
QSize minimumSizeHint() const
|
||||
{
|
||||
return QSize(280,280);
|
||||
}
|
||||
|
||||
private:
|
||||
void resetVariables(QPainter* painter);
|
||||
void drawBackground(QPainter* painter);
|
||||
void drawBox(QPainter* painter);
|
||||
void drawText(QPainter* painter);
|
||||
void drawGraph(QPainter* painter);
|
||||
void drawTitle(QPainter* painter);
|
||||
|
||||
private:
|
||||
qreal m_leftSpace;
|
||||
qreal m_topSpace;
|
||||
QVector<qreal> m_dataVec;
|
||||
// QVector<QPointF> m_potVec;
|
||||
bool m_bUseAntialiasing;
|
||||
bool m_bShowHLine;
|
||||
bool m_bShowPoint;
|
||||
QRectF m_topRect;
|
||||
QRectF m_bottomRect;
|
||||
QRectF m_boxRect;
|
||||
QColor m_hLineClr;
|
||||
QString m_strTitle;
|
||||
|
||||
void initVariables();
|
||||
void updateVector();
|
||||
QMutex mutex;
|
||||
};
|
||||
|
||||
#endif // MYCHART1_H
|
||||
@ -1,91 +0,0 @@
|
||||
#ifndef SWITCHBUTTON_H
|
||||
#define SWITCHBUTTON_H
|
||||
|
||||
#include <QtWidgets/QWidget>
|
||||
|
||||
class SWitchButton : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SWitchButton(QWidget *parent = 0);
|
||||
~SWitchButton();
|
||||
private:
|
||||
uchar m_pressstyle; //开关风格
|
||||
QColor m_offbkcolor1;
|
||||
QColor m_offbkcolor2;
|
||||
QColor m_onbkcolor1;
|
||||
QColor m_onbkcolor2;
|
||||
QColor m_slidecolor1;
|
||||
QColor m_slidecolor2;
|
||||
QColor m_textcolor;
|
||||
QFont m_textfont;
|
||||
|
||||
QString m_offname;
|
||||
QString m_onname;
|
||||
uchar m_state;
|
||||
|
||||
public:
|
||||
//设置属性接口
|
||||
//开关风格
|
||||
uchar GetPressStyle() { return m_pressstyle; };
|
||||
void SetPressStyle(uchar style) { m_pressstyle = style; };
|
||||
|
||||
//关闭背景颜色1
|
||||
QColor GetPressOffBkColor1() { return m_offbkcolor1; };
|
||||
void SetPressOffBkColor1(QColor color) { m_offbkcolor1 = color; };
|
||||
|
||||
//关闭背景颜色2
|
||||
QColor GetPressOffBkColor2() { return m_offbkcolor2; };
|
||||
void SetPressOffBkColor2(QColor color) { m_offbkcolor2 = color; };
|
||||
|
||||
//合上背景颜色1
|
||||
QColor GetPressOnBkColor1() { return m_onbkcolor1; };
|
||||
void SetPressOnBkColor1(QColor color) { m_onbkcolor1 = color; };
|
||||
|
||||
//合上背景颜色2
|
||||
QColor GetPressOnBkColor2() { return m_onbkcolor2; };
|
||||
void SetPressOnBkColor2(QColor color) { m_onbkcolor2 = color; };
|
||||
|
||||
//滑块颜色1
|
||||
QColor GetPressSlideColor1() { return m_slidecolor1; };
|
||||
void SetPressSlideColor1(QColor color) { m_slidecolor1 = color; };
|
||||
|
||||
//滑块颜色2
|
||||
QColor GetPressSlideColor2() { return m_slidecolor2; };
|
||||
void SetPressSlideColor2(QColor color) { m_slidecolor2 = color; };
|
||||
|
||||
//文字颜色
|
||||
QColor GetPressTextColor() { return m_textcolor; };
|
||||
void SetPressTextColor(QColor color) { m_textcolor = color; };
|
||||
|
||||
//文字字体
|
||||
QFont GetPressTextFont() { return m_textfont; };
|
||||
void SetPressTextFont(QFont font) { m_textfont = font; };
|
||||
|
||||
//开关分状态文字描述
|
||||
QString GetOffName() { return m_offname; };
|
||||
void SetOffName(QString name) { m_offname = name; };
|
||||
|
||||
//开关合状态文字描述
|
||||
QString GetOnName() { return m_onname; };
|
||||
void SetOnName(QString name) { m_onname = name; };
|
||||
|
||||
//设置开关状态
|
||||
uchar GetSwitchState() { return m_state; };
|
||||
void SetSwitchState(uchar state) { m_state = state; repaint(); };
|
||||
signals:
|
||||
void onStateChanged(int state);
|
||||
|
||||
protected:
|
||||
virtual void mousePressEvent(QMouseEvent * event);
|
||||
virtual void paintEvent(QPaintEvent *event);
|
||||
|
||||
protected:
|
||||
void DrawPressStyle(QPainter *painter, QRect &rect, uchar state);
|
||||
void DrawPressBkGround(QPainter *painter, QRect &rect, uchar state);
|
||||
void DrawPressText(QPainter *painter, QRect &rect, uchar state);
|
||||
void DrawPressSlide(QPainter *painter, QRect &rect, uchar state);
|
||||
};
|
||||
|
||||
#endif // SWITCHBUTTON_H
|
||||
@ -1,70 +0,0 @@
|
||||
#ifndef CHECKDATA_H
|
||||
#define CHECKDATA_H
|
||||
|
||||
#include <QObject>
|
||||
#include "QStandardItemModel.h"
|
||||
#include "QIcon"
|
||||
#include "QPixmap"
|
||||
#include "QByteArray"
|
||||
#include "databasesql.h"
|
||||
#include "QJsonObject"
|
||||
#include <QVariantMap>
|
||||
#pragma execution_character_set("utf-8")//使用utf-8编码 可以使用中文,解决乱码
|
||||
|
||||
class CheckData : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CheckData(QObject *parent=0){ m_pDb = NULL; };
|
||||
~CheckData(){};
|
||||
void setDB(DataBaseSql* pDB){ m_pDb = pDB; };
|
||||
public slots:
|
||||
void doWork(QVariantMap m_map)
|
||||
{
|
||||
QVariantMap m_proMap;
|
||||
m_proMap.insert("Type", "start");
|
||||
emit sgShowProgress(m_proMap);
|
||||
|
||||
QVariantMap Mapstr;
|
||||
QString strSql_Count = m_map.value("SqlCount").toString();
|
||||
QString strSql_Check = m_map.value("SqlCheck").toString();
|
||||
int nLimit = m_map.value("limit").toInt();
|
||||
int nSum = 0;
|
||||
int nIndex = 0;
|
||||
QSqlQuery sql_Check;
|
||||
if (m_pDb){
|
||||
QSqlQuery sql_Count;
|
||||
m_proMap.insert("msg", "正在获取数量");
|
||||
emit sgShowProgress(m_proMap);
|
||||
m_pDb->checkoutData(strSql_Count, sql_Count);
|
||||
while (sql_Count.next()){
|
||||
nSum = sql_Count.value(0).toInt();
|
||||
}
|
||||
//加入
|
||||
//emit something
|
||||
m_proMap.remove("msg");
|
||||
m_proMap.insert("msg", "正在获取数据");
|
||||
emit sgShowProgress(m_proMap);
|
||||
m_pDb->checkoutData(strSql_Check, sql_Check);
|
||||
|
||||
}
|
||||
Mapstr.insert("sum", nSum);
|
||||
Mapstr.insert("nIndex", nIndex);
|
||||
Mapstr.insert("limit", nLimit);
|
||||
m_proMap.remove("Type");
|
||||
m_proMap.insert("Type", "stop");
|
||||
emit sgShowProgress(m_proMap);
|
||||
|
||||
emit resultReady(Mapstr, sql_Check);
|
||||
//emit something
|
||||
};
|
||||
private:
|
||||
class DataBaseSql *m_pDb;
|
||||
signals:
|
||||
void resultReady(QVariantMap Mapstr,QSqlQuery sql);
|
||||
void sgShowMsg(QString str);
|
||||
void sgShowProgress(QVariantMap m_Map);
|
||||
};
|
||||
|
||||
#endif // CHECKDATA_H
|
||||
@ -1,53 +0,0 @@
|
||||
#ifndef CHECKTHREAD_H
|
||||
#define CHECKTHREAD_H
|
||||
|
||||
#include <QThread>
|
||||
#include "QSqlQuery"
|
||||
#include "databasesql.h"
|
||||
#include "QMetaType"
|
||||
#include "QStandardItemModel"
|
||||
#include <QSqlRecord>
|
||||
class CheckThread : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CheckThread(QObject *parent){ bFlags = false; };
|
||||
~CheckThread(){};
|
||||
void setModelFlags(bool m_flags = false){ bFlags = m_flags; }
|
||||
void setCheckStr(DataBaseSql *pDb ,QString m_str){
|
||||
m_pDb = pDb;
|
||||
m_CheckStr = m_str;
|
||||
};
|
||||
void run() Q_DECL_OVERRIDE{
|
||||
QSqlQuery sql;
|
||||
int nCount = 0;
|
||||
if (m_pDb){
|
||||
|
||||
m_pDb->checkoutData(m_CheckStr, sql);
|
||||
|
||||
if (bFlags == true)
|
||||
{
|
||||
while (sql.next())
|
||||
{
|
||||
QSqlRecord record = sql.record();
|
||||
QString fieldName = record.fieldName(0);
|
||||
QString num = sql.value(0).toString();
|
||||
nCount = num.toInt();
|
||||
// /*这里下面是统计查询到的通道对应的产品总数*/
|
||||
}
|
||||
}
|
||||
}
|
||||
emit (resultReady(sql));
|
||||
emit(resultCount(nCount));
|
||||
}
|
||||
private:
|
||||
DataBaseSql *m_pDb;
|
||||
QString m_CheckStr;
|
||||
bool bFlags;
|
||||
signals:
|
||||
void resultReady(QSqlQuery sql);
|
||||
void resultCount(int nCount);
|
||||
};
|
||||
|
||||
#endif // CHECKTHREAD_H
|
||||
@ -1,18 +0,0 @@
|
||||
#ifndef QCHECKCAL_H
|
||||
#define QCHECKCAL_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QCheckCal : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QCheckCal(QWidget *parent);
|
||||
~QCheckCal();
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
#endif // QCHECKCAL_H
|
||||
@ -1,18 +0,0 @@
|
||||
#ifndef QGENALWIDGET_H
|
||||
#define QGENALWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QGenalWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QGenalWidget(QWidget *parent);
|
||||
~QGenalWidget();
|
||||
virtual QWidget *loadUi(QString filePath);
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
#endif // QGENALWIDGET_H
|
||||
@ -1,51 +0,0 @@
|
||||
#ifndef QREPORTWIDGET_H
|
||||
#define QREPORTWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QPainter>
|
||||
#include <QDateTime>
|
||||
#include <QMap>
|
||||
#include <QTableView>
|
||||
#include <QLabel>
|
||||
#include <QGridLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QVBoxLayout>
|
||||
#include <QStandardItemModel>
|
||||
#include <QStandardItem>
|
||||
struct DataItem
|
||||
{
|
||||
QString m_str;
|
||||
int num;
|
||||
};
|
||||
|
||||
|
||||
class QReportWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QReportWidget(QString str =QString(), QWidget *parent=0);
|
||||
~QReportWidget();
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent *event);
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
private:
|
||||
void drawTexts(QPainter* painter);
|
||||
private:
|
||||
QMap<QString, int> m_str;
|
||||
QString m_Title;
|
||||
public:
|
||||
Q_SLOT void SetData(QMap<QString, int> &m_strMap);
|
||||
void UpdateTableView();
|
||||
void DrawOneItem(QPainter* painter, QPoint& point, QStringList &mList);
|
||||
void AppendData(QString str, int num, bool model = 0);
|
||||
void ClearData();
|
||||
void setTitle(QString str);
|
||||
QList<DataItem> m_listStr;
|
||||
|
||||
QLabel *m_titleLabel;
|
||||
QTableView *m_TableView;
|
||||
QStandardItemModel *m_tableViewModel;
|
||||
};
|
||||
|
||||
#endif // QREPORTWIDGET_H
|
||||
@ -1,124 +0,0 @@
|
||||
#ifndef QSAVECSVTHREAD_H
|
||||
#define QSAVECSVTHREAD_H
|
||||
|
||||
#include <QThread>
|
||||
#include "QFile"
|
||||
#include "QTextStream"
|
||||
#include "QSqlQuery"
|
||||
#include "QDateTime"
|
||||
#include "databasesql.h"
|
||||
#pragma execution_character_set("utf-8")
|
||||
class QSaveCSVThread : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QSaveCSVThread(QObject *parent){};
|
||||
~QSaveCSVThread(){};
|
||||
void setInform(QString Title, QString username)
|
||||
{
|
||||
m_title = Title;
|
||||
m_username = username;
|
||||
}
|
||||
void setCheckStr(DataBaseSql *pDb, QString m_str, QString savefilePath,int nType){
|
||||
m_pDb = pDb;
|
||||
m_CheckStr = m_str;
|
||||
m_saveFilename = savefilePath;
|
||||
m_Type = nType;
|
||||
};
|
||||
void run() Q_DECL_OVERRIDE{
|
||||
if (m_Type == 0){
|
||||
saveHistory();
|
||||
}
|
||||
else if (m_Type==1)
|
||||
{
|
||||
saveLog();
|
||||
}
|
||||
|
||||
emit(resultReady(m_Type));
|
||||
};
|
||||
private:
|
||||
void saveLog()
|
||||
{
|
||||
QSqlQuery sql;
|
||||
if (m_pDb){
|
||||
m_pDb->checkoutData(m_CheckStr, sql);
|
||||
QFile file(m_saveFilename);
|
||||
if (!file.open(QIODevice::WriteOnly | QIODevice::Text/* | QIODevice::Append*/))// 追加写入数据
|
||||
return;
|
||||
QTextStream out(&file);
|
||||
QString tableData;
|
||||
int nIndex = 0;
|
||||
out << m_title << "\n";
|
||||
out << QString("序号") << "," << QString("时间") << "," << QString("信息") << "\n";
|
||||
while (sql.next())
|
||||
{
|
||||
nIndex = nIndex + 1;
|
||||
out << nIndex << ",";
|
||||
QString time = sql.value("time").toString();
|
||||
QString message = sql.value("message").toString();
|
||||
QString classd = sql.value("class").toString();
|
||||
out << time << "," << message << ",";
|
||||
out << "\n";
|
||||
}
|
||||
|
||||
out << QString("总数") << "," << QString::number(nIndex) << "\n";
|
||||
out << QString("保存时间:") << "," << QDateTime::currentDateTime().toString("yyyy-MM-dd") << "," << QDateTime::currentDateTime().toString("hh:mm:ss") << "\n";
|
||||
out << QString("用户:") << "," << m_username << "," << "\n";
|
||||
file.close();
|
||||
}
|
||||
};
|
||||
void saveHistory()
|
||||
{
|
||||
QSqlQuery sql;
|
||||
if (m_pDb){
|
||||
m_pDb->checkoutData(m_CheckStr, sql);
|
||||
|
||||
QFile file(m_saveFilename);
|
||||
if (!file.open(QIODevice::WriteOnly | QIODevice::Text/* | QIODevice::Append*/))// 追加写入数据
|
||||
return ;
|
||||
QTextStream out(&file);
|
||||
QString tableData;
|
||||
|
||||
out << m_title << "\n";
|
||||
|
||||
out << QString("序号") << "," << QString("时间") << "," << QString("匹配型号") << "," << QString("相似度") << "," << QString("消耗时间") << "," << QString("直径") << "," << QString("厚度") << "\n";
|
||||
int nIndex = 0;
|
||||
while (sql.next())
|
||||
{
|
||||
QString time = sql.value("time").toString();
|
||||
QString model = sql.value("model").toString();
|
||||
double dCorrelate = sql.value("correlate").toDouble();
|
||||
QString correlate;
|
||||
if (dCorrelate >= 1.7976931348623158e+308)
|
||||
dCorrelate = 0;
|
||||
correlate = QString::number(dCorrelate * 100, 'f', 3) + "%";
|
||||
double dDetecttime = sql.value("detecttime").toDouble();
|
||||
QString detecttime = QString::number(dDetecttime, 'f', 3);
|
||||
double dDiameter = sql.value("diameter").toDouble();
|
||||
QString diameter = QString::number(dDiameter, 'f', 3);
|
||||
double dHight = sql.value("hight").toDouble();
|
||||
QString hight = QString::number(dHight, 'f', 3);
|
||||
|
||||
nIndex = nIndex + 1;
|
||||
out << nIndex << ",";
|
||||
out << time << "," << model << "," << correlate << "," << detecttime << "," << diameter << "," << hight << "\n";
|
||||
}
|
||||
out << QString("总数") << "," << QString::number(nIndex) << "\n";
|
||||
out << QString("时间:") << "," << QDateTime::currentDateTime().toString("yyyy-MM-dd") << "," << QDateTime::currentDateTime().toString("hh:mm:ss") << "\n";
|
||||
out << QString("用户:") << "," << m_username << "," << "\n";
|
||||
file.close();
|
||||
}
|
||||
};
|
||||
private:
|
||||
int m_Type;
|
||||
DataBaseSql *m_pDb;
|
||||
QString m_CheckStr;
|
||||
QString m_saveFilename;
|
||||
QString m_title;
|
||||
QString m_username;
|
||||
signals:
|
||||
void resultReady(int nType);
|
||||
};
|
||||
|
||||
#endif // QSAVECSVTHREAD_H
|
||||
@ -1,477 +0,0 @@
|
||||
#ifndef QTIMEDLG_H
|
||||
#define QTIMEDLG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include "ui_qtimedlg.h"
|
||||
#include <QDate>
|
||||
#include <QTime>
|
||||
#include <QBasicTimer>
|
||||
#include <QTime>
|
||||
#include <QKeyEvent>
|
||||
#include <QAction>
|
||||
#include <QTimeLine>
|
||||
#include <QPainter>
|
||||
class Digits : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/*Define three transition modes of the digital clock*/
|
||||
enum {
|
||||
Slide,
|
||||
Flip,
|
||||
Rotate
|
||||
};
|
||||
|
||||
Digits(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, m_number(0)
|
||||
, m_transition(Slide)
|
||||
{
|
||||
setAttribute(Qt::WA_OpaquePaintEvent, true);
|
||||
//Widget paints all its pixels when it receives a paint event
|
||||
|
||||
setAttribute(Qt::WA_NoSystemBackground, true);
|
||||
//Indicates that the widget has no background, i.e. when the widget receives paint events, the background is not automatically repainted.
|
||||
|
||||
connect(&m_animator, SIGNAL(frameChanged(int)), SLOT(update()));
|
||||
//start animation
|
||||
|
||||
m_animator.setFrameRange(0, 100);
|
||||
m_animator.setDuration(600);
|
||||
//Construct a 0.6-second timeline with a frame range of 0 - 100
|
||||
|
||||
m_animator.setCurveShape(QTimeLine::EaseInOutCurve);
|
||||
//starts growing slowly, then runs steadily, then grows slowly again
|
||||
}
|
||||
|
||||
/*Set transition when time changed*/
|
||||
void setTransition(int tr) {
|
||||
m_transition = tr;
|
||||
}
|
||||
|
||||
/*Get transition mode*/
|
||||
int transition() const {
|
||||
return m_transition;
|
||||
}
|
||||
|
||||
/*Set hours and minutes*/
|
||||
void setNumber(int n) {
|
||||
if (m_number != n) {
|
||||
m_number = qBound(0, n, 99);
|
||||
preparePixmap();
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
/*Flip to next state*/
|
||||
void flipTo(int n) {
|
||||
if (m_number != n) {
|
||||
m_number = qBound(0, n, 99);
|
||||
m_lastPixmap = m_pixmap;
|
||||
preparePixmap();
|
||||
m_animator.stop();
|
||||
m_animator.start();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/*Draw the main frame of the digits area*/
|
||||
void drawFrame(QPainter *p, const QRect &rect) {
|
||||
p->setPen(Qt::NoPen);
|
||||
QLinearGradient gradient(rect.topLeft(), rect.bottomLeft());
|
||||
//Set linear gradient area
|
||||
|
||||
gradient.setColorAt(0.00, QColor(245, 245, 245));
|
||||
gradient.setColorAt(0.49, QColor(192, 192, 192));
|
||||
gradient.setColorAt(0.51, QColor(245, 245, 245));
|
||||
gradient.setColorAt(1.00, QColor(192, 192, 192));
|
||||
//Creates stop points at the given position with the given color
|
||||
|
||||
p->setBrush(gradient);
|
||||
QRect r = rect;
|
||||
p->drawRoundedRect(r, 15, 15, Qt::RelativeSize);
|
||||
/*
|
||||
Draws outer rectangle rect with rounded corners.
|
||||
Qt::RelativeSize specifies the size relative to the bounding rectangle,
|
||||
typically using percentage measurements.
|
||||
*/
|
||||
|
||||
r.adjust(1, 4, -1, -4);
|
||||
//Adds 1, 4, -1 and -4 respectively to the existing coordinates of the rectangle
|
||||
|
||||
p->setPen(QColor(181, 181, 181));
|
||||
p->setBrush(Qt::NoBrush);
|
||||
p->drawRoundedRect(r, 15, 15, Qt::RelativeSize);
|
||||
//Draws inner rectangle rect with rounded corners.
|
||||
|
||||
p->setPen(QColor(159, 159, 159));
|
||||
int y = rect.top() + rect.height() / 2 - 1;
|
||||
p->drawLine(rect.left(), y, rect.right(), y);
|
||||
//Draws the mid-line from (rect.left(), y) to (rect.right(), y) and sets the current pen position to (rect.right(), y)
|
||||
|
||||
}
|
||||
|
||||
/*Draw the digits*/
|
||||
QPixmap drawDigits(int n, const QRect &rect) {
|
||||
|
||||
int scaleFactor = 2;
|
||||
#if defined(Q_OS_SYMBIAN) || defined(Q_OS_WINCE_WM)
|
||||
if (rect.height() > 240)
|
||||
scaleFactor = 1;
|
||||
#endif
|
||||
|
||||
QString str = QString::number(n);
|
||||
if (str.length() == 1)
|
||||
str.prepend("0");
|
||||
//Ensure it is double-digit
|
||||
|
||||
QFont font;
|
||||
font.setFamily("Helvetica");
|
||||
int fontHeight = scaleFactor * 0.55 * rect.height();
|
||||
font.setPixelSize(fontHeight);
|
||||
//Sets the font size to pixelSize pixels
|
||||
|
||||
font.setBold(true);
|
||||
|
||||
QPixmap pixmap(rect.size() * scaleFactor);
|
||||
pixmap.fill(Qt::transparent);
|
||||
|
||||
QLinearGradient gradient(QPoint(0, 0), QPoint(0, pixmap.height()));
|
||||
//Constructs a linear gradient with interpolation area between (0,0) and (0,pixmap.height())
|
||||
|
||||
gradient.setColorAt(0.00, QColor(128, 128, 128));
|
||||
gradient.setColorAt(0.49, QColor(64, 64, 64));
|
||||
gradient.setColorAt(0.51, QColor(128, 128, 128));
|
||||
gradient.setColorAt(1.00, QColor(16, 16, 16));
|
||||
//Creates stop points at the given position with the given color
|
||||
|
||||
QPainter p;
|
||||
p.begin(&pixmap);
|
||||
p.setFont(font);
|
||||
QPen pen;
|
||||
pen.setBrush(QBrush(gradient));
|
||||
//Set penbrush with linergrident
|
||||
|
||||
p.setPen(pen);
|
||||
p.drawText(pixmap.rect(), Qt::AlignCenter, str);
|
||||
//Draws the digit number(str here) within the provided rectangle
|
||||
|
||||
p.end();
|
||||
|
||||
return pixmap.scaledToWidth(width(), Qt::SmoothTransformation);
|
||||
//Returns a scaled copy of the image which is transformed using bilinear filtering
|
||||
}
|
||||
|
||||
/*prepare the pixmap */
|
||||
void preparePixmap() {
|
||||
m_pixmap = QPixmap(size());
|
||||
m_pixmap.fill(Qt::transparent);
|
||||
//Fills the pixmap with the given transparent black value (i.e., QColor(0, 0, 0, 0))
|
||||
|
||||
QPainter p;
|
||||
p.begin(&m_pixmap);
|
||||
p.drawPixmap(0, 0, drawDigits(m_number, rect()));
|
||||
//Draws the given digits-pixmap at position (0, 0)
|
||||
|
||||
p.end();
|
||||
}
|
||||
|
||||
/*define a resize event*/
|
||||
void resizeEvent(QResizeEvent*) {
|
||||
preparePixmap();
|
||||
update();//Causes a paintEvent() call
|
||||
|
||||
}
|
||||
|
||||
/*Paint the static state*/
|
||||
void paintStatic() {
|
||||
QPainter p(this);
|
||||
p.fillRect(rect(), Qt::black);
|
||||
//Fill the widget rec with black color
|
||||
|
||||
int pad = width() / 10;
|
||||
drawFrame(&p, rect().adjusted(pad, pad, -pad, -pad));
|
||||
p.drawPixmap(0, 0, m_pixmap);
|
||||
}
|
||||
|
||||
/*Paint the slide state*/
|
||||
void paintSlide() {
|
||||
QPainter p(this);
|
||||
p.fillRect(rect(), Qt::black);
|
||||
|
||||
int pad = width() / 10;
|
||||
QRect fr = rect().adjusted(pad, pad, -pad, -pad);
|
||||
drawFrame(&p, fr);
|
||||
p.setClipRect(fr);
|
||||
//sets the clip region to the given rectangle using the given clip operation
|
||||
|
||||
int y = height() * m_animator.currentFrame() / 100;
|
||||
p.drawPixmap(0, y, m_lastPixmap);
|
||||
//Draw last-time state pixmap from 0 to height()(Y Coordinate) in 0.6 second
|
||||
|
||||
p.drawPixmap(0, y - height(), m_pixmap);
|
||||
//Draw current-time state pixmap from -height() to 0 (Y Coordinate) in 0.6 second
|
||||
}
|
||||
|
||||
/*Paint the flip state*/
|
||||
void paintFlip() {
|
||||
QPainter p(this);
|
||||
#if !defined(Q_OS_SYMBIAN) && !defined(Q_OS_WINCE_WM)
|
||||
p.setRenderHint(QPainter::SmoothPixmapTransform, true);
|
||||
p.setRenderHint(QPainter::Antialiasing, true);
|
||||
#endif
|
||||
p.fillRect(rect(), Qt::black);
|
||||
|
||||
int hw = width() / 2;
|
||||
int hh = height() / 2;
|
||||
|
||||
// behind is the new pixmap
|
||||
int pad = width() / 10;
|
||||
QRect fr = rect().adjusted(pad, pad, -pad, -pad);
|
||||
drawFrame(&p, fr);
|
||||
p.drawPixmap(0, 0, m_pixmap);
|
||||
|
||||
int index = m_animator.currentFrame();
|
||||
|
||||
if (index <= 50) {
|
||||
|
||||
// the top part of the old pixmap is flipping
|
||||
int angle = -180 * index / 100;
|
||||
QTransform transform;
|
||||
transform.translate(hw, hh);
|
||||
//Moves the coordinate system to the center of widget
|
||||
|
||||
transform.rotate(angle, Qt::XAxis);
|
||||
//Rotates the coordinate system counterclockwise by angle about the X axis
|
||||
|
||||
p.setTransform(transform);
|
||||
drawFrame(&p, fr.adjusted(-hw, -hh, -hw, -hh));
|
||||
p.drawPixmap(-hw, -hh, m_lastPixmap);
|
||||
|
||||
// the bottom part is still the old pixmap
|
||||
p.resetTransform();
|
||||
p.setClipRect(0, hh, width(), hh);
|
||||
//Enables clipping, and sets the clip region to the rectangle beginning at (0, hh) with the given width and height
|
||||
|
||||
drawFrame(&p, fr);
|
||||
p.drawPixmap(0, 0, m_lastPixmap);
|
||||
}
|
||||
else {
|
||||
|
||||
p.setClipRect(0, hh, width(), hh);
|
||||
|
||||
// the bottom part is still the old pixmap
|
||||
drawFrame(&p, fr);
|
||||
p.drawPixmap(0, 0, m_lastPixmap);
|
||||
|
||||
// the bottom part of the new pixmap is flipping
|
||||
int angle = 180 - 180 * m_animator.currentFrame() / 100;
|
||||
QTransform transform;
|
||||
transform.translate(hw, hh);
|
||||
transform.rotate(angle, Qt::XAxis);
|
||||
p.setTransform(transform);
|
||||
drawFrame(&p, fr.adjusted(-hw, -hh, -hw, -hh));
|
||||
p.drawPixmap(-hw, -hh, m_pixmap);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*Paint the rotate state*/
|
||||
void paintRotate() {
|
||||
QPainter p(this);
|
||||
|
||||
int pad = width() / 10;
|
||||
QRect fr = rect().adjusted(pad, pad, -pad, -pad);
|
||||
drawFrame(&p, fr);
|
||||
p.setClipRect(fr);
|
||||
|
||||
int angle1 = -180 * m_animator.currentFrame() / 100;
|
||||
int angle2 = 180 - 180 * m_animator.currentFrame() / 100;
|
||||
int angle = (m_animator.currentFrame() <= 50) ? angle1 : angle2;
|
||||
QPixmap pix = (m_animator.currentFrame() <= 50) ? m_lastPixmap : m_pixmap;
|
||||
|
||||
QTransform transform;
|
||||
transform.translate(width() / 2, height() / 2);
|
||||
transform.rotate(angle, Qt::XAxis);
|
||||
|
||||
p.setTransform(transform);
|
||||
p.setRenderHint(QPainter::SmoothPixmapTransform, true);
|
||||
p.drawPixmap(-width() / 2, -height() / 2, pix);
|
||||
}
|
||||
|
||||
void paintEvent(QPaintEvent *event) {
|
||||
Q_UNUSED(event);
|
||||
if (m_animator.state() == QTimeLine::Running) {
|
||||
if (m_transition == Slide)
|
||||
paintSlide();
|
||||
if (m_transition == Flip)
|
||||
paintFlip();
|
||||
if (m_transition == Rotate)
|
||||
paintRotate();
|
||||
}
|
||||
else {
|
||||
paintStatic();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
int m_number;//number to set to digits
|
||||
|
||||
int m_transition;//transition mode(change effect)
|
||||
|
||||
QPixmap m_pixmap;//current time pixmap
|
||||
|
||||
QPixmap m_lastPixmap;//next state time pixmap
|
||||
|
||||
QTimeLine m_animator;
|
||||
//used to animate a GUI control by calling a slot periodically
|
||||
//The timeline's duration describes for how long the animation will run
|
||||
//connect the frameChanged() signal to a suitable slot in the widget you wish to animate
|
||||
};
|
||||
class QClockDlg : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QClockDlg(QWidget *parent = 0) : QWidget(parent)
|
||||
{
|
||||
m_Ihour = 0;
|
||||
m_Iminute = 0;
|
||||
m_hour = new Digits(this);
|
||||
m_hour->show();
|
||||
m_minute = new Digits(this);
|
||||
m_minute->show();
|
||||
|
||||
QPalette pal = palette();
|
||||
pal.setColor(QPalette::Window, Qt::gray);
|
||||
//Sets the color used for the given color role, in all color groups, to the specified solid color.
|
||||
|
||||
setPalette(pal);
|
||||
QAction *slideAction = new QAction("&Slide", this);
|
||||
QAction *flipAction = new QAction("&Flip", this);
|
||||
QAction *rotateAction = new QAction("&Rotate", this);
|
||||
connect(slideAction, SIGNAL(triggered()), SLOT(chooseSlide()));
|
||||
connect(flipAction, SIGNAL(triggered()), SLOT(chooseFlip()));
|
||||
connect(rotateAction, SIGNAL(triggered()), SLOT(chooseRotate()));
|
||||
#if defined(Q_OS_SYMBIAN) || defined(Q_OS_WINCE_WM)
|
||||
menuBar()->addAction(slideAction);
|
||||
menuBar()->addAction(flipAction);
|
||||
menuBar()->addAction(rotateAction);
|
||||
#else
|
||||
addAction(slideAction);
|
||||
addAction(flipAction);
|
||||
addAction(rotateAction);
|
||||
setContextMenuPolicy(Qt::ActionsContextMenu);
|
||||
//Shows a context menu(right click)
|
||||
#endif
|
||||
}
|
||||
void InitTime(int hour, int min){
|
||||
m_hour->setNumber(hour);
|
||||
m_minute->setNumber(min);
|
||||
}
|
||||
void SetTime(int hour, int min){
|
||||
|
||||
m_hour->flipTo(hour);
|
||||
m_minute->flipTo(min);
|
||||
m_Ihour = hour;
|
||||
m_Iminute = min;
|
||||
}
|
||||
private:
|
||||
QBasicTimer m_ticker;
|
||||
Digits *m_hour;
|
||||
Digits *m_minute;
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent*) {
|
||||
int digitsWidth = width() / 2;
|
||||
int digitsHeight = digitsWidth * 1.2;
|
||||
|
||||
int y = (height() - digitsHeight) / 3;
|
||||
|
||||
m_hour->resize(digitsWidth, digitsHeight);
|
||||
m_hour->move(0, y);
|
||||
|
||||
m_minute->resize(digitsWidth, digitsHeight);
|
||||
m_minute->move(width() / 2, y);
|
||||
}
|
||||
|
||||
/*Timer event,receive timer events */
|
||||
void timerEvent(QTimerEvent*) {
|
||||
updateTime();
|
||||
}
|
||||
|
||||
/* Get key press event */
|
||||
void keyPressEvent(QKeyEvent *event) {
|
||||
if (event->key() == Qt::Key_Right) {
|
||||
switchTransition(1);
|
||||
event->accept();
|
||||
}
|
||||
if (event->key() == Qt::Key_Left) {
|
||||
switchTransition(-1);
|
||||
event->accept();
|
||||
}
|
||||
}
|
||||
|
||||
private slots:
|
||||
void chooseSlide() {
|
||||
m_hour->setTransition(0);
|
||||
m_minute->setTransition(0);
|
||||
updateTime();
|
||||
}
|
||||
|
||||
void chooseFlip() {
|
||||
m_hour->setTransition(1);
|
||||
m_minute->setTransition(1);
|
||||
updateTime();
|
||||
}
|
||||
|
||||
void chooseRotate() {
|
||||
m_hour->setTransition(2);
|
||||
m_minute->setTransition(2);
|
||||
updateTime();
|
||||
}
|
||||
public:
|
||||
int m_Ihour, m_Iminute;
|
||||
/*Real-time updates*/
|
||||
void updateTime() {
|
||||
m_hour->flipTo(m_Ihour);
|
||||
m_minute->flipTo(m_Iminute);
|
||||
}
|
||||
|
||||
/*Switch transition mode*/
|
||||
void switchTransition(int delta) {
|
||||
int i = (m_hour->transition() + delta + 3) % 3;
|
||||
m_hour->setTransition(i);
|
||||
m_minute->setTransition(i);
|
||||
updateTime();
|
||||
}
|
||||
};
|
||||
|
||||
class QTimeDlg : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QTimeDlg(QWidget *parent = 0);
|
||||
~QTimeDlg();
|
||||
Q_SLOT void SlotOk();
|
||||
Q_SLOT void valuechange(int m_value);
|
||||
Q_SLOT void SlotCalWidget(const QDate &m_date);
|
||||
void SetDateTime(QDate m_date, QTime m_time);
|
||||
void SetDateTime(QDateTime m_datetime);
|
||||
void GetDateTime(QDate &m_date, QTime &m_time);
|
||||
void GetDateTime(QDateTime &m_datetime);
|
||||
Q_SLOT void onCurrentStrChange(QString str);
|
||||
Q_SLOT void oncurrentPageChanged(int nyear, int nMonth);
|
||||
private:
|
||||
Ui::QTimeDlg ui;
|
||||
QDate m_date;
|
||||
QTime m_time;
|
||||
QClockDlg *m_clock;
|
||||
int m_year, m_month, m_Day;
|
||||
};
|
||||
|
||||
#endif // QTIMEDLG_H
|
||||
@ -1,611 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>QTimeDlg</class>
|
||||
<widget class="QDialog" name="QTimeDlg">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>584</width>
|
||||
<height>380</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>时间设置</string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCalendarWidget" name="calendarWidget_timedlg">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(170, 170, 127);</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0" colspan="4">
|
||||
<layout class="QGridLayout" name="gridLayout"/>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QComboBox" name="minute_comboBox">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>60</width>
|
||||
<height>45</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Consolas</family>
|
||||
<pointsize>12</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">font: 12pt "Consolas";</string>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>1</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>2</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>3</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>4</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>5</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>6</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>7</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>8</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>9</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>10</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>11</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>12</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>13</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>14</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>15</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>16</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>17</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>18</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>19</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>20</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>21</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>22</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>23</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>24</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>25</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>26</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>27</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>28</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>29</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>30</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>31</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>32</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>33</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>34</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>35</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>36</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>37</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>38</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>39</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>40</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>41</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>42</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>43</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>44</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>45</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>46</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>47</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>48</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>49</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>50</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>51</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>52</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>53</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>54</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>55</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>56</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>57</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>58</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>59</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QComboBox" name="hour_comboBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>60</width>
|
||||
<height>45</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Consolas</family>
|
||||
<pointsize>12</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::WheelFocus</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">font: 12pt "Consolas";</string>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>1</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>2</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>3</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>4</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>5</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>6</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>7</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>8</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>9</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>10</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>11</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>12</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>13</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>14</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>15</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>16</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>17</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>18</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>19</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>20</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>21</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>22</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>23</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">font: 12pt "Consolas";</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>小时</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">font: 12pt "Consolas";</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>分钟</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout_2"/>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_timedlg">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Consolas</family>
|
||||
<pointsize>14</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::DefaultContextMenu</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>2017/00/00 00:00</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="pushButton_timedlg">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>60</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(76, 230, 0);
|
||||
font: 75 12pt "Consolas";</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>确定</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,187 +0,0 @@
|
||||
#ifndef REPORTMODEL_H
|
||||
#define REPORTMODEL_H
|
||||
|
||||
#include "reportmodel_global.h"
|
||||
#include <QMap>
|
||||
#include <QDateTime>
|
||||
#include <QStandardItemModel>
|
||||
#include <QTableView>
|
||||
#include "InfoFile.h"
|
||||
#include <QStringList>
|
||||
#include <QSqlQuery>
|
||||
#include <QMessageBox>
|
||||
#include <QThread>
|
||||
#include "countdata.h"
|
||||
#include "workfordb.h"
|
||||
#include "checkdata.h"
|
||||
#include "waitingdialog.h"
|
||||
#include <QCompleter>
|
||||
|
||||
class TimeStruct;
|
||||
class DetectState;
|
||||
|
||||
class REPORTMODEL_EXPORT ReportModel:public IWheelUi
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ReportModel(const QString str, class IWheelCtrl *pCtrl);
|
||||
~ReportModel();
|
||||
virtual bool onPolished(QWidget *p);
|
||||
virtual bool onExec();
|
||||
virtual bool onClose();
|
||||
virtual bool onUserRole();
|
||||
|
||||
Q_SLOT void SlotEditTime();
|
||||
//Q_SLOT void onChangeStackIndex();
|
||||
Q_SLOT void onCheckButton();
|
||||
Q_SLOT void onTableViewClick(QModelIndex mIndex);
|
||||
Q_SLOT void SlotCombox(int index);
|
||||
Q_SLOT void onDeleteDatas();
|
||||
Q_SLOT void onDelAllDatas();
|
||||
Q_SLOT void onHistoryButton();
|
||||
Q_SLOT void onLogButton();
|
||||
Q_SLOT void onSlowPixmap(QSqlQuery sql);
|
||||
Q_SLOT void onUpdateTableViewShow(QSqlQuery sql);
|
||||
Q_SLOT void onUpdateTableViewShowlog(QSqlQuery sql);
|
||||
Q_SLOT void onResultCountlog(int nCount);
|
||||
Q_SLOT void onResultCount(int nCount);
|
||||
Q_SLOT void onSetCurrentIndex(int);
|
||||
Q_SLOT void ontest();
|
||||
Q_SLOT void onSaveCSVDone(int);
|
||||
Q_SLOT void handleResults(QString str);//线程
|
||||
Q_SLOT void handleResultsCount(const QString &result, const QMap<QString, int> *p);//线程
|
||||
Q_SLOT void handleResultsHistory(QVariantMap Mapstr, QSqlQuery sql);
|
||||
Q_SLOT void onShowMsg();
|
||||
Q_SLOT void onShowMessage(QString str);
|
||||
Q_SLOT void onProgressForTsk(QVariantMap m_map);
|
||||
|
||||
QString getLogCheckString(int nCheckCount=0);
|
||||
QString getHistoryCheckString();
|
||||
void onEventLoop(QString strMsg );
|
||||
|
||||
bool SaveDataToCSV(QString filePath, QMap<QString, int> &m_mapTable);
|
||||
void CheckDataByDate(QString m_strLast, QString m_endLast);
|
||||
void CheckDataHistoryByDate(QString m_strLast, QString m_endLast, QString modelname);
|
||||
void CheckDataWarningByDate(int nType, QString m_strLast, QString m_endLast);
|
||||
void SetDB(class DataBaseSql *m_pDb, QMap<QString, TimeStruct> *m_time);
|
||||
void SetModelNames(QStringList models);
|
||||
void SaveLog(QString str);
|
||||
|
||||
void SetSettingPage();
|
||||
void DisableUI(bool nflags);
|
||||
private:
|
||||
virtual void timerEvent(QTimerEvent *);
|
||||
bool deleteDatas();
|
||||
void updateModelShowHistory(QSqlQuery &sql);
|
||||
void updateModelShowLog(QSqlQuery &sql);
|
||||
void cleanHistorycal();
|
||||
bool onMessageBox(QMessageBox::Icon ntype, QString strTitle, QString strAtl,int onlyOK=0);
|
||||
signals:
|
||||
void sgSetCurrentIndex(int);
|
||||
void sgFinish();
|
||||
void operate(const QString& strTime, const int &ncount);
|
||||
void operateCount(QVariantMap m_Map);
|
||||
void operateHistory(QVariantMap m_map);
|
||||
void sgshowMsg();
|
||||
private:
|
||||
class IWheelCtrl *m_pCtrl{ nullptr };
|
||||
class DataBaseSql *m_pDb{ nullptr };
|
||||
class QLabel *label_6{ nullptr };
|
||||
class QLabel *label_Time1_warning{ nullptr };
|
||||
class QLabel *label_Time2_warning{ nullptr };
|
||||
class QLabel *label_Time1_History{ nullptr };
|
||||
class QLabel *label_Time2_History{ nullptr };
|
||||
class QLabel *label_Time1_Count{ nullptr };
|
||||
class QLabel *label_Time2_Count{ nullptr };
|
||||
class QLabel *label_Title{ nullptr };
|
||||
class QLabel *label_Number{ nullptr };
|
||||
class QLabel *label_Tab3_Title{ nullptr };
|
||||
class QLabel *label_Tab2_Title{ nullptr };
|
||||
class QStackedWidget*stackedWidget{ nullptr };
|
||||
class QComboBox *comboBox_Banci{ nullptr };
|
||||
class QComboBox *comboBox_Banci_Calculate{ nullptr };
|
||||
class QComboBox *comboBox_Model{ nullptr };
|
||||
class QComboBox *comboBox_CheckOutDelTime{ nullptr };
|
||||
|
||||
class QTableView *tableView_TWarning{ nullptr };
|
||||
class QTableView *tableView_checkShengchang{ nullptr };
|
||||
class QWidget *m_pDlgCheck{ nullptr };
|
||||
class QScrollArea *scrollArea{ nullptr };
|
||||
class QWidget *m_countwidget{ nullptr };
|
||||
class QPushButton *pushButton_SaveCalculate{ nullptr };
|
||||
class QPushButton *pushButton_SaveWaring{ nullptr };
|
||||
class QPushButton *pushButton_SaveHistory{ nullptr };
|
||||
class QPushButton *pushButton_SaveTime{ nullptr };
|
||||
class QPushButton *pushButton_ModTime{ nullptr };
|
||||
class QPushButton *pushButton_CHeckDB_DelAll{ nullptr };
|
||||
class QPushButton *pushButton_CHeckDB_Test{ nullptr };
|
||||
|
||||
class QComboBox *m_comboBox_Wandring_Log{ nullptr };
|
||||
class QSpinBox *m_spinBox_CheckDB{ nullptr };
|
||||
|
||||
class QLineEdit *m_LineNumber_checkShengchang{ nullptr };
|
||||
class QPushButton *m_Prev_checkShengchang{ nullptr };
|
||||
class QPushButton *m_Next_checkShengchang{ nullptr };
|
||||
class QLabel *m_showNum_Label_Checkdata{ nullptr };
|
||||
class QLabel *m_showPage_Label_Checkdata{ nullptr };
|
||||
|
||||
class QLineEdit *m_LineNumber_log{ nullptr };
|
||||
class QPushButton *m_Prev_checklog{ nullptr };
|
||||
class QPushButton *m_Next_checklog{ nullptr };
|
||||
class QLabel *m_showPage_Label_Checkdata_2{ nullptr };
|
||||
class QLabel *m_showNum_Label_Checkdata_2{ nullptr };
|
||||
class QGroupBox *m_groupBox_CheckDB_02{ nullptr };
|
||||
|
||||
class QListWidget *m_check_listWidget{ nullptr };
|
||||
|
||||
QMap<int, QTableView*> m_tableView;
|
||||
QMap<int, QStandardItemModel*> m_standItemModel;
|
||||
QMap<QString, TimeStruct> *m_Totaltime;
|
||||
QMap<QString, QString> m_Mapcombox;
|
||||
bool m_checkModel;
|
||||
QDateTime m_startDate_Count, m_endDate_Count;
|
||||
QDateTime m_startDate_History, m_endDate_History;
|
||||
QDateTime m_startDate_Warning, m_endDate_Warning;
|
||||
QTime m_startTime, m_endTime;
|
||||
int m_nTimerID;
|
||||
class QReportWidget *reportdlg{ nullptr };
|
||||
|
||||
QMap<QString, int> m_CountNumber;
|
||||
QMap<int, QMap<QString, int>> m_channels;
|
||||
QStandardItemModel *m_tableModel{ nullptr };
|
||||
QStandardItemModel *m_tableWarnModel{ nullptr };
|
||||
bool m_CheckFlags{false};
|
||||
QTime nstartTime;
|
||||
QTime nEndTime;
|
||||
QString m_userName;
|
||||
class QGridLayout *m_GridLayout{ nullptr };
|
||||
class QVBoxLayout *Hbox{ nullptr };
|
||||
|
||||
DetectState *m_pDeteState{ nullptr };
|
||||
|
||||
int m_PrevNum;
|
||||
int m_NextNum;
|
||||
int m_totlaNum;
|
||||
int m_page,m_totalPage;
|
||||
|
||||
int m_PrevNumlog;
|
||||
int m_NextNumlog;
|
||||
int m_totlaNumlog;
|
||||
int m_pagelog, m_totalPagelog;
|
||||
|
||||
QThread m_Workthread;
|
||||
WorkForDB *m_WorkDB{ nullptr };
|
||||
|
||||
QThread m_WorkThreadCount;
|
||||
CountData *m_WorkCount{ nullptr };
|
||||
|
||||
QThread m_WorkThreadCheckHistory;
|
||||
CheckData *m_WorkHistory{ nullptr };
|
||||
|
||||
WaitingDialog m_Progressdlg;
|
||||
|
||||
bool m_IsRunCountTsk{false};
|
||||
QCompleter *_pCompleter{ nullptr };
|
||||
};
|
||||
|
||||
#endif // REPORTMODEL_H
|
||||
@ -1,18 +0,0 @@
|
||||
#ifndef REPORTMODEL_GLOBAL_H
|
||||
#define REPORTMODEL_GLOBAL_H
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
#include "IWheelCtrl.h"
|
||||
#include "IWheelUi.h"
|
||||
#include "qstring.h"
|
||||
#ifdef REPORTMODEL_LIB
|
||||
# define REPORTMODEL_EXPORT Q_DECL_EXPORT
|
||||
#else
|
||||
# define REPORTMODEL_EXPORT Q_DECL_IMPORT
|
||||
#endif
|
||||
|
||||
extern "C" REPORTMODEL_EXPORT IWheelUi* ReportModelCreate(const QString,class IWheelCtrl * = NULL );
|
||||
extern "C" REPORTMODEL_EXPORT void ReportModelDelete(IWheelUi* pUi);
|
||||
typedef IWheelUi* (*_ReportModelCreate)(const QString, class IWheelCtrl *pCtrl);// 定义导出函数类型 在加载时用于导出
|
||||
|
||||
#endif // REPORTMODEL_GLOBAL_H
|
||||
@ -1,22 +0,0 @@
|
||||
#ifndef TESTWIDGET_H
|
||||
#define TESTWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
#include "ui_testwidget.h"
|
||||
#include <QTreeWidget>
|
||||
class TestWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TestWidget(QWidget *parent = 0);
|
||||
~TestWidget();
|
||||
void initTreewidget(QTreeWidget* pTreewidget);
|
||||
void addIPRoot(QTreeWidget *pTreewidget);
|
||||
void addEDitRoot(QTreeWidget *pTreewidget);
|
||||
private:
|
||||
Ui::TestWidget ui;
|
||||
QTreeWidget * m_treewidget;
|
||||
};
|
||||
|
||||
#endif // TESTWIDGET_H
|
||||
@ -1,35 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TestWidget</class>
|
||||
<widget class="QWidget" name="TestWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>659</width>
|
||||
<height>562</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>TestWidget</string>
|
||||
</property>
|
||||
<widget class="QTreeWidget" name="treeWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>491</width>
|
||||
<height>541</height>
|
||||
</rect>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">1</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@ -1,28 +0,0 @@
|
||||
#ifndef WAITINGDIALOG_H
|
||||
#define WAITINGDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include "QTimer"
|
||||
#include <QProgressBar>
|
||||
class WaitingDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
WaitingDialog(QWidget *parent =0);
|
||||
~WaitingDialog();
|
||||
void Start(int interval = 100, int maxValue = 100);
|
||||
void Stop();
|
||||
|
||||
private slots:
|
||||
void UpdateSlot();
|
||||
private:
|
||||
int m_CurrentValue;
|
||||
int m_UpdateInterval;
|
||||
int m_MaxValue;
|
||||
QTimer m_Timer;
|
||||
QProgressBar *m_ProgressBar;
|
||||
|
||||
};
|
||||
|
||||
#endif // WAITINGDIALOG_H
|
||||
@ -1,32 +0,0 @@
|
||||
#ifndef WORKFORDB_H
|
||||
#define WORKFORDB_H
|
||||
|
||||
#include <QObject>
|
||||
#include "databasesql.h"
|
||||
|
||||
class WorkForDB : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
WorkForDB(QObject *parent = 0){ m_pDb = NULL; };
|
||||
~WorkForDB(){};
|
||||
void setDB(DataBaseSql* pDB){ m_pDb = pDB; };
|
||||
public slots:
|
||||
void doWork(const QString& strTime, const int &ncount)
|
||||
{
|
||||
QString str;
|
||||
if (m_pDb){
|
||||
m_pDb->DelDatasByTime(strTime);
|
||||
m_pDb->DelWarnDataByCount(1, ncount);
|
||||
m_pDb->DelWarnDataByCount(4, ncount);
|
||||
}
|
||||
emit resultReady(str);
|
||||
};
|
||||
private:
|
||||
class DataBaseSql *m_pDb;
|
||||
signals:
|
||||
void resultReady(QString str);
|
||||
};
|
||||
|
||||
#endif // WORKFORDB_H
|
||||
@ -1,275 +0,0 @@
|
||||
#ifndef _EDCIRCLES_
|
||||
#define _EDCIRCLES_
|
||||
|
||||
#include "EDPF.h"
|
||||
#include "EDLines.h"
|
||||
|
||||
#define PI 3.141592653589793238462
|
||||
#define TWOPI (2*PI)
|
||||
|
||||
// Circular arc, circle thresholds
|
||||
#define VERY_SHORT_ARC_ERROR 0.40 // Used for very short arcs (>= CANDIDATE_CIRCLE_RATIO1 && < CANDIDATE_CIRCLE_RATIO2)
|
||||
#define SHORT_ARC_ERROR 1.00 // Used for short arcs (>= CANDIDATE_CIRCLE_RATIO2 && < HALF_CIRCLE_RATIO)
|
||||
#define HALF_ARC_ERROR 1.25 // Used for arcs with length (>=HALF_CIRCLE_RATIO && < FULL_CIRCLE_RATIO)
|
||||
#define LONG_ARC_ERROR 1.50 // Used for long arcs (>= FULL_CIRCLE_RATIO)
|
||||
|
||||
#define CANDIDATE_CIRCLE_RATIO1 0.25 // 25% -- If only 25% of the circle is detected, it may be a candidate for validation
|
||||
#define CANDIDATE_CIRCLE_RATIO2 0.33 // 33% -- If only 33% of the circle is detected, it may be a candidate for validation
|
||||
#define HALF_CIRCLE_RATIO 0.50 // 50% -- If 50% of a circle is detected at any point during joins, we immediately make it a candidate
|
||||
#define FULL_CIRCLE_RATIO 0.87 // 67% -- If 67% of the circle is detected, we assume that it is fully covered
|
||||
|
||||
// Ellipse thresholds
|
||||
#define CANDIDATE_ELLIPSE_RATIO 0.50 // 50% -- If 50% of the ellipse is detected, it may be candidate for validation
|
||||
#define ELLIPSE_ERROR 1.50 // Used for ellipses. (used to be 1.65 for what reason?)
|
||||
|
||||
#define BOOKSTEIN 0 // method1 for ellipse fit
|
||||
#define FPF 1 // method2 for ellipse fit
|
||||
|
||||
enum ImageStyle{NONE=0, CIRCLES, ELLIPSES, BOTH};
|
||||
|
||||
// Circle equation: (x-xc)^2 + (y-yc)^2 = r^2
|
||||
struct mCircle {
|
||||
cv::Point2d center;
|
||||
double r;
|
||||
mCircle(cv::Point2d _center, double _r) { center = _center; r = _r; }
|
||||
};
|
||||
|
||||
// Ellipse equation: Ax^2 + Bxy + Cy^2 + Dx + Ey + F = 0
|
||||
struct mEllipse {
|
||||
cv::Point2d center;
|
||||
cv::Size axes;
|
||||
double theta;
|
||||
mEllipse(cv::Point2d _center, cv::Size _axes, double _theta) { center = _center; axes = _axes; theta = _theta; }
|
||||
};
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Ellipse Equation is of the form:
|
||||
// Ax^2 + Bxy + Cy^2 + Dx + Ey + F = 0
|
||||
//
|
||||
struct EllipseEquation {
|
||||
double coeff[7]; // coeff[1] = A
|
||||
|
||||
EllipseEquation() {
|
||||
for (int i = 0; i<7; i++) coeff[i] = 0;
|
||||
} //end-EllipseEquation
|
||||
|
||||
double A() { return coeff[1]; }
|
||||
double B() { return coeff[2]; }
|
||||
double C() { return coeff[3]; }
|
||||
double D() { return coeff[4]; }
|
||||
double E() { return coeff[5]; }
|
||||
double F() { return coeff[6]; }
|
||||
};
|
||||
|
||||
// ================================ CIRCLES ================================
|
||||
struct Circle {
|
||||
double xc, yc, r; // Center (xc, yc) & radius.
|
||||
double circleFitError; // circle fit error
|
||||
double coverRatio; // Percentage of the circle covered by the arcs making up this circle [0-1]
|
||||
|
||||
double *x, *y; // Pointers to buffers containing the pixels making up this circle
|
||||
int noPixels; // # of pixels making up this circle
|
||||
|
||||
// If this circle is better approximated by an ellipse, we set isEllipse to true & eq contains the ellipse's equation
|
||||
EllipseEquation eq;
|
||||
double ellipseFitError; // ellipse fit error
|
||||
bool isEllipse;
|
||||
double majorAxisLength; // Length of the major axis
|
||||
double minorAxisLength; // Length of the minor axis
|
||||
};
|
||||
|
||||
// ------------------------------------------- ARCS ----------------------------------------------------
|
||||
struct MyArc {
|
||||
double xc, yc, r; // center x, y and radius
|
||||
double circleFitError; // Error during circle fit
|
||||
|
||||
double sTheta, eTheta; // Start & end angle in radius
|
||||
double coverRatio; // Ratio of the pixels covered on the covering circle [0-1] (noPixels/circumference)
|
||||
|
||||
int turn; // Turn direction: 1 or -1
|
||||
|
||||
int segmentNo; // SegmentNo where this arc belongs
|
||||
|
||||
int sx, sy; // Start (x, y) coordinate
|
||||
int ex, ey; // End (x, y) coordinate of the arc
|
||||
|
||||
double *x, *y; // Pointer to buffer containing the pixels making up this arc
|
||||
int noPixels; // # of pixels making up the arc
|
||||
|
||||
bool isEllipse; // Did we fit an ellipse to this arc?
|
||||
EllipseEquation eq; // If an ellipse, then the ellipse's equation
|
||||
double ellipseFitError; // Error during ellipse fit
|
||||
};
|
||||
|
||||
// =============================== AngleSet ==================================
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// add a circular arc to the list of arcs
|
||||
//
|
||||
inline double ArcLength(double sTheta, double eTheta) {
|
||||
if (eTheta > sTheta) return eTheta - sTheta;
|
||||
else return TWOPI - sTheta + eTheta;
|
||||
} // end-ArcLength
|
||||
|
||||
// A fast implementation of the AngleSet class. The slow implementation is really bad. About 10 times slower than this!
|
||||
struct AngleSetArc {
|
||||
double sTheta;
|
||||
double eTheta;
|
||||
int next; // Next AngleSetArc in the linked list
|
||||
};
|
||||
|
||||
struct AngleSet {
|
||||
AngleSetArc angles[360];
|
||||
int head;
|
||||
int next; // Next AngleSetArc to be allocated
|
||||
double overlapAmount; // Total overlap of the arcs in angleSet. Computed during set() function
|
||||
|
||||
AngleSet() { clear(); } //end-AngleSet
|
||||
void clear() { head = -1; next = 0; overlapAmount = 0; }
|
||||
double overlapRatio() { return overlapAmount / (TWOPI); }
|
||||
|
||||
void _set(double sTheta, double eTheta);
|
||||
void set(double sTheta, double eTheta);
|
||||
|
||||
double _overlap(double sTheta, double eTheta);
|
||||
double overlap(double sTheta, double eTheta);
|
||||
|
||||
void computeStartEndTheta(double &sTheta, double &eTheta);
|
||||
double coverRatio();
|
||||
};
|
||||
|
||||
|
||||
struct EDArcs {
|
||||
MyArc *arcs;
|
||||
int noArcs;
|
||||
|
||||
public:
|
||||
EDArcs(int size = 10000) {
|
||||
arcs = new MyArc[size];
|
||||
noArcs = 0;
|
||||
} //end-EDArcs
|
||||
|
||||
~EDArcs() {
|
||||
delete arcs;
|
||||
} //end-~EDArcs
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// Buffer manager
|
||||
struct BufferManager {
|
||||
double *x, *y;
|
||||
int index;
|
||||
|
||||
BufferManager(int maxSize) {
|
||||
x = new double[maxSize];
|
||||
y = new double[maxSize];
|
||||
index = 0;
|
||||
} //end-BufferManager
|
||||
|
||||
~BufferManager() {
|
||||
delete x;
|
||||
delete y;
|
||||
} //end-~BufferManager
|
||||
|
||||
double *getX() { return &x[index]; }
|
||||
double *getY() { return &y[index]; }
|
||||
void move(int size) { index += size; }
|
||||
};
|
||||
|
||||
struct Info {
|
||||
int sign; // -1 or 1: sign of the cross product
|
||||
double angle; // angle with the next line (in radians)
|
||||
bool taken; // Is this line taken during arc detection
|
||||
};
|
||||
|
||||
|
||||
class EDCircles: public EDPF {
|
||||
public:
|
||||
EDCircles(cv::Mat srcImage);
|
||||
EDCircles(ED obj);
|
||||
EDCircles(EDColor obj);
|
||||
|
||||
cv::Mat drawResult(bool, ImageStyle);
|
||||
|
||||
std::vector<mCircle> getCircles();
|
||||
std::vector<mEllipse> getEllipses();
|
||||
int getCirclesNo();
|
||||
int getEllipsesNo();
|
||||
|
||||
private:
|
||||
int noEllipses;
|
||||
int noCircles;
|
||||
std::vector<mCircle> circles;
|
||||
std::vector<mEllipse> ellipses;
|
||||
|
||||
Circle *circles1;
|
||||
Circle *circles2;
|
||||
Circle *circles3;
|
||||
int noCircles1;
|
||||
int noCircles2;
|
||||
int noCircles3;
|
||||
|
||||
EDArcs *edarcs1;
|
||||
EDArcs *edarcs2;
|
||||
EDArcs *edarcs3;
|
||||
EDArcs *edarcs4;
|
||||
|
||||
int *segmentStartLines;
|
||||
BufferManager *bm;
|
||||
Info *info;
|
||||
NFALUT *nfa;
|
||||
|
||||
void GenerateCandidateCircles();
|
||||
void DetectArcs(std::vector<LineSegment> lines);
|
||||
void ValidateCircles();
|
||||
void JoinCircles();
|
||||
void JoinArcs1();
|
||||
void JoinArcs2();
|
||||
void JoinArcs3();
|
||||
|
||||
// circle utility functions
|
||||
static Circle *addCircle(Circle *circles, int &noCircles,double xc, double yc, double r, double circleFitError, double *x, double *y, int noPixels);
|
||||
static Circle *addCircle(Circle *circles, int &noCircles,double xc, double yc, double r, double circleFitError, EllipseEquation *pEq, double ellipseFitError, double *x, double *y, int noPixels);
|
||||
static void sortCircles(Circle *circles, int noCircles);
|
||||
static bool CircleFit(double *x, double *y, int N, double *pxc, double *pyc, double *pr, double *pe);
|
||||
static void ComputeCirclePoints(double xc, double yc, double r, double *px, double *py, int *noPoints);
|
||||
static void sortCircle(Circle *circles, int noCircles);
|
||||
|
||||
// ellipse utility functions
|
||||
static bool EllipseFit(double *x, double *y, int noPoints, EllipseEquation *pResult, int mode=FPF);
|
||||
static double **AllocateMatrix(int noRows, int noColumns);
|
||||
static void A_TperB(double **_A, double **_B, double **_res, int _righA, int _colA, int _righB, int _colB);
|
||||
static void choldc(double **a, int n, double **l);
|
||||
static int inverse(double **TB, double **InvB, int N);
|
||||
static void DeallocateMatrix(double **m, int noRows);
|
||||
static void AperB_T(double **_A, double **_B, double **_res, int _righA, int _colA, int _righB, int _colB);
|
||||
static void AperB(double **_A, double **_B, double **_res, int _righA, int _colA, int _righB, int _colB);
|
||||
static void jacobi(double **a, int n, double d[], double **v, int nrot);
|
||||
static void ROTATE(double **a, int i, int j, int k, int l, double tau, double s);
|
||||
static double computeEllipsePerimeter(EllipseEquation *eq);
|
||||
static double ComputeEllipseError(EllipseEquation *eq, double *px, double *py, int noPoints);
|
||||
static double ComputeEllipseCenterAndAxisLengths(EllipseEquation *eq, double *pxc, double *pyc, double *pmajorAxisLength, double *pminorAxisLength);
|
||||
static void ComputeEllipsePoints(double *pvec, double *px, double *py, int noPoints);
|
||||
|
||||
// arc utility functions
|
||||
static void joinLastTwoArcs(MyArc *arcs, int &noArcs);
|
||||
static void addArc(MyArc *arcs, int &noArchs,double xc, double yc, double r, double circleFitError, // Circular arc
|
||||
double sTheta, double eTheta, int turn, int segmentNo,
|
||||
int sx, int sy, int ex, int ey,
|
||||
double *x, double *y, int noPixels, double overlapRatio = 0.0);
|
||||
static void addArc(MyArc *arcs, int &noArchs, double xc, double yc, double r, double circleFitError, // Elliptic arc
|
||||
double sTheta, double eTheta, int turn, int segmentNo,
|
||||
EllipseEquation *pEq, double ellipseFitError,
|
||||
int sx, int sy, int ex, int ey,
|
||||
double *x, double *y, int noPixels, double overlapRatio = 0.0);
|
||||
|
||||
static void ComputeStartAndEndAngles(double xc, double yc, double r,
|
||||
double *x, double *y, int len,
|
||||
double *psTheta, double *peTheta);
|
||||
|
||||
static void sortArc(MyArc *arcs, int noArcs);
|
||||
};
|
||||
|
||||
#endif // ! _EDCIRCLES_
|
||||
|
||||
@ -1,77 +0,0 @@
|
||||
#ifndef _EDColor_
|
||||
#define _EDColor_
|
||||
|
||||
#include <opencv2/opencv.hpp>
|
||||
|
||||
// Look up table size for fast color space conversion
|
||||
#define LUT_SIZE (1024*4096)
|
||||
|
||||
// Special defines
|
||||
#define EDGE_VERTICAL 1
|
||||
#define EDGE_HORIZONTAL 2
|
||||
#define EDGE_45 3
|
||||
#define EDGE_135 4
|
||||
|
||||
#define MAX_GRAD_VALUE 128*256
|
||||
#define EPSILON 1.0
|
||||
#define MIN_PATH_LEN 10
|
||||
|
||||
|
||||
class EDColor {
|
||||
public:
|
||||
EDColor(cv::Mat srcImage, int gradThresh = 20, int anchor_thresh = 4, double sigma = 1.5, bool validateSegments=false);
|
||||
cv::Mat getEdgeImage();
|
||||
std::vector<std::vector<cv::Point>> getSegments();
|
||||
int getSegmentNo();
|
||||
|
||||
int getWidth();
|
||||
int getHeight();
|
||||
|
||||
cv::Mat inputImage;
|
||||
private:
|
||||
uchar *L_Img;
|
||||
uchar *a_Img;
|
||||
uchar *b_Img;
|
||||
|
||||
uchar *smooth_L;
|
||||
uchar *smooth_a;
|
||||
uchar *smooth_b;
|
||||
|
||||
uchar *dirImg;
|
||||
short *gradImg;
|
||||
|
||||
cv::Mat edgeImage;
|
||||
uchar *edgeImg;
|
||||
|
||||
const uchar *blueImg;
|
||||
const uchar *greenImg;
|
||||
const uchar *redImg;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
|
||||
double divForTestSegment;
|
||||
double *H;
|
||||
int np;
|
||||
int segmentNo;
|
||||
|
||||
std::vector<std::vector<cv::Point>> segments;
|
||||
|
||||
static double LUT1[LUT_SIZE + 1];
|
||||
static double LUT2[LUT_SIZE + 1];
|
||||
static bool LUT_Initialized;
|
||||
|
||||
void MyRGB2LabFast();
|
||||
void ComputeGradientMapByDiZenzo();
|
||||
void smoothChannel(uchar *src, uchar *smooth, double sigma);
|
||||
void validateEdgeSegments();
|
||||
void testSegment(int i, int index1, int index2);
|
||||
void extractNewSegments();
|
||||
double NFA(double prob, int len);
|
||||
|
||||
static void fixEdgeSegments(std::vector<std::vector<cv::Point>> map, int noPixels);
|
||||
|
||||
static void InitColorEDLib();
|
||||
};
|
||||
|
||||
#endif // ! _EDColor_
|
||||
@ -1,27 +0,0 @@
|
||||
#ifndef _EDPF_
|
||||
#define _EDPF_
|
||||
|
||||
#include "ED.h"
|
||||
|
||||
#define MAX_GRAD_VALUE 128*256
|
||||
#define EPSILON 1.0
|
||||
|
||||
class EDPF : public ED {
|
||||
public:
|
||||
EDPF(cv::Mat srcImage);
|
||||
EDPF(ED obj);
|
||||
EDPF(EDColor obj);
|
||||
private:
|
||||
double divForTestSegment;
|
||||
double *H;
|
||||
int np;
|
||||
short *gradImg;
|
||||
|
||||
void validateEdgeSegments();
|
||||
short *ComputePrewitt3x3(); // differs from base class's prewit function (calculates H)
|
||||
void TestSegment(int i, int index1, int index2);
|
||||
void ExtractNewSegments();
|
||||
double NFA(double prob, int len);
|
||||
};
|
||||
|
||||
#endif // ! _EDPF_
|
||||
@ -1,51 +0,0 @@
|
||||
#ifndef _NFA_
|
||||
#define _NFA_
|
||||
|
||||
#define TABSIZE 100000
|
||||
|
||||
//----------------------------------------------
|
||||
// Fast arctan2 using a lookup table
|
||||
//
|
||||
#define MAX_LUT_SIZE 1024
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif /* !TRUE */
|
||||
|
||||
/** ln(10) */
|
||||
#ifndef M_LN10
|
||||
#define M_LN10 2.30258509299404568402
|
||||
#endif /* !M_LN10 */
|
||||
|
||||
/** PI */
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif /* !M_PI */
|
||||
|
||||
#define RELATIVE_ERROR_FACTOR 100.0
|
||||
|
||||
// Lookup table (LUT) for NFA computation
|
||||
class NFALUT {
|
||||
public:
|
||||
|
||||
NFALUT(int size, double _prob, double _logNT);
|
||||
~NFALUT();
|
||||
|
||||
int *LUT; // look up table
|
||||
int LUTSize;
|
||||
|
||||
double prob;
|
||||
double logNT;
|
||||
|
||||
bool checkValidationByNFA(int n, int k);
|
||||
static double myAtan2(double yy, double xx);
|
||||
|
||||
private:
|
||||
double nfa(int n, int k);
|
||||
static double log_gamma_lanczos(double x);
|
||||
static double log_gamma_windschitl(double x);
|
||||
static double log_gamma(double x);
|
||||
static int double_equal(double a, double b);
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,624 +0,0 @@
|
||||
#include "EDColor.h"
|
||||
#include "ED.h"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
EDColor::EDColor(Mat srcImage, int gradThresh, int anchor_thresh , double sigma, bool validateSegments)
|
||||
{
|
||||
inputImage = srcImage.clone();
|
||||
|
||||
// check parameters for sanity
|
||||
if (sigma < 1) sigma = 1;
|
||||
if (gradThresh < 1) gradThresh = 1;
|
||||
if (anchor_thresh < 0) anchor_thresh = 0;
|
||||
|
||||
if (validateSegments) { // setup for validation
|
||||
anchor_thresh = 0;
|
||||
divForTestSegment = 2.25;
|
||||
}
|
||||
|
||||
// split channels (OpenCV uses BGR)
|
||||
Mat bgr[3];
|
||||
split(srcImage, bgr);
|
||||
blueImg = bgr[0].data;
|
||||
greenImg = bgr[1].data;
|
||||
redImg = bgr[2].data;
|
||||
|
||||
height = srcImage.rows;
|
||||
width = srcImage.cols;
|
||||
|
||||
// Allocate space for L*a*b color space
|
||||
L_Img = new uchar[width*height];
|
||||
a_Img = new uchar[width*height];
|
||||
b_Img = new uchar[width*height];
|
||||
|
||||
// Convert RGB2Lab
|
||||
MyRGB2LabFast();
|
||||
|
||||
// Allocate space for smooth channels
|
||||
smooth_L = new uchar[width*height];
|
||||
smooth_a = new uchar[width*height];
|
||||
smooth_b = new uchar[width*height];
|
||||
|
||||
// Smooth Channels
|
||||
smoothChannel(L_Img, smooth_L, sigma);
|
||||
smoothChannel(a_Img, smooth_a, sigma);
|
||||
smoothChannel(b_Img, smooth_b, sigma);
|
||||
|
||||
// Allocate space for direction and gradient images
|
||||
dirImg = new uchar[width*height];
|
||||
gradImg = new short[width*height];
|
||||
|
||||
// Compute Gradient & Edge Direction Maps
|
||||
ComputeGradientMapByDiZenzo();
|
||||
|
||||
|
||||
// Validate edge segments if the flag is set
|
||||
if (validateSegments) {
|
||||
// Get Edge Image using ED
|
||||
ED edgeObj = ED(gradImg, dirImg, width, height, gradThresh, anchor_thresh, 1, 10, false);
|
||||
segments = edgeObj.getSegments();
|
||||
edgeImage = edgeObj.getEdgeImage();
|
||||
|
||||
sigma /= 2.5;
|
||||
smoothChannel(L_Img, smooth_L, sigma);
|
||||
smoothChannel(a_Img, smooth_a, sigma);
|
||||
smoothChannel(b_Img, smooth_b, sigma);
|
||||
|
||||
edgeImg = edgeImage.data; // validation steps uses pointer to edgeImage
|
||||
|
||||
validateEdgeSegments();
|
||||
|
||||
// Extract the new edge segments after validation
|
||||
extractNewSegments();
|
||||
}
|
||||
|
||||
else {
|
||||
ED edgeObj = ED(gradImg, dirImg, width, height, gradThresh, anchor_thresh);
|
||||
segments = edgeObj.getSegments();
|
||||
edgeImage = edgeObj.getEdgeImage();
|
||||
segmentNo = edgeObj.getSegmentNo();
|
||||
}
|
||||
|
||||
// Fix 1 pixel errors in the edge map
|
||||
fixEdgeSegments(segments, 1);
|
||||
|
||||
// clean space
|
||||
delete[] L_Img;
|
||||
delete[] a_Img;
|
||||
delete[] b_Img;
|
||||
|
||||
delete[] smooth_L;
|
||||
delete[] smooth_a;
|
||||
delete[] smooth_b;
|
||||
|
||||
delete[] gradImg;
|
||||
delete[] dirImg;
|
||||
}
|
||||
|
||||
cv::Mat EDColor::getEdgeImage()
|
||||
{
|
||||
return edgeImage;
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::vector<cv::Point>> EDColor::getSegments()
|
||||
{
|
||||
return segments;
|
||||
}
|
||||
|
||||
int EDColor::getSegmentNo()
|
||||
{
|
||||
return segmentNo;
|
||||
}
|
||||
|
||||
int EDColor::getWidth()
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
int EDColor::getHeight()
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
void EDColor::MyRGB2LabFast()
|
||||
{
|
||||
// Inialize LUTs if necessary
|
||||
if (!LUT_Initialized)
|
||||
InitColorEDLib();
|
||||
|
||||
// First RGB 2 XYZ
|
||||
double red, green, blue;
|
||||
double x, y, z;
|
||||
|
||||
// Space for temp. allocation
|
||||
double *L = new double[width*height];
|
||||
double *a = new double[width*height];
|
||||
double *b = new double[width*height];
|
||||
|
||||
for (int i = 0; i<width*height; i++) {
|
||||
red = redImg[i] / 255.0;
|
||||
green = greenImg[i] / 255.0;
|
||||
blue = blueImg[i] / 255.0;
|
||||
|
||||
red = LUT1[(int)(red*LUT_SIZE + 0.5)];
|
||||
green = LUT1[(int)(green*LUT_SIZE + 0.5)];
|
||||
blue = LUT1[(int)(blue*LUT_SIZE + 0.5)];
|
||||
|
||||
red = red * 100;
|
||||
green = green * 100;
|
||||
blue = blue * 100;
|
||||
|
||||
//Observer. = 2? Illuminant = D65
|
||||
x = red*0.4124564 + green*0.3575761 + blue*0.1804375;
|
||||
y = red*0.2126729 + green*0.7151522 + blue*0.0721750;
|
||||
z = red*0.0193339 + green*0.1191920 + blue*0.9503041;
|
||||
|
||||
// Now xyz 2 Lab
|
||||
double refX = 95.047;
|
||||
double refY = 100.000;
|
||||
double refZ = 108.883;
|
||||
|
||||
x = x / refX; //ref_X = 95.047 Observer= 2? Illuminant= D65
|
||||
y = y / refY; //ref_Y = 100.000
|
||||
z = z / refZ; //ref_Z = 108.883
|
||||
|
||||
x = LUT2[(int)(x*LUT_SIZE + 0.5)];
|
||||
y = LUT2[(int)(y*LUT_SIZE + 0.5)];
|
||||
z = LUT2[(int)(z*LUT_SIZE + 0.5)];
|
||||
|
||||
L[i] = (116.0*y) - 16;
|
||||
a[i] = 500 * (x / y);
|
||||
b[i] = 200 * (y - z);
|
||||
} //end-for
|
||||
|
||||
// Scale L to [0-255]
|
||||
double min = 1e10;
|
||||
double max = -1e10;
|
||||
for (int i = 0; i<width*height; i++) {
|
||||
if (L[i]<min) min = L[i];
|
||||
else if (L[i]>max) max = L[i];
|
||||
} //end-for
|
||||
|
||||
double scale = 255.0 / (max - min);
|
||||
for (int i = 0; i<width*height; i++) { L_Img[i] = (unsigned char)((L[i] - min)*scale); }
|
||||
|
||||
// Scale a to [0-255]
|
||||
min = 1e10;
|
||||
max = -1e10;
|
||||
for (int i = 0; i<width*height; i++) {
|
||||
if (a[i]<min) min = a[i];
|
||||
else if (a[i]>max) max = a[i];
|
||||
} //end-for
|
||||
|
||||
scale = 255.0 / (max - min);
|
||||
for (int i = 0; i<width*height; i++) { a_Img[i] = (unsigned char)((a[i] - min)*scale); }
|
||||
|
||||
// Scale b to [0-255]
|
||||
min = 1e10;
|
||||
max = -1e10;
|
||||
for (int i = 0; i<width*height; i++) {
|
||||
if (b[i]<min) min = b[i];
|
||||
else if (b[i]>max) max = b[i];
|
||||
} //end-for
|
||||
|
||||
scale = 255.0 / (max - min);
|
||||
for (int i = 0; i<width*height; i++) { b_Img[i] = (unsigned char)((b[i] - min)*scale); }
|
||||
|
||||
|
||||
// clean space
|
||||
delete[] L;
|
||||
delete[] a;
|
||||
delete[] b;
|
||||
}
|
||||
|
||||
void EDColor::ComputeGradientMapByDiZenzo()
|
||||
{
|
||||
memset(gradImg, 0, sizeof(short)*width*height);
|
||||
|
||||
int max = 0;
|
||||
|
||||
for (int i = 1; i < height - 1; i++) {
|
||||
for (int j = 1; j < width - 1; j++) {
|
||||
#if 1
|
||||
// Prewitt for channel1
|
||||
int com1 = smooth_L[(i + 1)*width + j + 1] - smooth_L[(i - 1)*width + j - 1];
|
||||
int com2 = smooth_L[(i - 1)*width + j + 1] - smooth_L[(i + 1)*width + j - 1];
|
||||
|
||||
int gxCh1 = com1 + com2 + (smooth_L[i*width + j + 1] - smooth_L[i*width + j - 1]);
|
||||
int gyCh1 = com1 - com2 + (smooth_L[(i + 1)*width + j] - smooth_L[(i - 1)*width + j]);
|
||||
|
||||
// Prewitt for channel2
|
||||
com1 = smooth_a[(i + 1)*width + j + 1] - smooth_a[(i - 1)*width + j - 1];
|
||||
com2 = smooth_a[(i - 1)*width + j + 1] - smooth_a[(i + 1)*width + j - 1];
|
||||
|
||||
int gxCh2 = com1 + com2 + (smooth_a[i*width + j + 1] - smooth_a[i*width + j - 1]);
|
||||
int gyCh2 = com1 - com2 + (smooth_a[(i + 1)*width + j] - smooth_a[(i - 1)*width + j]);
|
||||
|
||||
// Prewitt for channel3
|
||||
com1 = smooth_b[(i + 1)*width + j + 1] - smooth_b[(i - 1)*width + j - 1];
|
||||
com2 = smooth_b[(i - 1)*width + j + 1] - smooth_b[(i + 1)*width + j - 1];
|
||||
|
||||
int gxCh3 = com1 + com2 + (smooth_b[i*width + j + 1] - smooth_b[i*width + j - 1]);
|
||||
int gyCh3 = com1 - com2 + (smooth_b[(i + 1)*width + j] - smooth_b[(i - 1)*width + j]);
|
||||
#else
|
||||
// Sobel for channel1
|
||||
int com1 = smooth_L[(i + 1)*width + j + 1] - smooth_L[(i - 1)*width + j - 1];
|
||||
int com2 = smooth_L[(i - 1)*width + j + 1] - smooth_L[(i + 1)*width + j - 1];
|
||||
|
||||
int gxCh1 = com1 + com2 + 2 * (smooth_L[i*width + j + 1] - smooth_L[i*width + j - 1]);
|
||||
int gyCh1 = com1 - com2 + 2 * (smooth_L[(i + 1)*width + j] - smooth_L[(i - 1)*width + j]);
|
||||
|
||||
// Sobel for channel2
|
||||
com1 = smooth_a[(i + 1)*width + j + 1] - smooth_a[(i - 1)*width + j - 1];
|
||||
com2 = smooth_a[(i - 1)*width + j + 1] - smooth_a[(i + 1)*width + j - 1];
|
||||
|
||||
int gxCh2 = com1 + com2 + 2 * (smooth_a[i*width + j + 1] - smooth_a[i*width + j - 1]);
|
||||
int gyCh2 = com1 - com2 + 2 * (smooth_a[(i + 1)*width + j] - smooth_a[(i - 1)*width + j]);
|
||||
|
||||
// Sobel for channel3
|
||||
com1 = smooth_b[(i + 1)*width + j + 1] - smooth_b[(i - 1)*width + j - 1];
|
||||
com2 = smooth_b[(i - 1)*width + j + 1] - smooth_b[(i + 1)*width + j - 1];
|
||||
|
||||
int gxCh3 = com1 + com2 + 2 * (smooth_b[i*width + j + 1] - smooth_b[i*width + j - 1]);
|
||||
int gyCh3 = com1 - com2 + 2 * (smooth_b[(i + 1)*width + j] - smooth_b[(i - 1)*width + j]);
|
||||
#endif
|
||||
int gxx = gxCh1*gxCh1 + gxCh2*gxCh2 + gxCh3*gxCh3;
|
||||
int gyy = gyCh1*gyCh1 + gyCh2*gyCh2 + gyCh3*gyCh3;
|
||||
int gxy = gxCh1*gyCh1 + gxCh2*gyCh2 + gxCh3*gyCh3;
|
||||
|
||||
#if 1
|
||||
// Di Zenzo's formulas from Gonzales & Woods - Page 337
|
||||
double theta = atan2(2.0*gxy, (double)(gxx - gyy)) / 2; // Gradient Direction
|
||||
int grad = (int)(sqrt(((gxx + gyy) + (gxx - gyy)*cos(2 * theta) + 2 * gxy*sin(2 * theta)) / 2.0) + 0.5); // Gradient Magnitude
|
||||
#else
|
||||
// Koschan & Abidi - 2005 - Signal Processing Magazine
|
||||
double theta = atan2(2.0*gxy, (double)(gxx - gyy)) / 2; // Gradient Direction
|
||||
|
||||
double cosTheta = cos(theta);
|
||||
double sinTheta = sin(theta);
|
||||
int grad = (int)(sqrt(gxx*cosTheta*cosTheta + 2 * gxy*sinTheta*cosTheta + gyy*sinTheta*sinTheta) + 0.5); // Gradient Magnitude
|
||||
#endif
|
||||
|
||||
// Gradient is perpendicular to the edge passing through the pixel
|
||||
if (theta >= -3.14159 / 4 && theta <= 3.14159 / 4)
|
||||
dirImg[i*width + j] = EDGE_VERTICAL;
|
||||
else
|
||||
dirImg[i*width + j] = EDGE_HORIZONTAL;
|
||||
|
||||
gradImg[i*width + j] = grad;
|
||||
if (grad > max) max = grad;
|
||||
|
||||
}
|
||||
} // end outer for
|
||||
|
||||
// Scale the gradient values to 0-255
|
||||
double scale = 255.0 / max;
|
||||
for (int i = 0; i<width*height; i++)
|
||||
gradImg[i] = (short)(gradImg[i] * scale);
|
||||
}
|
||||
|
||||
void EDColor::smoothChannel(uchar *src, uchar *smooth, double sigma)
|
||||
{
|
||||
Mat srcImage = Mat(height, width, CV_8UC1, src);
|
||||
Mat smoothImage = Mat(height, width, CV_8UC1, smooth);
|
||||
|
||||
if (sigma == 1.0)
|
||||
GaussianBlur(srcImage, smoothImage, Size(5, 5), 1);
|
||||
else if (sigma == 1.5)
|
||||
GaussianBlur(srcImage, smoothImage, Size(7, 7), 1.5); // seems to be better?
|
||||
else
|
||||
GaussianBlur(srcImage, smoothImage, Size(), sigma);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------
|
||||
// Validate the edge segments using the Helmholtz principle (for color images) channel1, channel2 and channel3 images
|
||||
//
|
||||
void EDColor::validateEdgeSegments()
|
||||
{
|
||||
int maxGradValue = MAX_GRAD_VALUE;
|
||||
H = new double[maxGradValue];
|
||||
memset(H, 0, sizeof(double)*maxGradValue);
|
||||
|
||||
memset(edgeImg, 0, width*height); // clear edge image
|
||||
|
||||
// Compute the gradient
|
||||
memset(gradImg, 0, sizeof(short)*width*height); // reset gradient Image pixels to zero
|
||||
|
||||
int *grads = new int[maxGradValue];
|
||||
memset(grads, 0, sizeof(int)*maxGradValue);
|
||||
|
||||
for (int i = 1; i<height - 1; i++) {
|
||||
for (int j = 1; j<width - 1; j++) {
|
||||
// Gradient for channel1
|
||||
int com1 = smooth_L[(i + 1)*width + j + 1] - smooth_L[(i - 1)*width + j - 1];
|
||||
int com2 = smooth_L[(i - 1)*width + j + 1] - smooth_L[(i + 1)*width + j - 1];
|
||||
|
||||
int gxCh1 = abs(com1 + com2 + (smooth_L[i*width + j + 1] - smooth_L[i*width + j - 1]));
|
||||
int gyCh1 = abs(com1 - com2 + (smooth_L[(i + 1)*width + j] - smooth_L[(i - 1)*width + j]));
|
||||
int ch1Grad = gxCh1 + gyCh1;
|
||||
|
||||
// Gradient for channel2
|
||||
com1 = smooth_a[(i + 1)*width + j + 1] - smooth_a[(i - 1)*width + j - 1];
|
||||
com2 = smooth_a[(i - 1)*width + j + 1] - smooth_a[(i + 1)*width + j - 1];
|
||||
|
||||
int gxCh2 = abs(com1 + com2 + (smooth_a[i*width + j + 1] - smooth_a[i*width + j - 1]));
|
||||
int gyCh2 = abs(com1 - com2 + (smooth_a[(i + 1)*width + j] - smooth_a[(i - 1)*width + j]));
|
||||
int ch2Grad = gxCh2 + gyCh2;
|
||||
|
||||
// Gradient for channel3
|
||||
com1 = smooth_b[(i + 1)*width + j + 1] - smooth_b[(i - 1)*width + j - 1];
|
||||
com2 = smooth_b[(i - 1)*width + j + 1] - smooth_b[(i + 1)*width + j - 1];
|
||||
|
||||
int gxCh3 = abs(com1 + com2 + (smooth_b[i*width + j + 1] - smooth_b[i*width + j - 1]));
|
||||
int gyCh3 = abs(com1 - com2 + (smooth_b[(i + 1)*width + j] - smooth_b[(i - 1)*width + j]));
|
||||
int ch3Grad = gxCh3 + gyCh3;
|
||||
|
||||
// Take average
|
||||
int grad = (ch1Grad + ch2Grad + ch3Grad + 2) / 3;
|
||||
|
||||
gradImg[i*width + j] = grad;
|
||||
grads[grad]++;
|
||||
} //end-for
|
||||
} //end-for
|
||||
|
||||
Mat gradImage = Mat(height, width, CV_16SC1, gradImg);
|
||||
imwrite("newGrad.pgm", gradImage);
|
||||
|
||||
// Compute probability function H
|
||||
int size = (width - 2)*(height - 2);
|
||||
// size -= grads[0];
|
||||
|
||||
for (int i = maxGradValue - 1; i>0; i--)
|
||||
grads[i - 1] += grads[i];
|
||||
|
||||
for (int i = 0; i<maxGradValue; i++)
|
||||
H[i] = (double)grads[i] / ((double)size);
|
||||
|
||||
// Compute np: # of segment pieces
|
||||
np = 0;
|
||||
for (int i = 0; i<segments.size(); i++) {
|
||||
int len = segments[i].size();
|
||||
np += (len*(len - 1)) / 2;
|
||||
} //end-for
|
||||
|
||||
// Validate segments
|
||||
for (int i = 0; i< segments.size(); i++) {
|
||||
testSegment(i, 0, segments[i].size() - 1);
|
||||
} //end-for
|
||||
|
||||
// clear space
|
||||
delete[] H;
|
||||
delete[] grads;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Resursive validation using half of the pixels as suggested by DMM algorithm
|
||||
// We take pixels at Nyquist distance, i.e., 2 (as suggested by DMM)
|
||||
//
|
||||
void EDColor::testSegment(int i, int index1, int index2)
|
||||
{
|
||||
|
||||
int chainLen = index2 - index1 + 1;
|
||||
if (chainLen < MIN_PATH_LEN)
|
||||
return;
|
||||
|
||||
// Test from index1 to index2. If OK, then we are done. Otherwise, split into two and
|
||||
// recursively test the left & right halves
|
||||
|
||||
// First find the min. gradient along the segment
|
||||
int minGrad = 1 << 30;
|
||||
int minGradIndex;
|
||||
for (int k = index1; k <= index2; k++) {
|
||||
int r = segments[i][k].y;
|
||||
int c = segments[i][k].x;
|
||||
if (gradImg[r*width + c] < minGrad) { minGrad = gradImg[r*width + c]; minGradIndex = k; }
|
||||
} //end-for
|
||||
|
||||
// Compute nfa
|
||||
double nfa = NFA(H[minGrad], (int)(chainLen / divForTestSegment));
|
||||
|
||||
if (nfa <= EPSILON) {
|
||||
for (int k = index1; k <= index2; k++) {
|
||||
int r = segments[i][k].y;
|
||||
int c = segments[i][k].x;
|
||||
|
||||
edgeImg[r*width + c] = 255;
|
||||
} //end-for
|
||||
|
||||
return;
|
||||
} //end-if
|
||||
|
||||
// Split into two halves. We divide at the point where the gradient is the minimum
|
||||
int end = minGradIndex - 1;
|
||||
while (end > index1) {
|
||||
int r = segments[i][end].y;
|
||||
int c = segments[i][end].x;
|
||||
|
||||
if (gradImg[r*width + c] <= minGrad) end--;
|
||||
else break;
|
||||
} //end-while
|
||||
|
||||
int start = minGradIndex + 1;
|
||||
while (start < index2) {
|
||||
int r = segments[i][start].y;
|
||||
int c = segments[i][start].x;
|
||||
|
||||
if (gradImg[r*width + c] <= minGrad) start++;
|
||||
else break;
|
||||
} //end-while
|
||||
|
||||
testSegment(i, index1, end);
|
||||
testSegment(i, start, index2);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------
|
||||
// After the validation of the edge segments, extracts the valid ones
|
||||
// In other words, updates the valid segments' pixel arrays and their lengths
|
||||
//
|
||||
void EDColor::extractNewSegments()
|
||||
{
|
||||
vector< vector<Point> > validSegments;
|
||||
int noSegments = 0;
|
||||
|
||||
for (int i = 0; i < segments.size(); i++) {
|
||||
int start = 0;
|
||||
while (start < segments[i].size()) {
|
||||
|
||||
while (start < segments[i].size()) {
|
||||
int r = segments[i][start].y;
|
||||
int c = segments[i][start].x;
|
||||
|
||||
if (edgeImg[r*width + c]) break;
|
||||
start++;
|
||||
} //end-while
|
||||
|
||||
int end = start + 1;
|
||||
while (end < segments[i].size()) {
|
||||
int r = segments[i][end].y;
|
||||
int c = segments[i][end].x;
|
||||
|
||||
if (edgeImg[r*width + c] == 0) break;
|
||||
end++;
|
||||
} //end-while
|
||||
|
||||
int len = end - start;
|
||||
if (len >= 10) {
|
||||
// A new segment. Accepted only only long enough (whatever that means)
|
||||
//segments[noSegments].pixels = &map->segments[i].pixels[start];
|
||||
//segments[noSegments].noPixels = len;
|
||||
validSegments.push_back(vector<Point>());
|
||||
vector<Point> subVec(&segments[i][start], &segments[i][end - 1]);
|
||||
validSegments[noSegments] = subVec;
|
||||
noSegments++;
|
||||
} //end-else
|
||||
|
||||
start = end + 1;
|
||||
} //end-while
|
||||
} //end-for
|
||||
|
||||
// Update
|
||||
segments = validSegments;
|
||||
segmentNo = noSegments; // = validSegments.size()
|
||||
|
||||
}
|
||||
|
||||
|
||||
double EDColor::NFA(double prob, int len)
|
||||
{
|
||||
double nfa = np;
|
||||
for (int i = 0; i<len && nfa > EPSILON; i++)
|
||||
nfa *= prob;
|
||||
|
||||
return nfa;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------
|
||||
// Fix edge segments having one or two pixel fluctuations
|
||||
// An example one pixel problem getting fixed:
|
||||
// x
|
||||
// x x --> xxx
|
||||
//
|
||||
// An example two pixel problem getting fixed:
|
||||
// xx
|
||||
// x x --> xxxx
|
||||
//
|
||||
void EDColor::fixEdgeSegments(std::vector<std::vector<cv::Point>> map, int noPixels)
|
||||
{
|
||||
/// First fix one pixel problems: There are four cases
|
||||
for (int i = 0; i < map.size(); i++) {
|
||||
int cp = map[i].size() - 2; // Current pixel index
|
||||
int n2 = 0; // next next pixel index
|
||||
|
||||
while (n2 < map[i].size()) {
|
||||
int n1 = cp + 1; // next pixel
|
||||
|
||||
cp = cp % map[i].size(); // Roll back to the beginning
|
||||
n1 = n1 % map[i].size(); // Roll back to the beginning
|
||||
|
||||
int r = map[i][cp].y;
|
||||
int c = map[i][cp].x;
|
||||
|
||||
int r1 = map[i][n1].y;
|
||||
int c1 = map[i][n1].x;
|
||||
|
||||
int r2 = map[i][n2].y;
|
||||
int c2 = map[i][n2].x;
|
||||
|
||||
// 4 cases to fix
|
||||
if (r2 == r - 2 && c2 == c) {
|
||||
if (c1 != c) {
|
||||
map[i][n1].x = c;
|
||||
} //end-if
|
||||
|
||||
cp = n2;
|
||||
n2 += 2;
|
||||
|
||||
}
|
||||
else if (r2 == r + 2 && c2 == c) {
|
||||
if (c1 != c) {
|
||||
map[i][n1].x = c;
|
||||
} //end-if
|
||||
|
||||
cp = n2;
|
||||
n2 += 2;
|
||||
|
||||
}
|
||||
else if (r2 == r && c2 == c - 2) {
|
||||
if (r1 != r) {
|
||||
map[i][n1].y = r;
|
||||
} //end-if
|
||||
|
||||
cp = n2;
|
||||
n2 += 2;
|
||||
|
||||
}
|
||||
else if (r2 == r && c2 == c + 2) {
|
||||
if (r1 != r) {
|
||||
map[i][n1].y = r;
|
||||
} //end-if
|
||||
|
||||
cp = n2;
|
||||
n2 += 2;
|
||||
|
||||
}
|
||||
else {
|
||||
cp++;
|
||||
n2++;
|
||||
} //end-else
|
||||
} //end-while
|
||||
} // end-for
|
||||
}
|
||||
|
||||
void EDColor::InitColorEDLib()
|
||||
{
|
||||
if (LUT_Initialized)
|
||||
return;
|
||||
|
||||
double inc = 1.0 / LUT_SIZE;
|
||||
for (int i = 0; i <= LUT_SIZE; i++) {
|
||||
double d = i * inc;
|
||||
|
||||
if (d >= 0.04045) LUT1[i] = pow(((d + 0.055) / 1.055), 2.4);
|
||||
else LUT1[i] = d / 12.92;
|
||||
} //end-for
|
||||
|
||||
inc = 1.0 / LUT_SIZE;
|
||||
for (int i = 0; i <= LUT_SIZE; i++) {
|
||||
double d = i * inc;
|
||||
|
||||
if (d > 0.008856) LUT2[i] = pow(d, 1.0 / 3.0);
|
||||
else LUT2[i] = (7.787*d) + (16.0 / 116.0);
|
||||
} //end-for
|
||||
|
||||
LUT_Initialized = true;
|
||||
}
|
||||
|
||||
bool EDColor::LUT_Initialized = false;
|
||||
double EDColor::LUT1[LUT_SIZE + 1] = {0};
|
||||
double EDColor::LUT2[LUT_SIZE + 1] = {0};
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue