diff --git a/Graphs/gGraphView.cpp b/Graphs/gGraphView.cpp index 0d4d016d..d0bfc3fc 100644 --- a/Graphs/gGraphView.cpp +++ b/Graphs/gGraphView.cpp @@ -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; } } diff --git a/Graphs/gGraphView.h b/Graphs/gGraphView.h index 99980f54..d40f83dd 100644 --- a/Graphs/gGraphView.h +++ b/Graphs/gGraphView.h @@ -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); diff --git a/Graphs/gLineChart.cpp b/Graphs/gLineChart.cpp index 5c1a537c..778a5ce5 100644 --- a/Graphs/gLineChart.cpp +++ b/Graphs/gLineChart.cpp @@ -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; } } diff --git a/Resources.qrc b/Resources.qrc index 18f45453..8c9928df 100644 --- a/Resources.qrc +++ b/Resources.qrc @@ -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> diff --git a/SleepLib/calcs.cpp b/SleepLib/calcs.cpp index e6f4161f..d05788be 100644 --- a/SleepLib/calcs.cpp +++ b/SleepLib/calcs.cpp @@ -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); diff --git a/SleepLib/calcs.h b/SleepLib/calcs.h index 7cf6e2e9..5eee64eb 100644 --- a/SleepLib/calcs.h +++ b/SleepLib/calcs.h @@ -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); diff --git a/SleepLib/loader_plugins/resmed_loader.cpp b/SleepLib/loader_plugins/resmed_loader.cpp index 71034b35..f108f912 100644 --- a/SleepLib/loader_plugins/resmed_loader.cpp +++ b/SleepLib/loader_plugins/resmed_loader.cpp @@ -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); diff --git a/SleepLib/preferences.cpp b/SleepLib/preferences.cpp index 21eb5187..750c4389 100644 --- a/SleepLib/preferences.cpp +++ b/SleepLib/preferences.cpp @@ -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() { diff --git a/SleepLib/preferences.h b/SleepLib/preferences.h index 76db1870..774b6b1e 100644 --- a/SleepLib/preferences.h +++ b/SleepLib/preferences.h @@ -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; diff --git a/SleepLib/profiles.cpp b/SleepLib/profiles.cpp index ef157a8b..97618ffa 100644 --- a/SleepLib/profiles.cpp +++ b/SleepLib/profiles.cpp @@ -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"; diff --git a/SleepLib/profiles.h b/SleepLib/profiles.h index a4979d73..1ce50018 100644 --- a/SleepLib/profiles.h +++ b/SleepLib/profiles.h @@ -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; }; diff --git a/daily.cpp b/daily.cpp index 0c135573..1953a666 100644 --- a/daily.cpp +++ b/daily.cpp @@ -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"); diff --git a/daily.ui b/daily.ui index 5aa9b982..1acf63e8 100644 --- a/daily.ui +++ b/daily.ui @@ -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> diff --git a/docs/channels.xml b/docs/channels.xml index 8c711014..85b89a2a 100644 --- a/docs/channels.xml +++ b/docs/channels.xml @@ -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<n<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"/> diff --git a/docs/release_notes.html b/docs/release_notes.html index 2d8b7948..f9d410b2 100644 --- a/docs/release_notes.html +++ b/docs/release_notes.html @@ -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/> diff --git a/icons/sheep.png b/icons/nographs.png similarity index 100% rename from icons/sheep.png rename to icons/nographs.png diff --git a/main.cpp b/main.cpp index f097722c..ab7ee837 100644 --- a/main.cpp +++ b/main.cpp @@ -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"; diff --git a/mainwindow.cpp b/mainwindow.cpp index 3ec8a416..33b5842a 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -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 %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 %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> </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 %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 %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> </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+=" "+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); } diff --git a/mainwindow.h b/mainwindow.h index afb22b7e..01f9320d 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -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; diff --git a/mainwindow.ui b/mainwindow.ui index 6654f6ae..50496ddc 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -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"> diff --git a/overview.cpp b/overview.cpp index 84721fda..f05e4e9c 100644 --- a/overview.cpp +++ b/overview.cpp @@ -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"); diff --git a/preferencesdialog.cpp b/preferencesdialog.cpp index 0158437d..ff13db5c 100644 --- a/preferencesdialog.cpp +++ b/preferencesdialog.cpp @@ -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(); diff --git a/preferencesdialog.ui b/preferencesdialog.ui index da9c3124..9799331b 100644 --- a/preferencesdialog.ui +++ b/preferencesdialog.ui @@ -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><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:italic;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; font-style:normal;">Note: </span>Before the following date, all leaks </p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">will show as reported by the machine.</p></body></html></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><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; font-style:normal;">Note: </span>Leak profiles currently does not work yet..</p></body></html></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><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Custom flagging is an experimental method of detecting events missed by the machine.</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">** This only affects <span style=" text-decoration: underline;">future</span> imports **</p></body></html></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">