Miscellaneous fixes and code cleanup.. Made PRS1 custom event flagging optional, made minor improvements to it's functionality. enabled AHI/hr graph options. Use just 2 decimal places in stats. Changed bookmarks in right sidebar to HTML view as List was broken

This commit is contained in:
Mark Watkins 2012-01-07 02:07:54 +10:00
parent 990a068172
commit edf44d3e72
23 changed files with 560 additions and 509 deletions

View File

@ -90,14 +90,13 @@ void InitGraphs()
mediumfont->setStyleHint(QFont::AnyStyle,QFont::OpenGLCompatible);
bigfont->setStyleHint(QFont::AnyStyle,QFont::OpenGLCompatible);
images["mask"]=new QImage(":/icons/mask.png");
//images["mask"]=new QImage(":/icons/mask.png");
images["oximeter"]=new QImage(":/icons/cubeoximeter.png");
images["smiley"]=new QImage(":/icons/smileyface.png");
images["sad"]=new QImage(":/icons/sadface.png");
//images["sad"]=new QImage(":/icons/sadface.png");
images["brick"]=new QImage(":/icons/brick.png");
//images["warning"]=new QImage(":/icons/warning.png");
//images["bug"]=new QImage(":/icons/bug.png");
images["sheep"]=new QImage(":/icons/sheep.png");
images["nographs"]=new QImage(":/icons/nographs.png");
images["nodata"]=new QImage(":/icons/nodata.png");
_graph_init=true;
@ -2160,9 +2159,9 @@ void gGraphView::selectionTime()
}
}
void gGraphView::GetRXBounds(qint64 st, qint64 et)
void gGraphView::GetRXBounds(qint64 & st, qint64 & et)
{
qint64 m1=0,m2=0;
//qint64 m1=0,m2=0;
gGraph *g=NULL;
for (int i=0;i<m_graphs.size();i++) {
g=m_graphs[i];
@ -2356,7 +2355,7 @@ void gGraphView::renderSomethingFun()
// When I'm feeling more energetic, I'll change it to a textured sheep or something.
static float rotqube=0;
static float xpos=0,ypos=7,spos=0;
static float xpos=0,ypos=7;
glLoadIdentity();
@ -2370,12 +2369,17 @@ void gGraphView::renderSomethingFun()
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
double xx=sin(M_PI/180.0 * xpos)*2; // ((4.0/width()) * m_mouse.rx())-2.0;
double yy=cos(M_PI/180.0 * ypos)*2; //2-((4.0/height()) * m_mouse.ry());
xpos+=1;
ypos+=1.32;
if (xpos > 360) xpos-=360.0;
if (ypos > 360) ypos-=360.0;
double xx=0.0,yy=0.0;
// set this to 0 to make the cube stay in the center of the screen
if (1) {
xx=sin(M_PI/180.0 * xpos)*2; // ((4.0/width()) * m_mouse.rx())-2.0;
yy=cos(M_PI/180.0 * ypos)*2; //2-((4.0/height()) * m_mouse.ry());
xpos+=1;
ypos+=1.32;
if (xpos > 360) xpos-=360.0;
if (ypos > 360) ypos-=360.0;
}
//m_mouse.x();
@ -2808,6 +2812,7 @@ void gGraphView::setCubeImage(QImage *img)
{
cubeimg.clear();
cubeimg.push_back(img);
cubetex=bindTexture(*img);
glBindTexture(GL_TEXTURE_2D,0);
}
@ -2920,22 +2925,8 @@ void gGraphView::mouseMoveEvent(QMouseEvent * event)
this->setCursor(Qt::SplitVCursor);
} else if (!m_button_down && (y >= py) && (y < py+m_graphs[i]->top)) {
// Mouse cursor is in top graph margin.
// if (m_graphs[i]->isSelected()) {
// m_graphs[i]->deselect();
// if (m_tooltip->visible())
// m_tooltip->cancel();
// redraw();
// }
//qDebug() << "upper bounds";
} else if (!m_button_down && (y >= py+h-m_graphs[i]->bottom) && (y <= py+h)) {
// Mouse cursor is in bottom grpah margin.
// if (m_graphs[i]->isSelected()) {
// if (m_tooltip->visible())
// m_tooltip->cancel();
// m_graphs[i]->deselect();
// redraw();
// }
//qDebug() << "lower bounds";
} else if (m_button_down || ((y >= py+m_graphs[i]->top) && (y < py + h-m_graphs[i]->bottom))) {
if (m_button_down || (x >= titleWidth+10)) { //(gYAxis::Margin-5)
this->setCursor(Qt::ArrowCursor);
@ -2988,7 +2979,7 @@ void gGraphView::mouseMoveEvent(QMouseEvent * event)
}
py+=h;
py+=graphSpacer; // do we want the extra spacer down the bottom?
py+=graphSpacer;
}
}
@ -3007,7 +2998,7 @@ void gGraphView::mousePressEvent(QMouseEvent * event)
h=m_graphs[i]->height()*m_scaleY;
if (py>height())
break; // we are done.. can't draw anymore
break;
if ((py + h + graphSpacer) >= 0) {
if ((y >= py) && (y < py + h)) {
@ -3041,7 +3032,7 @@ void gGraphView::mousePressEvent(QMouseEvent * event)
}
py+=h;
py+=graphSpacer; // do we want the extra spacer down the bottom?
py+=graphSpacer;
}
}

View File

@ -836,7 +836,7 @@ public:
void GetXBounds(qint64 & st,qint64 & et);
//! \brief Returns the maximum time range bounds
void GetRXBounds(qint64 st, qint64 et);
void GetRXBounds(qint64 & st, qint64 & et);
//! \brief Resets the time range to default for this day. Refreshing the display if refresh==true.
void ResetBounds(bool refresh=true); //short group=0);

View File

@ -604,7 +604,7 @@ void gLineChart::paint(gGraph & w,int left, int top, int width, int height)
legendx-=bw/2;
int tp=top-5-bw/2;
w.quads()->add(legendx-bw,tp+bw/2,legendx,tp+bw/2,legendx,tp-bw/2,legendx-bw,tp-bw/2,m_line_color.rgba());
w.quads()->add(legendx-bw,tp+bw/2,legendx,tp+bw/2,legendx,tp-bw/2,legendx-bw,tp-bw/2,m_colors[gi].rgba());
legendx-=hi+bw/2;
}
}

View File

@ -29,7 +29,6 @@
<file>icons/sadface.png</file>
<file>icons/mask.png</file>
<file>icons/brick.png</file>
<file>icons/sheep.png</file>
<file>icons/nodata.png</file>
<file>icons/cubeoximeter.png</file>
<file>icons/trophy.png</file>
@ -41,5 +40,6 @@
<file>icons/session-on.png</file>
<file>icons/bob-v3.0.png</file>
<file>docs/script.js</file>
<file>icons/nographs.png</file>
</qresource>
</RCC>

View File

