mirror of
https://gitlab.com/pholy/OSCAR-code.git
synced 2025-04-15 18:20:46 +00:00
Major cleanup. Added MachineInfo structure. Intellipap BiLevel support plus backup
This commit is contained in:
parent
4c213bd529
commit
a5cb32f4cf
@ -227,7 +227,7 @@ void gFlagsLine::paint(QPainter &painter, gGraph &w, const QRegion ®ion)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
drift = ((*s)->machine()->GetType() == MT_CPAP) ? clockdrift : 0;
|
drift = ((*s)->machine()->type() == MT_CPAP) ? clockdrift : 0;
|
||||||
|
|
||||||
cei = (*s)->eventlist.find(m_code);
|
cei = (*s)->eventlist.find(m_code);
|
||||||
|
|
||||||
|
@ -366,7 +366,7 @@ void gLineChart::paint(QPainter &painter, gGraph &w, const QRegion ®ion)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
drift = (sess->machine()->GetType() == MT_CPAP) ? clockdrift : 0;
|
drift = (sess->machine()->type() == MT_CPAP) ? clockdrift : 0;
|
||||||
|
|
||||||
if (!sess->enabled()) { continue; }
|
if (!sess->enabled()) { continue; }
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ void gLineOverlayBar::paint(QPainter &painter, gGraph &w, const QRegion ®ion)
|
|||||||
|
|
||||||
if (evlist.size() == 0) { continue; }
|
if (evlist.size() == 0) { continue; }
|
||||||
|
|
||||||
drift = ((*s)->machine()->GetType() == MT_CPAP) ? clockdrift : 0;
|
drift = ((*s)->machine()->type() == MT_CPAP) ? clockdrift : 0;
|
||||||
|
|
||||||
// Could loop through here, but nowhere uses more than one yet..
|
// Could loop through here, but nowhere uses more than one yet..
|
||||||
for (int k = 0; k < evlist.size(); k++) {
|
for (int k = 0; k < evlist.size(); k++) {
|
||||||
|
@ -444,8 +444,19 @@ void SummaryChart::paint(QPainter &painter, gGraph &w, const QRegion ®ion)
|
|||||||
painter.drawLine( left+width, top, left, top);
|
painter.drawLine( left+width, top, left, top);
|
||||||
|
|
||||||
qint64 minx = w.min_x, maxx = w.max_x;
|
qint64 minx = w.min_x, maxx = w.max_x;
|
||||||
|
|
||||||
|
int days = ceil(double(maxx-minx) / 86400000.0);
|
||||||
|
|
||||||
|
if (days >= 1) {
|
||||||
|
minx = floor(double(minx)/86400000.0);
|
||||||
|
minx *= 86400000L;
|
||||||
|
|
||||||
|
maxx = minx + 86400000L * qint64(days)-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
qint64 xx = maxx - minx;
|
qint64 xx = maxx - minx;
|
||||||
float days = double(xx) / 86400000.0;
|
|
||||||
|
|
||||||
EventDataType miny = m_physminy;
|
EventDataType miny = m_physminy;
|
||||||
EventDataType maxy = m_physmaxy;
|
EventDataType maxy = m_physmaxy;
|
||||||
|
@ -44,6 +44,8 @@ gXAxis::gXAxis(QColor col, bool fadeout)
|
|||||||
|
|
||||||
tz_offset = timezoneOffset();
|
tz_offset = timezoneOffset();
|
||||||
tz_hours = tz_offset / 3600000.0;
|
tz_hours = tz_offset / 3600000.0;
|
||||||
|
|
||||||
|
m_roundDays = false;
|
||||||
}
|
}
|
||||||
gXAxis::~gXAxis()
|
gXAxis::~gXAxis()
|
||||||
{
|
{
|
||||||
@ -107,6 +109,16 @@ void gXAxis::paint(QPainter &painter, gGraph &w, const QRegion ®ion)
|
|||||||
maxx = w.max_x;
|
maxx = w.max_x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int days = ceil(double(maxx-minx) / 86400000.0);
|
||||||
|
|
||||||
|
if (m_roundDays && (days >= 1)) {
|
||||||
|
minx = floor(double(minx)/86400000.0);
|
||||||
|
minx *= 86400000L;
|
||||||
|
|
||||||
|
maxx = minx + 86400000L * qint64(days);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// duration of graph display window in milliseconds.
|
// duration of graph display window in milliseconds.
|
||||||
qint64 xx = maxx - minx;
|
qint64 xx = maxx - minx;
|
||||||
|
|
||||||
|
@ -38,6 +38,8 @@ class gXAxis: public Layer
|
|||||||
bool ShowMajorTicks() { return m_show_major_ticks; }
|
bool ShowMajorTicks() { return m_show_major_ticks; }
|
||||||
void setUtcFix(bool b) { m_utcfix = b; }
|
void setUtcFix(bool b) { m_utcfix = b; }
|
||||||
|
|
||||||
|
void setRoundDays(bool b) { m_roundDays = b; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool m_show_major_lines;
|
bool m_show_major_lines;
|
||||||
bool m_show_minor_lines;
|
bool m_show_minor_lines;
|
||||||
@ -55,6 +57,8 @@ class gXAxis: public Layer
|
|||||||
float tz_hours;
|
float tz_hours;
|
||||||
|
|
||||||
QImage m_image;
|
QImage m_image;
|
||||||
|
|
||||||
|
bool m_roundDays;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // GXAXIS_H
|
#endif // GXAXIS_H
|
||||||
|
@ -34,7 +34,7 @@ bool SearchEvent(Session * session, ChannelID code, qint64 time, int dur, bool u
|
|||||||
int cnt;
|
int cnt;
|
||||||
|
|
||||||
//qint64 rate;
|
//qint64 rate;
|
||||||
// bool fixdurations = (session->machine()->GetClass() != STR_MACH_ResMed);
|
// bool fixdurations = (session->machine()->loaderName() != STR_MACH_ResMed);
|
||||||
|
|
||||||
if (!p_profile->cpap->resyncFromUserFlagging()) {
|
if (!p_profile->cpap->resyncFromUserFlagging()) {
|
||||||
update=false;
|
update=false;
|
||||||
@ -867,9 +867,9 @@ void FlowParser::flagEvents()
|
|||||||
|
|
||||||
void calcRespRate(Session *session, FlowParser *flowparser)
|
void calcRespRate(Session *session, FlowParser *flowparser)
|
||||||
{
|
{
|
||||||
if (session->machine()->GetType() != MT_CPAP) { return; }
|
if (session->machine()->type() != MT_CPAP) { return; }
|
||||||
|
|
||||||
// if (session->machine()->GetClass()!=STR_MACH_PRS1) return;
|
// if (session->machine()->loaderName() != STR_MACH_PRS1) return;
|
||||||
|
|
||||||
if (!session->eventlist.contains(CPAP_FlowRate)) {
|
if (!session->eventlist.contains(CPAP_FlowRate)) {
|
||||||
//qDebug() << "calcRespRate called without FlowRate waveform available";
|
//qDebug() << "calcRespRate called without FlowRate waveform available";
|
||||||
@ -999,7 +999,7 @@ EventDataType calcAHI(Session *session, qint64 start, qint64 end)
|
|||||||
|
|
||||||
int calcAHIGraph(Session *session)
|
int calcAHIGraph(Session *session)
|
||||||
{
|
{
|
||||||
bool calcrdi = session->machine()->GetClass() == "PRS1";
|
bool calcrdi = session->machine()->loaderName() == "PRS1";
|
||||||
//p_profile->general->calculateRDI()
|
//p_profile->general->calculateRDI()
|
||||||
|
|
||||||
|
|
||||||
@ -1009,7 +1009,7 @@ int calcAHIGraph(Session *session)
|
|||||||
|
|
||||||
bool zeroreset = p_profile->cpap->AHIReset();
|
bool zeroreset = p_profile->cpap->AHIReset();
|
||||||
|
|
||||||
if (session->machine()->GetType() != MT_CPAP) { return 0; }
|
if (session->machine()->type() != MT_CPAP) { return 0; }
|
||||||
|
|
||||||
bool hasahi = session->eventlist.contains(CPAP_AHI);
|
bool hasahi = session->eventlist.contains(CPAP_AHI);
|
||||||
bool hasrdi = session->eventlist.contains(CPAP_RDI);
|
bool hasrdi = session->eventlist.contains(CPAP_RDI);
|
||||||
@ -1692,7 +1692,7 @@ bool mmaskFirst = true;
|
|||||||
int calcLeaks(Session *session)
|
int calcLeaks(Session *session)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (session->machine()->GetType() != MT_CPAP) { return 0; }
|
if (session->machine()->type() != MT_CPAP) { return 0; }
|
||||||
|
|
||||||
if (session->eventlist.contains(CPAP_Leak)) { return 0; } // abort if already there
|
if (session->eventlist.contains(CPAP_Leak)) { return 0; } // abort if already there
|
||||||
|
|
||||||
|
@ -103,6 +103,32 @@ bool removeDir(const QString &path)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void copyPath(QString src, QString dst)
|
||||||
|
{
|
||||||
|
QDir dir(src);
|
||||||
|
if (!dir.exists())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Recursively handle directories
|
||||||
|
foreach (QString d, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) {
|
||||||
|
QString dst_path = dst + QDir::separator() + d;
|
||||||
|
dir.mkpath(dst_path);
|
||||||
|
copyPath(src + QDir::separator() + d, dst_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Files
|
||||||
|
foreach (QString f, dir.entryList(QDir::Files)) {
|
||||||
|
QString srcFile = src + QDir::separator() + f;
|
||||||
|
QString destFile = dst + QDir::separator() + f;
|
||||||
|
|
||||||
|
if (!QFile::exists(destFile)) {
|
||||||
|
QFile::copy(srcFile, destFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
QString STR_UNIT_CM;
|
QString STR_UNIT_CM;
|
||||||
QString STR_UNIT_INCH;
|
QString STR_UNIT_INCH;
|
||||||
QString STR_UNIT_FOOT;
|
QString STR_UNIT_FOOT;
|
||||||
|
@ -41,6 +41,9 @@ struct ValueCount {
|
|||||||
double p;
|
double p;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void copyPath(QString src, QString dst);
|
||||||
|
|
||||||
|
|
||||||
// Primarily sort by value
|
// Primarily sort by value
|
||||||
bool operator <(const ValueCount &a, const ValueCount &b);
|
bool operator <(const ValueCount &a, const ValueCount &b);
|
||||||
|
|
||||||
@ -88,17 +91,6 @@ const QString STR_PREF_AllowEarlyUpdates = "AllowEarlyUpdates";
|
|||||||
const QString STR_PREF_ReimportBackup = "ReimportBackup";
|
const QString STR_PREF_ReimportBackup = "ReimportBackup";
|
||||||
const QString STR_PREF_LastCPAPPath = "LastCPAPPath";
|
const QString STR_PREF_LastCPAPPath = "LastCPAPPath";
|
||||||
|
|
||||||
const QString STR_PROP_Brand = "Brand";
|
|
||||||
const QString STR_PROP_Model = "Model";
|
|
||||||
const QString STR_PROP_Series = "Series";
|
|
||||||
const QString STR_PROP_ModelNumber = "ModelNumber";
|
|
||||||
const QString STR_PROP_SubModel = "SubModel";
|
|
||||||
const QString STR_PROP_Serial = "Serial";
|
|
||||||
const QString STR_PROP_DataVersion = "DataVersion";
|
|
||||||
const QString STR_PROP_Path = "Path";
|
|
||||||
const QString STR_PROP_BackupPath = "BackupPath";
|
|
||||||
const QString STR_PROP_LastImported = "LastImported";
|
|
||||||
|
|
||||||
const QString STR_MACH_ResMed = "ResMed";
|
const QString STR_MACH_ResMed = "ResMed";
|
||||||
const QString STR_MACH_PRS1 = "PRS1";
|
const QString STR_MACH_PRS1 = "PRS1";
|
||||||
const QString STR_MACH_Journal = "Journal";
|
const QString STR_MACH_Journal = "Journal";
|
||||||
|
@ -31,7 +31,7 @@ Day::~Day()
|
|||||||
}
|
}
|
||||||
MachineType Day::machine_type() const
|
MachineType Day::machine_type() const
|
||||||
{
|
{
|
||||||
return machine->GetType();
|
return machine->type();
|
||||||
}
|
}
|
||||||
Session *Day::find(SessionID sessid)
|
Session *Day::find(SessionID sessid)
|
||||||
{
|
{
|
||||||
|
@ -163,7 +163,7 @@ void CMS50Loader::processBytes(QByteArray bytes)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
;
|
;
|
||||||
// qDebug() << "Device mode not supported by" << ClassName();
|
// qDebug() << "Device mode not supported by" << loaderName();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idx >= available) {
|
if (idx >= available) {
|
||||||
@ -627,37 +627,6 @@ bool CMS50Loader::readSpoRFile(QString path)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Machine *CMS50Loader::CreateMachine()
|
|
||||||
{
|
|
||||||
Q_ASSERT(p_profile != nullptr);
|
|
||||||
|
|
||||||
// NOTE: This only allows for one CMS50 machine per profile..
|
|
||||||
// Upgrading their oximeter will use this same record..
|
|
||||||
|
|
||||||
QList<Machine *> ml = p_profile->GetMachines(MT_OXIMETER);
|
|
||||||
|
|
||||||
for (QList<Machine *>::iterator i = ml.begin(); i != ml.end(); i++) {
|
|
||||||
if ((*i)->GetClass() == cms50_class_name) {
|
|
||||||
return (*i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
qDebug() << "Create CMS50 Machine Record";
|
|
||||||
|
|
||||||
Machine *m = new Oximeter(0);
|
|
||||||
m->SetClass(cms50_class_name);
|
|
||||||
m->properties[STR_PROP_Brand] = "Contec";
|
|
||||||
m->properties[STR_PROP_Model] = "CMS50X";
|
|
||||||
m->properties[STR_PROP_DataVersion] = QString::number(cms50_data_version);
|
|
||||||
|
|
||||||
p_profile->AddMachine(m);
|
|
||||||
QString path = "{" + STR_GEN_DataFolder + "}/" + m->GetClass() + "_" + m->hexid() + "/";
|
|
||||||
m->properties[STR_PROP_Path] = path;
|
|
||||||
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMS50Loader::process()
|
void CMS50Loader::process()
|
||||||
{
|
{
|
||||||
// Just clean up any extra crap before oximeterimport parses the oxirecords..
|
// Just clean up any extra crap before oximeterimport parses the oxirecords..
|
||||||
|
@ -36,9 +36,14 @@ Q_OBJECT
|
|||||||
static void Register();
|
static void Register();
|
||||||
|
|
||||||
virtual int Version() { return cms50_data_version; }
|
virtual int Version() { return cms50_data_version; }
|
||||||
virtual const QString &ClassName() { return cms50_class_name; }
|
virtual const QString &loaderName() { return cms50_class_name; }
|
||||||
|
|
||||||
Machine *CreateMachine();
|
virtual MachineInfo newInfo() {
|
||||||
|
return MachineInfo(MT_OXIMETER, cms50_class_name, QObject::tr("Contec"), QString(), QString(), QString(), QObject::tr("CMS50"), QDateTime::currentDateTime(), cms50_data_version);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Machine *CreateMachine();
|
||||||
|
|
||||||
virtual void process();
|
virtual void process();
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@ const QString FPHCARE = "FPHCARE";
|
|||||||
FPIcon::FPIcon(MachineID id)
|
FPIcon::FPIcon(MachineID id)
|
||||||
: CPAP(id)
|
: CPAP(id)
|
||||||
{
|
{
|
||||||
m_class = fpicon_class_name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FPIcon::~FPIcon()
|
FPIcon::~FPIcon()
|
||||||
@ -56,7 +55,7 @@ bool FPIconLoader::Detect(const QString & givenpath)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CHECKME: I can't access F&P ICON data right now
|
// CHECKME: I can't access F&P ICON data right now
|
||||||
if (!dir.exists("FPCARE/ICON")) {
|
if (!dir.exists("FPHCARE/ICON")) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,18 +112,22 @@ int FPIconLoader::Open(QString path)
|
|||||||
|
|
||||||
QString npath;
|
QString npath;
|
||||||
|
|
||||||
|
int c = 0;
|
||||||
for (int i = 0; i < SerialNumbers.size(); i++) {
|
for (int i = 0; i < SerialNumbers.size(); i++) {
|
||||||
QString &sn = SerialNumbers[i];
|
MachineInfo info = newInfo();
|
||||||
m = CreateMachine(sn);
|
info.serial = SerialNumbers[i];
|
||||||
|
m = CreateMachine(info);
|
||||||
|
|
||||||
npath = newpath + "/" + sn;
|
npath = newpath + "/" + info.serial;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (m) { OpenMachine(m, npath); }
|
if (m) {
|
||||||
|
c+=OpenMachine(m, npath);
|
||||||
|
}
|
||||||
} catch (OneTypePerDay e) {
|
} catch (OneTypePerDay e) {
|
||||||
Q_UNUSED(e)
|
Q_UNUSED(e)
|
||||||
p_profile->DelMachine(m);
|
p_profile->DelMachine(m);
|
||||||
MachList.erase(MachList.find(sn));
|
MachList.erase(MachList.find(info.serial));
|
||||||
QMessageBox::warning(nullptr, "Import Error",
|
QMessageBox::warning(nullptr, "Import Error",
|
||||||
"This Machine Record cannot be imported in this profile.\nThe Day records overlap with already existing content.",
|
"This Machine Record cannot be imported in this profile.\nThe Day records overlap with already existing content.",
|
||||||
QMessageBox::Ok);
|
QMessageBox::Ok);
|
||||||
@ -132,7 +135,7 @@ int FPIconLoader::Open(QString path)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return MachList.size();
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FPWaveChunk {
|
struct FPWaveChunk {
|
||||||
@ -219,73 +222,77 @@ int FPIconLoader::OpenMachine(Machine *mach, QString &path)
|
|||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
QDateTime dt;
|
QDateTime dt;
|
||||||
QString a;
|
QString a;
|
||||||
QMap<SessionID, Session *>::iterator it = Sessions.end();
|
|
||||||
it--;
|
|
||||||
dt = QDateTime::fromTime_t(qint64(it.value()->first()) / 1000L);
|
|
||||||
QDate date = dt.date().addDays(-7);
|
|
||||||
it++;
|
|
||||||
|
|
||||||
do {
|
if (Sessions.size() > 0) {
|
||||||
|
|
||||||
|
QMap<SessionID, Session *>::iterator it = Sessions.end();
|
||||||
it--;
|
it--;
|
||||||
Session *sess = it.value();
|
|
||||||
sid = sess->session();
|
|
||||||
hours = sess->hours();
|
|
||||||
mins = hours * 60;
|
|
||||||
dt = QDateTime::fromTime_t(sid);
|
|
||||||
|
|
||||||
if (sess->channelDataExists(CPAP_FlowRate)) { a = "(flow)"; }
|
dt = QDateTime::fromTime_t(qint64(it.value()->first()) / 1000L);
|
||||||
else { a = ""; }
|
QDate date = dt.date().addDays(-7);
|
||||||
|
it++;
|
||||||
|
|
||||||
qDebug() << cnt << ":" << dt << "session" << sid << "," << mins << "minutes" << a;
|
do {
|
||||||
|
it--;
|
||||||
|
Session *sess = it.value();
|
||||||
|
sid = sess->session();
|
||||||
|
hours = sess->hours();
|
||||||
|
mins = hours * 60;
|
||||||
|
dt = QDateTime::fromTime_t(sid);
|
||||||
|
|
||||||
if (dt.date() < date) { break; }
|
if (sess->channelDataExists(CPAP_FlowRate)) { a = "(flow)"; }
|
||||||
|
else { a = ""; }
|
||||||
|
|
||||||
++cnt;
|
qDebug() << cnt << ":" << dt << "session" << sid << "," << mins << "minutes" << a;
|
||||||
|
|
||||||
} while (it != Sessions.begin());
|
if (dt.date() < date) { break; }
|
||||||
|
|
||||||
|
++cnt;
|
||||||
|
|
||||||
// qDebug() << "Unmatched Sessions";
|
} while (it != Sessions.begin());
|
||||||
// QList<FPWaveChunk> chunks;
|
|
||||||
// for (QMap<int,QDate>::iterator dit=FLWDate.begin();dit!=FLWDate.end();dit++) {
|
|
||||||
// int k=dit.key();
|
|
||||||
// //QDate date=dit.value();
|
|
||||||
//// QList<Session *> values = SessDate.values(date);
|
|
||||||
// for (int j=0;j<FLWTS[k].size();j++) {
|
|
||||||
|
|
||||||
// FPWaveChunk chunk(FLWTS[k].at(j),FLWDuration[k].at(j),k);
|
}
|
||||||
// chunk.flow=FLWMapFlow[k].at(j);
|
// qDebug() << "Unmatched Sessions";
|
||||||
// chunk.leak=FLWMapLeak[k].at(j);
|
// QList<FPWaveChunk> chunks;
|
||||||
// chunk.pressure=FLWMapPres[k].at(j);
|
// for (QMap<int,QDate>::iterator dit=FLWDate.begin();dit!=FLWDate.end();dit++) {
|
||||||
|
// int k=dit.key();
|
||||||
|
// //QDate date=dit.value();
|
||||||
|
//// QList<Session *> values = SessDate.values(date);
|
||||||
|
// for (int j=0;j<FLWTS[k].size();j++) {
|
||||||
|
|
||||||
// chunks.push_back(chunk);
|
// FPWaveChunk chunk(FLWTS[k].at(j),FLWDuration[k].at(j),k);
|
||||||
|
// chunk.flow=FLWMapFlow[k].at(j);
|
||||||
|
// chunk.leak=FLWMapLeak[k].at(j);
|
||||||
|
// chunk.pressure=FLWMapPres[k].at(j);
|
||||||
|
|
||||||
// zz=FLWTS[k].at(j)/1000;
|
// chunks.push_back(chunk);
|
||||||
// dur=double(FLWDuration[k].at(j))/60000.0;
|
|
||||||
// bool b,c=false;
|
// zz=FLWTS[k].at(j)/1000;
|
||||||
// if (Sessions.contains(zz)) b=true; else b=false;
|
// dur=double(FLWDuration[k].at(j))/60000.0;
|
||||||
// if (b) {
|
// bool b,c=false;
|
||||||
// if (Sessions[zz]->channelDataExists(CPAP_FlowRate)) c=true;
|
// if (Sessions.contains(zz)) b=true; else b=false;
|
||||||
// }
|
// if (b) {
|
||||||
// qDebug() << k << "-" <<j << ":" << zz << qRound(dur) << "minutes" << (b ? "*" : "") << (c ? QDateTime::fromTime_t(zz).toString() : "");
|
// if (Sessions[zz]->channelDataExists(CPAP_FlowRate)) c=true;
|
||||||
// }
|
// }
|
||||||
// }
|
// qDebug() << k << "-" <<j << ":" << zz << qRound(dur) << "minutes" << (b ? "*" : "") << (c ? QDateTime::fromTime_t(zz).toString() : "");
|
||||||
// qSort(chunks);
|
// }
|
||||||
// bool b,c;
|
// }
|
||||||
// for (int i=0;i<chunks.size();i++) {
|
// qSort(chunks);
|
||||||
// const FPWaveChunk & chunk=chunks.at(i);
|
// bool b,c;
|
||||||
// zz=chunk.st/1000;
|
// for (int i=0;i<chunks.size();i++) {
|
||||||
// dur=double(chunk.duration)/60000.0;
|
// const FPWaveChunk & chunk=chunks.at(i);
|
||||||
// if (Sessions.contains(zz)) b=true; else b=false;
|
// zz=chunk.st/1000;
|
||||||
// if (b) {
|
// dur=double(chunk.duration)/60000.0;
|
||||||
// if (Sessions[zz]->channelDataExists(CPAP_FlowRate)) c=true;
|
// if (Sessions.contains(zz)) b=true; else b=false;
|
||||||
// }
|
// if (b) {
|
||||||
// qDebug() << chunk.file << ":" << i << zz << dur << "minutes" << (b ? "*" : "") << (c ? QDateTime::fromTime_t(zz).toString() : "");
|
// if (Sessions[zz]->channelDataExists(CPAP_FlowRate)) c=true;
|
||||||
// }
|
// }
|
||||||
|
// qDebug() << chunk.file << ":" << i << zz << dur << "minutes" << (b ? "*" : "") << (c ? QDateTime::fromTime_t(zz).toString() : "");
|
||||||
|
// }
|
||||||
|
|
||||||
mach->Save();
|
mach->Save();
|
||||||
|
|
||||||
return true;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// !\brief Convert F&P 32bit date format to 32bit UNIX Timestamp
|
// !\brief Convert F&P 32bit date format to 32bit UNIX Timestamp
|
||||||
@ -451,8 +458,8 @@ bool FPIconLoader::OpenFLW(Machine *mach, QString filename)
|
|||||||
htxt >> model;
|
htxt >> model;
|
||||||
htxt >> type;
|
htxt >> type;
|
||||||
|
|
||||||
if (mach->properties[STR_PROP_Model].isEmpty()) {
|
if (mach->model().isEmpty()) {
|
||||||
mach->properties[STR_PROP_Model] = model + " " + type;
|
mach->setModel(model+" "+type);
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray buf = file.read(4);
|
QByteArray buf = file.read(4);
|
||||||
@ -591,7 +598,7 @@ bool FPIconLoader::OpenFLW(Machine *mach, QString filename)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (p_profile->session->backupCardData()) {
|
if (p_profile->session->backupCardData()) {
|
||||||
QString backup = p_profile->Get(mach->properties[STR_PROP_BackupPath])+"FPHCARE/ICON/"+serial.right(serial.size()-4)+"/";
|
QString backup = mach->getBackupPath()+"FPHCARE/ICON/"+serial.right(serial.size()-4)+"/";
|
||||||
QDir dir;
|
QDir dir;
|
||||||
QString newname = QString("FLW%1.FPH").arg(ts);
|
QString newname = QString("FLW%1.FPH").arg(ts);
|
||||||
dir.mkpath(backup);
|
dir.mkpath(backup);
|
||||||
@ -645,7 +652,8 @@ bool FPIconLoader::OpenSummary(Machine *mach, QString filename)
|
|||||||
htxt >> serial;
|
htxt >> serial;
|
||||||
htxt >> model;
|
htxt >> model;
|
||||||
htxt >> type;
|
htxt >> type;
|
||||||
mach->properties[STR_PROP_Model] = model + " " + type;
|
|
||||||
|
mach->setModel(model + " " + type);
|
||||||
|
|
||||||
QByteArray data;
|
QByteArray data;
|
||||||
data = file.readAll();
|
data = file.readAll();
|
||||||
@ -744,7 +752,7 @@ bool FPIconLoader::OpenSummary(Machine *mach, QString filename)
|
|||||||
} while (!in.atEnd());
|
} while (!in.atEnd());
|
||||||
|
|
||||||
if (p_profile->session->backupCardData()) {
|
if (p_profile->session->backupCardData()) {
|
||||||
QString backup = p_profile->Get(mach->properties[STR_PROP_BackupPath])+"FPHCARE/ICON/"+serial.right(serial.size()-4)+"/";
|
QString backup = mach->getBackupPath()+"FPHCARE/ICON/"+serial.right(serial.size()-4)+"/";
|
||||||
QDir dir;
|
QDir dir;
|
||||||
QString newname = QString("SUM%1.FPH").arg(QDate::currentDate().year(),4,10,QChar('0'));
|
QString newname = QString("SUM%1.FPH").arg(QDate::currentDate().year(),4,10,QChar('0'));
|
||||||
dir.mkpath(backup);
|
dir.mkpath(backup);
|
||||||
@ -911,7 +919,7 @@ bool FPIconLoader::OpenDetail(Machine *mach, QString filename)
|
|||||||
ts = data[0] | data[1] << 8 | data[2] << 16 | data[3] << 24;
|
ts = data[0] | data[1] << 8 | data[2] << 16 | data[3] << 24;
|
||||||
ts = convertDate(ts);
|
ts = convertDate(ts);
|
||||||
|
|
||||||
QString backup = p_profile->Get(mach->properties[STR_PROP_BackupPath])+"FPHCARE/ICON/"+serial.right(serial.size()-4)+"/";
|
QString backup = mach->getBackupPath()+"FPHCARE/ICON/"+serial.right(serial.size()-4)+"/";
|
||||||
QDir dir;
|
QDir dir;
|
||||||
QString newname = QString("DET%1.FPH").arg(ts);
|
QString newname = QString("DET%1.FPH").arg(ts);
|
||||||
|
|
||||||
@ -925,53 +933,6 @@ bool FPIconLoader::OpenDetail(Machine *mach, QString filename)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Machine *FPIconLoader::CreateMachine(QString serial)
|
|
||||||
{
|
|
||||||
Q_ASSERT(p_profile != nullptr);
|
|
||||||
|
|
||||||
qDebug() << "Create Machine " << serial;
|
|
||||||
|
|
||||||
QList<Machine *> ml = p_profile->GetMachines(MT_CPAP);
|
|
||||||
bool found = false;
|
|
||||||
QList<Machine *>::iterator i;
|
|
||||||
Machine *m;
|
|
||||||
|
|
||||||
for (i = ml.begin(); i != ml.end(); i++) {
|
|
||||||
if (((*i)->GetClass() == fpicon_class_name) && ((*i)->properties[STR_PROP_Serial] == serial)) {
|
|
||||||
MachList[serial] = *i;
|
|
||||||
found = true;
|
|
||||||
m = *i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
m = new FPIcon(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
m->properties[STR_PROP_Brand] = "Fisher & Paykel";
|
|
||||||
m->properties[STR_PROP_Series] = STR_MACH_FPIcon;
|
|
||||||
m->properties[STR_PROP_Model] = STR_MACH_FPIcon;
|
|
||||||
|
|
||||||
if (found) {
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
MachList[serial] = m;
|
|
||||||
p_profile->AddMachine(m);
|
|
||||||
|
|
||||||
m->properties[STR_PROP_Serial] = serial;
|
|
||||||
m->properties[STR_PROP_DataVersion] = QString::number(fpicon_data_version);
|
|
||||||
|
|
||||||
QString path = "{" + STR_GEN_DataFolder + "}/" + m->GetClass() + "_" + serial + "/";
|
|
||||||
m->properties[STR_PROP_Path] = path;
|
|
||||||
m->properties[STR_PROP_BackupPath] = path + "Backup/";
|
|
||||||
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool fpicon_initialized = false;
|
bool fpicon_initialized = false;
|
||||||
void FPIconLoader::Register()
|
void FPIconLoader::Register()
|
||||||
{
|
{
|
||||||
|
@ -70,10 +70,15 @@ class FPIconLoader : public MachineLoader
|
|||||||
virtual int Version() { return fpicon_data_version; }
|
virtual int Version() { return fpicon_data_version; }
|
||||||
|
|
||||||
//! \brief Returns the machine class name of this CPAP machine, "FPIcon"
|
//! \brief Returns the machine class name of this CPAP machine, "FPIcon"
|
||||||
virtual const QString &ClassName() { return fpicon_class_name; }
|
virtual const QString &loaderName() { return fpicon_class_name; }
|
||||||
|
|
||||||
|
// ! \brief Creates a machine object, indexed by serial number
|
||||||
|
//Machine *CreateMachine(QString serial);
|
||||||
|
|
||||||
|
virtual MachineInfo newInfo() {
|
||||||
|
return MachineInfo(MT_CPAP, fpicon_class_name, QObject::tr("Fisher & Paykel"), QString(), QString(), QString(), QObject::tr("ICON"), QDateTime::currentDateTime(), fpicon_data_version);
|
||||||
|
}
|
||||||
|
|
||||||
//! \brief Creates a machine object, indexed by serial number
|
|
||||||
Machine *CreateMachine(QString serial);
|
|
||||||
|
|
||||||
//! \brief Registers this MachineLoader with the master list, so F&P Icon data can load
|
//! \brief Registers this MachineLoader with the master list, so F&P Icon data can load
|
||||||
static void Register();
|
static void Register();
|
||||||
|
@ -20,7 +20,6 @@ extern QProgressBar *qprogress;
|
|||||||
Intellipap::Intellipap(MachineID id)
|
Intellipap::Intellipap(MachineID id)
|
||||||
: CPAP(id)
|
: CPAP(id)
|
||||||
{
|
{
|
||||||
m_class = intellipap_class_name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Intellipap::~Intellipap()
|
Intellipap::~Intellipap()
|
||||||
@ -88,17 +87,40 @@ int IntellipapLoader::Open(QString path)
|
|||||||
f.open(QFile::ReadOnly);
|
f.open(QFile::ReadOnly);
|
||||||
QTextStream tstream(&f);
|
QTextStream tstream(&f);
|
||||||
|
|
||||||
|
const QString INT_PROP_Serial = "Serial";
|
||||||
|
const QString INT_PROP_Model = "Model";
|
||||||
|
const QString INT_PROP_Mode = "Mode";
|
||||||
|
const QString INT_PROP_MaxPressure = "Max Pressure";
|
||||||
|
const QString INT_PROP_MinPressure = "Min Pressure";
|
||||||
|
const QString INT_PROP_IPAP = "IPAP";
|
||||||
|
const QString INT_PROP_EPAP = "EPAP";
|
||||||
|
const QString INT_PROP_PS = "PS";
|
||||||
|
const QString INT_PROP_RampPressure = "Ramp Pressure";
|
||||||
|
const QString INT_PROP_RampTime = "Ramp Time";
|
||||||
|
|
||||||
|
const QString INT_PROP_HourMeter = "Usage Hours";
|
||||||
|
const QString INT_PROP_ComplianceMeter = "Compliance Hours";
|
||||||
|
const QString INT_PROP_ErrorCode = "Error";
|
||||||
|
const QString INT_PROP_LastErrorCode = "Long Error";
|
||||||
|
const QString INT_PROP_LowUseThreshold = "Low Usage";
|
||||||
|
const QString INT_PROP_SmartFlex = "SmartFlex";
|
||||||
|
const QString INT_PROP_SmartFlexMode = "SmartFlexMode";
|
||||||
|
|
||||||
|
|
||||||
QHash<QString, QString> lookup;
|
QHash<QString, QString> lookup;
|
||||||
lookup["Sn"]=STR_PROP_Serial;
|
lookup["Sn"] = INT_PROP_Serial;
|
||||||
lookup["Mn"]=STR_PROP_ModelNumber;
|
lookup["Mn"] = INT_PROP_Model;
|
||||||
lookup["Mo"]="PAPMode"; // 0 cpap, 1 auto
|
lookup["Mo"] = INT_PROP_Mode; // 0 cpap, 1 auto
|
||||||
//lookup["Pn"]="??";
|
//lookup["Pn"]="??";
|
||||||
lookup["Pu"]="MaxPressure";
|
lookup["Pu"] = INT_PROP_MaxPressure;
|
||||||
lookup["Pl"]="MaxPressure";
|
lookup["Pl"] = INT_PROP_MinPressure;
|
||||||
|
lookup["Pi"] = INT_PROP_IPAP;
|
||||||
|
lookup["Pe"] = INT_PROP_EPAP; // == WF on Auto models
|
||||||
|
lookup["Ps"] = INT_PROP_PS; // == WF on Auto models, Pressure support
|
||||||
//lookup["Ds"]="??";
|
//lookup["Ds"]="??";
|
||||||
//lookup["Pc"]="??";
|
//lookup["Pc"]="??";
|
||||||
lookup["Pd"]="RampPressure"; // Pressure Delay
|
lookup["Pd"] = INT_PROP_RampPressure;
|
||||||
lookup["Dt"]="RampTime";
|
lookup["Dt"] = INT_PROP_RampTime;
|
||||||
//lookup["Ld"]="??";
|
//lookup["Ld"]="??";
|
||||||
//lookup["Lh"]="??";
|
//lookup["Lh"]="??";
|
||||||
//lookup["FC"]="??";
|
//lookup["FC"]="??";
|
||||||
@ -114,24 +136,34 @@ int IntellipapLoader::Open(QString path)
|
|||||||
lookup["Re"]="SmartFlexERnd"; // Inhale Rounding (0-5)
|
lookup["Re"]="SmartFlexERnd"; // Inhale Rounding (0-5)
|
||||||
//lookup["Bu"]="??"; // WF
|
//lookup["Bu"]="??"; // WF
|
||||||
//lookup["Ie"]="??"; // 20
|
//lookup["Ie"]="??"; // 20
|
||||||
//lookup["Se"]="??"; // 05
|
//lookup["Se"]="??"; // 05 //Inspiratory trigger?
|
||||||
//lookup["Si"]="??"; // 05
|
//lookup["Si"]="??"; // 05 // Expiratory Trigger?
|
||||||
//lookup["Mi"]="??"; // 0
|
//lookup["Mi"]="??"; // 0
|
||||||
lookup["Uh"]="HoursMeter"; // 0000.0
|
lookup["Uh"]="HoursMeter"; // 0000.0
|
||||||
lookup["Up"]="ComplianceMeter"; // 0000.00
|
lookup["Up"]="ComplianceMeter"; // 0000.00
|
||||||
//lookup["Er"]="ErrorCode";, // E00
|
//lookup["Er"]="ErrorCode";, // E00
|
||||||
//lookup["El"]="LastErrorCode"; // E00 00/00/0000
|
//lookup["El"]="LongErrorCode"; // E00 00/00/0000
|
||||||
//lookup["Hp"]="??";, // 1
|
//lookup["Hp"]="??";, // 1
|
||||||
//lookup["Hs"]="??";, // 02
|
//lookup["Hs"]="??";, // 02
|
||||||
//lookup["Lu"]="LowUseThreshold"; // defaults to 0 (4 hours)
|
//lookup["Lu"]="LowUseThreshold"; // defaults to 0 (4 hours)
|
||||||
lookup["Sf"]="SmartFlex";
|
lookup["Sf"] = INT_PROP_SmartFlex;
|
||||||
lookup["Sm"]="SmartFlexMode";
|
lookup["Sm"] = INT_PROP_SmartFlexMode;
|
||||||
lookup["Ks=s"]="Ks_s";
|
lookup["Ks=s"]="Ks_s";
|
||||||
lookup["Ks=i"]="ks_i";
|
lookup["Ks=i"]="ks_i";
|
||||||
|
|
||||||
QHash<QString, QString> set1;
|
QHash<QString, QString> set1;
|
||||||
QHash<QString, QString>::iterator hi;
|
QHash<QString, QString>::iterator hi;
|
||||||
|
|
||||||
|
Machine *mach = nullptr;
|
||||||
|
|
||||||
|
MachineInfo info = newInfo();
|
||||||
|
|
||||||
|
|
||||||
|
bool ok;
|
||||||
|
|
||||||
|
EventDataType min_pressure = 0, max_pressure = 0, ramp_pressure = 0, set_epap = 0, set_ipap = 0, set_ps = 0, ramp_time = 0;
|
||||||
|
|
||||||
|
int papmode = 0, smartflex = 0, smartflexmode = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
QString line = tstream.readLine();
|
QString line = tstream.readLine();
|
||||||
|
|
||||||
@ -146,14 +178,52 @@ int IntellipapLoader::Open(QString path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString value = line.section("\t", 1).trimmed();
|
QString value = line.section("\t", 1).trimmed();
|
||||||
set1[key] = value;
|
|
||||||
|
if (key == INT_PROP_Mode) {
|
||||||
|
papmode = value.toInt(&ok);
|
||||||
|
} else if (key == INT_PROP_Serial) {
|
||||||
|
info.serial = value;
|
||||||
|
} else if (key == INT_PROP_Model) {
|
||||||
|
info.model = value;
|
||||||
|
} else if (key == INT_PROP_MinPressure) {
|
||||||
|
min_pressure = value.toFloat() / 10.0;
|
||||||
|
} else if (key == INT_PROP_MaxPressure) {
|
||||||
|
max_pressure = value.toFloat() / 10.0;
|
||||||
|
} else if (key == INT_PROP_IPAP) {
|
||||||
|
set_ipap = value.toFloat() / 10.0;
|
||||||
|
} else if (key == INT_PROP_EPAP) {
|
||||||
|
set_epap = value.toFloat() / 10.0;
|
||||||
|
} else if (key == INT_PROP_PS) {
|
||||||
|
set_ps = value.toFloat() / 10.0;
|
||||||
|
} else if (key == INT_PROP_RampPressure) {
|
||||||
|
ramp_pressure = value.toFloat() / 10.0;
|
||||||
|
} else if (key == INT_PROP_RampTime) {
|
||||||
|
ramp_time = value.toFloat() / 10.0;
|
||||||
|
} else if (key == INT_PROP_SmartFlex) {
|
||||||
|
smartflex = value.toInt();
|
||||||
|
} else if (key == INT_PROP_SmartFlexMode) {
|
||||||
|
smartflexmode = value.toInt();
|
||||||
|
} else {
|
||||||
|
set1[key] = value;
|
||||||
|
}
|
||||||
qDebug() << key << "=" << value;
|
qDebug() << key << "=" << value;
|
||||||
}
|
}
|
||||||
|
|
||||||
Machine *mach = nullptr;
|
CPAPMode mode = MODE_UNKNOWN;
|
||||||
|
|
||||||
if (set1.contains(STR_PROP_Serial)) {
|
switch (papmode) {
|
||||||
mach = CreateMachine(set1[STR_PROP_Serial]);
|
case 0:
|
||||||
|
mode = MODE_CPAP;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
mode = (set_epap > 0) ? MODE_BILEVEL_FIXED : MODE_APAP;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qDebug() << "New machine mode";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!info.serial.isEmpty()) {
|
||||||
|
mach = CreateMachine(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mach) {
|
if (!mach) {
|
||||||
@ -161,19 +231,24 @@ int IntellipapLoader::Open(QString path)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString backupPath = mach->getBackupPath();
|
||||||
|
QString copypath = path;
|
||||||
|
|
||||||
|
if (QDir::cleanPath(path).compare(QDir::cleanPath(backupPath)) != 0) {
|
||||||
|
copyPath(path, backupPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Refresh properties data..
|
// Refresh properties data..
|
||||||
for (QHash<QString, QString>::iterator i = set1.begin(); i != set1.end(); i++) {
|
for (QHash<QString, QString>::iterator i = set1.begin(); i != set1.end(); i++) {
|
||||||
mach->properties[i.key()] = i.value();
|
mach->properties[i.key()] = i.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
mach->properties[STR_PROP_Model] = STR_MACH_Intellipap + " " +
|
|
||||||
mach->properties[STR_PROP_ModelNumber];
|
|
||||||
|
|
||||||
f.close();
|
f.close();
|
||||||
|
|
||||||
//////////////////////////
|
///////////////////////////////////////////////
|
||||||
// Parse the Session Index
|
// Parse the Session Index (U File)
|
||||||
//////////////////////////
|
///////////////////////////////////////////////
|
||||||
unsigned char buf[27];
|
unsigned char buf[27];
|
||||||
filename = newpath + "/U";
|
filename = newpath + "/U";
|
||||||
f.setFileName(filename);
|
f.setFileName(filename);
|
||||||
@ -193,21 +268,22 @@ int IntellipapLoader::Open(QString path)
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
cnt = f.read((char *)buf, 9);
|
cnt = f.read((char *)buf, 9);
|
||||||
|
// big endian
|
||||||
ts1 = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
|
ts1 = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
|
||||||
ts2 = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
|
ts2 = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
|
||||||
|
// buf[8] == ??? What is this byte? A Bit Field? A checksum?
|
||||||
ts1 += ep;
|
ts1 += ep;
|
||||||
ts2 += ep;
|
ts2 += ep;
|
||||||
SessionStart.append(ts1);
|
SessionStart.append(ts1);
|
||||||
SessionEnd.append(ts2);
|
SessionEnd.append(ts2);
|
||||||
//cs=buf[8];
|
|
||||||
} while (cnt > 0);
|
} while (cnt > 0);
|
||||||
|
|
||||||
qDebug() << "U file logs" << SessionStart.size() << "sessions.";
|
qDebug() << "U file logs" << SessionStart.size() << "sessions.";
|
||||||
f.close();
|
f.close();
|
||||||
|
|
||||||
//////////////////////////
|
///////////////////////////////////////////////
|
||||||
// Parse the Session Data
|
// Parse the Session Data (L File)
|
||||||
//////////////////////////
|
///////////////////////////////////////////////
|
||||||
filename = newpath + "/L";
|
filename = newpath + "/L";
|
||||||
f.setFileName(filename);
|
f.setFileName(filename);
|
||||||
|
|
||||||
@ -225,6 +301,7 @@ int IntellipapLoader::Open(QString path)
|
|||||||
|
|
||||||
Session *sess;
|
Session *sess;
|
||||||
SessionID sid;
|
SessionID sid;
|
||||||
|
QHash<SessionID,qint64> rampstart;
|
||||||
|
|
||||||
for (int i = 0; i < SessionStart.size(); i++) {
|
for (int i = 0; i < SessionStart.size(); i++) {
|
||||||
sid = SessionStart[i];
|
sid = SessionStart[i];
|
||||||
@ -235,10 +312,15 @@ int IntellipapLoader::Open(QString path)
|
|||||||
SessionEnd[i] = 0;
|
SessionEnd[i] = 0;
|
||||||
} else if (!Sessions.contains(sid)) {
|
} else if (!Sessions.contains(sid)) {
|
||||||
sess = Sessions[sid] = new Session(mach, sid);
|
sess = Sessions[sid] = new Session(mach, sid);
|
||||||
|
rampstart[sid] = 0;
|
||||||
sess->SetChanged(true);
|
sess->SetChanged(true);
|
||||||
sess->AddEventList(CPAP_IPAP, EVL_Event);
|
if (mode >= MODE_BILEVEL_FIXED) {
|
||||||
sess->AddEventList(CPAP_EPAP, EVL_Event);
|
sess->AddEventList(CPAP_IPAP, EVL_Event);
|
||||||
sess->AddEventList(CPAP_Pressure, EVL_Event);
|
sess->AddEventList(CPAP_EPAP, EVL_Event);
|
||||||
|
sess->AddEventList(CPAP_PS, EVL_Event);
|
||||||
|
} else {
|
||||||
|
sess->AddEventList(CPAP_Pressure, EVL_Event);
|
||||||
|
}
|
||||||
|
|
||||||
sess->AddEventList(INTELLIPAP_Unknown1, EVL_Event);
|
sess->AddEventList(INTELLIPAP_Unknown1, EVL_Event);
|
||||||
sess->AddEventList(INTELLIPAP_Unknown2, EVL_Event);
|
sess->AddEventList(INTELLIPAP_Unknown2, EVL_Event);
|
||||||
@ -271,6 +353,7 @@ int IntellipapLoader::Open(QString path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
long pos = 0;
|
long pos = 0;
|
||||||
|
int rampval = 0;
|
||||||
|
|
||||||
for (int i = 0; i < recs; i++) {
|
for (int i = 0; i < recs; i++) {
|
||||||
// convert timestamp to real epoch
|
// convert timestamp to real epoch
|
||||||
@ -284,16 +367,61 @@ int IntellipapLoader::Open(QString path)
|
|||||||
if ((ts1 >= (quint32)sid) && (ts1 <= SessionEnd[j])) {
|
if ((ts1 >= (quint32)sid) && (ts1 <= SessionEnd[j])) {
|
||||||
Session *sess = Sessions[sid];
|
Session *sess = Sessions[sid];
|
||||||
qint64 time = quint64(ts1) * 1000L;
|
qint64 time = quint64(ts1) * 1000L;
|
||||||
sess->eventlist[CPAP_Pressure][0]->AddEvent(time, m_buffer[pos + 0xd] / 10.0); // current pressure
|
sess->settings[CPAP_Mode] = mode;
|
||||||
sess->eventlist[CPAP_EPAP][0]->AddEvent(time, m_buffer[pos + 0x13] / 10.0); // epap / low
|
|
||||||
sess->eventlist[CPAP_IPAP][0]->AddEvent(time, m_buffer[pos + 0x14] / 10.0); // ipap / high
|
int minp = m_buffer[pos + 0x13];
|
||||||
|
int maxp = m_buffer[pos + 0x14];
|
||||||
|
int ps = m_buffer[pos + 0x15];
|
||||||
|
int pres = m_buffer[pos + 0xd];
|
||||||
|
|
||||||
|
if (mode >= MODE_BILEVEL_FIXED) {
|
||||||
|
|
||||||
|
sess->settings[CPAP_EPAP] = float(minp) / 10.0;
|
||||||
|
sess->settings[CPAP_IPAP] = float(maxp) / 10.0;
|
||||||
|
|
||||||
|
sess->settings[CPAP_PS] = float(ps) / 10.0;
|
||||||
|
|
||||||
|
|
||||||
|
sess->eventlist[CPAP_IPAP][0]->AddEvent(time, float(pres) / 10.0);
|
||||||
|
sess->eventlist[CPAP_EPAP][0]->AddEvent(time, float(pres-ps) / 10.0);
|
||||||
|
rampval = maxp;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
sess->eventlist[CPAP_Pressure][0]->AddEvent(time, float(pres) / 10.0); // current pressure
|
||||||
|
rampval = minp;
|
||||||
|
|
||||||
|
if (mode == MODE_APAP) {
|
||||||
|
sess->settings[CPAP_PressureMin] = float(minp) / 10.0;
|
||||||
|
sess->settings[CPAP_PressureMax] = float(maxp) / 10.0;
|
||||||
|
} else if (mode == MODE_CPAP) {
|
||||||
|
sess->settings[CPAP_Pressure] = float(maxp) / 10.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
qint64 rs = rampstart[sid];
|
||||||
|
|
||||||
|
if (pres < rampval) {
|
||||||
|
if (!rs) {
|
||||||
|
rampstart[sid] = time;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (rs > 0) {
|
||||||
|
if (!sess->eventlist.contains(CPAP_Ramp)) {
|
||||||
|
sess->AddEventList(CPAP_Ramp, EVL_Event);
|
||||||
|
}
|
||||||
|
int duration = (time - rs) / 1000L;
|
||||||
|
sess->eventlist[CPAP_Ramp][0]->AddEvent(time, duration);
|
||||||
|
|
||||||
|
rampstart[sid] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
sess->eventlist[CPAP_LeakTotal][0]->AddEvent(time, m_buffer[pos + 0x7]); // "Average Leak"
|
sess->eventlist[CPAP_LeakTotal][0]->AddEvent(time, m_buffer[pos + 0x7]); // "Average Leak"
|
||||||
sess->eventlist[CPAP_MaxLeak][0]->AddEvent(time, m_buffer[pos + 0x6]); // "Max Leak"
|
sess->eventlist[CPAP_MaxLeak][0]->AddEvent(time, m_buffer[pos + 0x6]); // "Max Leak"
|
||||||
|
|
||||||
int rr = m_buffer[pos + 0xa];
|
int rr = m_buffer[pos + 0xa];
|
||||||
sess->eventlist[CPAP_RespRate][0]->AddEvent(time, rr); // Respiratory Rate
|
sess->eventlist[CPAP_RespRate][0]->AddEvent(time, rr); // Respiratory Rate
|
||||||
sess->eventlist[INTELLIPAP_Unknown1][0]->AddEvent(time, m_buffer[pos + 0xf]); //
|
// sess->eventlist[INTELLIPAP_Unknown1][0]->AddEvent(time, m_buffer[pos + 0xf]); //
|
||||||
sess->eventlist[INTELLIPAP_Unknown1][0]->AddEvent(time, m_buffer[pos + 0xc]);
|
sess->eventlist[INTELLIPAP_Unknown1][0]->AddEvent(time, m_buffer[pos + 0xc]);
|
||||||
|
|
||||||
sess->eventlist[CPAP_Snore][0]->AddEvent(time, m_buffer[pos + 0x4]); //4/5??
|
sess->eventlist[CPAP_Snore][0]->AddEvent(time, m_buffer[pos + 0x4]); //4/5??
|
||||||
@ -314,9 +442,9 @@ int IntellipapLoader::Open(QString path)
|
|||||||
sess->AddEventList(CPAP_ExP, EVL_Event);
|
sess->AddEventList(CPAP_ExP, EVL_Event);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int q = 0; q < m_buffer[pos + 0x5]; q++) {
|
// for (int q = 0; q < m_buffer[pos + 0x5]; q++) {
|
||||||
sess->eventlist[CPAP_ExP][0]->AddEvent(time, m_buffer[pos + 0x5]);
|
sess->eventlist[CPAP_ExP][0]->AddEvent(time, m_buffer[pos + 0x5]);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_buffer[pos + 0x10] > 0) {
|
if (m_buffer[pos + 0x10] > 0) {
|
||||||
@ -324,9 +452,9 @@ int IntellipapLoader::Open(QString path)
|
|||||||
sess->AddEventList(CPAP_Obstructive, EVL_Event);
|
sess->AddEventList(CPAP_Obstructive, EVL_Event);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int q = 0; q < m_buffer[pos + 0x10]; q++) {
|
// for (int q = 0; q < m_buffer[pos + 0x10]; q++) {
|
||||||
sess->eventlist[CPAP_Obstructive][0]->AddEvent(time, m_buffer[pos + 0x10]);
|
sess->eventlist[CPAP_Obstructive][0]->AddEvent(time, m_buffer[pos + 0x10]);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_buffer[pos + 0x11] > 0) {
|
if (m_buffer[pos + 0x11] > 0) {
|
||||||
@ -334,9 +462,9 @@ int IntellipapLoader::Open(QString path)
|
|||||||
sess->AddEventList(CPAP_Hypopnea, EVL_Event);
|
sess->AddEventList(CPAP_Hypopnea, EVL_Event);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int q = 0; q < m_buffer[pos + 0x11]; q++) {
|
// for (int q = 0; q < m_buffer[pos + 0x11]; q++) {
|
||||||
sess->eventlist[CPAP_Hypopnea][0]->AddEvent(time, m_buffer[pos + 0x11]);
|
sess->eventlist[CPAP_Hypopnea][0]->AddEvent(time, m_buffer[pos + 0x11]);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_buffer[pos + 0x12] > 0) { // NRI // is this == to RERA?? CA??
|
if (m_buffer[pos + 0x12] > 0) { // NRI // is this == to RERA?? CA??
|
||||||
@ -344,9 +472,9 @@ int IntellipapLoader::Open(QString path)
|
|||||||
sess->AddEventList(CPAP_NRI, EVL_Event);
|
sess->AddEventList(CPAP_NRI, EVL_Event);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int q = 0; q < m_buffer[pos + 0x12]; q++) {
|
// for (int q = 0; q < m_buffer[pos + 0x12]; q++) {
|
||||||
sess->eventlist[CPAP_NRI][0]->AddEvent(time, m_buffer[pos + 0x12]);
|
sess->eventlist[CPAP_NRI][0]->AddEvent(time, m_buffer[pos + 0x12]);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
quint16 tv = (m_buffer[pos + 0x8] << 8) | m_buffer[pos + 0x9]; // correct
|
quint16 tv = (m_buffer[pos + 0x8] << 8) | m_buffer[pos + 0x9]; // correct
|
||||||
@ -368,47 +496,45 @@ int IntellipapLoader::Open(QString path)
|
|||||||
|
|
||||||
if (sid) {
|
if (sid) {
|
||||||
sess = Sessions[sid];
|
sess = Sessions[sid];
|
||||||
//if (sess->eventlist.size()==0) {
|
|
||||||
// delete sess;
|
|
||||||
// continue;
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
quint64 first = qint64(sid) * 1000L;
|
quint64 first = qint64(sid) * 1000L;
|
||||||
quint64 last = qint64(SessionEnd[i]) * 1000L;
|
quint64 last = qint64(SessionEnd[i]) * 1000L;
|
||||||
|
|
||||||
sess->settings[CPAP_PresReliefType] = (PRTypes)PR_SMARTFLEX;
|
sess->settings[CPAP_PresReliefType] = (PRTypes)PR_SMARTFLEX;
|
||||||
int i = set1["SmartFlex"].toInt();
|
|
||||||
sess->settings[CPAP_PresReliefSet] = i;
|
|
||||||
int sfm = set1["SmartFlexMode"].toInt();
|
|
||||||
|
|
||||||
if (sfm == 0) {
|
sess->settings[CPAP_PresReliefSet] = smartflex;
|
||||||
|
|
||||||
|
if (smartflexmode == 0) {
|
||||||
sess->settings[CPAP_PresReliefMode] = PM_FullTime;
|
sess->settings[CPAP_PresReliefMode] = PM_FullTime;
|
||||||
} else {
|
} else {
|
||||||
sess->settings[CPAP_PresReliefMode] = PM_RampOnly;
|
sess->settings[CPAP_PresReliefMode] = PM_RampOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
EventDataType max = sess->Max(CPAP_IPAP);
|
sess->settings[CPAP_RampPressure] = ramp_pressure;
|
||||||
EventDataType min = sess->Min(CPAP_EPAP);
|
sess->settings[CPAP_RampTime] = ramp_time;
|
||||||
EventDataType pres = sess->Min(CPAP_Pressure);
|
|
||||||
|
|
||||||
if (max == min) {
|
|
||||||
sess->settings[CPAP_Mode] = (int)MODE_CPAP;
|
|
||||||
sess->settings[CPAP_Pressure] = min;
|
|
||||||
} else {
|
|
||||||
sess->settings[CPAP_Mode] = (int)MODE_APAP;
|
|
||||||
sess->settings[CPAP_PressureMin] = min;
|
|
||||||
sess->settings[CPAP_PressureMax] = max;
|
|
||||||
}
|
|
||||||
|
|
||||||
sess->eventlist.erase(sess->eventlist.find(CPAP_IPAP));
|
// EventDataType max = sess->Max(CPAP_IPAP);
|
||||||
sess->eventlist.erase(sess->eventlist.find(CPAP_EPAP));
|
// EventDataType min = sess->Min(CPAP_EPAP);
|
||||||
sess->m_min.erase(sess->m_min.find(CPAP_EPAP));
|
// EventDataType pres = sess->Min(CPAP_Pressure);
|
||||||
sess->m_max.erase(sess->m_max.find(CPAP_EPAP));
|
|
||||||
|
|
||||||
if (pres < min) {
|
// if (max == min) {
|
||||||
sess->settings[CPAP_RampPressure] = pres;
|
// sess->settings[CPAP_Mode] = (int)MODE_CPAP;
|
||||||
}
|
// sess->settings[CPAP_Pressure] = min;
|
||||||
|
// } else {
|
||||||
|
// sess->settings[CPAP_Mode] = (int)MODE_APAP;
|
||||||
|
// sess->settings[CPAP_PressureMin] = min;
|
||||||
|
// sess->settings[CPAP_PressureMax] = max;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// sess->eventlist.erase(sess->eventlist.find(CPAP_IPAP));
|
||||||
|
// sess->eventlist.erase(sess->eventlist.find(CPAP_EPAP));
|
||||||
|
// sess->m_min.erase(sess->m_min.find(CPAP_EPAP));
|
||||||
|
// sess->m_max.erase(sess->m_max.find(CPAP_EPAP));
|
||||||
|
|
||||||
|
// if (pres < min) {
|
||||||
|
// sess->settings[CPAP_RampPressure] = pres;
|
||||||
|
// }
|
||||||
|
|
||||||
sess->set_first(first);
|
sess->set_first(first);
|
||||||
sess->set_last(last);
|
sess->set_last(last);
|
||||||
@ -418,8 +544,6 @@ int IntellipapLoader::Open(QString path)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mach->properties[STR_PROP_DataVersion] = QString().sprintf("%i", intellipap_data_version);
|
|
||||||
|
|
||||||
mach->Save();
|
mach->Save();
|
||||||
|
|
||||||
delete [] m_buffer;
|
delete [] m_buffer;
|
||||||
@ -431,52 +555,6 @@ int IntellipapLoader::Open(QString path)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Machine *IntellipapLoader::CreateMachine(QString serial)
|
|
||||||
{
|
|
||||||
Q_ASSERT(p_profile != nullptr);
|
|
||||||
|
|
||||||
qDebug() << "Create Machine " << serial;
|
|
||||||
|
|
||||||
QList<Machine *> ml = p_profile->GetMachines(MT_CPAP);
|
|
||||||
bool found = false;
|
|
||||||
QList<Machine *>::iterator i;
|
|
||||||
Machine *m = nullptr;
|
|
||||||
|
|
||||||
for (i = ml.begin(); i != ml.end(); i++) {
|
|
||||||
if (((*i)->GetClass() == intellipap_class_name) && ((*i)->properties[STR_PROP_Serial] == serial)) {
|
|
||||||
MachList[serial] = *i; //static_cast<CPAP *>(*i);
|
|
||||||
found = true;
|
|
||||||
m = *i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
m = new Intellipap(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
m->properties[STR_PROP_Brand] = "DeVilbiss";
|
|
||||||
m->properties[STR_PROP_Series] = STR_MACH_Intellipap;
|
|
||||||
|
|
||||||
if (found) {
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
MachList[serial] = m;
|
|
||||||
p_profile->AddMachine(m);
|
|
||||||
|
|
||||||
m->properties[STR_PROP_Serial] = serial;
|
|
||||||
m->properties[STR_PROP_DataVersion] = QString::number(intellipap_data_version);
|
|
||||||
|
|
||||||
QString path = "{" + STR_GEN_DataFolder + "}/" + m->GetClass() + "_" + serial + "/";
|
|
||||||
m->properties[STR_PROP_Path] = path;
|
|
||||||
m->properties[STR_PROP_BackupPath] = path + "Backup/";
|
|
||||||
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool intellipap_initialized = false;
|
bool intellipap_initialized = false;
|
||||||
void IntellipapLoader::Register()
|
void IntellipapLoader::Register()
|
||||||
{
|
{
|
||||||
|
@ -62,13 +62,17 @@ class IntellipapLoader : public MachineLoader
|
|||||||
virtual int Version() { return intellipap_data_version; }
|
virtual int Version() { return intellipap_data_version; }
|
||||||
|
|
||||||
//! \brief Returns the machine class name of this IntelliPap, "Intellipap"
|
//! \brief Returns the machine class name of this IntelliPap, "Intellipap"
|
||||||
virtual const QString &ClassName() { return intellipap_class_name; }
|
virtual const QString &loaderName() { return intellipap_class_name; }
|
||||||
|
|
||||||
//! \brief Creates a machine object, indexed by serial number
|
//! \brief Creates a machine object, indexed by serial number
|
||||||
Machine *CreateMachine(QString serial);
|
// Machine *CreateMachine(QString serial);
|
||||||
|
|
||||||
//! \brief Registers this MachineLoader with the master list, so Intellipap data can load
|
//! \brief Registers this MachineLoader with the master list, so Intellipap data can load
|
||||||
static void Register();
|
static void Register();
|
||||||
|
|
||||||
|
virtual MachineInfo newInfo() {
|
||||||
|
return MachineInfo(MT_CPAP, intellipap_class_name, QObject::tr("DeVilbiss"), QString(), QString(), QString(), QObject::tr("Intellipap"), QDateTime::currentDateTime(), intellipap_data_version);
|
||||||
|
}
|
||||||
protected:
|
protected:
|
||||||
QString last;
|
QString last;
|
||||||
QHash<QString, Machine *> MachList;
|
QHash<QString, Machine *> MachList;
|
||||||
|
@ -221,37 +221,6 @@ bool MD300W1Loader::readDATFile(QString path)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Machine *MD300W1Loader::CreateMachine()
|
|
||||||
{
|
|
||||||
Q_ASSERT(p_profile);
|
|
||||||
|
|
||||||
// NOTE: This only allows for one MD300W1 machine per profile..
|
|
||||||
// Upgrading their oximeter will use this same record..
|
|
||||||
|
|
||||||
QList<Machine *> ml = p_profile->GetMachines(MT_OXIMETER);
|
|
||||||
|
|
||||||
for (QList<Machine *>::iterator i = ml.begin(); i != ml.end(); i++) {
|
|
||||||
if ((*i)->GetClass() == md300w1_class_name) {
|
|
||||||
return (*i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
qDebug() << "Create MD300W1 Machine Record";
|
|
||||||
|
|
||||||
Machine *m = new Oximeter(0);
|
|
||||||
m->SetClass(md300w1_class_name);
|
|
||||||
m->properties[STR_PROP_Brand] = "ChoiceMMed";
|
|
||||||
m->properties[STR_PROP_Model] = "MD300W1";
|
|
||||||
m->properties[STR_PROP_DataVersion] = QString::number(md300w1_data_version);
|
|
||||||
|
|
||||||
p_profile->AddMachine(m);
|
|
||||||
QString path = "{" + STR_GEN_DataFolder + "}/" + m->GetClass() + "_" + m->hexid() + "/";
|
|
||||||
m->properties[STR_PROP_Path] = path;
|
|
||||||
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MD300W1Loader::process()
|
void MD300W1Loader::process()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -36,9 +36,14 @@ Q_OBJECT
|
|||||||
static void Register();
|
static void Register();
|
||||||
|
|
||||||
virtual int Version() { return md300w1_data_version; }
|
virtual int Version() { return md300w1_data_version; }
|
||||||
virtual const QString &ClassName() { return md300w1_class_name; }
|
virtual const QString &loaderName() { return md300w1_class_name; }
|
||||||
|
|
||||||
|
// Machine *CreateMachine();
|
||||||
|
|
||||||
|
virtual MachineInfo newInfo() {
|
||||||
|
return MachineInfo(MT_OXIMETER, md300w1_class_name, QObject::tr("ChoiceMMed"), QString(), QString(), QString(), QObject::tr("MD300"), QDateTime::currentDateTime(), md300w1_data_version);
|
||||||
|
}
|
||||||
|
|
||||||
Machine *CreateMachine();
|
|
||||||
|
|
||||||
virtual void process();
|
virtual void process();
|
||||||
|
|
||||||
|
@ -20,9 +20,6 @@ extern QProgressBar *qprogress;
|
|||||||
MSeries::MSeries(MachineID id)
|
MSeries::MSeries(MachineID id)
|
||||||
: CPAP(id)
|
: CPAP(id)
|
||||||
{
|
{
|
||||||
m_class = mseries_class_name;
|
|
||||||
properties[STR_PROP_Brand] = "Respironics";
|
|
||||||
properties[STR_PROP_Model] = STR_MACH_MSeries;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MSeries::~MSeries()
|
MSeries::~MSeries()
|
||||||
@ -484,40 +481,6 @@ int MSeriesLoader::Open(QString path)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Machine *MSeriesLoader::CreateMachine(QString serial)
|
|
||||||
{
|
|
||||||
Q_ASSERT(p_profile != nullptr);
|
|
||||||
|
|
||||||
qDebug() << "Create Machine " << serial;
|
|
||||||
|
|
||||||
QList<Machine *> ml = p_profile->GetMachines(MT_CPAP);
|
|
||||||
bool found = false;
|
|
||||||
QList<Machine *>::iterator i;
|
|
||||||
|
|
||||||
for (i = ml.begin(); i != ml.end(); i++) {
|
|
||||||
if (((*i)->GetClass() == mseries_class_name) && ((*i)->properties[STR_PROP_Serial] == serial)) {
|
|
||||||
MachList[serial] = *i;
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (found) { return *i; }
|
|
||||||
|
|
||||||
Machine *m = new MSeries(0);
|
|
||||||
|
|
||||||
MachList[serial] = m;
|
|
||||||
p_profile->AddMachine(m);
|
|
||||||
|
|
||||||
m->properties[STR_PROP_Serial] = serial;
|
|
||||||
m->properties[STR_PROP_DataVersion] = QString::number(mseries_data_version);
|
|
||||||
|
|
||||||
QString path = "{" + STR_GEN_DataFolder + "}/" + m->GetClass() + "_" + serial + "/";
|
|
||||||
m->properties[STR_PROP_Path] = path;
|
|
||||||
m->properties[STR_PROP_BackupPath] = path + "Backup/";
|
|
||||||
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool mseries_initialized = false;
|
bool mseries_initialized = false;
|
||||||
void MSeriesLoader::Register()
|
void MSeriesLoader::Register()
|
||||||
|
@ -56,11 +56,15 @@ class MSeriesLoader : public MachineLoader
|
|||||||
//! \brief Returns the database version of this loader
|
//! \brief Returns the database version of this loader
|
||||||
virtual int Version() { return mseries_data_version; }
|
virtual int Version() { return mseries_data_version; }
|
||||||
|
|
||||||
//! \brief Return the ClassName, in this case "MSeries"
|
//! \brief Return the loaderName, in this case "MSeries"
|
||||||
virtual const QString &ClassName() { return mseries_class_name; }
|
virtual const QString &loaderName() { return mseries_class_name; }
|
||||||
|
|
||||||
//! \brief Create a new PRS1 machine record, indexed by Serial number.
|
//! \brief Create a new PRS1 machine record, indexed by Serial number.
|
||||||
Machine *CreateMachine(QString serial);
|
// Machine *CreateMachine(QString serial);
|
||||||
|
|
||||||
|
virtual MachineInfo newInfo() {
|
||||||
|
return MachineInfo(MT_CPAP, mseries_class_name, QObject::tr("Respironics"), QString(), QString(), QString(), QObject::tr("M-Series"), QDateTime::currentDateTime(), mseries_data_version);
|
||||||
|
}
|
||||||
|
|
||||||
//! \brief Register this Module to the list of Loaders, so it knows to search for PRS1 data.
|
//! \brief Register this Module to the list of Loaders, so it knows to search for PRS1 data.
|
||||||
static void Register();
|
static void Register();
|
||||||
|
@ -101,7 +101,6 @@ crc_t CRC16(const unsigned char *data, size_t data_len)
|
|||||||
|
|
||||||
PRS1::PRS1(MachineID id): CPAP(id)
|
PRS1::PRS1(MachineID id): CPAP(id)
|
||||||
{
|
{
|
||||||
m_class = prs1_class_name;
|
|
||||||
}
|
}
|
||||||
PRS1::~PRS1()
|
PRS1::~PRS1()
|
||||||
{
|
{
|
||||||
@ -130,49 +129,7 @@ PRS1Loader::PRS1Loader()
|
|||||||
PRS1Loader::~PRS1Loader()
|
PRS1Loader::~PRS1Loader()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
Machine *PRS1Loader::CreateMachine(QString serial)
|
|
||||||
{
|
|
||||||
Q_ASSERT(p_profile != nullptr);
|
|
||||||
|
|
||||||
qDebug() << "Create Machine " << serial;
|
|
||||||
|
|
||||||
QList<Machine *> ml = p_profile->GetMachines(MT_CPAP);
|
|
||||||
bool found = false;
|
|
||||||
QList<Machine *>::iterator i;
|
|
||||||
Machine *m = nullptr;
|
|
||||||
|
|
||||||
for (i = ml.begin(); i != ml.end(); i++) {
|
|
||||||
if (((*i)->GetClass() == STR_MACH_PRS1) && ((*i)->properties[STR_PROP_Serial] == serial)) {
|
|
||||||
PRS1List[serial] = *i; //static_cast<CPAP *>(*i);
|
|
||||||
found = true;
|
|
||||||
m = *i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
m = new PRS1(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
m->properties[STR_PROP_Brand] = "Philips Respironics";
|
|
||||||
m->properties[STR_PROP_Series] = "System One";
|
|
||||||
|
|
||||||
if (found) {
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
PRS1List[serial] = m;
|
|
||||||
p_profile->AddMachine(m);
|
|
||||||
|
|
||||||
m->properties[STR_PROP_Serial] = serial;
|
|
||||||
m->properties[STR_PROP_DataVersion] = QString::number(prs1_data_version);
|
|
||||||
|
|
||||||
QString path = "{" + STR_GEN_DataFolder + "}/" + m->GetClass() + "_" + serial + "/";
|
|
||||||
m->properties[STR_PROP_Path] = path;
|
|
||||||
m->properties[STR_PROP_BackupPath] = path + "Backup/";
|
|
||||||
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
bool isdigit(QChar c)
|
bool isdigit(QChar c)
|
||||||
{
|
{
|
||||||
if ((c >= '0') && (c <= '9')) { return true; }
|
if ((c >= '0') && (c <= '9')) { return true; }
|
||||||
@ -282,17 +239,18 @@ int PRS1Loader::Open(QString path)
|
|||||||
Machine *m;
|
Machine *m;
|
||||||
|
|
||||||
for (sn = SerialNumbers.begin(); sn != SerialNumbers.end(); sn++) {
|
for (sn = SerialNumbers.begin(); sn != SerialNumbers.end(); sn++) {
|
||||||
QString s = *sn;
|
MachineInfo info = newInfo();
|
||||||
m = CreateMachine(s);
|
info.serial = *sn;
|
||||||
|
m = CreateMachine(info);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (m) {
|
if (m) {
|
||||||
OpenMachine(m, newpath + "/" + (*sn));
|
OpenMachine(m, newpath + "/" + info.serial);
|
||||||
}
|
}
|
||||||
} catch (OneTypePerDay e) {
|
} catch (OneTypePerDay e) {
|
||||||
Q_UNUSED(e)
|
Q_UNUSED(e)
|
||||||
p_profile->DelMachine(m);
|
p_profile->DelMachine(m);
|
||||||
PRS1List.erase(PRS1List.find(s));
|
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."),
|
QObject::tr("This Machine Record cannot be imported in this profile.\nThe Day records overlap with already existing content."),
|
||||||
QMessageBox::Ok);
|
QMessageBox::Ok);
|
||||||
@ -320,11 +278,11 @@ bool PRS1Loader::ParseProperties(Machine *m, QString filename)
|
|||||||
QString key, value;
|
QString key, value;
|
||||||
|
|
||||||
while (!f.atEnd()) {
|
while (!f.atEnd()) {
|
||||||
key = s.section(sep, 0, 0); //BeforeFirst(sep);
|
key = s.section(sep, 0, 0);
|
||||||
|
|
||||||
if (key == s) { continue; }
|
if (key == s) { continue; }
|
||||||
|
|
||||||
value = s.section(sep, 1).trimmed(); //AfterFirst(sep).Strip();
|
value = s.section(sep, 1).trimmed();
|
||||||
|
|
||||||
if (value == s) { continue; }
|
if (value == s) { continue; }
|
||||||
|
|
||||||
@ -338,11 +296,11 @@ bool PRS1Loader::ParseProperties(Machine *m, QString filename)
|
|||||||
|
|
||||||
if (ok) {
|
if (ok) {
|
||||||
if (ModelMap.find(i) != ModelMap.end()) {
|
if (ModelMap.find(i) != ModelMap.end()) {
|
||||||
m->properties[STR_PROP_Model] = ModelMap[i];
|
m->setModel(ModelMap[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prop["SerialNumber"] != m->properties[STR_PROP_Serial]) {
|
if (prop["SerialNumber"] != m->serial()) {
|
||||||
qDebug() << "Serial Number in PRS1 properties.txt doesn't match directory structure";
|
qDebug() << "Serial Number in PRS1 properties.txt doesn't match directory structure";
|
||||||
} else { prop.erase(prop.find("SerialNumber")); } // already got it stored.
|
} else { prop.erase(prop.find("SerialNumber")); } // already got it stored.
|
||||||
|
|
||||||
@ -354,31 +312,6 @@ bool PRS1Loader::ParseProperties(Machine *m, QString filename)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void copyPath(QString src, QString dst)
|
|
||||||
{
|
|
||||||
QDir dir(src);
|
|
||||||
if (!dir.exists())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Recursively handle directories
|
|
||||||
foreach (QString d, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) {
|
|
||||||
QString dst_path = dst + QDir::separator() + d;
|
|
||||||
dir.mkpath(dst_path);
|
|
||||||
copyPath(src + QDir::separator() + d, dst_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Files
|
|
||||||
foreach (QString f, dir.entryList(QDir::Files)) {
|
|
||||||
QString srcFile = src + QDir::separator() + f;
|
|
||||||
QString destFile = dst + QDir::separator() + f;
|
|
||||||
|
|
||||||
if (!QFile::exists(destFile)) {
|
|
||||||
QFile::copy(srcFile, destFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int PRS1Loader::OpenMachine(Machine *m, QString path)
|
int PRS1Loader::OpenMachine(Machine *m, QString path)
|
||||||
{
|
{
|
||||||
Q_ASSERT(p_profile != nullptr);
|
Q_ASSERT(p_profile != nullptr);
|
||||||
@ -389,9 +322,9 @@ int PRS1Loader::OpenMachine(Machine *m, QString path)
|
|||||||
if (!dir.exists() || (!dir.isReadable())) {
|
if (!dir.exists() || (!dir.isReadable())) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
QString backupPath = p_profile->Get(m->properties[STR_PROP_BackupPath]) + path.section("/", -2);
|
QString backupPath = m->getBackupPath() + path.section("/", -2);
|
||||||
|
|
||||||
if (dir.absolutePath().compare(QDir(backupPath).absolutePath()) != 0) {
|
if (QDir::cleanPath(path).compare(QDir::cleanPath(backupPath)) != 0) {
|
||||||
copyPath(path, backupPath);
|
copyPath(path, backupPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,7 +353,7 @@ int PRS1Loader::OpenMachine(Machine *m, QString path)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString modelstr = m->properties["ModelNumber"];
|
QString modelstr = m->modelnumber();
|
||||||
|
|
||||||
if (modelstr.endsWith("P"))
|
if (modelstr.endsWith("P"))
|
||||||
modelstr.chop(1);
|
modelstr.chop(1);
|
||||||
@ -434,7 +367,7 @@ int PRS1Loader::OpenMachine(Machine *m, QString path)
|
|||||||
QObject::tr("Non Data Capable Machine"),
|
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"+
|
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 for this machine.")).
|
||||||
arg(m->properties["ModelNumber"]),QMessageBox::Ok);
|
arg(m->modelnumber()),QMessageBox::Ok);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -448,7 +381,7 @@ int PRS1Loader::OpenMachine(Machine *m, QString path)
|
|||||||
|
|
||||||
SessionID sid;
|
SessionID sid;
|
||||||
long ext;
|
long ext;
|
||||||
QHash<SessionID, QStringList> sessfiles;
|
|
||||||
int size = paths.size();
|
int size = paths.size();
|
||||||
|
|
||||||
prs1sessions.clear();
|
prs1sessions.clear();
|
||||||
@ -457,8 +390,6 @@ int PRS1Loader::OpenMachine(Machine *m, QString path)
|
|||||||
|
|
||||||
// Note, I have observed p0/p1/etc folders containing duplicates session files (in Robin Sanders data.)
|
// Note, I have observed p0/p1/etc folders containing duplicates session files (in Robin Sanders data.)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// for each p0/p1/p2/etc... folder
|
// for each p0/p1/p2/etc... folder
|
||||||
for (int p=0; p < size; ++p) {
|
for (int p=0; p < size; ++p) {
|
||||||
dir.setPath(paths.at(p));
|
dir.setPath(paths.at(p));
|
||||||
@ -1496,7 +1427,7 @@ void PRS1Import::run()
|
|||||||
|
|
||||||
// Save is not threadsafe
|
// Save is not threadsafe
|
||||||
loader->saveMutex.lock();
|
loader->saveMutex.lock();
|
||||||
sg->session->Store(p_profile->Get(mach->properties[STR_PROP_Path]));
|
sg->session->Store(mach->getDataPath());
|
||||||
loader->saveMutex.unlock();
|
loader->saveMutex.unlock();
|
||||||
|
|
||||||
sg->session->TrashEvents();
|
sg->session->TrashEvents();
|
||||||
|
@ -189,15 +189,20 @@ class PRS1Loader : public MachineLoader
|
|||||||
//! \brief Returns the database version of this loader
|
//! \brief Returns the database version of this loader
|
||||||
virtual int Version() { return prs1_data_version; }
|
virtual int Version() { return prs1_data_version; }
|
||||||
|
|
||||||
//! \brief Return the ClassName, in this case "PRS1"
|
//! \brief Return the loaderName, in this case "PRS1"
|
||||||
virtual const QString &ClassName() { return prs1_class_name; }
|
virtual const QString &loaderName() { return prs1_class_name; }
|
||||||
|
|
||||||
//! \brief Create a new PRS1 machine record, indexed by Serial number.
|
// //! \brief Create a new PRS1 machine record, indexed by Serial number.
|
||||||
Machine *CreateMachine(QString serial);
|
//Machine *CreateMachine(QString serial);
|
||||||
|
|
||||||
//! \brief Register this Module to the list of Loaders, so it knows to search for PRS1 data.
|
//! \brief Register this Module to the list of Loaders, so it knows to search for PRS1 data.
|
||||||
static void Register();
|
static void Register();
|
||||||
|
|
||||||
|
virtual MachineInfo newInfo() {
|
||||||
|
return MachineInfo(MT_CPAP, prs1_class_name, QObject::tr("Philips Respironics"), QString(), QString(), QString(), QObject::tr("System One"), QDateTime::currentDateTime(), prs1_data_version);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
QHash<SessionID, PRS1FileGroup*> prs1sessions;
|
QHash<SessionID, PRS1FileGroup*> prs1sessions;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -130,8 +130,8 @@ void ResmedLoader::ParseSTR(Machine *mach, QStringList strfiles)
|
|||||||
for (QStringList::iterator it = strfiles.begin(); it != strend; ++it) {
|
for (QStringList::iterator it = strfiles.begin(); it != strend; ++it) {
|
||||||
EDFParser str(*it);
|
EDFParser str(*it);
|
||||||
if (!str.Parse()) continue;
|
if (!str.Parse()) continue;
|
||||||
if (mach->properties[STR_PROP_Serial] != str.serialnumber) {
|
if (mach->serial() != str.serialnumber) {
|
||||||
qDebug() << "Trying to import a STR.edf from another machine, skipping" << mach->properties[STR_PROP_Serial] << str.serialnumber;
|
qDebug() << "Trying to import a STR.edf from another machine, skipping" << mach->serial() << str.serialnumber;
|
||||||
qDebug() << (*it);
|
qDebug() << (*it);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -750,7 +750,7 @@ void ResmedImport::run()
|
|||||||
|
|
||||||
// Save is not threadsafe
|
// Save is not threadsafe
|
||||||
loader->saveMutex.lock();
|
loader->saveMutex.lock();
|
||||||
sess->Store(p_profile->Get(mach->properties[STR_PROP_Path]));
|
sess->Store(mach->getDataPath());
|
||||||
loader->saveMutex.unlock();
|
loader->saveMutex.unlock();
|
||||||
|
|
||||||
// Free the memory used by this session
|
// Free the memory used by this session
|
||||||
@ -765,52 +765,6 @@ ResmedLoader::~ResmedLoader()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Machine *ResmedLoader::CreateMachine(QString serial)
|
|
||||||
{
|
|
||||||
Q_ASSERT(p_profile != nullptr);
|
|
||||||
|
|
||||||
QList<Machine *> ml = p_profile->GetMachines(MT_CPAP);
|
|
||||||
bool found = false;
|
|
||||||
QList<Machine *>::iterator i;
|
|
||||||
Machine *m = nullptr;
|
|
||||||
|
|
||||||
for (i = ml.begin(); i != ml.end(); i++) {
|
|
||||||
if (((*i)->GetClass() == resmed_class_name) && ((*i)->properties[STR_PROP_Serial] == serial)) {
|
|
||||||
ResmedList[serial] = *i;
|
|
||||||
found = true;
|
|
||||||
m = *i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
m = new CPAP(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
m->properties[STR_PROP_Brand] = STR_MACH_ResMed;
|
|
||||||
m->properties[STR_PROP_Series] = "S9";
|
|
||||||
|
|
||||||
if (found) {
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
qDebug() << "Create ResMed Machine" << serial;
|
|
||||||
m->SetClass(resmed_class_name);
|
|
||||||
|
|
||||||
ResmedList[serial] = m;
|
|
||||||
p_profile->AddMachine(m);
|
|
||||||
|
|
||||||
m->properties[STR_PROP_Serial] = serial;
|
|
||||||
m->properties[STR_PROP_DataVersion] = QString::number(resmed_data_version);
|
|
||||||
|
|
||||||
QString path = "{" + STR_GEN_DataFolder + "}/" + m->GetClass() + "_" + serial + "/";
|
|
||||||
m->properties[STR_PROP_Path] = path;
|
|
||||||
m->properties[STR_PROP_BackupPath] = path + "Backup/";
|
|
||||||
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ResmedImportStage2::run()
|
void ResmedImportStage2::run()
|
||||||
{
|
{
|
||||||
Session * sess = new Session(mach, R.maskon);
|
Session * sess = new Session(mach, R.maskon);
|
||||||
@ -910,7 +864,7 @@ void ResmedImportStage2::run()
|
|||||||
|
|
||||||
loader->saveMutex.lock();
|
loader->saveMutex.lock();
|
||||||
mach->AddSession(sess);
|
mach->AddSession(sess);
|
||||||
sess->Store(p_profile->Get(mach->properties[STR_PROP_Path]));
|
sess->Store(mach->getDataPath());
|
||||||
loader->saveMutex.unlock();
|
loader->saveMutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -943,6 +897,44 @@ bool ResmedLoader::Detect(const QString & givenpath)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MachineInfo ResmedLoader::PeekInfo(const QString & path)
|
||||||
|
{
|
||||||
|
if (!Detect(path)) return MachineInfo();
|
||||||
|
|
||||||
|
QFile f(path+"/"+RMS9_STR_idfile+"tgt");
|
||||||
|
|
||||||
|
// Abort if this file is dodgy..
|
||||||
|
if (!f.exists() || !f.open(QIODevice::ReadOnly)) {
|
||||||
|
return MachineInfo();
|
||||||
|
}
|
||||||
|
MachineInfo info = newInfo();
|
||||||
|
|
||||||
|
// Parse # entries into idmap.
|
||||||
|
while (!f.atEnd()) {
|
||||||
|
QString line = f.readLine().trimmed();
|
||||||
|
|
||||||
|
if (!line.isEmpty()) {
|
||||||
|
QString key = line.section(" ", 0, 0).section("#", 1);
|
||||||
|
QString value = line.section(" ", 1);
|
||||||
|
|
||||||
|
if (key == "SRN") { // Serial Number
|
||||||
|
info.serial = value;
|
||||||
|
|
||||||
|
} else if (key == "PNA") { // Product Name
|
||||||
|
value.replace("_"," ");
|
||||||
|
info.model = value;
|
||||||
|
|
||||||
|
} else if (key == "PCD") { // Product Code
|
||||||
|
info.modelnumber = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct EDFduration {
|
struct EDFduration {
|
||||||
EDFduration() { start = end = 0; }
|
EDFduration() { start = end = 0; }
|
||||||
EDFduration(const EDFduration & copy) {
|
EDFduration(const EDFduration & copy) {
|
||||||
@ -1071,14 +1063,12 @@ EDFduration getEDFDuration(QString filename)
|
|||||||
|
|
||||||
void ResmedLoader::scanFiles(Machine * mach, QString datalog_path)
|
void ResmedLoader::scanFiles(Machine * mach, QString datalog_path)
|
||||||
{
|
{
|
||||||
|
QHash<QString, SessionID> skipfiles;
|
||||||
|
|
||||||
bool create_backups = p_profile->session->backupCardData();
|
bool create_backups = p_profile->session->backupCardData();
|
||||||
|
|
||||||
QString backup_path = p_profile->Get(mach->properties[STR_PROP_BackupPath]);
|
QString backup_path = mach->getBackupPath();
|
||||||
|
|
||||||
if (backup_path.isEmpty()) {
|
|
||||||
backup_path = p_profile->Get(mach->properties[STR_PROP_Path]) + "Backup/";
|
|
||||||
}
|
|
||||||
QString dlog = datalog_path;
|
QString dlog = datalog_path;
|
||||||
|
|
||||||
if (datalog_path == backup_path + RMS9_STR_datalog + "/") {
|
if (datalog_path == backup_path + RMS9_STR_datalog + "/") {
|
||||||
@ -1086,15 +1076,13 @@ void ResmedLoader::scanFiles(Machine * mach, QString datalog_path)
|
|||||||
create_backups = false;
|
create_backups = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
skipfiles.clear();
|
|
||||||
|
|
||||||
// Read the already imported file list
|
// Read the already imported file list
|
||||||
QFile impfile(mach->getDataPath()+"/imported_files.csv");
|
QFile impfile(mach->getDataPath()+"/imported_files.csv");
|
||||||
if (impfile.open(QFile::ReadOnly)) {
|
if (impfile.open(QFile::ReadOnly)) {
|
||||||
QTextStream impstream(&impfile);
|
QTextStream impstream(&impfile);
|
||||||
QString serial;
|
QString serial;
|
||||||
impstream >> serial;
|
impstream >> serial;
|
||||||
if (mach->properties[STR_PROP_Serial] == serial) {
|
if (mach->serial() == serial) {
|
||||||
QString line, file, str;
|
QString line, file, str;
|
||||||
SessionID sid;
|
SessionID sid;
|
||||||
bool ok;
|
bool ok;
|
||||||
@ -1279,6 +1267,7 @@ void ResmedLoader::scanFiles(Machine * mach, QString datalog_path)
|
|||||||
|
|
||||||
if (impfile.open(QFile::WriteOnly)) {
|
if (impfile.open(QFile::WriteOnly)) {
|
||||||
QTextStream out(&impfile);
|
QTextStream out(&impfile);
|
||||||
|
out << mach->serial();
|
||||||
QHash<QString, SessionID>::iterator skit;
|
QHash<QString, SessionID>::iterator skit;
|
||||||
QHash<QString, SessionID>::iterator skit_end = skipfiles.end();
|
QHash<QString, SessionID>::iterator skit_end = skipfiles.end();
|
||||||
for (skit = skipfiles.begin(); skit != skit_end; ++skit) {
|
for (skit = skipfiles.begin(); skit != skit_end; ++skit) {
|
||||||
@ -1294,7 +1283,6 @@ void ResmedLoader::scanFiles(Machine * mach, QString datalog_path)
|
|||||||
int ResmedLoader::Open(QString path)
|
int ResmedLoader::Open(QString path)
|
||||||
{
|
{
|
||||||
|
|
||||||
QString serial; // Serial number
|
|
||||||
QString key, value;
|
QString key, value;
|
||||||
QString line;
|
QString line;
|
||||||
QString newpath;
|
QString newpath;
|
||||||
@ -1335,6 +1323,7 @@ int ResmedLoader::Open(QString path)
|
|||||||
if (!f.exists() || !f.open(QIODevice::ReadOnly)) {
|
if (!f.exists() || !f.open(QIODevice::ReadOnly)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
MachineInfo info = newInfo();
|
||||||
|
|
||||||
// Parse # entries into idmap.
|
// Parse # entries into idmap.
|
||||||
while (!f.atEnd()) {
|
while (!f.atEnd()) {
|
||||||
@ -1345,15 +1334,17 @@ int ResmedLoader::Open(QString path)
|
|||||||
value = line.section(" ", 1);
|
value = line.section(" ", 1);
|
||||||
|
|
||||||
if (key == "SRN") { // Serial Number
|
if (key == "SRN") { // Serial Number
|
||||||
key = STR_PROP_Serial;
|
info.serial = value;
|
||||||
serial = value;
|
continue;
|
||||||
|
|
||||||
} else if (key == "PNA") { // Product Name
|
} else if (key == "PNA") { // Product Name
|
||||||
key = STR_PROP_Model;
|
|
||||||
value.replace("_"," ");
|
value.replace("_"," ");
|
||||||
|
info.model = value;
|
||||||
|
continue;
|
||||||
|
|
||||||
} else if (key == "PCD") { // Product Code
|
} else if (key == "PCD") { // Product Code
|
||||||
key = STR_PROP_ModelNumber;
|
info.modelnumber = value;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
idmap[key] = value;
|
idmap[key] = value;
|
||||||
@ -1363,7 +1354,7 @@ int ResmedLoader::Open(QString path)
|
|||||||
f.close();
|
f.close();
|
||||||
|
|
||||||
// Abort if no serial number
|
// Abort if no serial number
|
||||||
if (serial.isEmpty()) {
|
if (info.serial.isEmpty()) {
|
||||||
qDebug() << "S9 Data card has no valid serial number in Indentification.tgt";
|
qDebug() << "S9 Data card has no valid serial number in Indentification.tgt";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1385,16 +1376,12 @@ int ResmedLoader::Open(QString path)
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
// Create machine object (unless it's already registered)
|
// Create machine object (unless it's already registered)
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
Machine *m = CreateMachine(serial);
|
Machine *m = CreateMachine(info);
|
||||||
|
|
||||||
bool create_backups = p_profile->session->backupCardData();
|
bool create_backups = p_profile->session->backupCardData();
|
||||||
bool compress_backups = p_profile->session->compressBackupData();
|
bool compress_backups = p_profile->session->compressBackupData();
|
||||||
|
|
||||||
QString backup_path = p_profile->Get(m->properties[STR_PROP_BackupPath]);
|
QString backup_path = m->getBackupPath();
|
||||||
|
|
||||||
if (backup_path.isEmpty()) {
|
|
||||||
backup_path = p_profile->Get(m->properties[STR_PROP_Path]) + "Backup/";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (path == backup_path) {
|
if (path == backup_path) {
|
||||||
// Don't create backups if importing from backup folder
|
// Don't create backups if importing from backup folder
|
||||||
@ -1437,7 +1424,7 @@ int ResmedLoader::Open(QString path)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stredf.serialnumber != serial) {
|
if (stredf.serialnumber != info.serial) {
|
||||||
qDebug() << "Identification.tgt Serial number doesn't match STR.edf!";
|
qDebug() << "Identification.tgt Serial number doesn't match STR.edf!";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1508,17 +1495,6 @@ int ResmedLoader::Open(QString path)
|
|||||||
|
|
||||||
int days = duration / 86400000L; // GetNumDataRecords = this.. Duh!
|
int days = duration / 86400000L; // GetNumDataRecords = this.. Duh!
|
||||||
|
|
||||||
//QDateTime dt1=QDateTime::fromTime_t(stredf.startdate/1000L);
|
|
||||||
//QDateTime dt2=QDateTime::fromTime_t(stredf.enddate/1000L);
|
|
||||||
//QDate dd1=dt1.date();
|
|
||||||
//QDate dd2=dt2.date();
|
|
||||||
|
|
||||||
// for (int s=0;s<stredf.GetNumSignals();s++) {
|
|
||||||
// EDFSignal &es = stredf.edfsignals[s];
|
|
||||||
// long recs=es.nr*stredf.GetNumDataRecords();
|
|
||||||
// //qDebug() << "STREDF:" << es.label << recs;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Process STR.edf and find first and last time for each day
|
// Process STR.edf and find first and last time for each day
|
||||||
|
|
||||||
QVector<qint8> dayused;
|
QVector<qint8> dayused;
|
||||||
@ -1530,167 +1506,9 @@ int ResmedLoader::Open(QString path)
|
|||||||
time = stredf.startdate / 1000;
|
time = stredf.startdate / 1000;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
// Open DATALOG file and build list of session files
|
// Scan DATALOG files, sort, and import any new sessions
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
scanFiles(m, newpath);
|
|
||||||
|
|
||||||
/* QStringList dirs;
|
|
||||||
dirs.push_back(newpath);
|
|
||||||
dir.setFilter(QDir::Dirs | QDir::Hidden | QDir::NoDotAndDotDot);
|
|
||||||
flist = dir.entryInfoList();
|
|
||||||
bool ok;
|
|
||||||
|
|
||||||
for (int i = 0; i < flist.size(); i++) {
|
|
||||||
QFileInfo fi = flist.at(i);
|
|
||||||
filename = fi.fileName();
|
|
||||||
|
|
||||||
if (filename.length() == 4) {
|
|
||||||
filename.toInt(&ok);
|
|
||||||
|
|
||||||
if (ok) {
|
|
||||||
dirs.push_back(fi.canonicalFilePath());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString datestr;
|
|
||||||
SessionID sessionid;
|
|
||||||
QDateTime date;
|
|
||||||
QString fullname;
|
|
||||||
QString edftypestr;
|
|
||||||
bool gz;
|
|
||||||
int size;
|
|
||||||
QMap<SessionID, QStringList>::iterator si;
|
|
||||||
|
|
||||||
sessfiles.clear();
|
|
||||||
|
|
||||||
QMap<SessionID, EDFGroup> filegroups;
|
|
||||||
QMap<SessionID, EDFGroup>::iterator fgit;
|
|
||||||
|
|
||||||
|
|
||||||
QStringList files;
|
|
||||||
|
|
||||||
enum EDF_Type {
|
|
||||||
ET_ERR=0, BRP, EVE, PLD, SAD
|
|
||||||
} edftype;
|
|
||||||
|
|
||||||
SessionID lastsession = 0;
|
|
||||||
|
|
||||||
for (int dc = 0; dc < dirs.size(); dc++) {
|
|
||||||
|
|
||||||
dir.setPath(dirs.at(dc));
|
|
||||||
dir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks);
|
|
||||||
dir.setSorting(QDir::Name);
|
|
||||||
flist = dir.entryInfoList();
|
|
||||||
|
|
||||||
size = flist.size();
|
|
||||||
|
|
||||||
|
|
||||||
// For each file in flist...
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
QFileInfo fi = flist.at(i);
|
|
||||||
filename = fi.fileName();
|
|
||||||
|
|
||||||
// Forget about it if it can't be read.
|
|
||||||
if (!fi.isReadable()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filename.endsWith(STR_ext_gz)) {
|
|
||||||
filename.chop(3);
|
|
||||||
gz = true;
|
|
||||||
} else { gz = false; }
|
|
||||||
|
|
||||||
// Accept only .edf and .edf.gz files
|
|
||||||
if (filename.right(4).toLower() != "." + STR_ext_EDF) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
fullname = fi.canonicalFilePath();
|
|
||||||
|
|
||||||
// Extract the session date out of the filename
|
|
||||||
datestr = filename.section("_", 0, 1);
|
|
||||||
|
|
||||||
// Take the filename's date, and
|
|
||||||
date = QDateTime::fromString(datestr, "yyyyMMdd_HHmmss");
|
|
||||||
date = date.toUTC();
|
|
||||||
|
|
||||||
// Skip file if dates invalid, the filename is clearly wrong..
|
|
||||||
if (!date.isValid()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
edftypestr = filename.section("_", 2).section(".", 0, 0);
|
|
||||||
|
|
||||||
// Could always just compare first letter, seeing date is already checked..
|
|
||||||
if (edftypestr.compare("BRP", Qt::CaseInsensitive) == 0) edftype = BRP;
|
|
||||||
else if (edftypestr.compare("EVE", Qt::CaseInsensitive) == 0) edftype = EVE;
|
|
||||||
else if (edftypestr.compare("PLD", Qt::CaseInsensitive) == 0) edftype = PLD;
|
|
||||||
else if (edftypestr.compare("SAD", Qt::CaseInsensitive) == 0) edftype = SAD;
|
|
||||||
else edftype = ET_ERR;
|
|
||||||
|
|
||||||
// convert this date to UNIX epoch to form the sessionID
|
|
||||||
sessionid = date.toTime_t();
|
|
||||||
|
|
||||||
fgit = filegroups.find(sessionid);
|
|
||||||
if (fgit == filegroups.end()) {
|
|
||||||
if ((edftype == EVE) || (edftype == BRP)) {
|
|
||||||
fgit = filegroups.insert(sessionid,EDFGroup());
|
|
||||||
lastsession = sessionid;
|
|
||||||
} else {
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Resmed bugs up on the session filenames.. Biggest observed delay so far of 14 seconds
|
|
||||||
// Moral of the story, when writing firmware and saving in batches, use the same datetimes,
|
|
||||||
// and provide firmware updates for free to your customers.
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Check how long since last EVE/BRP session
|
|
||||||
if ((sessionid - lastsession) < 30) {
|
|
||||||
fgit = filegroups.find(lastsession);
|
|
||||||
} else {
|
|
||||||
// It appears we have a lonely PLD or SAD file...
|
|
||||||
fgit = filegroups.insert(sessionid,EDFGroup());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fullname = backup(fullname, backup_path);
|
|
||||||
|
|
||||||
switch (edftype) {
|
|
||||||
case BRP:
|
|
||||||
fgit.value().BRP = fullname;
|
|
||||||
break;
|
|
||||||
case EVE:
|
|
||||||
fgit.value().EVE = fullname;
|
|
||||||
break;
|
|
||||||
case PLD:
|
|
||||||
fgit.value().PLD = fullname;
|
|
||||||
break;
|
|
||||||
case SAD:
|
|
||||||
fgit.value().SAD = fullname;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
// No such thing..
|
|
||||||
}
|
|
||||||
|
|
||||||
if (qprogress) {
|
|
||||||
if ((i % 5) == 0) {
|
|
||||||
qprogress->setValue((float(i + 1) / float(size) * 100.0));
|
|
||||||
QApplication::processEvents();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Session *sess;
|
|
||||||
int cnt = 0;
|
|
||||||
size = filegroups.size();
|
|
||||||
|
|
||||||
backup_path += RMS9_STR_datalog + "/";
|
|
||||||
|
|
||||||
#ifdef LOCK_RESMED_SESSIONS
|
#ifdef LOCK_RESMED_SESSIONS
|
||||||
// Have to sacrifice these features to get access to summary data.
|
// Have to sacrifice these features to get access to summary data.
|
||||||
p_profile->session->setCombineCloseSessions(0);
|
p_profile->session->setCombineCloseSessions(0);
|
||||||
@ -1698,16 +1516,12 @@ int ResmedLoader::Open(QString path)
|
|||||||
p_profile->session->setIgnoreShortSessions(false);
|
p_profile->session->setIgnoreShortSessions(false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
scanFiles(m, newpath);
|
||||||
// Scan through new file list and import sessions
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
m_totaltasks = filegroups.size();
|
|
||||||
for (fgit = filegroups.begin(); fgit != filegroups.end(); ++fgit) {
|
|
||||||
queTask(new ResmedImport(this, fgit.key(), fgit.value(), m));
|
|
||||||
}
|
|
||||||
runTasks(p_profile->session->multithreading()); */
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Now look for any new summary data that can be extracted from STR.edf records
|
// Now look for any new summary data that can be extracted from STR.edf records
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
QMap<quint32, STRRecord>::iterator it;
|
QMap<quint32, STRRecord>::iterator it;
|
||||||
QMap<quint32, STRRecord>::iterator end = strsess.end();
|
QMap<quint32, STRRecord>::iterator end = strsess.end();
|
||||||
|
|
||||||
@ -1738,10 +1552,6 @@ int ResmedLoader::Open(QString path)
|
|||||||
// strsess end can change above.
|
// strsess end can change above.
|
||||||
end = strsess.end();
|
end = strsess.end();
|
||||||
|
|
||||||
// m->lockSaveMutex();
|
|
||||||
// m->setTotalTasks(m->totalTasks() + size);
|
|
||||||
// m->unlockSaveMutex();
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Scan through unmatched strsess records, and attempt to get at summary data
|
// Scan through unmatched strsess records, and attempt to get at summary data
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -339,6 +339,11 @@ class ResmedLoader : public MachineLoader
|
|||||||
//! \brief Detect if the given path contains a valid Folder structure
|
//! \brief Detect if the given path contains a valid Folder structure
|
||||||
virtual bool Detect(const QString & path);
|
virtual bool Detect(const QString & path);
|
||||||
|
|
||||||
|
|
||||||
|
//! \brief Look up machine model information of ResMed file structure stored at path
|
||||||
|
virtual MachineInfo PeekInfo(const QString & path);
|
||||||
|
|
||||||
|
|
||||||
//! \brief Scans for S9 SD folder structure signature, and loads any new data if found
|
//! \brief Scans for S9 SD folder structure signature, and loads any new data if found
|
||||||
virtual int Open(QString path);
|
virtual int Open(QString path);
|
||||||
|
|
||||||
@ -346,15 +351,12 @@ class ResmedLoader : public MachineLoader
|
|||||||
virtual int Version() { return resmed_data_version; }
|
virtual int Version() { return resmed_data_version; }
|
||||||
|
|
||||||
//! \brief Returns the Machine class name of this loader. ("ResMed")
|
//! \brief Returns the Machine class name of this loader. ("ResMed")
|
||||||
virtual const QString &ClassName() { return resmed_class_name; }
|
virtual const QString &loaderName() { return resmed_class_name; }
|
||||||
|
|
||||||
//! \brief Converts EDFSignal data to time delta packed EventList, and adds to Session
|
//! \brief Converts EDFSignal data to time delta packed EventList, and adds to Session
|
||||||
void ToTimeDelta(Session *sess, EDFParser &edf, EDFSignal &es, ChannelID code, long recs,
|
void ToTimeDelta(Session *sess, EDFParser &edf, EDFSignal &es, ChannelID code, long recs,
|
||||||
qint64 duration, EventDataType min = 0, EventDataType max = 0, bool square = false);
|
qint64 duration, EventDataType min = 0, EventDataType max = 0, bool square = false);
|
||||||
|
|
||||||
//! \brief Create Machine record, and index it by serial number
|
|
||||||
Machine *CreateMachine(QString serial);
|
|
||||||
|
|
||||||
//! \brief Register the ResmedLoader with the list of other machine loaders
|
//! \brief Register the ResmedLoader with the list of other machine loaders
|
||||||
static void Register();
|
static void Register();
|
||||||
|
|
||||||
@ -374,25 +376,23 @@ class ResmedLoader : public MachineLoader
|
|||||||
//! This contains the Pressure, Leak, Respiratory Rate, Minute Ventilation, Tidal Volume, etc..
|
//! This contains the Pressure, Leak, Respiratory Rate, Minute Ventilation, Tidal Volume, etc..
|
||||||
bool LoadPLD(Session *sess, const QString & path);
|
bool LoadPLD(Session *sess, const QString & path);
|
||||||
|
|
||||||
protected:
|
virtual MachineInfo newInfo() {
|
||||||
QHash<QString, Machine *> ResmedList;
|
return MachineInfo(MT_CPAP, resmed_class_name, QObject::tr("ResMed"), QString(), QString(), QString(), QObject::tr("S9"), QDateTime::currentDateTime(), resmed_data_version);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
void ParseSTR(Machine *mach, QStringList strfiles);
|
void ParseSTR(Machine *mach, QStringList strfiles);
|
||||||
|
|
||||||
//! \brief Scan for new files to import, group into sessions and add to task que
|
//! \brief Scan for new files to import, group into sessions and add to task que
|
||||||
void scanFiles(Machine * mach, QString datalog_path);
|
void scanFiles(Machine * mach, QString datalog_path);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
QString backup(QString file, QString backup_path);
|
QString backup(QString file, QString backup_path);
|
||||||
|
|
||||||
QMap<SessionID, QStringList> sessfiles;
|
QMap<SessionID, QStringList> sessfiles;
|
||||||
QMap<quint32, STRRecord> strsess;
|
QMap<quint32, STRRecord> strsess;
|
||||||
QMap<QDate, QList<STRRecord *> > strdate;
|
QMap<QDate, QList<STRRecord *> > strdate;
|
||||||
|
|
||||||
QHash<QString, SessionID> skipfiles;
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG_EFFICIENCY
|
#ifdef DEBUG_EFFICIENCY
|
||||||
QHash<ChannelID, qint64> channel_efficiency;
|
QHash<ChannelID, qint64> channel_efficiency;
|
||||||
QHash<ChannelID, qint64> channel_time;
|
QHash<ChannelID, qint64> channel_time;
|
||||||
|
@ -54,36 +54,6 @@ int SomnoposeLoader::Open(QString path)
|
|||||||
|
|
||||||
return 0; // number of machines affected
|
return 0; // number of machines affected
|
||||||
}
|
}
|
||||||
Machine *SomnoposeLoader::CreateMachine()
|
|
||||||
{
|
|
||||||
Q_ASSERT(p_profile != nullptr);
|
|
||||||
|
|
||||||
QList<Machine *> ml = p_profile->GetMachines(MT_POSITION);
|
|
||||||
|
|
||||||
for (QList<Machine *>::iterator i = ml.begin(); i != ml.end(); i++) {
|
|
||||||
if ((*i)->GetClass() == somnopose_class_name) {
|
|
||||||
return (*i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
qDebug("Create Somnopose Machine Record");
|
|
||||||
|
|
||||||
Machine *m = new PositionSensor(0);
|
|
||||||
m->SetType(MT_POSITION);
|
|
||||||
m->SetClass(somnopose_class_name);
|
|
||||||
m->properties[STR_PROP_Brand] = "Somnopose";
|
|
||||||
m->properties[STR_PROP_Model] = "Somnopose Position Data";
|
|
||||||
m->properties[STR_PROP_DataVersion] = QString::number(somnopose_data_version);
|
|
||||||
|
|
||||||
p_profile->AddMachine(m);
|
|
||||||
|
|
||||||
QString path = "{" + STR_GEN_DataFolder + "}/" + m->GetClass() + "_" + m->hexid() + "/";
|
|
||||||
m->properties[STR_PROP_Path] = path;
|
|
||||||
m->properties[STR_PROP_BackupPath] = path + "Backup/";
|
|
||||||
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
int SomnoposeLoader::OpenFile(QString filename)
|
int SomnoposeLoader::OpenFile(QString filename)
|
||||||
{
|
{
|
||||||
@ -137,7 +107,8 @@ int SomnoposeLoader::OpenFile(QString filename)
|
|||||||
bool ok;
|
bool ok;
|
||||||
|
|
||||||
bool first = true;
|
bool first = true;
|
||||||
Machine *mach = CreateMachine();
|
MachineInfo info = newInfo();
|
||||||
|
Machine *mach = CreateMachine(info);
|
||||||
Session *sess = nullptr;
|
Session *sess = nullptr;
|
||||||
SessionID sid;
|
SessionID sid;
|
||||||
|
|
||||||
|
@ -33,10 +33,14 @@ class SomnoposeLoader : public MachineLoader
|
|||||||
static void Register();
|
static void Register();
|
||||||
|
|
||||||
virtual int Version() { return somnopose_data_version; }
|
virtual int Version() { return somnopose_data_version; }
|
||||||
virtual const QString &ClassName() { return somnopose_class_name; }
|
virtual const QString &loaderName() { return somnopose_class_name; }
|
||||||
|
|
||||||
|
virtual MachineInfo newInfo() {
|
||||||
|
return MachineInfo(MT_POSITION, somnopose_class_name, QObject::tr("Somnopose"), QString(), QString(), QString(), QObject::tr("Somnopose Software"), QDateTime::currentDateTime(), somnopose_data_version);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Machine *CreateMachine();
|
//Machine *CreateMachine();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
private:
|
private:
|
||||||
|
@ -56,42 +56,6 @@ int ZEOLoader::Open(QString path)
|
|||||||
return 0; // number of machines affected
|
return 0; // number of machines affected
|
||||||
}
|
}
|
||||||
|
|
||||||
Machine *ZEOLoader::CreateMachine(Profile *profile)
|
|
||||||
{
|
|
||||||
if (!profile) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: This only allows for one ZEO machine per profile..
|
|
||||||
// Upgrading their ZEO will use this same record..
|
|
||||||
|
|
||||||
QList<Machine *> ml = profile->GetMachines(MT_SLEEPSTAGE);
|
|
||||||
|
|
||||||
for (QList<Machine *>::iterator i = ml.begin(); i != ml.end(); i++) {
|
|
||||||
if ((*i)->GetClass() == zeo_class_name) {
|
|
||||||
return (*i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
qDebug("Create ZEO Machine Record");
|
|
||||||
|
|
||||||
Machine *m = new SleepStage(0);
|
|
||||||
m->SetType(MT_SLEEPSTAGE);
|
|
||||||
m->SetClass(zeo_class_name);
|
|
||||||
m->properties[STR_PROP_Brand] = "ZEO";
|
|
||||||
m->properties[STR_PROP_Model] = "Personal Sleep Coach";
|
|
||||||
m->properties[STR_PROP_DataVersion] = QString::number(zeo_data_version);
|
|
||||||
|
|
||||||
profile->AddMachine(m);
|
|
||||||
|
|
||||||
QString path = "{" + STR_GEN_DataFolder + "}/" + m->GetClass() + "_" + m->hexid() + "/";
|
|
||||||
m->properties[STR_PROP_Path] = path;
|
|
||||||
m->properties[STR_PROP_BackupPath] = path + "Backup/";
|
|
||||||
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*15233: "Sleep Date"
|
/*15233: "Sleep Date"
|
||||||
15234: "ZQ"
|
15234: "ZQ"
|
||||||
15236: "Total Z"
|
15236: "Total Z"
|
||||||
@ -154,7 +118,8 @@ int ZEOLoader::OpenFile(QString filename)
|
|||||||
|
|
||||||
QStringList SG, DSG;
|
QStringList SG, DSG;
|
||||||
|
|
||||||
Machine *mach = CreateMachine(p_profile);
|
MachineInfo info = newInfo();
|
||||||
|
Machine *mach = CreateMachine(info);
|
||||||
|
|
||||||
|
|
||||||
int idxZQ = header.indexOf("ZQ");
|
int idxZQ = header.indexOf("ZQ");
|
||||||
|
@ -33,10 +33,12 @@ class ZEOLoader : public MachineLoader
|
|||||||
static void Register();
|
static void Register();
|
||||||
|
|
||||||
virtual int Version() { return zeo_data_version; }
|
virtual int Version() { return zeo_data_version; }
|
||||||
virtual const QString &ClassName() { return zeo_class_name; }
|
virtual const QString &loaderName() { return zeo_class_name; }
|
||||||
|
|
||||||
|
//Machine *CreateMachine();
|
||||||
Machine *CreateMachine(Profile *profile);
|
virtual MachineInfo newInfo() {
|
||||||
|
return MachineInfo(MT_SLEEPSTAGE, zeo_class_name, QObject::tr("Zeo"), QString(), QString(), QString(), QObject::tr("Personal Sleep Coach"), QDateTime::currentDateTime(), zeo_data_version);
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
private:
|
private:
|
||||||
|
@ -46,13 +46,13 @@ Machine::Machine(MachineID id)
|
|||||||
|
|
||||||
} else { m_id = id; }
|
} else { m_id = id; }
|
||||||
|
|
||||||
qDebug() << "Create Machine: " << hex << m_id; //%lx",m_id);
|
// qDebug() << "Create Machine: " << hex << m_id; //%lx",m_id);
|
||||||
m_type = MT_UNKNOWN;
|
m_type = MT_UNKNOWN;
|
||||||
firstsession = true;
|
firstsession = true;
|
||||||
}
|
}
|
||||||
Machine::~Machine()
|
Machine::~Machine()
|
||||||
{
|
{
|
||||||
qDebug() << "Destroy Machine" << m_class << hex << m_id;
|
qDebug() << "Destroy Machine" << info.loadername << hex << m_id;
|
||||||
|
|
||||||
for (QMap<QDate, Day *>::iterator d = day.begin(); d != day.end(); d++) {
|
for (QMap<QDate, Day *>::iterator d = day.begin(); d != day.end(); d++) {
|
||||||
delete d.value();
|
delete d.value();
|
||||||
@ -272,7 +272,7 @@ bool Machine::Purge(int secret)
|
|||||||
// Boring api key to stop this function getting called by accident :)
|
// Boring api key to stop this function getting called by accident :)
|
||||||
if (secret != 3478216) { return false; }
|
if (secret != 3478216) { return false; }
|
||||||
|
|
||||||
QString path = p_profile->Get(properties[STR_PROP_Path]);
|
QString path = getDataPath();
|
||||||
|
|
||||||
QDir dir(path);
|
QDir dir(path);
|
||||||
|
|
||||||
@ -284,7 +284,7 @@ bool Machine::Purge(int secret)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "Purging" << m_class << properties[STR_PROP_Serial] << dir.absoluteFilePath(path);
|
qDebug() << "Purging" << info.loadername << info.serial << dir.absoluteFilePath(path);
|
||||||
|
|
||||||
// Remove any imported file list
|
// Remove any imported file list
|
||||||
QFile impfile(getDataPath()+"/imported_files.csv");
|
QFile impfile(getDataPath()+"/imported_files.csv");
|
||||||
@ -298,7 +298,7 @@ bool Machine::Purge(int secret)
|
|||||||
for (int i=0; i < sessions.size(); ++i) {
|
for (int i=0; i < sessions.size(); ++i) {
|
||||||
Session * sess = sessions[i];
|
Session * sess = sessions[i];
|
||||||
if (!sess->Destroy()) {
|
if (!sess->Destroy()) {
|
||||||
qDebug() << "Could not destroy "+ m_class+" ("+properties[STR_PROP_Serial]+") session" << sess->session();
|
qDebug() << "Could not destroy "+ info.loadername +" ("+info.serial+") session" << sess->session();
|
||||||
success = false;
|
success = false;
|
||||||
} else {
|
} else {
|
||||||
// sessionlist.remove(sess->session());
|
// sessionlist.remove(sess->session());
|
||||||
@ -346,15 +346,21 @@ bool Machine::Purge(int secret)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//const quint32 channel_version=1;
|
//const quint32 channel_version=1;
|
||||||
|
|
||||||
const QString Machine::getDataPath()
|
const QString Machine::getDataPath()
|
||||||
{
|
{
|
||||||
return p_profile->Get(properties[STR_PROP_Path]);
|
return p_profile->Get("{" + STR_GEN_DataFolder + "}/" + info.loadername + "_" + (info.serial.isEmpty() ? hexid() : info.serial)) + "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString Machine::getBackupPath()
|
||||||
|
{
|
||||||
|
return p_profile->Get("{" + STR_GEN_DataFolder + "}/" + info.loadername + "_" + (info.serial.isEmpty() ? hexid() : info.serial) + "/Backup/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Machine::Load()
|
bool Machine::Load()
|
||||||
{
|
{
|
||||||
QString path = p_profile->Get(properties[STR_PROP_Path]);
|
QString path = getDataPath();
|
||||||
|
|
||||||
QDir dir(path);
|
QDir dir(path);
|
||||||
qDebug() << "Loading " << QDir::toNativeSeparators(path);
|
qDebug() << "Loading " << QDir::toNativeSeparators(path);
|
||||||
@ -424,7 +430,7 @@ bool Machine::Load()
|
|||||||
|
|
||||||
bool Machine::SaveSession(Session *sess)
|
bool Machine::SaveSession(Session *sess)
|
||||||
{
|
{
|
||||||
QString path = p_profile->Get(properties[STR_PROP_Path]);
|
QString path = getDataPath();
|
||||||
|
|
||||||
if (sess->IsChanged()) { sess->Store(path); }
|
if (sess->IsChanged()) { sess->Store(path); }
|
||||||
|
|
||||||
@ -440,7 +446,7 @@ void Machine::queSaveList(Session * sess)
|
|||||||
QApplication::processEvents();
|
QApplication::processEvents();
|
||||||
|
|
||||||
sess->UpdateSummaries();
|
sess->UpdateSummaries();
|
||||||
sess->Store(p_profile->Get(properties[STR_PROP_Path]));
|
sess->Store(getDataPath());
|
||||||
|
|
||||||
if (!p_profile->session->cacheSessions()) {
|
if (!p_profile->session->cacheSessions()) {
|
||||||
sess->TrashEvents();
|
sess->TrashEvents();
|
||||||
@ -474,7 +480,7 @@ void Machine::StartSaveThreads()
|
|||||||
m_savelist.clear();
|
m_savelist.clear();
|
||||||
if (!p_profile->session->multithreading()) return;
|
if (!p_profile->session->multithreading()) return;
|
||||||
|
|
||||||
QString path = p_profile->Get(properties[STR_PROP_Path]);
|
QString path = getDataPath();
|
||||||
|
|
||||||
int threads = QThread::idealThreadCount();
|
int threads = QThread::idealThreadCount();
|
||||||
savelistSem = new QSemaphore(threads);
|
savelistSem = new QSemaphore(threads);
|
||||||
@ -567,7 +573,7 @@ void SaveTask::run()
|
|||||||
{
|
{
|
||||||
sess->UpdateSummaries();
|
sess->UpdateSummaries();
|
||||||
mach->saveMutex.lock();
|
mach->saveMutex.lock();
|
||||||
sess->Store(p_profile->Get(mach->properties[STR_PROP_Path]));
|
sess->Store(mach->getDataPath());
|
||||||
mach->saveMutex.unlock();
|
mach->saveMutex.unlock();
|
||||||
sess->TrashEvents();
|
sess->TrashEvents();
|
||||||
}
|
}
|
||||||
@ -609,7 +615,7 @@ bool Machine::Save()
|
|||||||
//int size;
|
//int size;
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
|
|
||||||
QString path = p_profile->Get(properties[STR_PROP_Path]);
|
QString path = getDataPath();
|
||||||
QDir dir(path);
|
QDir dir(path);
|
||||||
|
|
||||||
if (!dir.exists()) {
|
if (!dir.exists()) {
|
||||||
@ -682,7 +688,7 @@ PositionSensor::~PositionSensor()
|
|||||||
ChannelID NoChannel, SESSION_ENABLED, CPAP_SummaryOnly;
|
ChannelID NoChannel, SESSION_ENABLED, CPAP_SummaryOnly;
|
||||||
ChannelID CPAP_IPAP, CPAP_IPAPLo, CPAP_IPAPHi, CPAP_EPAP, CPAP_EPAPLo, CPAP_EPAPHi, CPAP_Pressure,
|
ChannelID CPAP_IPAP, CPAP_IPAPLo, CPAP_IPAPHi, CPAP_EPAP, CPAP_EPAPLo, CPAP_EPAPHi, CPAP_Pressure,
|
||||||
CPAP_PS, CPAP_Mode, CPAP_AHI,
|
CPAP_PS, CPAP_Mode, CPAP_AHI,
|
||||||
CPAP_PressureMin, CPAP_PressureMax, CPAP_RampTime, CPAP_RampPressure, CPAP_Obstructive,
|
CPAP_PressureMin, CPAP_PressureMax, CPAP_Ramp, CPAP_RampTime, CPAP_RampPressure, CPAP_Obstructive,
|
||||||
CPAP_Hypopnea,
|
CPAP_Hypopnea,
|
||||||
CPAP_ClearAirway, CPAP_Apnea, CPAP_CSR, CPAP_LeakFlag, CPAP_ExP, CPAP_NRI, CPAP_VSnore,
|
CPAP_ClearAirway, CPAP_Apnea, CPAP_CSR, CPAP_LeakFlag, CPAP_ExP, CPAP_NRI, CPAP_VSnore,
|
||||||
CPAP_VSnore2,
|
CPAP_VSnore2,
|
||||||
|
@ -68,6 +68,7 @@ public:
|
|||||||
virtual void run() {}
|
virtual void run() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MachineLaoder;
|
||||||
/*! \class Machine
|
/*! \class Machine
|
||||||
\brief This Machine class is the Heart of SleepyLib, representing a single Machine and holding it's data
|
\brief This Machine class is the Heart of SleepyLib, representing a single Machine and holding it's data
|
||||||
|
|
||||||
@ -75,6 +76,7 @@ public:
|
|||||||
class Machine
|
class Machine
|
||||||
{
|
{
|
||||||
friend class SaveThread;
|
friend class SaveThread;
|
||||||
|
friend class MachineLaoder;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*! \fn Machine(MachineID id=0);
|
/*! \fn Machine(MachineID id=0);
|
||||||
@ -119,19 +121,8 @@ class Machine
|
|||||||
//! \brief Find the date this session belongs in, according to profile settings
|
//! \brief Find the date this session belongs in, according to profile settings
|
||||||
QDate pickDate(qint64 start);
|
QDate pickDate(qint64 start);
|
||||||
|
|
||||||
//! \brief Sets the Class of machine (Used to reference the particular loader that created it)
|
|
||||||
void SetClass(QString t) { m_class = t; }
|
|
||||||
|
|
||||||
//! \brief Sets the type of machine, according to MachineType enum
|
|
||||||
void SetType(MachineType t) { m_type = t; }
|
|
||||||
|
|
||||||
//! \brief Returns the Class of machine (Used to reference the particular loader that created it)
|
|
||||||
const QString &GetClass() { return m_class; }
|
|
||||||
|
|
||||||
//! \brief Returns the type of machine, according to MachineType enum
|
|
||||||
const MachineType &GetType() const { return m_type; }
|
|
||||||
|
|
||||||
const QString getDataPath();
|
const QString getDataPath();
|
||||||
|
const QString getBackupPath();
|
||||||
|
|
||||||
//! \brief Returns the machineID as a lower case hexadecimal string
|
//! \brief Returns the machineID as a lower case hexadecimal string
|
||||||
QString hexid() { return QString().sprintf("%08lx", m_id); }
|
QString hexid() { return QString().sprintf("%08lx", m_id); }
|
||||||
@ -142,6 +133,7 @@ class Machine
|
|||||||
|
|
||||||
//! \brief Returns this objects MachineID
|
//! \brief Returns this objects MachineID
|
||||||
const MachineID &id() { return m_id; }
|
const MachineID &id() { return m_id; }
|
||||||
|
void setId(MachineID id) { m_id = id; }
|
||||||
|
|
||||||
//! \brief Returns the date of the first loaded Session
|
//! \brief Returns the date of the first loaded Session
|
||||||
const QDate &FirstDay() { return firstday; }
|
const QDate &FirstDay() { return firstday; }
|
||||||
@ -183,15 +175,34 @@ class Machine
|
|||||||
inline int doneTasks() { return m_donetasks; }
|
inline int doneTasks() { return m_donetasks; }
|
||||||
|
|
||||||
|
|
||||||
|
inline MachineType type() const { return info.type; }
|
||||||
|
inline QString brand() const { return info.brand; }
|
||||||
|
inline QString loaderName() const { return info.loadername; }
|
||||||
|
inline QString model() const { return info.model; }
|
||||||
|
inline QString modelnumber() const { return info.modelnumber; }
|
||||||
|
inline QString serial() const { return info.serial; }
|
||||||
|
inline QString series() const { return info.series; }
|
||||||
|
inline int version() const { return info.version; }
|
||||||
|
inline QDateTime lastImported() const { return info.lastimported; }
|
||||||
|
|
||||||
|
inline void setModel(QString value) { info.model = value; }
|
||||||
|
inline void setSerial(QString value) { info.serial = value; }
|
||||||
|
inline void setType(MachineType type) { info.type = type; }
|
||||||
|
inline void setLoaderName(QString value) { info.loadername = value; }
|
||||||
|
|
||||||
// much more simpler multithreading...
|
// much more simpler multithreading...
|
||||||
void queTask(ImportTask * task);
|
void queTask(ImportTask * task);
|
||||||
void runTasks();
|
void runTasks();
|
||||||
QMutex saveMutex;
|
QMutex saveMutex;
|
||||||
|
|
||||||
|
void setInfo(MachineInfo inf) { info = inf; }
|
||||||
|
const MachineInfo getInfo() { return info; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
MachineInfo info;
|
||||||
QDate firstday, lastday;
|
QDate firstday, lastday;
|
||||||
SessionID highest_sessionid;
|
SessionID highest_sessionid;
|
||||||
MachineID m_id;
|
MachineID m_id;
|
||||||
QString m_class;
|
|
||||||
MachineType m_type;
|
MachineType m_type;
|
||||||
QString m_path;
|
QString m_path;
|
||||||
|
|
||||||
@ -204,7 +215,6 @@ class Machine
|
|||||||
volatile bool m_save_threads_running;
|
volatile bool m_save_threads_running;
|
||||||
|
|
||||||
QList<ImportTask *> m_tasklist;
|
QList<ImportTask *> m_tasklist;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <QDateTime>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -72,6 +73,35 @@ enum PRModes { //:short
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct MachineInfo {
|
||||||
|
MachineInfo() { type = MT_UNKNOWN; version = 0; }
|
||||||
|
MachineInfo(const MachineInfo & copy) {
|
||||||
|
type = copy.type;
|
||||||
|
loadername = copy.loadername;
|
||||||
|
brand = copy.brand;
|
||||||
|
model = copy.model;
|
||||||
|
modelnumber = copy.modelnumber;
|
||||||
|
serial = copy.serial;
|
||||||
|
series = copy.series;
|
||||||
|
version = copy.version;
|
||||||
|
lastimported = copy.lastimported;
|
||||||
|
}
|
||||||
|
|
||||||
|
MachineInfo(MachineType type, QString loadername, QString brand, QString model, QString modelnumber, QString serial, QString series, QDateTime lastimported, int version) :
|
||||||
|
type(type), loadername(loadername), brand(brand), model(model), modelnumber(modelnumber), serial(serial), series(series), lastimported(lastimported), version(version) {}
|
||||||
|
|
||||||
|
MachineType type;
|
||||||
|
QString loadername;
|
||||||
|
QString brand;
|
||||||
|
QString model;
|
||||||
|
QString modelnumber;
|
||||||
|
QString serial;
|
||||||
|
QString series;
|
||||||
|
QDateTime lastimported;
|
||||||
|
int version;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//extern map<ChannelID,QString> DefaultMCShortNames;
|
//extern map<ChannelID,QString> DefaultMCShortNames;
|
||||||
//extern map<ChannelID,QString> DefaultMCLongNames;
|
//extern map<ChannelID,QString> DefaultMCLongNames;
|
||||||
//extern map<PRTypes,QString> PressureReliefNames;
|
//extern map<PRTypes,QString> PressureReliefNames;
|
||||||
@ -89,7 +119,7 @@ extern ChannelID NoChannel, SESSION_ENABLED, CPAP_SummaryOnly;
|
|||||||
extern ChannelID CPAP_IPAP, CPAP_IPAPLo, CPAP_IPAPHi, CPAP_EPAP, CPAP_EPAPLo, CPAP_EPAPHi,
|
extern ChannelID CPAP_IPAP, CPAP_IPAPLo, CPAP_IPAPHi, CPAP_EPAP, CPAP_EPAPLo, CPAP_EPAPHi,
|
||||||
CPAP_Pressure, CPAP_PS, CPAP_PSMin, CPAP_PSMax,
|
CPAP_Pressure, CPAP_PS, CPAP_PSMin, CPAP_PSMax,
|
||||||
CPAP_Mode, CPAP_AHI,
|
CPAP_Mode, CPAP_AHI,
|
||||||
CPAP_PressureMin, CPAP_PressureMax, CPAP_RampTime, CPAP_RampPressure, CPAP_Obstructive,
|
CPAP_PressureMin, CPAP_PressureMax, CPAP_Ramp, CPAP_RampTime, CPAP_RampPressure, CPAP_Obstructive,
|
||||||
CPAP_Hypopnea,
|
CPAP_Hypopnea,
|
||||||
CPAP_ClearAirway, CPAP_Apnea, CPAP_CSR, CPAP_LeakFlag, CPAP_ExP, CPAP_NRI, CPAP_VSnore,
|
CPAP_ClearAirway, CPAP_Apnea, CPAP_CSR, CPAP_LeakFlag, CPAP_ExP, CPAP_NRI, CPAP_VSnore,
|
||||||
CPAP_VSnore2,
|
CPAP_VSnore2,
|
||||||
|
@ -38,6 +38,68 @@ QList<MachineLoader *> GetLoaders(MachineType mt)
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MachineLoader * lookupLoader(Machine * m)
|
||||||
|
{
|
||||||
|
for (int i=0; i < m_loaders.size(); ++i) {
|
||||||
|
MachineLoader * loader = m_loaders.at(i);
|
||||||
|
if (loader->loaderName() == m->loaderName())
|
||||||
|
return loader;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<QString, QHash<QString, Machine *> > MachineList;
|
||||||
|
|
||||||
|
|
||||||
|
Machine * MachineLoader::CreateMachine(MachineInfo info, MachineID id)
|
||||||
|
{
|
||||||
|
Q_ASSERT(p_profile != nullptr);
|
||||||
|
|
||||||
|
Machine *m = nullptr;
|
||||||
|
|
||||||
|
QHash<QString, QHash<QString, Machine *> >::iterator mlit = MachineList.find(info.loadername);
|
||||||
|
|
||||||
|
if (mlit != MachineList.end()) {
|
||||||
|
QHash<QString, Machine *>::iterator mit = mlit.value().find(info.serial);
|
||||||
|
if (mit != mlit.value().end()) {
|
||||||
|
mit.value()->setInfo(info); // update info
|
||||||
|
return mit.value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (info.type) {
|
||||||
|
case MT_CPAP:
|
||||||
|
m = new CPAP(id);
|
||||||
|
break;
|
||||||
|
case MT_SLEEPSTAGE:
|
||||||
|
m = new SleepStage(id);
|
||||||
|
break;
|
||||||
|
case MT_OXIMETER:
|
||||||
|
m = new Oximeter(id);
|
||||||
|
break;
|
||||||
|
case MT_POSITION:
|
||||||
|
m = new PositionSensor(id);
|
||||||
|
break;
|
||||||
|
case MT_JOURNAL:
|
||||||
|
m = new Machine(id);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
m = new Machine(id);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m->setInfo(info);
|
||||||
|
|
||||||
|
qDebug() << "Create" << info.loadername << "Machine" << (info.serial.isEmpty() ? m->hexid() : info.serial);
|
||||||
|
|
||||||
|
MachineList[info.loadername][info.serial] = m;
|
||||||
|
p_profile->AddMachine(m);
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegisterLoader(MachineLoader *loader)
|
void RegisterLoader(MachineLoader *loader)
|
||||||
{
|
{
|
||||||
m_loaders.push_back(loader);
|
m_loaders.push_back(loader);
|
||||||
|
@ -25,6 +25,7 @@ class MachineLoader;
|
|||||||
enum DeviceStatus { NEUTRAL, IMPORTING, LIVE };
|
enum DeviceStatus { NEUTRAL, IMPORTING, LIVE };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*! \class MachineLoader
|
/*! \class MachineLoader
|
||||||
\brief Base class to derive a new Machine importer from
|
\brief Base class to derive a new Machine importer from
|
||||||
*/
|
*/
|
||||||
@ -32,6 +33,7 @@ class MachineLoader: public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
friend class ImportThread;
|
friend class ImportThread;
|
||||||
|
friend class Machine;
|
||||||
public:
|
public:
|
||||||
MachineLoader();
|
MachineLoader();
|
||||||
virtual ~MachineLoader();
|
virtual ~MachineLoader();
|
||||||
@ -39,14 +41,22 @@ class MachineLoader: public QObject
|
|||||||
//! \brief Detect if the given path contains a valid folder structure
|
//! \brief Detect if the given path contains a valid folder structure
|
||||||
virtual bool Detect(const QString & path) = 0;
|
virtual bool Detect(const QString & path) = 0;
|
||||||
|
|
||||||
|
//! \brief Look up and return machine model information stored at path
|
||||||
|
virtual MachineInfo PeekInfo(const QString & path) { Q_UNUSED(path); return MachineInfo(); }
|
||||||
|
|
||||||
//! \brief Override this to scan path and detect new machine data
|
//! \brief Override this to scan path and detect new machine data
|
||||||
virtual int Open(QString path) = 0;
|
virtual int Open(QString path) = 0;
|
||||||
|
|
||||||
//! \brief Override to returns the Version number of this MachineLoader
|
//! \brief Override to returns the Version number of this MachineLoader
|
||||||
virtual int Version() = 0;
|
virtual int Version() = 0;
|
||||||
|
|
||||||
|
static Machine * CreateMachine(MachineInfo info, MachineID id = 0);
|
||||||
|
|
||||||
|
// !\\brief Used internally by loaders, override to return base MachineInfo record
|
||||||
|
virtual MachineInfo newInfo() { return MachineInfo(); }
|
||||||
|
|
||||||
//! \brief Override to returns the class name of this MachineLoader
|
//! \brief Override to returns the class name of this MachineLoader
|
||||||
virtual const QString &ClassName() = 0;
|
virtual const QString &loaderName() = 0;
|
||||||
inline MachineType type() { return m_type; }
|
inline MachineType type() { return m_type; }
|
||||||
|
|
||||||
// virtual bool openDevice() { return false; }
|
// virtual bool openDevice() { return false; }
|
||||||
@ -109,10 +119,28 @@ signals:
|
|||||||
QList<ImportTask *> m_tasklist;
|
QList<ImportTask *> m_tasklist;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ImportPath
|
||||||
|
{
|
||||||
|
ImportPath() {
|
||||||
|
loader = nullptr;
|
||||||
|
}
|
||||||
|
ImportPath(const ImportPath & copy) {
|
||||||
|
loader = copy.loader;
|
||||||
|
path = copy.path;
|
||||||
|
}
|
||||||
|
ImportPath(QString path, MachineLoader * loader) :
|
||||||
|
path(path), loader(loader) {}
|
||||||
|
|
||||||
|
QString path;
|
||||||
|
MachineLoader * loader;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// Put in machine loader class as static??
|
// Put in machine loader class as static??
|
||||||
void RegisterLoader(MachineLoader *loader);
|
void RegisterLoader(MachineLoader *loader);
|
||||||
|
MachineLoader * lookupLoader(Machine * m);
|
||||||
void DestroyLoaders();
|
void DestroyLoaders();
|
||||||
|
|
||||||
bool compressFile(QString inpath, QString outpath = "");
|
bool compressFile(QString inpath, QString outpath = "");
|
||||||
|
|
||||||
QList<MachineLoader *> GetLoaders(MachineType mt = MT_UNKNOWN);
|
QList<MachineLoader *> GetLoaders(MachineType mt = MT_UNKNOWN);
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
#include "preferences.h"
|
#include "preferences.h"
|
||||||
#include "profiles.h"
|
#include "profiles.h"
|
||||||
#include "machine.h"
|
#include "machine.h"
|
||||||
|
#include "machine_common.h"
|
||||||
|
|
||||||
#include "machine_loader.h"
|
#include "machine_loader.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
@ -117,6 +119,8 @@ QString Profile::checkLock()
|
|||||||
|
|
||||||
bool Profile::Open(QString filename)
|
bool Profile::Open(QString filename)
|
||||||
{
|
{
|
||||||
|
p_profile = this;
|
||||||
|
|
||||||
if (filename.isEmpty()) {
|
if (filename.isEmpty()) {
|
||||||
filename=p_filename;
|
filename=p_filename;
|
||||||
}
|
}
|
||||||
@ -301,12 +305,12 @@ void Profile::DataFormatError(Machine *m)
|
|||||||
|
|
||||||
msg = "<font size=+1>"+QObject::tr("SleepyHead (%1) needs to upgrade its database for %2 %3 %4").
|
msg = "<font size=+1>"+QObject::tr("SleepyHead (%1) needs to upgrade its database for %2 %3 %4").
|
||||||
arg(FullVersionString).
|
arg(FullVersionString).
|
||||||
arg(m->properties[STR_PROP_Brand]).arg(m->properties[STR_PROP_Model]).arg(m->properties[STR_PROP_Serial])
|
arg(m->brand()).arg(m->model()).arg(m->serial())
|
||||||
+ "</font><br/><br/>";
|
+ "</font><br/><br/>";
|
||||||
|
|
||||||
bool backups = false;
|
bool backups = false;
|
||||||
if (p_profile->session->backupCardData() && m->properties.contains(STR_PROP_BackupPath)) {
|
if (p_profile->session->backupCardData()) {
|
||||||
QString bpath = Get(m->properties[STR_PROP_BackupPath]);
|
QString bpath = m->getBackupPath();
|
||||||
int cnt = dirCount(bpath);
|
int cnt = dirCount(bpath);
|
||||||
if (cnt > 0) backups = true;
|
if (cnt > 0) backups = true;
|
||||||
}
|
}
|
||||||
@ -344,11 +348,11 @@ void Profile::DataFormatError(Machine *m)
|
|||||||
}
|
}
|
||||||
// Note: I deliberately haven't added a Profile help for this
|
// Note: I deliberately haven't added a Profile help for this
|
||||||
if (backups) {
|
if (backups) {
|
||||||
mainwin->importCPAP(Get(m->properties[STR_PROP_BackupPath]), QObject::tr("Rebuilding from %1 Backup").arg(m->properties[STR_PROP_Brand]));
|
mainwin->importCPAP(ImportPath(m->getBackupPath(), lookupLoader(m)), QObject::tr("Rebuilding from %1 Backup").arg(m->brand()));
|
||||||
} else {
|
} else {
|
||||||
if (!p_profile->session->backupCardData()) {
|
if (!p_profile->session->backupCardData()) {
|
||||||
// Automatic backups not available for Intellipap users yet, so don't taunt them..
|
// Automatic backups not available for Intellipap users yet, so don't taunt them..
|
||||||
if (m->GetClass() != STR_MACH_Intellipap) {
|
if (m->loaderName() != STR_MACH_Intellipap) {
|
||||||
if (QMessageBox::question(nullptr, STR_MessageBox_Question, QObject::tr("Would you like to switch on automatic backups, so next time a new version of SleepyHead needs to do so, it can rebuild from these?"),
|
if (QMessageBox::question(nullptr, STR_MessageBox_Question, QObject::tr("Would you like to switch on automatic backups, so next time a new version of SleepyHead needs to do so, it can rebuild from these?"),
|
||||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)) {
|
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)) {
|
||||||
p_profile->session->setBackupCardData(true);
|
p_profile->session->setBackupCardData(true);
|
||||||
@ -356,7 +360,7 @@ void Profile::DataFormatError(Machine *m)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
QMessageBox::information(nullptr, STR_MessageBox_Information,
|
QMessageBox::information(nullptr, STR_MessageBox_Information,
|
||||||
QObject::tr("SleepyHead will now start the import wizard so you can reinstall your %1 data.").arg(m->properties[STR_PROP_Brand])
|
QObject::tr("SleepyHead will now start the import wizard so you can reinstall your %1 data.").arg(m->brand())
|
||||||
,QMessageBox::Ok, QMessageBox::Ok);
|
,QMessageBox::Ok, QMessageBox::Ok);
|
||||||
mainwin->startImportDialog();
|
mainwin->startImportDialog();
|
||||||
}
|
}
|
||||||
@ -386,25 +390,11 @@ void Profile::LoadMachineData()
|
|||||||
for (QHash<MachineID, Machine *>::iterator i = machlist.begin(); i != machlist.end(); i++) {
|
for (QHash<MachineID, Machine *>::iterator i = machlist.begin(); i != machlist.end(); i++) {
|
||||||
Machine *m = i.value();
|
Machine *m = i.value();
|
||||||
|
|
||||||
MachineLoader *loader = GetLoader(m->GetClass());
|
MachineLoader *loader = lookupLoader(m);
|
||||||
|
|
||||||
if (loader) {
|
if (loader) {
|
||||||
long v = loader->Version();
|
if (m->version() < loader->Version()) {
|
||||||
long cv = 0;
|
|
||||||
|
|
||||||
if (m->properties.find(STR_PROP_DataVersion) == m->properties.end()) {
|
|
||||||
m->properties[STR_PROP_DataVersion] = "0";
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ok;
|
|
||||||
cv = m->properties[STR_PROP_DataVersion].toLong(&ok);
|
|
||||||
|
|
||||||
if (!ok || cv < v) {
|
|
||||||
DataFormatError(m);
|
DataFormatError(m);
|
||||||
// It may exit above and not return here..
|
|
||||||
QString s;
|
|
||||||
s.sprintf("%li", v);
|
|
||||||
m->properties[STR_PROP_DataVersion] = s; // Dont need to nag again if they are too lazy.
|
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
m->Load();
|
m->Load();
|
||||||
@ -419,13 +409,24 @@ void Profile::LoadMachineData()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QString STR_PROP_Brand = "brand";
|
||||||
|
const QString STR_PROP_Model = "model";
|
||||||
|
const QString STR_PROP_Series = "series";
|
||||||
|
const QString STR_PROP_ModelNumber = "modelnumber";
|
||||||
|
const QString STR_PROP_SubModel = "submodel";
|
||||||
|
const QString STR_PROP_Serial = "serial";
|
||||||
|
const QString STR_PROP_DataVersion = "dataversion";
|
||||||
|
const QString STR_PROP_LastImported = "lastimported";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Machine XML section in profile.
|
* @brief Machine XML section in profile.
|
||||||
* @param root
|
* @param root
|
||||||
*/
|
*/
|
||||||
void Profile::ExtraLoad(QDomElement &root)
|
void Profile::ExtraLoad(QDomElement &root)
|
||||||
{
|
{
|
||||||
if (root.tagName() != "Machines") {
|
if (root.tagName().toLower() != "machines") {
|
||||||
qDebug() << "No Machines Tag in Profiles.xml";
|
qDebug() << "No Machines Tag in Profiles.xml";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -435,8 +436,8 @@ void Profile::ExtraLoad(QDomElement &root)
|
|||||||
while (!elem.isNull()) {
|
while (!elem.isNull()) {
|
||||||
QString pKey = elem.tagName();
|
QString pKey = elem.tagName();
|
||||||
|
|
||||||
if (pKey != "Machine") {
|
if (pKey.toLower() != "machine") {
|
||||||
qWarning() << "Profile::ExtraLoad() pKey!=\"Machine\"";
|
qWarning() << "Profile::ExtraLoad() pKey!=\"machine\"";
|
||||||
elem = elem.nextSiblingElement();
|
elem = elem.nextSiblingElement();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -449,34 +450,53 @@ void Profile::ExtraLoad(QDomElement &root)
|
|||||||
MachineType m_type = (MachineType)mt;
|
MachineType m_type = (MachineType)mt;
|
||||||
|
|
||||||
QString m_class = elem.attribute("class", "");
|
QString m_class = elem.attribute("class", "");
|
||||||
//MachineLoader *ml=GetLoader(m_class);
|
|
||||||
Machine *m;
|
|
||||||
|
|
||||||
//if (ml) {
|
MachineInfo info;
|
||||||
// ml->CreateMachine
|
|
||||||
//}
|
info.type = m_type;
|
||||||
if (m_type == MT_CPAP) {
|
info.loadername = m_class;
|
||||||
m = new CPAP(m_id);
|
|
||||||
} else if (m_type == MT_OXIMETER) {
|
QHash<QString, QString> prop;
|
||||||
m = new Oximeter(m_id);
|
|
||||||
} else if (m_type == MT_SLEEPSTAGE) {
|
|
||||||
m = new SleepStage(m_id);
|
|
||||||
} else if (m_type == MT_POSITION) {
|
|
||||||
m = new PositionSensor(m_id);
|
|
||||||
} else {
|
|
||||||
m = new Machine(m_id);
|
|
||||||
m->SetType(m_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
m->SetClass(m_class);
|
|
||||||
AddMachine(m);
|
|
||||||
QDomElement e = elem.firstChildElement();
|
QDomElement e = elem.firstChildElement();
|
||||||
|
|
||||||
for (; !e.isNull(); e = e.nextSiblingElement()) {
|
for (; !e.isNull(); e = e.nextSiblingElement()) {
|
||||||
QString pKey = e.tagName();
|
QString pKey = e.tagName();
|
||||||
m->properties[pKey] = e.text();
|
QString key = pKey.toLower();
|
||||||
|
if (key == STR_PROP_Brand) {
|
||||||
|
info.brand = e.text();
|
||||||
|
} else if (key == STR_PROP_Model) {
|
||||||
|
info.model = e.text();
|
||||||
|
} else if (key == STR_PROP_ModelNumber) {
|
||||||
|
info.modelnumber = e.text();
|
||||||
|
} else if (key == STR_PROP_Serial) {
|
||||||
|
info.serial = e.text();
|
||||||
|
} else if (key == STR_PROP_Series) {
|
||||||
|
info.series = e.text();
|
||||||
|
} else if (key == STR_PROP_DataVersion) {
|
||||||
|
info.version = e.text().toInt();
|
||||||
|
} else if (key == STR_PROP_LastImported) {
|
||||||
|
info.lastimported = QDateTime::fromString(e.text(), Qt::ISODate);
|
||||||
|
} else if (key == "properties") {
|
||||||
|
QDomElement pe = e.firstChildElement();
|
||||||
|
for (; !pe.isNull(); pe = pe.nextSiblingElement()) {
|
||||||
|
prop[pe.tagName()] = pe.text();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// skip any old rubbish
|
||||||
|
if ((key == "backuppath") || (key == "path") || (key == "submodel")) continue;
|
||||||
|
|
||||||
|
prop[pKey] = e.text();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Machine *m = nullptr;
|
||||||
|
|
||||||
|
m = MachineLoader::CreateMachine(info, m_id);
|
||||||
|
//m->setId(m_id);
|
||||||
|
if (m) m->properties = prop;
|
||||||
|
|
||||||
elem = elem.nextSiblingElement();
|
elem = elem.nextSiblingElement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -503,25 +523,52 @@ void Profile::DelMachine(Machine *m)
|
|||||||
// Potential Memory Leak Here..
|
// Potential Memory Leak Here..
|
||||||
QDomElement Profile::ExtraSave(QDomDocument &doc)
|
QDomElement Profile::ExtraSave(QDomDocument &doc)
|
||||||
{
|
{
|
||||||
QDomElement mach = doc.createElement("Machines");
|
QDomElement mach = doc.createElement("machines");
|
||||||
|
|
||||||
for (QHash<MachineID, Machine *>::iterator i = machlist.begin(); i != machlist.end(); i++) {
|
for (QHash<MachineID, Machine *>::iterator i = machlist.begin(); i != machlist.end(); i++) {
|
||||||
QDomElement me = doc.createElement("Machine");
|
QDomElement me = doc.createElement("machine");
|
||||||
Machine *m = i.value();
|
Machine *m = i.value();
|
||||||
me.setAttribute("id", (int)m->id());
|
me.setAttribute("id", (int)m->id());
|
||||||
me.setAttribute("type", (int)m->GetType());
|
me.setAttribute("type", (int)m->type());
|
||||||
me.setAttribute("class", m->GetClass());
|
me.setAttribute("class", m->loaderName());
|
||||||
|
|
||||||
if (!m->properties.contains(STR_PROP_Path)) { m->properties[STR_PROP_Path] = "{DataFolder}/" + m->GetClass() + "_" + m->hexid(); }
|
QDomElement pe = doc.createElement("properties");
|
||||||
|
me.appendChild(pe);
|
||||||
|
|
||||||
for (QHash<QString, QString>::iterator j = i.value()->properties.begin();
|
for (QHash<QString, QString>::iterator j = i.value()->properties.begin(); j != i.value()->properties.end(); j++) {
|
||||||
j != i.value()->properties.end(); j++) {
|
QDomElement pp = doc.createElement(j.key());
|
||||||
QDomElement mp = doc.createElement(j.key());
|
pp.appendChild(doc.createTextNode(j.value()));
|
||||||
mp.appendChild(doc.createTextNode(j.value()));
|
pe.appendChild(pp);
|
||||||
//mp->LinkEndChild(new QDomText(j->second.toLatin1()));
|
|
||||||
me.appendChild(mp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDomElement mp = doc.createElement(STR_PROP_Brand);
|
||||||
|
mp.appendChild(doc.createTextNode(m->brand()));
|
||||||
|
me.appendChild(mp);
|
||||||
|
|
||||||
|
mp = doc.createElement(STR_PROP_Model);
|
||||||
|
mp.appendChild(doc.createTextNode(m->model()));
|
||||||
|
me.appendChild(mp);
|
||||||
|
|
||||||
|
mp = doc.createElement(STR_PROP_ModelNumber);
|
||||||
|
mp.appendChild(doc.createTextNode(m->modelnumber()));
|
||||||
|
me.appendChild(mp);
|
||||||
|
|
||||||
|
mp = doc.createElement(STR_PROP_Serial);
|
||||||
|
mp.appendChild(doc.createTextNode(m->serial()));
|
||||||
|
me.appendChild(mp);
|
||||||
|
|
||||||
|
mp = doc.createElement(STR_PROP_Series);
|
||||||
|
mp.appendChild(doc.createTextNode(m->series()));
|
||||||
|
me.appendChild(mp);
|
||||||
|
|
||||||
|
mp = doc.createElement(STR_PROP_DataVersion);
|
||||||
|
mp.appendChild(doc.createTextNode(QString::number(m->version())));
|
||||||
|
me.appendChild(mp);
|
||||||
|
|
||||||
|
mp = doc.createElement(STR_PROP_LastImported);
|
||||||
|
mp.appendChild(doc.createTextNode(m->lastImported().toString(Qt::ISODate)));
|
||||||
|
me.appendChild(mp);
|
||||||
|
|
||||||
mach.appendChild(me);
|
mach.appendChild(me);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -554,7 +601,7 @@ void Profile::AddDay(QDate date, Day *day, MachineType mt)
|
|||||||
QList<Day *> &dl = daylist[date];
|
QList<Day *> &dl = daylist[date];
|
||||||
|
|
||||||
for (QList<Day *>::iterator a = dl.begin(); a != dl.end(); a++) {
|
for (QList<Day *>::iterator a = dl.begin(); a != dl.end(); a++) {
|
||||||
if ((*a)->machine->GetType() == mt) {
|
if ((*a)->machine->type() == mt) {
|
||||||
|
|
||||||
// disabled this because two machines isn't all that bad
|
// disabled this because two machines isn't all that bad
|
||||||
// if (QMessageBox::question(nullptr,"Different Machine Detected","This data comes from another machine to what's usually imported, and has overlapping data.\nThis new data will override any older data from the old machine. Are you sure you want to do this?",QMessageBox::Yes,QMessageBox::No)==QMessageBox::No) {
|
// if (QMessageBox::question(nullptr,"Different Machine Detected","This data comes from another machine to what's usually imported, and has overlapping data.\nThis new data will override any older data from the old machine. Are you sure you want to do this?",QMessageBox::Yes,QMessageBox::No)==QMessageBox::No) {
|
||||||
@ -642,7 +689,7 @@ MachineLoader *GetLoader(QString name)
|
|||||||
QList<MachineLoader *>loaders = GetLoaders(MT_CPAP);
|
QList<MachineLoader *>loaders = GetLoaders(MT_CPAP);
|
||||||
|
|
||||||
Q_FOREACH(MachineLoader * loader, loaders) {
|
Q_FOREACH(MachineLoader * loader, loaders) {
|
||||||
if (loader->ClassName() == name) {
|
if (loader->loaderName() == name) {
|
||||||
return loader;
|
return loader;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -664,7 +711,7 @@ QList<Machine *> Profile::GetMachines(MachineType t)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
MachineType mt = i.value()->GetType();
|
MachineType mt = i.value()->type();
|
||||||
|
|
||||||
if ((t == MT_UNKNOWN) || (mt == t)) {
|
if ((t == MT_UNKNOWN) || (mt == t)) {
|
||||||
vec.push_back(i.value());
|
vec.push_back(i.value());
|
||||||
@ -781,6 +828,7 @@ Profile *Get(QString name)
|
|||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Profile *Create(QString name)
|
Profile *Create(QString name)
|
||||||
{
|
{
|
||||||
QString path = PREF.Get("{home}/Profiles/") + name;
|
QString path = PREF.Get("{home}/Profiles/") + name;
|
||||||
@ -797,16 +845,12 @@ Profile *Create(QString name)
|
|||||||
p_profile->user->setUserName(name);
|
p_profile->user->setUserName(name);
|
||||||
//p_profile->Set("Realname",realname);
|
//p_profile->Set("Realname",realname);
|
||||||
//if (!password.isEmpty()) p_profile.user->setPassword(password);
|
//if (!password.isEmpty()) p_profile.user->setPassword(password);
|
||||||
p_profile->Set(STR_GEN_DataFolder, QString("{home}/Profiles/{") + QString(STR_UI_UserName) +
|
p_profile->Set(STR_GEN_DataFolder, QString("{home}/Profiles/{") + QString(STR_UI_UserName) + QString("}"));
|
||||||
QString("}"));
|
|
||||||
|
|
||||||
Machine *m = new Machine(0);
|
Machine *m = new Machine(0);
|
||||||
m->SetClass("Journal");
|
MachineInfo info(MT_JOURNAL, STR_MACH_Journal, "SleepyHead", STR_MACH_Journal, QString(), m->hexid(), QString(), QDateTime::currentDateTime(), 0);
|
||||||
m->properties[STR_PROP_Brand] = "Journal";
|
|
||||||
m->properties[STR_PROP_Model] = "Journal Data Machine Object";
|
m->setInfo(info);
|
||||||
m->properties[STR_PROP_Serial] = m->hexid();
|
|
||||||
m->properties[STR_PROP_Path] = "{DataFolder}/" + m->GetClass() + "_" + m->hexid();
|
|
||||||
m->SetType(MT_JOURNAL);
|
|
||||||
p_profile->AddMachine(m);
|
p_profile->AddMachine(m);
|
||||||
|
|
||||||
p_profile->Save();
|
p_profile->Save();
|
||||||
@ -883,7 +927,7 @@ QList<Day *> Profile::getDays(MachineType mt, QDate start, QDate end)
|
|||||||
Day *day = GetGoodDay(date, mt);
|
Day *day = GetGoodDay(date, mt);
|
||||||
|
|
||||||
if (day) {
|
if (day) {
|
||||||
if ((mt == MT_UNKNOWN) || (day->machine->GetType() == mt)) {
|
if ((mt == MT_UNKNOWN) || (day->machine->type() == mt)) {
|
||||||
daylist.push_back(day);
|
daylist.push_back(day);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -916,7 +960,7 @@ int Profile::countDays(MachineType mt, QDate start, QDate end)
|
|||||||
Day *day = GetGoodDay(date, mt);
|
Day *day = GetGoodDay(date, mt);
|
||||||
|
|
||||||
if (day) {
|
if (day) {
|
||||||
if ((mt == MT_UNKNOWN) || (day->machine->GetType() == mt)) { days++; }
|
if ((mt == MT_UNKNOWN) || (day->machine->type() == mt)) { days++; }
|
||||||
}
|
}
|
||||||
|
|
||||||
date = date.addDays(1);
|
date = date.addDays(1);
|
||||||
@ -950,7 +994,7 @@ int Profile::countCompliantDays(MachineType mt, QDate start, QDate end)
|
|||||||
Day *day = GetGoodDay(date, mt);
|
Day *day = GetGoodDay(date, mt);
|
||||||
|
|
||||||
if (day) {
|
if (day) {
|
||||||
if ((day->machine->GetType() == mt) && (day->hours() > compliance)) { days++; }
|
if ((day->machine->type() == mt) && (day->hours() > compliance)) { days++; }
|
||||||
}
|
}
|
||||||
|
|
||||||
date = date.addDays(1);
|
date = date.addDays(1);
|
||||||
|
@ -133,6 +133,11 @@ void init()
|
|||||||
QObject::tr("Ramp Pr."), STR_UNIT_CMH2O, DEFAULT, QColor("black")));
|
QObject::tr("Ramp Pr."), STR_UNIT_CMH2O, DEFAULT, QColor("black")));
|
||||||
|
|
||||||
|
|
||||||
|
schema::channel.add(GRP_CPAP, new Channel(CPAP_Ramp = 0x1027, SPAN, SESSION,
|
||||||
|
"Ramp", QObject::tr("Ramp Event") , QObject::tr("Ramp Event"),
|
||||||
|
QObject::tr("Ramp"), STR_UNIT_EventsPerHour, DEFAULT, QColor("light blue")));
|
||||||
|
|
||||||
|
|
||||||
// Flags
|
// Flags
|
||||||
schema::channel.add(GRP_CPAP, new Channel(CPAP_CSR = 0x1000, SPAN, SESSION, "CSR",
|
schema::channel.add(GRP_CPAP, new Channel(CPAP_CSR = 0x1000, SPAN, SESSION, "CSR",
|
||||||
QObject::tr("Periodic Breathing"),
|
QObject::tr("Periodic Breathing"),
|
||||||
|
@ -46,8 +46,10 @@ public:
|
|||||||
static void Register() {}
|
static void Register() {}
|
||||||
|
|
||||||
virtual int Version()=0;
|
virtual int Version()=0;
|
||||||
virtual const QString &ClassName()=0;
|
virtual const QString &loaderName()=0;
|
||||||
|
virtual MachineInfo newInfo() {
|
||||||
|
return MachineInfo(MT_OXIMETER, "", QString(), QString(), QString(), QString(), "Generic", QDateTime::currentDateTime(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
// Serial Stuff
|
// Serial Stuff
|
||||||
virtual bool scanDevice(QString keyword="",quint16 vendor_id=0, quint16 product_id=0);
|
virtual bool scanDevice(QString keyword="",quint16 vendor_id=0, quint16 product_id=0);
|
||||||
@ -60,7 +62,7 @@ public:
|
|||||||
|
|
||||||
virtual void process() {}
|
virtual void process() {}
|
||||||
|
|
||||||
virtual Machine *CreateMachine()=0;
|
//virtual Machine *CreateMachine()=0;
|
||||||
|
|
||||||
// available sessions
|
// available sessions
|
||||||
QMap<QDateTime, QVector<OxiRecord> *> oxisessions;
|
QMap<QDateTime, QVector<OxiRecord> *> oxisessions;
|
||||||
|
@ -115,7 +115,7 @@ bool Session::OpenEvents()
|
|||||||
|
|
||||||
bool Session::Destroy()
|
bool Session::Destroy()
|
||||||
{
|
{
|
||||||
QString path = p_profile->Get(s_machine->properties[STR_PROP_Path]);
|
QString path = s_machine->getDataPath();
|
||||||
|
|
||||||
QDir dir(path);
|
QDir dir(path);
|
||||||
QString base;
|
QString base;
|
||||||
@ -475,7 +475,7 @@ bool Session::StoreEvents(QString filename)
|
|||||||
|
|
||||||
header << (quint16)compress;
|
header << (quint16)compress;
|
||||||
|
|
||||||
header << (quint16)s_machine->GetType();// Machine Type
|
header << (quint16)s_machine->type();// Machine Type
|
||||||
|
|
||||||
QByteArray databytes;
|
QByteArray databytes;
|
||||||
QDataStream out(&databytes, QIODevice::WriteOnly);
|
QDataStream out(&databytes, QIODevice::WriteOnly);
|
||||||
@ -916,7 +916,6 @@ void Session::UpdateSummaries()
|
|||||||
for (; c != ev_end; c++) {
|
for (; c != ev_end; c++) {
|
||||||
id = c.key();
|
id = c.key();
|
||||||
|
|
||||||
|
|
||||||
schema::ChanType ctype = schema::channel[id].type();
|
schema::ChanType ctype = schema::channel[id].type();
|
||||||
if (ctype != schema::SETTING) {
|
if (ctype != schema::SETTING) {
|
||||||
//sum(id); // avg calculates this and cnt.
|
//sum(id); // avg calculates this and cnt.
|
||||||
@ -1158,7 +1157,7 @@ qint64 Session::first(ChannelID id)
|
|||||||
if (i != m_firstchan.end()) {
|
if (i != m_firstchan.end()) {
|
||||||
tmp = i.value();
|
tmp = i.value();
|
||||||
|
|
||||||
if (s_machine->GetType() == MT_CPAP) {
|
if (s_machine->type() == MT_CPAP) {
|
||||||
tmp += drift;
|
tmp += drift;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1190,7 +1189,7 @@ qint64 Session::first(ChannelID id)
|
|||||||
|
|
||||||
m_firstchan[id] = min;
|
m_firstchan[id] = min;
|
||||||
|
|
||||||
if (s_machine->GetType() == MT_CPAP) {
|
if (s_machine->type() == MT_CPAP) {
|
||||||
min += drift;
|
min += drift;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1205,7 +1204,7 @@ qint64 Session::last(ChannelID id)
|
|||||||
if (i != m_lastchan.end()) {
|
if (i != m_lastchan.end()) {
|
||||||
tmp = i.value();
|
tmp = i.value();
|
||||||
|
|
||||||
if (s_machine->GetType() == MT_CPAP) {
|
if (s_machine->type() == MT_CPAP) {
|
||||||
tmp += drift;
|
tmp += drift;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1238,7 +1237,7 @@ qint64 Session::last(ChannelID id)
|
|||||||
|
|
||||||
m_lastchan[id] = max;
|
m_lastchan[id] = max;
|
||||||
|
|
||||||
if (s_machine->GetType() == MT_CPAP) {
|
if (s_machine->type() == MT_CPAP) {
|
||||||
max += drift;
|
max += drift;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1950,7 +1949,7 @@ qint64 Session::first()
|
|||||||
{
|
{
|
||||||
qint64 start = s_first;
|
qint64 start = s_first;
|
||||||
|
|
||||||
if (s_machine->GetType() == MT_CPAP) {
|
if (s_machine->type() == MT_CPAP) {
|
||||||
start += qint64(p_profile->cpap->clockDrift()) * 1000L;
|
start += qint64(p_profile->cpap->clockDrift()) * 1000L;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1961,7 +1960,7 @@ qint64 Session::last()
|
|||||||
{
|
{
|
||||||
qint64 last = s_last;
|
qint64 last = s_last;
|
||||||
|
|
||||||
if (s_machine->GetType() == MT_CPAP) {
|
if (s_machine->type() == MT_CPAP) {
|
||||||
last += qint64(p_profile->cpap->clockDrift()) * 1000L;
|
last += qint64(p_profile->cpap->clockDrift()) * 1000L;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,6 +327,7 @@ class Session
|
|||||||
}
|
}
|
||||||
|
|
||||||
const QString & eventFile() { return s_eventfile; }
|
const QString & eventFile() { return s_eventfile; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
SessionID s_session;
|
SessionID s_session;
|
||||||
|
|
||||||
|
@ -69,6 +69,7 @@ QColor COLOR_Obstructive = COLOR_Aqua;
|
|||||||
QColor COLOR_Apnea = Qt::darkGreen;
|
QColor COLOR_Apnea = Qt::darkGreen;
|
||||||
QColor COLOR_CSR = COLOR_LightGreen;
|
QColor COLOR_CSR = COLOR_LightGreen;
|
||||||
QColor COLOR_LargeLeak = COLOR_LightGray;
|
QColor COLOR_LargeLeak = COLOR_LightGray;
|
||||||
|
QColor COLOR_Ramp = COLOR_LightBlue;
|
||||||
QColor COLOR_ClearAirway = QColor("#b254cd");
|
QColor COLOR_ClearAirway = QColor("#b254cd");
|
||||||
QColor COLOR_RERA = COLOR_Gold;
|
QColor COLOR_RERA = COLOR_Gold;
|
||||||
QColor COLOR_VibratorySnore = QColor("#ff4040");
|
QColor COLOR_VibratorySnore = QColor("#ff4040");
|
||||||
|
@ -45,6 +45,7 @@ extern QColor COLOR_Obstructive;
|
|||||||
extern QColor COLOR_Apnea;
|
extern QColor COLOR_Apnea;
|
||||||
extern QColor COLOR_CSR;
|
extern QColor COLOR_CSR;
|
||||||
extern QColor COLOR_LargeLeak;
|
extern QColor COLOR_LargeLeak;
|
||||||
|
extern QColor COLOR_Ramp;
|
||||||
extern QColor COLOR_ClearAirway;
|
extern QColor COLOR_ClearAirway;
|
||||||
extern QColor COLOR_RERA;
|
extern QColor COLOR_RERA;
|
||||||
extern QColor COLOR_VibratorySnore;
|
extern QColor COLOR_VibratorySnore;
|
||||||
|
@ -205,6 +205,7 @@ Daily::Daily(QWidget *parent,gGraphView * shared)
|
|||||||
// Spans
|
// Spans
|
||||||
fg->AddLayer((new gFlagsLine(CPAP_CSR, COLOR_CSR, STR_TR_PB, false, FT_Span)));
|
fg->AddLayer((new gFlagsLine(CPAP_CSR, COLOR_CSR, STR_TR_PB, false, FT_Span)));
|
||||||
fg->AddLayer((new gFlagsLine(CPAP_LargeLeak, COLOR_LargeLeak, STR_TR_LL, false, FT_Span)));
|
fg->AddLayer((new gFlagsLine(CPAP_LargeLeak, COLOR_LargeLeak, STR_TR_LL, false, FT_Span)));
|
||||||
|
fg->AddLayer((new gFlagsLine(CPAP_Ramp, COLOR_Ramp, schema::channel[CPAP_Ramp].label(), false, FT_Span)));
|
||||||
// Flags
|
// Flags
|
||||||
fg->AddLayer((new gFlagsLine(CPAP_ClearAirway, COLOR_ClearAirway, STR_TR_CA,false)));
|
fg->AddLayer((new gFlagsLine(CPAP_ClearAirway, COLOR_ClearAirway, STR_TR_CA,false)));
|
||||||
fg->AddLayer((new gFlagsLine(CPAP_Obstructive, COLOR_Obstructive, STR_TR_OA,true)));
|
fg->AddLayer((new gFlagsLine(CPAP_Obstructive, COLOR_Obstructive, STR_TR_OA,true)));
|
||||||
@ -255,6 +256,7 @@ Daily::Daily(QWidget *parent,gGraphView * shared)
|
|||||||
// Draw layer is important... spans first..
|
// Draw layer is important... spans first..
|
||||||
FRW->AddLayer(AddCPAP(new gLineOverlayBar(CPAP_CSR, COLOR_CSR, STR_TR_CSR, FT_Span)));
|
FRW->AddLayer(AddCPAP(new gLineOverlayBar(CPAP_CSR, COLOR_CSR, STR_TR_CSR, FT_Span)));
|
||||||
FRW->AddLayer(AddCPAP(new gLineOverlayBar(CPAP_LargeLeak, COLOR_LargeLeak, STR_TR_LL, FT_Span)));
|
FRW->AddLayer(AddCPAP(new gLineOverlayBar(CPAP_LargeLeak, COLOR_LargeLeak, STR_TR_LL, FT_Span)));
|
||||||
|
//FRW->AddLayer(AddCPAP(new gLineOverlayBar(CPAP_Ramp, COLOR_Ramp, schema::channel[CPAP_Ramp].label(), FT_Span)));
|
||||||
|
|
||||||
// Then the graph itself
|
// Then the graph itself
|
||||||
FRW->AddLayer(l);
|
FRW->AddLayer(l);
|
||||||
@ -446,12 +448,14 @@ void Daily::showEvent(QShowEvent *)
|
|||||||
|
|
||||||
void Daily::closeEvent(QCloseEvent *event)
|
void Daily::closeEvent(QCloseEvent *event)
|
||||||
{
|
{
|
||||||
|
|
||||||
disconnect(webView,SIGNAL(linkClicked(QUrl)),this,SLOT(Link_clicked(QUrl)));
|
disconnect(webView,SIGNAL(linkClicked(QUrl)),this,SLOT(Link_clicked(QUrl)));
|
||||||
|
|
||||||
if (previous_date.isValid())
|
if (previous_date.isValid())
|
||||||
Unload(previous_date);
|
Unload(previous_date);
|
||||||
GraphView->SaveSettings("Daily");
|
GraphView->SaveSettings("Daily");
|
||||||
QWidget::closeEvent(event);
|
QWidget::closeEvent(event);
|
||||||
|
event->accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -612,7 +616,7 @@ void Daily::UpdateEventsTree(QTreeWidget *tree,Day *day)
|
|||||||
&& (code!=CPAP_VSnore)) continue;
|
&& (code!=CPAP_VSnore)) continue;
|
||||||
|
|
||||||
if (!userflags && ((code==CPAP_UserFlag1) || (code==CPAP_UserFlag2) || (code==CPAP_UserFlag3))) continue;
|
if (!userflags && ((code==CPAP_UserFlag1) || (code==CPAP_UserFlag2) || (code==CPAP_UserFlag3))) continue;
|
||||||
drift=(*s)->machine()->GetType()==MT_CPAP ? clockdrift : 0;
|
drift=((*s)->machine()->type() == MT_CPAP) ? clockdrift : 0;
|
||||||
|
|
||||||
QTreeWidgetItem *mcr;
|
QTreeWidgetItem *mcr;
|
||||||
if (mcroot.find(code)==mcroot.end()) {
|
if (mcroot.find(code)==mcroot.end()) {
|
||||||
@ -913,7 +917,7 @@ QString Daily::getSessionInformation(Day * cpap, Day * oxi, Day * stage, Day * p
|
|||||||
int h=len/3600;
|
int h=len/3600;
|
||||||
int m=(len/60) % 60;
|
int m=(len/60) % 60;
|
||||||
int s1=len % 60;
|
int s1=len % 60;
|
||||||
tooltip=day->machine->GetClass()+QString(":#%1").arg((*s)->session(),8,10,QChar('0'));
|
tooltip=day->machine->loaderName()+QString(":#%1").arg((*s)->session(),8,10,QChar('0'));
|
||||||
|
|
||||||
#define DEBUG_SESSIONS
|
#define DEBUG_SESSIONS
|
||||||
#ifdef DEBUG_SESSIONS
|
#ifdef DEBUG_SESSIONS
|
||||||
@ -968,7 +972,7 @@ QString Daily::getMachineSettings(Day * cpap) {
|
|||||||
int j=cpap->settings_max(CPAP_PresReliefMode);
|
int j=cpap->settings_max(CPAP_PresReliefMode);
|
||||||
QString flexstr;
|
QString flexstr;
|
||||||
|
|
||||||
if (cpap->machine->GetClass() == STR_MACH_ResMed) {
|
if (cpap->machine->loaderName() == STR_MACH_ResMed) {
|
||||||
// this is temporary..
|
// this is temporary..
|
||||||
flexstr = QString(tr("EPR:%1 EPR_LEVEL:%2")).arg(cpap->settings_max(RMS9_EPR)).arg(cpap->settings_max(RMS9_EPRLevel));
|
flexstr = QString(tr("EPR:%1 EPR_LEVEL:%2")).arg(cpap->settings_max(RMS9_EPR)).arg(cpap->settings_max(RMS9_EPRLevel));
|
||||||
} else {
|
} else {
|
||||||
@ -980,7 +984,7 @@ QString Daily::getMachineSettings(Day * cpap) {
|
|||||||
.arg(schema::channel[CPAP_PresReliefType].description())
|
.arg(schema::channel[CPAP_PresReliefType].description())
|
||||||
.arg(flexstr);
|
.arg(flexstr);
|
||||||
}
|
}
|
||||||
QString mclass=cpap->machine->GetClass();
|
QString mclass=cpap->machine->loaderName();
|
||||||
if (mclass==STR_MACH_PRS1 || mclass==STR_MACH_FPIcon) {
|
if (mclass==STR_MACH_PRS1 || mclass==STR_MACH_FPIcon) {
|
||||||
int humid=round(cpap->settings_wavg(CPAP_HumidSetting));
|
int humid=round(cpap->settings_wavg(CPAP_HumidSetting));
|
||||||
html+=QString("<tr><td><a class='info' href='#'>"+STR_TR_Humidifier+"<span>%1</span></a></td><td colspan=4>%2</td></tr>")
|
html+=QString("<tr><td><a class='info' href='#'>"+STR_TR_Humidifier+"<span>%1</span></a></td><td colspan=4>%2</td></tr>")
|
||||||
@ -1000,7 +1004,7 @@ QString Daily::getOximeterInformation(Day * oxi)
|
|||||||
html="<table cellpadding=0 cellspacing=0 border=0 width=100%>";
|
html="<table cellpadding=0 cellspacing=0 border=0 width=100%>";
|
||||||
html+=QString("<tr><td colspan=5 align=center><b>%1</b></td></tr>\n").arg(tr("Oximeter Information"));
|
html+=QString("<tr><td colspan=5 align=center><b>%1</b></td></tr>\n").arg(tr("Oximeter Information"));
|
||||||
html+="<tr><td colspan=5 align=center> </td></tr>";
|
html+="<tr><td colspan=5 align=center> </td></tr>";
|
||||||
html+="<tr><td colspan=5 align=center>"+oxi->machine->properties[STR_PROP_Brand]+" "+oxi->machine->properties[STR_PROP_Model]+"</td></tr>\n";
|
html+="<tr><td colspan=5 align=center>"+oxi->machine->brand()+" "+oxi->machine->model()+"</td></tr>\n";
|
||||||
html+="<tr><td colspan=5 align=center> </td></tr>";
|
html+="<tr><td colspan=5 align=center> </td></tr>";
|
||||||
html+=QString("<tr><td colspan=5 align=center>%1: %2 (%3%)</td></tr>").arg(tr("SpO2 Desaturations")).arg(oxi->count(OXI_SPO2Drop)).arg((100.0/oxi->hours()) * (oxi->sum(OXI_SPO2Drop)/3600.0),0,'f',2);
|
html+=QString("<tr><td colspan=5 align=center>%1: %2 (%3%)</td></tr>").arg(tr("SpO2 Desaturations")).arg(oxi->count(OXI_SPO2Drop)).arg((100.0/oxi->hours()) * (oxi->sum(OXI_SPO2Drop)/3600.0),0,'f',2);
|
||||||
html+=QString("<tr><td colspan=5 align=center>%1: %2 (%3%)</td></tr>").arg(tr("Pulse Change events")).arg(oxi->count(OXI_PulseChange)).arg((100.0/oxi->hours()) * (oxi->sum(OXI_PulseChange)/3600.0),0,'f',2);
|
html+=QString("<tr><td colspan=5 align=center>%1: %2 (%3%)</td></tr>").arg(tr("Pulse Change events")).arg(oxi->count(OXI_PulseChange)).arg((100.0/oxi->hours()) * (oxi->sum(OXI_PulseChange)/3600.0),0,'f',2);
|
||||||
@ -1017,15 +1021,12 @@ QString Daily::getCPAPInformation(Day * cpap)
|
|||||||
if (!cpap)
|
if (!cpap)
|
||||||
return html;
|
return html;
|
||||||
|
|
||||||
QString brand=cpap->machine->properties[STR_PROP_Brand];
|
MachineInfo info = cpap->machine->getInfo();
|
||||||
QString series=cpap->machine->properties[STR_PROP_Series];
|
|
||||||
QString model=cpap->machine->properties[STR_PROP_Model];
|
|
||||||
QString number=cpap->machine->properties[STR_PROP_ModelNumber];
|
|
||||||
|
|
||||||
html="<table cellspacing=0 cellpadding=0 border=0 width='100%'>\n";
|
html="<table cellspacing=0 cellpadding=0 border=0 width='100%'>\n";
|
||||||
|
|
||||||
html+="<tr><td colspan=4 align=center><a class=info2 href='#'>"+model+"<span>";
|
html+="<tr><td colspan=4 align=center><a class=info2 href='#'>"+info.model+"<span>";
|
||||||
QString tooltip=(brand+"\n"+series+" "+number+"\n"+cpap->machine->properties[STR_PROP_Serial]);
|
QString tooltip=(info.brand+"\n"+info.series+" "+info.modelnumber+"\n"+info.serial);
|
||||||
tooltip=tooltip.replace(" "," ");
|
tooltip=tooltip.replace(" "," ");
|
||||||
|
|
||||||
|
|
||||||
@ -1157,8 +1158,7 @@ QString Daily::getStatisticsInfo(Day * cpap,Day * oxi,Day *pos)
|
|||||||
if (GraphView->isEmpty() && ((ccnt>0) || (cpap && cpap->summaryOnly()))) {
|
if (GraphView->isEmpty() && ((ccnt>0) || (cpap && cpap->summaryOnly()))) {
|
||||||
html+="<tr><td colspan=5> </td></tr>\n";
|
html+="<tr><td colspan=5> </td></tr>\n";
|
||||||
html+=QString("<tr><td colspan=5 align=center><i>%1</i></td></tr>").arg("<b>"+STR_MessageBox_PleaseNote+"</b> "+ tr("This day just contains summary data, only limited information is available ."));
|
html+=QString("<tr><td colspan=5 align=center><i>%1</i></td></tr>").arg("<b>"+STR_MessageBox_PleaseNote+"</b> "+ tr("This day just contains summary data, only limited information is available ."));
|
||||||
} else
|
} else if (cpap && p_profile->cpap->showLeakRedline()) {
|
||||||
if (cpap && p_profile->cpap->showLeakRedline()) {
|
|
||||||
float rlt = cpap->timeAboveThreshold(CPAP_Leak, p_profile->cpap->leakRedline()) / 60.0;
|
float rlt = cpap->timeAboveThreshold(CPAP_Leak, p_profile->cpap->leakRedline()) / 60.0;
|
||||||
float pc = 100.0 / cpap->hours() * rlt;
|
float pc = 100.0 / cpap->hours() * rlt;
|
||||||
html+="<tr><td colspan=5> </td></tr>";
|
html+="<tr><td colspan=5> </td></tr>";
|
||||||
@ -1166,6 +1166,20 @@ QString Daily::getStatisticsInfo(Day * cpap,Day * oxi,Day *pos)
|
|||||||
QString("</b></td><td colspan=2 bgcolor='white'>%1%</td></tr>").arg(pc, 0, 'f', 3);
|
QString("</b></td><td colspan=2 bgcolor='white'>%1%</td></tr>").arg(pc, 0, 'f', 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cpap) {
|
||||||
|
int l = cpap->sum(CPAP_Ramp);
|
||||||
|
|
||||||
|
// if (l>0) {
|
||||||
|
int h = l / 3600;
|
||||||
|
int m = (l / 60) % 60;
|
||||||
|
int s = l % 60;
|
||||||
|
html+="<tr><td colspan=3 align='left' bgcolor='white'><b>"+tr("Time spent in ramp")+
|
||||||
|
QString("</b></td><td colspan=2 bgcolor='white'>%1:%2:%3</td></tr>").arg(h, 2, 10, QChar('0')).arg(m, 2, 10, QChar('0')).arg(s, 2, 10, QChar('0'));
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
html+="</table>\n";
|
html+="</table>\n";
|
||||||
html+="<hr/>\n";
|
html+="<hr/>\n";
|
||||||
return html;
|
return html;
|
||||||
@ -1357,7 +1371,7 @@ void Daily::Load(QDate date)
|
|||||||
for (int i=0;i<numchans;i++) {
|
for (int i=0;i<numchans;i++) {
|
||||||
if (!cpap->channelHasData(chans[i].id))
|
if (!cpap->channelHasData(chans[i].id))
|
||||||
continue;
|
continue;
|
||||||
if ((cpap->machine->GetClass()==STR_MACH_PRS1) && (chans[i].id==CPAP_VSnore))
|
if ((cpap->machine->loaderName() == STR_MACH_PRS1) && (chans[i].id == CPAP_VSnore))
|
||||||
continue;
|
continue;
|
||||||
html+=QString("<tr><td align='left' bgcolor='%1'><b><font color='%2'><a href='event=%5'>%3</a></font></b></td><td width=20% bgcolor='%1'><b><font color='%2'>%4</font></b></td></tr>\n")
|
html+=QString("<tr><td align='left' bgcolor='%1'><b><font color='%2'><a href='event=%5'>%3</a></font></b></td><td width=20% bgcolor='%1'><b><font color='%2'>%4</font></b></td></tr>\n")
|
||||||
.arg(chans[i].color.name()).arg(chans[i].color2.name()).arg(schema::channel[chans[i].id].fullname()).arg(chans[i].value,0,'f',2).arg(chans[i].id);
|
.arg(chans[i].color.name()).arg(chans[i].color2.name()).arg(schema::channel[chans[i].id].fullname()).arg(chans[i].value,0,'f',2).arg(chans[i].id);
|
||||||
@ -1733,9 +1747,12 @@ Session * Daily::CreateJournalSession(QDate date)
|
|||||||
Machine *m=p_profile->GetMachine(MT_JOURNAL);
|
Machine *m=p_profile->GetMachine(MT_JOURNAL);
|
||||||
if (!m) {
|
if (!m) {
|
||||||
m=new Machine(0);
|
m=new Machine(0);
|
||||||
m->SetClass("Journal");
|
MachineInfo info;
|
||||||
m->properties[STR_PROP_Brand]="Virtual";
|
info.loadername = "Journal";
|
||||||
m->SetType(MT_JOURNAL);
|
info.serial = m->hexid();
|
||||||
|
info.brand = "Journal";
|
||||||
|
info.type = MT_JOURNAL;
|
||||||
|
m->setInfo(info);
|
||||||
p_profile->AddMachine(m);
|
p_profile->AddMachine(m);
|
||||||
}
|
}
|
||||||
Session *sess=new Session(m,0);
|
Session *sess=new Session(m,0);
|
||||||
|
@ -172,7 +172,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||||||
#ifdef LOCK_RESMED_SESSIONS
|
#ifdef LOCK_RESMED_SESSIONS
|
||||||
QList<Machine *> machines = p_profile->GetMachines(MT_CPAP);
|
QList<Machine *> machines = p_profile->GetMachines(MT_CPAP);
|
||||||
for (QList<Machine *>::iterator it = machines.begin(); it != machines.end(); ++it) {
|
for (QList<Machine *>::iterator it = machines.begin(); it != machines.end(); ++it) {
|
||||||
QString mclass=(*it)->GetClass();
|
QString mclass=(*it)->loaderName();
|
||||||
if (mclass == STR_MACH_ResMed) {
|
if (mclass == STR_MACH_ResMed) {
|
||||||
qDebug() << "ResMed machine found.. locking Session splitting capabilities";
|
qDebug() << "ResMed machine found.. locking Session splitting capabilities";
|
||||||
|
|
||||||
@ -262,7 +262,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||||||
restoreGeometry(settings.value("MainWindow/geometry").toByteArray());
|
restoreGeometry(settings.value("MainWindow/geometry").toByteArray());
|
||||||
|
|
||||||
daily = new Daily(ui->tabWidget, nullptr);
|
daily = new Daily(ui->tabWidget, nullptr);
|
||||||
ui->tabWidget->insertTab(2, daily, STR_TR_Daily);
|
ui->tabWidget->insertTab(1, daily, STR_TR_Daily);
|
||||||
|
|
||||||
|
|
||||||
// Start with the Summary Tab
|
// Start with the Summary Tab
|
||||||
@ -428,6 +428,22 @@ void MyStatsPage::javaScriptAlert(QWebFrame *frame, const QString &msg)
|
|||||||
mainwin->sendStatsUrl(msg);
|
mainwin->sendStatsUrl(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString getCPAPPixmap(QString mach_class)
|
||||||
|
{
|
||||||
|
QString cpapimage;
|
||||||
|
if (mach_class == STR_MACH_ResMed) cpapimage = ":/icons/rms9.png";
|
||||||
|
else if (mach_class == STR_MACH_PRS1) cpapimage = ":/icons/prs1.png";
|
||||||
|
else if (mach_class == STR_MACH_Intellipap) cpapimage = ":/icons/intellipap.png";
|
||||||
|
return cpapimage;
|
||||||
|
}
|
||||||
|
|
||||||
|
QIcon getCPAPIcon(QString mach_class)
|
||||||
|
{
|
||||||
|
QString cpapimage = getCPAPPixmap(mach_class);
|
||||||
|
|
||||||
|
return QIcon(cpapimage);
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::PopulatePurgeMenu()
|
void MainWindow::PopulatePurgeMenu()
|
||||||
{
|
{
|
||||||
QList<QAction *> actions = ui->menu_Rebuild_CPAP_Data->actions();
|
QList<QAction *> actions = ui->menu_Rebuild_CPAP_Data->actions();
|
||||||
@ -439,12 +455,14 @@ void MainWindow::PopulatePurgeMenu()
|
|||||||
QList<Machine *> machines = p_profile->GetMachines(MT_CPAP);
|
QList<Machine *> machines = p_profile->GetMachines(MT_CPAP);
|
||||||
for (int i=0; i < machines.size(); ++i) {
|
for (int i=0; i < machines.size(); ++i) {
|
||||||
Machine *mach = machines.at(i);
|
Machine *mach = machines.at(i);
|
||||||
QString name = mach->properties[STR_PROP_Brand]+" "+
|
QString name = mach->brand() + " "+
|
||||||
mach->properties[STR_PROP_Model]+" "+
|
mach->model() + " "+
|
||||||
mach->properties[STR_PROP_Serial];
|
mach->serial();
|
||||||
|
|
||||||
QAction * action = new QAction(name.replace("&","&&"), ui->menu_Rebuild_CPAP_Data);
|
QAction * action = new QAction(name.replace("&","&&"), ui->menu_Rebuild_CPAP_Data);
|
||||||
action->setData(mach->GetClass()+":"+mach->properties[STR_PROP_Serial]);
|
action->setIconVisibleInMenu(true);
|
||||||
|
action->setIcon(getCPAPIcon(mach->loaderName()));
|
||||||
|
action->setData(mach->loaderName()+":"+mach->serial());
|
||||||
ui->menu_Rebuild_CPAP_Data->addAction(action);
|
ui->menu_Rebuild_CPAP_Data->addAction(action);
|
||||||
}
|
}
|
||||||
ui->menu_Rebuild_CPAP_Data->connect(ui->menu_Rebuild_CPAP_Data, SIGNAL(triggered(QAction*)), this, SLOT(on_actionPurgeMachine(QAction*)));
|
ui->menu_Rebuild_CPAP_Data->connect(ui->menu_Rebuild_CPAP_Data, SIGNAL(triggered(QAction*)), this, SLOT(on_actionPurgeMachine(QAction*)));
|
||||||
@ -498,8 +516,12 @@ void MainWindow::Startup()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int MainWindow::importCPAP(const QString &path, const QString &message)
|
int MainWindow::importCPAP(ImportPath import, const QString &message)
|
||||||
{
|
{
|
||||||
|
if (!import.loader) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
QDialog popup(this, Qt::SplashScreen);
|
QDialog popup(this, Qt::SplashScreen);
|
||||||
QLabel waitmsg(message);
|
QLabel waitmsg(message);
|
||||||
QVBoxLayout waitlayout(&popup);
|
QVBoxLayout waitlayout(&popup);
|
||||||
@ -507,7 +529,7 @@ int MainWindow::importCPAP(const QString &path, const QString &message)
|
|||||||
waitlayout.addWidget(qprogress,1);
|
waitlayout.addWidget(qprogress,1);
|
||||||
qprogress->setVisible(true);
|
qprogress->setVisible(true);
|
||||||
popup.show();
|
popup.show();
|
||||||
int c=p_profile->Import(path);
|
int c=import.loader->Open(import.path);;
|
||||||
popup.hide();
|
popup.hide();
|
||||||
ui->statusbar->insertWidget(2,qprogress,1);
|
ui->statusbar->insertWidget(2,qprogress,1);
|
||||||
qprogress->setVisible(false);
|
qprogress->setVisible(false);
|
||||||
@ -528,35 +550,23 @@ void MainWindow::importCPAPBackups()
|
|||||||
{
|
{
|
||||||
// Get BackupPaths for all CPAP machines
|
// Get BackupPaths for all CPAP machines
|
||||||
QList<Machine *> machlist = p_profile->GetMachines(MT_CPAP);
|
QList<Machine *> machlist = p_profile->GetMachines(MT_CPAP);
|
||||||
QStringList paths;
|
QList<ImportPath> paths;
|
||||||
Q_FOREACH(Machine *m, machlist) {
|
Q_FOREACH(Machine *m, machlist) {
|
||||||
if (m->properties.contains(STR_PROP_BackupPath)) {
|
paths.append(ImportPath(m->getBackupPath(), lookupLoader(m)));
|
||||||
paths.push_back(p_profile->Get(m->properties[STR_PROP_BackupPath]));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (paths.size() > 0) {
|
if (paths.size() > 0) {
|
||||||
if (QMessageBox::question(
|
int c=0;
|
||||||
this,
|
QString str=tr("Data successfully imported from the following locations:")+"\n\n";
|
||||||
STR_MessageBox_Question,
|
Q_FOREACH(ImportPath path, paths) {
|
||||||
tr("CPAP data was recently purged and needs to be re-imported.")+"\n\n"+
|
c+=importCPAP(path, tr("Please wait, importing from backup folder(s)..."));
|
||||||
tr("Would you like this done automatically from the Backup Folder?")+"\n\n"+
|
str.append(QDir::toNativeSeparators(path.path)+"\n");
|
||||||
QDir::toNativeSeparators(paths.join("\n")),
|
}
|
||||||
QMessageBox::Yes | QMessageBox::No,
|
if (c>0) {
|
||||||
QMessageBox::Yes) == QMessageBox::Yes)
|
mainwin->Notify(str);
|
||||||
{
|
finishCPAPImport();
|
||||||
int c=0;
|
} else {
|
||||||
Q_FOREACH(QString path, paths) {
|
mainwin->Notify(tr("Couldn't find any new Machine Data at the locations given."),tr("Import Problem"));
|
||||||
c+=importCPAP(path,tr("Please wait, importing from backup folder(s)..."));
|
|
||||||
}
|
|
||||||
if (c>0) {
|
|
||||||
QString str=tr("Data successfully imported from the following locations:")+"\n\n"+
|
|
||||||
QDir::toNativeSeparators(paths.join("\n"));
|
|
||||||
mainwin->Notify(str);
|
|
||||||
finishCPAPImport();
|
|
||||||
} else {
|
|
||||||
mainwin->Notify(tr("Couldn't find any new Machine Data at the locations given."),tr("Import Problem"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -634,11 +644,12 @@ QStringList getDriveList()
|
|||||||
return drivelist;
|
return drivelist;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList MainWindow::detectCPAPCards()
|
|
||||||
|
QList<ImportPath> MainWindow::detectCPAPCards()
|
||||||
{
|
{
|
||||||
const int timeout = 20000;
|
const int timeout = 20000;
|
||||||
|
|
||||||
QStringList datapaths;
|
QList<ImportPath> detectedCards;
|
||||||
|
|
||||||
QList<MachineLoader *>loaders = GetLoaders(MT_CPAP);
|
QList<MachineLoader *>loaders = GetLoaders(MT_CPAP);
|
||||||
QTime time;
|
QTime time;
|
||||||
@ -674,9 +685,9 @@ QStringList MainWindow::detectCPAPCards()
|
|||||||
// Scan through available machine loaders and test if this folder contains valid folder structure
|
// Scan through available machine loaders and test if this folder contains valid folder structure
|
||||||
Q_FOREACH(MachineLoader * loader, loaders) {
|
Q_FOREACH(MachineLoader * loader, loaders) {
|
||||||
if (loader->Detect(path)) {
|
if (loader->Detect(path)) {
|
||||||
datapaths.push_back(path);
|
detectedCards.append(ImportPath(path, loader));
|
||||||
|
|
||||||
qDebug() << "Found" << loader->ClassName() << "datacard at" << path;
|
qDebug() << "Found" << loader->loaderName() << "datacard at" << path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -687,13 +698,14 @@ QStringList MainWindow::detectCPAPCards()
|
|||||||
if (!popup.isVisible()) break;
|
if (!popup.isVisible()) break;
|
||||||
// needs a slight delay here
|
// needs a slight delay here
|
||||||
QThread::msleep(200);
|
QThread::msleep(200);
|
||||||
} while (datapaths.size() == 0);
|
} while (detectedCards.size() == 0);
|
||||||
popup.hide();
|
popup.hide();
|
||||||
popup.disconnect(&skipbtn, SIGNAL(clicked()), &popup, SLOT(hide()));
|
popup.disconnect(&skipbtn, SIGNAL(clicked()), &popup, SLOT(hide()));
|
||||||
|
|
||||||
return datapaths;
|
return detectedCards;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MainWindow::on_action_Import_Data_triggered()
|
void MainWindow::on_action_Import_Data_triggered()
|
||||||
{
|
{
|
||||||
if (m_inRecalculation) {
|
if (m_inRecalculation) {
|
||||||
@ -701,7 +713,7 @@ void MainWindow::on_action_Import_Data_triggered()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList datapaths = detectCPAPCards();
|
QList<ImportPath> datacards = detectCPAPCards();
|
||||||
|
|
||||||
QList<MachineLoader *>loaders = GetLoaders(MT_CPAP);
|
QList<MachineLoader *>loaders = GetLoaders(MT_CPAP);
|
||||||
|
|
||||||
@ -717,23 +729,35 @@ void MainWindow::on_action_Import_Data_triggered()
|
|||||||
bool asknew = false;
|
bool asknew = false;
|
||||||
qprogress->setVisible(false);
|
qprogress->setVisible(false);
|
||||||
|
|
||||||
if (datapaths.size() > 0) {
|
if (datacards.size() > 0) {
|
||||||
int res = QMessageBox::question(this,
|
MachineInfo info = datacards[0].loader->PeekInfo(datacards[0].path);
|
||||||
tr("CPAP Data Located"),
|
QString infostr;
|
||||||
tr("CPAP Datacard structures were detected at the following locations:")+
|
if (!info.model.isEmpty()) {
|
||||||
QString("\n\n%1\n\n").arg(QDir::toNativeSeparators(datapaths.join("\n")))+
|
QString infostr2 = info.model+" ("+info.serial+")";
|
||||||
tr("Would you like to import from the path(s) shown above?"),
|
infostr = tr("A %1 file structure for a %2 was located at:").arg(info.brand).arg(infostr2);
|
||||||
STR_MessageBox_Yes,
|
} else {
|
||||||
tr("Select another folder"),
|
infostr = tr("A %1 file structure was located at:").arg(datacards[0].loader->loaderName());
|
||||||
STR_MessageBox_Cancel,
|
|
||||||
0, 2);
|
|
||||||
if (res == 1) {
|
|
||||||
waitmsg.setText(tr("Please wait, launching file dialog..."));
|
|
||||||
datapaths.clear();
|
|
||||||
asknew = true;
|
|
||||||
}
|
}
|
||||||
|
QMessageBox mbox(QMessageBox::NoIcon,
|
||||||
|
tr("CPAP Data Located"),
|
||||||
|
infostr+"\n\n"+QDir::toNativeSeparators(datacards[0].path)+"\n\n"+
|
||||||
|
tr("Would you like to import from this location?"),
|
||||||
|
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
|
||||||
|
this);
|
||||||
|
mbox.setDefaultButton(QMessageBox::Yes);
|
||||||
|
mbox.setButtonText(QMessageBox::No, tr("Specify"));
|
||||||
|
|
||||||
if (res == 2) {
|
QPixmap pixmap = QPixmap(getCPAPPixmap(datacards[0].loader->loaderName())).scaled(64,64);
|
||||||
|
mbox.setIconPixmap(pixmap);
|
||||||
|
int res = mbox.exec();
|
||||||
|
|
||||||
|
if (res == QMessageBox::Cancel) {
|
||||||
|
return;
|
||||||
|
} else if (res == QMessageBox::No) {
|
||||||
|
waitmsg.setText(tr("Please wait, launching file dialog..."));
|
||||||
|
datacards.clear();
|
||||||
|
asknew = true;
|
||||||
|
} else {
|
||||||
// Give the communal progress bar back
|
// Give the communal progress bar back
|
||||||
ui->statusbar->insertWidget(2,qprogress,1);
|
ui->statusbar->insertWidget(2,qprogress,1);
|
||||||
return;
|
return;
|
||||||
@ -807,7 +831,12 @@ void MainWindow::on_action_Import_Data_triggered()
|
|||||||
popup.hide();
|
popup.hide();
|
||||||
|
|
||||||
for (int i = 0; i < w.selectedFiles().size(); i++) {
|
for (int i = 0; i < w.selectedFiles().size(); i++) {
|
||||||
datapaths.append(w.selectedFiles().at(i));
|
Q_FOREACH(MachineLoader * loader, loaders) {
|
||||||
|
if (loader->Detect(w.selectedFiles().at(i))) {
|
||||||
|
datacards.append(ImportPath(w.selectedFiles().at(i), loader));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -819,14 +848,16 @@ void MainWindow::on_action_Import_Data_triggered()
|
|||||||
qprogress->setVisible(true);
|
qprogress->setVisible(true);
|
||||||
|
|
||||||
popup.show();
|
popup.show();
|
||||||
for (int i = 0; i < datapaths.size(); i++) {
|
for (int i = 0; i < datacards.size(); i++) {
|
||||||
QString dir = datapaths[i];
|
QString dir = datacards[i].path;
|
||||||
|
MachineLoader * loader = datacards[i].loader;
|
||||||
|
if (!loader) continue;
|
||||||
|
|
||||||
if (!dir.isEmpty()) {
|
if (!dir.isEmpty()) {
|
||||||
qprogress->setValue(0);
|
qprogress->setValue(0);
|
||||||
qprogress->show();
|
qprogress->show();
|
||||||
qstatus->setText(tr("Importing Data"));
|
qstatus->setText(tr("Importing Data"));
|
||||||
int c = p_profile->Import(dir);
|
int c = loader->Open(dir);
|
||||||
qDebug() << "Finished Importing data" << c;
|
qDebug() << "Finished Importing data" << c;
|
||||||
|
|
||||||
if (c) {
|
if (c) {
|
||||||
@ -1746,6 +1777,10 @@ void MainWindow::on_actionChange_User_triggered()
|
|||||||
RestartApplication(true);
|
RestartApplication(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void purgeCPAPDay(QDate date)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionPurge_Current_Day_triggered()
|
void MainWindow::on_actionPurge_Current_Day_triggered()
|
||||||
{
|
{
|
||||||
QDate date = getDaily()->getDate();
|
QDate date = getDaily()->getDate();
|
||||||
@ -1759,11 +1794,56 @@ void MainWindow::on_actionPurge_Current_Day_triggered()
|
|||||||
QList<Session *>::iterator s;
|
QList<Session *>::iterator s;
|
||||||
|
|
||||||
QList<Session *> list;
|
QList<Session *> list;
|
||||||
|
QList<SessionID> sidlist;
|
||||||
for (s = day->begin(); s != day->end(); ++s) {
|
for (s = day->begin(); s != day->end(); ++s) {
|
||||||
list.push_back(*s);
|
list.push_back(*s);
|
||||||
|
sidlist.push_back((*s)->session());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QHash<QString, SessionID> skipfiles;
|
||||||
|
// Read the already imported file list
|
||||||
|
|
||||||
|
QFile impfile(m->getDataPath()+"/imported_files.csv");
|
||||||
|
if (impfile.exists()) {
|
||||||
|
if (impfile.open(QFile::ReadOnly)) {
|
||||||
|
QTextStream impstream(&impfile);
|
||||||
|
QString serial;
|
||||||
|
impstream >> serial;
|
||||||
|
if (m->serial() == serial) {
|
||||||
|
QString line, file, str;
|
||||||
|
SessionID sid;
|
||||||
|
bool ok;
|
||||||
|
do {
|
||||||
|
line = impstream.readLine();
|
||||||
|
file = line.section(',',0,0);
|
||||||
|
str = line.section(',',1);
|
||||||
|
sid = str.toInt(&ok);
|
||||||
|
if (!sidlist.contains(sid)) {
|
||||||
|
skipfiles[file] = sid;
|
||||||
|
}
|
||||||
|
} while (!impstream.atEnd());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impfile.close();
|
||||||
|
// Delete the file
|
||||||
|
impfile.remove();
|
||||||
|
|
||||||
|
// Rewrite the file without the sessions being removed.
|
||||||
|
if (impfile.open(QFile::WriteOnly)) {
|
||||||
|
QTextStream out(&impfile);
|
||||||
|
out << m->serial();
|
||||||
|
QHash<QString, SessionID>::iterator skit;
|
||||||
|
QHash<QString, SessionID>::iterator skit_end = skipfiles.end();
|
||||||
|
for (skit = skipfiles.begin(); skit != skit_end; ++skit) {
|
||||||
|
QString a = QString("%1,%2\n").arg(skit.key()).arg(skit.value());;
|
||||||
|
out << a;
|
||||||
|
}
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
impfile.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// m->day.erase(m->day.find(date));
|
// m->day.erase(m->day.find(date));
|
||||||
|
|
||||||
for (int i = 0; i < list.size(); i++) {
|
for (int i = 0; i < list.size(); i++) {
|
||||||
@ -1791,7 +1871,7 @@ void MainWindow::on_actionPurgeMachine(QAction *action)
|
|||||||
Machine * mach = nullptr;
|
Machine * mach = nullptr;
|
||||||
for (int i=0; i < machines.size(); ++i) {
|
for (int i=0; i < machines.size(); ++i) {
|
||||||
Machine * m = machines.at(i);
|
Machine * m = machines.at(i);
|
||||||
if ((m->GetClass() == cls) && (m->properties[STR_PROP_Serial] == serial)) {
|
if ((m->loaderName() == cls) && (m->serial() == serial)) {
|
||||||
mach = m;
|
mach = m;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1803,19 +1883,15 @@ void MainWindow::on_actionPurgeMachine(QAction *action)
|
|||||||
void MainWindow::purgeMachine(Machine * mach)
|
void MainWindow::purgeMachine(Machine * mach)
|
||||||
{
|
{
|
||||||
// detect backups
|
// detect backups
|
||||||
bool backups = false;
|
QString bpath = mach->getBackupPath();
|
||||||
if (mach->properties.contains(STR_PROP_BackupPath)) {
|
bool backups = (dirCount(bpath) > 0) ? true : false;
|
||||||
QString bpath = p_profile->Get(mach->properties[STR_PROP_BackupPath]);
|
|
||||||
int cnt = dirCount(bpath);
|
|
||||||
if (cnt > 0) backups = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (backups) {
|
if (backups) {
|
||||||
if (QMessageBox::question(this,
|
if (QMessageBox::question(this,
|
||||||
STR_MessageBox_Question,
|
STR_MessageBox_Question,
|
||||||
tr("Are you sure you want to rebuild all CPAP data for the following machine:")+ "\n\n" +
|
tr("Are you sure you want to rebuild all CPAP data for the following machine:")+ "\n\n" +
|
||||||
mach->properties[STR_PROP_Brand] + " " + mach->properties[STR_PROP_Model] + " " +
|
mach->brand() + " " + mach->model() + " " +
|
||||||
mach->properties[STR_PROP_ModelNumber] + " (" + mach->properties[STR_PROP_Serial] + ")" + "\n\n"+
|
mach->modelnumber() + " (" + mach->serial() + ")" + "\n\n"+
|
||||||
tr("Please note, that this could result in loss of graph data if SleepyHead's internal backups have been disabled or interfered with in any way."),
|
tr("Please note, that this could result in loss of graph data if SleepyHead's internal backups have been disabled or interfered with in any way."),
|
||||||
QMessageBox::Yes | QMessageBox::No,
|
QMessageBox::Yes | QMessageBox::No,
|
||||||
QMessageBox::No) == QMessageBox::No) {
|
QMessageBox::No) == QMessageBox::No) {
|
||||||
@ -1825,8 +1901,8 @@ void MainWindow::purgeMachine(Machine * mach)
|
|||||||
if (QMessageBox::question(this,
|
if (QMessageBox::question(this,
|
||||||
STR_MessageBox_Warning,
|
STR_MessageBox_Warning,
|
||||||
"<p><b>"+STR_MessageBox_Warning+": </b>"+tr("For some reason, SleepyHead does not have internal backups for the following machine:")+ "</p>" +
|
"<p><b>"+STR_MessageBox_Warning+": </b>"+tr("For some reason, SleepyHead does not have internal backups for the following machine:")+ "</p>" +
|
||||||
"<p>"+mach->properties[STR_PROP_Brand] + " " + mach->properties[STR_PROP_Model] + " " +
|
"<p>"+mach->brand() + " " + mach->model() + " " +
|
||||||
mach->properties[STR_PROP_ModelNumber] + " (" + mach->properties[STR_PROP_Serial] + ")" + "</p>"+
|
mach->modelnumber() + " (" + mach->serial() + ")" + "</p>"+
|
||||||
"<p>"+tr("Provided you have made <i>your <b>own</b> backups for ALL of your CPAP data</i>, you can still complete this operation, but you will have to restore from your backups manually.")+"</p>"
|
"<p>"+tr("Provided you have made <i>your <b>own</b> backups for ALL of your CPAP data</i>, you can still complete this operation, but you will have to restore from your backups manually.")+"</p>"
|
||||||
"<p><b>"+tr("Are you really sure you want to do this?")+"</b></p>",
|
"<p><b>"+tr("Are you really sure you want to do this?")+"</b></p>",
|
||||||
QMessageBox::Yes | QMessageBox::No,
|
QMessageBox::Yes | QMessageBox::No,
|
||||||
@ -1844,7 +1920,7 @@ void MainWindow::purgeMachine(Machine * mach)
|
|||||||
QMessageBox::warning(this, STR_MessageBox_Error,
|
QMessageBox::warning(this, STR_MessageBox_Error,
|
||||||
tr("A file permission error or simillar screwed up the purge process, you will have to delete the following folder manually:")
|
tr("A file permission error or simillar screwed up the purge process, you will have to delete the following folder manually:")
|
||||||
+"\n\n"+
|
+"\n\n"+
|
||||||
QDir::toNativeSeparators(p_profile->Get(mach->properties[STR_PROP_Path])), QMessageBox::Ok, QMessageBox::Ok);
|
QDir::toNativeSeparators(mach->getDataPath()), QMessageBox::Ok, QMessageBox::Ok);
|
||||||
if (overview) overview->ReloadGraphs();
|
if (overview) overview->ReloadGraphs();
|
||||||
|
|
||||||
if (daily) {
|
if (daily) {
|
||||||
@ -1866,7 +1942,7 @@ void MainWindow::purgeMachine(Machine * mach)
|
|||||||
|
|
||||||
|
|
||||||
if (backups) {
|
if (backups) {
|
||||||
importCPAP(p_profile->Get(mach->properties[STR_PROP_BackupPath]),tr("Please wait, importing..."));
|
importCPAP(ImportPath(mach->getBackupPath(), lookupLoader(mach)), tr("Please wait, importing..."));
|
||||||
} else {
|
} else {
|
||||||
if (QMessageBox::information(this, STR_MessageBox_Warning,
|
if (QMessageBox::information(this, STR_MessageBox_Warning,
|
||||||
tr("Because there are no internal backups to rebuild from, you will have to restore from your own.")+"\n\n"+
|
tr("Because there are no internal backups to rebuild from, you will have to restore from your own.")+"\n\n"+
|
||||||
|
@ -29,6 +29,7 @@ namespace Ui {
|
|||||||
class MainWindow;
|
class MainWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! \mainpage SleepyHead
|
/*! \mainpage SleepyHead
|
||||||
|
|
||||||
\section intro_sec Introduction
|
\section intro_sec Introduction
|
||||||
@ -132,7 +133,7 @@ class MainWindow : public QMainWindow
|
|||||||
|
|
||||||
//! \brief Internal function to set Records Box html from statistics module
|
//! \brief Internal function to set Records Box html from statistics module
|
||||||
void setRecBoxHTML(QString html);
|
void setRecBoxHTML(QString html);
|
||||||
int importCPAP(const QString &path, const QString &message);
|
int importCPAP(ImportPath import, const QString &message);
|
||||||
|
|
||||||
void startImportDialog() { on_action_Import_Data_triggered(); }
|
void startImportDialog() { on_action_Import_Data_triggered(); }
|
||||||
|
|
||||||
@ -320,7 +321,7 @@ class MainWindow : public QMainWindow
|
|||||||
private:
|
private:
|
||||||
void importCPAPBackups();
|
void importCPAPBackups();
|
||||||
void finishCPAPImport();
|
void finishCPAPImport();
|
||||||
QStringList detectCPAPCards();
|
QList<ImportPath> detectCPAPCards();
|
||||||
|
|
||||||
QString getWelcomeHTML();
|
QString getWelcomeHTML();
|
||||||
void FreeSessions();
|
void FreeSessions();
|
||||||
|
@ -346,6 +346,7 @@ gGraph *Overview::createGraph(QString code, QString name, QString units, YTicker
|
|||||||
g->AddLayer(yt, LayerLeft, gYAxis::Margin);
|
g->AddLayer(yt, LayerLeft, gYAxis::Margin);
|
||||||
gXAxis *x = new gXAxis();
|
gXAxis *x = new gXAxis();
|
||||||
x->setUtcFix(true);
|
x->setUtcFix(true);
|
||||||
|
x->setRoundDays(true);
|
||||||
g->AddLayer(x, LayerBottom, 0, gXAxis::Margin);
|
g->AddLayer(x, LayerBottom, 0, gXAxis::Margin);
|
||||||
g->AddLayer(new gXGrid());
|
g->AddLayer(new gXGrid());
|
||||||
return g;
|
return g;
|
||||||
|
@ -186,7 +186,7 @@ SerialOximeter * OximeterImport::detectOximeter()
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateStatus(tr("Connecting to %1 Oximeter").arg(oximodule->ClassName()));
|
updateStatus(tr("Connecting to %1 Oximeter").arg(oximodule->loaderName()));
|
||||||
|
|
||||||
return oximodule;
|
return oximodule;
|
||||||
}
|
}
|
||||||
@ -200,7 +200,7 @@ void OximeterImport::on_directImportButton_clicked()
|
|||||||
if (!oximodule)
|
if (!oximodule)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ui->connectLabel->setText("<h2>"+tr("Select upload option on %1").arg(oximodule->ClassName())+"</h2>");
|
ui->connectLabel->setText("<h2>"+tr("Select upload option on %1").arg(oximodule->loaderName())+"</h2>");
|
||||||
updateStatus(tr("Waiting for you to start the upload process..."));
|
updateStatus(tr("Waiting for you to start the upload process..."));
|
||||||
|
|
||||||
connect(oximodule, SIGNAL(updateProgress(int,int)), this, SLOT(doUpdateProgress(int,int)));
|
connect(oximodule, SIGNAL(updateProgress(int,int)), this, SLOT(doUpdateProgress(int,int)));
|
||||||
@ -226,7 +226,7 @@ void OximeterImport::on_directImportButton_clicked()
|
|||||||
oximodule->abort();
|
oximodule->abort();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ui->connectLabel->setText("<h2>"+tr("%1 device is uploading data...").arg(oximodule->ClassName())+"</h2>");
|
ui->connectLabel->setText("<h2>"+tr("%1 device is uploading data...").arg(oximodule->loaderName())+"</h2>");
|
||||||
updateStatus(tr("Please wait until oximeter upload process completes. Do not unplug your oximeter."));
|
updateStatus(tr("Please wait until oximeter upload process completes. Do not unplug your oximeter."));
|
||||||
|
|
||||||
importMode = IM_RECORDING;
|
importMode = IM_RECORDING;
|
||||||
@ -330,7 +330,8 @@ void OximeterImport::on_liveImportButton_clicked()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Machine *mach = oximodule->CreateMachine();
|
MachineInfo info = oximodule->newInfo();
|
||||||
|
Machine *mach = oximodule->CreateMachine(info);
|
||||||
|
|
||||||
connect(oximodule, SIGNAL(updatePlethy(QByteArray)), this, SLOT(on_updatePlethy(QByteArray)));
|
connect(oximodule, SIGNAL(updatePlethy(QByteArray)), this, SLOT(on_updatePlethy(QByteArray)));
|
||||||
ui->liveConnectLabel->setText(tr("Live Oximetery Mode"));
|
ui->liveConnectLabel->setText(tr("Live Oximetery Mode"));
|
||||||
@ -676,7 +677,8 @@ void OximeterImport::on_saveButton_clicked()
|
|||||||
|
|
||||||
|
|
||||||
// this can move to SerialOximeter class process function...
|
// this can move to SerialOximeter class process function...
|
||||||
Machine * mach = oximodule->CreateMachine();
|
MachineInfo info = oximodule->newInfo();
|
||||||
|
Machine * mach = oximodule->CreateMachine(info);
|
||||||
SessionID sid = ui->dateTimeEdit->dateTime().toUTC().toTime_t();
|
SessionID sid = ui->dateTimeEdit->dateTime().toUTC().toTime_t();
|
||||||
quint64 start = quint64(sid) * 1000L;
|
quint64 start = quint64(sid) * 1000L;
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ PreferencesDialog::PreferencesDialog(QWidget *parent, Profile *_profile) :
|
|||||||
#ifdef LOCK_RESMED_SESSIONS
|
#ifdef LOCK_RESMED_SESSIONS
|
||||||
QList<Machine *> machines = p_profile->GetMachines(MT_CPAP);
|
QList<Machine *> machines = p_profile->GetMachines(MT_CPAP);
|
||||||
for (QList<Machine *>::iterator it = machines.begin(); it != machines.end(); ++it) {
|
for (QList<Machine *>::iterator it = machines.begin(); it != machines.end(); ++it) {
|
||||||
QString mclass=(*it)->GetClass();
|
const QString & mclass=(*it)->loaderName();
|
||||||
if (mclass == STR_MACH_ResMed) {
|
if (mclass == STR_MACH_ResMed) {
|
||||||
ui->combineSlider->setEnabled(false);
|
ui->combineSlider->setEnabled(false);
|
||||||
ui->IgnoreSlider->setEnabled(false);
|
ui->IgnoreSlider->setEnabled(false);
|
||||||
@ -880,7 +880,7 @@ void PreferencesDialog::on_createSDBackups_toggled(bool checked)
|
|||||||
bool haveS9 = false;
|
bool haveS9 = false;
|
||||||
|
|
||||||
for (int i = 0; i < mach.size(); i++) {
|
for (int i = 0; i < mach.size(); i++) {
|
||||||
if (mach[i]->GetClass() == STR_MACH_ResMed) {
|
if (mach[i]->loaderName() == STR_MACH_ResMed) {
|
||||||
haveS9 = true;
|
haveS9 = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -210,12 +210,12 @@ void ProfileSelect::deleteProfile()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Profile *profile = Profiles::profiles[name];
|
Profile * profile = Profiles::profiles[name];
|
||||||
profile->Open();
|
p_profile = profile;
|
||||||
if (!profile) {
|
if (!profile->Open()) {
|
||||||
QMessageBox::warning(this, STR_MessageBox_Error,
|
QMessageBox::warning(this, STR_MessageBox_Error,
|
||||||
QString(tr("Could not open profile.. You will need to delete this profile directory manually")+
|
QString(tr("Could not open profile.. You will need to delete this profile directory manually")+
|
||||||
"\n\n"+tr("You will find it under the following location:")+"\n\n%1").arg(QDir::toNativeSeparators(GetAppRoot() + "/Profiles/" + p_profile->user->userName())), QMessageBox::Ok);
|
"\n\n"+tr("You will find it under the following location:")+"\n\n%1").arg(QDir::toNativeSeparators(GetAppRoot() + "/Profiles/" + profile->user->userName())), QMessageBox::Ok);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bool reallydelete = false;
|
bool reallydelete = false;
|
||||||
@ -267,6 +267,8 @@ void ProfileSelect::deleteProfile()
|
|||||||
}
|
}
|
||||||
|
|
||||||
model->removeRow(ui->listView->currentIndex().row());
|
model->removeRow(ui->listView->currentIndex().row());
|
||||||
|
delete p_profile;
|
||||||
|
p_profile = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -334,6 +336,7 @@ void ProfileSelect::on_listView_activated(const QModelIndex &index)
|
|||||||
profile->removeLock();
|
profile->removeLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p_profile = profile;
|
||||||
profile->Open();
|
profile->Open();
|
||||||
// Do this in case user renames the directory (otherwise it won't load)
|
// Do this in case user renames the directory (otherwise it won't load)
|
||||||
// Essentially makes the folder name the user name, but whatever..
|
// Essentially makes the folder name the user name, but whatever..
|
||||||
|
@ -185,12 +185,12 @@ void Report::PrintReport(gGraphView *gv, QString name, QDate date)
|
|||||||
QString submodel;
|
QString submodel;
|
||||||
cpapinfo += STR_TR_Machine + ": ";
|
cpapinfo += STR_TR_Machine + ": ";
|
||||||
|
|
||||||
if (cpap->machine->properties.find(STR_PROP_SubModel) != cpap->machine->properties.end()) {
|
// if (cpap->machine->properties.find(STR_PROP_SubModel) != cpap->machine->properties.end()) {
|
||||||
submodel = "\n" + cpap->machine->properties[STR_PROP_SubModel];
|
// submodel = "\n" + cpap->machine->info.modeproperties[STR_PROP_SubModel];
|
||||||
}
|
// }
|
||||||
|
|
||||||
cpapinfo += cpap->machine->properties[STR_PROP_Brand] + " " +
|
cpapinfo += cpap->machine->brand() + " " +
|
||||||
cpap->machine->properties[STR_PROP_Model] + submodel;
|
cpap->machine->model() + submodel;
|
||||||
CPAPMode mode = (CPAPMode)(int)cpap->settings_max(CPAP_Mode);
|
CPAPMode mode = (CPAPMode)(int)cpap->settings_max(CPAP_Mode);
|
||||||
cpapinfo += "\n" + STR_TR_Mode + ": ";
|
cpapinfo += "\n" + STR_TR_Mode + ": ";
|
||||||
|
|
||||||
@ -306,13 +306,13 @@ void Report::PrintReport(gGraphView *gv, QString name, QDate date)
|
|||||||
stats = QObject::tr("AI=%1 HI=%2 CAI=%3 ").arg(oai, 0, 'f', 2).arg(hi, 0, 'f', 2).arg(cai, 0, 'f',
|
stats = QObject::tr("AI=%1 HI=%2 CAI=%3 ").arg(oai, 0, 'f', 2).arg(hi, 0, 'f', 2).arg(cai, 0, 'f',
|
||||||
2);
|
2);
|
||||||
|
|
||||||
if (cpap->machine->GetClass() == STR_MACH_PRS1) {
|
if (cpap->machine->loaderName() == STR_MACH_PRS1) {
|
||||||
stats += QObject::tr("REI=%1 VSI=%2 FLI=%3 PB/CSR=%4%%")
|
stats += QObject::tr("REI=%1 VSI=%2 FLI=%3 PB/CSR=%4%%")
|
||||||
.arg(rei, 0, 'f', 2).arg(vsi, 0, 'f', 2)
|
.arg(rei, 0, 'f', 2).arg(vsi, 0, 'f', 2)
|
||||||
.arg(fli, 0, 'f', 2).arg(csr, 0, 'f', 2);
|
.arg(fli, 0, 'f', 2).arg(csr, 0, 'f', 2);
|
||||||
} else if (cpap->machine->GetClass() == STR_MACH_ResMed) {
|
} else if (cpap->machine->loaderName() == STR_MACH_ResMed) {
|
||||||
stats += QObject::tr("UAI=%1 ").arg(uai, 0, 'f', 2);
|
stats += QObject::tr("UAI=%1 ").arg(uai, 0, 'f', 2);
|
||||||
} else if (cpap->machine->GetClass() == STR_MACH_Intellipap) {
|
} else if (cpap->machine->loaderName() == STR_MACH_Intellipap) {
|
||||||
stats += QObject::tr("NRI=%1 LKI=%2 EPI=%3").arg(nri, 0, 'f', 2).arg(lki, 0, 'f', 2).arg(exp, 0,
|
stats += QObject::tr("NRI=%1 LKI=%2 EPI=%3").arg(nri, 0, 'f', 2).arg(lki, 0, 'f', 2).arg(exp, 0,
|
||||||
'f', 2);
|
'f', 2);
|
||||||
}
|
}
|
||||||
|
@ -1116,16 +1116,16 @@ QString Statistics::GenerateHTML()
|
|||||||
|
|
||||||
QString machstr;
|
QString machstr;
|
||||||
|
|
||||||
if (rx.machine->properties.contains(STR_PROP_Brand)) {
|
if (!rx.machine->brand().isEmpty()) {
|
||||||
machstr += rx.machine->properties[STR_PROP_Brand];
|
machstr += rx.machine->brand();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rx.machine->properties.contains(STR_PROP_Model)) {
|
if (!rx.machine->model().isEmpty()) {
|
||||||
machstr += " " + rx.machine->properties[STR_PROP_Model];
|
machstr += " " + rx.machine->model();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rx.machine->properties.contains(STR_PROP_Serial)) {
|
if (!rx.machine->serial().isEmpty()) {
|
||||||
machstr += " (" + rx.machine->properties[STR_PROP_Serial] + ")<br/>";
|
machstr += " (" + rx.machine->serial() + ")<br/>";
|
||||||
}
|
}
|
||||||
|
|
||||||
mode = rx.mode;
|
mode = rx.mode;
|
||||||
@ -1197,7 +1197,7 @@ QString Statistics::GenerateHTML()
|
|||||||
if (p_profile->hasChannel(CPAP_SensAwake)) {
|
if (p_profile->hasChannel(CPAP_SensAwake)) {
|
||||||
html += QString("<td>%1</td>").arg(calcSA(rx.first, rx.last), 0, 'f', decimals);
|
html += QString("<td>%1</td>").arg(calcSA(rx.first, rx.last), 0, 'f', decimals);
|
||||||
}
|
}
|
||||||
html += QString("<td>%1</td>").arg(rx.machine->GetClass());
|
html += QString("<td>%1</td>").arg(rx.machine->loaderName());
|
||||||
html += QString("<td>%1</td>").arg(presrel);
|
html += QString("<td>%1</td>").arg(presrel);
|
||||||
html += QString("<td>%1</td>").arg(schema::channel[CPAP_Mode].option(int(rx.mode) - 1));
|
html += QString("<td>%1</td>").arg(schema::channel[CPAP_Mode].option(int(rx.mode) - 1));
|
||||||
html += QString("<td>%1</td>").arg(extratxt);
|
html += QString("<td>%1</td>").arg(extratxt);
|
||||||
@ -1231,14 +1231,14 @@ QString Statistics::GenerateHTML()
|
|||||||
for (int i = 0; i < mach.size(); i++) {
|
for (int i = 0; i < mach.size(); i++) {
|
||||||
m = mach.at(i);
|
m = mach.at(i);
|
||||||
|
|
||||||
if (m->GetType() == MT_JOURNAL) { continue; }
|
if (m->type() == MT_JOURNAL) { continue; }
|
||||||
|
|
||||||
QString mn = m->properties[STR_PROP_ModelNumber];
|
QString mn = m->modelnumber();
|
||||||
html += QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td></tr>")
|
html += QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td></tr>")
|
||||||
.arg(m->properties[STR_PROP_Brand])
|
.arg(m->brand())
|
||||||
.arg(m->properties[STR_PROP_Model] + " " + m->properties[STR_PROP_SubModel] +
|
.arg(m->model() +
|
||||||
(mn.isEmpty() ? "" : QString(" (") + mn + QString(")")))
|
(mn.isEmpty() ? "" : QString(" (") + mn + QString(")")))
|
||||||
.arg(m->properties[STR_PROP_Serial])
|
.arg(m->serial())
|
||||||
.arg(m->FirstDay().toString(Qt::SystemLocaleShortDate))
|
.arg(m->FirstDay().toString(Qt::SystemLocaleShortDate))
|
||||||
.arg(m->LastDay().toString(Qt::SystemLocaleShortDate));
|
.arg(m->LastDay().toString(Qt::SystemLocaleShortDate));
|
||||||
}
|
}
|
||||||
|
@ -130,15 +130,15 @@ QString GenerateWelcomeHTML()
|
|||||||
QDate date = p_profile->LastDay(MT_CPAP);
|
QDate date = p_profile->LastDay(MT_CPAP);
|
||||||
Day *day = p_profile->GetDay(date, MT_CPAP);
|
Day *day = p_profile->GetDay(date, MT_CPAP);
|
||||||
if (day) {
|
if (day) {
|
||||||
if (day->machine->GetClass() == STR_MACH_ResMed) cpapimage = "qrc:/icons/rms9.png";
|
if (day->machine->loaderName() == STR_MACH_ResMed) cpapimage = "qrc:/icons/rms9.png";
|
||||||
else if (day->machine->GetClass() == STR_MACH_PRS1) cpapimage = "qrc:/icons/prs1.png";
|
else if (day->machine->loaderName() == STR_MACH_PRS1) cpapimage = "qrc:/icons/prs1.png";
|
||||||
else if (day->machine->GetClass() == STR_MACH_Intellipap) cpapimage = "qrc:/icons/intellipap.png";
|
else if (day->machine->loaderName() == STR_MACH_Intellipap) cpapimage = "qrc:/icons/intellipap.png";
|
||||||
}
|
}
|
||||||
html += "<table cellpadding=4><tr><td><img src='"+cpapimage+"' width=160px><br/>";
|
html += "<table cellpadding=4><tr><td><img src='"+cpapimage+"' width=160px><br/>";
|
||||||
|
|
||||||
html+="</td><td align=center><table cellpadding=4 class=curved2 title=\""+QObject::tr("Click this box to see this in daily view.")+"\"><tr>"+
|
html+="</td><td align=center><table cellpadding=4 class=curved2 title=\""+QObject::tr("Click this box to see this in daily view.")+"\"><tr>"+
|
||||||
QString("<td align=center onmouseover='ChangeColor(this, \"#efefa0\");' onmouseout='ChangeColor(this, \"#ffffc0\");' onclick='alert(\"daily=%1\");'>").arg(date.toString(Qt::ISODate))+"<b>"+
|
QString("<td align=center onmouseover='ChangeColor(this, \"#efefa0\");' onmouseout='ChangeColor(this, \"#ffffc0\");' onclick='alert(\"daily=%1\");'>").arg(date.toString(Qt::ISODate))+"<b>"+
|
||||||
QObject::tr("The last time you used your %1...").arg(day->machine->properties[STR_PROP_Brand]+" "+day->machine->properties[STR_PROP_Model])+"</b><br/>";
|
QObject::tr("The last time you used your %1...").arg(day->machine->brand()+" "+day->machine->model())+"</b><br/>";
|
||||||
|
|
||||||
int daysto = date.daysTo(QDate::currentDate());
|
int daysto = date.daysTo(QDate::currentDate());
|
||||||
QString daystring;
|
QString daystring;
|
||||||
@ -199,10 +199,18 @@ QString GenerateWelcomeHTML()
|
|||||||
EventDataType ipap = day->percentile(CPAP_IPAP, perc/100.0);
|
EventDataType ipap = day->percentile(CPAP_IPAP, perc/100.0);
|
||||||
EventDataType epap = day->percentile(CPAP_EPAP, perc/100.0);
|
EventDataType epap = day->percentile(CPAP_EPAP, perc/100.0);
|
||||||
html += QObject::tr("Your machine was under %1-%2 %3 for %4% of the time.").arg(epap).arg(ipap).arg(schema::channel[CPAP_Pressure].units()).arg(perc);
|
html += QObject::tr("Your machine was under %1-%2 %3 for %4% of the time.").arg(epap).arg(ipap).arg(schema::channel[CPAP_Pressure].units()).arg(perc);
|
||||||
} else {
|
} else if (cpapmode == MODE_ASV){
|
||||||
EventDataType pressure = day->percentile(CPAP_Pressure, perc/100.0);
|
EventDataType ipap = day->percentile(CPAP_IPAP, perc/100.0);
|
||||||
html += QObject::tr("Your EPAP pressure was under %1%2 for %3% of the time.").arg(pressure).arg(schema::channel[CPAP_EPAP].units()).arg(perc);
|
EventDataType epap = qRound(day->settings_wavg(CPAP_EPAP));
|
||||||
html += QObject::tr("Your IPAP pressure was under %1%2 for %3% of the time.").arg(pressure).arg(schema::channel[CPAP_EPAP].units()).arg(perc);
|
|
||||||
|
html += QObject::tr("Your EPAP pressure fixed at %1%2.").arg(epap).arg(schema::channel[CPAP_EPAP].units())+"<br/>";
|
||||||
|
html += QObject::tr("Your IPAP pressure was under %1%2 for %3% of the time.").arg(ipap).arg(schema::channel[CPAP_IPAP].units()).arg(perc);
|
||||||
|
} else if (cpapmode == MODE_ASV_VARIABLE_EPAP){
|
||||||
|
EventDataType ipap = day->percentile(CPAP_IPAP, perc/100.0);
|
||||||
|
EventDataType epap = day->percentile(CPAP_EPAP, perc/100.0);
|
||||||
|
|
||||||
|
html += QObject::tr("Your EPAP pressure was under %1%2 for %3% of the time.").arg(epap).arg(schema::channel[CPAP_EPAP].units()).arg(perc)+"<br/>";
|
||||||
|
html += QObject::tr("Your IPAP pressure was under %1%2 for %3% of the time.").arg(ipap).arg(schema::channel[CPAP_IPAP].units()).arg(perc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user