mirror of
https://gitlab.com/pholy/OSCAR-code.git
synced 2025-04-07 11:40:42 +00:00
Code cleanup, path separator fix, moved printing and summary to seperate modules
This commit is contained in:
parent
387e250c6f
commit
439a7744c6
@ -3811,7 +3811,7 @@ const quint16 gvversion=0;
|
|||||||
|
|
||||||
void gGraphView::SaveSettings(QString title)
|
void gGraphView::SaveSettings(QString title)
|
||||||
{
|
{
|
||||||
QString filename=PROFILE.Get("{DataFolder}")+QDir::separator()+title.toLower()+".shg";
|
QString filename=PROFILE.Get("{DataFolder}/")+title.toLower()+".shg";
|
||||||
QFile f(filename);
|
QFile f(filename);
|
||||||
f.open(QFile::WriteOnly);
|
f.open(QFile::WriteOnly);
|
||||||
QDataStream out(&f);
|
QDataStream out(&f);
|
||||||
@ -3835,7 +3835,7 @@ void gGraphView::SaveSettings(QString title)
|
|||||||
|
|
||||||
bool gGraphView::LoadSettings(QString title)
|
bool gGraphView::LoadSettings(QString title)
|
||||||
{
|
{
|
||||||
QString filename=PROFILE.Get("{DataFolder}")+QDir::separator()+title.toLower()+".shg";
|
QString filename=PROFILE.Get("{DataFolder}/")+title.toLower()+".shg";
|
||||||
QFile f(filename);
|
QFile f(filename);
|
||||||
if (!f.exists()) return false;
|
if (!f.exists()) return false;
|
||||||
|
|
||||||
|
@ -44,14 +44,16 @@ int FPIconLoader::Open(QString & path,Profile *profile)
|
|||||||
{
|
{
|
||||||
QString newpath;
|
QString newpath;
|
||||||
|
|
||||||
|
path=path.replace("\\","/");
|
||||||
|
|
||||||
if (path.endsWith("/"))
|
if (path.endsWith("/"))
|
||||||
path.chop(1);
|
path.chop(1);
|
||||||
|
|
||||||
QString dirtag="FPHCARE";
|
QString dirtag="FPHCARE";
|
||||||
if (path.endsWith(QDir::separator()+dirtag)) {
|
if (path.endsWith("/"+dirtag)) {
|
||||||
newpath=path;
|
newpath=path;
|
||||||
} else {
|
} else {
|
||||||
newpath=path+QDir::separator()+dirtag;
|
newpath=path+"/"+dirtag;
|
||||||
}
|
}
|
||||||
|
|
||||||
newpath+="/ICON/";
|
newpath+="/ICON/";
|
||||||
|
@ -44,12 +44,14 @@ int IntellipapLoader::Open(QString & path,Profile *profile)
|
|||||||
// Check for DV5MFirm.bin?
|
// Check for DV5MFirm.bin?
|
||||||
QString newpath;
|
QString newpath;
|
||||||
|
|
||||||
|
path=path.replace("\\","/");
|
||||||
|
|
||||||
QString dirtag="SL";
|
QString dirtag="SL";
|
||||||
if (path.endsWith(QDir::separator()+dirtag)) {
|
if (path.endsWith("/"+dirtag)) {
|
||||||
return 0;
|
return 0;
|
||||||
//newpath=path;
|
//newpath=path;
|
||||||
} else {
|
} else {
|
||||||
newpath=path+QDir::separator()+dirtag;
|
newpath=path+"/"+dirtag;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString filename;
|
QString filename;
|
||||||
@ -57,7 +59,7 @@ int IntellipapLoader::Open(QString & path,Profile *profile)
|
|||||||
//////////////////////////
|
//////////////////////////
|
||||||
// Parse the Settings File
|
// Parse the Settings File
|
||||||
//////////////////////////
|
//////////////////////////
|
||||||
filename=newpath+QDir::separator()+"SET1";
|
filename=newpath+"/SET1";
|
||||||
QFile f(filename);
|
QFile f(filename);
|
||||||
if (!f.exists()) return 0;
|
if (!f.exists()) return 0;
|
||||||
f.open(QFile::ReadOnly);
|
f.open(QFile::ReadOnly);
|
||||||
@ -141,7 +143,7 @@ int IntellipapLoader::Open(QString & path,Profile *profile)
|
|||||||
// Parse the Session Index
|
// Parse the Session Index
|
||||||
//////////////////////////
|
//////////////////////////
|
||||||
unsigned char buf[27];
|
unsigned char buf[27];
|
||||||
filename=newpath+QDir::separator()+"U";
|
filename=newpath+"/U";
|
||||||
f.setFileName(filename);
|
f.setFileName(filename);
|
||||||
if (!f.exists()) return 0;
|
if (!f.exists()) return 0;
|
||||||
|
|
||||||
@ -171,7 +173,7 @@ int IntellipapLoader::Open(QString & path,Profile *profile)
|
|||||||
//////////////////////////
|
//////////////////////////
|
||||||
// Parse the Session Data
|
// Parse the Session Data
|
||||||
//////////////////////////
|
//////////////////////////
|
||||||
filename=newpath+QDir::separator()+"L";
|
filename=newpath+"/L";
|
||||||
f.setFileName(filename);
|
f.setFileName(filename);
|
||||||
if (!f.exists()) return 0;
|
if (!f.exists()) return 0;
|
||||||
|
|
||||||
|
@ -165,15 +165,20 @@ bool isdigit(QChar c)
|
|||||||
if ((c>='0') && (c<='9')) return true;
|
if ((c>='0') && (c<='9')) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QString PR_STR_PSeries="P-Series";
|
||||||
|
|
||||||
int PRS1Loader::Open(QString & path,Profile *profile)
|
int PRS1Loader::Open(QString & path,Profile *profile)
|
||||||
{
|
{
|
||||||
QString newpath,pseries="P-Series";
|
QString newpath;
|
||||||
qDebug() << "PRS1Loader::Open path=" << newpath;
|
path=path.replace("\\","/");
|
||||||
if (path.endsWith(QDir::separator()+pseries)) {
|
|
||||||
|
if (path.endsWith("/"+PR_STR_PSeries)) {
|
||||||
newpath=path;
|
newpath=path;
|
||||||
} else {
|
} else {
|
||||||
newpath=path+QDir::separator()+pseries;
|
newpath=path+"/"+PR_STR_PSeries;
|
||||||
}
|
}
|
||||||
|
qDebug() << "PRS1Loader::Open path=" << newpath;
|
||||||
|
|
||||||
QDir dir(newpath);
|
QDir dir(newpath);
|
||||||
|
|
||||||
@ -218,11 +223,12 @@ int PRS1Loader::Open(QString & path,Profile *profile)
|
|||||||
QString s=*sn;
|
QString s=*sn;
|
||||||
m=CreateMachine(s,profile);
|
m=CreateMachine(s,profile);
|
||||||
try {
|
try {
|
||||||
if (m) OpenMachine(m,newpath+QDir::separator()+(*sn),profile);
|
if (m)
|
||||||
|
OpenMachine(m,newpath+"/"+(*sn),profile);
|
||||||
} catch(OneTypePerDay e) {
|
} catch(OneTypePerDay e) {
|
||||||
profile->DelMachine(m);
|
profile->DelMachine(m);
|
||||||
PRS1List.erase(PRS1List.find(s));
|
PRS1List.erase(PRS1List.find(s));
|
||||||
QMessageBox::warning(NULL,"Import Error","This Machine Record cannot be imported in this profile.\nThe Day records overlap with already existing content.",QMessageBox::Ok);
|
QMessageBox::warning(NULL,QObject::tr("Import Error"),QObject::tr("This Machine Record cannot be imported in this profile.\nThe Day records overlap with already existing content."),QMessageBox::Ok);
|
||||||
delete m;
|
delete m;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -297,7 +303,8 @@ int PRS1Loader::OpenMachine(Machine *m,QString path,Profile *profile)
|
|||||||
} else if (filename.toLower()=="properties.txt") {
|
} else if (filename.toLower()=="properties.txt") {
|
||||||
ParseProperties(m,fi.canonicalFilePath());
|
ParseProperties(m,fi.canonicalFilePath());
|
||||||
} else if (filename.toLower()=="e") {
|
} else if (filename.toLower()=="e") {
|
||||||
// don't really give a crap about .004 files yet.
|
// Error files..
|
||||||
|
// Reminder: I have been given some info about these. should check it over.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1298,14 +1305,14 @@ bool PRS1Loader::OpenFile(Machine *mach, QString filename)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
qDebug() << "Loading" << filename << sequence << timestamp << size;
|
qDebug() << "Loading" << QDir::toNativeSeparators(filename) << sequence << timestamp << size;
|
||||||
//if (ext==0) ParseCompliance(data,size);
|
//if (ext==0) ParseCompliance(data,size);
|
||||||
if (ext<=1) {
|
if (ext<=1) {
|
||||||
ParseSummary(mach,sequence,timestamp,data,datasize,family,familyVersion);
|
ParseSummary(mach,sequence,timestamp,data,datasize,family,familyVersion);
|
||||||
} else if (ext==2) {
|
} else if (ext==2) {
|
||||||
if (family==5) {
|
if (family==5) {
|
||||||
if (!Parse002v5(sequence,timestamp,data,datasize)) {
|
if (!Parse002v5(sequence,timestamp,data,datasize)) {
|
||||||
qDebug() << "in file: " << filename;
|
qDebug() << "in file: " << QDir::toNativeSeparators(filename);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Parse002(sequence,timestamp,data,datasize, family, familyVersion);
|
Parse002(sequence,timestamp,data,datasize, family, familyVersion);
|
||||||
|
@ -31,20 +31,32 @@ extern QProgressBar *qprogress;
|
|||||||
QHash<int,QString> RMS9ModelMap;
|
QHash<int,QString> RMS9ModelMap;
|
||||||
QHash<ChannelID, QVector<QString> > resmed_codes;
|
QHash<ChannelID, QVector<QString> > resmed_codes;
|
||||||
|
|
||||||
|
const QString STR_ext_TGT="tgt";
|
||||||
|
const QString STR_ext_CRC="crc";
|
||||||
|
const QString STR_ext_EDF="edf";
|
||||||
|
const QString STR_ext_gz=".gz";
|
||||||
|
|
||||||
|
|
||||||
// Looks up foreign language Signal names that match this channelID
|
// Looks up foreign language Signal names that match this channelID
|
||||||
EDFSignal * EDFParser::lookupSignal(ChannelID ch)
|
EDFSignal * EDFParser::lookupSignal(ChannelID ch)
|
||||||
{
|
{
|
||||||
QHash<ChannelID, QVector<QString> >::iterator ci;
|
QHash<ChannelID, QVector<QString> >::iterator ci;
|
||||||
QHash<QString,EDFSignal *>::iterator jj;
|
QHash<QString,EDFSignal *>::iterator jj;
|
||||||
ci=resmed_codes.find(ch);
|
ci=resmed_codes.find(ch);
|
||||||
if (ci==resmed_codes.end()) return NULL;
|
|
||||||
|
if (ci==resmed_codes.end())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
for (int i=0;i<ci.value().size();i++) {
|
for (int i=0;i<ci.value().size();i++) {
|
||||||
jj=lookup.find(ci.value()[i]);
|
jj=lookup.find(ci.value()[i]);
|
||||||
if (jj==lookup.end()) continue;
|
if (jj==lookup.end())
|
||||||
|
continue;
|
||||||
return jj.value();
|
return jj.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
EDFSignal * EDFParser::lookupName(QString name)
|
EDFSignal * EDFParser::lookupName(QString name)
|
||||||
{
|
{
|
||||||
QHash<QString,EDFSignal *>::iterator i=lookup.find(name);
|
QHash<QString,EDFSignal *>::iterator i=lookup.find(name);
|
||||||
@ -52,8 +64,6 @@ EDFSignal * EDFParser::lookupName(QString name)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
EDFParser::EDFParser(QString name)
|
EDFParser::EDFParser(QString name)
|
||||||
{
|
{
|
||||||
buffer=NULL;
|
buffer=NULL;
|
||||||
@ -114,6 +124,7 @@ bool EDFParser::Parse()
|
|||||||
}
|
}
|
||||||
QDateTime startDate=QDateTime::fromString(QString::fromLatin1(header.datetime,16),"dd.MM.yyHH.mm.ss");
|
QDateTime startDate=QDateTime::fromString(QString::fromLatin1(header.datetime,16),"dd.MM.yyHH.mm.ss");
|
||||||
//startDate.toTimeSpec(Qt::UTC);
|
//startDate.toTimeSpec(Qt::UTC);
|
||||||
|
|
||||||
QDate d2=startDate.date();
|
QDate d2=startDate.date();
|
||||||
if (d2.year()<2000) {
|
if (d2.year()<2000) {
|
||||||
d2.setDate(d2.year()+100,d2.month(),d2.day());
|
d2.setDate(d2.year()+100,d2.month(),d2.day());
|
||||||
@ -207,7 +218,7 @@ bool EDFParser::Open(QString name)
|
|||||||
|
|
||||||
//Urk.. This needs fixing for VC++, as it doesn't have packed attribute type..
|
//Urk.. This needs fixing for VC++, as it doesn't have packed attribute type..
|
||||||
|
|
||||||
if (name.endsWith(".gz")) {
|
if (name.endsWith(STR_ext_gz)) {
|
||||||
filename=name.mid(0,-3);
|
filename=name.mid(0,-3);
|
||||||
QFile fi(name);
|
QFile fi(name);
|
||||||
fi.open(QFile::ReadOnly);
|
fi.open(QFile::ReadOnly);
|
||||||
@ -285,21 +296,17 @@ Machine *ResmedLoader::CreateMachine(QString serial,Profile *profile)
|
|||||||
m->properties[STR_PROP_BackupPath]=path+"Backup/";
|
m->properties[STR_PROP_BackupPath]=path+"Backup/";
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
long event_cnt=0;
|
long event_cnt=0;
|
||||||
|
|
||||||
|
const QString RMS9_STR_datalog="DATALOG";
|
||||||
|
const QString RMS9_STR_idfile="Identification.";
|
||||||
|
const QString RMS9_STR_strfile="STR.";
|
||||||
|
|
||||||
|
|
||||||
int ResmedLoader::Open(QString & path,Profile *profile)
|
int ResmedLoader::Open(QString & path,Profile *profile)
|
||||||
{
|
{
|
||||||
const QString datalog="DATALOG";
|
|
||||||
const QString idfile="Identification.";
|
|
||||||
const QString strfile="STR.";
|
|
||||||
|
|
||||||
const QString ext_TGT="tgt";
|
|
||||||
const QString ext_CRC="crc";
|
|
||||||
const QString ext_EDF="edf";
|
|
||||||
const QString ext_gz=".gz";
|
|
||||||
|
|
||||||
QString serial; // Serial number
|
QString serial; // Serial number
|
||||||
QString key,value;
|
QString key,value;
|
||||||
@ -309,16 +316,18 @@ int ResmedLoader::Open(QString & path,Profile *profile)
|
|||||||
|
|
||||||
QHash<QString,QString> idmap; // Temporary properties hash
|
QHash<QString,QString> idmap; // Temporary properties hash
|
||||||
|
|
||||||
|
path=path.replace("\\","/");
|
||||||
|
|
||||||
// Strip off end "/" if any
|
// Strip off end "/" if any
|
||||||
if (path.endsWith("/"))
|
if (path.endsWith("/"))
|
||||||
path=path.section("/",0,-2);
|
path=path.section("/",0,-2);
|
||||||
|
|
||||||
// Strip off DATALOG from path, and set newpath to the path contianing DATALOG
|
// Strip off DATALOG from path, and set newpath to the path contianing DATALOG
|
||||||
if (path.endsWith(datalog)) {
|
if (path.endsWith(RMS9_STR_datalog)) {
|
||||||
newpath=path+"/";
|
newpath=path+"/";
|
||||||
path=path.section("/",0,-2);
|
path=path.section("/",0,-2);
|
||||||
} else {
|
} else {
|
||||||
newpath=path+"/"+datalog+"/";
|
newpath=path+"/"+RMS9_STR_datalog+"/";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add separator back
|
// Add separator back
|
||||||
@ -331,7 +340,7 @@ int ResmedLoader::Open(QString & path,Profile *profile)
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
// Parse Identification.tgt file (containing serial number and machine information)
|
// Parse Identification.tgt file (containing serial number and machine information)
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
filename=path+idfile+ext_TGT;
|
filename=path+RMS9_STR_idfile+STR_ext_TGT;
|
||||||
QFile f(filename);
|
QFile f(filename);
|
||||||
// Abort if this file is dodgy..
|
// Abort if this file is dodgy..
|
||||||
if (!f.exists() || !f.open(QIODevice::ReadOnly))
|
if (!f.exists() || !f.open(QIODevice::ReadOnly))
|
||||||
@ -360,10 +369,10 @@ int ResmedLoader::Open(QString & path,Profile *profile)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Early check for STR.edf file, so we can early exit before creating faulty machine record.
|
// Early check for STR.edf file, so we can early exit before creating faulty machine record.
|
||||||
QString strpath=path+strfile+ext_EDF; // STR.edf file
|
QString strpath=path+RMS9_STR_strfile+STR_ext_EDF; // STR.edf file
|
||||||
f.setFileName(strpath);
|
f.setFileName(strpath);
|
||||||
if (!f.exists()) { // No STR.edf.. Do we have a STR.edf.gz?
|
if (!f.exists()) { // No STR.edf.. Do we have a STR.edf.gz?
|
||||||
strpath+=ext_gz;
|
strpath+=STR_ext_gz;
|
||||||
f.setFileName(strpath);
|
f.setFileName(strpath);
|
||||||
if (!f.exists()) {
|
if (!f.exists()) {
|
||||||
qDebug() << "Missing STR.edf file";
|
qDebug() << "Missing STR.edf file";
|
||||||
@ -405,7 +414,7 @@ int ResmedLoader::Open(QString & path,Profile *profile)
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
EDFParser stredf(strpath);
|
EDFParser stredf(strpath);
|
||||||
if (!stredf.Parse()) {
|
if (!stredf.Parse()) {
|
||||||
qDebug() << "Faulty file" << strfile;
|
qDebug() << "Faulty file" << RMS9_STR_strfile;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (stredf.serialnumber!=serial) {
|
if (stredf.serialnumber!=serial) {
|
||||||
@ -423,20 +432,20 @@ int ResmedLoader::Open(QString & path,Profile *profile)
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
if (create_backups) {
|
if (create_backups) {
|
||||||
if (!dir.exists(backup_path)) {
|
if (!dir.exists(backup_path)) {
|
||||||
if (!dir.mkpath(backup_path+datalog)) {
|
if (!dir.mkpath(backup_path+RMS9_STR_datalog)) {
|
||||||
qDebug() << "Could not create S9 backup directory :-/";
|
qDebug() << "Could not create S9 backup directory :-/";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy Identification files to backup folder
|
// Copy Identification files to backup folder
|
||||||
QFile::copy(path+idfile+ext_TGT,backup_path+idfile+ext_TGT);
|
QFile::copy(path+RMS9_STR_idfile+STR_ext_TGT,backup_path+RMS9_STR_idfile+STR_ext_TGT);
|
||||||
QFile::copy(path+idfile+ext_CRC,backup_path+idfile+ext_CRC);
|
QFile::copy(path+RMS9_STR_idfile+STR_ext_CRC,backup_path+RMS9_STR_idfile+STR_ext_CRC);
|
||||||
|
|
||||||
//copy STR files to backup folder
|
//copy STR files to backup folder
|
||||||
if (strpath.endsWith(ext_gz)) // Already compressed.
|
if (strpath.endsWith(STR_ext_gz)) // Already compressed.
|
||||||
QFile::copy(strpath,backup_path+strfile+ext_EDF+ext_gz);
|
QFile::copy(strpath,backup_path+RMS9_STR_strfile+STR_ext_EDF+STR_ext_gz);
|
||||||
else { // Compress STR file to backup folder
|
else { // Compress STR file to backup folder
|
||||||
QString strf=backup_path+strfile+ext_EDF;
|
QString strf=backup_path+RMS9_STR_strfile+STR_ext_EDF;
|
||||||
if (QFile::exists(strf))
|
if (QFile::exists(strf))
|
||||||
QFile::remove(strf);
|
QFile::remove(strf);
|
||||||
|
|
||||||
@ -557,9 +566,9 @@ int ResmedLoader::Open(QString & path,Profile *profile)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Accept only .edf and .edf.gz files
|
// Accept only .edf and .edf.gz files
|
||||||
if (filename.right(4).toLower() != "."+ext_EDF) {
|
if (filename.right(4).toLower() != "."+STR_ext_EDF) {
|
||||||
|
|
||||||
if (filename.right(7).toLower() != "."+ext_EDF+ext_gz)
|
if (filename.right(7).toLower() != "."+STR_ext_EDF+STR_ext_gz)
|
||||||
continue;
|
continue;
|
||||||
gz=true;
|
gz=true;
|
||||||
} else gz=false;
|
} else gz=false;
|
||||||
@ -604,7 +613,7 @@ int ResmedLoader::Open(QString & path,Profile *profile)
|
|||||||
if (si!=sessfiles.end()) {
|
if (si!=sessfiles.end()) {
|
||||||
// Ignore if already compressed version of the same file exists.. (just in case)
|
// Ignore if already compressed version of the same file exists.. (just in case)
|
||||||
if (!gz) {
|
if (!gz) {
|
||||||
if (si.value().contains(filename+ext_gz,Qt::CaseInsensitive))
|
if (si.value().contains(filename+STR_ext_gz,Qt::CaseInsensitive))
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
QString str=filename;
|
QString str=filename;
|
||||||
@ -1046,7 +1055,7 @@ int ResmedLoader::Open(QString & path,Profile *profile)
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// }
|
// }
|
||||||
backup_path+=datalog+"/";
|
backup_path+=RMS9_STR_datalog+"/";
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
// Scan through new file list and import sessions
|
// Scan through new file list and import sessions
|
||||||
@ -1065,14 +1074,14 @@ int ResmedLoader::Open(QString & path,Profile *profile)
|
|||||||
// Process EDF File List
|
// Process EDF File List
|
||||||
for (int i=0;i<si.value().size();++i) {
|
for (int i=0;i<si.value().size();++i) {
|
||||||
filename=si.value()[i];
|
filename=si.value()[i];
|
||||||
gz=(filename.right(3).toLower()==ext_gz);
|
gz=(filename.right(3).toLower()==STR_ext_gz);
|
||||||
fullpath=newpath+filename;
|
fullpath=newpath+filename;
|
||||||
|
|
||||||
// Copy the EDF file to the backup folder
|
// Copy the EDF file to the backup folder
|
||||||
if (create_backups) {
|
if (create_backups) {
|
||||||
backupfile=backup_path+filename;
|
backupfile=backup_path+filename;
|
||||||
bool dobackup=true;
|
bool dobackup=true;
|
||||||
if (!gz && QFile::exists(backupfile+".gz")) {
|
if (!gz && QFile::exists(backupfile+STR_ext_gz)) {
|
||||||
dobackup=false;
|
dobackup=false;
|
||||||
} else if (QFile::exists(backupfile)) {
|
} else if (QFile::exists(backupfile)) {
|
||||||
if (gz) {
|
if (gz) {
|
||||||
@ -1650,8 +1659,6 @@ bool ResmedLoader::LoadPLD(Session *sess,EDFParser &edf)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResInitModelMap()
|
|
||||||
{
|
|
||||||
const QString RMS9_STR_Escape="S9 Escape";
|
const QString RMS9_STR_Escape="S9 Escape";
|
||||||
const QString RMS9_STR_EscapeAuto="S9 Escape Auto";
|
const QString RMS9_STR_EscapeAuto="S9 Escape Auto";
|
||||||
const QString RMS9_STR_Elite="S9 Elite";
|
const QString RMS9_STR_Elite="S9 Elite";
|
||||||
@ -1666,6 +1673,8 @@ void ResInitModelMap()
|
|||||||
const QString RMS9_STR_VPAP_STA="S9 VPAP ST-A";
|
const QString RMS9_STR_VPAP_STA="S9 VPAP ST-A";
|
||||||
const QString RMS9_STR_VPAP_ST22="S9 VPAP ST 22";
|
const QString RMS9_STR_VPAP_ST22="S9 VPAP ST 22";
|
||||||
|
|
||||||
|
void ResInitModelMap()
|
||||||
|
{
|
||||||
// Escape Series
|
// Escape Series
|
||||||
RMS9ModelMap[36001]=RMS9ModelMap[36011]=RMS9ModelMap[36021]=RMS9ModelMap[36141]=
|
RMS9ModelMap[36001]=RMS9ModelMap[36011]=RMS9ModelMap[36021]=RMS9ModelMap[36141]=
|
||||||
RMS9ModelMap[36201]=RMS9ModelMap[36221]=RMS9ModelMap[36261]=RMS9ModelMap[36301]=
|
RMS9ModelMap[36201]=RMS9ModelMap[36221]=RMS9ModelMap[36261]=RMS9ModelMap[36301]=
|
||||||
@ -1772,6 +1781,8 @@ void ResInitModelMap()
|
|||||||
RMS9ModelMap[33129]="S8 AutoSet II";
|
RMS9ModelMap[33129]="S8 AutoSet II";
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// Translation lookup table for non-english machines
|
||||||
resmed_codes[CPAP_FlowRate].push_back("Flow");
|
resmed_codes[CPAP_FlowRate].push_back("Flow");
|
||||||
resmed_codes[CPAP_MaskPressureHi].push_back("Mask Pres");
|
resmed_codes[CPAP_MaskPressureHi].push_back("Mask Pres");
|
||||||
resmed_codes[CPAP_MaskPressureHi].push_back("Mask Pressure"); // vpap
|
resmed_codes[CPAP_MaskPressureHi].push_back("Mask Pressure"); // vpap
|
||||||
|
@ -38,14 +38,16 @@ int ZEOLoader::Open(QString & path,Profile *profile)
|
|||||||
|
|
||||||
// Could Scan the ZEO folder for a list of CSVs
|
// Could Scan the ZEO folder for a list of CSVs
|
||||||
|
|
||||||
if (path.toLower().endsWith(QDir::separator()+dirtag)) {
|
path=path.replace("\\","/");
|
||||||
|
|
||||||
|
if (path.toLower().endsWith("/"+dirtag)) {
|
||||||
return 0;
|
return 0;
|
||||||
//newpath=path;
|
//newpath=path;
|
||||||
} else {
|
} else {
|
||||||
newpath=path+QDir::separator()+dirtag.toUpper();
|
newpath=path+"/"+dirtag.toUpper();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString filename;
|
//QString filename;
|
||||||
|
|
||||||
// ZEO folder structure detection stuff here.
|
// ZEO folder structure detection stuff here.
|
||||||
|
|
||||||
|
@ -225,7 +225,7 @@ bool Machine::Purge(int secret)
|
|||||||
bool ok;
|
bool ok;
|
||||||
ext_s.toInt(&ok,10);
|
ext_s.toInt(&ok,10);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
qDebug() << "Deleting " << fullpath;
|
qDebug() << "Deleting " << QDir::toNativeSeparators(fullpath);
|
||||||
dir.remove(fullpath);
|
dir.remove(fullpath);
|
||||||
} else could_not_kill++;
|
} else could_not_kill++;
|
||||||
|
|
||||||
@ -246,7 +246,7 @@ bool Machine::Load()
|
|||||||
QString path=profile->Get(properties[STR_PROP_Path]); //STR_GEN_DataFolder)+"/"+m_class+"_"+hexid();
|
QString path=profile->Get(properties[STR_PROP_Path]); //STR_GEN_DataFolder)+"/"+m_class+"_"+hexid();
|
||||||
|
|
||||||
QDir dir(path);
|
QDir dir(path);
|
||||||
qDebug() << "Loading " << path;
|
qDebug() << "Loading " << QDir::toNativeSeparators(path);
|
||||||
|
|
||||||
if (!dir.exists() || !dir.isReadable())
|
if (!dir.exists() || !dir.isReadable())
|
||||||
return false;
|
return false;
|
||||||
|
@ -67,7 +67,7 @@ QString GetAppRoot()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (HomeAppRoot.isEmpty())
|
if (HomeAppRoot.isEmpty())
|
||||||
HomeAppRoot=desktopFolder+QDir::separator()+AppRoot;
|
HomeAppRoot=desktopFolder+"/"+AppRoot;
|
||||||
|
|
||||||
return HomeAppRoot;
|
return HomeAppRoot;
|
||||||
}
|
}
|
||||||
@ -81,25 +81,22 @@ Preferences::Preferences()
|
|||||||
|
|
||||||
Preferences::Preferences(QString name,QString filename)
|
Preferences::Preferences(QString name,QString filename)
|
||||||
{
|
{
|
||||||
|
if (name.endsWith(STR_ext_XML)) {
|
||||||
const QString xmlext=".xml";
|
|
||||||
|
|
||||||
if (name.endsWith(xmlext)) {
|
|
||||||
p_name=name.section(".",0,0);
|
p_name=name.section(".",0,0);
|
||||||
} else {
|
} else {
|
||||||
p_name=name;
|
p_name=name;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filename.isEmpty()) {
|
if (filename.isEmpty()) {
|
||||||
p_filename=GetAppRoot()+QDir::separator()+p_name+xmlext;
|
p_filename=GetAppRoot()+"/"+p_name+STR_ext_XML;
|
||||||
} else {
|
} else {
|
||||||
if (!filename.contains(QDir::separator())) {
|
if (!filename.contains("/")) {
|
||||||
p_filename=GetAppRoot()+QDir::separator();
|
p_filename=GetAppRoot()+"/";
|
||||||
} else p_filename="";
|
} else p_filename="";
|
||||||
|
|
||||||
p_filename+=filename;
|
p_filename+=filename;
|
||||||
|
|
||||||
if (!p_filename.endsWith(xmlext)) p_filename+=xmlext;
|
if (!p_filename.endsWith(STR_ext_XML)) p_filename+=STR_ext_XML;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,7 +146,7 @@ const QString Preferences::Get(QString name)
|
|||||||
} else if (ref.toLower()=="user") {
|
} else if (ref.toLower()=="user") {
|
||||||
temp+=getUserName();
|
temp+=getUserName();
|
||||||
} else if (ref.toLower()=="sep") { // redundant in QT
|
} else if (ref.toLower()=="sep") { // redundant in QT
|
||||||
temp+=QDir::separator();
|
temp+="/";
|
||||||
} else {
|
} else {
|
||||||
temp+=Get(ref);
|
temp+=Get(ref);
|
||||||
}
|
}
|
||||||
@ -169,13 +166,13 @@ bool Preferences::Open(QString filename)
|
|||||||
|
|
||||||
QDomDocument doc(p_name);
|
QDomDocument doc(p_name);
|
||||||
QFile file(p_filename);
|
QFile file(p_filename);
|
||||||
qDebug() << "Scanning " << p_filename;
|
qDebug() << "Scanning " << QDir::toNativeSeparators(p_filename);
|
||||||
if (!file.open(QIODevice::ReadOnly)) {
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
qWarning() << "Could not open" << p_filename;
|
qWarning() << "Could not open" << QDir::toNativeSeparators(p_filename);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!doc.setContent(&file)) {
|
if (!doc.setContent(&file)) {
|
||||||
qWarning() << "Invalid XML Content in" << p_filename;
|
qWarning() << "Invalid XML Content in" << QDir::toNativeSeparators(p_filename);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
file.close();
|
file.close();
|
||||||
|
@ -21,6 +21,8 @@ License: GPL
|
|||||||
const QString AppName="SleepyHead"; // Outer tag of XML files
|
const QString AppName="SleepyHead"; // Outer tag of XML files
|
||||||
const QString AppRoot="SleepyHeadData"; // The Folder Name
|
const QString AppRoot="SleepyHeadData"; // The Folder Name
|
||||||
|
|
||||||
|
const QString STR_ext_XML=".xml";
|
||||||
|
|
||||||
extern QString GetAppRoot(); //returns app root path plus trailing path separator.
|
extern QString GetAppRoot(); //returns app root path plus trailing path separator.
|
||||||
|
|
||||||
inline QString PrefMacro(QString s)
|
inline QString PrefMacro(QString s)
|
||||||
|
@ -48,15 +48,15 @@ Profile::Profile()
|
|||||||
Profile::Profile(QString path)
|
Profile::Profile(QString path)
|
||||||
:Preferences(),is_first_day(true)
|
:Preferences(),is_first_day(true)
|
||||||
{
|
{
|
||||||
const QString xmlext=".xml";
|
|
||||||
p_name=STR_GEN_Profile;
|
p_name=STR_GEN_Profile;
|
||||||
if (path.isEmpty())
|
if (path.isEmpty())
|
||||||
p_path=GetAppRoot();
|
p_path=GetAppRoot();
|
||||||
else p_path=path;
|
else p_path=path;
|
||||||
(*this)[STR_GEN_DataFolder]=p_path;
|
(*this)[STR_GEN_DataFolder]=p_path;
|
||||||
|
path=path.replace("\\","/");
|
||||||
if (!p_path.endsWith("/"))
|
if (!p_path.endsWith("/"))
|
||||||
p_path+="/";
|
p_path+="/";
|
||||||
p_filename=p_path+p_name+xmlext;
|
p_filename=p_path+p_name+STR_ext_XML;
|
||||||
machlist.clear();
|
machlist.clear();
|
||||||
|
|
||||||
doctor=NULL;
|
doctor=NULL;
|
||||||
@ -247,7 +247,6 @@ QDomElement Profile::ExtraSave(QDomDocument & doc)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <QMessageBox>
|
|
||||||
void Profile::AddDay(QDate date,Day *day,MachineType mt) {
|
void Profile::AddDay(QDate date,Day *day,MachineType mt) {
|
||||||
//date+=wxTimeSpan::Day();
|
//date+=wxTimeSpan::Day();
|
||||||
if (!day) {
|
if (!day) {
|
||||||
@ -279,6 +278,7 @@ void Profile::AddDay(QDate date,Day *day,MachineType mt) {
|
|||||||
daylist[date].push_back(day);
|
daylist[date].push_back(day);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get Day record if data available for date and machine type, and has enabled session data, else return NULL
|
||||||
Day * Profile::GetGoodDay(QDate date,MachineType type)
|
Day * Profile::GetGoodDay(QDate date,MachineType type)
|
||||||
{
|
{
|
||||||
Day *day=NULL;
|
Day *day=NULL;
|
||||||
@ -363,8 +363,8 @@ MachineLoader * GetLoader(QString name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QList<Machine *> Profile::GetMachines(MachineType t)
|
|
||||||
// Returns a QVector containing all machine objects regisered of type t
|
// Returns a QVector containing all machine objects regisered of type t
|
||||||
|
QList<Machine *> Profile::GetMachines(MachineType t)
|
||||||
{
|
{
|
||||||
QList<Machine *> vec;
|
QList<Machine *> vec;
|
||||||
QHash<MachineID,Machine *>::iterator i;
|
QHash<MachineID,Machine *>::iterator i;
|
||||||
@ -912,6 +912,7 @@ EventDataType Profile::calcPercentile(ChannelID code, EventDataType percent, Mac
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Lookup first day record of the specified machine type, or return the first day overall if MT_UNKNOWN
|
||||||
QDate Profile::FirstDay(MachineType mt)
|
QDate Profile::FirstDay(MachineType mt)
|
||||||
{
|
{
|
||||||
if ((mt==MT_UNKNOWN) || (!m_last.isValid()) || (!m_first.isValid()))
|
if ((mt==MT_UNKNOWN) || (!m_last.isValid()) || (!m_first.isValid()))
|
||||||
@ -925,6 +926,8 @@ QDate Profile::FirstDay(MachineType mt)
|
|||||||
} while (d<=m_last);
|
} while (d<=m_last);
|
||||||
return m_last;
|
return m_last;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Lookup last day record of the specified machine type, or return the first day overall if MT_UNKNOWN
|
||||||
QDate Profile::LastDay(MachineType mt)
|
QDate Profile::LastDay(MachineType mt)
|
||||||
{
|
{
|
||||||
if ((mt==MT_UNKNOWN) || (!m_last.isValid()) || (!m_first.isValid()))
|
if ((mt==MT_UNKNOWN) || (!m_last.isValid()) || (!m_first.isValid()))
|
||||||
|
@ -88,7 +88,9 @@ SOURCES += main.cpp\
|
|||||||
UpdaterWindow.cpp \
|
UpdaterWindow.cpp \
|
||||||
SleepLib/common.cpp \
|
SleepLib/common.cpp \
|
||||||
SleepLib/loader_plugins/icon_loader.cpp \
|
SleepLib/loader_plugins/icon_loader.cpp \
|
||||||
SleepLib/loader_plugins/mseries_loader.cpp
|
SleepLib/loader_plugins/mseries_loader.cpp \
|
||||||
|
reports.cpp \
|
||||||
|
summary.cpp
|
||||||
|
|
||||||
unix:SOURCES += qextserialport/posix_qextserialport.cpp
|
unix:SOURCES += qextserialport/posix_qextserialport.cpp
|
||||||
unix:!macx:SOURCES += qextserialport/qextserialenumerator_unix.cpp
|
unix:!macx:SOURCES += qextserialport/qextserialenumerator_unix.cpp
|
||||||
@ -168,7 +170,9 @@ HEADERS += \
|
|||||||
UpdaterWindow.h \
|
UpdaterWindow.h \
|
||||||
SleepLib/common.h \
|
SleepLib/common.h \
|
||||||
SleepLib/loader_plugins/icon_loader.h \
|
SleepLib/loader_plugins/icon_loader.h \
|
||||||
SleepLib/loader_plugins/mseries_loader.h
|
SleepLib/loader_plugins/mseries_loader.h \
|
||||||
|
reports.h \
|
||||||
|
summary.h
|
||||||
|
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
|
1435
mainwindow.cpp
1435
mainwindow.cpp
File diff suppressed because it is too large
Load Diff
12
mainwindow.h
12
mainwindow.h
@ -128,19 +128,15 @@ public:
|
|||||||
|
|
||||||
void JumpDaily();
|
void JumpDaily();
|
||||||
|
|
||||||
/*! \fn void PrintReport gGraphView *gv,QString name, QDate date=QDate::currentDate());
|
|
||||||
\brief Prepares a report using gGraphView object, and sends to a created QPrinter object
|
|
||||||
\param gGraphView *gv GraphView Object containing which graph set to print
|
|
||||||
\param QString name Report Title
|
|
||||||
\param QDate date
|
|
||||||
*/
|
|
||||||
void PrintReport(gGraphView *gv,QString name, QDate date=QDate::currentDate());
|
|
||||||
|
|
||||||
void sendStatsUrl(QString msg) { on_recordsBox_linkClicked(QUrl(msg)); }
|
void sendStatsUrl(QString msg) { on_recordsBox_linkClicked(QUrl(msg)); }
|
||||||
|
|
||||||
//! \brief Sets up recalculation of all event summaries and flags
|
//! \brief Sets up recalculation of all event summaries and flags
|
||||||
void reprocessEvents(bool restart=false);
|
void reprocessEvents(bool restart=false);
|
||||||
|
|
||||||
|
|
||||||
|
//! \brief Internal function to set Records Box html from summary module
|
||||||
|
void setRecBoxHTML(QString html);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
//! \brief Recalculate all event summaries and flags
|
//! \brief Recalculate all event summaries and flags
|
||||||
void doReprocessEvents();
|
void doReprocessEvents();
|
||||||
|
@ -99,9 +99,9 @@ void NewProfile::on_nextButton_clicked()
|
|||||||
switch(index) {
|
switch(index) {
|
||||||
case 0:
|
case 0:
|
||||||
settings.setValue("Settings/AppRoot", ui->dataFolderPath->text());
|
settings.setValue("Settings/AppRoot", ui->dataFolderPath->text());
|
||||||
p_pref->setFilename(ui->dataFolderPath->text()+QDir::separator()+p_pref->name()+xmlext);
|
p_pref->setFilename(ui->dataFolderPath->text()+"/"+p_pref->name()+xmlext);
|
||||||
p_pref->setPath(ui->dataFolderPath->text());
|
p_pref->setPath(ui->dataFolderPath->text());
|
||||||
p_layout->setFilename(ui->dataFolderPath->text()+QDir::separator()+p_layout->name()+xmlext);
|
p_layout->setFilename(ui->dataFolderPath->text()+"/"+p_layout->name()+xmlext);
|
||||||
p_layout->setPath(ui->dataFolderPath->text());
|
p_layout->setPath(ui->dataFolderPath->text());
|
||||||
// Reload Preferences object
|
// Reload Preferences object
|
||||||
break;
|
break;
|
||||||
|
@ -510,6 +510,11 @@ void CMS50Serial::import_process()
|
|||||||
a=data.at(i++); // low bits are supposedly the high bits of the heart rate? not here
|
a=data.at(i++); // low bits are supposedly the high bits of the heart rate? not here
|
||||||
pl=((data.at(i++) & 0x7f) | ((a & 1) << 7)) & 0xff;
|
pl=((data.at(i++) & 0x7f) | ((a & 1) << 7)) & 0xff;
|
||||||
o2=data.at(i++) & 0x7f;
|
o2=data.at(i++) & 0x7f;
|
||||||
|
|
||||||
|
// Faulty data..?
|
||||||
|
if (o2 < 50)
|
||||||
|
o2=0;
|
||||||
|
|
||||||
if (pl!=0) {
|
if (pl!=0) {
|
||||||
if (lastpl!=pl) {
|
if (lastpl!=pl) {
|
||||||
if (lastpl==0 || !pulse) {
|
if (lastpl==0 || !pulse) {
|
||||||
|
532
reports.cpp
Normal file
532
reports.cpp
Normal file
@ -0,0 +1,532 @@
|
|||||||
|
/*
|
||||||
|
Reports / Printing Module
|
||||||
|
Copyright (c)2013 Mark Watkins <jedimark@users.sourceforge.net>
|
||||||
|
License: GPL3
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QPrinter>
|
||||||
|
#include <QPrintDialog>
|
||||||
|
#include <QTextDocument>
|
||||||
|
#include <QProgressBar>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include "reports.h"
|
||||||
|
#include "mainwindow.h"
|
||||||
|
#include "common_gui.h"
|
||||||
|
|
||||||
|
extern QProgressBar *qprogress;
|
||||||
|
extern MainWindow * mainwin;
|
||||||
|
|
||||||
|
|
||||||
|
Report::Report()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Report::PrintReport(gGraphView *gv,QString name, QDate date)
|
||||||
|
{
|
||||||
|
if (!gv) return;
|
||||||
|
Session * journal=NULL;
|
||||||
|
//QDate d=QDate::currentDate();
|
||||||
|
|
||||||
|
int visgraphs=gv->visibleGraphs();
|
||||||
|
if (visgraphs==0) {
|
||||||
|
mainwin->Notify(QObject::tr("There are no graphs visible to print"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString username=PROFILE.Get(QString("_{")+QString(STR_UI_UserName)+"}_");
|
||||||
|
|
||||||
|
bool print_bookmarks=false;
|
||||||
|
if (name==STR_TR_Daily) {
|
||||||
|
QVariantList book_start;
|
||||||
|
journal=mainwin->getDaily()->GetJournalSession(mainwin->getDaily()->getDate());
|
||||||
|
if (journal && journal->settings.contains(Bookmark_Start)) {
|
||||||
|
book_start=journal->settings[Bookmark_Start].toList();
|
||||||
|
if (book_start.size()>0) {
|
||||||
|
if (QMessageBox::question(mainwin,STR_TR_Bookmarks,QObject::tr("Would you like to show bookmarked areas in this report?"),QMessageBox::Yes,QMessageBox::No)==QMessageBox::Yes) {
|
||||||
|
print_bookmarks=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QPrinter * printer;
|
||||||
|
|
||||||
|
bool aa_setting=PROFILE.appearance->antiAliasing();
|
||||||
|
|
||||||
|
bool force_antialiasing=aa_setting;
|
||||||
|
|
||||||
|
printer=new QPrinter(QPrinter::HighResolution);
|
||||||
|
|
||||||
|
#ifdef Q_WS_X11
|
||||||
|
printer->setPrinterName("Print to File (PDF)");
|
||||||
|
printer->setOutputFormat(QPrinter::PdfFormat);
|
||||||
|
QString filename=PREF.Get("{home}/"+name+username+date.toString(Qt::ISODate)+".pdf");
|
||||||
|
|
||||||
|
printer->setOutputFileName(filename);
|
||||||
|
#endif
|
||||||
|
printer->setPrintRange(QPrinter::AllPages);
|
||||||
|
printer->setOrientation(QPrinter::Portrait);
|
||||||
|
printer->setFullPage(false); // This has nothing to do with scaling
|
||||||
|
printer->setNumCopies(1);
|
||||||
|
printer->setPageMargins(10,10,10,10,QPrinter::Millimeter);
|
||||||
|
QPrintDialog dialog(printer);
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
// QTBUG-17913
|
||||||
|
QApplication::processEvents();
|
||||||
|
#endif
|
||||||
|
if (dialog.exec() != QDialog::Accepted) {
|
||||||
|
delete printer;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mainwin->Notify(QObject::tr("This make take some time to complete..\nPlease don't touch anything until it's done."),QObject::tr("Printing %1 Report").arg(name),20000);
|
||||||
|
QPainter painter;
|
||||||
|
painter.begin(printer);
|
||||||
|
|
||||||
|
GLint gw;
|
||||||
|
gw=2048; // Rough guess.. No GL_MAX_RENDERBUFFER_SIZE in mingw.. :(
|
||||||
|
|
||||||
|
//QSizeF pxres=printer->paperSize(QPrinter::DevicePixel);
|
||||||
|
QRect prect=printer->pageRect();
|
||||||
|
float ratio=float(prect.height())/float(prect.width());
|
||||||
|
float virt_width=gw;
|
||||||
|
float virt_height=virt_width*ratio;
|
||||||
|
painter.setWindow(0,0,virt_width, virt_height);
|
||||||
|
painter.setViewport(0,0,prect.width(),prect.height());
|
||||||
|
painter.setViewTransformEnabled(true);
|
||||||
|
|
||||||
|
QFont report_font=*defaultfont;
|
||||||
|
QFont medium_font=*mediumfont;
|
||||||
|
QFont title_font=*bigfont;
|
||||||
|
float normal_height=30; //fm2.ascent();
|
||||||
|
report_font.setPixelSize(normal_height);
|
||||||
|
medium_font.setPixelSize(40);
|
||||||
|
title_font.setPixelSize(90);
|
||||||
|
painter.setFont(report_font);
|
||||||
|
|
||||||
|
//QFontMetrics fm2(*defaultfont);
|
||||||
|
|
||||||
|
qDebug() << "Printer Resolution is" << virt_width << "x" << virt_height;
|
||||||
|
|
||||||
|
const int graphs_per_page=6;
|
||||||
|
float full_graph_height=(virt_height-(normal_height*graphs_per_page)) / float(graphs_per_page);
|
||||||
|
|
||||||
|
QString title=QObject::tr("%1 Report").arg(name);
|
||||||
|
painter.setFont(title_font);
|
||||||
|
int top=0;
|
||||||
|
QRectF bounds=painter.boundingRect(QRectF(0,top,virt_width,0),title,QTextOption(Qt::AlignHCenter | Qt::AlignTop));
|
||||||
|
painter.drawText(bounds,title,QTextOption(Qt::AlignHCenter | Qt::AlignTop));
|
||||||
|
top+=bounds.height()+normal_height/2.0;
|
||||||
|
painter.setFont(report_font);
|
||||||
|
|
||||||
|
int maxy=0;
|
||||||
|
if (!PROFILE.user->firstName().isEmpty()) {
|
||||||
|
QString userinfo=STR_TR_Name+QString(":\t %1, %2\n").arg(PROFILE.user->lastName()).arg(PROFILE.user->firstName());
|
||||||
|
userinfo+=STR_TR_DOB+QString(":\t%1\n").arg(PROFILE.user->DOB().toString(Qt::SystemLocaleShortDate));
|
||||||
|
if (!PROFILE.doctor->patientID().isEmpty()) userinfo+=STR_TR_PatientID+QString(":\t%1\n").arg(PROFILE.doctor->patientID());
|
||||||
|
userinfo+=STR_TR_Phone+QString(":\t%1\n").arg(PROFILE.user->phone());
|
||||||
|
userinfo+=STR_TR_Email+QString(":\t%1\n").arg(PROFILE.user->email());
|
||||||
|
if (!PROFILE.user->address().isEmpty()) userinfo+="\n"+STR_TR_Address+QString(":\n%1").arg(PROFILE.user->address());
|
||||||
|
|
||||||
|
QRectF bounds=painter.boundingRect(QRectF(0,top,virt_width,0),userinfo,QTextOption(Qt::AlignLeft | Qt::AlignTop));
|
||||||
|
painter.drawText(bounds,userinfo,QTextOption(Qt::AlignLeft | Qt::AlignTop));
|
||||||
|
if (bounds.height()>maxy) maxy=bounds.height();
|
||||||
|
}
|
||||||
|
Day *cpap=NULL, *oxi=NULL;
|
||||||
|
|
||||||
|
int graph_slots=0;
|
||||||
|
if (name==STR_TR_Daily) {
|
||||||
|
cpap=PROFILE.GetGoodDay(date,MT_CPAP);
|
||||||
|
oxi=PROFILE.GetGoodDay(date,MT_OXIMETER);
|
||||||
|
QString cpapinfo=date.toString(Qt::SystemLocaleLongDate)+"\n\n";
|
||||||
|
if (cpap) {
|
||||||
|
time_t f=cpap->first()/1000L;
|
||||||
|
time_t l=cpap->last()/1000L;
|
||||||
|
int tt=qint64(cpap->total_time())/1000L;
|
||||||
|
int h=tt/3600;
|
||||||
|
int m=(tt/60)%60;
|
||||||
|
int s=tt % 60;
|
||||||
|
|
||||||
|
cpapinfo+=STR_TR_MaskTime+QObject::tr(": %1 hours, %2 minutes, %3 seconds\n").arg(h).arg(m).arg(s);
|
||||||
|
cpapinfo+=STR_TR_BedTime+": "+QDateTime::fromTime_t(f).time().toString("HH:mm:ss")+" ";
|
||||||
|
cpapinfo+=STR_TR_WakeUp+": "+QDateTime::fromTime_t(l).time().toString("HH:mm:ss")+"\n\n";
|
||||||
|
QString submodel;
|
||||||
|
cpapinfo+=STR_TR_Machine+": ";
|
||||||
|
if (cpap->machine->properties.find(STR_PROP_SubModel)!=cpap->machine->properties.end())
|
||||||
|
submodel="\n"+cpap->machine->properties[STR_PROP_SubModel];
|
||||||
|
cpapinfo+=cpap->machine->properties[STR_PROP_Brand]+" "+cpap->machine->properties[STR_PROP_Model]+submodel;
|
||||||
|
CPAPMode mode=(CPAPMode)(int)cpap->settings_max(CPAP_Mode);
|
||||||
|
cpapinfo+="\n"+STR_TR_Mode+": ";
|
||||||
|
|
||||||
|
if (mode==MODE_CPAP) {
|
||||||
|
EventDataType min=round(cpap->settings_wavg(CPAP_Pressure)*2)/2.0;
|
||||||
|
cpapinfo+=STR_TR_CPAP+" "+QString::number(min)+STR_UNIT_CMH2O;
|
||||||
|
} else if (mode==MODE_APAP) {
|
||||||
|
EventDataType min=cpap->settings_min(CPAP_PressureMin);
|
||||||
|
EventDataType max=cpap->settings_max(CPAP_PressureMax);
|
||||||
|
cpapinfo+=STR_TR_APAP+" "+QString::number(min)+"-"+QString::number(max)+STR_UNIT_CMH2O;
|
||||||
|
} else if (mode==MODE_BIPAP) {
|
||||||
|
EventDataType epap=cpap->settings_min(CPAP_EPAP);
|
||||||
|
EventDataType ipap=cpap->settings_max(CPAP_IPAP);
|
||||||
|
EventDataType ps=cpap->settings_max(CPAP_PS);
|
||||||
|
cpapinfo+=STR_TR_BiLevel+QString("\n"+STR_TR_EPAP+": %1 "+STR_TR_IPAP+": %2 %3\n"+STR_TR_PS+": %4")
|
||||||
|
.arg(epap,0,'f',1).arg(ipap,0,'f',1).arg(STR_UNIT_CMH2O).arg(ps,0,'f',1);
|
||||||
|
}
|
||||||
|
else if (mode==MODE_ASV) {
|
||||||
|
EventDataType epap=cpap->settings_min(CPAP_EPAP);
|
||||||
|
EventDataType low=cpap->settings_min(CPAP_IPAPLo);
|
||||||
|
EventDataType high=cpap->settings_max(CPAP_IPAPHi);
|
||||||
|
EventDataType psl=cpap->settings_min(CPAP_PSMin);
|
||||||
|
EventDataType psh=cpap->settings_max(CPAP_PSMax);
|
||||||
|
cpapinfo+=STR_TR_ASV+QString("\n"+STR_TR_EPAP+": %1 "+STR_TR_IPAP+": %2 - %3 %4\n"+STR_TR_PS+": %5 / %6")
|
||||||
|
.arg(epap,0,'f',1)
|
||||||
|
.arg(low,0,'f',1)
|
||||||
|
.arg(high,0,'f',1)
|
||||||
|
.arg(STR_UNIT_CMH2O)
|
||||||
|
.arg(psl,0,'f',1)
|
||||||
|
.arg(psh,0,'f',1);
|
||||||
|
}
|
||||||
|
else cpapinfo+=STR_TR_Unknown;
|
||||||
|
|
||||||
|
float ahi=(cpap->count(CPAP_Obstructive)+cpap->count(CPAP_Hypopnea)+cpap->count(CPAP_ClearAirway)+cpap->count(CPAP_Apnea));
|
||||||
|
if (PROFILE.general->calculateRDI()) ahi+=cpap->count(CPAP_RERA);
|
||||||
|
ahi/=cpap->hours();
|
||||||
|
float csr=(100.0/cpap->hours())*(cpap->sum(CPAP_CSR)/3600.0);
|
||||||
|
float uai=cpap->count(CPAP_Apnea)/cpap->hours();
|
||||||
|
float oai=cpap->count(CPAP_Obstructive)/cpap->hours();
|
||||||
|
float hi=(cpap->count(CPAP_ExP)+cpap->count(CPAP_Hypopnea))/cpap->hours();
|
||||||
|
float cai=cpap->count(CPAP_ClearAirway)/cpap->hours();
|
||||||
|
float rei=cpap->count(CPAP_RERA)/cpap->hours();
|
||||||
|
float vsi=cpap->count(CPAP_VSnore)/cpap->hours();
|
||||||
|
float fli=cpap->count(CPAP_FlowLimit)/cpap->hours();
|
||||||
|
float nri=cpap->count(CPAP_NRI)/cpap->hours();
|
||||||
|
float lki=cpap->count(CPAP_LeakFlag)/cpap->hours();
|
||||||
|
float exp=cpap->count(CPAP_ExP)/cpap->hours();
|
||||||
|
|
||||||
|
int piesize=(2048.0/8.0)*1.3; // 1.5" in size
|
||||||
|
//float fscale=font_scale;
|
||||||
|
//if (!highres)
|
||||||
|
// fscale=1;
|
||||||
|
|
||||||
|
QString stats;
|
||||||
|
painter.setFont(medium_font);
|
||||||
|
if (PROFILE.general->calculateRDI())
|
||||||
|
stats=QObject::tr("RDI\t%1\n").arg(ahi,0,'f',2);
|
||||||
|
else
|
||||||
|
stats=QObject::tr("AHI\t%1\n").arg(ahi,0,'f',2);
|
||||||
|
QRectF bounds=painter.boundingRect(QRectF(0,0,virt_width,0),stats,QTextOption(Qt::AlignRight));
|
||||||
|
painter.drawText(bounds,stats,QTextOption(Qt::AlignRight));
|
||||||
|
|
||||||
|
|
||||||
|
mainwin->getDaily()->eventBreakdownPie()->setShowTitle(false);
|
||||||
|
mainwin->getDaily()->eventBreakdownPie()->setMargins(0,0,0,0);
|
||||||
|
QPixmap ebp;
|
||||||
|
if (ahi>0) {
|
||||||
|
ebp=mainwin->getDaily()->eventBreakdownPie()->renderPixmap(piesize,piesize,true);
|
||||||
|
} else {
|
||||||
|
ebp=QPixmap(":/icons/smileyface.png");
|
||||||
|
}
|
||||||
|
if (!ebp.isNull()) {
|
||||||
|
painter.drawPixmap(virt_width-piesize,bounds.height(),piesize,piesize,ebp);
|
||||||
|
}
|
||||||
|
mainwin->getDaily()->eventBreakdownPie()->setShowTitle(true);
|
||||||
|
|
||||||
|
cpapinfo+="\n\n";
|
||||||
|
|
||||||
|
painter.setFont(report_font);
|
||||||
|
//bounds=painter.boundingRect(QRectF((virt_width/2)-(virt_width/6),top,virt_width/2,0),cpapinfo,QTextOption(Qt::AlignLeft));
|
||||||
|
bounds=painter.boundingRect(QRectF(0,top,virt_width,0),cpapinfo,QTextOption(Qt::AlignHCenter));
|
||||||
|
painter.drawText(bounds,cpapinfo,QTextOption(Qt::AlignHCenter));
|
||||||
|
|
||||||
|
int ttop=bounds.height();
|
||||||
|
|
||||||
|
stats=QObject::tr("AI=%1 HI=%2 CAI=%3 ").arg(oai,0,'f',2).arg(hi,0,'f',2).arg(cai,0,'f',2);
|
||||||
|
if (cpap->machine->GetClass()==STR_MACH_PRS1) {
|
||||||
|
stats+=QObject::tr("REI=%1 VSI=%2 FLI=%3 PB/CSR=%4\%")
|
||||||
|
.arg(rei,0,'f',2).arg(vsi,0,'f',2)
|
||||||
|
.arg(fli,0,'f',2).arg(csr,0,'f',2);
|
||||||
|
} else if (cpap->machine->GetClass()==STR_MACH_ResMed) {
|
||||||
|
stats+=QObject::tr("UAI=%1 ").arg(uai,0,'f',2);
|
||||||
|
} else if (cpap->machine->GetClass()==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,'f',2);
|
||||||
|
}
|
||||||
|
bounds=painter.boundingRect(QRectF(0,top+ttop,virt_width,0),stats,QTextOption(Qt::AlignHCenter));
|
||||||
|
painter.drawText(bounds,stats,QTextOption(Qt::AlignHCenter));
|
||||||
|
ttop+=bounds.height();
|
||||||
|
|
||||||
|
if (journal) {
|
||||||
|
stats="";
|
||||||
|
if (journal->settings.contains(Journal_Weight))
|
||||||
|
stats+=STR_TR_Weight+QString(" %1 ").arg(weightString(journal->settings[Journal_Weight].toDouble()));
|
||||||
|
if (journal->settings.contains(Journal_BMI))
|
||||||
|
stats+=STR_TR_BMI+QString(" %1 ").arg(journal->settings[Journal_BMI].toDouble(),0,'f',2);
|
||||||
|
if (journal->settings.contains(Journal_ZombieMeter))
|
||||||
|
stats+=STR_TR_Zombie+QString(" %1/10 ").arg(journal->settings[Journal_ZombieMeter].toDouble(),0,'f',0);
|
||||||
|
|
||||||
|
if (!stats.isEmpty()) {
|
||||||
|
bounds=painter.boundingRect(QRectF(0,top+ttop,virt_width,0),stats,QTextOption(Qt::AlignHCenter));
|
||||||
|
|
||||||
|
painter.drawText(bounds,stats,QTextOption(Qt::AlignHCenter));
|
||||||
|
ttop+=bounds.height();
|
||||||
|
}
|
||||||
|
ttop+=normal_height;
|
||||||
|
if (journal->settings.contains(Journal_Notes)) {
|
||||||
|
QTextDocument doc;
|
||||||
|
doc.setHtml(journal->settings[Journal_Notes].toString());
|
||||||
|
stats=doc.toPlainText();
|
||||||
|
//doc.drawContents(&painter); // doesn't work as intended..
|
||||||
|
|
||||||
|
bounds=painter.boundingRect(QRectF(0,top+ttop,virt_width,0),stats,QTextOption(Qt::AlignHCenter));
|
||||||
|
painter.drawText(bounds,stats,QTextOption(Qt::AlignHCenter));
|
||||||
|
bounds.setLeft(virt_width/4);
|
||||||
|
bounds.setRight(virt_width-(virt_width/4));
|
||||||
|
|
||||||
|
QPen pen(Qt::black);
|
||||||
|
pen.setWidth(4);
|
||||||
|
painter.setPen(pen);
|
||||||
|
painter.drawRect(bounds);
|
||||||
|
ttop+=bounds.height()+normal_height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (ttop>maxy) maxy=ttop;
|
||||||
|
} else {
|
||||||
|
bounds=painter.boundingRect(QRectF(0,top+maxy,virt_width,0),cpapinfo,QTextOption(Qt::AlignCenter));
|
||||||
|
painter.drawText(bounds,cpapinfo,QTextOption(Qt::AlignCenter));
|
||||||
|
if (maxy+bounds.height()>maxy) maxy=maxy+bounds.height();
|
||||||
|
}
|
||||||
|
} else if (name==STR_TR_Overview) {
|
||||||
|
QDateTime first=QDateTime::fromTime_t((*gv)[0]->min_x/1000L);
|
||||||
|
QDateTime last=QDateTime::fromTime_t((*gv)[0]->max_x/1000L);
|
||||||
|
QString ovinfo=QObject::tr("Reporting from %1 to %2").arg(first.date().toString(Qt::SystemLocaleShortDate)).arg(last.date().toString(Qt::SystemLocaleShortDate));
|
||||||
|
QRectF bounds=painter.boundingRect(QRectF(0,top,virt_width,0),ovinfo,QTextOption(Qt::AlignHCenter));
|
||||||
|
painter.drawText(bounds,ovinfo,QTextOption(Qt::AlignHCenter));
|
||||||
|
|
||||||
|
if (bounds.height()>maxy) maxy=bounds.height();
|
||||||
|
} else if (name==STR_TR_Oximetry) {
|
||||||
|
QString ovinfo=QObject::tr("Reporting data goes here");
|
||||||
|
QRectF bounds=painter.boundingRect(QRectF(0,top,virt_width,0),ovinfo,QTextOption(Qt::AlignHCenter));
|
||||||
|
painter.drawText(bounds,ovinfo,QTextOption(Qt::AlignHCenter));
|
||||||
|
|
||||||
|
if (bounds.height()>maxy) maxy=bounds.height();
|
||||||
|
}
|
||||||
|
top+=maxy;
|
||||||
|
|
||||||
|
graph_slots=graphs_per_page-((virt_height-top)/(full_graph_height+normal_height));
|
||||||
|
|
||||||
|
bool first=true;
|
||||||
|
QStringList labels;
|
||||||
|
QVector<gGraph *> graphs;
|
||||||
|
QVector<qint64> start,end;
|
||||||
|
qint64 savest,saveet;
|
||||||
|
gv->GetXBounds(savest,saveet);
|
||||||
|
qint64 st=savest,et=saveet;
|
||||||
|
|
||||||
|
gGraph *g;
|
||||||
|
if (name==STR_TR_Daily) {
|
||||||
|
if (!print_bookmarks) {
|
||||||
|
for (int i=0;i<gv->size();i++) {
|
||||||
|
g=(*gv)[i];
|
||||||
|
if (g->isEmpty()) continue;
|
||||||
|
if (!g->visible()) continue;
|
||||||
|
|
||||||
|
if (cpap) {
|
||||||
|
st=cpap->first();
|
||||||
|
et=cpap->last();
|
||||||
|
} else if (oxi) {
|
||||||
|
st=oxi->first();
|
||||||
|
et=oxi->last();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g->title()==STR_TR_FlowRate) {
|
||||||
|
if (!((qAbs(savest-st)<2000) && (qAbs(saveet-et)<2000))) {
|
||||||
|
start.push_back(st);
|
||||||
|
end.push_back(et);
|
||||||
|
graphs.push_back(g);
|
||||||
|
labels.push_back(QObject::tr("Entire Day's Flow Waveform"));
|
||||||
|
}
|
||||||
|
start.push_back(savest);
|
||||||
|
end.push_back(saveet);
|
||||||
|
graphs.push_back(g);
|
||||||
|
labels.push_back(QObject::tr("Current Selection"));
|
||||||
|
} else {
|
||||||
|
start.push_back(savest);
|
||||||
|
end.push_back(saveet);
|
||||||
|
graphs.push_back(g);
|
||||||
|
labels.push_back("");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const QString EntireDay=QObject::tr("Entire Day");
|
||||||
|
if (journal) {
|
||||||
|
if (journal->settings.contains(Bookmark_Start)) {
|
||||||
|
QVariantList st1=journal->settings[Bookmark_Start].toList();
|
||||||
|
QVariantList et1=journal->settings[Bookmark_End].toList();
|
||||||
|
QStringList notes=journal->settings[Bookmark_Notes].toStringList();
|
||||||
|
gGraph *flow=gv->findGraph(STR_TR_FlowRate),
|
||||||
|
*spo2=gv->findGraph(STR_TR_SpO2),
|
||||||
|
*pulse=gv->findGraph(STR_TR_PulseRate);
|
||||||
|
|
||||||
|
|
||||||
|
if (cpap && flow && !flow->isEmpty() && flow->visible()) {
|
||||||
|
labels.push_back(EntireDay);
|
||||||
|
start.push_back(cpap->first());
|
||||||
|
end.push_back(cpap->last());
|
||||||
|
graphs.push_back(flow);
|
||||||
|
}
|
||||||
|
if (oxi && spo2 && !spo2->isEmpty() && spo2->visible()) {
|
||||||
|
labels.push_back(EntireDay);
|
||||||
|
start.push_back(oxi->first());
|
||||||
|
end.push_back(oxi->last());
|
||||||
|
graphs.push_back(spo2);
|
||||||
|
}
|
||||||
|
if (oxi && pulse && !pulse->isEmpty() && pulse->visible()) {
|
||||||
|
labels.push_back(EntireDay);
|
||||||
|
start.push_back(oxi->first());
|
||||||
|
end.push_back(oxi->last());
|
||||||
|
graphs.push_back(pulse);
|
||||||
|
}
|
||||||
|
for (int i=0;i<notes.size();i++) {
|
||||||
|
if (flow && !flow->isEmpty() && flow->visible()) {
|
||||||
|
labels.push_back(notes.at(i));
|
||||||
|
start.push_back(st1.at(i).toLongLong());
|
||||||
|
end.push_back(et1.at(i).toLongLong());
|
||||||
|
graphs.push_back(flow);
|
||||||
|
}
|
||||||
|
if (spo2 && !spo2->isEmpty() && spo2->visible()) {
|
||||||
|
labels.push_back(notes.at(i));
|
||||||
|
start.push_back(st1.at(i).toLongLong());
|
||||||
|
end.push_back(et1.at(i).toLongLong());
|
||||||
|
graphs.push_back(spo2);
|
||||||
|
}
|
||||||
|
if (pulse && !pulse->isEmpty() && pulse->visible()) {
|
||||||
|
labels.push_back(notes.at(i));
|
||||||
|
start.push_back(st1.at(i).toLongLong());
|
||||||
|
end.push_back(et1.at(i).toLongLong());
|
||||||
|
graphs.push_back(pulse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i=0;i<gv->size();i++) {
|
||||||
|
gGraph *g=(*gv)[i];
|
||||||
|
if (g->isEmpty()) continue;
|
||||||
|
if (!g->visible()) continue;
|
||||||
|
if ((g->title()!=STR_TR_FlowRate ) && (g->title()!=STR_TR_SpO2) && (g->title()!=STR_TR_PulseRate)) {
|
||||||
|
start.push_back(st);
|
||||||
|
end.push_back(et);
|
||||||
|
graphs.push_back(g);
|
||||||
|
labels.push_back("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i=0;i<gv->size();i++) {
|
||||||
|
gGraph *g=(*gv)[i];
|
||||||
|
if (g->isEmpty()) continue;
|
||||||
|
if (!g->visible()) continue;
|
||||||
|
|
||||||
|
start.push_back(st);
|
||||||
|
end.push_back(et);
|
||||||
|
graphs.push_back(g);
|
||||||
|
labels.push_back(""); // date range?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int pages=ceil(float(graphs.size()+graph_slots)/float(graphs_per_page));
|
||||||
|
|
||||||
|
if (qprogress) {
|
||||||
|
qprogress->setValue(0);
|
||||||
|
qprogress->setMaximum(graphs.size());
|
||||||
|
qprogress->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
int page=1;
|
||||||
|
int gcnt=0;
|
||||||
|
for (int i=0;i<graphs.size();i++) {
|
||||||
|
|
||||||
|
if ((top+full_graph_height+normal_height) > virt_height) {
|
||||||
|
top=0;
|
||||||
|
gcnt=0;
|
||||||
|
first=true;
|
||||||
|
if (page > pages)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!printer->newPage()) {
|
||||||
|
qWarning("failed in flushing page to disk, disk full?");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
if (first) {
|
||||||
|
QString footer=QObject::tr("SleepyHead v%1 - http://sleepyhead.sourceforge.net").arg(VersionString);
|
||||||
|
|
||||||
|
QRectF bounds=painter.boundingRect(QRectF(0,virt_height,virt_width,normal_height),footer,QTextOption(Qt::AlignHCenter));
|
||||||
|
painter.drawText(bounds,footer,QTextOption(Qt::AlignHCenter));
|
||||||
|
|
||||||
|
QString pagestr=QObject::tr("Page %1 of %2").arg(page).arg(pages);
|
||||||
|
QRectF pagebnds=painter.boundingRect(QRectF(0,virt_height,virt_width,normal_height),pagestr,QTextOption(Qt::AlignRight));
|
||||||
|
painter.drawText(pagebnds,pagestr,QTextOption(Qt::AlignRight));
|
||||||
|
first=false;
|
||||||
|
page++;
|
||||||
|
}
|
||||||
|
|
||||||
|
gGraph *g=graphs[i];
|
||||||
|
g->SetXBounds(start[i],end[i]);
|
||||||
|
g->deselect();
|
||||||
|
|
||||||
|
QString label=labels[i];
|
||||||
|
if (!label.isEmpty()) {
|
||||||
|
//label+=":";
|
||||||
|
top+=normal_height/3;
|
||||||
|
QRectF bounds=painter.boundingRect(QRectF(0,top,virt_width,0),label,QTextOption(Qt::AlignHCenter));
|
||||||
|
//QRectF pagebnds=QRectF(0,top,virt_width,normal_height);
|
||||||
|
painter.drawText(bounds,label,QTextOption(Qt::AlignHCenter));
|
||||||
|
top+=bounds.height();
|
||||||
|
} else top+=normal_height/2;
|
||||||
|
|
||||||
|
PROFILE.appearance->setAntiAliasing(force_antialiasing);
|
||||||
|
int tmb=g->m_marginbottom;
|
||||||
|
g->m_marginbottom=0;
|
||||||
|
|
||||||
|
|
||||||
|
//painter.beginNativePainting();
|
||||||
|
//g->showTitle(false);
|
||||||
|
int hhh=full_graph_height-normal_height;
|
||||||
|
QPixmap pm2=g->renderPixmap(virt_width,hhh,1);
|
||||||
|
QImage pm=pm2.toImage();//fscale);
|
||||||
|
pm2.detach();
|
||||||
|
//g->showTitle(true);
|
||||||
|
//painter.endNativePainting();
|
||||||
|
g->m_marginbottom=tmb;
|
||||||
|
PROFILE.appearance->setAntiAliasing(aa_setting);
|
||||||
|
|
||||||
|
|
||||||
|
if (!pm.isNull()) {
|
||||||
|
painter.drawImage(0,top,pm);;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//painter.drawImage(0,top,virt_width,full_graph_height-normal_height,pm);
|
||||||
|
}
|
||||||
|
top+=full_graph_height;
|
||||||
|
|
||||||
|
gcnt++;
|
||||||
|
if (qprogress) {
|
||||||
|
qprogress->setValue(i);
|
||||||
|
QApplication::processEvents();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gv->SetXBounds(savest,saveet);
|
||||||
|
qprogress->hide();
|
||||||
|
painter.end();
|
||||||
|
delete printer;
|
||||||
|
mainwin->Notify(QObject::tr("SleepyHead has finished sending the job to the printer."));
|
||||||
|
}
|
||||||
|
|
25
reports.h
Normal file
25
reports.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
Reports Header
|
||||||
|
Copyright (c)2013 Mark Watkins <jedimark@users.sourceforge.net>
|
||||||
|
License: GPL3
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef REPORTS_H
|
||||||
|
#define REPORTS_H
|
||||||
|
#include "Graphs/gGraphView.h"
|
||||||
|
|
||||||
|
class Report
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Report();
|
||||||
|
|
||||||
|
/*! \fn void PrintReport gGraphView *gv,QString name, QDate date=QDate::currentDate());
|
||||||
|
\brief Prepares a report using gGraphView object, and sends to a created QPrinter object
|
||||||
|
\param gGraphView *gv GraphView Object containing which graph set to print
|
||||||
|
\param QString name Report Title
|
||||||
|
\param QDate date
|
||||||
|
*/
|
||||||
|
static void PrintReport(gGraphView *gv,QString name, QDate date=QDate::currentDate());
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // REPORTS_H
|
918
summary.cpp
Normal file
918
summary.cpp
Normal file
@ -0,0 +1,918 @@
|
|||||||
|
/*
|
||||||
|
Summary Module
|
||||||
|
Copyright (c)2013 Mark Watkins <jedimark@users.sourceforge.net>
|
||||||
|
License: GPL3
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include "mainwindow.h"
|
||||||
|
#include "summary.h"
|
||||||
|
#include "SleepLib/schema.h"
|
||||||
|
|
||||||
|
|
||||||
|
extern MainWindow *mainwin;
|
||||||
|
|
||||||
|
|
||||||
|
Summary::Summary(QObject *parent) :
|
||||||
|
QObject(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString htmlHeader()
|
||||||
|
{
|
||||||
|
|
||||||
|
// "a:link,a:visited { color: '#000020'; text-decoration: none; font-weight: bold;}"
|
||||||
|
// "a:hover { background-color: inherit; color: red; text-decoration:none; font-weight: bold; }"
|
||||||
|
return QString("<html><head>"
|
||||||
|
"</head>"
|
||||||
|
"<style type='text/css'>"
|
||||||
|
"<!--h1,p,a,td,body { font-family: 'FreeSans', 'Sans Serif' } --/>"
|
||||||
|
"p,a,td,body { font-size: 14px }"
|
||||||
|
"</style>"
|
||||||
|
"<link rel='stylesheet' type='text/css' href='qrc:/docs/tooltips.css' />"
|
||||||
|
"<script type='text/javascript'>"
|
||||||
|
"function ChangeColor(tableRow, highLight)"
|
||||||
|
"{ tableRow.style.backgroundColor = highLight; }"
|
||||||
|
"function Go(url) { throw(url); }"
|
||||||
|
"</script>"
|
||||||
|
"</head>"
|
||||||
|
"<body leftmargin=0 topmargin=0 rightmargin=0>"
|
||||||
|
"<div align=center><table cellpadding=3 cellspacing=0 border=0>"
|
||||||
|
"<tr><td><img src='qrc:/icons/bob-v3.0.png' width=140px height=140px><td valign=center align=center><h1>"+
|
||||||
|
QObject::tr("SleepyHead")+" v"+VersionString+"</h1><i>"+
|
||||||
|
QObject::tr("This is a beta software and some functionality may not work as intended yet.")+"<br/>"+
|
||||||
|
QObject::tr("Please report any bugs you find to SleepyHead's SourceForge page.")+
|
||||||
|
"</i></td></tr></table>"
|
||||||
|
"</div>"
|
||||||
|
"<hr/>");
|
||||||
|
}
|
||||||
|
QString htmlFooter()
|
||||||
|
{
|
||||||
|
return QString("</body></html>");
|
||||||
|
}
|
||||||
|
|
||||||
|
QString formatTime(float time)
|
||||||
|
{
|
||||||
|
int hours=time;
|
||||||
|
int seconds=time*3600.0;
|
||||||
|
int minutes=(seconds / 60) % 60;
|
||||||
|
seconds %= 60;
|
||||||
|
return QString().sprintf("%02i:%02i",hours,minutes); //,seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EventDataType calcAHI(QDate start, QDate end)
|
||||||
|
{
|
||||||
|
EventDataType val=(p_profile->calcCount(CPAP_Obstructive,MT_CPAP,start,end)
|
||||||
|
+p_profile->calcCount(CPAP_Hypopnea,MT_CPAP,start,end)
|
||||||
|
+p_profile->calcCount(CPAP_ClearAirway,MT_CPAP,start,end)
|
||||||
|
+p_profile->calcCount(CPAP_Apnea,MT_CPAP,start,end));
|
||||||
|
if (PROFILE.general->calculateRDI())
|
||||||
|
val+=p_profile->calcCount(CPAP_RERA,MT_CPAP,start,end);
|
||||||
|
EventDataType hours=p_profile->calcHours(MT_CPAP,start,end);
|
||||||
|
|
||||||
|
if (hours>0)
|
||||||
|
val/=hours;
|
||||||
|
else
|
||||||
|
val=0;
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
EventDataType calcFL(QDate start, QDate end)
|
||||||
|
{
|
||||||
|
EventDataType val=(p_profile->calcCount(CPAP_FlowLimit,MT_CPAP,start,end));
|
||||||
|
EventDataType hours=p_profile->calcHours(MT_CPAP,start,end);
|
||||||
|
|
||||||
|
if (hours>0)
|
||||||
|
val/=hours;
|
||||||
|
else
|
||||||
|
val=0;
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct RXChange
|
||||||
|
{
|
||||||
|
RXChange() { highlight=0; machine=NULL; }
|
||||||
|
RXChange(const RXChange & copy) {
|
||||||
|
first=copy.first;
|
||||||
|
last=copy.last;
|
||||||
|
days=copy.days;
|
||||||
|
ahi=copy.ahi;
|
||||||
|
fl=copy.fl;
|
||||||
|
mode=copy.mode;
|
||||||
|
min=copy.min;
|
||||||
|
max=copy.max;
|
||||||
|
maxhi=copy.maxhi;
|
||||||
|
machine=copy.machine;
|
||||||
|
per1=copy.per1;
|
||||||
|
per2=copy.per2;
|
||||||
|
highlight=copy.highlight;
|
||||||
|
weighted=copy.weighted;
|
||||||
|
prelief=copy.prelief;
|
||||||
|
prelset=copy.prelset;
|
||||||
|
}
|
||||||
|
QDate first;
|
||||||
|
QDate last;
|
||||||
|
int days;
|
||||||
|
EventDataType ahi;
|
||||||
|
EventDataType fl;
|
||||||
|
CPAPMode mode;
|
||||||
|
EventDataType min;
|
||||||
|
EventDataType max;
|
||||||
|
EventDataType maxhi;
|
||||||
|
EventDataType per1;
|
||||||
|
EventDataType per2;
|
||||||
|
EventDataType weighted;
|
||||||
|
PRTypes prelief;
|
||||||
|
Machine * machine;
|
||||||
|
short prelset;
|
||||||
|
short highlight;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum RXSortMode { RX_first, RX_last, RX_days, RX_ahi, RX_mode, RX_min, RX_max, RX_maxhi, RX_per1, RX_per2, RX_weighted };
|
||||||
|
RXSortMode RXsort=RX_first;
|
||||||
|
bool RXorder=false;
|
||||||
|
|
||||||
|
bool operator<(const RXChange & c1, const RXChange & c2) {
|
||||||
|
const RXChange * comp1=&c1;
|
||||||
|
const RXChange * comp2=&c2;
|
||||||
|
if (RXorder) {
|
||||||
|
switch (RXsort) {
|
||||||
|
case RX_ahi: return comp1->ahi < comp2->ahi;
|
||||||
|
case RX_days: return comp1->days < comp2->days;
|
||||||
|
case RX_first: return comp1->first < comp2->first;
|
||||||
|
case RX_last: return comp1->last < comp2->last;
|
||||||
|
case RX_mode: return comp1->mode < comp2->mode;
|
||||||
|
case RX_min: return comp1->min < comp2->min;
|
||||||
|
case RX_max: return comp1->max < comp2->max;
|
||||||
|
case RX_maxhi: return comp1->maxhi < comp2->maxhi;
|
||||||
|
case RX_per1: return comp1->per1 < comp2->per1;
|
||||||
|
case RX_per2: return comp1->per2 < comp2->per2;
|
||||||
|
case RX_weighted: return comp1->weighted < comp2->weighted;
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
switch (RXsort) {
|
||||||
|
case RX_ahi: return comp1->ahi > comp2->ahi;
|
||||||
|
case RX_days: return comp1->days > comp2->days;
|
||||||
|
case RX_first: return comp1->first > comp2->first;
|
||||||
|
case RX_last: return comp1->last > comp2->last;
|
||||||
|
case RX_mode: return comp1->mode > comp2->mode;
|
||||||
|
case RX_min: return comp1->min > comp2->min;
|
||||||
|
case RX_max: return comp1->max > comp2->max;
|
||||||
|
case RX_maxhi: return comp1->maxhi > comp2->maxhi;
|
||||||
|
case RX_per1: return comp1->per1 > comp2->per1;
|
||||||
|
case RX_per2: return comp1->per2 > comp2->per2;
|
||||||
|
case RX_weighted: return comp1->weighted > comp2->weighted;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RXSort(const RXChange * comp1, const RXChange * comp2) {
|
||||||
|
if (RXorder) {
|
||||||
|
switch (RXsort) {
|
||||||
|
case RX_ahi: return comp1->ahi < comp2->ahi;
|
||||||
|
case RX_days: return comp1->days < comp2->days;
|
||||||
|
case RX_first: return comp1->first < comp2->first;
|
||||||
|
case RX_last: return comp1->last < comp2->last;
|
||||||
|
case RX_mode: return comp1->mode < comp2->mode;
|
||||||
|
case RX_min: return comp1->min < comp2->min;
|
||||||
|
case RX_max: return comp1->max < comp2->max;
|
||||||
|
case RX_maxhi: return comp1->maxhi < comp2->maxhi;
|
||||||
|
case RX_per1: return comp1->per1 < comp2->per1;
|
||||||
|
case RX_per2: return comp1->per2 < comp2->per2;
|
||||||
|
case RX_weighted: return comp1->weighted < comp2->weighted;
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
switch (RXsort) {
|
||||||
|
case RX_ahi: return comp1->ahi > comp2->ahi;
|
||||||
|
case RX_days: return comp1->days > comp2->days;
|
||||||
|
case RX_first: return comp1->first > comp2->first;
|
||||||
|
case RX_last: return comp1->last > comp2->last;
|
||||||
|
case RX_mode: return comp1->mode > comp2->mode;
|
||||||
|
case RX_min: return comp1->min > comp2->min;
|
||||||
|
case RX_max: return comp1->max > comp2->max;
|
||||||
|
case RX_maxhi: return comp1->maxhi > comp2->maxhi;
|
||||||
|
case RX_per1: return comp1->per1 > comp2->per1;
|
||||||
|
case RX_per2: return comp1->per2 > comp2->per2;
|
||||||
|
case RX_weighted: return comp1->weighted > comp2->weighted;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
struct UsageData {
|
||||||
|
UsageData() { ahi=0; hours=0; }
|
||||||
|
UsageData(QDate d, EventDataType v, EventDataType h) { date=d; ahi=v; hours=h; }
|
||||||
|
UsageData(const UsageData & copy) { date=copy.date; ahi=copy.ahi; hours=copy.hours; }
|
||||||
|
QDate date;
|
||||||
|
EventDataType ahi;
|
||||||
|
EventDataType hours;
|
||||||
|
};
|
||||||
|
bool operator <(const UsageData & c1, const UsageData & c2)
|
||||||
|
{
|
||||||
|
if (c1.ahi < c2.ahi)
|
||||||
|
return true;
|
||||||
|
if ((c1.ahi == c2.ahi) && (c1.date > c2.date)) return true;
|
||||||
|
return false;
|
||||||
|
//return c1.value < c2.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Summary::GenerateHTML()
|
||||||
|
{
|
||||||
|
QString html=htmlHeader();
|
||||||
|
|
||||||
|
QDate lastcpap=p_profile->LastGoodDay(MT_CPAP);
|
||||||
|
QDate firstcpap=p_profile->FirstGoodDay(MT_CPAP);
|
||||||
|
QDate cpapweek=lastcpap.addDays(-7);
|
||||||
|
QDate cpapmonth=lastcpap.addDays(-30);
|
||||||
|
QDate cpap6month=lastcpap.addMonths(-6);
|
||||||
|
QDate cpapyear=lastcpap.addYears(-12);
|
||||||
|
if (cpapweek<firstcpap) cpapweek=firstcpap;
|
||||||
|
if (cpapmonth<firstcpap) cpapmonth=firstcpap;
|
||||||
|
if (cpap6month<firstcpap) cpap6month=firstcpap;
|
||||||
|
if (cpapyear<firstcpap) cpapyear=firstcpap;
|
||||||
|
|
||||||
|
|
||||||
|
QList<Machine *> cpap_machines=PROFILE.GetMachines(MT_CPAP);
|
||||||
|
QList<Machine *> oximeters=PROFILE.GetMachines(MT_OXIMETER);
|
||||||
|
QList<Machine *> mach;
|
||||||
|
mach.append(cpap_machines);
|
||||||
|
mach.append(oximeters);
|
||||||
|
|
||||||
|
|
||||||
|
if (mach.size()==0) {
|
||||||
|
html+="<table cellpadding=2 cellspacing=0 border=0 width=100% height=60%>";
|
||||||
|
QString datacard;
|
||||||
|
html+="<tr><td align=center><h1>"+tr("Please Import Some Data")+"</h1><i>"+tr("SleepyHead is pretty much useless without it.")+"</i><br/><p>"+tr("It might be a good idea to check preferences first,</br>as there are some options that affect import.")+"</p><p>"+tr("First import can take a few minutes.")+"</p></td></tr></table>";
|
||||||
|
html+=htmlFooter();
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
int cpapdays=PROFILE.countDays(MT_CPAP,firstcpap,lastcpap);
|
||||||
|
int cpapweekdays=PROFILE.countDays(MT_CPAP,cpapweek,lastcpap);
|
||||||
|
int cpapmonthdays=PROFILE.countDays(MT_CPAP,cpapmonth,lastcpap);
|
||||||
|
int cpapyeardays=PROFILE.countDays(MT_CPAP,cpapyear,lastcpap);
|
||||||
|
int cpap6monthdays=PROFILE.countDays(MT_CPAP,cpap6month,lastcpap);
|
||||||
|
|
||||||
|
CPAPMode cpapmode=(CPAPMode)(int)p_profile->calcSettingsMax(CPAP_Mode,MT_CPAP,firstcpap,lastcpap);
|
||||||
|
|
||||||
|
float percentile=PROFILE.general->prefCalcPercentile()/100.0;
|
||||||
|
|
||||||
|
// int mididx=PROFILE.general->prefCalcMiddle();
|
||||||
|
// SummaryType ST_mid;
|
||||||
|
// if (mididx==0) ST_mid=ST_PERC;
|
||||||
|
// if (mididx==1) ST_mid=ST_WAVG;
|
||||||
|
// if (mididx==2) ST_mid=ST_AVG;
|
||||||
|
|
||||||
|
QString ahitxt;
|
||||||
|
if (PROFILE.general->calculateRDI()) {
|
||||||
|
ahitxt=STR_TR_RDI;
|
||||||
|
} else {
|
||||||
|
ahitxt=STR_TR_AHI;
|
||||||
|
}
|
||||||
|
|
||||||
|
int decimals=2;
|
||||||
|
html+="<div align=center>";
|
||||||
|
html+=QString("<table cellpadding=2 cellspacing=0 border=1 width=90%>");
|
||||||
|
if (cpapdays==0) {
|
||||||
|
html+="<tr><td colspan=6 align=center>"+tr("No CPAP Machine Data Imported")+"</td></tr>";
|
||||||
|
} else {
|
||||||
|
html+=QString("<tr><td colspan=6 align=center><b>")+tr("CPAP Statistics as of")+QString(" %1</b></td></tr>").arg(lastcpap.toString(Qt::SystemLocaleLongDate));
|
||||||
|
|
||||||
|
if (cpap_machines.size()>0) {
|
||||||
|
// html+=QString("<tr><td colspan=6 align=center><b>%1</b></td></tr>").arg(tr("CPAP Summary"));
|
||||||
|
|
||||||
|
if (!cpapdays) {
|
||||||
|
html+=QString("<tr><td colspan=6 align=center><b>%1</b></td></tr>").arg(tr("No CPAP data available."));
|
||||||
|
} else if (cpapdays==1) {
|
||||||
|
html+=QString("<tr><td colspan=6 align=center>%1</td></tr>").arg(QString(tr("%1 day of CPAP Data, on %2.")).arg(cpapdays).arg(firstcpap.toString(Qt::SystemLocaleShortDate)));
|
||||||
|
} else {
|
||||||
|
html+=QString("<tr><td colspan=6 align=center>%1</td></tr>").arg(QString(tr("%1 days of CPAP Data, between %2 and %3")).arg(cpapdays).arg(firstcpap.toString(Qt::SystemLocaleShortDate)).arg(lastcpap.toString(Qt::SystemLocaleShortDate)));
|
||||||
|
}
|
||||||
|
|
||||||
|
html+=QString("<tr><td><b>%1</b></td><td><b>%2</b></td><td><b>%3</b></td><td><b>%4</b></td><td><b>%5</b></td><td><b>%6</td></tr>")
|
||||||
|
.arg(tr("Details")).arg(tr("Most Recent")).arg(tr("Last 7 Days")).arg(tr("Last 30 Days")).arg(tr("Last 6 months")).arg(tr("Last Year"));
|
||||||
|
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
|
||||||
|
.arg(ahitxt)
|
||||||
|
.arg(calcAHI(lastcpap,lastcpap),0,'f',decimals)
|
||||||
|
.arg(calcAHI(cpapweek,lastcpap),0,'f',decimals)
|
||||||
|
.arg(calcAHI(cpapmonth,lastcpap),0,'f',decimals)
|
||||||
|
.arg(calcAHI(cpap6month,lastcpap),0,'f',decimals)
|
||||||
|
.arg(calcAHI(cpapyear,lastcpap),0,'f',decimals);
|
||||||
|
|
||||||
|
if (PROFILE.calcCount(CPAP_RERA,MT_CPAP,cpapyear,lastcpap)) {
|
||||||
|
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
|
||||||
|
.arg(tr("RERA Index"))
|
||||||
|
.arg(PROFILE.calcCount(CPAP_RERA,MT_CPAP,lastcpap,lastcpap)/PROFILE.calcHours(MT_CPAP,lastcpap,lastcpap),0,'f',decimals)
|
||||||
|
.arg(PROFILE.calcCount(CPAP_RERA,MT_CPAP,cpapweek,lastcpap)/PROFILE.calcHours(MT_CPAP,cpapweek,lastcpap),0,'f',decimals)
|
||||||
|
.arg(PROFILE.calcCount(CPAP_RERA,MT_CPAP,cpapmonth,lastcpap)/PROFILE.calcHours(MT_CPAP,cpapmonth,lastcpap),0,'f',decimals)
|
||||||
|
.arg(PROFILE.calcCount(CPAP_RERA,MT_CPAP,cpap6month,lastcpap)/PROFILE.calcHours(MT_CPAP,cpap6month,lastcpap),0,'f',decimals)
|
||||||
|
.arg(PROFILE.calcCount(CPAP_RERA,MT_CPAP,cpapyear,lastcpap)/PROFILE.calcHours(MT_CPAP,cpapyear,lastcpap),0,'f',decimals);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PROFILE.calcCount(CPAP_FlowLimit,MT_CPAP,cpapyear,lastcpap)) {
|
||||||
|
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
|
||||||
|
.arg(tr("Flow Limit Index"))
|
||||||
|
.arg(PROFILE.calcCount(CPAP_FlowLimit,MT_CPAP,lastcpap,lastcpap)/PROFILE.calcHours(MT_CPAP,lastcpap,lastcpap),0,'f',decimals)
|
||||||
|
.arg(PROFILE.calcCount(CPAP_FlowLimit,MT_CPAP,cpapweek,lastcpap)/PROFILE.calcHours(MT_CPAP,cpapweek,lastcpap),0,'f',decimals)
|
||||||
|
.arg(PROFILE.calcCount(CPAP_FlowLimit,MT_CPAP,cpapmonth,lastcpap)/PROFILE.calcHours(MT_CPAP,cpapmonth,lastcpap),0,'f',decimals)
|
||||||
|
.arg(PROFILE.calcCount(CPAP_FlowLimit,MT_CPAP,cpap6month,lastcpap)/PROFILE.calcHours(MT_CPAP,cpap6month,lastcpap),0,'f',decimals)
|
||||||
|
.arg(PROFILE.calcCount(CPAP_FlowLimit,MT_CPAP,cpapyear,lastcpap)/PROFILE.calcHours(MT_CPAP,cpapyear,lastcpap),0,'f',decimals);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
|
||||||
|
.arg(tr("Hours per Night"))
|
||||||
|
.arg(formatTime(p_profile->calcHours(MT_CPAP)))
|
||||||
|
.arg(formatTime(p_profile->calcHours(MT_CPAP,cpapweek,lastcpap)/float(cpapweekdays)))
|
||||||
|
.arg(formatTime(p_profile->calcHours(MT_CPAP,cpapmonth,lastcpap)/float(cpapmonthdays)))
|
||||||
|
.arg(formatTime(p_profile->calcHours(MT_CPAP,cpap6month,lastcpap)/float(cpap6monthdays)))
|
||||||
|
.arg(formatTime(p_profile->calcHours(MT_CPAP,cpapyear,lastcpap)/float(cpapyeardays)));
|
||||||
|
|
||||||
|
if (cpapmode>=MODE_BIPAP) {
|
||||||
|
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
|
||||||
|
.arg(tr("Min EPAP"))
|
||||||
|
.arg(p_profile->calcMin(CPAP_EPAP,MT_CPAP),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcMin(CPAP_EPAP,MT_CPAP,cpapweek,lastcpap),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcMin(CPAP_EPAP,MT_CPAP,cpapmonth,lastcpap),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcMin(CPAP_EPAP,MT_CPAP,cpap6month,lastcpap),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcMin(CPAP_EPAP,MT_CPAP,cpapyear,lastcpap),0,'f',decimals);
|
||||||
|
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
|
||||||
|
.arg(QString("%1% "+STR_TR_EPAP).arg(percentile*100.0,0,'f',0))
|
||||||
|
.arg(p_profile->calcPercentile(CPAP_EPAP,percentile,MT_CPAP),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcPercentile(CPAP_EPAP,percentile,MT_CPAP,cpapweek,lastcpap),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcPercentile(CPAP_EPAP,percentile,MT_CPAP,cpapmonth,lastcpap),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcPercentile(CPAP_EPAP,percentile,MT_CPAP,cpap6month,lastcpap),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcPercentile(CPAP_EPAP,percentile,MT_CPAP,cpapyear,lastcpap),0,'f',decimals);
|
||||||
|
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
|
||||||
|
.arg(tr("Max IPAP"))
|
||||||
|
.arg(p_profile->calcMax(CPAP_IPAP,MT_CPAP),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcMax(CPAP_IPAP,MT_CPAP,cpapweek,lastcpap),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcMax(CPAP_IPAP,MT_CPAP,cpapmonth,lastcpap),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcMax(CPAP_IPAP,MT_CPAP,cpap6month,lastcpap),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcMax(CPAP_IPAP,MT_CPAP,cpapyear,lastcpap),0,'f',decimals);
|
||||||
|
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
|
||||||
|
.arg(QString("%1% "+STR_TR_IPAP).arg(percentile*100.0,0,'f',0))
|
||||||
|
.arg(p_profile->calcPercentile(CPAP_IPAP,percentile,MT_CPAP),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcPercentile(CPAP_IPAP,percentile,MT_CPAP,cpapweek,lastcpap),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcPercentile(CPAP_IPAP,percentile,MT_CPAP,cpapmonth,lastcpap),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcPercentile(CPAP_IPAP,percentile,MT_CPAP,cpap6month,lastcpap),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcPercentile(CPAP_IPAP,percentile,MT_CPAP,cpapyear,lastcpap),0,'f',decimals);
|
||||||
|
} else if (cpapmode>=MODE_APAP) {
|
||||||
|
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
|
||||||
|
.arg(tr("Average Pressure"))
|
||||||
|
.arg(p_profile->calcWavg(CPAP_Pressure,MT_CPAP),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcWavg(CPAP_Pressure,MT_CPAP,cpapweek,lastcpap),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcWavg(CPAP_Pressure,MT_CPAP,cpapmonth,lastcpap),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcWavg(CPAP_Pressure,MT_CPAP,cpap6month,lastcpap),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcWavg(CPAP_Pressure,MT_CPAP,cpapyear,lastcpap),0,'f',decimals);
|
||||||
|
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
|
||||||
|
.arg(tr("%1% Pressure").arg(percentile*100.0,0,'f',0))
|
||||||
|
.arg(p_profile->calcPercentile(CPAP_Pressure,percentile,MT_CPAP),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcPercentile(CPAP_Pressure,percentile,MT_CPAP,cpapweek,lastcpap),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcPercentile(CPAP_Pressure,percentile,MT_CPAP,cpapmonth,lastcpap),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcPercentile(CPAP_Pressure,percentile,MT_CPAP,cpap6month,lastcpap),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcPercentile(CPAP_Pressure,percentile,MT_CPAP,cpapyear,lastcpap),0,'f',decimals);
|
||||||
|
} else {
|
||||||
|
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
|
||||||
|
.arg(tr("Pressure"))
|
||||||
|
.arg(p_profile->calcSettingsMin(CPAP_Pressure,MT_CPAP),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcSettingsMin(CPAP_Pressure,MT_CPAP,cpapweek,lastcpap),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcSettingsMin(CPAP_Pressure,MT_CPAP,cpapmonth,lastcpap),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcSettingsMin(CPAP_Pressure,MT_CPAP,cpap6month,lastcpap),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcSettingsMin(CPAP_Pressure,MT_CPAP,cpapyear,lastcpap),0,'f',decimals);
|
||||||
|
}
|
||||||
|
//html+="<tr><td colspan=6>TODO: 90% pressure.. Any point showing if this is all CPAP?</td></tr>";
|
||||||
|
|
||||||
|
|
||||||
|
ChannelID leak;
|
||||||
|
if (p_profile->calcCount(CPAP_LeakTotal,MT_CPAP,cpapyear,lastcpap)>0) {
|
||||||
|
leak=CPAP_LeakTotal;
|
||||||
|
} else leak=CPAP_Leak;
|
||||||
|
|
||||||
|
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
|
||||||
|
.arg(tr("Average %1").arg(schema::channel[leak].label()))
|
||||||
|
.arg(p_profile->calcWavg(leak,MT_CPAP),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcWavg(leak,MT_CPAP,cpapweek,lastcpap),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcWavg(leak,MT_CPAP,cpapmonth,lastcpap),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcWavg(leak,MT_CPAP,cpap6month,lastcpap),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcWavg(leak,MT_CPAP,cpapyear,lastcpap),0,'f',decimals);
|
||||||
|
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
|
||||||
|
.arg(tr("%1% %2").arg(percentile*100.0f,0,'f',0).arg(schema::channel[leak].label()))
|
||||||
|
.arg(p_profile->calcPercentile(leak,percentile,MT_CPAP),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcPercentile(leak,percentile,MT_CPAP,cpapweek,lastcpap),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcPercentile(leak,percentile,MT_CPAP,cpapmonth,lastcpap),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcPercentile(leak,percentile,MT_CPAP,cpap6month,lastcpap),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcPercentile(leak,percentile,MT_CPAP,cpapyear,lastcpap),0,'f',decimals);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int oxisize=oximeters.size();
|
||||||
|
if (oxisize>0) {
|
||||||
|
QDate lastoxi=p_profile->LastGoodDay(MT_OXIMETER);
|
||||||
|
QDate firstoxi=p_profile->FirstGoodDay(MT_OXIMETER);
|
||||||
|
int days=PROFILE.countDays(MT_OXIMETER,firstoxi,lastoxi);
|
||||||
|
if (days>0) {
|
||||||
|
html+=QString("<tr><td colspan=6 align=center><b>%1</b></td></tr>").arg(tr("Oximetry Summary"));
|
||||||
|
if (days==1) {
|
||||||
|
html+=QString("<tr><td colspan=6 align=center>%1</td></tr>").arg(QString(tr("%1 day of Oximetry Data, on %2.")).arg(days).arg(firstoxi.toString(Qt::SystemLocaleShortDate)));
|
||||||
|
} else {
|
||||||
|
html+=QString("<tr><td colspan=6 align=center>%1</td></tr>").arg(QString(tr("%1 days of Oximetry Data, between %2 and %3")).arg(days).arg(firstoxi.toString(Qt::SystemLocaleShortDate)).arg(lastoxi.toString(Qt::SystemLocaleShortDate)));
|
||||||
|
}
|
||||||
|
|
||||||
|
html+=QString("<tr><td><b>%1</b></td><td><b>%2</b></td><td><b>%3</b></td><td><b>%4</b></td><td><b>%5</b></td><td><b>%6</td></tr>")
|
||||||
|
.arg(tr("Details")).arg(tr("Most Recent")).arg(tr("Last 7 Days")).arg(tr("Last 30 Days")).arg(tr("Last 6 months")).arg(tr("Last Year"));
|
||||||
|
QDate oxiweek=lastoxi.addDays(-7);
|
||||||
|
QDate oximonth=lastoxi.addDays(-30);
|
||||||
|
QDate oxi6month=lastoxi.addMonths(-6);
|
||||||
|
QDate oxiyear=lastoxi.addYears(-12);
|
||||||
|
if (oxiweek<firstoxi) oxiweek=firstoxi;
|
||||||
|
if (oximonth<firstoxi) oximonth=firstoxi;
|
||||||
|
if (oxi6month<firstoxi) oxi6month=firstoxi;
|
||||||
|
if (oxiyear<firstoxi) oxiyear=firstoxi;
|
||||||
|
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
|
||||||
|
.arg(tr("Average SpO2"))
|
||||||
|
.arg(p_profile->calcWavg(OXI_SPO2,MT_OXIMETER),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcWavg(OXI_SPO2,MT_OXIMETER,oxiweek,lastoxi),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcWavg(OXI_SPO2,MT_OXIMETER,oximonth,lastoxi),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcWavg(OXI_SPO2,MT_OXIMETER,oxi6month,lastoxi),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcWavg(OXI_SPO2,MT_OXIMETER,oxiyear,lastoxi),0,'f',decimals);
|
||||||
|
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
|
||||||
|
.arg(tr("Minimum SpO2"))
|
||||||
|
.arg(p_profile->calcMin(OXI_SPO2,MT_OXIMETER),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcMin(OXI_SPO2,MT_OXIMETER,oxiweek,lastoxi),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcMin(OXI_SPO2,MT_OXIMETER,oximonth,lastoxi),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcMin(OXI_SPO2,MT_OXIMETER,oxi6month,lastoxi),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcMin(OXI_SPO2,MT_OXIMETER,oxiyear,lastoxi),0,'f',decimals);
|
||||||
|
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
|
||||||
|
.arg(tr("SpO2 Events / Hour"))
|
||||||
|
.arg(p_profile->calcCount(OXI_SPO2Drop,MT_OXIMETER)/p_profile->calcHours(MT_OXIMETER),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcCount(OXI_SPO2Drop,MT_OXIMETER,oxiweek,lastoxi)/p_profile->calcHours(MT_OXIMETER,oxiweek,lastoxi),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcCount(OXI_SPO2Drop,MT_OXIMETER,oximonth,lastoxi)/p_profile->calcHours(MT_OXIMETER,oximonth,lastoxi),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcCount(OXI_SPO2Drop,MT_OXIMETER,oxi6month,lastoxi)/p_profile->calcHours(MT_OXIMETER,oxi6month,lastoxi),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcCount(OXI_SPO2Drop,MT_OXIMETER,oxiyear,lastoxi)/p_profile->calcHours(MT_OXIMETER,oxiyear,lastoxi),0,'f',decimals);
|
||||||
|
html+=QString("<tr><td>%1</td><td>%2\%</td><td>%3\%</td><td>%4\%</td><td>%5\%</td><td>%6\%</td></tr>")
|
||||||
|
.arg(tr("% of time in SpO2 Events"))
|
||||||
|
.arg(100.0/p_profile->calcHours(MT_OXIMETER)*p_profile->calcSum(OXI_SPO2Drop,MT_OXIMETER)/3600.0,0,'f',decimals)
|
||||||
|
.arg(100.0/p_profile->calcHours(MT_OXIMETER,oxiweek,lastoxi)*p_profile->calcSum(OXI_SPO2Drop,MT_OXIMETER,oxiweek,lastoxi)/3600.0,0,'f',decimals)
|
||||||
|
.arg(100.0/p_profile->calcHours(MT_OXIMETER,oximonth,lastoxi)*p_profile->calcSum(OXI_SPO2Drop,MT_OXIMETER,oximonth,lastoxi)/3600.0,0,'f',decimals)
|
||||||
|
.arg(100.0/p_profile->calcHours(MT_OXIMETER,oxi6month,lastoxi)*p_profile->calcSum(OXI_SPO2Drop,MT_OXIMETER,oxi6month,lastoxi)/3600.0,0,'f',decimals)
|
||||||
|
.arg(100.0/p_profile->calcHours(MT_OXIMETER,oxiyear,lastoxi)*p_profile->calcSum(OXI_SPO2Drop,MT_OXIMETER,oxiyear,lastoxi)/3600.0,0,'f',decimals);
|
||||||
|
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
|
||||||
|
.arg(tr("Average Pulse Rate"))
|
||||||
|
.arg(p_profile->calcWavg(OXI_Pulse,MT_OXIMETER),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcWavg(OXI_Pulse,MT_OXIMETER,oxiweek,lastoxi),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcWavg(OXI_Pulse,MT_OXIMETER,oximonth,lastoxi),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcWavg(OXI_Pulse,MT_OXIMETER,oxi6month,lastoxi),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcWavg(OXI_Pulse,MT_OXIMETER,oxiyear,lastoxi),0,'f',decimals);
|
||||||
|
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
|
||||||
|
.arg(tr("Minimum Pulse Rate"))
|
||||||
|
.arg(p_profile->calcMin(OXI_Pulse,MT_OXIMETER),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcMin(OXI_Pulse,MT_OXIMETER,oxiweek,lastoxi),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcMin(OXI_Pulse,MT_OXIMETER,oximonth,lastoxi),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcMin(OXI_Pulse,MT_OXIMETER,oxi6month,lastoxi),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcMin(OXI_Pulse,MT_OXIMETER,oxiyear,lastoxi),0,'f',decimals);
|
||||||
|
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
|
||||||
|
.arg(tr("Maximum Pulse Rate"))
|
||||||
|
.arg(p_profile->calcMax(OXI_Pulse,MT_OXIMETER),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcMax(OXI_Pulse,MT_OXIMETER,oxiweek,lastoxi),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcMax(OXI_Pulse,MT_OXIMETER,oximonth,lastoxi),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcMax(OXI_Pulse,MT_OXIMETER,oxi6month,lastoxi),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcMax(OXI_Pulse,MT_OXIMETER,oxiyear,lastoxi),0,'f',decimals);
|
||||||
|
html+=QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td><td>%5</td><td>%6</td></tr>")
|
||||||
|
.arg(tr("Pulse Change Events / Hour"))
|
||||||
|
.arg(p_profile->calcCount(OXI_PulseChange,MT_OXIMETER)/p_profile->calcHours(MT_OXIMETER),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcCount(OXI_PulseChange,MT_OXIMETER,oxiweek,lastoxi)/p_profile->calcHours(MT_OXIMETER,oxiweek,lastoxi),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcCount(OXI_PulseChange,MT_OXIMETER,oximonth,lastoxi)/p_profile->calcHours(MT_OXIMETER,oximonth,lastoxi),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcCount(OXI_PulseChange,MT_OXIMETER,oxi6month,lastoxi)/p_profile->calcHours(MT_OXIMETER,oxi6month,lastoxi),0,'f',decimals)
|
||||||
|
.arg(p_profile->calcCount(OXI_PulseChange,MT_OXIMETER,oxiyear,lastoxi)/p_profile->calcHours(MT_OXIMETER,oxiyear,lastoxi),0,'f',decimals);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
html+="</table>";
|
||||||
|
html+="</div>";
|
||||||
|
|
||||||
|
QList<UsageData> AHI;
|
||||||
|
|
||||||
|
//QDate bestAHIdate, worstAHIdate;
|
||||||
|
//EventDataType bestAHI=999.0, worstAHI=0;
|
||||||
|
if (cpapdays>0) {
|
||||||
|
QDate first,last=lastcpap;
|
||||||
|
CPAPMode mode=MODE_UNKNOWN,cmode=MODE_UNKNOWN;
|
||||||
|
EventDataType cmin=0,cmax=0,cmaxhi=0, min=0,max=0,maxhi=0;
|
||||||
|
Machine *mach=NULL,*lastmach=NULL;
|
||||||
|
PRTypes lastpr=PR_UNKNOWN, prelief=PR_UNKNOWN;
|
||||||
|
short prelset=0, lastprelset=-1;
|
||||||
|
QDate date=lastcpap;
|
||||||
|
Day * day;
|
||||||
|
bool lastchanged=false;
|
||||||
|
QVector<RXChange> rxchange;
|
||||||
|
EventDataType hours;
|
||||||
|
|
||||||
|
int compliant=0;
|
||||||
|
do {
|
||||||
|
day=PROFILE.GetGoodDay(date,MT_CPAP);
|
||||||
|
|
||||||
|
if (day) {
|
||||||
|
lastchanged=false;
|
||||||
|
|
||||||
|
hours=day->hours();
|
||||||
|
|
||||||
|
if (hours > PROFILE.cpap->complianceHours())
|
||||||
|
compliant++;
|
||||||
|
|
||||||
|
EventDataType ahi=day->count(CPAP_Obstructive)+day->count(CPAP_Hypopnea)+day->count(CPAP_Apnea)+day->count(CPAP_ClearAirway);
|
||||||
|
if (PROFILE.general->calculateRDI()) ahi+=day->count(CPAP_RERA);
|
||||||
|
ahi/=hours;
|
||||||
|
AHI.push_back(UsageData(date,ahi,hours));
|
||||||
|
|
||||||
|
prelief=(PRTypes)(int)round(day->settings_wavg(CPAP_PresReliefType));
|
||||||
|
prelset=round(day->settings_wavg(CPAP_PresReliefSet));
|
||||||
|
mode=(CPAPMode)(int)round(day->settings_wavg(CPAP_Mode));
|
||||||
|
mach=day->machine;
|
||||||
|
if (mode>=MODE_ASV) {
|
||||||
|
min=day->settings_min(CPAP_EPAP);
|
||||||
|
max=day->settings_max(CPAP_IPAPLo);
|
||||||
|
maxhi=day->settings_max(CPAP_IPAPHi);
|
||||||
|
} else if (mode>=MODE_BIPAP) {
|
||||||
|
min=day->settings_min(CPAP_EPAP);
|
||||||
|
max=day->settings_max(CPAP_IPAP);
|
||||||
|
} else if (mode>=MODE_APAP) {
|
||||||
|
min=day->settings_min(CPAP_PressureMin);
|
||||||
|
max=day->settings_max(CPAP_PressureMax);
|
||||||
|
} else {
|
||||||
|
min=day->settings_min(CPAP_Pressure);
|
||||||
|
}
|
||||||
|
if ((mode!=cmode) || (min!=cmin) || (max!=cmax) || (mach!=lastmach) || (prelset!=lastprelset)) {
|
||||||
|
if ((cmode!=MODE_UNKNOWN) && (lastmach!=NULL)) {
|
||||||
|
first=date.addDays(1);
|
||||||
|
int days=PROFILE.countDays(MT_CPAP,first,last);
|
||||||
|
RXChange rx;
|
||||||
|
rx.first=first;
|
||||||
|
rx.last=last;
|
||||||
|
rx.days=days;
|
||||||
|
rx.ahi=calcAHI(first,last);
|
||||||
|
rx.fl=calcFL(first,last);
|
||||||
|
rx.mode=cmode;
|
||||||
|
rx.min=cmin;
|
||||||
|
rx.max=cmax;
|
||||||
|
rx.maxhi=cmaxhi;
|
||||||
|
rx.prelief=lastpr;
|
||||||
|
rx.prelset=lastprelset;
|
||||||
|
rx.machine=lastmach;
|
||||||
|
|
||||||
|
if (mode<MODE_BIPAP) {
|
||||||
|
rx.per1=p_profile->calcPercentile(CPAP_Pressure,percentile,MT_CPAP,first,last);
|
||||||
|
rx.per2=0;
|
||||||
|
} else if (mode<MODE_ASV) {
|
||||||
|
rx.per1=p_profile->calcPercentile(CPAP_EPAP,percentile,MT_CPAP,first,last);
|
||||||
|
rx.per2=p_profile->calcPercentile(CPAP_IPAP,percentile,MT_CPAP,first,last);
|
||||||
|
} else {
|
||||||
|
rx.per1=p_profile->calcPercentile(CPAP_EPAP,percentile,MT_CPAP,first,last);
|
||||||
|
rx.per2=p_profile->calcPercentile(CPAP_IPAP,percentile,MT_CPAP,first,last);
|
||||||
|
}
|
||||||
|
rx.weighted=float(rx.days)/float(cpapdays)*rx.ahi;
|
||||||
|
rxchange.push_back(rx);
|
||||||
|
}
|
||||||
|
cmode=mode;
|
||||||
|
cmin=min;
|
||||||
|
cmax=max;
|
||||||
|
cmaxhi=maxhi;
|
||||||
|
lastpr=prelief;
|
||||||
|
lastprelset=prelset;
|
||||||
|
last=date;
|
||||||
|
lastmach=mach;
|
||||||
|
lastchanged=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
date=date.addDays(-1);
|
||||||
|
} while (date>=firstcpap);
|
||||||
|
|
||||||
|
// Sort list by AHI
|
||||||
|
qSort(AHI);
|
||||||
|
|
||||||
|
lastchanged=false;
|
||||||
|
if (!lastchanged && (mach!=NULL)) {
|
||||||
|
// last=date.addDays(1);
|
||||||
|
first=firstcpap;
|
||||||
|
int days=PROFILE.countDays(MT_CPAP,first,last);
|
||||||
|
RXChange rx;
|
||||||
|
rx.first=first;
|
||||||
|
rx.last=last;
|
||||||
|
rx.days=days;
|
||||||
|
rx.ahi=calcAHI(first,last);
|
||||||
|
rx.fl=calcFL(first,last);
|
||||||
|
rx.mode=mode;
|
||||||
|
rx.min=min;
|
||||||
|
rx.max=max;
|
||||||
|
rx.maxhi=maxhi;
|
||||||
|
rx.prelief=prelief;
|
||||||
|
rx.prelset=prelset;
|
||||||
|
rx.machine=mach;
|
||||||
|
if (mode<MODE_BIPAP) {
|
||||||
|
rx.per1=p_profile->calcPercentile(CPAP_Pressure,percentile,MT_CPAP,first,last);
|
||||||
|
rx.per2=0;
|
||||||
|
} else if (mode<MODE_ASV) {
|
||||||
|
rx.per1=p_profile->calcPercentile(CPAP_EPAP,percentile,MT_CPAP,first,last);
|
||||||
|
rx.per2=p_profile->calcPercentile(CPAP_IPAP,percentile,MT_CPAP,first,last);
|
||||||
|
} else {
|
||||||
|
rx.per1=p_profile->calcPercentile(CPAP_EPAP,percentile,MT_CPAP,first,last);
|
||||||
|
rx.per2=p_profile->calcPercentile(CPAP_IPAPHi,percentile,MT_CPAP,first,last);
|
||||||
|
}
|
||||||
|
rx.weighted=float(rx.days)/float(cpapdays);
|
||||||
|
//rx.weighted=float(days)*rx.ahi;
|
||||||
|
rxchange.push_back(rx);
|
||||||
|
}
|
||||||
|
|
||||||
|
int rxthresh=5;
|
||||||
|
QVector<RXChange *> tmpRX;
|
||||||
|
for (int i=0;i<rxchange.size();i++) {
|
||||||
|
RXChange & rx=rxchange[i];
|
||||||
|
if (rx.days>rxthresh)
|
||||||
|
tmpRX.push_back(&rx);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString recbox="<html><head><style type='text/css'>"
|
||||||
|
"p,a,td,body { font-family: '"+QApplication::font().family()+"'; }"
|
||||||
|
"p,a,td,body { font-size: "+QString::number(QApplication::font().pointSize() + 2)+"px; }"
|
||||||
|
"a:link,a:visited { color: inherit; text-decoration: none; }" //font-weight: normal;
|
||||||
|
"a:hover { background-color: inherit; color: white; text-decoration:none; font-weight: bold; }"
|
||||||
|
"</style></head><body>";
|
||||||
|
recbox+="<table width=100% cellpadding=1 cellspacing=0>";
|
||||||
|
int numdays=AHI.size();
|
||||||
|
if (numdays>1) {
|
||||||
|
int z=numdays/2;
|
||||||
|
if (z>4) z=4;
|
||||||
|
|
||||||
|
recbox+=QString("<tr><td colspan=2 align=center><b>%1</b></td></tr>").arg(tr("Usage Information"));
|
||||||
|
recbox+=QString("<tr><td>%1</td><td align=right>%2</td></tr>").arg(tr("Total Days")).arg(numdays);
|
||||||
|
if (PROFILE.cpap->showComplianceInfo()) {
|
||||||
|
recbox+=QString("<tr><td>%1</td><td align=right>%2</td></tr>").arg(tr("Compliant Days")).arg(compliant);
|
||||||
|
}
|
||||||
|
int highahi=0;
|
||||||
|
for (int i=0;i<numdays;i++) {
|
||||||
|
if (AHI.at(i).ahi > 5.0)
|
||||||
|
highahi++;
|
||||||
|
}
|
||||||
|
recbox+=QString("<tr><td>%1</td><td align=right>%2</td></tr>").arg(tr("Days AHI >5.0")).arg(highahi);
|
||||||
|
|
||||||
|
|
||||||
|
recbox+=QString("<tr><td colspan=2> </td></tr>");
|
||||||
|
recbox+=QString("<tr><td colspan=2 align=center><b>%1</b></td></tr>").arg(tr("Best %1").arg(ahitxt));
|
||||||
|
for (int i=0;i<z;i++) {
|
||||||
|
const UsageData & a=AHI.at(i);
|
||||||
|
recbox+=QString("<tr><td><a href='daily=%1'>%2</a></td><td align=right>%3</td></tr>")
|
||||||
|
.arg(a.date.toString(Qt::ISODate))
|
||||||
|
.arg(a.date.toString(Qt::SystemLocaleShortDate))
|
||||||
|
.arg(a.ahi,0,'f',decimals);
|
||||||
|
}
|
||||||
|
recbox+=QString("<tr><td colspan=2> </td></tr>");
|
||||||
|
recbox+=QString("<tr><td colspan=2 align=center><b>%1</b></td></tr>").arg(tr("Worst %1").arg(ahitxt));
|
||||||
|
for (int i=0;i<z;i++) {
|
||||||
|
const UsageData & a=AHI.at((numdays-1)-i);
|
||||||
|
recbox+=QString("<tr><td><a href='daily=%1'>%2</a></td><td align=right>%3</td></tr>")
|
||||||
|
.arg(a.date.toString(Qt::ISODate))
|
||||||
|
.arg(a.date.toString(Qt::SystemLocaleShortDate))
|
||||||
|
.arg(a.ahi,0,'f',decimals);
|
||||||
|
}
|
||||||
|
recbox+=QString("<tr><td colspan=2> </td></tr>");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (tmpRX.size()>0) {
|
||||||
|
RXsort=RX_ahi;
|
||||||
|
QString minstr,maxstr,modestr,maxhistr;
|
||||||
|
qSort(tmpRX.begin(),tmpRX.end(),RXSort);
|
||||||
|
tmpRX[0]->highlight=4; // worst
|
||||||
|
int ls=tmpRX.size()-1;
|
||||||
|
tmpRX[ls]->highlight=1; //best
|
||||||
|
CPAPMode mode=(CPAPMode)(int)PROFILE.calcSettingsMax(CPAP_Mode,MT_CPAP,tmpRX[ls]->first,tmpRX[ls]->last);
|
||||||
|
|
||||||
|
if (mode<MODE_APAP) { // is CPAP?
|
||||||
|
minstr=STR_TR_Pressure;
|
||||||
|
maxstr="";
|
||||||
|
modestr=STR_TR_CPAP;
|
||||||
|
} else if (mode<MODE_BIPAP) { // is AUTO?
|
||||||
|
minstr=STR_TR_Min;
|
||||||
|
maxstr=STR_TR_Max;
|
||||||
|
modestr=STR_TR_APAP;
|
||||||
|
} else if (mode<MODE_ASV) { // BIPAP
|
||||||
|
minstr=STR_TR_EPAP;
|
||||||
|
maxstr=STR_TR_IPAP;
|
||||||
|
modestr=STR_TR_BiLevel;
|
||||||
|
} else {
|
||||||
|
minstr=STR_TR_EPAP;
|
||||||
|
maxstr=STR_TR_IPAPLo;
|
||||||
|
maxhistr=STR_TR_IPAPHi;
|
||||||
|
modestr=STR_TR_STASV;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
recbox+=QString("<tr><td colspan=2><table width=100% border=0 cellpadding=1 cellspacing=0><tr><td colspan=2 align=center><b>%3</b></td></tr>")
|
||||||
|
.arg(tr("Best RX Setting"));
|
||||||
|
recbox+=QString("<tr><td valign=top>")+STR_TR_Start+"<br/>"+STR_TR_End+QString("</td><td align=right><a href='overview=%1,%2'>%3<br/>%4</a></td></tr>")
|
||||||
|
.arg(tmpRX[ls]->first.toString(Qt::ISODate))
|
||||||
|
.arg(tmpRX[ls]->last.toString(Qt::ISODate))
|
||||||
|
.arg(tmpRX[ls]->first.toString(Qt::SystemLocaleShortDate))
|
||||||
|
.arg(tmpRX[ls]->last.toString(Qt::SystemLocaleShortDate));
|
||||||
|
recbox+=QString("<tr><td><b>%1</b></td><td align=right><b>%2</b></td></tr>").arg(ahitxt).arg(tmpRX[ls]->ahi,0,'f',decimals);
|
||||||
|
recbox+=QString("<tr><td>%1</td><td align=right>%2</td></tr>").arg(STR_TR_Mode).arg(modestr);
|
||||||
|
recbox+=QString("<tr><td>%1</td><td align=right>%2%3</td></tr>").arg(minstr).arg(tmpRX[ls]->min,0,'f',1).arg(STR_UNIT_CMH2O);
|
||||||
|
if (!maxstr.isEmpty()) recbox+=QString("<tr><td>%1</td><td align=right>%2%3</td></tr>").arg(maxstr).arg(tmpRX[ls]->max,0,'f',1).arg(STR_UNIT_CMH2O);
|
||||||
|
if (!maxhistr.isEmpty()) recbox+=QString("<tr><td>%1</td><td align=right>%2%3</td></tr>").arg(maxhistr).arg(tmpRX[ls]->maxhi,0,'f',1).arg(STR_UNIT_CMH2O);
|
||||||
|
recbox+="</table></td></tr>";
|
||||||
|
|
||||||
|
recbox+=QString("<tr><td colspan=2> </td></tr>");
|
||||||
|
|
||||||
|
mode=(CPAPMode)(int)PROFILE.calcSettingsMax(CPAP_Mode,MT_CPAP,tmpRX[0]->first,tmpRX[0]->last);
|
||||||
|
if (mode<MODE_APAP) { // is CPAP?
|
||||||
|
minstr=STR_TR_Pressure;
|
||||||
|
maxstr="";
|
||||||
|
modestr=STR_TR_CPAP;
|
||||||
|
} else if (mode<MODE_BIPAP) { // is AUTO?
|
||||||
|
minstr=STR_TR_Min;
|
||||||
|
maxstr=STR_TR_Max;
|
||||||
|
modestr=STR_TR_APAP;
|
||||||
|
} else if (mode<MODE_ASV) { // BIPAP or greater
|
||||||
|
minstr=STR_TR_EPAP;
|
||||||
|
maxstr=STR_TR_IPAP;
|
||||||
|
modestr=STR_TR_BiLevel;
|
||||||
|
} else {
|
||||||
|
minstr=STR_TR_EPAP;
|
||||||
|
maxstr=STR_TR_IPAPLo;
|
||||||
|
maxhistr=STR_TR_IPAPHi;
|
||||||
|
modestr=STR_TR_STASV;
|
||||||
|
}
|
||||||
|
|
||||||
|
recbox+=QString("<tr><td colspan=2><table width=100% border=0 cellpadding=1 cellspacing=0><tr><td colspan=2 align=center><b>%3</b></td></tr>")
|
||||||
|
.arg(tr("Worst RX Setting"));
|
||||||
|
recbox+=QString("<tr><td valign=top>")+STR_TR_Start+"<br/>"+STR_TR_End+QString("</td><td align=right><a href='overview=%1,%2'>%3<br/>%4</a></td></tr>")
|
||||||
|
.arg(tmpRX[0]->first.toString(Qt::ISODate))
|
||||||
|
.arg(tmpRX[0]->last.toString(Qt::ISODate))
|
||||||
|
.arg(tmpRX[0]->first.toString(Qt::SystemLocaleShortDate))
|
||||||
|
.arg(tmpRX[0]->last.toString(Qt::SystemLocaleShortDate));
|
||||||
|
recbox+=QString("<tr><td><b>%1</b></td><td align=right><b>%2</b></td></tr>").arg(ahitxt).arg(tmpRX[0]->ahi,0,'f',decimals);
|
||||||
|
recbox+=QString("<tr><td>%1</td><td align=right>%2</td></tr>").arg(STR_TR_Mode).arg(modestr);
|
||||||
|
recbox+=QString("<tr><td>%1</td><td align=right>%2%3</td></tr>").arg(minstr).arg(tmpRX[0]->min,0,'f',1).arg(STR_UNIT_CMH2O);
|
||||||
|
if (!maxstr.isEmpty()) recbox+=QString("<tr><td>%1</td><td align=right>%2%3</td></tr>").arg(maxstr).arg(tmpRX[0]->max,0,'f',1).arg(STR_UNIT_CMH2O);
|
||||||
|
if (!maxhistr.isEmpty()) recbox+=QString("<tr><td>%1</td><td align=right>%2%3</td></tr>").arg(maxhistr).arg(tmpRX[0]->maxhi,0,'f',1).arg(STR_UNIT_CMH2O);
|
||||||
|
recbox+="</table></td></tr>";
|
||||||
|
|
||||||
|
}
|
||||||
|
recbox+="</table>";
|
||||||
|
recbox+="</body></html>";
|
||||||
|
mainwin->setRecBoxHTML(recbox);
|
||||||
|
|
||||||
|
/*RXsort=RX_min;
|
||||||
|
RXorder=true;
|
||||||
|
qSort(rxchange.begin(),rxchange.end());*/
|
||||||
|
html+="<div align=center>";
|
||||||
|
html+=QString("<br/><b>")+tr("Changes to Prescription Settings")+"</b>";
|
||||||
|
html+=QString("<table cellpadding=2 cellspacing=0 border=1 width=90%>");
|
||||||
|
QString extratxt;
|
||||||
|
|
||||||
|
if (cpapmode>=MODE_ASV) {
|
||||||
|
extratxt=QString("<td><b>%1</b></td><td><b>%2</b></td><td><b>%3</b></td><td><b>%4</b></td><td><b>%5</b></td>")
|
||||||
|
.arg(STR_TR_EPAP).arg(STR_TR_IPAPLo).arg(STR_TR_IPAPHi).arg(tr("PS Min")).arg(tr("PS Max"));
|
||||||
|
} else if (cpapmode>=MODE_BIPAP) {
|
||||||
|
extratxt=QString("<td><b>%1</b></td><td><b>%2</b></td><td><b>%3</b></td>")
|
||||||
|
.arg(STR_TR_EPAP).arg(STR_TR_IPAP).arg(STR_TR_PS);
|
||||||
|
} else if (cpapmode>MODE_CPAP) {
|
||||||
|
extratxt=QString("<td><b>%1</b></td><td><b>%2</b></td>")
|
||||||
|
.arg(tr("Min Pres.")).arg(tr("Max Pres."));
|
||||||
|
} else {
|
||||||
|
extratxt=QString("<td><b>%1</b></td>")
|
||||||
|
.arg(STR_TR_Pressure);
|
||||||
|
}
|
||||||
|
QString tooltip;
|
||||||
|
html+=QString("<tr><td><b>%1</b></td><td><b>%2</b></td><td><b>%3</b></td><td><b>%4</b></td><td><b>%5</b></td><td><b>%6</b></td><td><b>%7</td><td><b>%8</td>%9</tr>")
|
||||||
|
.arg(STR_TR_First)
|
||||||
|
.arg(STR_TR_Last)
|
||||||
|
.arg(tr("Days"))
|
||||||
|
.arg(ahitxt)
|
||||||
|
.arg(tr("FL"))
|
||||||
|
.arg(STR_TR_Machine)
|
||||||
|
.arg(STR_TR_Mode)
|
||||||
|
.arg(tr("Pr. Rel."))
|
||||||
|
.arg(extratxt);
|
||||||
|
|
||||||
|
for (int i=0;i<rxchange.size();i++) {
|
||||||
|
RXChange rx=rxchange.at(i);
|
||||||
|
QString color;
|
||||||
|
if (rx.highlight==1) {
|
||||||
|
color="#c0ffc0";
|
||||||
|
} else if (rx.highlight==2) {
|
||||||
|
color="#e0ffe0";
|
||||||
|
} else if (rx.highlight==3) {
|
||||||
|
color="#ffe0e0";
|
||||||
|
} else if (rx.highlight==4) {
|
||||||
|
color="#ffc0c0";
|
||||||
|
} else color="";
|
||||||
|
QString machstr;
|
||||||
|
if (rx.machine->properties.contains(STR_PROP_Brand))
|
||||||
|
machstr+=rx.machine->properties[STR_PROP_Brand];
|
||||||
|
if (rx.machine->properties.contains(STR_PROP_Model)) {
|
||||||
|
machstr+=" "+rx.machine->properties[STR_PROP_Model];
|
||||||
|
}
|
||||||
|
if (rx.machine->properties.contains(STR_PROP_Serial)) {
|
||||||
|
machstr+=" ("+rx.machine->properties[STR_PROP_Serial]+")<br/>";
|
||||||
|
}
|
||||||
|
|
||||||
|
mode=rx.mode;
|
||||||
|
if(mode>=MODE_ASV) {
|
||||||
|
extratxt=QString("<td>%1</td><td>%2</td><td>%3</td><td>%4</td>")
|
||||||
|
.arg(rx.max,0,'f',decimals).arg(rx.maxhi,0,'f',decimals).arg(rx.max-rx.min,0,'f',decimals).arg(rx.maxhi-rx.min,0,'f',decimals);
|
||||||
|
|
||||||
|
tooltip=QString("%1 %2% ").arg(machstr).arg(percentile*100.0)+STR_TR_EPAP+
|
||||||
|
QString("=%1<br/>%2% ").arg(rx.per1,0,'f',decimals).arg(percentile*100.0)+
|
||||||
|
STR_TR_IPAP+QString("=%1").arg(rx.per2,0,'f',decimals);
|
||||||
|
} else if (mode>=MODE_BIPAP) {
|
||||||
|
extratxt=QString("<td>%1</td><td>%2</td>")
|
||||||
|
.arg(rx.max,0,'f',decimals).arg(rx.max-rx.min,0,'f',decimals);
|
||||||
|
tooltip=QString("%1 %2% ").arg(machstr).arg(percentile*100.0)+
|
||||||
|
STR_TR_EPAP+
|
||||||
|
QString("=%1<br/>%2% ").arg(rx.per1,0,'f',decimals)
|
||||||
|
.arg(percentile*100.0)
|
||||||
|
+STR_TR_IPAP+QString("=%1").arg(rx.per2,0,'f',decimals);
|
||||||
|
} else if (mode>MODE_CPAP) {
|
||||||
|
extratxt=QString("<td>%1</td>").arg(rx.max,0,'f',decimals);
|
||||||
|
tooltip=QString("%1 %2% ").arg(machstr).arg(percentile*100.0)+STR_TR_Pressure+
|
||||||
|
QString("=%2").arg(rx.per1,0,'f',decimals);
|
||||||
|
} else {
|
||||||
|
if (cpapmode>MODE_CPAP) {
|
||||||
|
extratxt="<td> </td>";
|
||||||
|
tooltip=QString("%1").arg(machstr);
|
||||||
|
} else {
|
||||||
|
extratxt="";
|
||||||
|
tooltip="";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QString presrel;
|
||||||
|
if (rx.prelset>0) {
|
||||||
|
presrel=schema::channel[CPAP_PresReliefType].option(int(rx.prelief));
|
||||||
|
presrel+=QString(" x%1").arg(rx.prelset);
|
||||||
|
} else presrel=STR_TR_None;
|
||||||
|
QString tooltipshow,tooltiphide;
|
||||||
|
if (!tooltip.isEmpty()) {
|
||||||
|
tooltipshow=QString("tooltip.show(\"%1\");").arg(tooltip);
|
||||||
|
tooltiphide="tooltip.hide();";
|
||||||
|
}
|
||||||
|
html+=QString("<tr bgcolor='"+color+"' onmouseover='ChangeColor(this, \"#eeeeee\"); %13' onmouseout='ChangeColor(this, \""+color+"\"); %14' onclick='alert(\"overview=%1,%2\");'><td>%3</td><td>%4</td><td>%5</td><td>%6</td><td>%7</td><td>%8</td><td>%9</td><td>%10</td><td>%11</td>%12</tr>")
|
||||||
|
.arg(rx.first.toString(Qt::ISODate))
|
||||||
|
.arg(rx.last.toString(Qt::ISODate))
|
||||||
|
.arg(rx.first.toString(Qt::SystemLocaleShortDate))
|
||||||
|
.arg(rx.last.toString(Qt::SystemLocaleShortDate))
|
||||||
|
.arg(rx.days)
|
||||||
|
.arg(rx.ahi,0,'f',decimals)
|
||||||
|
.arg(rx.fl,0,'f',decimals)
|
||||||
|
.arg(rx.machine->GetClass())
|
||||||
|
.arg(schema::channel[CPAP_Mode].option(int(rx.mode)-1))
|
||||||
|
.arg(presrel)
|
||||||
|
.arg(rx.min,0,'f',decimals)
|
||||||
|
.arg(extratxt)
|
||||||
|
.arg(tooltipshow)
|
||||||
|
.arg(tooltiphide);
|
||||||
|
}
|
||||||
|
html+="</table>";
|
||||||
|
html+=QString("<i>")+tr("The above has a threshold which excludes day counts less than %1 from the best/worst highlighting").arg(rxthresh)+QString("</i><br/>");
|
||||||
|
html+="</div>";
|
||||||
|
|
||||||
|
}
|
||||||
|
if (mach.size()>0) {
|
||||||
|
html+="<div align=center>";
|
||||||
|
|
||||||
|
html+=QString("<br/><b>")+tr("Machine Information")+"</b>";
|
||||||
|
html+=QString("<table cellpadding=2 cellspacing=0 border=1 width=90%>");
|
||||||
|
html+=QString("<tr><td><b>%1</b></td><td><b>%2</b></td><td><b>%3</b></td><td><b>%4</b></td><td><b>%5</b></td></tr>")
|
||||||
|
.arg(STR_TR_Brand)
|
||||||
|
.arg(STR_TR_Model)
|
||||||
|
.arg(STR_TR_Serial)
|
||||||
|
.arg(tr("First Use"))
|
||||||
|
.arg(tr("Last Use"));
|
||||||
|
Machine *m;
|
||||||
|
for (int i=0;i<mach.size();i++) {
|
||||||
|
m=mach.at(i);
|
||||||
|
if (m->GetType()==MT_JOURNAL) continue;
|
||||||
|
QString mn=m->properties[STR_PROP_ModelNumber];
|
||||||
|
//if (mn.isEmpty())
|
||||||
|
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->properties[STR_PROP_Model]+" "+m->properties[STR_PROP_SubModel]+ (mn.isEmpty() ? "" : QString(" (")+mn+QString(")")))
|
||||||
|
.arg(m->properties[STR_PROP_Serial])
|
||||||
|
.arg(m->FirstDay().toString(Qt::SystemLocaleShortDate))
|
||||||
|
.arg(m->LastDay().toString(Qt::SystemLocaleShortDate));
|
||||||
|
}
|
||||||
|
html+="</table>";
|
||||||
|
html+="</div>";
|
||||||
|
}
|
||||||
|
html+="<script type='text/javascript' language='javascript' src='qrc:/docs/script.js'></script>";
|
||||||
|
//updateFavourites();
|
||||||
|
html+=htmlFooter();
|
||||||
|
return html;
|
||||||
|
}
|
26
summary.h
Normal file
26
summary.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
Summary Header
|
||||||
|
Copyright (c)2013 Mark Watkins <jedimark@users.sourceforge.net>
|
||||||
|
License: GPL3
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SUMMARY_H
|
||||||
|
#define SUMMARY_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class Summary : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit Summary(QObject *parent = 0);
|
||||||
|
|
||||||
|
static QString GenerateHTML();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SUMMARY_H
|
Loading…
Reference in New Issue
Block a user