diff --git a/TSI_Config.pro b/TSI_Config.pro index 96ea9ec..aeea952 100644 --- a/TSI_Config.pro +++ b/TSI_Config.pro @@ -10,10 +10,12 @@ CONFIG += c++11 SOURCES += \ MyTcpClient.cpp \ + TableHeaderView.cpp \ acceleration.cpp \ cardbase.cpp \ channel_1_2.cpp \ channel_3_4.cpp \ + channel_crc.cpp \ common.cpp \ config_mgr.cpp \ connect.cpp \ @@ -21,6 +23,7 @@ SOURCES += \ dc_output_channel.cpp \ dc_outputs.cpp \ ethconfig.cpp \ + headerView.cpp \ keyphase.cpp \ keyphase_data.cpp \ macconfig.cpp \ @@ -48,11 +51,13 @@ SOURCES += \ HEADERS += \ MyTcpClient.h \ + TableHeaderView.h \ acceleration.h \ acceleration_ds.h \ cardbase.h \ channel_1_2.h \ channel_3_4.h \ + channel_crc.h \ common.h \ config_mgr.h \ connect.h \ @@ -62,6 +67,7 @@ HEADERS += \ dc_outputs.h \ displacement_ds.h \ ethconfig.h \ + headerView.h \ keyphase.h \ keyphase_data.h \ macconfig.h \ @@ -92,6 +98,7 @@ FORMS += \ acceleration.ui \ channel_1_2.ui \ channel_3_4.ui \ + channel_crc.ui \ connect.ui \ copy_channel.ui \ dc_output_channel.ui \ diff --git a/TableHeaderView.cpp b/TableHeaderView.cpp new file mode 100644 index 0000000..dd14d4d --- /dev/null +++ b/TableHeaderView.cpp @@ -0,0 +1,206 @@ +#include "TableHeaderView.h" +#include +#include +#include +#include + +#ifdef _MSC_VER +#pragma execution_character_set("utf-8") +#endif + +#define CHECK_BOX_COLUMN 0 +TableHeaderView::TableHeaderView(Qt::Orientation orientation, QWidget *parent) + : QHeaderView(orientation, parent), + m_bPressed(false), + m_bChecked(false), + m_bTristate(false), + m_bNoChange(false), + m_bMoving(false) + +{ + setSectionsClickable(true); // 响应鼠标 +} + +TableHeaderView::~TableHeaderView() +{ + +} + +// 槽函数,用于更新复选框状态 +void TableHeaderView::onStateChanged(int state) +{ + if (state == Qt::PartiallyChecked) { + m_bTristate = true; + m_bNoChange = true; + } + else { + m_bNoChange = false; + } + + m_bChecked = (state != Qt::Unchecked); + update(); +} + +// 绘制复选框 +void TableHeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const +{ + painter->save(); + QHeaderView::paintSection(painter, rect, logicalIndex); + painter->restore(); + + if (logicalIndex == CHECK_BOX_COLUMN ) + { + QStyleOptionButton option; + option.initFrom(this); + + if (m_bChecked) + option.state |= QStyle::State_Sunken; + + if (m_bTristate && m_bNoChange) + option.state |= QStyle::State_NoChange; + else + option.state |= m_bChecked ? QStyle::State_On : QStyle::State_Off; + if (testAttribute(Qt::WA_Hover) && underMouse()) { + if (m_bMoving) + option.state |= QStyle::State_MouseOver; + else + option.state &= ~QStyle::State_MouseOver; + } + + QCheckBox checkBox; + option.iconSize = QSize(20, 20); + option.rect = rect; + style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &option, painter, &checkBox); + } +} + +// 鼠标按下表头 +void TableHeaderView::mousePressEvent(QMouseEvent *event) +{ + int nColumn = logicalIndexAt(event->pos()); + if ((event->buttons() & Qt::LeftButton) && (nColumn == CHECK_BOX_COLUMN)) + { + m_bPressed = true; + } + else + { + QHeaderView::mousePressEvent(event); + } +} + +// 鼠标从表头释放,发送信号,更新model数据 +void TableHeaderView::mouseReleaseEvent(QMouseEvent *event) +{ + + if (m_bPressed) + { + if (m_bTristate && m_bNoChange) + { + m_bChecked = true; + m_bNoChange = false; + } + else + { + m_bChecked = !m_bChecked; + } + + update(); + + Qt::CheckState state = m_bChecked ? Qt::Checked : Qt::Unchecked; + + emit stateChanged(state); + + updateSection(0); + } + else + { + QHeaderView::mouseReleaseEvent(event); + } + + m_bPressed = false; +} + +// 鼠标滑过、离开,更新复选框状态 +bool TableHeaderView::event(QEvent *event) +{ + updateSection(0); + if (event->type() == QEvent::Enter || event->type() == QEvent::Leave) + { + QMouseEvent *pEvent = static_cast(event); + int nColumn = logicalIndexAt(pEvent->x()); + if (nColumn == CHECK_BOX_COLUMN) + { + m_bMoving = (event->type() == QEvent::Enter); + + update(); + return true; + } + } + return QHeaderView::event(event); +} + + + + +CheckBoxDelegate::CheckBoxDelegate(QObject *parent) :QStyledItemDelegate(parent) +{ + +} + +CheckBoxDelegate::~CheckBoxDelegate() +{ + +} + +// 绘制复选框 +void CheckBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + QStyleOptionViewItem viewOption(option); + initStyleOption(&viewOption, index); + if (option.state.testFlag(QStyle::State_HasFocus)) + viewOption.state = viewOption.state ^ QStyle::State_HasFocus; + + QStyledItemDelegate::paint(painter, viewOption, index); + + if (index.column() == CHECK_BOX_COLUMN ) + { + bool data = index.model()->data(index, Qt::UserRole).toBool(); + + QStyleOptionButton checkBoxStyle; + checkBoxStyle.state = data ? QStyle::State_On : QStyle::State_Off; + checkBoxStyle.state |= QStyle::State_Enabled; + checkBoxStyle.iconSize = QSize(20, 20); + checkBoxStyle.rect = option.rect; + + QCheckBox checkBox; + checkBoxStyle.iconSize = QSize(20, 20); + checkBoxStyle.rect = option.rect; + QApplication::style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &checkBoxStyle, painter, &checkBox); + + checkBox.setEnabled(false); + } +} + +// 响应鼠标事件,更新数据 +bool CheckBoxDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) +{ + QRect decorationRect = option.rect; + + QMouseEvent *mouseEvent = static_cast(event); + if (event->type() == QEvent::MouseButtonPress && decorationRect.contains(mouseEvent->pos())) + { + if (index.column() == CHECK_BOX_COLUMN ) + { + + bool data = model->data(index, Qt::UserRole).toBool(); + model->setData(index, !data, Qt::UserRole); + + } + } + + return QStyledItemDelegate::editorEvent(event, model, option, index); +} + + + + diff --git a/TableHeaderView.h b/TableHeaderView.h new file mode 100644 index 0000000..8a4de02 --- /dev/null +++ b/TableHeaderView.h @@ -0,0 +1,57 @@ +#ifndef CCHECKBOXMODEL_H +#define CCHECKBOXMODEL_H + +#include +#include +#include +#include +#include + + +class TableHeaderView :public QHeaderView +{ + Q_OBJECT +public: + TableHeaderView(Qt::Orientation orientation, QWidget *parent); + ~TableHeaderView(); + +protected: + void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const; + bool event(QEvent *e) Q_DECL_OVERRIDE; + void mousePressEvent(QMouseEvent *e) Q_DECL_OVERRIDE; + void mouseReleaseEvent(QMouseEvent *e) Q_DECL_OVERRIDE; + + public slots: + void onStateChanged(int state); + +signals: + void stateChanged(int state); + +private: + bool m_bPressed; + bool m_bChecked; + bool m_bTristate; + bool m_bNoChange; + bool m_bMoving; +}; + + +class CheckBoxDelegate :public QStyledItemDelegate +{ + Q_OBJECT +public: + CheckBoxDelegate(QObject *parent); + ~CheckBoxDelegate(); + // painting + void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; + +protected: + bool editorEvent(QEvent *event, QAbstractItemModel *model, + const QStyleOptionViewItem &option, const QModelIndex &index); +}; + + + +#endif // TABLE_MODEL_H + + diff --git a/channel_crc.cpp b/channel_crc.cpp new file mode 100644 index 0000000..6cc72a7 --- /dev/null +++ b/channel_crc.cpp @@ -0,0 +1,73 @@ +#include "channel_crc.h" +#include "ui_channel_crc.h" +#include "config_mgr.h" +#include "data_config.h" + +ChannelCRC::ChannelCRC(QWidget *parent) : + QWidget(parent), + ui(new Ui::ChannelCRC) +{ + ui->setupUi(this); + + initable(); + m_tcpClient = MyTcpClient::instance(); + connect(m_tcpClient, SIGNAL(dataReceived(const QByteArray &)), this, SLOT(readData(const QByteArray &))); + +} + +ChannelCRC::~ChannelCRC() +{ + delete ui; +} +void ChannelCRC::initable() +{ + headerStr = QObject::tr("板卡,通道1,通道2,通道3,通道4"); + myHeader = new TableHeaderView(Qt::Horizontal, ui->tableView); + model = new QStandardItemModel(ui->tableView); + ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers); + ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows); + QStringList headerList = headerStr.split(","); + model->setHorizontalHeaderLabels(headerList); + model->setColumnCount(headerList.size()); + ui->tableView->setModel(model); +} + +void ChannelCRC::on_pushButton_get_clicked() +{ + model->removeRows(0, model->rowCount()); + int rows = 0; + for (int slot = 1; slot <= SLOT_NUM; slot ++ ) { + std::shared_ptr base_ptr = ConfigMgr::Instance()->GetSlotPtr(slot); + if(base_ptr == nullptr) + continue; + if(base_ptr->card_type_ == kCardVibSingle || + base_ptr->card_type_ == kCardSpeedSingle || + base_ptr->card_type_ == kCardKeyphaseSingle){ + for (int ch = 1 ; ch <= 4 ; ch ++ ) { + model->setRowCount(rows + 1); + model->setData(model->index(rows,0,QModelIndex()),slot); + rows_slot[slot] = rows; + + GetChannelCRCCountReq get_ch_crc_req = { {0xAA, 0x55, 0xAA}, kGetChannelCRCValue, 1,(uint8_t)slot,(uint8_t)ch }; + int length = sizeof(GetChannelCRCCountReq); + qint64 bytesWritten = m_tcpClient->sendData((char*)&get_ch_crc_req, length); + m_tcpClient->waitForRead(); + qDebug() << "bytesWritten: " << bytesWritten; + } + rows ++ ; + } + } + +} +void ChannelCRC::readData(const QByteArray &data) { + qDebug() << "Received from server111:" << data; + + uint8_t cmd = data[3]; + if (cmd == kGetChannelCRCValue) { + GetChannelCRCCountRsp get_ch_crc_rsp; + memcpy(&get_ch_crc_rsp, data.data(), sizeof(GetChannelCRCCountRsp)); + qDebug() << "get_ch_crc_rsp code" << get_ch_crc_rsp.code << get_ch_crc_rsp.card_id << get_ch_crc_rsp.channel_id << get_ch_crc_rsp.count << rows_slot[(int)get_ch_crc_rsp.card_id] ; + model->setData(model->index(rows_slot[(int)get_ch_crc_rsp.card_id],((int)get_ch_crc_rsp.channel_id),QModelIndex()),get_ch_crc_rsp.count); + + } +} diff --git a/channel_crc.h b/channel_crc.h new file mode 100644 index 0000000..93098ca --- /dev/null +++ b/channel_crc.h @@ -0,0 +1,36 @@ +#ifndef CHANNEL_CRC_H +#define CHANNEL_CRC_H + +#include +#include //数据模型类 +#include +#include "headerView.h" +#include "TableHeaderView.h" +#include "MyTcpClient.h" + +namespace Ui { +class ChannelCRC; +} + +class ChannelCRC : public QWidget +{ + Q_OBJECT + +public: + explicit ChannelCRC(QWidget *parent = nullptr); + ~ChannelCRC(); + +private slots: + void on_pushButton_get_clicked(); + void readData(const QByteArray&); +private: + Ui::ChannelCRC *ui; + TableHeaderView *myHeader; + QStandardItemModel *model; + QString headerStr ; + MyTcpClient* m_tcpClient; + QMap rows_slot;// + void initable(); +}; + +#endif // CHANNEL_CRC_H diff --git a/channel_crc.ui b/channel_crc.ui new file mode 100644 index 0000000..d2cf246 --- /dev/null +++ b/channel_crc.ui @@ -0,0 +1,59 @@ + + + ChannelCRC + + + + 0 + 0 + 766 + 519 + + + + 获取通道CRC + + + + + + + 0 + 100 + + + + + 16777215 + 100 + + + + + + 650 + 50 + 81 + 31 + + + + 获取 + + + + + + + + + + + + + + + + + + diff --git a/data_config.h b/data_config.h index 1365f4e..1ad2043 100644 --- a/data_config.h +++ b/data_config.h @@ -239,6 +239,7 @@ enum CMTCommand { kGetVoltageRangeValue = 33, // 获取子板动态电压范围 kGetVibAuxProcessVersion = 34, kGetProcessID = 38, // 获取进程号 + kGetChannelCRCValue = 39, // 获取振动与转速板通道的CRC计数 kGetProductInfo = 101, // 获取产品信息 kSetProductInfo = 102 // 填写产品信息 }; @@ -976,6 +977,24 @@ typedef struct { uint8_t code; // 0: 成功, 1:失败 } SetProductInfoRsp; +typedef struct { + uint8_t head[3]; // 固定值:0xAA55AA + uint8_t cmd; // kGetChannelCRCValue + uint8_t version; // 版本号,默认为1 + uint8_t card_id; + uint8_t channel_id; +} GetChannelCRCCountReq; + +typedef struct { + uint8_t head[3]; // 固定值:0xAA55AA + uint8_t cmd; // kGetChannelCRCValue + uint8_t version; // 版本号,默认为1 + uint8_t code; + uint8_t card_id; + uint8_t channel_id; + uint32_t count; // crc计数值 +} GetChannelCRCCountRsp; + struct BaseHeader { uint8_t head[3]; // 固定 0xAA 0x55 0xAA uint8_t cmd; diff --git a/headerView.cpp b/headerView.cpp new file mode 100644 index 0000000..e209860 --- /dev/null +++ b/headerView.cpp @@ -0,0 +1,75 @@ +#include "headerView.h" +#include +#include +#include + +CHeaderView::CHeaderView(Qt::Orientation orientation, QWidget *parent) + : QHeaderView(orientation, parent) +{ + //设置Section可点击,若不设置则不能发出sectionClicked信号 + this->setSectionsClickable(true); + //当发出sectionClicked就进入匿名函数 + connect(this, &CHeaderView::sectionClicked, [=](int logicalIndex) + { + //判断map容器是否包含当前点击列,包含则更新并发出columnSectionClicked + if(m_columpnCheckedMap.contains(logicalIndex)) + { + //更新当前值 + m_columpnCheckedMap[logicalIndex] = !m_columpnCheckedMap[logicalIndex]; + //发出信号 + emit columnSectionClicked(logicalIndex, m_columpnCheckedMap[logicalIndex]); + } + }); +} + +void CHeaderView::setColumnCheckable(int column, bool checkable) +{ + //当可选值为true + if(checkable) + { + //将指定列添加到map容器中 + m_columpnCheckedMap[column] = false; + } + else if(m_columpnCheckedMap.contains(column)) //当可选值为false,且map容器包含指定列 + { + //移除指定列 + m_columpnCheckedMap.remove(column); + } +} + +bool CHeaderView::getColumnCheckable(int column) +{ + return m_columpnCheckedMap[column]; +} + +void CHeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const +{ + qDebug()<<"paintSection" << endl; + painter->save(); //保存当前画笔状态 + QHeaderView::paintSection(painter, rect, logicalIndex); + painter->restore(); //恢复保存的画笔状态 + + //当map容器包含当前列才绘制复选框 + if(m_columpnCheckedMap.contains(logicalIndex)) + { + //创建样式对象并设置区域 + QStyleOptionButton styleOption; + styleOption.rect = rect.adjusted(10, 0, 0, 0); + styleOption.state = QStyle::State_Enabled; + + //根据map中的值设置状态 + if(m_columpnCheckedMap[logicalIndex]) + { + styleOption.state |= QStyle::State_On; + } + else + { + styleOption.state |= QStyle::State_Off; + } + + //调用this的style对象绘制复选框 + this->style()->drawControl(QStyle::CE_CheckBox, &styleOption, painter); + } +} + + diff --git a/headerView.h b/headerView.h new file mode 100644 index 0000000..093c4c4 --- /dev/null +++ b/headerView.h @@ -0,0 +1,47 @@ +#ifndef HEADERVIEW_H +#define HEADERVIEW_H + +#include +#include +#include + +class CHeaderView : public QHeaderView +{ + Q_OBJECT +public: + /** + * @brief CHeaderView 鏋勯€犲嚱鏁 * @param orientation 鏂瑰悜 + * @param parent 鐖剁被瀵硅薄 + */ + CHeaderView(Qt::Orientation orientation, QWidget *parent = nullptr); + + /** + * @brief setColumnCheckable 璁剧疆鎸囧畾鍒楁槸鍚﹀彲閫 * @param column 鎸囧畾鍒 * @param checkable 鍙€夊€ */ + void setColumnCheckable(int column, bool checkable); + + bool getColumnCheckable(int column); + +signals: + /** + * @brief columnSectionClicked Section鐐瑰嚮淇″彿 + * @param logicalIndex 鐐瑰嚮浣嶇疆 + * @param checked 閫変腑鍊 */ + void columnSectionClicked(int logicalIndex, bool checked); + + // QHeaderView interface +protected: + /** + * @brief paintSection 缁樺埗澶嶉€夋 + * @param painter 缁樺埗瀵硅薄 + * @param rect 缁樺埗鍖哄煙 + * @param logicalIndex 褰撳墠绱㈠紩浣嶇疆 + */ + void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const; + +private: + QMap m_columpnCheckedMap; //鍖呭惈澶嶉€夋鍒楃殑map瀹瑰櫒 + +}; + +#endif // HEADERVIEW_H + diff --git a/mainwindow.cpp b/mainwindow.cpp index 0651a8b..cbb97dd 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -32,6 +32,7 @@ #include #include #include +#include "channel_crc.h" QString g_strServerIp; QString g_version; @@ -113,6 +114,7 @@ MainWindow::MainWindow(QWidget *parent) QObject::connect(ui->action_get_deviceID, &QAction::triggered, this, &MainWindow::onGetDeviceID); QObject::connect(ui->action_close, &QAction::triggered, this, &MainWindow::onCloseConfig); QObject::connect(ui->action_user_manual, &QAction::triggered, this, &MainWindow::onOpenUserManual); + QObject::connect(ui->action_get_channel_crc, &QAction::triggered, this, &MainWindow::onGetChannelCRC); QSettings settingsread(QCoreApplication::applicationDirPath() + "\\config\\config.ini", QSettings::IniFormat); g_strServerIp = settingsread.value("Server/IP").toString(); @@ -122,7 +124,7 @@ MainWindow::MainWindow(QWidget *parent) //qInstallMessageHandler(messageHandler); #endif QDate buildDate = QLocale( QLocale::English ).toDate( QString(__DATE__).replace(" ", " 0"), "MMM dd yyyy"); - QString Version = "V1.0_" + buildDate.toString("yyyyMMdd") + "_8102"; + QString Version = "V1.0_" + buildDate.toString("yyyyMMdd") + "_129d"; ui->label_version->setText(Version); } @@ -1361,6 +1363,16 @@ void MainWindow::UploadConfigFile(uint8_t sub_cmd){ free(send_buf); } } +void MainWindow::onGetChannelCRC(){ + if(tsi_config_file == ""){ + QMessageBox::warning(this, QStringLiteral("警告"), "请先打开配置!"); + return; + } + ChannelCRC *channel_crc = new ChannelCRC(); + channel_crc->setWindowModality(Qt::ApplicationModal); + channel_crc->show(); +} + void MainWindow::on_pushButton_upload_clicked(){ UploadConfigFile(0x0); } diff --git a/mainwindow.h b/mainwindow.h index ae965d0..53583d6 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -87,6 +87,7 @@ private slots: void onGetDeviceID(); void onCloseConfig(); void onOpenUserManual(); + void onGetChannelCRC(); void onMenuActionTriggered(); diff --git a/mainwindow.ui b/mainwindow.ui index 62049a6..c91f441 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -1117,6 +1117,7 @@ + @@ -1198,6 +1199,11 @@ 使用手册 + + + 获取通道CRC + +