@ -5,6 +5,7 @@
*/
#include <cmath>
#include <algorithm>
#include "calcs.h"
#include "profiles.h"
@ -117,6 +118,8 @@ int filterFlow(Session *session, EventList *in, EventList *out, EventList *tv, E
// int rpos=0;
EventDataType min=0,max=0;
qint64 peakmin=0, peakmax=0;
double avgmax=0;
double avgmin=0;
for (i=0;i<size;i++) {
c=stage2[i];
@ -144,6 +147,7 @@ int filterFlow(Session *session, EventList *in, EventList *out, EventList *tv, E
// keep previously calculated negative peak
breaths_min_peak.push_back(peakmin);
breaths_min.push_back(min);
avgmin+=min;
max=0;
}
} else {
@ -176,6 +180,7 @@ int filterFlow(Session *session, EventList *in, EventList *out, EventList *tv, E
// keep previously calculated positive peak
breaths_max_peak.push_back(peakmax);
breaths_max.push_back(max);
avgmax+=max;
min=0;
}
@ -195,53 +200,90 @@ int filterFlow(Session *session, EventList *in, EventList *out, EventList *tv, E
if (!breaths.size()) {
return 0;
}
double avgmax=0;
for (int i=0;i<breaths_max.size();i++) {
max=breaths_max[i];
avgmax+=max;
}
avgmax/=EventDataType(breaths_max.size());
double avgmin=0;
for (int i=0;i<breaths_min.size();i++) {
min=breaths_min[i];
avgmin+=min;
}
avgmax/=EventDataType(breaths_max.size());
avgmin/=EventDataType(breaths_min.size());
QVector<qint64> goodb;
for (int i=0;i<breaths_max.size();i++) {
max=breaths_max[i];
time=breaths_max_peak[i];
if ((breaths_max.size()>5) && (breaths_min.size()>5) && (p_profile->cpap->userEventFlagging())) {
EventDataType maxperc,minperc;
if (max > avgmax*0.2) {
goodb.push_back(time);
}
}
for (int i=0;i<breaths_min.size();i++) {
min=breaths_min[i];
time=breaths_min_peak[i];
if (min < avgmin*0.2) {
goodb.push_back(time);
}
}
EventList *uf=NULL;
int n=breaths_max.size()*0.8;
if (n > breaths_max.size()-1) n-=1;
nth_element(breaths_max.begin(),breaths_max.begin()+n,breaths_max.end());
maxperc=breaths_max[n];
qSort(goodb);
for (int i=1;i<goodb.size();i++) {
qint64 len=qAbs(goodb[i]-goodb[i-1]);
if (len>=10000) {
time=goodb[i-1]+len/2;
if (!SearchApnea(session,time)) {
if (!uf) {
uf=new EventList(EVL_Event,1,0,0,0,0,true);
session->eventlist[CPAP_UserFlag1].push_back(uf);
n=breaths_min.size()*0.2;
if (n > breaths_min.size()-1) n-=1;
nth_element(breaths_min.begin(),breaths_min.begin()+n,breaths_min.end());
minperc=breaths_min[n];
QVector<qint64> goodb;
EventDataType restriction=p_profile->cpap->userFlowRestriction()/100.0;
// This is faster than vector access.
EventDataType *dptr=breaths_max.data();
qint64 * tptr=breaths_max_peak.data();
EventDataType restrict=maxperc * restriction;
// Knock out all the upper breath components above the flow restriction
for (int i=0;i<breaths_max.size();i++) {
max=*dptr++; //breaths_max[i];
time=*tptr++; //breaths_max_peak[i];
if ((time > 0) && (max > restrict)) {
goodb.push_back(time);
}
}
dptr=breaths_min.data();
tptr=breaths_min_peak.data();
restrict=minperc * restriction;
// Knock out all the lower breath components above the flow restriction
for (int i=0;i<breaths_min.size();i++) {
min=*dptr++; //breaths_min[i];
time=*tptr++; //breaths_min_peak[i];
if ((time > 0) && (min < restrict)) {
goodb.push_back(time);
}
}
EventList *uf=NULL;
if (goodb.size()>2) {
qint64 duration=p_profile->cpap->userEventDuration()*1000;
qSort(goodb);
tptr=goodb.data();
qint64 g0=*tptr++,g1;
EventDataType lf;
//
for (int i=1;i<goodb.size();i++) {
g1=*tptr++;
qint64 len=g1-g0;
if (len >= duration) {
time=g0 + (len/2);
if (!SearchApnea(session,time)) {
if (!uf) {
uf=new EventList(EVL_Event,1,0,0,0,0,true);
session->eventlist[CPAP_UserFlag1].push_back(uf);
}
lf=double(len)/1000.0;
if (lf>30) {
int i=5;
}
uf->AddEvent(time,lf,1);
}
}
uf->AddEvent(time,len/1000L,1);
g0=g1;
}
}
}
qint64 window=60000;
qint64 t1=in->first()-window/2;
qint64 t2=in->first()+window/2;
@ -385,7 +427,7 @@ int calcRespRate(Session *session)
EventDataType calcAHI(Session *session,qint64 start, qint64 end)
{
double hours,ahi,cnt;
if ((start==end) && (start==0)) {
if (start<0) {
// much faster..
hours=session->hours();
cnt=session->count(CPAP_Obstructive)
@ -396,6 +438,7 @@ EventDataType calcAHI(Session *session,qint64 start, qint64 end)
ahi=cnt/hours;
} else {
hours=double(end-start)/3600000L;
if (hours==0) return 0;
cnt=session->rangeCount(CPAP_Obstructive,start,end)
+session->rangeCount(CPAP_Hypopnea,start,end)
+session->rangeCount(CPAP_ClearAirway,start,end)
@ -408,8 +451,11 @@ EventDataType calcAHI(Session *session,qint64 start, qint64 end)
int calcAHIGraph(Session *session)
{
const qint64 window_size=3600000L;
const qint64 window_step=30000; // 30 second windows
double window_size=p_profile->cpap->AHIWindow();
qint64 window_size_ms=window_size*60000L;
bool zeroreset=p_profile->cpap->AHIReset();
if (session->machine()->GetType()!=MT_CPAP) return 0;
if (session->eventlist.contains(CPAP_AHI)) return 0; // abort if already there
@ -428,22 +474,55 @@ int calcAHIGraph(Session *session)
EventDataType ahi;
qint64 ti;
qint64 ti=first,lastti=first;
double avg=0;
int cnt=0;
for (ti=first;ti<last;ti+=window_step) {
f=ti-window_size;
ahi=calcAHI(session,f,ti);
if (ti>=last) {
AHI->AddEvent(last,ahi);
double events;
double hours=(window_size/60.0);
if (zeroreset) {
// I personally don't see the point of resetting each hour.
do {
// For each window, in 30 second increments
for (qint64 t=ti;t < ti+window_size_ms; t+=window_step) {
if (t > last)
break;
events=session->rangeCount(CPAP_Obstructive,ti,t)
+session->rangeCount(CPAP_Hypopnea,ti,t)
+session->rangeCount(CPAP_ClearAirway,ti,t)
+session->rangeCount(CPAP_Apnea,ti,t);
//ahi=calcAHI(session,ti,t)* hours;
ahi = events / hours;
AHI->AddEvent(t,ahi);
avg+=ahi;
cnt++;
}
lastti=ti;
ti+=window_size_ms;
} while (ti<last);
} else {
for (ti=first;ti<last;ti+=window_step) {
// if (ti>last) {
//// AHI->AddEvent(last,ahi);
//// avg+=ahi;
//// cnt++;
// break;
// }
f=ti-window_size_ms;
ahi=calcAHI(session,f,ti);
avg+=ahi;
cnt++;
break;
AHI->AddEvent(ti,ahi);
lastti=ti;
ti+=window_step;
}
AHI->AddEvent(ti,ahi);
ti+=window_step;
}
AHI->AddEvent(last,0);
AHI->AddEvent(lastti,0);
if (!cnt) avg=0; else avg/=double(cnt);
session->setAvg(CPAP_AHI,avg);

View File

@ -15,7 +15,7 @@ int calcRespRate(Session *session);
int calcAHIGraph(Session *session);
//! \brief Calculates AHI for a session between start & end (a support function for the sliding window graph)
EventDataType calcAHI(Session *session,qint64 start=0, qint64 end=0);
EventDataType calcAHI(Session *session,qint64 start=-1, qint64 end=-1);
//! \brief Leaks calculations for PRS1
int calcLeaks(Session *session);

View File

@ -430,15 +430,18 @@ int ResmedLoader::Open(QString & path,Profile *profile)
QFile::copy(path+idfile+ext_TGT,backup_path+idfile+ext_TGT);
QFile::copy(path+idfile+ext_CRC,backup_path+idfile+ext_CRC);
//copy STR files to backup folder
if (strpath.endsWith(ext_gz)) // Already compressed.
QFile::copy(strpath,backup_path+strfile+ext_EDF+ext_gz);
else { // Compress STR file to backup folder
QString strf=backup_path+strfile+ext_EDF;
if (QFile::exists(strf))
QFile::remove(strf);
compress_backups ?
compressFile(strpath,backup_path+strfile+ext_EDF)
compressFile(strpath,strf)
:
QFile::copy(strpath,backup_path+strfile+ext_EDF);
QFile::copy(strpath,strf);
}
QFile::copy(path+"STR.crc",backup_path+"STR.crc");
@ -983,15 +986,41 @@ int ResmedLoader::Open(QString & path,Profile *profile)
// Copy the EDF file to the backup folder
if (create_backups) {
backupfile=backup_path+filename;
if (!gz) {
compress_backups ?
compressFile(fullpath, backupfile)
:
bool dobackup=true;
if (!gz && QFile::exists(backupfile+".gz")) {
dobackup=false;
} else if (QFile::exists(backupfile)) {
if (gz) {
// don't bother, it's already there and compressed.
dobackup=false;
} else {
// non compressed file is there..
if (compress_backups) {
// remove old edf file, as we are writing a compressed one
QFile::remove(backupfile);
} else { // don't bother copying it.
dobackup=false;
}
}
}
if (dobackup) {
if (!gz) {
compress_backups ?
compressFile(fullpath, backupfile)
:
QFile::copy(fullpath, backupfile);
} else {
// already compressed, just copy it.
QFile::copy(fullpath, backupfile);
} else // already compressed, just copy it.
QFile::copy(fullpath, backupfile);
}
}
if (!gz) {
backfile=filename.replace(".edf",".crc",Qt::CaseInsensitive);
} else {
backfile=filename.replace(".edf.gz",".crc",Qt::CaseInsensitive);
}
backfile=filename.replace(".edf",".crc",Qt::CaseInsensitive);
backupfile=backup_path+backfile;
crcfile=newpath+backfile;
QFile::copy(crcfile, backupfile);
@ -1311,13 +1340,16 @@ bool ResmedLoader::LoadBRP(Session *sess,EDFParser &edf)
for (int s=0;s<edf.GetNumSignals();s++) {
EDFSignal & es=*edf.edfsignals[s];
//qDebug() << "BRP:" << es.digital_maximum << es.digital_minimum << es.physical_maximum << es.physical_minimum;
long recs=edf.edfsignals[s]->nr*edf.GetNumDataRecords();
long recs=es.nr*edf.GetNumDataRecords();
ChannelID code;
if (edf.edfsignals[s]->label=="Flow") {
if (es.offset>0) {
int i=5;
}
if (es.label=="Flow") {
es.gain*=60;
es.physical_dimension="L/M";
code=CPAP_FlowRate;
} else if (edf.edfsignals[s]->label.startsWith("Mask Pres")) {
} else if (es.label.startsWith("Mask Pres")) {
code=CPAP_MaskPressureHi;
} else if (es.label.startsWith("Resp Event")) {
code=CPAP_RespEvent;
@ -1400,11 +1432,11 @@ bool ResmedLoader::LoadSAD(Session *sess,EDFParser &edf)
for (int s=0;s<edf.GetNumSignals();s++) {
EDFSignal & es=*edf.edfsignals[s];
//qDebug() << "SAD:" << es.label << es.digital_maximum << es.digital_minimum << es.physical_maximum << es.physical_minimum;
long recs=edf.edfsignals[s]->nr*edf.GetNumDataRecords();
long recs=es.nr*edf.GetNumDataRecords();
ChannelID code;
if (edf.edfsignals[s]->label.startsWith("Puls")) {
if (es.label.startsWith("Puls")) {
code=OXI_Pulse;
} else if (edf.edfsignals[s]->label=="SpO2") {
} else if (es.label=="SpO2") {
code=OXI_SPO2;
} else {
qDebug() << "Unobserved ResMed SAD Signal " << edf.edfsignals[s]->label;
@ -1446,6 +1478,9 @@ bool ResmedLoader::LoadPLD(Session *sess,EDFParser &edf)
ChannelID code;
for (int s=0;s<edf.GetNumSignals();s++) {
EDFSignal & es=*edf.edfsignals[s];
if (es.offset>0) {
int i=5;
}
recs=es.nr*edf.GetNumDataRecords();
if (recs<=0) continue;
rate=double(duration)/double(recs);

View File

@ -61,33 +61,6 @@ const QString & GetAppRoot()
return HomeAppRoot;
}
Preference::Preference(Preferences * pref,QString code, PrefType type, QString label, QString tooltip, QVariant default_value) :
m_pref(pref), m_code(code), m_type(type), m_label(label),m_tooltip(tooltip), m_defaultValue(default_value)
{
}
void Preference::setValue(QVariant v)
{
if (!m_pref) {
qDebug() << "Bad Preferences object" << m_code;
return;
}
if (m_pref)
(*m_pref)[m_code]=v;
}
QVariant & Preference::value() {
if (!m_pref) {
qDebug() << "Bad Preferences object" << m_code;
return m_defaultValue;
}
QHash<QString,QVariant>::iterator i=m_pref->find(m_code);
if (i==m_pref->end()) {
(*m_pref)[m_code]=m_defaultValue;
return (*m_pref)[m_code];
}
return i.value();
}
Preferences::Preferences()
{

View File

@ -121,49 +121,6 @@ protected:
QString p_path;
};
enum PrefType { PT_Checkbox, PT_Spinbox, PT_Integer, PT_Number, PT_Date, PT_Time, PT_DateTime, PT_LineEdit, PT_TextEdit, PT_Dropdown };
/*! \class Preference
\brief Holds a single preference
\note This is a work in progress to clean up preferences system
*/
class Preference
{
public:
Preference() {
m_pref=NULL;
}
Preference(const Preference & copy) {
m_pref=copy.m_pref;
m_code=copy.m_code;
m_type=copy.m_type;
m_label=copy.m_label;
m_tooltip=copy.m_tooltip;
m_defaultValue=copy.m_defaultValue;
}
Preference(Preferences * pref, QString code, PrefType type, QString label, QString tooltip, QVariant default_value);
~Preference() {}
QString code() { return m_code; }
void setValue(QVariant v);
QVariant & value();
PrefType type() { return m_type; }
QString label() { return m_label; }
QString tooltip() { return m_tooltip; }
QVariant defaultValue() { return m_defaultValue; }
protected:
Preferences * m_pref;
QString m_code;
PrefType m_type;
QString m_label;
QString m_tooltip;
QVariant m_defaultValue;
};
Q_DECLARE_METATYPE(Preference)
//! \brief Main Preferences Object used throughout the application
extern Preferences PREF;

View File

@ -97,10 +97,10 @@ void Profile::DataFormatError(Machine *m)
if (!m->Purge(3478216)) { // Do not copy this line without thinking.. You will be eaten by a Grue if you do
QMessageBox::critical(NULL,QObject::tr("Purge Failed"),QObject::tr("Sorry, I could not purge this data, which means this version of SleepyHead can't start.. SleepyHead's Data folder needs to be removed manually\n\nThis folder currently resides at the following location:\n")+PREF[STR_GEN_DataFolder].toString(),QMessageBox::Ok);
exit(-1);
QApplication::exit(-1);
}
} else {
exit(-1);
QApplication::exit(-1);
}
return;
@ -909,6 +909,11 @@ const char * STR_CS_PrescribedMaxPressure="CPAPPrescribedMaxPressure";
const char * STR_CS_UntreatedAHI="UntreatedAHI";
const char * STR_CS_Notes="CPAPNotes";
const char * STR_CS_DateDiagnosed="DateDiagnosed";
const char * STR_CS_UserEventFlagging="UserEventFlagging";
const char * STR_CS_UserFlowRestriction="UserFlowRestriction";
const char * STR_CS_UserEventDuration="UserEventDuration";
const char * STR_CS_AHIWindow="AHIWindow";
const char * STR_CS_AHIReset="AHIReset";
// ImportSettings Strings
const char * STR_IS_DaySplitTime="DaySplitTime";

View File

@ -342,6 +342,11 @@ extern const char * STR_CS_PrescribedMaxPressure;
extern const char * STR_CS_UntreatedAHI;
extern const char * STR_CS_Notes;
extern const char * STR_CS_DateDiagnosed;
extern const char * STR_CS_UserEventFlagging;
extern const char * STR_CS_UserFlowRestriction;
extern const char * STR_CS_UserEventDuration;
extern const char * STR_CS_AHIWindow;
extern const char * STR_CS_AHIReset;
/*! \class CPAPSettings
\brief Profile Options relating to the CPAP settings
@ -365,6 +370,11 @@ public:
if (!m_profile->contains(STR_CS_UntreatedAHI)) (*m_profile)[STR_CS_UntreatedAHI]=0.0;
if (!m_profile->contains(STR_CS_Notes)) (*m_profile)[STR_CS_Notes]=QString();
if (!m_profile->contains(STR_CS_DateDiagnosed)) (*m_profile)[STR_CS_DateDiagnosed]=QDate();
if (!m_profile->contains(STR_CS_UserFlowRestriction)) (*m_profile)[STR_CS_UserFlowRestriction]=10.0;
if (!m_profile->contains(STR_CS_UserEventDuration)) (*m_profile)[STR_CS_UserEventDuration]=10.0;
if (!m_profile->contains(STR_CS_UserEventFlagging)) (*m_profile)[STR_CS_UserEventFlagging]=false;
if (!m_profile->contains(STR_CS_AHIWindow)) (*m_profile)[STR_CS_AHIWindow]=60.0;
if (!m_profile->contains(STR_CS_AHIReset)) (*m_profile)[STR_CS_AHIReset]=false;
}
~CPAPSettings() {}
@ -384,6 +394,11 @@ public:
double untreatedAHI() { return (*m_profile)[STR_CS_UntreatedAHI].toDouble(); }
const QString notes() { return (*m_profile)[STR_CS_Notes].toString(); }
QDate dateDiagnosed() { return (*m_profile)[STR_CS_DateDiagnosed].toDate(); }
double userFlowRestriction() { return (*m_profile)[STR_CS_UserFlowRestriction].toDouble(); }
double userEventDuration() { return (*m_profile)[STR_CS_UserEventDuration].toDouble(); }
double AHIWindow() { return (*m_profile)[STR_CS_AHIWindow].toDouble(); }
bool AHIReset() { return (*m_profile)[STR_CS_AHIReset].toBool(); }
bool userEventFlagging() { return (*m_profile)[STR_CS_UserEventFlagging].toBool(); }
//Setters
void setMode(CPAPMode mode) { (*m_profile)[STR_CS_PrescribedMode]=(int)mode; }
@ -398,6 +413,11 @@ public:
void setMaskStartDate(QDate date) { (*m_profile)[STR_CS_MaskStartDate]=date; }
void setMaskDescription(QString description) { (*m_profile)[STR_CS_MaskDescription]=description; }
void setMaskType(MaskType masktype) { (*m_profile)[STR_CS_MaskType]=(int)masktype; }
void setUserFlowRestriction(double flow) { (*m_profile)[STR_CS_UserFlowRestriction]=flow; }
void setUserEventDuration(double duration) { (*m_profile)[STR_CS_UserEventDuration]=duration; }
void setAHIWindow(double window) { (*m_profile)[STR_CS_AHIWindow]=window; }
void setAHIReset(bool reset) { (*m_profile)[STR_CS_AHIReset]=reset; }
void setUserEventFlagging(bool flagging) { (*m_profile)[STR_CS_UserEventFlagging]=flagging; }
Profile *m_profile;
};

View File

@ -153,8 +153,10 @@ Daily::Daily(QWidget *parent,gGraphView * shared)
fg->AddLayer((new gFlagsLine(CPAP_FlowLimit,QColor("black"),tr("FL"))));
fg->AddLayer((new gFlagsLine(CPAP_RERA,QColor("gold"),tr("RE"))));
fg->AddLayer((new gFlagsLine(CPAP_VSnore,QColor("red"),tr("VS"))));
fg->AddLayer((new gFlagsLine(CPAP_UserFlag1,QColor("yellow"),tr("UF1"))));
fg->AddLayer((new gFlagsLine(CPAP_UserFlag2,QColor("green"),tr("UF2"))));
if (PROFILE.cpap->userEventFlagging()) {
fg->AddLayer((new gFlagsLine(CPAP_UserFlag1,QColor("yellow"),tr("UF1"))));
fg->AddLayer((new gFlagsLine(CPAP_UserFlag2,QColor("green"),tr("UF2"))));
}
//fg->AddLayer((new gFlagsLine(PRS1_0B,QColor("dark green"),tr("U0B"))));
fg->AddLayer((new gFlagsLine(CPAP_VSnore2,QColor("red"),tr("VS2"))));
SF->setBlockZoom(true);
@ -189,8 +191,10 @@ Daily::Daily(QWidget *parent,gGraphView * shared)
FRW->AddLayer(AddCPAP(new gLineOverlayBar(CPAP_FlowLimit,QColor("black"),tr("FL"))));
FRW->AddLayer(AddCPAP(los->add(new gLineOverlayBar(CPAP_Obstructive,QColor("#40c0ff"),tr("OA")))));
FRW->AddLayer(AddCPAP(los->add(new gLineOverlayBar(CPAP_ClearAirway,QColor("purple"),tr("CA")))));
FRW->AddLayer(AddCPAP(new gLineOverlayBar(CPAP_UserFlag1,QColor("yellow"),tr("U1"),FT_Bar)));
FRW->AddLayer(AddCPAP(new gLineOverlayBar(CPAP_UserFlag2,QColor("orange"),tr("U2"),FT_Bar)));
if (PROFILE.cpap->userEventFlagging()) {
FRW->AddLayer(AddCPAP(new gLineOverlayBar(CPAP_UserFlag1,QColor("yellow"),tr("U1"),FT_Bar)));
FRW->AddLayer(AddCPAP(new gLineOverlayBar(CPAP_UserFlag2,QColor("orange"),tr("U2"),FT_Bar)));
}
FRW->AddLayer(AddOXI(new gLineOverlayBar(OXI_SPO2Drop,QColor("red"),tr("O2"))));
FRW->AddLayer(AddOXI(new gLineOverlayBar(OXI_PulseChange,QColor("blue"),tr("PC"),FT_Dot)));
@ -437,6 +441,7 @@ void Daily::UpdateEventsTree(QTreeWidget *tree,Day *day)
QHash<ChannelID,QTreeWidgetItem *> mcroot;
QHash<ChannelID,int> mccnt;
int total_events=0;
bool userflags=p_profile->cpap->userEventFlagging();
for (QVector<Session *>::iterator s=day->begin();s!=day->end();s++) {
if (!(*s)->enabled()) continue;
@ -460,6 +465,9 @@ void Daily::UpdateEventsTree(QTreeWidget *tree,Day *day)
&& (code!=CPAP_PressurePulse)
&& (code!=CPAP_VSnore2)
&& (code!=CPAP_VSnore)) continue;
if (!userflags && ((code==CPAP_UserFlag1) || (code==CPAP_UserFlag2))) continue;
QTreeWidgetItem *mcr;
if (mcroot.find(code)==mcroot.end()) {
int cnt=day->count(code);
@ -657,8 +665,7 @@ void Daily::Load(QDate date)
"<body leftmargin=0 rightmargin=0 topmargin=0 marginwidth=0 marginheight=0>"
"<table cellspacing=0 cellpadding=1 border=0 width='100%'>\n";
QString tmp;
//const int gwwidth=240;
//const int gwheight=100;
UpdateOXIGraphs(oxi);
UpdateCPAPGraphs(cpap);
UpdateEventsTree(ui->treeWidget,cpap);
@ -667,51 +674,20 @@ void Daily::Load(QDate date)
snapGV->setDay(cpap);
GraphView->ResetBounds(false);
//GraphView->setEmptyText(tr("No Data")); //tr("No data for ")+date.toString(Qt::SystemLocaleLongDate));
if (!cpap && !oxi) {
//splitter->setMinimumHeight(0);
scrollbar->hide();
// GraphView->hide();
} else {
//NoData->hide();
// GraphView->show();
scrollbar->show();
}
//GraphView->redraw();
//snapGV->redraw();
// for (int i=0;i<GraphView->size();i++) {
// QString title=(*GraphView)[i]->title();
// bool empty=(*GraphView)[i]->isEmpty();
// if (!empty) graphsAvailable++;
// GraphToggles[title]->setVisible(!empty);
// }
// emptyToggleArea->setVisible(graphsAvailable==0);
//ui->graphVisibilityToggleArea->setVisible(graphsAvailable>0);
//RedrawGraphs();
QString modestr;
//float iap90,eap90;
CPAPMode mode=MODE_UNKNOWN;
QString a;
bool isBrick=false;
//ui->graphVisibilityToggleArea->setVisible(true);
updateGraphCombo();
//int graphsAvailable=GraphView->visibleGraphs();
// if (graphsAvailable>0) {
// GraphView->setCubeImage(images["sheep"]);
// GraphView->setEmptyText(tr("Graphs Switched Off"));
// } else {
// GraphView->setCubeImage(images["nodata"]);
// GraphView->setEmptyText(tr("No Data"));
// emptyToggleArea->setText("No graph data available for this day");
// }
if (cpap) {
if (GraphView->isEmpty()) {
@ -867,6 +843,12 @@ void Daily::Load(QDate date)
}
html+="</tr>";
if (PROFILE.cpap->userEventFlagging()) {
EventDataType uf=cpap->count(CPAP_UserFlag1) / cpap->hours();
if (uf>0)
html+=QString("<tr><td colspan=5>User flag index=%1</td></tr>").arg(uf,0,'f',2);
}
// Note, this may not be a problem since Qt bug 13622 was discovered
// as it only relates to text drawing, which the Pie chart does not do
@ -1762,7 +1744,7 @@ void Daily::updateCube()
if (ui->graphCombo->count()>0) {
GraphView->setEmptyText(tr("No Graphs On!"));
GraphView->setCubeImage(images["sheep"]);
GraphView->setCubeImage(images["nographs"]);
} else {
GraphView->setEmptyText("No Data");

View File

@ -248,7 +248,7 @@
</size>
</property>
<property name="currentIndex">
<number>2</number>
<number>0</number>
</property>
<property name="movable">
<bool>true</bool>
@ -773,14 +773,10 @@
<item>
<widget class="QToolButton" name="resetLayoutButton">
<property name="toolTip">
<string>Reset the graphs to uniform sizes</string>
<string>Reset the graph heights to uniform sizes</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="Resources.qrc">
<normaloff>:/icons/refresh.png</normaloff>:/icons/refresh.png</iconset>
<string>Reset</string>
</property>
<property name="autoRaise">
<bool>true</bool>

View File

@ -48,7 +48,7 @@ Important: One id code per item, DO NOT CHANGE ID NUMBERS!!!
<channel id="0x1110" class="data" name="IPAPLo" details="Inspiratory Pressure Lo" label="IPAP" unit="cmH20" color="grey"/>
<channel id="0x1111" class="data" name="IPAPHi" details="Inspiratory Pressure Hi" label="IPAP" unit="cmH20" color="grey"/>
<channel id="0x1112" class="data" name="RespEvent" details="Respiratory Events" label="Resp Events" unit="" color="black"/>
<channel id="0x1113" class="data" name="FLG" details="Flow Limit Graph" label="Flow Limit" unit="0&lt;n&lt;1" color="dark grey"/>
<channel id="0x1113" class="data" name="FLG" details="Flow Limit Graph" label="Flow Limit" unit="0-1" color="dark grey"/>
<channel id="0x1114" class="data" name="TgMV" details="Target Minute Ventilation" label="Target Vent." unit="" color="dark cyan"/>
<channel id="0x1115" class="data" name="MaxLeak" details="Maximum Leak" label="MaxLeaks" unit="L/min" color="dark red"/>
<channel id="0x1116" class="data" name="AHI" details="Apnea / Hypopnea Index" label="AHI/Hr" unit="events/hr" color="dark red"/>
@ -69,7 +69,7 @@ Important: One id code per item, DO NOT CHANGE ID NUMBERS!!!
<channel id="0x1158" class="data" name="PRS1_10" details="Unknown 10" label="U10" unit="?" color="black"/>
<channel id="0x1159" class="data" name="PRS1_12" details="PRS1 Unknown 12" label="U12" unit="" color="black"/>
<channel id="0x1160" class="data" name="RMS9_E01" details="RMS9 Empty 1" label="E01" unit="" color="black"/>
<channel id="0x1161" class="data" name="RMS9_E02" details="RMS9 Empty 2" label="U02" unit="" color="black"/>
<channel id="0x1161" class="data" name="RMS9_E02" details="RMS9 Empty 2" label="E02" unit="" color="black"/>
<channel id="0x1162" class="data" name="SetPressure" details="Set Pressure" label="Pressure" unit="" color="black"/>
<channel id="0x1163" class="data" name="BrokenSummary" details="Broken Summary" label="Broken Summary" unit="" color="black"/>
<channel id="0x1164" class="data" name="BrokenWaveform" details="Broken Waveform" label="Broken Waveform" unit="" color="black"/>

View File

@ -11,16 +11,19 @@
<p><b>New Features:</b></br>
<list>
<li>Auto-Updater for Windows & Mac Platforms</li>
<li>SleepLib database improvements, and lots of other underneath stuff and code cleanups you don't see.</li>
<li>SleepLib database improvements, and lots of other underneath stuff, code cleanups and optimisations you don't see.</li>
<li>Session Hiding capabilities, by clicking on the toggle button down the bottom of Daily views details panel</li>
<li>New Statistics page showing some more useful data.</li>
<li>Prescription Settings list in statistics shows recent machine settings changes, and jumps to overview when clicked on</li>
<li>Welcome page has become a Help Browser.</li>
<li>New Navigation Panel on the right side, now accessible from all tabs. It can be hidden to reclaim screen space.</li>
<li>New Favourites tab in this right panel for bookmarking days and quickly finding them again.</li>
<li>New Bookmarks tab in this right panel for showing days with bookmarks, allowing you to quickly jump to them.</li>
<li>New Records tab to show some best/worst entries, which have links going directly to the related day or overview range.</li>
<li>Daily reports bookmarked areas show oximetry data when available.</li>
<li>Daily (printed) reports show oximetry data when showing bookmarks.</li>
<li>Can print from both the Statistics & Help Browser pages.</li>
<li>New Context cube can be switched on to make empty pages more attractive.</li>
<li>Option to automatically maintain backup folder for ResMed users. (on by default)</li>
<li>Compression options to save disk space for SleepyHead data and backups.</li>
<li>New Context cube to make empty pages more attractive.. Yes you can switch it off. No it doesn't take much resources.</li>
<li>Plenty of other bug fixes, including more oximetry fixes.</li>
</list></p>
<p><b>Important Information:</b><br/>

View File

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

View File

@ -105,36 +105,47 @@ int main(int argc, char *argv[])
a.setApplicationName("SleepyHead");
initialize();
////////////////////////////////////////////////////////////////////////////////////////////
// Register Importer Modules
////////////////////////////////////////////////////////////////////////////////////////////
PRS1Loader::Register();
CMS50Loader::Register();
ZEOLoader::Register();
//ZEOLoader::Register();
ResmedLoader::Register();
IntellipapLoader::Register();
// Scan for user profiles
Profiles::Scan();
qRegisterMetaType<Preference>("Preference");
//qRegisterMetaType<Preference>("Preference");
PREF["AppName"]=QObject::tr("SleepyHead");
// Skip login screen, unless asked not to on the command line
bool skip_login=(PREF.ExistsAndTrue("SkipLoginScreen"));
if (force_login_screen) skip_login=false;
// Todo: Make a wrapper for Preference settings, like Profile settings have..
QDateTime lastchecked, today=QDateTime::currentDateTime();
if (!PREF.contains(STR_GEN_UpdatesAutoCheck)) {
PREF[STR_GEN_UpdatesAutoCheck]=true;
PREF[STR_GEN_UpdateCheckFrequency]=7;
}
////////////////////////////////////////////////////////////////////////////////////////////
// Check when last checked for updates..
////////////////////////////////////////////////////////////////////////////////////////////
bool check_updates=false;
if (PREF[STR_GEN_UpdatesAutoCheck].toBool()) {
int update_frequency=PREF[STR_GEN_UpdateCheckFrequency].toInt();
int days=1000;
// p_pref ->Get
lastchecked=PREF[STR_GEN_UpdatesLastChecked].toDateTime();
if (PREF.contains(STR_GEN_UpdatesLastChecked)) {
days=lastchecked.secsTo(today);
days/=86400;
};
if (days>update_frequency) {
//QMessageBox::information(NULL,"Check for updates","Placeholder. Would automatically check for updates here.",QMessageBox::Ok);
check_updates=true;
//PREF[STR_GEN_UpdatesLastChecked]=today;
}
}
@ -173,14 +184,13 @@ int main(int argc, char *argv[])
p_profile=Profiles::Get(PREF[STR_GEN_Profile].toString());
qDebug() << "Selected Profile" << p_profile->user->userName();
//if (!PREF.Exists(STR_GEN_Profile)) PREF[STR_GEN_Profile]=getUserName();
//int id=QFontDatabase::addApplicationFont(":/fonts/FreeSans.ttf");
/* QFontDatabase fdb;
QStringList ffam=fdb.families();
for (QStringList::iterator i=ffam.begin();i!=ffam.end();i++) {
qDebug() << "Loaded Font: " << (*i);
} */
// int id=QFontDatabase::addApplicationFont(":/fonts/FreeSans.ttf");
// QFontDatabase fdb;
// QStringList ffam=fdb.families();
// for (QStringList::iterator i=ffam.begin();i!=ffam.end();i++) {
// qDebug() << "Loaded Font: " << (*i);
// }
if (!PREF.contains("Fonts_Application_Name")) {
PREF["Fonts_Application_Name"]="Sans Serif";

View File

@ -151,6 +151,7 @@ MainWindow::MainWindow(QWidget *parent) :
ui->recordsBox->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
ui->summaryView->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
ui->webView->page()->setLinkDelegationPolicy(QWebPage::DelegateExternalLinks);
ui->bookmarkView->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
ui->toolBox->setStyleSheet(
"QToolBox::tab {"
"background: #6789ab;"
@ -278,8 +279,11 @@ void MainWindow::on_action_Import_Data_triggered()
}
if (res==2) return;
}
if (asknew) {
mainwin->Notify("Please remember to point the importer at the root folder or drive letter of your data-card, and not a subfolder.","Import Reminder",8000);
}
QStringList importFrom=importLocations;
QStringList importFrom;
if (asknew) {
QFileDialog w;
@ -311,7 +315,7 @@ void MainWindow::on_action_Import_Data_triggered()
//addnew=true;
}
}
}
} else importFrom=importLocations;
int successful=false;
@ -559,8 +563,9 @@ void MainWindow::on_summaryButton_clicked()
if (mach.size()==0) {
html+="<table cellpadding=2 cellspacing=0 border=0 width=100% height=70%>";
html+="<tr><td align=center><h1>Please Import Some Data</h1><br/><i>SleepyHead is pretty much useless without it.</i><br/>First import can take a few minutes.</td></tr></table>";
html+="<table cellpadding=2 cellspacing=0 border=0 width=100% height=60%>";
QString datacard;
html+="<tr><td align=center><h1>Please Import Some Data</h1><i>SleepyHead is pretty much useless without it.</i><br/><p>It might be a good idea to check preferences first,</br>as there are some options that affect import.</p><p>First import can take a few minutes.</p></td></tr></table>";
html+=htmlFooter();
ui->summaryView->setHtml(html);
return;
@ -581,6 +586,8 @@ void MainWindow::on_summaryButton_clicked()
} else {
ahitxt=tr("AHI");
}
int decimals=2;
html+="<div align=center>";
html+=QString("<table cellpadding=2 cellspacing=0 border=1 width=90%>");
if (cpapdays==0) {
@ -603,30 +610,30 @@ void MainWindow::on_summaryButton_clicked()
.arg(tr("Details")).arg(tr("Most Recent")).arg(tr("Last 7 Days")).arg(tr("Last 30 Days")).arg(tr("Last 6 months")).arg(tr("Last Year"));
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
.arg(ahitxt)
.arg(calcAHI(lastcpap,lastcpap),0,'f',3)
.arg(calcAHI(cpapweek,lastcpap),0,'f',3)
.arg(calcAHI(cpapmonth,lastcpap),0,'f',3)
.arg(calcAHI(cpap6month,lastcpap),0,'f',3)
.arg(calcAHI(cpapyear,lastcpap),0,'f',3);
.arg(calcAHI(lastcpap,lastcpap),0,'f',decimals)
.arg(calcAHI(cpapweek,lastcpap),0,'f',decimals)
.arg(calcAHI(cpapmonth,lastcpap),0,'f',decimals)
.arg(calcAHI(cpap6month,lastcpap),0,'f',decimals)
.arg(calcAHI(cpapyear,lastcpap),0,'f',decimals);
if (PROFILE.calcCount(CPAP_RERA,MT_CPAP,cpapyear,lastcpap)) {
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
.arg(tr("RERA Index"))
.arg(PROFILE.calcCount(CPAP_RERA,MT_CPAP,lastcpap,lastcpap)/PROFILE.calcHours(MT_CPAP,lastcpap,lastcpap),0,'f',3)
.arg(PROFILE.calcCount(CPAP_RERA,MT_CPAP,cpapweek,lastcpap)/PROFILE.calcHours(MT_CPAP,cpapweek,lastcpap),0,'f',3)
.arg(PROFILE.calcCount(CPAP_RERA,MT_CPAP,cpapmonth,lastcpap)/PROFILE.calcHours(MT_CPAP,cpapmonth,lastcpap),0,'f',3)
.arg(PROFILE.calcCount(CPAP_RERA,MT_CPAP,cpap6month,lastcpap)/PROFILE.calcHours(MT_CPAP,cpap6month,lastcpap),0,'f',3)
.arg(PROFILE.calcCount(CPAP_RERA,MT_CPAP,cpapyear,lastcpap)/PROFILE.calcHours(MT_CPAP,cpapyear,lastcpap),0,'f',3);
.arg(PROFILE.calcCount(CPAP_RERA,MT_CPAP,lastcpap,lastcpap)/PROFILE.calcHours(MT_CPAP,lastcpap,lastcpap),0,'f',decimals)
.arg(PROFILE.calcCount(CPAP_RERA,MT_CPAP,cpapweek,lastcpap)/PROFILE.calcHours(MT_CPAP,cpapweek,lastcpap),0,'f',decimals)
.arg(PROFILE.calcCount(CPAP_RERA,MT_CPAP,cpapmonth,lastcpap)/PROFILE.calcHours(MT_CPAP,cpapmonth,lastcpap),0,'f',decimals)
.arg(PROFILE.calcCount(CPAP_RERA,MT_CPAP,cpap6month,lastcpap)/PROFILE.calcHours(MT_CPAP,cpap6month,lastcpap),0,'f',decimals)
.arg(PROFILE.calcCount(CPAP_RERA,MT_CPAP,cpapyear,lastcpap)/PROFILE.calcHours(MT_CPAP,cpapyear,lastcpap),0,'f',decimals);
}
if (PROFILE.calcCount(CPAP_FlowLimit,MT_CPAP,cpapyear,lastcpap)) {
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
.arg(tr("Flow Limit Index"))
.arg(PROFILE.calcCount(CPAP_FlowLimit,MT_CPAP,lastcpap,lastcpap)/PROFILE.calcHours(MT_CPAP,lastcpap,lastcpap),0,'f',3)
.arg(PROFILE.calcCount(CPAP_FlowLimit,MT_CPAP,cpapweek,lastcpap)/PROFILE.calcHours(MT_CPAP,cpapweek,lastcpap),0,'f',3)
.arg(PROFILE.calcCount(CPAP_FlowLimit,MT_CPAP,cpapmonth,lastcpap)/PROFILE.calcHours(MT_CPAP,cpapmonth,lastcpap),0,'f',3)
.arg(PROFILE.calcCount(CPAP_FlowLimit,MT_CPAP,cpap6month,lastcpap)/PROFILE.calcHours(MT_CPAP,cpap6month,lastcpap),0,'f',3)
.arg(PROFILE.calcCount(CPAP_FlowLimit,MT_CPAP,cpapyear,lastcpap)/PROFILE.calcHours(MT_CPAP,cpapyear,lastcpap),0,'f',3);
.arg(PROFILE.calcCount(CPAP_FlowLimit,MT_CPAP,lastcpap,lastcpap)/PROFILE.calcHours(MT_CPAP,lastcpap,lastcpap),0,'f',decimals)
.arg(PROFILE.calcCount(CPAP_FlowLimit,MT_CPAP,cpapweek,lastcpap)/PROFILE.calcHours(MT_CPAP,cpapweek,lastcpap),0,'f',decimals)
.arg(PROFILE.calcCount(CPAP_FlowLimit,MT_CPAP,cpapmonth,lastcpap)/PROFILE.calcHours(MT_CPAP,cpapmonth,lastcpap),0,'f',decimals)
.arg(PROFILE.calcCount(CPAP_FlowLimit,MT_CPAP,cpap6month,lastcpap)/PROFILE.calcHours(MT_CPAP,cpap6month,lastcpap),0,'f',decimals)
.arg(PROFILE.calcCount(CPAP_FlowLimit,MT_CPAP,cpapyear,lastcpap)/PROFILE.calcHours(MT_CPAP,cpapyear,lastcpap),0,'f',decimals);
}
@ -642,55 +649,55 @@ void MainWindow::on_summaryButton_clicked()
if (cpapmode>=MODE_BIPAP) {
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
.arg(tr("Min EPAP"))
.arg(p_profile->calcMin(CPAP_EPAP,MT_CPAP),0,'f',3)
.arg(p_profile->calcMin(CPAP_EPAP,MT_CPAP,cpapweek,lastcpap),0,'f',3)
.arg(p_profile->calcMin(CPAP_EPAP,MT_CPAP,cpapmonth,lastcpap),0,'f',3)
.arg(p_profile->calcMin(CPAP_EPAP,MT_CPAP,cpap6month,lastcpap),0,'f',3)
.arg(p_profile->calcMin(CPAP_EPAP,MT_CPAP,cpapyear,lastcpap),0,'f',3);
.arg(p_profile->calcMin(CPAP_EPAP,MT_CPAP),0,'f',decimals)
.arg(p_profile->calcMin(CPAP_EPAP,MT_CPAP,cpapweek,lastcpap),0,'f',decimals)
.arg(p_profile->calcMin(CPAP_EPAP,MT_CPAP,cpapmonth,lastcpap),0,'f',decimals)
.arg(p_profile->calcMin(CPAP_EPAP,MT_CPAP,cpap6month,lastcpap),0,'f',decimals)
.arg(p_profile->calcMin(CPAP_EPAP,MT_CPAP,cpapyear,lastcpap),0,'f',decimals);
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
.arg(tr("95% EPAP"))
.arg(p_profile->calcPercentile(CPAP_EPAP,percentile,MT_CPAP),0,'f',3)
.arg(p_profile->calcPercentile(CPAP_EPAP,percentile,MT_CPAP,cpapweek,lastcpap),0,'f',3)
.arg(p_profile->calcPercentile(CPAP_EPAP,percentile,MT_CPAP,cpapmonth,lastcpap),0,'f',3)
.arg(p_profile->calcPercentile(CPAP_EPAP,percentile,MT_CPAP,cpap6month,lastcpap),0,'f',3)
.arg(p_profile->calcPercentile(CPAP_EPAP,percentile,MT_CPAP,cpapyear,lastcpap),0,'f',3);
.arg(p_profile->calcPercentile(CPAP_EPAP,percentile,MT_CPAP),0,'f',decimals)
.arg(p_profile->calcPercentile(CPAP_EPAP,percentile,MT_CPAP,cpapweek,lastcpap),0,'f',decimals)
.arg(p_profile->calcPercentile(CPAP_EPAP,percentile,MT_CPAP,cpapmonth,lastcpap),0,'f',decimals)
.arg(p_profile->calcPercentile(CPAP_EPAP,percentile,MT_CPAP,cpap6month,lastcpap),0,'f',decimals)
.arg(p_profile->calcPercentile(CPAP_EPAP,percentile,MT_CPAP,cpapyear,lastcpap),0,'f',decimals);
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
.arg(tr("Max IPAP"))
.arg(p_profile->calcMax(CPAP_IPAP,MT_CPAP),0,'f',3)
.arg(p_profile->calcMax(CPAP_IPAP,MT_CPAP,cpapweek,lastcpap),0,'f',3)
.arg(p_profile->calcMax(CPAP_IPAP,MT_CPAP,cpapmonth,lastcpap),0,'f',3)
.arg(p_profile->calcMax(CPAP_IPAP,MT_CPAP,cpap6month,lastcpap),0,'f',3)
.arg(p_profile->calcMax(CPAP_IPAP,MT_CPAP,cpapyear,lastcpap),0,'f',3);
.arg(p_profile->calcMax(CPAP_IPAP,MT_CPAP),0,'f',decimals)
.arg(p_profile->calcMax(CPAP_IPAP,MT_CPAP,cpapweek,lastcpap),0,'f',decimals)
.arg(p_profile->calcMax(CPAP_IPAP,MT_CPAP,cpapmonth,lastcpap),0,'f',decimals)
.arg(p_profile->calcMax(CPAP_IPAP,MT_CPAP,cpap6month,lastcpap),0,'f',decimals)
.arg(p_profile->calcMax(CPAP_IPAP,MT_CPAP,cpapyear,lastcpap),0,'f',decimals);
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
.arg(tr("95% IPAP"))
.arg(p_profile->calcPercentile(CPAP_IPAP,percentile,MT_CPAP),0,'f',3)
.arg(p_profile->calcPercentile(CPAP_IPAP,percentile,MT_CPAP,cpapweek,lastcpap),0,'f',3)
.arg(p_profile->calcPercentile(CPAP_IPAP,percentile,MT_CPAP,cpapmonth,lastcpap),0,'f',3)
.arg(p_profile->calcPercentile(CPAP_IPAP,percentile,MT_CPAP,cpap6month,lastcpap),0,'f',3)
.arg(p_profile->calcPercentile(CPAP_IPAP,percentile,MT_CPAP,cpapyear,lastcpap),0,'f',3);
.arg(p_profile->calcPercentile(CPAP_IPAP,percentile,MT_CPAP),0,'f',decimals)
.arg(p_profile->calcPercentile(CPAP_IPAP,percentile,MT_CPAP,cpapweek,lastcpap),0,'f',decimals)
.arg(p_profile->calcPercentile(CPAP_IPAP,percentile,MT_CPAP,cpapmonth,lastcpap),0,'f',decimals)
.arg(p_profile->calcPercentile(CPAP_IPAP,percentile,MT_CPAP,cpap6month,lastcpap),0,'f',decimals)
.arg(p_profile->calcPercentile(CPAP_IPAP,percentile,MT_CPAP,cpapyear,lastcpap),0,'f',decimals);
} else if (cpapmode>=MODE_APAP) {
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
.arg(tr("Average Pressure"))
.arg(p_profile->calcWavg(CPAP_Pressure,MT_CPAP),0,'f',3)
.arg(p_profile->calcWavg(CPAP_Pressure,MT_CPAP,cpapweek,lastcpap),0,'f',3)
.arg(p_profile->calcWavg(CPAP_Pressure,MT_CPAP,cpapmonth,lastcpap),0,'f',3)
.arg(p_profile->calcWavg(CPAP_Pressure,MT_CPAP,cpap6month,lastcpap),0,'f',3)
.arg(p_profile->calcWavg(CPAP_Pressure,MT_CPAP,cpapyear,lastcpap),0,'f',3);
.arg(p_profile->calcWavg(CPAP_Pressure,MT_CPAP),0,'f',decimals)
.arg(p_profile->calcWavg(CPAP_Pressure,MT_CPAP,cpapweek,lastcpap),0,'f',decimals)
.arg(p_profile->calcWavg(CPAP_Pressure,MT_CPAP,cpapmonth,lastcpap),0,'f',decimals)
.arg(p_profile->calcWavg(CPAP_Pressure,MT_CPAP,cpap6month,lastcpap),0,'f',decimals)
.arg(p_profile->calcWavg(CPAP_Pressure,MT_CPAP,cpapyear,lastcpap),0,'f',decimals);
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
.arg(tr("95% Pressure"))
.arg(p_profile->calcPercentile(CPAP_Pressure,percentile,MT_CPAP),0,'f',3)
.arg(p_profile->calcPercentile(CPAP_Pressure,percentile,MT_CPAP,cpapweek,lastcpap),0,'f',3)
.arg(p_profile->calcPercentile(CPAP_Pressure,percentile,MT_CPAP,cpapmonth,lastcpap),0,'f',3)
.arg(p_profile->calcPercentile(CPAP_Pressure,percentile,MT_CPAP,cpap6month,lastcpap),0,'f',3)
.arg(p_profile->calcPercentile(CPAP_Pressure,percentile,MT_CPAP,cpapyear,lastcpap),0,'f',3);
.arg(p_profile->calcPercentile(CPAP_Pressure,percentile,MT_CPAP),0,'f',decimals)
.arg(p_profile->calcPercentile(CPAP_Pressure,percentile,MT_CPAP,cpapweek,lastcpap),0,'f',decimals)
.arg(p_profile->calcPercentile(CPAP_Pressure,percentile,MT_CPAP,cpapmonth,lastcpap),0,'f',decimals)
.arg(p_profile->calcPercentile(CPAP_Pressure,percentile,MT_CPAP,cpap6month,lastcpap),0,'f',decimals)
.arg(p_profile->calcPercentile(CPAP_Pressure,percentile,MT_CPAP,cpapyear,lastcpap),0,'f',decimals);
} else {
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
.arg(tr("Pressure"))
.arg(p_profile->calcSettingsMin(CPAP_Pressure,MT_CPAP),0,'f',3)
.arg(p_profile->calcSettingsMin(CPAP_Pressure,MT_CPAP,cpapweek,lastcpap),0,'f',3)
.arg(p_profile->calcSettingsMin(CPAP_Pressure,MT_CPAP,cpapmonth,lastcpap),0,'f',3)
.arg(p_profile->calcSettingsMin(CPAP_Pressure,MT_CPAP,cpap6month,lastcpap),0,'f',3)
.arg(p_profile->calcSettingsMin(CPAP_Pressure,MT_CPAP,cpapyear,lastcpap),0,'f',3);
.arg(p_profile->calcSettingsMin(CPAP_Pressure,MT_CPAP),0,'f',decimals)
.arg(p_profile->calcSettingsMin(CPAP_Pressure,MT_CPAP,cpapweek,lastcpap),0,'f',decimals)
.arg(p_profile->calcSettingsMin(CPAP_Pressure,MT_CPAP,cpapmonth,lastcpap),0,'f',decimals)
.arg(p_profile->calcSettingsMin(CPAP_Pressure,MT_CPAP,cpap6month,lastcpap),0,'f',decimals)
.arg(p_profile->calcSettingsMin(CPAP_Pressure,MT_CPAP,cpapyear,lastcpap),0,'f',decimals);
}
//html+="<tr><td colspan=6>TODO: 90% pressure.. Any point showing if this is all CPAP?</td></tr>";
@ -702,18 +709,18 @@ void MainWindow::on_summaryButton_clicked()
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
.arg(tr("Average %1").arg(schema::channel[leak].label()))
.arg(p_profile->calcWavg(leak,MT_CPAP),0,'f',3)
.arg(p_profile->calcWavg(leak,MT_CPAP,cpapweek,lastcpap),0,'f',3)
.arg(p_profile->calcWavg(leak,MT_CPAP,cpapmonth,lastcpap),0,'f',3)
.arg(p_profile->calcWavg(leak,MT_CPAP,cpap6month,lastcpap),0,'f',3)
.arg(p_profile->calcWavg(leak,MT_CPAP,cpapyear,lastcpap),0,'f',3);
.arg(p_profile->calcWavg(leak,MT_CPAP),0,'f',decimals)
.arg(p_profile->calcWavg(leak,MT_CPAP,cpapweek,lastcpap),0,'f',decimals)
.arg(p_profile->calcWavg(leak,MT_CPAP,cpapmonth,lastcpap),0,'f',decimals)
.arg(p_profile->calcWavg(leak,MT_CPAP,cpap6month,lastcpap),0,'f',decimals)
.arg(p_profile->calcWavg(leak,MT_CPAP,cpapyear,lastcpap),0,'f',decimals);
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
.arg(tr("%1% %2").arg(percentile*100.0f,0,'f',0).arg(schema::channel[leak].label()))
.arg(p_profile->calcPercentile(leak,percentile,MT_CPAP),0,'f',3)
.arg(p_profile->calcPercentile(leak,percentile,MT_CPAP,cpapweek,lastcpap),0,'f',3)
.arg(p_profile->calcPercentile(leak,percentile,MT_CPAP,cpapmonth,lastcpap),0,'f',3)
.arg(p_profile->calcPercentile(leak,percentile,MT_CPAP,cpap6month,lastcpap),0,'f',3)
.arg(p_profile->calcPercentile(leak,percentile,MT_CPAP,cpapyear,lastcpap),0,'f',3);
.arg(p_profile->calcPercentile(leak,percentile,MT_CPAP),0,'f',decimals)
.arg(p_profile->calcPercentile(leak,percentile,MT_CPAP,cpapweek,lastcpap),0,'f',decimals)
.arg(p_profile->calcPercentile(leak,percentile,MT_CPAP,cpapmonth,lastcpap),0,'f',decimals)
.arg(p_profile->calcPercentile(leak,percentile,MT_CPAP,cpap6month,lastcpap),0,'f',decimals)
.arg(p_profile->calcPercentile(leak,percentile,MT_CPAP,cpapyear,lastcpap),0,'f',decimals);
}
}
int oxisize=oximeters.size();
@ -741,60 +748,60 @@ void MainWindow::on_summaryButton_clicked()
if (oxiyear<firstoxi) oxiyear=firstoxi;
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
.arg(tr("Average SpO2"))
.arg(p_profile->calcWavg(OXI_SPO2,MT_OXIMETER),0,'f',3)
.arg(p_profile->calcWavg(OXI_SPO2,MT_OXIMETER,oxiweek,lastoxi),0,'f',3)
.arg(p_profile->calcWavg(OXI_SPO2,MT_OXIMETER,oximonth,lastoxi),0,'f',3)
.arg(p_profile->calcWavg(OXI_SPO2,MT_OXIMETER,oxi6month,lastoxi),0,'f',3)
.arg(p_profile->calcWavg(OXI_SPO2,MT_OXIMETER,oxiyear,lastoxi),0,'f',3);
.arg(p_profile->calcWavg(OXI_SPO2,MT_OXIMETER),0,'f',decimals)
.arg(p_profile->calcWavg(OXI_SPO2,MT_OXIMETER,oxiweek,lastoxi),0,'f',decimals)
.arg(p_profile->calcWavg(OXI_SPO2,MT_OXIMETER,oximonth,lastoxi),0,'f',decimals)
.arg(p_profile->calcWavg(OXI_SPO2,MT_OXIMETER,oxi6month,lastoxi),0,'f',decimals)
.arg(p_profile->calcWavg(OXI_SPO2,MT_OXIMETER,oxiyear,lastoxi),0,'f',decimals);
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
.arg(tr("Minimum SpO2"))
.arg(p_profile->calcMin(OXI_SPO2,MT_OXIMETER),0,'f',3)
.arg(p_profile->calcMin(OXI_SPO2,MT_OXIMETER,oxiweek,lastoxi),0,'f',3)
.arg(p_profile->calcMin(OXI_SPO2,MT_OXIMETER,oximonth,lastoxi),0,'f',3)
.arg(p_profile->calcMin(OXI_SPO2,MT_OXIMETER,oxi6month,lastoxi),0,'f',3)
.arg(p_profile->calcMin(OXI_SPO2,MT_OXIMETER,oxiyear,lastoxi),0,'f',3);
.arg(p_profile->calcMin(OXI_SPO2,MT_OXIMETER),0,'f',decimals)
.arg(p_profile->calcMin(OXI_SPO2,MT_OXIMETER,oxiweek,lastoxi),0,'f',decimals)
.arg(p_profile->calcMin(OXI_SPO2,MT_OXIMETER,oximonth,lastoxi),0,'f',decimals)
.arg(p_profile->calcMin(OXI_SPO2,MT_OXIMETER,oxi6month,lastoxi),0,'f',decimals)
.arg(p_profile->calcMin(OXI_SPO2,MT_OXIMETER,oxiyear,lastoxi),0,'f',decimals);
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
.arg(tr("SpO2 Events / Hour"))
.arg(p_profile->calcCount(OXI_SPO2Drop,MT_OXIMETER)/p_profile->calcHours(MT_OXIMETER),0,'f',3)
.arg(p_profile->calcCount(OXI_SPO2Drop,MT_OXIMETER,oxiweek,lastoxi)/p_profile->calcHours(MT_OXIMETER,oxiweek,lastoxi),0,'f',3)
.arg(p_profile->calcCount(OXI_SPO2Drop,MT_OXIMETER,oximonth,lastoxi)/p_profile->calcHours(MT_OXIMETER,oximonth,lastoxi),0,'f',3)
.arg(p_profile->calcCount(OXI_SPO2Drop,MT_OXIMETER,oxi6month,lastoxi)/p_profile->calcHours(MT_OXIMETER,oxi6month,lastoxi),0,'f',3)
.arg(p_profile->calcCount(OXI_SPO2Drop,MT_OXIMETER,oxiyear,lastoxi)/p_profile->calcHours(MT_OXIMETER,oxiyear,lastoxi),0,'f',3);
.arg(p_profile->calcCount(OXI_SPO2Drop,MT_OXIMETER)/p_profile->calcHours(MT_OXIMETER),0,'f',decimals)
.arg(p_profile->calcCount(OXI_SPO2Drop,MT_OXIMETER,oxiweek,lastoxi)/p_profile->calcHours(MT_OXIMETER,oxiweek,lastoxi),0,'f',decimals)
.arg(p_profile->calcCount(OXI_SPO2Drop,MT_OXIMETER,oximonth,lastoxi)/p_profile->calcHours(MT_OXIMETER,oximonth,lastoxi),0,'f',decimals)
.arg(p_profile->calcCount(OXI_SPO2Drop,MT_OXIMETER,oxi6month,lastoxi)/p_profile->calcHours(MT_OXIMETER,oxi6month,lastoxi),0,'f',decimals)
.arg(p_profile->calcCount(OXI_SPO2Drop,MT_OXIMETER,oxiyear,lastoxi)/p_profile->calcHours(MT_OXIMETER,oxiyear,lastoxi),0,'f',decimals);
html+=QString("<tr><td>%1</td><td>%2\%</td><td>%3\%</td><td>%4\%</td><td>%5\%</td><td>%6\%</td></tr>")
.arg(tr("% of time in SpO2 Events"))
.arg(100.0/p_profile->calcHours(MT_OXIMETER)*p_profile->calcSum(OXI_SPO2Drop,MT_OXIMETER)/3600.0,0,'f',3)
.arg(100.0/p_profile->calcHours(MT_OXIMETER,oxiweek,lastoxi)*p_profile->calcSum(OXI_SPO2Drop,MT_OXIMETER,oxiweek,lastoxi)/3600.0,0,'f',3)
.arg(100.0/p_profile->calcHours(MT_OXIMETER,oximonth,lastoxi)*p_profile->calcSum(OXI_SPO2Drop,MT_OXIMETER,oximonth,lastoxi)/3600.0,0,'f',3)
.arg(100.0/p_profile->calcHours(MT_OXIMETER,oxi6month,lastoxi)*p_profile->calcSum(OXI_SPO2Drop,MT_OXIMETER,oxi6month,lastoxi)/3600.0,0,'f',3)
.arg(100.0/p_profile->calcHours(MT_OXIMETER,oxiyear,lastoxi)*p_profile->calcSum(OXI_SPO2Drop,MT_OXIMETER,oxiyear,lastoxi)/3600.0,0,'f',3);
.arg(100.0/p_profile->calcHours(MT_OXIMETER)*p_profile->calcSum(OXI_SPO2Drop,MT_OXIMETER)/3600.0,0,'f',decimals)
.arg(100.0/p_profile->calcHours(MT_OXIMETER,oxiweek,lastoxi)*p_profile->calcSum(OXI_SPO2Drop,MT_OXIMETER,oxiweek,lastoxi)/3600.0,0,'f',decimals)
.arg(100.0/p_profile->calcHours(MT_OXIMETER,oximonth,lastoxi)*p_profile->calcSum(OXI_SPO2Drop,MT_OXIMETER,oximonth,lastoxi)/3600.0,0,'f',decimals)
.arg(100.0/p_profile->calcHours(MT_OXIMETER,oxi6month,lastoxi)*p_profile->calcSum(OXI_SPO2Drop,MT_OXIMETER,oxi6month,lastoxi)/3600.0,0,'f',decimals)
.arg(100.0/p_profile->calcHours(MT_OXIMETER,oxiyear,lastoxi)*p_profile->calcSum(OXI_SPO2Drop,MT_OXIMETER,oxiyear,lastoxi)/3600.0,0,'f',decimals);
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
.arg(tr("Average Pulse Rate"))
.arg(p_profile->calcWavg(OXI_Pulse,MT_OXIMETER),0,'f',3)
.arg(p_profile->calcWavg(OXI_Pulse,MT_OXIMETER,oxiweek,lastoxi),0,'f',3)
.arg(p_profile->calcWavg(OXI_Pulse,MT_OXIMETER,oximonth,lastoxi),0,'f',3)
.arg(p_profile->calcWavg(OXI_Pulse,MT_OXIMETER,oxi6month,lastoxi),0,'f',3)
.arg(p_profile->calcWavg(OXI_Pulse,MT_OXIMETER,oxiyear,lastoxi),0,'f',3);
.arg(p_profile->calcWavg(OXI_Pulse,MT_OXIMETER),0,'f',decimals)
.arg(p_profile->calcWavg(OXI_Pulse,MT_OXIMETER,oxiweek,lastoxi),0,'f',decimals)
.arg(p_profile->calcWavg(OXI_Pulse,MT_OXIMETER,oximonth,lastoxi),0,'f',decimals)
.arg(p_profile->calcWavg(OXI_Pulse,MT_OXIMETER,oxi6month,lastoxi),0,'f',decimals)
.arg(p_profile->calcWavg(OXI_Pulse,MT_OXIMETER,oxiyear,lastoxi),0,'f',decimals);
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
.arg(tr("Minimum Pulse Rate"))
.arg(p_profile->calcMin(OXI_Pulse,MT_OXIMETER),0,'f',3)
.arg(p_profile->calcMin(OXI_Pulse,MT_OXIMETER,oxiweek,lastoxi),0,'f',3)
.arg(p_profile->calcMin(OXI_Pulse,MT_OXIMETER,oximonth,lastoxi),0,'f',3)
.arg(p_profile->calcMin(OXI_Pulse,MT_OXIMETER,oxi6month,lastoxi),0,'f',3)
.arg(p_profile->calcMin(OXI_Pulse,MT_OXIMETER,oxiyear,lastoxi),0,'f',3);
.arg(p_profile->calcMin(OXI_Pulse,MT_OXIMETER),0,'f',decimals)
.arg(p_profile->calcMin(OXI_Pulse,MT_OXIMETER,oxiweek,lastoxi),0,'f',decimals)
.arg(p_profile->calcMin(OXI_Pulse,MT_OXIMETER,oximonth,lastoxi),0,'f',decimals)
.arg(p_profile->calcMin(OXI_Pulse,MT_OXIMETER,oxi6month,lastoxi),0,'f',decimals)
.arg(p_profile->calcMin(OXI_Pulse,MT_OXIMETER,oxiyear,lastoxi),0,'f',decimals);
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
.arg(tr("Maximum Pulse Rate"))
.arg(p_profile->calcMax(OXI_Pulse,MT_OXIMETER),0,'f',3)
.arg(p_profile->calcMax(OXI_Pulse,MT_OXIMETER,oxiweek,lastoxi),0,'f',3)
.arg(p_profile->calcMax(OXI_Pulse,MT_OXIMETER,oximonth,lastoxi),0,'f',3)
.arg(p_profile->calcMax(OXI_Pulse,MT_OXIMETER,oxi6month,lastoxi),0,'f',3)
.arg(p_profile->calcMax(OXI_Pulse,MT_OXIMETER,oxiyear,lastoxi),0,'f',3);
.arg(p_profile->calcMax(OXI_Pulse,MT_OXIMETER),0,'f',decimals)
.arg(p_profile->calcMax(OXI_Pulse,MT_OXIMETER,oxiweek,lastoxi),0,'f',decimals)
.arg(p_profile->calcMax(OXI_Pulse,MT_OXIMETER,oximonth,lastoxi),0,'f',decimals)
.arg(p_profile->calcMax(OXI_Pulse,MT_OXIMETER,oxi6month,lastoxi),0,'f',decimals)
.arg(p_profile->calcMax(OXI_Pulse,MT_OXIMETER,oxiyear,lastoxi),0,'f',decimals);
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
.arg(tr("Pulse Change Events / Hour"))
.arg(p_profile->calcCount(OXI_PulseChange,MT_OXIMETER)/p_profile->calcHours(MT_OXIMETER),0,'f',3)
.arg(p_profile->calcCount(OXI_PulseChange,MT_OXIMETER,oxiweek,lastoxi)/p_profile->calcHours(MT_OXIMETER,oxiweek,lastoxi),0,'f',3)
.arg(p_profile->calcCount(OXI_PulseChange,MT_OXIMETER,oximonth,lastoxi)/p_profile->calcHours(MT_OXIMETER,oximonth,lastoxi),0,'f',3)
.arg(p_profile->calcCount(OXI_PulseChange,MT_OXIMETER,oxi6month,lastoxi)/p_profile->calcHours(MT_OXIMETER,oxi6month,lastoxi),0,'f',3)
.arg(p_profile->calcCount(OXI_PulseChange,MT_OXIMETER,oxiyear,lastoxi)/p_profile->calcHours(MT_OXIMETER,oxiyear,lastoxi),0,'f',3);
.arg(p_profile->calcCount(OXI_PulseChange,MT_OXIMETER)/p_profile->calcHours(MT_OXIMETER),0,'f',decimals)
.arg(p_profile->calcCount(OXI_PulseChange,MT_OXIMETER,oxiweek,lastoxi)/p_profile->calcHours(MT_OXIMETER,oxiweek,lastoxi),0,'f',decimals)
.arg(p_profile->calcCount(OXI_PulseChange,MT_OXIMETER,oximonth,lastoxi)/p_profile->calcHours(MT_OXIMETER,oximonth,lastoxi),0,'f',decimals)
.arg(p_profile->calcCount(OXI_PulseChange,MT_OXIMETER,oxi6month,lastoxi)/p_profile->calcHours(MT_OXIMETER,oxi6month,lastoxi),0,'f',decimals)
.arg(p_profile->calcCount(OXI_PulseChange,MT_OXIMETER,oxiyear,lastoxi)/p_profile->calcHours(MT_OXIMETER,oxiyear,lastoxi),0,'f',decimals);
}
}
@ -944,10 +951,10 @@ void MainWindow::on_summaryButton_clicked()
"a:hover { background-color: inherit; color: white; text-decoration:none; font-weight: bold; }"
"</style></head><body>";
recbox+="<table width=100% cellpadding=2 cellspacing=0>";
recbox+=QString("<tr><td><b><a href='daily=%1'>%2</b></td><td><b>%3</b></td></tr>").arg(bestAHIdate.toString(Qt::ISODate)).arg(tr("Best&nbsp;%1").arg(ahitxt)).arg(bestAHI,0,'f',2);
recbox+=QString("<tr><td><b><a href='daily=%1'>%2</b></td><td><b>%3</b></td></tr>").arg(bestAHIdate.toString(Qt::ISODate)).arg(tr("Best&nbsp;%1").arg(ahitxt)).arg(bestAHI,0,'f',decimals);
recbox+=QString("<tr><td colspan=2>%1</td></tr>").arg(bestAHIdate.toString(Qt::SystemLocaleShortDate));
recbox+=QString("<tr><td colspan=2>&nbsp;</td></tr>");
recbox+=QString("<tr><td><b><a href='daily=%1'>%2</a></b></td><td><b>%3</b></td></tr>").arg(worstAHIdate.toString(Qt::ISODate)).arg(tr("Worst&nbsp;%1").arg(ahitxt)).arg(worstAHI,0,'f',2);
recbox+=QString("<tr><td><b><a href='daily=%1'>%2</a></b></td><td><b>%3</b></td></tr>").arg(worstAHIdate.toString(Qt::ISODate)).arg(tr("Worst&nbsp;%1").arg(ahitxt)).arg(worstAHI,0,'f',decimals);
recbox+=QString("<tr><td colspan=2>%1</td></tr>").arg(worstAHIdate.toString(Qt::SystemLocaleShortDate));
recbox+=QString("<tr><td colspan=2>&nbsp;</td></tr>");
@ -985,7 +992,7 @@ void MainWindow::on_summaryButton_clicked()
.arg(tmpRX[ls]->first.toString(Qt::ISODate))
.arg(tmpRX[ls]->last.toString(Qt::ISODate))
.arg(tr("Best RX Setting"));
recbox+=QString("<tr><td colspan=2>%1: %2</td></tr>").arg(ahitxt).arg(tmpRX[ls]->ahi,0,'f',2);
recbox+=QString("<tr><td colspan=2>%1: %2</td></tr>").arg(ahitxt).arg(tmpRX[ls]->ahi,0,'f',decimals);
recbox+=QString("<tr><td colspan=2>%1: %2</td></tr>").arg(tr("Mode")).arg(modestr);
recbox+=QString("<tr><td colspan=2>%1: %2").arg(minstr).arg(tmpRX[ls]->min,0,'f',1);
if (!maxstr.isEmpty()) recbox+=QString(" %1: %2").arg(maxstr).arg(tmpRX[ls]->max,0,'f',1);
@ -1020,7 +1027,7 @@ void MainWindow::on_summaryButton_clicked()
.arg(tmpRX[0]->first.toString(Qt::ISODate))
.arg(tmpRX[0]->last.toString(Qt::ISODate))
.arg(tr("Worst RX Setting"));
recbox+=QString("<tr><td colspan=2>%1: %2</td></tr>").arg(ahitxt).arg(tmpRX[0]->ahi,0,'f',2);
recbox+=QString("<tr><td colspan=2>%1: %2</td></tr>").arg(ahitxt).arg(tmpRX[0]->ahi,0,'f',decimals);
recbox+=QString("<tr><td colspan=2>%1: %2</td></tr>").arg(tr("Mode")).arg(modestr);
recbox+=QString("<tr><td colspan=2>%1: %2").arg(minstr).arg(tmpRX[0]->min,0,'f',1);
if (!maxstr.isEmpty()) recbox+=QString(" %1: %2").arg(maxstr).arg(tmpRX[0]->max,0,'f',1);
@ -1088,30 +1095,30 @@ void MainWindow::on_summaryButton_clicked()
mode=rx.mode;
if(mode>=MODE_ASV) {
extratxt=QString("<td>%1</td><td>%2</td><td>%3</td><td>%4</td>")
.arg(rx.max,0,'f',2).arg(rx.maxhi,0,'f',2).arg(rx.max-rx.min,0,'f',2).arg(rx.maxhi-rx.min,0,'f',2);
.arg(rx.max,0,'f',decimals).arg(rx.maxhi,0,'f',decimals).arg(rx.max-rx.min,0,'f',decimals).arg(rx.maxhi-rx.min,0,'f',decimals);
tooltip=tr("%5 %1% EPAP=%2<br/>%3% IPAP=%4")
.arg(percentile*100.0)
.arg(rx.per1,0,'f',2)
.arg(rx.per1,0,'f',decimals)
.arg(percentile*100.0)
.arg(rx.per2,0,'f',2)
.arg(rx.per2,0,'f',decimals)
.arg(machstr)
;
} else if (mode>=MODE_BIPAP) {
extratxt=QString("<td>%1</td><td>%2</td>")
.arg(rx.max,0,'f',2).arg(rx.max-rx.min,0,'f',2);
.arg(rx.max,0,'f',decimals).arg(rx.max-rx.min,0,'f',decimals);
tooltip=tr("%5 %1% EPAP=%2<br/>%3% IPAP=%4")
.arg(percentile*100.0)
.arg(rx.per1,0,'f',2)
.arg(rx.per1,0,'f',decimals)
.arg(percentile*100.0)
.arg(rx.per2,0,'f',2)
.arg(rx.per2,0,'f',decimals)
.arg(machstr)
;
} else if (mode>MODE_CPAP) {
extratxt=QString("<td>%1</td>").arg(rx.max,0,'f',2);
extratxt=QString("<td>%1</td>").arg(rx.max,0,'f',decimals);
tooltip=tr("%3 %1% Pressure=%2")
.arg(percentile*100.0)
.arg(rx.per1,0,'f',2)
.arg(rx.per1,0,'f',decimals)
.arg(machstr)
;
} else {
@ -1139,11 +1146,11 @@ void MainWindow::on_summaryButton_clicked()
.arg(rx.first.toString(Qt::SystemLocaleShortDate))
.arg(rx.last.toString(Qt::SystemLocaleShortDate))
.arg(rx.days)
.arg(rx.ahi,0,'f',2)
.arg(rx.ahi,0,'f',decimals)
.arg(rx.machine->GetClass())
.arg(schema::channel[CPAP_Mode].option(int(rx.mode)-1))
.arg(presrel)
.arg(rx.min,0,'f',2)
.arg(rx.min,0,'f',decimals)
.arg(extratxt)
.arg(tooltipshow)
.arg(tooltiphide);
@ -1201,8 +1208,16 @@ void MainWindow::updateFavourites()
if (!date.isValid())
return;
ui->favouritesList->blockSignals(true);
ui->favouritesList->clear();
QString html="<html><head><style type='text/css'>"
"p,a,td,body { font-family: '"+QApplication::font().family()+"'; }"
"p,a,td,body { font-size: "+QString::number(QApplication::font().pointSize() + 2)+"px; }"
"a:link,a:visited { color: inherit; text-decoration: none; }" //font-weight: normal;
"a:hover { background-color: inherit; color: white; text-decoration:none; font-weight: bold; }"
"</style></head><body>";
html+="<table width=100% cellpadding=2 cellspacing=0>";
//ui->favouritesList->blockSignals(true);
//ui->favouritesList->clear();
do {
Day * journal=PROFILE.GetDay(date,MT_JOURNAL);
@ -1210,20 +1225,19 @@ void MainWindow::updateFavourites()
if (journal->size()>0) {
Session *sess=(*journal)[0];
if (sess->settings.contains(Bookmark_Start)) {
QVariantList start=sess->settings[Bookmark_Start].toList();
QVariantList end=sess->settings[Bookmark_End].toList();
//QVariantList start=sess->settings[Bookmark_Start].toList();
//QVariantList end=sess->settings[Bookmark_End].toList();
QStringList notes=sess->settings[Bookmark_Notes].toStringList();
if (notes.size()>0) {
QListWidgetItem *item=new QListWidgetItem(date.toString());
/*QString tooltip;
html+=QString("<tr><td><b><a href='daily=%1'>%2</a></b><br/>")
.arg(date.toString(Qt::ISODate))
.arg(date.toString());
for (int i=0;i<notes.size();i++) {
QDate d=start[i].toDate();
tooltip+=d.toString(Qt::SystemLocaleShortDate)+":"+notes[i];
if (i<notes.size()-1) tooltip+="\n";
//QDate d=start[i].toDate();
html+="&nbsp;"+notes[i]+"<br/>";
}
item->setToolTip(tooltip);*/
item->setData(Qt::UserRole,date);
ui->favouritesList->addItem(item);
html+="</td>";
}
}
}
@ -1231,7 +1245,9 @@ void MainWindow::updateFavourites()
date=date.addDays(-1);
} while (date>=PROFILE.FirstDay(MT_JOURNAL));
ui->favouritesList->blockSignals(false);
html+="</table></body></html>";
ui->bookmarkView->setHtml(html);
//ui->favouritesList->blockSignals(false);
}
void MainWindow::on_backButton_clicked()
@ -1841,13 +1857,17 @@ void MainWindow::PrintReport(gGraphView *gv,QString name, QDate date)
graphs.push_back(g);
labels.push_back(tr("Entire Day's Flow Waveform"));
}
start.push_back(savest);
end.push_back(saveet);
graphs.push_back(g);
labels.push_back("Current Selection");
} else {
start.push_back(savest);
end.push_back(saveet);
graphs.push_back(g);
labels.push_back("");
}
start.push_back(savest);
end.push_back(saveet);
graphs.push_back(g);
labels.push_back("");
}
} else {
if (journal) {
@ -2243,6 +2263,8 @@ void MainWindow::on_actionAll_Data_for_current_CPAP_machine_triggered()
}
if (QMessageBox::question(this,tr("Are you sure?"),tr("Are you sure you want to purge all CPAP data for the following machine:\n")+m->properties[STR_PROP_Brand]+" "+m->properties[STR_PROP_Model]+" "+m->properties[STR_PROP_ModelNumber]+" ("+m->properties[STR_PROP_Serial]+")",QMessageBox::Yes,QMessageBox::No)==QMessageBox::Yes) {
m->Purge(3478216);
PROFILE.machlist.erase(PROFILE.machlist.find(m->id()));
delete m;
RestartApplication();
}
}
@ -2308,16 +2330,16 @@ void MainWindow::on_webView_linkClicked(const QUrl &url)
}
}
void MainWindow::on_favouritesList_itemSelectionChanged()
{
QListWidgetItem *item=ui->favouritesList->currentItem();
if (!item) return;
QDate date=item->data(Qt::UserRole).toDate();
if (date.isValid()) {
daily->LoadDate(date);
ui->tabWidget->setCurrentWidget(daily);
}
}
//void MainWindow::on_favouritesList_itemSelectionChanged()
//{
// QListWidgetItem *item=ui->favouritesList->currentItem();
// if (!item) return;
// QDate date=item->data(Qt::UserRole).toDate();
// if (date.isValid()) {
// daily->LoadDate(date);
// ui->tabWidget->setCurrentWidget(daily);
// }
//}
/*void MainWindow::on_favouritesList_itemClicked(QListWidgetItem *item)
{
@ -2364,6 +2386,11 @@ void MainWindow::on_tabWidget_currentChanged(int index)
void MainWindow::on_summaryView_linkClicked(const QUrl &arg1)
{
qDebug() << arg1;
//qDebug() << arg1;
on_recordsBox_linkClicked(arg1);
}
void MainWindow::on_bookmarkView_linkClicked(const QUrl &arg1)
{
on_recordsBox_linkClicked(arg1);
}

View File

@ -265,7 +265,7 @@ private slots:
void on_webView_linkClicked(const QUrl &arg1);
void on_favouritesList_itemSelectionChanged();
//void on_favouritesList_itemSelectionChanged();
//void on_favouritesList_itemClicked(QListWidgetItem *item);
@ -277,6 +277,8 @@ private slots:
void on_summaryView_linkClicked(const QUrl &arg1);
void on_bookmarkView_linkClicked(const QUrl &arg1);
private:
Ui::MainWindow *ui;

View File

@ -286,13 +286,13 @@
<widget class="QToolBox" name="toolBox">
<property name="minimumSize">
<size>
<width>160</width>
<width>180</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>160</width>
<width>180</width>
<height>16777215</height>
</size>
</property>
@ -405,7 +405,7 @@
<number>1</number>
</property>
<property name="currentIndex">
<number>0</number>
<number>1</number>
</property>
<property name="tabSpacing">
<number>0</number>
@ -743,7 +743,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>158</width>
<width>178</width>
<height>313</height>
</rect>
</property>
@ -765,7 +765,7 @@
<number>0</number>
</property>
<item>
<widget class="QListWidget" name="favouritesList">
<widget class="QWebView" name="bookmarkView">
<property name="palette">
<palette>
<active>
@ -778,15 +778,6 @@
</color>
</brush>
</colorrole>
<colorrole role="AlternateBase">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>85</red>
<green>170</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="Base">
@ -798,15 +789,6 @@
</color>
</brush>
</colorrole>
<colorrole role="AlternateBase">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>85</red>
<green>170</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="Base">
@ -818,40 +800,13 @@
</color>
</brush>
</colorrole>
<colorrole role="AlternateBase">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>85</red>
<green>170</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="font">
<font>
<pointsize>10</pointsize>
</font>
</property>
<property name="mouseTracking">
<bool>true</bool>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="selectionRectVisible">
<bool>false</bool>
<property name="url">
<url>
<string>about:blank</string>
</url>
</property>
</widget>
</item>
@ -862,8 +817,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>98</width>
<height>28</height>
<width>158</width>
<height>313</height>
</rect>
</property>
<property name="mouseTracking">

View File

@ -564,7 +564,7 @@ void Overview::updateCube()
if (ui->graphCombo->count()>0) {
GraphView->setEmptyText(tr("No Graphs On!"));
GraphView->setCubeImage(images["sheep"]);
GraphView->setCubeImage(images["nographs"]);
} else {
GraphView->setEmptyText("No Data");

View File

@ -43,8 +43,8 @@ PreferencesDialog::PreferencesDialog(QWidget *parent,Profile * _profile) :
ui->leakProfile->setColumnWidth(0,100);
ui->maskTypeCombo->clear();
ui->ahiGraphGroupbox->setEnabled(false);
ui->customEventGroupbox->setEnabled(false);
//ui->ahiGraphGroupbox->setEnabled(false);
//ui->customEventGroupbox->setEnabled(false);
QString masktype=tr("Nasal Pillows");
//masktype=PROFILEMaskType
@ -194,6 +194,13 @@ PreferencesDialog::PreferencesDialog(QWidget *parent,Profile * _profile) :
if (ot<0) ot=0;
ui->oximetryType->setCurrentIndex(ot);
ui->ahiGraphWindowSize->setValue(profile->cpap->AHIWindow());
ui->ahiGraphZeroReset->setChecked(profile->cpap->AHIReset());
ui->customEventGroupbox->setChecked(profile->cpap->userEventFlagging());
ui->apneaDuration->setValue(profile->cpap->userEventDuration());
ui->apneaFlowRestriction->setValue(profile->cpap->userFlowRestriction());
ui->eventTable->setColumnWidth(0,40);
ui->eventTable->setColumnWidth(1,55);
ui->eventTable->setColumnHidden(3,true);
@ -338,6 +345,17 @@ void PreferencesDialog::Save()
profile->oxi->setPulseChangeDuration(ui->pulseChangeTime->value());
profile->oxi->setOxiDiscardThreshold(ui->oxiDiscardThreshold->value());
profile->cpap->setAHIWindow(ui->ahiGraphWindowSize->value());
profile->cpap->setAHIReset(ui->ahiGraphZeroReset->isChecked());
// Restart if turning user event flagging on/off
if (profile->cpap->userEventFlagging()!=ui->customEventGroupbox->isChecked())
needs_restart=true;
profile->cpap->setUserEventFlagging(ui->customEventGroupbox->isChecked());
profile->cpap->setUserEventDuration(ui->apneaDuration->value());
profile->cpap->setUserFlowRestriction(ui->apneaFlowRestriction->value());
PREF[STR_GEN_SkipLogin]=ui->skipLoginScreen->isChecked();
PREF[STR_GEN_UpdatesAutoCheck]=ui->automaticallyCheckUpdates->isChecked();

View File

@ -42,7 +42,7 @@
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
<number>5</number>
</property>
<widget class="QWidget" name="importTab">
<attribute name="title">
@ -310,7 +310,7 @@ p, li { white-space: pre-wrap; }
<item row="1" column="0">
<widget class="QCheckBox" name="createSDBackups">
<property name="text">
<string>Create SD Card Backups during Import (especially important for ResMed users)</string>
<string>Create SD Card Backups during Import (only works with ResMed for now)</string>
</property>
</widget>
</item>
@ -507,24 +507,7 @@ p, li { white-space: pre-wrap; }
</property>
</widget>
</item>
<item row="5" column="0" colspan="3">
<widget class="QLabel" name="label_31">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans'; font-size:10pt; font-weight:400; font-style:italic;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600; font-style:normal;&quot;&gt;Note: &lt;/span&gt;Before the following date, all leaks &lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;will show as reported by the machine.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="10" column="0">
<item row="11" column="0">
<widget class="QLabel" name="label_28">
<property name="font">
<font>
@ -537,7 +520,7 @@ p, li { white-space: pre-wrap; }
</property>
</widget>
</item>
<item row="11" column="0" colspan="3">
<item row="12" column="0" colspan="3">
<widget class="QTableWidget" name="leakProfile">
<property name="alternatingRowColors">
<bool>true</bool>
@ -557,6 +540,22 @@ p, li { white-space: pre-wrap; }
</column>
</widget>
</item>
<item row="10" column="0" colspan="3">
<widget class="QLabel" name="label_31">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans'; font-size:10pt; font-weight:400; font-style:italic;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600; font-style:normal;&quot;&gt;Note: &lt;/span&gt;Leak profiles currently does not work yet..&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
@ -651,20 +650,19 @@ p, li { white-space: pre-wrap; }
<item>
<widget class="QGroupBox" name="customEventGroupbox">
<property name="title">
<string>Custom Event Flagging</string>
<string>Custom PRS1 Event Flagging</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout_6">
<item row="0" column="1">
<widget class="QLabel" name="label_38">
<property name="text">
<string>Duration</string>
</property>
</widget>
</item>
<item row="0" column="2">
<property name="margin">
<number>4</number>
</property>
<property name="spacing">
<number>4</number>
</property>
<item row="1" column="1">
<widget class="QLabel" name="label_35">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
@ -677,34 +675,14 @@ p, li { white-space: pre-wrap; }
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_34">
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="apneaFlowRestriction">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Apnea</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="apneaDuration">
<property name="suffix">
<string>s</string>
</property>
<property name="minimum">
<double>1.000000000000000</double>
</property>
<property name="value">
<double>10.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QDoubleSpinBox" name="apneaFlowRestriction">
<property name="suffix">
<string>%</string>
</property>
@ -713,7 +691,7 @@ p, li { white-space: pre-wrap; }
</property>
</widget>
</item>
<item row="1" column="3">
<item row="2" column="4">
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@ -726,30 +704,44 @@ p, li { white-space: pre-wrap; }
</property>
</spacer>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_37">
<item row="0" column="0" colspan="5">
<widget class="QLabel" name="label_34">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string>Hypopnea</string>
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans'; font-size:10pt; font-weight:400; font-style:italic;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Custom flagging is an experimental method of detecting events missed by the machine.&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;** This only affects &lt;span style=&quot; text-decoration: underline;&quot;&gt;future&lt;/span&gt; imports **&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="hypopneaDuration">
<item row="2" column="3">
<widget class="QDoubleSpinBox" name="apneaDuration">
<property name="suffix">
<string>s</string>
</property>
<property name="minimum">
<double>1.000000000000000</double>
</property>
<property name="value">
<double>10.000000000000000</double>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QDoubleSpinBox" name="hypopneaFlowRestriction">
<property name="suffix">
<string>%</string>
</property>
<property name="value">
<double>40.000000000000000</double>
<item row="1" column="3">
<widget class="QLabel" name="label_38">
<property name="text">
<string>Event Duration</string>
</property>
</widget>
</item>
@ -765,6 +757,12 @@ p, li { white-space: pre-wrap; }
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout_8">
<property name="horizontalSpacing">
<number>4</number>
</property>
<property name="margin">
<number>4</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_36">
<property name="sizePolicy">