/**
* @file mainwindow.cpp
* @brief 主窗口
*/
#include <QDebug>
#include <QFileDialog>
#include <QDateTime>
#include <QPainter>
#include <QString>
#include <QFile>
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "readthread.h"
#include "common.h"
/**
* @brief 19 寸 1080P 显示器点距为 0.21375mm/dot
* @todo 其他显示器未处理 TODO (在VC中只有TODO前面只有空格、斜杠或者*才计入列表, QtCreator只要单列就可以计入列表)
* @note 演示 IDE 与输出文档同时能适应TODO列表
*/
const int VIEW_DOT = 21375;
/// 构造函数
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_LastPosX = 0;
m_WaveTimer = NULL;
m_DemoThread = NULL;
setFocusPolicy(Qt::ClickFocus);
setAttribute(Qt::WA_DeleteOnClose, true);
ui->paintWave->setGeometry(QRect(10, 50, this->width()- 20, this->height()- 50- 40));
QPalette pal(ui->paintWave->palette());
//设置背景黑色
pal.setColor(QPalette::Background, Qt::black);
ui->paintWave->setAutoFillBackground(true);
ui->paintWave->setPalette(pal);
ui->cbxGain->setCurrentIndex(m_Gain);
ui->cbxSpeed->setCurrentIndex(m_Speed);
ClearEcgData();
ui->paintWave->installEventFilter(this);
}
/// 构释函数
MainWindow::~MainWindow()
{
if(m_WaveTimer)
{
m_WaveTimer->stop();
delete m_WaveTimer;
}
delete ui;
}
/**
* @brief 将 Ecg 数据放入缓冲区
* @param[in] Data 数据指针
* @param[in] Count 数据长度(单位:采样点;4通道,第4通道为起搏器信号)
*/
void MainWindow::PutEcgBuff(const short int *Data, const int Count)
{
int m, n;
const int STEP = sizeof(m_EcgData[0])/sizeof(m_EcgData[0][0]);
for(m=0; m<Count; m++)
{
for(n=0; n<STEP; n++)
{
m_EcgData[m_EcgPutPos][n] = Data[STEP* m+ n];
}
m_EcgPutPos++;
m_EcgPutPos %= MAX_ECG_BUFF_LEN;
}
}
/**
* @brief 获取 Ecg 数据来画图
* @param[out] Data 数据指针
* @param[in] Count 数据长度(单位:采样点;4通道,第4通道为起搏器信号)
* @attention 直接获取数据进行画图,没有使用双缓冲处理
* @note 目前画图的针对的是 19 寸 1080P 显示器
* @bug 切换增益时可能引起波形不连续
*/
int MainWindow::DrawEcgData()
{
int m, n, stepX, viewY, len;
const int STEP = sizeof(m_EcgData[0])/sizeof(m_EcgData[0][0]);
len = GetEcgCount();
//OUT_RUNLOG("%d", len);
switch(m_Speed) // 速度
{
case 0:
default:
stepX = 12;
break;
case 1:
stepX = 6;
break;
case 2:
stepX = 3;
break;
}
switch(m_Gain) // 增益
{
case 0:
viewY = 25;
break;
case 1:
viewY = 50;
break;
case 2:
default:
viewY = 100;
break;
case 3:
viewY = 200;
break;
case 4:
viewY = 400;
break;
}
len -= (len% 12);
if(len >= 12)
{
short int minEcg[MAX_DATA_CHANNEL], maxEcg[MAX_DATA_CHANNEL];
if(m_FirstDraw)
{
m_LastData[0] = m_EcgData[m_EcgGetPos][0];
m_LastData[1] = m_EcgData[m_EcgGetPos][1];
m_LastData[2] = m_EcgData[m_EcgGetPos][1]- m_EcgData[m_EcgGetPos][0];
m_LastData[3] = 0- (m_EcgData[m_EcgGetPos][0]+ m_EcgData[m_EcgGetPos][1])/ 2;
m_LastData[4] = m_EcgData[m_EcgGetPos][0]- m_EcgData[m_EcgGetPos][1]/ 2;
m_LastData[5] = m_EcgData[m_EcgGetPos][1]- m_EcgData[m_EcgGetPos][0]/ 2;
m_LastData[6] = m_EcgData[m_EcgGetPos][2];
}
for(m=0; m<len; m+=stepX)
{
for(n=0; n<MAX_DATA_CHANNEL; n++)
{
minEcg[n] = m_LastData[n];
maxEcg[n] = m_LastData[n];
}
for(n=0; n<stepX; n++)
{
int temp;
temp = m_EcgData[m_EcgGetPos][0]; // I
if(minEcg[0] > temp) minEcg[0] = temp;
if(maxEcg[0] < temp) maxEcg[0] = temp;
temp = m_EcgData[m_EcgGetPos][1]; // II
if(minEcg[1] > temp) minEcg[1] = temp;
if(maxEcg[1] < temp) maxEcg[1] = temp;
temp = m_EcgData[m_EcgGetPos][1]- m_EcgData[m_EcgGetPos][0]; // III=II-I
if(minEcg[2] > temp) minEcg[2] = temp;
if(maxEcg[2] < temp) maxEcg[2] = temp;
temp = 0- (m_EcgData[m_EcgGetPos][1]+ m_EcgData[m_EcgGetPos][0])/ 2; // aVR=0-(I+II)/2
if(minEcg[3] > temp) minEcg[3] = temp;
if(maxEcg[3] < temp) maxEcg[3] = temp;
temp = m_EcgData[m_EcgGetPos][0]- m_EcgData[m_EcgGetPos][1]/ 2; // aVL=I-II/2
if(minEcg[4] > temp) minEcg[4] = temp;
if(maxEcg[4] < temp) maxEcg[4] = temp;
temp = m_EcgData[m_EcgGetPos][1]- m_EcgData[m_EcgGetPos][0]/ 2; // aVF=II-I/2
if(minEcg[5] > temp) minEcg[5] = temp;
if(maxEcg[5] < temp) maxEcg[5] = temp;
temp = m_EcgData[m_EcgGetPos][2]; // V
if(minEcg[6] > temp) minEcg[6] = temp;
if(maxEcg[6] < temp) maxEcg[6] = temp;
if((stepX- 1) == n)
{
m_LastData[0] = m_EcgData[m_EcgGetPos][0]; // I
m_LastData[1] = m_EcgData[m_EcgGetPos][1]; // II
m_LastData[2] = m_EcgData[m_EcgGetPos][1]- m_EcgData[m_EcgGetPos][0]; // III=II-I
m_LastData[3] = 0- (m_EcgData[m_EcgGetPos][1]+ m_EcgData[m_EcgGetPos][0])/ 2; // aVR=0-(I+II)/2
m_LastData[4] = m_EcgData[m_EcgGetPos][0]- m_EcgData[m_EcgGetPos][1]/ 2; // aVL=I-II/2
m_LastData[5] = m_EcgData[m_EcgGetPos][1]- m_EcgData[m_EcgGetPos][0]/ 2; // aVF=II-I/2
m_LastData[6] = m_EcgData[m_EcgGetPos][2]; // V
}
m_EcgGetPos++;
m_EcgGetPos %= MAX_ECG_BUFF_LEN;
}
int stepY = ui->paintWave->height()/ 14- 2;
for(n=0; n<MAX_DATA_CHANNEL; n++)
{
minEcg[n] = minEcg[n]* viewY* 29/ VIEW_DOT/ 2;
maxEcg[n] = maxEcg[n]* viewY* 29/ VIEW_DOT/ 2;
#if 0 /// 是否限制波形超出通道范围
if(minEcg[n] < 0- stepY- 2)
minEcg[n] = 0- stepY- 2;
if(minEcg[n] > stepY- 2)
minEcg[n] = stepY- 2;
if(maxEcg[n] < 0- stepY- 2)
maxEcg[n] = 0- stepY- 2;
if(maxEcg[n] > stepY- 2)
maxEcg[n] = stepY- 2;
#endif
minEcg[n] = (n* 2+ 1)* (stepY+ 2)- minEcg[n];
maxEcg[n] = (n* 2+ 1)* (stepY+ 2)- maxEcg[n];
m_PaintLine[n].append(QLine(QPoint(m_LastPosX, minEcg[n]), QPoint(m_LastPosX, maxEcg[n])));
}
m_LastPosX++;
m_LastPosX %= ui->paintWave->width();
m_FirstDraw = false;
//m_DrawCount++;
}
if(m_PaintLine[0].count() > ui->paintWave->width()- CLEAR_WIDTH)
{
int eraseCount = m_PaintLine[0].count()- (ui->paintWave->width()- CLEAR_WIDTH);
for(n=0; n<MAX_DATA_CHANNEL; n++)
m_PaintLine[n].erase(m_PaintLine[n].begin(), m_PaintLine[n].begin()+ eraseCount);
}
// 检测放入数据数量,与已经获取的数据(非画点个数)进行比较
m_DrawCount += len;
int putCount = 0;
if(m_DemoThread) putCoun