High quality print test for Mac. Oximetry fixes, plus tab time editor. Can now re-open oximetry sessions from daily view. AHI/Hr Overview graph

This commit is contained in:
Mark Watkins 2011-12-07 00:39:14 +10:00
parent 4e182582a7
commit a9c1b82c56
23 changed files with 510 additions and 296 deletions

View File

@ -90,7 +90,7 @@ gFlagsLine::gFlagsLine(ChannelID code,QColor flag_color,QString label,bool alway
//addGLBuf(lines=new GLBuffer(flag_color,1024,GL_LINES));
quads->setAntiAlias(true);
//lines->setAntiAlias(true);
GetTextExtent(m_label,m_lx,m_ly);
//GetTextExtent(m_label,m_lx,m_ly);
//m_static.setText(m_label);;
}
gFlagsLine::~gFlagsLine()
@ -119,6 +119,7 @@ void gFlagsLine::paint(gGraph & w,int left, int top, int width, int height)
double xmult=width/xx;
GetTextExtent(m_label,m_lx,m_ly);
// Draw text label
w.renderText(m_label,left-m_lx-10,top+(height/2)+(m_ly/2));

View File

@ -961,6 +961,9 @@ bool gGraph::isEmpty()
}
return empty;
}
float gGraph::printScaleX() { return m_graphview->printScaleX(); }
float gGraph::printScaleY() { return m_graphview->printScaleY(); }
void gGraph::drawGLBuf()
{
@ -1042,28 +1045,28 @@ void gGraph::paint(int originX, int originY, int width, int height)
*/
//glColor4f(0,0,0,1);
renderText(title(),20,originY+height/2,90,Qt::black,mediumfont);
renderText(title(),20*m_graphview->printScaleX(),originY+height/2,90,Qt::black,mediumfont);
left=0,right=0,top=0,bottom=0;
int tmp;
originX+=m_marginleft;
originY+=m_margintop;
width-=m_marginleft+m_marginright;
height-=m_margintop+m_marginbottom;
originX+=marginLeft();
originY+=marginTop();
width-=marginLeft()+marginRight();
height-=marginTop()+marginBottom();
//int lsize=m_layers.size();
for (int i=0;i<m_layers.size();i++) {
Layer *ll=m_layers[i];
tmp=ll->Height();
tmp=ll->Height()*m_graphview->printScaleY();
if (ll->position()==LayerTop) top+=tmp;
if (ll->position()==LayerBottom) bottom+=tmp;
}
for (int i=0;i<m_layers.size();i++) {
Layer *ll=m_layers[i];
tmp=ll->Width();
tmp=ll->Width()*m_graphview->printScaleX();
if (ll->position()==LayerLeft) {
ll->paint(*this,originX+left,originY+top,tmp,height-top-bottom);
left+=tmp;
@ -1077,7 +1080,7 @@ void gGraph::paint(int originX, int originY, int width, int height)
bottom=0; top=0;
for (int i=0;i<m_layers.size();i++) {
Layer *ll=m_layers[i];
tmp=ll->Height();
tmp=ll->Height()*m_graphview->printScaleY();
if (ll->position()==LayerTop) {
ll->paint(*this,originX+left,originY+top,width-left-right,tmp);
top+=tmp;
@ -1597,6 +1600,10 @@ GLShortBuffer * gGraph::quads()
{
return m_graphview->quads;
}
short gGraph::marginLeft() { return m_marginleft*m_graphview->printScaleX(); }
short gGraph::marginRight() { return m_marginright*m_graphview->printScaleX(); }
short gGraph::marginTop() { return m_margintop*m_graphview->printScaleY(); }
short gGraph::marginBottom() { return m_marginbottom*m_graphview->printScaleY(); }
QPixmap gGraph::renderPixmap(int w, int h)
{
@ -1608,16 +1615,19 @@ QPixmap gGraph::renderPixmap(int w, int h)
QFont fb=*mediumfont;
QFont fc=*bigfont;
//fa.setPointSizeF(fa.pointSizeF()*4.0);
//fb.setPointSizeF(fb.pointSizeF()*4.0);
//fc.setPointSizeF(fc.pointSizeF()*4.0);
gGraphView *sg=mainwin->snapshotGraph();
if (!sg) return QPixmap();
float scale=sg->printScaleX();
fa.setPointSize(fa.pointSize()*scale);
fb.setPointSize(fb.pointSize()*scale);
fc.setPointSize(fc.pointSize()*scale);
defaultfont=&fa;
mediumfont=&fb;
bigfont=&fc;
gGraphView *sg=mainwin->snapshotGraph();
if (!sg) return QPixmap();
sg->hideSplitter();
gGraphView *tgv=m_graphview;
m_graphview=sg;
@ -1625,12 +1635,12 @@ QPixmap gGraph::renderPixmap(int w, int h)
//qint64 mx=min_x, Mx=max_x;
float tmp=m_height;
m_height=PROFILE["GraphHeight"].toInt();
m_height=PROFILE["GraphHeight"].toInt()*sg->printScaleY();
sg->trashGraphs();
sg->addGraph(this);
//sg->ResetBounds();
//sg->SetXBounds(mx,Mx);
//sg->updateScrollBar();
sg->updateScale();
QPixmap pm=sg->renderPixmap(w,h,false);
@ -1697,7 +1707,13 @@ void gGraph::roundY(EventDataType &miny, EventDataType &maxy)
return;
}
if (maxy>=5) {
if (maxy>=300) {
m=ceil(maxy/10.0);
t=m*10;
if (!ymax_good) maxy=t;
m=floor(miny/10.0);
if (!ymin_good) miny=m*10;
} else if (maxy>=5) {
m=ceil(maxy/5.0);
t=m*5;
if (!ymax_good) maxy=t;
@ -1753,7 +1769,7 @@ gGraphView::gGraphView(QWidget *parent, gGraphView * shared) :
m_showsplitter=true;
timer=new QTimer(this);
connect(timer,SIGNAL(timeout()),SLOT(refreshTimeout()));
print_scaleY=print_scaleX=1.0;
}
gGraphView::~gGraphView()
{
@ -2123,7 +2139,6 @@ void gGraphView::paintGL()
if ((py + h + graphSpacer) >= 0) {
w=width();
queGraph(m_graphs[i],px,py,width()-titleWidth,h);
if (m_showsplitter) {
@ -2296,7 +2311,9 @@ void gGraphView::mouseMoveEvent(QMouseEvent * event)
break; // we are done.. can't draw anymore
if (m_button_down || ((py + h + graphSpacer) >= 0)) {
if (m_button_down || ((y >= py) && (y < py + h))) {
if ((y >= py + h) && (y <= py + h + graphSpacer + 1)) {
this->setCursor(Qt::SplitVCursor);
} else if (m_button_down || ((y >= py) && (y < py + h))) {
if (m_button_down || (x >= titleWidth+10)) { //(gYAxis::Margin-5)
this->setCursor(Qt::ArrowCursor);
m_horiz_travel+=qAbs(x-m_lastxpos)+qAbs(y-m_lastypos);
@ -2344,8 +2361,6 @@ void gGraphView::mouseMoveEvent(QMouseEvent * event)
this->setCursor(Qt::OpenHandCursor);
}
} else if ((y >= py + h) && (y <= py + h + graphSpacer + 1)) {
this->setCursor(Qt::SplitVCursor);
}
}

View File

@ -158,6 +158,8 @@ public:
void setMovable(bool b) { m_movable=b; }
bool movable() { return m_movable; }
virtual void paint(gGraph & gv,int left,int top,int width, int height)=0;
void setLayout(LayerPosition position, short width, short height, short order);
@ -286,6 +288,8 @@ public:
int maxHeight() { return m_max_height; }
void setMaxHeight(int height) { m_max_height=height; }
float printScaleX();
float printScaleY();
bool isEmpty();
void AddLayer(Layer * l,LayerPosition position=LayerCenter, short pixelsX=0, short pixelsY=0, short order=0, bool movable=false, short x=0, short y=0);
@ -346,15 +350,14 @@ public:
m_marginleft=left; m_marginright=right;
m_margintop=top; m_marginbottom=bottom;
}
inline short marginLeft() { return m_marginleft; }
inline short marginRight() { return m_marginright; }
inline short marginTop() { return m_margintop; }
inline short marginBottom() { return m_marginbottom; }
inline short marginLeft();
inline short marginRight();
inline short marginTop();
inline short marginBottom();
GLShortBuffer * lines();
GLShortBuffer * backlines();
GLShortBuffer * quads();
short m_marginleft, m_marginright, m_margintop, m_marginbottom;
short left,right,top,bottom; // dirty magin hacks..
QRect m_lastbounds;
@ -362,6 +365,7 @@ public:
QVector<Layer *> & layers() { return m_layers; }
protected:
short m_marginleft, m_marginright, m_margintop, m_marginbottom;
//void invalidate();
virtual void wheelEvent(QWheelEvent * event);
@ -420,7 +424,10 @@ public:
gGraph *findGraph(QString name);
//bool hasGraphs() { return m_graphs.size()>0; }
inline float printScaleX() { return print_scaleX; }
inline float printScaleY() { return print_scaleY; }
inline void setPrintScaleX(float x) { print_scaleX=x; }
inline void setPrintScaleY(float y) { print_scaleY=y; }
void deselect();
QPoint pointClicked() { return m_point_clicked; }
@ -517,6 +524,7 @@ protected:
bool m_showsplitter;
qint64 m_minx,m_maxx;
float print_scaleX,print_scaleY;
signals:

View File

@ -55,6 +55,9 @@ void gLineOverlayBar::paint(gGraph & w, int left, int topp, int width, int heigh
m_count=0;
m_flag_color=schema::channel[m_code].defaultColor();
if (m_flt==FT_Span) {
m_flag_color.setAlpha(128);
}
for (QVector<Session *>::iterator s=m_day->begin();s!=m_day->end(); s++) {
cei=(*s)->eventlist.find(m_code);
if (cei==(*s)->eventlist.end()) continue;
@ -84,7 +87,7 @@ void gLineOverlayBar::paint(gGraph & w, int left, int topp, int width, int heigh
if (x2<left) x2=left;
if (x1>width+left) x1=width+left;
//double w1=x2-x1;
quads->add(x1,start_py,x2,start_py,x2,start_py+height,x1,start_py+height);
quads->add(x1,start_py,x2,start_py,x2,start_py+height,x1,start_py+height,m_flag_color);
if (quads->full()) { verts_exceeded=true; break; }
} else if (m_flt==FT_Dot) {
if ((PROFILE["AlwaysShowOverlayBars"].toInt()==0) || (xx<3600000)) {

View File

@ -262,8 +262,8 @@ void SummaryChart::paint(gGraph & w,int left, int top, int width, int height)
graph=&w;
float px=left;
l_left=w.m_marginleft+gYAxis::Margin;
l_top=w.m_margintop;
l_left=w.marginLeft()+gYAxis::Margin;
l_top=w.marginTop();
l_width=width;
l_height=height;
float py;

View File

@ -155,16 +155,19 @@ void gXAxis::paint(gGraph & w,int left,int top, int width, int height)
py=left+float(aligned_start-minx)*xmult;
int texttop=top+18*w.printScaleX();
int mintop=top+4*w.printScaleX();
int majtop=top+6*w.printScaleX();
for (int i=0;i<num_minor_ticks;i++) {
py-=step_pixels;
if (py<start_px) continue;
lines->add(py,top,py,top+4,linecol);
lines->add(py,top,py,mintop,linecol);
}
for (qint64 i=aligned_start;i<maxx;i+=step) {
px=(i-minx)*xmult;
px+=left;
lines->add(px,top,px,top+6,linecol);
lines->add(px,top,px,majtop,linecol);
qint64 j=i;
if (!m_utcfix) j+=tz_offset;
int ms=j % 1000;
@ -196,12 +199,12 @@ void gXAxis::paint(gGraph & w,int left,int top, int width, int height)
if (m_utcfix)
tx+=step_pixels/2.0;
if ((tx+x)<(left+width))
w.renderText(tmpstr,tx,top+18);
w.renderText(tmpstr,tx,texttop);
py=px;
for (int j=1;j<num_minor_ticks;j++) {
py+=step_pixels;
if (py>=left+width) break;
lines->add(py,top,py,top+4,linecol);
lines->add(py,top,py,mintop,linecol);
}
if (lines->full()) {

View File

@ -47,7 +47,7 @@ void gXGrid::paint(gGraph & w,int left,int top, int width, int height)
static QString fd="0";
GetTextExtent(fd,x,y);
double max_yticks=round(height / (y+7.0)); // plus spacing between lines
double max_yticks=round(height / (y+10.0)); // plus spacing between lines
//double yt=1/max_yticks;
double mxy=MAX(fabs(maxy),fabs(miny));
@ -151,7 +151,7 @@ void gYAxis::paint(gGraph & w,int left,int top, int width, int height)
static QString fd="0";
GetTextExtent(fd,x,y);
double max_yticks=round(height / (y+7.0)); // plus spacing between lines
double max_yticks=round(height / (y+10.0)); // plus spacing between lines
double mxy=MAX(fabs(maxy),fabs(miny));
double mny=miny;

View File

@ -61,7 +61,7 @@ public:
QVector<Session *>::iterator begin() { return sessions.begin(); }
QVector<Session *>::iterator end() { return sessions.end(); }
int find(Session * sess) { return sessions.indexOf(sess); }
int size() { return sessions.size(); }
Machine *machine;

View File

@ -62,6 +62,7 @@ protected:
void CalcRespiratoryRate(Session *);
void filterFlow(EventList *in, EventList *out);
unsigned char * m_buffer;
QHash<SessionID, Session *> extra_session;
};
#endif // PRS1LOADER_H

View File

@ -321,25 +321,6 @@ bool Machine::Save()
dir.mkdir(path);
}
/*QString fn=path+"/channels.dat";
QFile cf(fn);
if (!cf.open(QIODevice::WriteOnly)) {
qDebug() << "Couldn't write.. Permissions? Hard disk crashing?";
return false;
}
QDataStream out(&cf);
out.setVersion(QDataStream::Qt_4_6);
out.setByteOrder(QDataStream::LittleEndian);
out << (quint32)magic; // Magic Number
out << (quint32)channel_version;// File Version
out << (quint32)m_id;// Machine ID
out << m_channels;
cf.close(); */
// Calculate size for progress bar
//size=sessionlist.size();
QHash<SessionID,Session *>::iterator s;

View File

@ -292,6 +292,35 @@ Machine * Profile::GetMachine(MachineType t)
}
void Profile::RemoveSession(Session * sess)
{
QMap<QDate,QVector<Day *> >::iterator di;
for (di=daylist.begin();di!=daylist.end();di++) {
for (int d=0;d<di.value().size();d++) {
Day *day=di.value()[d];
int i=day->getSessions().indexOf(sess);
if (i>=0) {
for (;i<day->getSessions().size()-1;i++) {
day->getSessions()[i]=day->getSessions()[i+1];
}
day->getSessions().pop_back();
qint64 first=0,last=0;
for (int i=0;i<day->getSessions().size();i++) {
Session & sess=*day->getSessions()[i];
if (!first || first>sess.first()) first=sess.first();
if (!last || last<sess.last()) last=sess.last();
}
day->setFirst(first);
day->setLast(last);
return;
}
}
}
}
//Profile *profile=NULL;
QString SHA1(QString pass)
{
@ -406,5 +435,6 @@ void Scan()
}
}; // namespace Profiles

View File

@ -38,6 +38,7 @@ public:
void LoadMachineData();
void DataFormatError(Machine *m);
int Import(QString path);
void RemoveSession(Session * sess);
void AddDay(QDate date,Day *day,MachineType mt);
Day * GetDay(QDate date,MachineType type=MT_UNKNOWN);

View File

@ -921,3 +921,31 @@ EventList * Session::AddEventList(QString chan, EventListType et,EventDataType g
//s_machine->registerChannel(chan);
return el;
}
void Session::offsetSession(qint64 offset)
{
//qDebug() << "Session starts" << QDateTime::fromTime_t(s_first/1000).toString("yyyy-MM-dd HH:mm:ss");
s_first+=offset;
s_last+=offset;
QHash<ChannelID,quint64>::iterator it;
for (it=m_firstchan.begin();it!=m_firstchan.end();it++) {
if (it.value()>0)
it.value()+=offset;
}
for (it=m_lastchan.begin();it!=m_lastchan.end();it++) {
if (it.value()>0)
it.value()+=offset;
}
QHash<ChannelID,QVector<EventList *> >::iterator i;
for (i=eventlist.begin();i!=eventlist.end();i++) {
for (int j=0;j<i.value().size();j++) {
EventList *e=i.value()[j];
e->setFirst(e->first()+offset);
e->setLast(e->last()+offset);
}
}
qDebug() << "Session now starts" << QDateTime::fromTime_t(s_first/1000).toString("yyyy-MM-dd HH:mm:ss");
}

View File

@ -51,6 +51,9 @@ public:
void SetSessionID(SessionID s) {
s_session=s;
}
void offsetSession(qint64 d);
void really_set_first(qint64 d) { s_first=d; }
void really_set_last(qint64 d) { s_last=d; }
void set_first(qint64 d) {
if (!s_first) s_first=d;
else if (d<s_first) s_first=d;

View File

@ -328,6 +328,12 @@ void Daily::Link_clicked(const QUrl &url)
day=PROFILE.GetDay(previous_date,MT_CPAP);
} else if (code=="oxi") {
day=PROFILE.GetDay(previous_date,MT_OXIMETER);
Session *sess=day->machine->sessionlist[sid];
if (mainwin->getOximetry()) {
mainwin->getOximetry()->openSession(sess);
mainwin->selectOximetryTab();
}
return;
} else if (code=="event") {
QList<QTreeWidgetItem *> list=ui->treeWidget->findItems(schema::channel[data].description(),Qt::MatchContains);
if (list.size()>0) {
@ -355,7 +361,11 @@ void Daily::Link_clicked(const QUrl &url)
void Daily::ReloadGraphs()
{
QDate d=PROFILE.LastDay();
QDate d;
if (previous_date.isValid()) {
d=previous_date;
Unload(d);
} else d=PROFILE.LastDay();
if (!d.isValid()) {
d=ui->calendar->selectedDate();
}
@ -818,11 +828,12 @@ void Daily::Load(QDate date)
//}
html+="</table><hr height=2><table cellpadding=0 cellspacing=0 border=0 width=100%>";
html+="<tr><td align=center>SessionID</td><td align=center>Date</td><td align=center>Start</td><td align=center>End</td></tr>";
QDateTime fd,ld;
bool corrupted_waveform=false;
QString tooltip;
if (cpap) {
html+="<tr><td align=left><b>SessionID</b></td><td align=center><b>Date</b></td><td align=center><b>Start</b></td><td align=center><b>End</b></td></tr>";
html+="<tr><td align=left colspan=4><i>CPAP Sessions</i></td></tr>";
for (QVector<Session *>::iterator s=cpap->begin();s!=cpap->end();s++) {
fd=QDateTime::fromTime_t((*s)->first()/1000L);
ld=QDateTime::fromTime_t((*s)->last()/1000L);
@ -833,11 +844,14 @@ void Daily::Load(QDate date)
QHash<ChannelID,QVariant>::iterator i=(*s)->settings.find("BrokenWaveform");
tooltip=cpap->machine->GetClass()+" CPAP "+QString().sprintf("%2ih&nbsp;%2im&nbsp;%2is",h,m,s1);
if ((i!=(*s)->settings.end()) && i.value().toBool()) corrupted_waveform=true;
tmp.sprintf(("<tr><td align=center><a href='cpap=%i' title='"+tooltip+"'>%08i</a></td><td align=center>"+fd.date().toString(Qt::SystemLocaleShortDate)+"</td><td align=center>"+fd.toString("HH:mm ")+"</td><td align=center>"+ld.toString("HH:mm")+"</td></tr>").toLatin1(),(*s)->session(),(*s)->session());
tmp.sprintf(("<tr><td align=left><a href='cpap=%i' title='"+tooltip+"'>%08i</a></td><td align=center>"+fd.date().toString(Qt::SystemLocaleShortDate)+"</td><td align=center>"+fd.toString("HH:mm ")+"</td><td align=center>"+ld.toString("HH:mm")+"</td></tr>").toLatin1(),(*s)->session(),(*s)->session());
html+=tmp;
}
//if (oxi) html+="<tr><td colspan=4><hr></td></tr>";
}
if (oxi) {
html+="<tr><td align=left colspan=4><i>Oximetry Sessions</i></td></tr>";
//html+="<tr><td align=left>SessionID</td><td align=center>Date</td><td align=center>Start</td><td align=center>End</td></tr>";
for (QVector<Session *>::iterator s=oxi->begin();s!=oxi->end();s++) {
fd=QDateTime::fromTime_t((*s)->first()/1000L);
ld=QDateTime::fromTime_t((*s)->last()/1000L);
@ -848,7 +862,7 @@ void Daily::Load(QDate date)
QHash<ChannelID,QVariant>::iterator i=(*s)->settings.find("BrokenWaveform");
tooltip=oxi->machine->GetClass()+" Oximeter "+QString().sprintf("%2ih,&nbsp;%2im,&nbsp;%2is",h,m,s1);
if ((i!=(*s)->settings.end()) && i.value().toBool()) corrupted_waveform=true;
tmp.sprintf(("<tr><td align=center><a href='oxi=%i' title='"+tooltip+"'>%08i</a></td><td align=center>"+fd.date().toString(Qt::SystemLocaleShortDate)+"</td><td align=center>"+fd.toString("HH:mm ")+"</td><td align=center>"+ld.toString("HH:mm")+"</td></tr>").toLatin1(),(*s)->session(),(*s)->session());
tmp.sprintf(("<tr><td align=left><a href='oxi=%i' title='"+tooltip+"'>%08i</a></td><td align=center>"+fd.date().toString(Qt::SystemLocaleShortDate)+"</td><td align=center>"+fd.toString("HH:mm ")+"</td><td align=center>"+ld.toString("HH:mm")+"</td></tr>").toLatin1(),(*s)->session(),(*s)->session());
html+=tmp;
}
}

View File

@ -76,8 +76,8 @@ One id code per item
<channel id="0x1800" class="data" name="Pulse" details="Pulse Rate" label="Pulse" unit="bpm" color="red"/>
<channel id="0x1801" class="data" name="SPO2" details="Oxygen Saturation" label="SpO2" unit="%" color="blue"/>
<channel id="0x1802" class="data" name="Plethy" details="Plethysomogram" label="Plethy" color="black"/>
<channel id="0x1803" class="data" name="PulseChange" details="Pulse Change" label="Pulse Change" color="red"/>
<channel id="0x1804" class="data" name="SPO2Drop" details="SPO2Drop" label="SPO2 Drop" color="blue"/>
<channel id="0x1803" class="data" name="PulseChange" details="Pulse Change" label="Pulse Change" color="light gray"/>
<channel id="0x1804" class="data" name="SPO2Drop" details="SPO2Drop" label="SPO2 Drop" color="light blue"/>
</group>
<group name="SLEEP">
<channel id="0x2000" class="data" name="SleepStage" details="Sleep Stage" label="Sleep Stage" color="dark grey"/>

View File

@ -479,6 +479,10 @@ void MainWindow::on_action_Preferences_triggered()
}
prefdialog=NULL;
}
void MainWindow::selectOximetryTab()
{
on_oximetryButton_clicked();
}
void MainWindow::on_oximetryButton_clicked()
{
@ -672,7 +676,8 @@ void MainWindow::PrintReport(gGraphView *gv,QString name, QDate date)
QString username=PROFILE.Get("_{Username}_");
QPrinter printer(QPrinter::ScreenResolution);
//QPrinter printer(QPrinter::ScreenResolution);
QPrinter printer(QPrinter::HighResolution);
#ifdef Q_WS_X11
printer.setPrinterName("Print to File (PDF)");
printer.setOutputFormat(QPrinter::PdfFormat);
@ -698,10 +703,23 @@ void MainWindow::PrintReport(gGraphView *gv,QString name, QDate date)
qDebug() << "Printer Resolution is" << res.width() << "x" << res.height();
const int graphs_per_page=5;
const int footer_height=(res.height()/20);
float gw=res.width();
float gh=(res.height()-40)/graphs_per_page;
mainwin->snapshotGraph()->setMinimumSize(gw,gh);
mainwin->snapshotGraph()->setMaximumSize(gw,gh);
float gh=(res.height()-footer_height)/graphs_per_page;
float gw2=gv->width();
//float gh2=gv->totalHeight();
float xscale=gw / gw2;
float yscale=gh / PROFILE["GraphHeight"].toDouble();
float div=1;
if (gh>500)
div=4;
//yscale=xscale;
SnapshotGraph->setPrintScaleX(xscale/div);
SnapshotGraph->setPrintScaleY(yscale/div);
mainwin->snapshotGraph()->setMinimumSize(gw/div,gh/div);
mainwin->snapshotGraph()->setMaximumSize(gw/div,gh/div);
int page=1;
int pages=ceil(float(visgraphs+1)/float(graphs_per_page));
int i=0;
@ -713,22 +731,25 @@ void MainWindow::PrintReport(gGraphView *gv,QString name, QDate date)
qprogress->show();
}
int header_height=200;
//int header_height=200;
QString title=name+" Report";
QTextOption t_op(Qt::AlignCenter);
painter.setFont(*bigfont);
QRectF bounds=painter.boundingRect(QRectF(0,0,res.width(),50),title,QTextOption(Qt::AlignCenter));
QRectF bounds=painter.boundingRect(QRectF(0,0,res.width(),0),title,QTextOption(Qt::AlignCenter));
painter.drawText(bounds,title,QTextOption(Qt::AlignCenter));
painter.setFont(*defaultfont);
top+=50;
top=bounds.height();
//top+=15*yscale; //spacer
int maxy=0;
if (!PROFILE["FirstName"].toString().isEmpty()) {
QString userinfo="Name:\t"+PROFILE["LastName"].toString()+", "+PROFILE["FirstName"].toString()+"\n";
userinfo+="DOB:\t"+PROFILE["DOB"].toString()+"\n";
userinfo+="Phone:\t"+PROFILE["Phone"].toString()+"\n";
userinfo+="Email:\t"+PROFILE["EmailAddress"].toString()+"\n";
if (!PROFILE["Address"].toString().isEmpty()) userinfo+="\nAddress:\n"+PROFILE["Address"].toString()+"\n";
QRectF bounds=painter.boundingRect(QRectF(0,50,res.width(),150),userinfo,QTextOption(Qt::AlignLeft));
QRectF bounds=painter.boundingRect(QRectF(0,top,res.width(),0),userinfo,QTextOption(Qt::AlignLeft));
painter.drawText(bounds,userinfo,QTextOption(Qt::AlignLeft));
if (bounds.height()>maxy) maxy=bounds.height();
}
if (name=="Daily") {
QString cpapinfo="Date: "+date.toString(Qt::SystemLocaleLongDate)+"\n";
@ -774,22 +795,26 @@ void MainWindow::PrintReport(gGraphView *gv,QString name, QDate date)
stats+="LKI\t"+QString::number(lki,'f',2)+"\n";
stats+="EPI\t"+QString::number(exp,'f',2)+"\n";
}
QRectF bounds=painter.boundingRect(QRectF(res.width()-250,50,250,200),stats,QTextOption(Qt::AlignRight));
QRectF bounds=painter.boundingRect(QRectF(res.width()-(250*xscale),top,250*xscale,0),stats,QTextOption(Qt::AlignRight));
painter.drawText(bounds,stats,QTextOption(Qt::AlignRight));
if (bounds.height()>maxy) maxy=bounds.height();
}
QRectF bounds=painter.boundingRect(QRectF(250,50,res.width()-250,200),cpapinfo,QTextOption(Qt::AlignLeft));
QRectF bounds=painter.boundingRect(QRectF((res.width()/2)-(res.width()/6),top,res.width()-(250*xscale),0),cpapinfo,QTextOption(Qt::AlignLeft));
painter.drawText(bounds,cpapinfo,QTextOption(Qt::AlignLeft));
if (bounds.height()>maxy) maxy=bounds.height();
} else if (name=="Overview") {
QDateTime first=QDateTime::fromTime_t((*gv)[0]->min_x/1000L);
QDateTime last=QDateTime::fromTime_t((*gv)[0]->max_x/1000L);
QString ovinfo="Reporting from "+first.date().toString(Qt::SystemLocaleShortDate)+" to "+last.date().toString(Qt::SystemLocaleShortDate);
QRectF bounds=painter.boundingRect(QRectF(250,50,res.width()-250,200),ovinfo,QTextOption(Qt::AlignLeft));
QRectF bounds=painter.boundingRect(QRectF(250*xscale,top,res.width()-(250*xscale),0),ovinfo,QTextOption(Qt::AlignLeft));
painter.drawText(bounds,ovinfo,QTextOption(Qt::AlignLeft));
if (bounds.height()>maxy) maxy=bounds.height();
}
top+=150;
top+=maxy;
// top+=15*yscale; //spacer
//top=header_height;
const int footer_height=40;
bool first=true;
do {
//+" on "+d.toString(Qt::SystemLocaleLongDate)
@ -799,7 +824,7 @@ void MainWindow::PrintReport(gGraphView *gv,QString name, QDate date)
QRectF bounds=painter.boundingRect(QRectF(0,res.height()-footer_height,res.width(),footer_height),footer,QTextOption(Qt::AlignHCenter));
painter.drawText(bounds,footer,QTextOption(Qt::AlignHCenter));
QRectF pagebnds(res.width()-80,res.height()-footer_height,80,footer_height);
QRectF pagebnds(res.width()-80*xscale,res.height()-footer_height,80*xscale,footer_height);
painter.drawText(pagebnds,"Page "+QString::number(page)+" of "+QString::number(pages),QTextOption(Qt::AlignRight));
first=false;
}
@ -807,15 +832,15 @@ void MainWindow::PrintReport(gGraphView *gv,QString name, QDate date)
if (g->isEmpty()) continue;
if (!g->visible()) continue;
g->deselect();
QPixmap pm=g->renderPixmap(gw,gh);
//QPixmap pm2=pm.scaledToWidth(res.width());
painter.drawPixmap(0,top,pm.width(),pm.height(),pm);
top+=pm.height();
QPixmap pm=g->renderPixmap(gw/div,gh/div);
QPixmap pm2=pm.scaledToWidth(res.width());
painter.drawPixmap(0,top,pm2.width(),pm2.height(),pm2);
top+=gh;
gcnt++;
if ((gcnt>=graphs_per_page) || (top+gh>(res.height()-footer_height))) { //top+pm.height()>res.height()) {
top=0;
gcnt=0;
header_height=0;
//header_height=0;
page++;
if (page>pages) break;
first=true;

View File

@ -48,6 +48,9 @@ public:
Daily *getDaily() { return daily; }
Overview *getOverview() { return overview; }
Oximetry *getOximetry() { return oximetry; }
void selectOximetryTab();
void JumpDaily();
void PrintReport(gGraphView *gv,QString name, QDate date=QDate::currentDate());
private slots:

View File

@ -101,18 +101,24 @@ Overview::Overview(QWidget *parent,gGraphView * shared) :
PR=createGraph("Pressure","Pressure\n(cmH2O)");
SET=createGraph("Settings","Settings");
LK=createGraph("Leaks","Leak Rate\n(L/min)");
SES=createGraph("Sessions","Sessions\n(count)");
NPB=createGraph("% in PB","Periodic\nBreathing\n(% of night)");
AHIHR=createGraph("AHI/Hour","AHI Events/Hour\n(ahi/hr)");
RR=createGraph("Resp. Rate","Respiratory\nRate\n(breaths/min)");
TV=createGraph("Tidal Volume","Tidal\nVolume\n(ml)");
MV=createGraph("Minute Vent.","Minute\nVentilation\n(L/min)");
PTB=createGraph("Pat. Trig. Br.","Patient\nTriggered\nBreaths\n(%)");
SES=createGraph("Sessions","Sessions\n(count)");
PULSE=createGraph("Pulse Rate","Pulse Rate\n(bpm)");
SPO2=createGraph("SpO2","Oxygen Saturation\n(%)");
WEIGHT=createGraph("Weight","Weight\n(kg)");
BMI=createGraph("BMI","Body\nMass\nIndex");
ZOMBIE=createGraph("Zombie","How you felt\n(% awesome)");
ahihr=new SummaryChart("AHI/Hr",GT_LINE);
ahihr->addSlice(CPAP_AHI,QColor("blue"),ST_MAX,true);
ahihr->addSlice(CPAP_AHI,QColor("orange"),ST_WAVG,true);
AHIHR->AddLayer(ahihr);
weight=new SummaryChart("Weight",GT_LINE);
weight->setMachineType(MT_JOURNAL);
weight->addSlice("Weight",QColor("black"),ST_SETAVG,true);

View File

@ -36,8 +36,8 @@ public:
void PrintReport();
gGraph *AHI,*UC, *US, *PR,*LK,*NPB,*SET,*SES,*RR,*MV,*TV,*PTB,*PULSE,*SPO2,*WEIGHT,*ZOMBIE, *BMI;
SummaryChart *bc,*uc, *us, *pr,*lk,*npb,*set,*ses,*rr,*mv,*tv,*ptb,*pulse,*spo2,*weight,*zombie, *bmi;
gGraph *AHI, *AHIHR, *UC, *US, *PR,*LK,*NPB,*SET,*SES,*RR,*MV,*TV,*PTB,*PULSE,*SPO2,*WEIGHT,*ZOMBIE, *BMI;
SummaryChart *bc,*uc, *us, *pr,*lk,*npb,*set,*ses,*rr,*mv,*tv,*ptb,*pulse,*spo2,*weight,*zombie, *bmi, *ahihr;
QVector<SummaryChart *> OverviewCharts;
public slots:

View File

@ -4,10 +4,14 @@
#include <QFileDialog>
#include <QMessageBox>
#include <QLabel>
#include <QLocale>
#include <QTimer>
#include <QCalendarWidget>
#include <QTextCharFormat>
#include "oximetry.h"
#include "ui_oximetry.h"
#include "common_gui.h"
#include "qextserialport/qextserialenumerator.h"
#include "SleepLib/loader_plugins/cms50_loader.h"
#include "SleepLib/event.h"
@ -48,6 +52,7 @@ SerialOximeter::SerialOximeter(QObject * parent,QString oxiname, QString portnam
connect(timer,SIGNAL(timeout()),this,SLOT(Timeout()));
import_mode=false;
m_mode=SO_WAIT;
}
SerialOximeter::~SerialOximeter()
@ -259,25 +264,48 @@ void SerialOximeter::compactToWaveform(EventList *el)
}
void SerialOximeter::compactToEvent(EventList *el)
{
if (el->count()==0) return;
if (el->count()<2) return;
EventList nel(EVL_Waveform);
EventDataType t,lastt=el->data(0);
qint64 ti=el->time(0);
nel.AddEvent(ti,lastt);
EventDataType t,lastt=0; //el->data(0);
qint64 ti;//=el->time(0);
//nel.AddEvent(ti,lastt);
bool f;
for (quint32 i=1;i<el->count();i++) {
qint64 lasttime=0;
EventDataType min=999,max=0;
for (quint32 i=0;i<el->count();i++) {
t=el->data(i);
ti=el->time(i);
f=false;
if (t!=lastt) {
ti=el->time(i);
nel.AddEvent(ti,t);
f=true;
if (t!=0) {
if (t!=lastt) {
if (!lasttime) {
nel.setFirst(ti);
}
nel.AddEvent(ti,t);
if (t < min) min=t;
if (t > max) max=t;
lasttime=ti;
f=true;
}
} else {
if (lastt!=0) {
nel.AddEvent(ti,lastt);
lasttime=ti;
f=true;
}
}
lastt=t;
}
if (!f) {
nel.AddEvent(el->last(),t);
if (t!=0) {
nel.AddEvent(ti,t);
lasttime=ti;
}
}
el->setFirst(nel.first());
el->setLast(nel.last());
el->setMin(min);
el->setMax(max);
el->getData().clear();
el->getTime().clear();
@ -291,15 +319,45 @@ void SerialOximeter::compactAll()
{
if (!session) return;
QHash<ChannelID,QVector<EventList *> >::iterator i;
qint64 tminx=0,tmaxx=0,minx,maxx;
EventDataType min,max;
for (i=session->eventlist.begin();i!=session->eventlist.end();i++) {
const QString & code=i.key();
min=999,max=0;
minx=maxx=0;
for (int j=0;j<i.value().size();j++) {
if (i.key()==OXI_SPO2) {
compactToEvent(i.value()[j]);
} else {
compactToWaveform(i.value()[j]);
EventList *e=i.value()[j];
if ((code==OXI_SPO2) || (code==OXI_Pulse)) {
compactToEvent(e);
} else if (code==OXI_Plethy) {
compactToWaveform(e);
}
if (min > e->min())
min=e->min();
if (max < e->max())
max=e->max();
if (!minx || (minx > e->first()))
minx=e->first();
if (!maxx || (maxx < e->last()))
maxx=e->last();
}
if ((code==OXI_SPO2) || (code==OXI_Pulse) || (code==OXI_Plethy)) {
session->setMin(code,min);
session->setMax(code,max);
if (minx!=0) {
session->setFirst(code,minx);
if (!tminx || tminx > minx) tminx=minx;
}
if (maxx!=0){
session->setLast(code,maxx);
if (!tmaxx || tmaxx < max) tmaxx=maxx;
}
}
}
if (tminx>0) session->really_set_first(tminx);
if (tmaxx>0) session->really_set_last(tmaxx);
}
Session *SerialOximeter::createSession(QDateTime date)
@ -420,6 +478,12 @@ void CMS50Serial::import_process()
if (pl > plmax) plmax=pl;
plcnt++;
}
} else {
if (lastpl!=0) {
pulse->AddEvent(lasttime,pl);
lastpltime=lasttime;
plcnt++;
}
}
if (o2!=0) {
if (lasto2!=o2) {
@ -442,6 +506,12 @@ void CMS50Serial::import_process()
if (o2 > o2max) o2max=o2;
o2cnt++;
}
} else {
if (lasto2!=0) {
spo2->AddEvent(lasttime,o2);
lasto2time=lasttime;
o2cnt++;
}
}
lasttime+=1000;
@ -450,7 +520,7 @@ void CMS50Serial::import_process()
lastpl=pl;
lasto2=o2;
}
if (pulse && (lastpltime!=lasttime) && (pl!=0)) {
/*if (pulse && (lastpltime!=lasttime) && (pl!=0)) {
// lastpl==pl
pulse->AddEvent(lasttime,pl);
lastpltime=lastpltime;
@ -460,8 +530,9 @@ void CMS50Serial::import_process()
spo2->AddEvent(lasttime,o2);
lasto2time=lasttime;
o2cnt++;
}
session->set_last(lasttime);
}*/
qint64 rlasttime=qMax(lastpltime,lasto2time);
session->set_last(rlasttime);
session->setLast(OXI_Pulse,lastpltime);
session->setLast(OXI_SPO2,lasto2time);
session->setMin(OXI_Pulse,plmin);
@ -788,6 +859,24 @@ Oximetry::Oximetry(QWidget *parent,gGraphView * shared) :
ui->saveButton->setEnabled(false);
GraphView->LoadSettings("Oximetry");
QLocale locale=QLocale::system();
QString shortformat=locale.dateFormat(QLocale::ShortFormat);
if (!shortformat.toLower().contains("yyyy")) {
shortformat.replace("yy","yyyy");
}
ui->dateEdit->setDisplayFormat(shortformat+" HH:mm:ss");
//Qt::DayOfWeek dow=firstDayOfWeekFromLocale();
//ui->dateEdit->calendarWidget()->setFirstDayOfWeek(dow);
// Stop both calendar drop downs highlighting weekends in red
//QTextCharFormat format = ui->dateEdit->calendarWidget()->weekdayTextFormat(Qt::Saturday);
//format.setForeground(QBrush(Qt::black, Qt::SolidPattern));
//ui->dateEdit->calendarWidget()->setWeekdayTextFormat(Qt::Saturday, format);
//ui->dateEdit->calendarWidget()->setWeekdayTextFormat(Qt::Sunday, format);
dont_update_date=false;
}
Oximetry::~Oximetry()
@ -876,6 +965,8 @@ void Oximetry::on_RunButton_toggled(bool checked)
ui->ImportButton->setEnabled(true);
lo2->SetDay(day);
lo1->SetDay(day);
if (oximeter->getSession())
saved_starttime=oximeter->getSession()->first();
@ -1113,62 +1204,17 @@ void Oximetry::import_complete(Session * session)
//calcSPO2Drop(session);
//calcPulseChange(session);
ui->pulseLCD->display(session->min(OXI_Pulse));
ui->spo2LCD->display(session->min(OXI_SPO2));
pulse->setMinY(session->min(OXI_Pulse));
pulse->setMaxY(session->max(OXI_Pulse));
spo2->setMinY(session->min(OXI_SPO2));
spo2->setMaxY(session->max(OXI_SPO2));
PULSE->setRecMinY(60);
PULSE->setRecMaxY(100);
SPO2->setRecMinY(90);
SPO2->setRecMaxY(100);
//PLETHY->setVisible(false);
CONTROL->setVisible(false);
qint64 f=session->first();
qint64 l=session->last();
day->setFirst(f);
day->setLast(l);
saved_starttime=session->first();
dont_update_date=true;
ui->dateEdit->setDateTime(QDateTime::fromTime_t(saved_starttime/1000L));
dont_update_date=false;
plethy->setMinX(f);
pulse->setMinX(f);
spo2->setMinX(f);
PLETHY->SetMinX(f);
CONTROL->SetMinX(f);
PULSE->SetMinX(f);
SPO2->SetMinX(f);
plethy->setMaxX(l);
pulse->setMaxX(l);
spo2->setMaxX(l);
PLETHY->SetMaxX(l);
CONTROL->SetMaxX(l);
PULSE->SetMaxX(l);
SPO2->SetMaxX(l);
PULSE->setDay(day);
SPO2->setDay(day);
for (int i=0;i<GraphView->size();i++) {
(*GraphView)[i]->SetXBounds(f,l);
}
{
int len=(l-f)/1000L;
int h=len/3600;
int m=(len /60) % 60;
int s=(len % 60);
if (qstatus2) qstatus2->setText(QString().sprintf("%02i:%02i:%02i",h,m,s));
}
GraphView->updateScale();
GraphView->updateGL();
updateGraphs();
}
void Oximetry::pulse_changed(float p)
@ -1204,11 +1250,20 @@ void Oximetry::on_saveButton_clicked()
{
if (QMessageBox::question(this,"Keep This Recording?","Would you like to save this oximetery session?",QMessageBox::Yes|QMessageBox::No)==QMessageBox::Yes) {
Session *session=oximeter->getSession();
// Process???
//session->UpdateSummaries();
oximeter->getMachine()->AddSession(session,p_profile);
PROFILE.RemoveSession(session);
Machine *m=oximeter->getMachine();
if (m->SessionExists(session->session())) {
m->sessionlist.erase(m->sessionlist.find(session->session()));
}
m->AddSession(session,p_profile);
//}
oximeter->getMachine()->Save();
day->getSessions().clear();
mainwin->getDaily()->ReloadGraphs();
mainwin->getOverview()->ReloadGraphs();
GraphView->setEmptyText("No Oximetry Data");
@ -1243,7 +1298,7 @@ bool Oximetry::openSPOFile(QString filename)
QString dstr(dchr);
QDateTime date=QDateTime::fromString(dstr,"MM/dd/yy HH:mm:ss");
if (date.date().year()<2000) date=date.addYears(100);
qDebug() << date << pos;
//ui->dateEdit->setDateTime(date);
day->getSessions().clear();
oximeter->createSession(date);
@ -1251,13 +1306,6 @@ bool Oximetry::openSPOFile(QString filename)
day->AddSession(session);
session->set_first(0);
PLETHY->setRecMinY(0);
PLETHY->setRecMaxY(128);
PULSE->setRecMinY(60);
PULSE->setRecMaxY(100);
SPO2->setRecMinY(90);
SPO2->setRecMaxY(100);
firstPulseUpdate=true;
firstSPO2Update=true;
secondPulseUpdate=true;
@ -1267,17 +1315,6 @@ bool Oximetry::openSPOFile(QString filename)
quint16 pl;
qint64 tt=qint64(date.toTime_t())*1000L;
/*session->set_first(tt);
day->setFirst(tt);
plethy->setMinX(tt);
pulse->setMinX(tt);
spo2->setMinX(tt);
PLETHY->SetMinX(tt);
CONTROL->SetMinX(tt);
PULSE->SetMinX(tt);
SPO2->SetMinX(tt); */
for (int i=pos;i<size-5;) {
o2=(unsigned char)(data.at(i+4));
pr=(unsigned char)(data.at(i+3));
@ -1299,73 +1336,22 @@ bool Oximetry::openSPOFile(QString filename)
qint64 t3=qMin(t1,t2);
session->set_first(t3);
day->setFirst(t3);
int zi=t3/1000L;
session->SetSessionID(zi);
date.fromTime_t(zi);
dont_update_date=true;
ui->dateEdit->setDateTime(date);
dont_update_date=false;
t1=session->last(OXI_Pulse);
t2=session->last(OXI_SPO2);
t3=qMax(t1,t2);
session->set_last(t3);
day->setLast(t3);
//session->setLast(OXI_Pulse,tt);
//session->setLast(OXI_Plethy,tt);
//session->setLast(OXI_SPO2,tt);
//session->set_last(tt);
ui->pulseLCD->display(session->min(OXI_Pulse));
ui->spo2LCD->display(session->min(OXI_SPO2));
pulse->setMinY(session->min(OXI_Pulse));
pulse->setMaxY(session->max(OXI_Pulse));
spo2->setMinY(session->min(OXI_SPO2));
spo2->setMaxY(session->max(OXI_SPO2));
PULSE->setRecMinY(60);
PULSE->setRecMaxY(100);
SPO2->setRecMinY(90);
SPO2->setRecMaxY(100);
//PLETHY->setVisible(false);
CONTROL->setVisible(false);
{
qint64 f=session->first();
qint64 l=session->last();
day->setFirst(f);
day->setLast(l);
updateGraphs();
plethy->setMinX(f);
pulse->setMinX(f);
spo2->setMinX(f);
PLETHY->SetMinX(f);
CONTROL->SetMinX(f);
PULSE->SetMinX(f);
SPO2->SetMinX(f);
plethy->setMaxX(l);
pulse->setMaxX(l);
spo2->setMaxX(l);
PLETHY->SetMaxX(l);
CONTROL->SetMaxX(l);
PULSE->SetMaxX(l);
SPO2->SetMaxX(l);
PULSE->setDay(day);
SPO2->setDay(day);
session->UpdateSummaries();
for (int i=0;i<GraphView->size();i++) {
(*GraphView)[i]->SetXBounds(f,l);
}
{
int len=(l-f)/1000L;
int h=len/3600;
int m=(len /60) % 60;
int s=(len % 60);
if (qstatus2) qstatus2->setText(QString().sprintf("%02i:%02i:%02i",h,m,s));
}
GraphView->updateScale();
GraphView->updateGL();
}
f.close();
ui->saveButton->setEnabled(true);
return true;
@ -1393,7 +1379,6 @@ bool Oximetry::openSPORFile(QString filename)
QString dstr(dchr);
QDateTime date=QDateTime::fromString(dstr,"MM/dd/yy HH:mm:ss");
if (date.date().year()<2000) date=date.addYears(100);
qDebug() << date << pos;
day->getSessions().clear();
oximeter->createSession(date);
@ -1401,13 +1386,6 @@ bool Oximetry::openSPORFile(QString filename)
day->AddSession(session);
session->set_first(0);
PLETHY->setRecMinY(0);
PLETHY->setRecMaxY(128);
PULSE->setRecMinY(60);
PULSE->setRecMaxY(100);
SPO2->setRecMinY(90);
SPO2->setRecMaxY(100);
firstPulseUpdate=true;
firstSPO2Update=true;
secondPulseUpdate=true;
@ -1431,69 +1409,25 @@ bool Oximetry::openSPORFile(QString filename)
qint64 t3=qMin(t1,t2);
session->set_first(t3);
day->setFirst(t3);
int zi=t3/1000L;
session->SetSessionID(zi);
date.fromTime_t(zi);
dont_update_date=true;
ui->dateEdit->setDateTime(date);
dont_update_date=false;
t1=session->last(OXI_Pulse);
t2=session->last(OXI_SPO2);
t3=qMax(t1,t2);
session->set_last(t3);
day->setLast(t3);
ui->pulseLCD->display(session->min(OXI_Pulse));
ui->spo2LCD->display(session->min(OXI_SPO2));
pulse->setMinY(session->min(OXI_Pulse));
pulse->setMaxY(session->max(OXI_Pulse));
spo2->setMinY(session->min(OXI_SPO2));
spo2->setMaxY(session->max(OXI_SPO2));
PULSE->setRecMinY(60);
PULSE->setRecMaxY(100);
SPO2->setRecMinY(90);
SPO2->setRecMaxY(100);
//PLETHY->setVisible(false);
CONTROL->setVisible(false);
{
qint64 f=session->first();
qint64 l=session->last();
day->setFirst(f);
day->setLast(l);
plethy->setMinX(f);
pulse->setMinX(f);
spo2->setMinX(f);
PLETHY->SetMinX(f);
CONTROL->SetMinX(f);
PULSE->SetMinX(f);
SPO2->SetMinX(f);
plethy->setMaxX(l);
pulse->setMaxX(l);
spo2->setMaxX(l);
PLETHY->SetMaxX(l);
CONTROL->SetMaxX(l);
PULSE->SetMaxX(l);
SPO2->SetMaxX(l);
PULSE->setDay(day);
SPO2->setDay(day);
session->UpdateSummaries();
for (int i=0;i<GraphView->size();i++) {
(*GraphView)[i]->SetXBounds(f,l);
}
{
int len=(l-f)/1000L;
int h=len/3600;
int m=(len /60) % 60;
int s=(len % 60);
if (qstatus2) qstatus2->setText(QString().sprintf("%02i:%02i:%02i",h,m,s));
}
GraphView->updateScale();
GraphView->updateGL();
}
updateGraphs();
f.close();
ui->saveButton->setEnabled(true);
return true;
@ -1530,3 +1464,132 @@ void Oximetry::on_openButton_clicked()
}
qDebug() << "opening" << filename;
}
void Oximetry::on_dateEdit_dateTimeChanged(const QDateTime &date)
{
Session *session=oximeter->getSession();
if (!session)
return;
if (dont_update_date)
return;
qint64 first=session->first();
qint64 last=session->last();
qint64 tt=qint64(date.toTime_t())*1000L;
qint64 offset=tt-first;
if (offset!=0) {
session->SetChanged(true);
ui->saveButton->setEnabled(true);
}
session->offsetSession(offset);
updateGraphs();
}
void Oximetry::openSession(Session * session)
{
if (oximeter->getSession() && oximeter->getSession()->IsChanged()) {
int res=QMessageBox::question(this,"Save Session?","Opening this oximetry session will destroy the unsavedsession in the oximetry tab.\nWould you like to store it first?","Save","Destroy It","Cancel",0,2);
if (res==0) {
on_saveButton_clicked();
return;
} else if (res==2) {
return;
}
} // else it's already saved.
day->getSessions().clear();
day->AddSession(session);
oximeter->setSession(session);
saved_starttime=session->first();
oximeter->compactAll();
QDateTime date=QDateTime::fromTime_t(saved_starttime/1000L);
dont_update_date=true;
ui->dateEdit->setDateTime(date);
dont_update_date=false;
updateGraphs();
}
void Oximetry::updateGraphs()
{
Session * session=oximeter->getSession();
if (!session) return;
qint64 first=session->first();
qint64 last=session->last();
ui->pulseLCD->display(session->min(OXI_Pulse));
ui->spo2LCD->display(session->min(OXI_SPO2));
pulse->setMinY(session->min(OXI_Pulse));
pulse->setMaxY(session->max(OXI_Pulse));
spo2->setMinY(session->min(OXI_SPO2));
spo2->setMaxY(session->max(OXI_SPO2));
PULSE->setRecMinY(60);
PULSE->setRecMaxY(100);
SPO2->setRecMinY(90);
SPO2->setRecMaxY(100);
day->setFirst(first);
day->setLast(last);
pulse->setMinY(session->min(OXI_Pulse));
pulse->setMaxY(session->max(OXI_Pulse));
spo2->setMinY(session->min(OXI_SPO2));
spo2->setMaxY(session->max(OXI_SPO2));
PULSE->setRecMinY(60);
PULSE->setRecMaxY(100);
SPO2->setRecMinY(90);
SPO2->setRecMaxY(100);
plethy->setMinX(first);
pulse->setMinX(first);
spo2->setMinX(first);
PLETHY->SetMinX(first);
CONTROL->SetMinX(first);
PULSE->SetMinX(first);
SPO2->SetMinX(first);
plethy->setMaxX(last);
pulse->setMaxX(last);
spo2->setMaxX(last);
PLETHY->SetMaxX(last);
CONTROL->SetMaxX(last);
PULSE->SetMaxX(last);
SPO2->SetMaxX(last);
PULSE->setDay(day);
SPO2->setDay(day);
for (int i=0;i<GraphView->size();i++) {
(*GraphView)[i]->SetXBounds(first,last);
}
{
int len=(last-first)/1000L;
int h=len/3600;
int m=(len /60) % 60;
int s=(len % 60);
if (qstatus2) qstatus2->setText(QString().sprintf("%02i:%02i:%02i",h,m,s));
}
GraphView->updateScale();
GraphView->updateGL();
}
void Oximetry::on_resetTimeButton_clicked() //revert to original session time
{
if (oximeter->getSession()) {
//qint64 tt=ui->dateEdit->dateTime().toTime_t()*1000;
//qint64 offset=saved_starttime-tt;
//oximeter->getSession()->offsetSession(offset);
dont_update_date=false;
//ui->dateEdit->setDateTime(QDateTime::fromTime_t(saved_starttime/1000L));
ui->dateEdit->setDateTime(QDateTime::fromTime_t(saved_starttime/1000L));
dont_update_date=false;
}
}

View File

@ -28,6 +28,7 @@ public:
explicit SerialOximeter(QObject * parent,QString oxiname, QString portname="",BaudRateType baud=BAUD19200, FlowType flow=FLOW_OFF, ParityType parity=PAR_ODD, DataBitsType databits=DATA_8, StopBitsType stopbits=STOP_1);
virtual ~SerialOximeter();
virtual void setSession(Session * sess) { session=sess; }
virtual bool Open(QextSerialPort::QueryMode mode=QextSerialPort::EventDriven);
virtual void Close();
@ -171,6 +172,7 @@ public:
void RedrawGraphs();
gGraphView *graphView() { return GraphView; }
void openSession(Session * session);
private slots:
void on_RefreshPortsButton_clicked();
@ -193,10 +195,15 @@ private slots:
void on_openButton_clicked();
void on_dateEdit_dateTimeChanged(const QDateTime &date);
void on_resetTimeButton_clicked();
private:
bool openSPOFile(QString filename);
bool openSPORFile(QString filename);
void import_finished();
void updateGraphs();
Ui::Oximetry *ui;
gGraphView *GraphView;
@ -224,11 +231,12 @@ private:
gGraphView * m_shared;
SerialOximeter *oximeter;
qint64 saved_starttime;
bool firstSPO2Update;
bool firstPulseUpdate;
bool secondPulseUpdate;
bool secondSPO2Update;
bool dont_update_date;
};
#endif // OXIMETRY_H

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>780</width>
<height>436</height>
<width>961</width>
<height>439</height>
</rect>
</property>
<property name="windowTitle">
@ -235,6 +235,27 @@
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Date</string>
</property>
</widget>
</item>
<item>
<widget class="QDateTimeEdit" name="dateEdit">
<property name="displayFormat">
<string>d/MM/yy h:mm:ss AP</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="resetTimeButton">
<property name="text">
<string>R</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">