diff --git a/sleepyhead/Graphs/gSummaryChart.cpp b/sleepyhead/Graphs/gSummaryChart.cpp index 80f80edd..74f15d6a 100644 --- a/sleepyhead/Graphs/gSummaryChart.cpp +++ b/sleepyhead/Graphs/gSummaryChart.cpp @@ -230,11 +230,12 @@ void SummaryChart::SetDay(Day * nullday) if (day->machine(m_machinetype) == nullptr) { continue; } bool hascode = //day->channelHasData(code) || - type == ST_HOURS || - type == ST_SESSIONS || + (type == ST_HOURS) || + (type == ST_SESSIONS) || day->settingExists(code) || day->hasData(code, type); + if (code == CPAP_Pressure) { if ((cpapmode > MODE_CPAP) && (mode == MODE_CPAP)) { hascode = false; diff --git a/sleepyhead/SleepLib/calcs.cpp b/sleepyhead/SleepLib/calcs.cpp index a07a2096..90b3f86e 100644 --- a/sleepyhead/SleepLib/calcs.cpp +++ b/sleepyhead/SleepLib/calcs.cpp @@ -1680,9 +1680,12 @@ void zMaskProfile::updateProfile(Session *session) void flagLargeLeaks(Session *session) { + // Already contains? if (session->eventlist.contains(CPAP_LargeLeak)) return; + if (!session->eventlist.contains(CPAP_Leak)) + return; EventDataType threshold = p_profile->cpap->leakRedline(); @@ -1690,6 +1693,7 @@ void flagLargeLeaks(Session *session) return; } + QVector & EVL = session->eventlist[CPAP_Leak]; int evlsize = EVL.size(); diff --git a/sleepyhead/SleepLib/day.cpp b/sleepyhead/SleepLib/day.cpp index 37b784fd..ee0e765d 100644 --- a/sleepyhead/SleepLib/day.cpp +++ b/sleepyhead/SleepLib/day.cpp @@ -954,6 +954,7 @@ bool Day::hasData(ChannelID code, SummaryType type) for (QList::iterator it = sessions.begin(); it != end; ++it) { Session & sess = *(*it); + if (sess.machine()->type() == MT_JOURNAL) continue; if (sess.enabled()) { switch (type) { @@ -1308,7 +1309,7 @@ qint64 Day::first() QList::iterator end = sessions.end(); for (QList::iterator it = sessions.begin(); it != end; ++it) { Session & sess = *(*it); - + if (sess.machine()->type() == MT_JOURNAL) continue; if (sess.enabled()) { tmp = sess.first(); @@ -1335,6 +1336,7 @@ qint64 Day::last() for (QList::iterator it = sessions.begin(); it != end; ++it) { Session & sess = *(*it); + if (sess.machine()->type() == MT_JOURNAL) continue; if (sess.enabled()) { tmp = sess.last(); diff --git a/sleepyhead/SleepLib/loader_plugins/prs1_loader.cpp b/sleepyhead/SleepLib/loader_plugins/prs1_loader.cpp index d035add5..fd707d75 100644 --- a/sleepyhead/SleepLib/loader_plugins/prs1_loader.cpp +++ b/sleepyhead/SleepLib/loader_plugins/prs1_loader.cpp @@ -259,7 +259,8 @@ int PRS1Loader::Open(QString path) Q_UNUSED(e) p_profile->DelMachine(m); PRS1List.erase(PRS1List.find(info.serial)); - QMessageBox::warning(nullptr, QObject::tr("Import Error"), + QMessageBox::warning(nullptr, + QObject::tr("Import Error"), QObject::tr("This Machine Record cannot be imported in this profile.\nThe Day records overlap with already existing content."), QMessageBox::Ok); delete m; @@ -379,19 +380,16 @@ int PRS1Loader::OpenMachine(Machine *m, QString path) int model = modelstr.toInt(&ok); if (ok) { // Assumption is made here all PRS1 machines less than 450P are not data capable.. this could be wrong one day. - if ((model < 450)) { - QMessageBox::information(NULL, + if ((model < 450) && p_profile->cpap->brickWarning()) { + QApplication::processEvents(); + QMessageBox::information(QApplication::activeWindow(), QObject::tr("Non Data Capable Machine"), QString(QObject::tr("Your Philips Respironics CPAP machine (Model %1) is unfortunately not a data capable model.")+"\n\n"+ - QObject::tr("I'm sorry to report that SleepyHead can only track hours of use for this machine.")). + QObject::tr("I'm sorry to report that SleepyHead can only track hours of use and very basic settings for this machine.")). arg(m->modelnumber()),QMessageBox::Ok); + p_profile->cpap->setBrickWarning(false); } - - if ((model % 100) >= 60) { - // 60 series machine warning?? - } - } else { // model number didn't parse.. Meh... } @@ -1127,8 +1125,63 @@ bool PRS1Import::ParseF0Events() bool PRS1Import::ParseCompliance() { + const unsigned char * data = (unsigned char *)compliance->m_data.constData(); + + if (data[0x00] > 0) { + return false; + } + + session->settings[CPAP_Mode] = (int)MODE_CPAP; + + EventDataType min_pressure = float(data[0x03]) / 10.0; + EventDataType max_pressure = float(data[0x04]) / 10.0; + + session->settings[CPAP_Pressure] = min_pressure; + + + int ramp_time = data[0x06]; + EventDataType ramp_pressure = float(data[0x07]) / 10.0; + + session->settings[CPAP_RampTime] = (int)ramp_time; + session->settings[CPAP_RampPressure] = ramp_pressure; + + + quint8 flex = data[0x09]; + int flexlevel = flex & 0x03; + + + FlexMode flexmode = FLEX_Unknown; + + flex &= 0xf8; + bool split = false; + + if (flex & 0x40) { // This bit defines the Flex setting for the CPAP component of the Split night + split = true; + } + if (flex & 0x80) { // CFlex bit + if (flex & 8) { // Plus bit + flexmode = FLEX_CFlexPlus; + } else { + flexmode = FLEX_CFlex; + } + } else flexmode = FLEX_None; + + session->settings[PRS1_FlexMode] = (int)flexmode; + session->settings[PRS1_FlexLevel] = (int)flexlevel; + session->settings[CPAP_SummaryOnly] = true; + + session->settings[PRS1_HumidStatus] = (bool)(data[0x0A] & 0x80); // Humidifier Connected + session->settings[PRS1_HumidLevel] = (int)(data[0x0A] & 7); // Humidifier Value + + + // This is probably wrong + summary_duration = data[0x12] | data[0x13] << 8; + + session->set_first(qint64(compliance->timestamp) * 1000L); + session->set_last(qint64(compliance->timestamp + (summary_duration * 2)) * 1000L); + + // Bleh!! There is probably 10 different formats for these useless piece of junk machines - if (!compliance) return false; return true; } @@ -1833,7 +1886,7 @@ void PRS1Import::run() { session = new Session(mach, sessionid); - if (summary && ParseSummary()) { + if ((compliance && ParseCompliance()) || (summary && ParseSummary())) { if (event && !ParseEvents()) { } waveforms = loader->ParseFile(waveform); diff --git a/sleepyhead/SleepLib/loader_plugins/resmed_loader.cpp b/sleepyhead/SleepLib/loader_plugins/resmed_loader.cpp index 641933ec..4bb3b4da 100644 --- a/sleepyhead/SleepLib/loader_plugins/resmed_loader.cpp +++ b/sleepyhead/SleepLib/loader_plugins/resmed_loader.cpp @@ -2407,10 +2407,10 @@ bool ResmedLoader::LoadBRP(Session *sess, const QString & path) } else if (matchSignal(CPAP_RespEvent, es.label)) { code = CPAP_RespEvent; - } else { + } else if (es.label != "Crc16") { qDebug() << "Unobserved ResMed BRP Signal " << es.label; continue; - } + } else continue; if (code) { double rate = double(duration) / double(recs); @@ -2615,7 +2615,7 @@ bool ResmedLoader::LoadSAD(Session *sess, const QString & path) ToTimeDelta(sess, edf, es, code, recs, duration); sess->setPhysMax(code, 100); sess->setPhysMin(code, 60); - } else { + } else if (es.label != "Crc16") { qDebug() << "Unobserved ResMed SAD Signal " << es.label; } } @@ -2666,7 +2666,13 @@ bool ResmedLoader::LoadPLD(Session *sess, const QString & path) es.physical_maximum = 25; es.physical_minimum = 4; ToTimeDelta(sess, edf, es, code, recs, duration, 0, 0); - } else if (matchSignal(CPAP_MinuteVent,es.label)) { + } else if (matchSignal(CPAP_EPAP, es.label)) { // Expiratory Pressure + code = CPAP_EPAP; + es.physical_maximum = 25; + es.physical_minimum = 4; + + ToTimeDelta(sess, edf, es, code, recs, duration, 0, 0); + } else if (matchSignal(CPAP_MinuteVent,es.label)) { code = CPAP_MinuteVent; ToTimeDelta(sess, edf, es, code, recs, duration, 0, 0); } else if (matchSignal(CPAP_RespRate, es.label)) { @@ -2700,12 +2706,6 @@ bool ResmedLoader::LoadPLD(Session *sess, const QString & path) es.physical_maximum = 25; es.physical_minimum = 4; - ToTimeDelta(sess, edf, es, code, recs, duration, 0, 0); - } else if (matchSignal(CPAP_EPAP, es.label)) { // Expiratory Pressure - code = CPAP_EPAP; - es.physical_maximum = 25; - es.physical_minimum = 4; - ToTimeDelta(sess, edf, es, code, recs, duration, 0, 0); } else if (matchSignal(CPAP_IE, es.label)) { //I:E ratio code = CPAP_IE; @@ -2739,16 +2739,16 @@ bool ResmedLoader::LoadPLD(Session *sess, const QString & path) } else if (es.label == "") { // What the hell resmed?? if (emptycnt == 0) { code = RMS9_E01; - ToTimeDelta(sess, edf, es, code, recs, duration); +// ToTimeDelta(sess, edf, es, code, recs, duration); } else if (emptycnt == 1) { code = RMS9_E02; - ToTimeDelta(sess, edf, es, code, recs, duration); +// ToTimeDelta(sess, edf, es, code, recs, duration); } else { qDebug() << "Unobserved Empty Signal " << es.label; } emptycnt++; - } else { + } else if (es.label != "Crc16") { qDebug() << "Unobserved ResMed PLD Signal " << es.label; a = nullptr; } @@ -2801,9 +2801,17 @@ void ResInitModelMap() resmed_codes.clear(); + // BRP file resmed_codes[CPAP_FlowRate].push_back("Flow"); + resmed_codes[CPAP_FlowRate].push_back("Flow.40ms"); resmed_codes[CPAP_MaskPressureHi].push_back("Mask Pres"); + resmed_codes[CPAP_MaskPressureHi].push_back("Press.40ms"); + + + // PLD File resmed_codes[CPAP_MaskPressure].push_back("Mask Pres"); + + resmed_codes[CPAP_RespEvent].push_back("Resp Event"); resmed_codes[CPAP_Pressure].push_back("Therapy Pres"); resmed_codes[CPAP_IPAP].push_back("Insp Pres"); @@ -2859,6 +2867,7 @@ void ResInitModelMap() resmed_codes[RMS9_SetPressure].push_back("Pres. prescrite"); resmed_codes[RMS9_SetPressure].push_back("Inställt tryck"); resmed_codes[RMS9_SetPressure].push_back("Inställt tryck"); + resmed_codes[RMS9_EPR].push_back("EPR"); resmed_codes[RMS9_EPR].push_back("S.EPR.EPRType"); @@ -2885,9 +2894,7 @@ void ResInitModelMap() resmed_codes[CPAP_PressureMin].push_back("Pression min."); resmed_codes[CPAP_PressureMin].push_back("Min tryck"); - // BRP file - resmed_codes[CPAP_FlowRate].push_back("Flow.40ms"); - resmed_codes[CPAP_MaskPressureHi].push_back("Pres.40ms"); + // SAD file resmed_codes[OXI_Pulse].push_back("Pulse.1s"); diff --git a/sleepyhead/SleepLib/profiles.h b/sleepyhead/SleepLib/profiles.h index 8ed35add..0975ed43 100644 --- a/sleepyhead/SleepLib/profiles.h +++ b/sleepyhead/SleepLib/profiles.h @@ -272,6 +272,7 @@ const QString STR_CS_DateDiagnosed = "DateDiagnosed"; const QString STR_CS_UserEventFlagging = "UserEventFlagging"; const QString STR_CS_UserEventPieChart = "UserEventPieChart"; const QString STR_CS_AutoImport = "AutoImport"; +const QString STR_CS_BrickWarning = "BrickWarning"; const QString STR_CS_UserFlowRestriction = "UserFlowRestriction"; const QString STR_CS_UserEventDuration = "UserEventDuration"; @@ -541,6 +542,7 @@ class CPAPSettings : public ProfileSettings initPref(STR_CS_UserEventPieChart, false); initPref(STR_CS_ResyncFromUserFlagging, false); initPref(STR_CS_AutoImport, false); + initPref(STR_CS_BrickWarning, true); initPref(STR_CS_ClockDrift, (int)0); m_clock_drift = getPref(STR_CS_ClockDrift).toInt(); @@ -573,7 +575,7 @@ class CPAPSettings : public ProfileSettings bool userEventPieChart() const { return getPref(STR_CS_UserEventPieChart).toBool(); } bool resyncFromUserFlagging() const { return getPref(STR_CS_ResyncFromUserFlagging).toBool(); } bool autoImport() const { return getPref(STR_CS_AutoImport).toBool(); } - + bool brickWarning() const { return getPref(STR_CS_BrickWarning).toBool(); } //Setters void setMode(CPAPMode mode) { setPref(STR_CS_PrescribedMode, (int)mode); } @@ -606,6 +608,7 @@ class CPAPSettings : public ProfileSettings void setUserEventPieChart(bool b) { setPref(STR_CS_UserEventPieChart, b); } void setResyncFromUserFlagging(bool b) { setPref(STR_CS_ResyncFromUserFlagging, b); } void setAutoImport(bool b) { setPref(STR_CS_AutoImport, b); } + void setBrickWarning(bool b) { setPref(STR_CS_BrickWarning, b); } public: int m_clock_drift; diff --git a/sleepyhead/daily.cpp b/sleepyhead/daily.cpp index 2f5801fe..1619109c 100644 --- a/sleepyhead/daily.cpp +++ b/sleepyhead/daily.cpp @@ -981,7 +981,7 @@ QString Daily::getMachineSettings(Day * day) { if (sess) for (; it != it_end; ++it) { ChannelID code = it.key(); - if ((code <= 1) || (code == RMS9_MaskOnTime) || (code == CPAP_Mode) || (code == cpapmode)) continue; + if ((code <= 1) || (code == RMS9_MaskOnTime) || (code == CPAP_Mode) || (code == cpapmode) || (code == CPAP_SummaryOnly)) continue; schema::Channel & chan = schema::channel[code]; @@ -1449,6 +1449,9 @@ void Daily::Load(QDate date) } + if (!cpap) { + GraphView->setEmptyImage(QPixmap(":/docs/sheep.png")); + } if (cpap) { //QHash > list; @@ -1456,9 +1459,12 @@ void Daily::Load(QDate date) float hours=day->hours(MT_CPAP); if (GraphView->isEmpty() && (hours>0)) { if (!p_profile->hasChannel(CPAP_Obstructive) && !p_profile->hasChannel(CPAP_Hypopnea)) { - GraphView->setEmptyText(STR_Empty_NoGraphs); + GraphView->setEmptyText(STR_Empty_Brick); + GraphView->setEmptyImage(QPixmap(":/icons/sadface.png")); isBrick=true; + } else { + GraphView->setEmptyImage(QPixmap(":/docs/sheep.png")); } } @@ -1470,17 +1476,22 @@ void Daily::Load(QDate date) if (p_profile->general->calculateRDI()) ahi+=day->count(CPAP_RERA); ahi/=hours; - if (!isBrick && hours>0) { + if (hours>0) { html+="\n"; - ChannelID ahichan=CPAP_AHI; - QString ahiname=STR_TR_AHI; - if (p_profile->general->calculateRDI()) { - ahichan=CPAP_RDI; - ahiname=STR_TR_RDI; - } html+=""; - html+=QString("\n") + if (!isBrick) { + ChannelID ahichan=CPAP_AHI; + QString ahiname=STR_TR_AHI; + if (p_profile->general->calculateRDI()) { + ahichan=CPAP_RDI; + ahiname=STR_TR_RDI; + } + html+=QString("\n") .arg("#F88017").arg(COLOR_Text.name()).arg(ahiname).arg(schema::channel[ahichan].fullname()).arg(ahi,0,'f',2); + } else { + html+=QString("\n") + .arg("#F88017").arg(tr("BRICK! :(")); + } html+="\n"; html+="
%3%4   %5%3%4   %5%2
\n"; html+=getCPAPInformation(day); @@ -1597,7 +1608,7 @@ void Daily::Load(QDate date) } else { if (cpap && day->hours(MT_CPAP)<0.0000001) { - } else { + } else if (!isBrick) { html+=""; html+=""; html+=""; @@ -2409,8 +2420,10 @@ void Daily::updateCube() && !p_profile->GetGoodDay(getDate(), MT_SLEEPSTAGE) && !p_profile->GetGoodDay(getDate(), MT_POSITION)) { GraphView->setEmptyText(STR_Empty_NoData); + } else { - GraphView->setEmptyText(STR_Empty_SummaryOnly); + if (GraphView->emptyText() != STR_Empty_Brick) + GraphView->setEmptyText(STR_Empty_SummaryOnly); } } } else { diff --git a/sleepyhead/mainwindow.cpp b/sleepyhead/mainwindow.cpp index 6f287cbb..4e71353f 100644 --- a/sleepyhead/mainwindow.cpp +++ b/sleepyhead/mainwindow.cpp @@ -657,7 +657,7 @@ int MainWindow::importCPAP(ImportPath import, const QString &message) return 0; } - QDialog * popup = new QDialog(this, Qt::SplashScreen); + QDialog * popup = new QDialog(this); QLabel * waitmsg = new QLabel(message); QHBoxLayout *hlayout = new QHBoxLayout; diff --git a/sleepyhead/profileselect.cpp b/sleepyhead/profileselect.cpp index a6920c16..f3a2b4ba 100644 --- a/sleepyhead/profileselect.cpp +++ b/sleepyhead/profileselect.cpp @@ -74,13 +74,16 @@ ProfileSelect::ProfileSelect(QWidget *parent) : proxy = new QSortFilterProxyModel(this); proxy->setSourceModel(model); + proxy->setSortCaseSensitivity(Qt::CaseInsensitive); + ui->listView->setModel(proxy); ui->listView->setSelectionBehavior(QAbstractItemView::SelectRows); ui->listView->setSelectionMode(QAbstractItemView::SingleSelection); - if (sel >= 0) { ui->listView->setCurrentIndex(proxy->index(sel,0)); } //model->item(sel)->index()); } + proxy->sort(0, Qt::AscendingOrder); + m_tries = 0; /*PREF["SkipLogin"]=false;
"+tr("\"Nothing's here!\"")+"