mirror of
https://gitlab.com/pholy/OSCAR-code.git
synced 2025-04-05 02:30:44 +00:00
Merge branch 'master' into vAuto-Settings
This commit is contained in:
commit
394f733c4b
@ -30,7 +30,7 @@
|
||||
<p>
|
||||
<b>Developers</b>
|
||||
<br>
|
||||
Phil Olynyk (pholynyk) (<i>Lead Developer</i>), GuyScharf, sawinglogz</p>
|
||||
Phil Olynyk (pholynyk) (<i>Lead Developer</i>), GuyScharf, sawinglogz, Ray Elliott (LoudSnorer), untoutseul05</p>
|
||||
<p>
|
||||
<b>Reporters</b>
|
||||
<br>AlanE, BrandonA, Crimson Nape, foxfire, Heyns, jeremieb, jaswilliams, palerider, patl</p>
|
||||
@ -41,11 +41,11 @@
|
||||
unidee</p>
|
||||
<p>
|
||||
<b>Advisors</b>
|
||||
<br>aviB, SkepticDoc, Sleeprider, SleepyProgrammer, srlevine1, LunaFerret, harre, mdhamptom, mitchcampbell, rtannerf</p>
|
||||
<br>aviB, SkepticDoc, Sleeprider, SleepyProgrammer, srlevine1, LunaFerret, harre, mdhamptom, mitchcampbell, rhashimoto, rtannerf</p>
|
||||
<p>
|
||||
<b>Translators</b>
|
||||
<br>
|
||||
Arie Klerk (A KLERK) (<i>Translations Team Coordinator, Dutch</i>), 1st.qwerty (<i>Polish</i>), C Chan (<i>Trad.Chinese)</i>, Caniss (<i>Swedish</i>), delta (<i>Romanian</i>), dolceitalia (<i>Italian</i>), drmaestro (<i>Turkish</i>), drol (<i>French</i>), FaureCourtet (<i>French</i>), GregK (<i>Russian, Hebrew</i>), hearsay73 (<i>Filipino</i>), Heyns (<i>Afrikaans</i>), Hypoxic (<i>Greek</i>), jaswilliams (<i>British</i>), johanh (<i>Finnish</i>), k2boys (<i>Korean</i>), Lazer1234 (<i>Swedish</i>), Mac_Sheepcounter (<i>German</i>), mazingas65 (<i>Italian</i>), Ppja (<i>Spanish</i>), pstrjds (<i>Bulgarian</i>), refurbished (<i>Polish</i>), Ristraus (<i>Brazilian Portugese</i>), rlabs (<i>Russian</i>), ShaunBlake (<i>British</i>), steffenreitz (<i>German</i>), tolnaiz (<i>Hungarian</i>), unidee (<i>Finnish</i>), untoutseul05 (<i>French</i>), yrnkrn (<i>Hebrew</i>), N-A-N (<i>Thai</i>). <br>
|
||||
Arie Klerk (A KLERK) (<i>Translations Team Coordinator, Dutch</i>), 1st.qwerty (<i>Polish</i>), C Chan (<i>Trad.Chinese)</i>, delta (<i>Romanian</i>), dolceitalia (<i>Italian</i>), drmaestro (<i>Turkish</i>), drol (<i>French</i>), FaureCourtet (<i>French</i>), GregK (<i>Russian, Hebrew</i>), hearsay73 (<i>Filipino</i>), Heyns (<i>Afrikaans</i>), Hypoxic (<i>Greek</i>), k2boys (<i>Korean</i>), Lazer1234 (<i>Swedish</i>), mazingas65 (<i>Italian</i>), Ppja (<i>Spanish</i>), pstrjds (<i>Bulgarian</i>), refurbished (<i>Polish</i>), Ristraus (<i>Portugese and Brazilian Portugese</i>), rlabs (<i>Russian</i>), ShaunBlake (<i>British</i>), steffenreitz (<i>German</i>), tolnaiz (<i>Hungarian</i>), unidee (<i>Finnish</i>), untoutseul05 (<i>French</i>), yrnkrn (<i>Hebrew</i>), N-A-N (<i>Thai</i>). <br>
|
||||
<b>Thank you all very much for your continuous effort!</b></p>
|
||||
<p>
|
||||
<b>OSCAR is always looking for help: programmers, testers, or translators. If you are interested, please PM 'Gideon' on the Apnea Board Forum.</b>
|
||||
|
@ -11,46 +11,40 @@
|
||||
<b>This page in other languages:</b>
|
||||
<br><a href=http://www.apneaboard.com/wiki/index.php/OSCAR_Release_Notes>http://www.apneaboard.com/wiki/index.php/OSCAR_Release_Notes</a></p>
|
||||
<p>
|
||||
<b>Changes and fixes in OSCAR v1.3.5-alpha.X</b>
|
||||
<b>Changes and fixes in OSCAR v1.4.1-xxxx</b>
|
||||
<br>Portions of OSCAR are © 2019-2022 by
|
||||
<i>The OSCAR Team</i></p>
|
||||
<ul>
|
||||
<li>[new] Additional Philips Respironics devices tested and fully supported:
|
||||
<li>[fix] Allow Graph and Event combo boxes to remain open after changes.<li>
|
||||
<li>[fix] Overview display of ResMed Oximeter events now works.<li>
|
||||
</ul>
|
||||
<p>
|
||||
<b>Changes and fixes in OSCAR v1.4.0</b>
|
||||
<br>Portions of OSCAR are © 2019-2022 by
|
||||
<i>The OSCAR Team</i></p>
|
||||
<ul>
|
||||
<li>[new] Support for Philips Respironics DreamStation 2:
|
||||
<ul>
|
||||
<li>DreamStation 2 CPAP (410X150C)</li>
|
||||
<li>DreamStation 2 Auto CPAP Advanced (520X130C)</li>
|
||||
<li>DreamStation 2 Advanced CPAP (420X150C)</li>
|
||||
<li>DreamStation 2 Auto CPAP Advanced (520X110C, 520X130C, 520X150C)</li>
|
||||
<li>DreamStation 2 Auto CPAP Advanced with P-Flex (521X120C, 521X140C)</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>[new] Additional Philips Respironics devices tested and fully supported:
|
||||
<ul>
|
||||
<li>BiPAP Auto (System One 60 Series) (761P)</li>
|
||||
<li>BiPAP autoSV Advanced 30 (System One 60 Series) (961TCA)</li>
|
||||
<li>REMstar Auto (System One) (552P)</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>[new] For AutoSet 11, two models were added to the tested list: 39421 and 39485.</li>
|
||||
<li>[fix] Added support for pressure pulse, CA, and VS on BiPAP autoSV Advanced 30 (System One 60 Series) (960T).</li>
|
||||
<li>[fix] Fixed pressure settings scale on BiPAP autoSV Advanced 30 (System One 60 Series) (960T).</li>
|
||||
</ul>
|
||||
<p>
|
||||
<b>Changes and fixes in OSCAR v1.3.5-alpha.2</b>
|
||||
<br>Portions of OSCAR are © 2019-2022 by
|
||||
<i>The OSCAR Team</i></p>
|
||||
<ul>
|
||||
<li>[new] Additional Philips Respironics devices tested and fully supported:
|
||||
<ul>
|
||||
<li>DreamStation 2 Auto CPAP Advanced with P-Flex (521X120C)</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>[fix] For all ResMed devices, square plot (no smoothing) has been forced on all 2 second pressure graphs.</li>
|
||||
<li>[fix] File Export Sessions now exports statistics session data properly.</li>
|
||||
<li>[fix] Fixed a rare crash on import when encountering corrupted Philips Respironics directories.</li>
|
||||
</ul>
|
||||
<p>
|
||||
<b>Changes and fixes in OSCAR v1.3.5-alpha.0</b>
|
||||
<br>Portions of OSCAR are © 2019-2022 by
|
||||
<i>The OSCAR Team</i></p>
|
||||
<ul>
|
||||
<li>[new] Additional Philips Respironics devices tested and fully supported:
|
||||
<ul>
|
||||
<li>DreamStation 2 Auto CPAP Advanced (520X110C, 520X150C)</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>[new] Test Mantis integration.</li>
|
||||
<li>[fix] Fixed an incorrect warning message when importing some CheckMe O2 Max data.</li>
|
||||
</ul>
|
||||
<p>
|
||||
<b>Changes and fixes in OSCAR v1.3.1</b>
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
9260
Translations/Japanese.ja.ts
Normal file
9260
Translations/Japanese.ja.ts
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
90
Translations/qt/oscar_qt_ja.ts
Normal file
90
Translations/qt/oscar_qt_ja.ts
Normal file
@ -0,0 +1,90 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1" language="ja_JP">
|
||||
<context>
|
||||
<name>QShortcut</name>
|
||||
<message>
|
||||
<source>No</source>
|
||||
<translation>いいえ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Yes</source>
|
||||
<translation>はい</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>QPlatformTheme</name>
|
||||
<message>
|
||||
<source>OK</source>
|
||||
<translation>よっしゃー</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>&No</source>
|
||||
<translation>いいえ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>&Yes</source>
|
||||
<translation>はい</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Help</source>
|
||||
<translation>ヘルプ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Open</source>
|
||||
<translation>オープン</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Save</source>
|
||||
<translation>セーブ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Abort</source>
|
||||
<translation>中止</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Apply</source>
|
||||
<translation>適用</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Close</source>
|
||||
<translation>閉じる</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Reset</source>
|
||||
<translation>リセット</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Retry</source>
|
||||
<translation>リトライ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Restore Defaults</source>
|
||||
<translation>初期設定に戻す</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cancel</source>
|
||||
<translation>キャンセル</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Ignore</source>
|
||||
<translation>無視</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>N&o to All</source>
|
||||
<translation>ノー・トゥ・オール</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Save All</source>
|
||||
<translation>すべて保存</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Discard</source>
|
||||
<translation>廃棄</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Yes to &All</source>
|
||||
<translation>イエス・トゥ・オール</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
@ -116,6 +116,7 @@ void gToolTip::display(QString text, int x, int y, ToolTipAlignment align, int t
|
||||
m_alignment = align;
|
||||
|
||||
m_text = text;
|
||||
// for testing add mouse position to tooltip. QString("%1:(%2,%3)").arg(text).arg(m_graphview->currentMousePos().x()).arg(m_graphview->currentMousePos().y());
|
||||
m_visible = true;
|
||||
// TODO: split multiline here
|
||||
//calcSize(m_text,tw,th);
|
||||
@ -139,53 +140,62 @@ void gToolTip::cancel()
|
||||
timer->stop();
|
||||
}
|
||||
|
||||
QRect gToolTip::calculateRect(QPainter &painter)
|
||||
QRect gToolTip::calculateRect(QPainter &painter)
|
||||
{
|
||||
int x = m_pos.x();
|
||||
int y = m_pos.y();
|
||||
|
||||
// calcualte size of tooltip
|
||||
QRect rect(x, y, 0, 0);
|
||||
|
||||
painter.setFont(*m_font);
|
||||
rect = painter.boundingRect(rect, Qt::AlignCenter, m_text);
|
||||
|
||||
// Set preffered locations
|
||||
rect.moveTo(m_pos);
|
||||
|
||||
// Add borders arround text area
|
||||
|
||||
// add space around rectangle horizontilally left & right sides.
|
||||
int w = rect.width() + m_spacer * 2;
|
||||
int xx = rect.x() - m_spacer;
|
||||
|
||||
if (xx < 0) { xx = 0; }
|
||||
|
||||
rect.setLeft(xx);
|
||||
rect.setTop(rect.y() - 15);
|
||||
rect.setWidth(w);
|
||||
|
||||
int z = rect.x() + rect.width();
|
||||
// add space around rectangle vertically
|
||||
int h = rect.height() + m_spacer * 2;
|
||||
rect.setHeight(h);
|
||||
|
||||
if (z > m_graphview->width() - 10) {
|
||||
rect.setLeft(m_graphview->width() - 2 - rect.width());
|
||||
rect.setRight(m_graphview->width() - 2);
|
||||
/*
|
||||
now must verify that the tooltip must fit inti the display area.
|
||||
if part of the display can not be displayed (outside the bounding rectangle of the graph then
|
||||
the tool tip will be moved to fit.
|
||||
If the tooltip is too big . (does not fit) then preference is giver to the top and left sides.
|
||||
the following checks are executed in the order.
|
||||
1) do right side
|
||||
2) do left side
|
||||
3) do bottom
|
||||
4) do top.
|
||||
these checks are independant of alignment requirements.
|
||||
*/
|
||||
|
||||
// get display area
|
||||
QRect displayRect = m_graphview->geometry();
|
||||
int right = displayRect.right() -2; // allow tooltip border to be displayed
|
||||
int left = displayRect.left();
|
||||
int top = displayRect.top();
|
||||
int bottom = displayRect.bottom();
|
||||
|
||||
if (rect.right() > right ) {
|
||||
rect.moveRight(right);
|
||||
}
|
||||
if (rect.left() < left ) {
|
||||
rect.moveLeft(left);
|
||||
}
|
||||
if (rect.bottom() > bottom ) {
|
||||
rect.moveBottom(bottom);
|
||||
}
|
||||
if (rect.top() < top ) {
|
||||
rect.moveTop(top);
|
||||
}
|
||||
|
||||
int h = rect.height();
|
||||
|
||||
if (rect.y() < 0) {
|
||||
rect.setY(0);
|
||||
rect.setHeight(h);
|
||||
}
|
||||
|
||||
if (m_alignment == TT_AlignRight) {
|
||||
rect.moveTopRight(m_pos);
|
||||
if ((x-w) < 0) {
|
||||
rect.moveLeft(0);
|
||||
}
|
||||
} else if (m_alignment == TT_AlignLeft) {
|
||||
rect.moveTopLeft(m_pos);
|
||||
}
|
||||
|
||||
int bot = rect.bottom() - m_graphview->height();
|
||||
if (bot > 0) {
|
||||
rect.setTop(rect.top()-bot);
|
||||
rect.setBottom(m_graphview->height());
|
||||
}
|
||||
return rect;
|
||||
}
|
||||
|
||||
|
@ -350,6 +350,7 @@ void gSummaryChart::populate(Day * day, int idx)
|
||||
auto & slices = cache[idx];
|
||||
|
||||
float hours = day->hours(m_machtype);
|
||||
if ((hours==0) && (m_machtype != MT_CPAP)) hours = day->hours();
|
||||
float base = 0;
|
||||
|
||||
for (auto & item : calcitems) {
|
||||
@ -1323,3 +1324,4 @@ QString gAHIChart::tooltipData(Day *day, int idx)
|
||||
}
|
||||
return QString("\n%1: %2").arg(STR_TR_AHI).arg(float(total) / hour,0,'f',2)+txt;
|
||||
}
|
||||
|
||||
|
@ -283,7 +283,7 @@ QString weightString(float kg, UnitSystem us)
|
||||
if (us == US_Metric) {
|
||||
return QString("%1kg").arg(kg, 0, 'f', 2);
|
||||
} else if (us == US_English) {
|
||||
int oz = (kg * 1000.0) / (float)ounce_convert;
|
||||
int oz = (kg * 1000.0) * (float)gram_ounce_convert;
|
||||
int lb = oz / 16.0;
|
||||
oz = oz % 16;
|
||||
return QString("%1lb %2oz").arg(lb, 0, 10).arg(oz);
|
||||
@ -526,6 +526,7 @@ QString STR_TR_CPAP; // Constant Positive Airway Pressure
|
||||
QString STR_TR_BIPAP; // Bi-Level Positive Airway Pressure
|
||||
QString STR_TR_BiLevel; // Another name for BiPAP
|
||||
QString STR_TR_EPAP; // Expiratory Positive Airway Pressure
|
||||
QString STR_TR_EEPAP; // End Expiratory Positive Airway Pressure
|
||||
QString STR_TR_EPAPLo; // Expiratory Positive Airway Pressure, Low
|
||||
QString STR_TR_EPAPHi; // Expiratory Positive Airway Pressure, High
|
||||
QString STR_TR_IPAP; // Inspiratory Positive Airway Pressure
|
||||
@ -735,6 +736,7 @@ void initializeStrings()
|
||||
STR_TR_BIPAP = QObject::tr("BiPAP"); // Bi-Level Positive Airway Pressure
|
||||
STR_TR_BiLevel = QObject::tr("Bi-Level"); // Another name for BiPAP
|
||||
STR_TR_EPAP = QObject::tr("EPAP"); // Expiratory Positive Airway Pressure
|
||||
STR_TR_EEPAP = QObject::tr("EEPAP"); // Expiratory Positive Airway Pressure
|
||||
STR_TR_EPAPLo = QObject::tr("Min EPAP"); // Lower Expiratory Positive Airway Pressure
|
||||
STR_TR_EPAPHi = QObject::tr("Max EPAP"); // Higher Expiratory Positive Airway Pressure
|
||||
STR_TR_IPAP = QObject::tr("IPAP"); // Inspiratory Positive Airway Pressure
|
||||
|
@ -83,6 +83,7 @@ bool operator <(const ValueCount &a, const ValueCount &b);
|
||||
|
||||
const float ounce_convert = 28.3495231F; // grams
|
||||
const float pound_convert = ounce_convert * 16;
|
||||
const float gram_ounce_convert = 0.0352754; // ounces in a gram
|
||||
|
||||
QString weightString(float kg, UnitSystem us = US_Undefined);
|
||||
|
||||
@ -162,6 +163,7 @@ const QString STR_MACH_SleepStyle = "SleepStyle";
|
||||
const QString STR_MACH_MSeries = "MSeries";
|
||||
const QString STR_MACH_CMS50 = "CMS50";
|
||||
const QString STR_MACH_ZEO = "Zeo";
|
||||
const QString STR_MACH_Prisma = "Prisma";
|
||||
|
||||
const QString STR_PREF_Language = "Language";
|
||||
|
||||
@ -249,6 +251,7 @@ extern QString STR_TR_CPAP; // Constant Positive Airway Pressure
|
||||
extern QString STR_TR_BIPAP; // Bi-Level Positive Airway Pressure
|
||||
extern QString STR_TR_BiLevel; // Another name for BiPAP
|
||||
extern QString STR_TR_EPAP; // Expiratory Positive Airway Pressure
|
||||
extern QString STR_TR_EEPAP; // Expiratory Positive Airway Pressure
|
||||
extern QString STR_TR_EPAPLo; // Expiratory Positive Airway Pressure, Low
|
||||
extern QString STR_TR_EPAPHi; // Expiratory Positive Airway Pressure, High
|
||||
extern QString STR_TR_IPAP; // Inspiratory Positive Airway Pressure
|
||||
|
@ -96,6 +96,20 @@ bool EDFInfo::Open(const QString & name)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EDFInfo::Open(const QByteArray &data)
|
||||
{
|
||||
fileData = data;
|
||||
if (fileData.size() <= EDFHeaderSize) {
|
||||
fileData.clear();;
|
||||
qDebug() << "EDFInfo::Open() buffer too short";
|
||||
return false;
|
||||
}
|
||||
// TODO AXT
|
||||
filename = "bytearray";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
QDateTime EDFInfo::getStartDT( QString dateTimeStr )
|
||||
{
|
||||
// edfHdr.startdate_orig = QDateTime::fromString(QString::fromLatin1(hdrPtr->datetime, 16), "dd.MM.yyHH.mm.ss");
|
||||
@ -146,14 +160,15 @@ bool EDFInfo::parseHeader( EDFHeaderRaw *hdrPtr )
|
||||
}
|
||||
edfHdr.reserved44=QString::fromLatin1(hdrPtr->reserved, 44).trimmed();
|
||||
edfHdr.num_data_records = QString::fromLatin1(hdrPtr->num_data_records, 8).toLong(&ok);
|
||||
if ( (! ok) || (edfHdr.num_data_records < 1) ) {
|
||||
#ifdef EDF_DEBUG
|
||||
qWarning() << "EDFInfo::Parse() Bad data record count " << filename;
|
||||
// sleep(1);
|
||||
#endif
|
||||
fileData.clear();
|
||||
return false;
|
||||
}
|
||||
// TODO AXT
|
||||
// if ( (! ok) || (edfHdr.num_data_records < 1) ) {
|
||||
//#ifdef EDF_DEBUG
|
||||
// qWarning() << "EDFInfo::Parse() Bad data record count " << filename;
|
||||
// // sleep(1);
|
||||
//#endif
|
||||
// fileData.clear();
|
||||
// return false;
|
||||
// }
|
||||
edfHdr.duration_Seconds = QString::fromLatin1(hdrPtr->dur_data_records, 8).toDouble(&ok);
|
||||
if (!ok) {
|
||||
#ifdef EDF_DEBUG
|
||||
@ -250,6 +265,12 @@ bool EDFInfo::Parse() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ret = ParseSignalData();
|
||||
fileData.clear();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool EDFInfo::ParseSignalData() {
|
||||
// Now check the file isn't truncated before allocating space for the values
|
||||
long allocsize = 0;
|
||||
for (auto & sig : edfsignals) {
|
||||
@ -265,7 +286,6 @@ bool EDFInfo::Parse() {
|
||||
fileData.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
// allocate the arrays for the signal values
|
||||
for (auto & sig : edfsignals) {
|
||||
long samples = sig.sampleCnt * edfHdr.num_data_records;
|
||||
@ -289,7 +309,7 @@ bool EDFInfo::Parse() {
|
||||
}
|
||||
}
|
||||
}
|
||||
fileData.clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -126,9 +126,13 @@ class EDFInfo
|
||||
virtual ~EDFInfo();
|
||||
|
||||
virtual bool Open(const QString & name); //! \brief Open the EDF+ file, and read it's header
|
||||
virtual bool Open(const QByteArray &data);
|
||||
|
||||
|
||||
virtual bool Parse(); //! \brief Parse the EDF+ file into the EDFheaderQT. Must call Open(..) first.
|
||||
|
||||
virtual bool ParseSignalData(); //! \brief Parse the signal data
|
||||
|
||||
virtual bool parseHeader( EDFHeaderRaw * hdrPtr ); //! \brief parse just the edf header for duration, etc
|
||||
|
||||
virtual EDFSignal * lookupLabel(const QString & name, int index=0); //! \brief Return a ptr to the i'th signal with that name
|
||||
@ -166,24 +170,27 @@ class EDFInfo
|
||||
QHash<QString, QList<EDFSignal *> > signalList; //! \brief ResMed sometimes re-uses the SAME signal name
|
||||
|
||||
// the following could be private
|
||||
protected:
|
||||
//! \brief This is the array of signal descriptors and values
|
||||
char *signalPtr;
|
||||
long filesize;
|
||||
long datasize;
|
||||
long pos;
|
||||
bool eof;
|
||||
|
||||
//! \brief This is the array holding the EDF file data
|
||||
QByteArray fileData;
|
||||
//! \brief Read 16 bit word of data from the EDF+ data stream
|
||||
qint16 Read16();
|
||||
|
||||
private:
|
||||
QVector<Annotation> ReadAnnotations( const char * data, int charLen ); //! \brief Create an Annotaion vector from the signal values
|
||||
|
||||
QString ReadBytes(unsigned n); //! \brief Read n bytes of 8 bit data from the EDF+ data stream
|
||||
|
||||
qint16 Read16(); //! \brief Read 16 bit word of data from the EDF+ data stream
|
||||
|
||||
//! \brief This is the array holding the EDF file data
|
||||
QByteArray fileData;
|
||||
//! \brief The EDF+ files header structure, used as a place holder while processing the text data.
|
||||
EDFHeaderRaw *hdrPtr;
|
||||
//! \brief This is the array of signal descriptors and values
|
||||
char *signalPtr;
|
||||
|
||||
long filesize;
|
||||
long datasize;
|
||||
long pos;
|
||||
bool eof;
|
||||
};
|
||||
|
||||
|
||||
|
1008
oscar/SleepLib/loader_plugins/prisma_loader.cpp
Normal file
1008
oscar/SleepLib/loader_plugins/prisma_loader.cpp
Normal file
File diff suppressed because it is too large
Load Diff
286
oscar/SleepLib/loader_plugins/prisma_loader.h
Normal file
286
oscar/SleepLib/loader_plugins/prisma_loader.h
Normal file
@ -0,0 +1,286 @@
|
||||
/* SleepLib Löwenstein Prisma Loader Header
|
||||
*
|
||||
* Copyright (c) 2019-2022 The OSCAR Team
|
||||
* Copyright (C) 2011-2018 Mark Watkins <mark@jedimark.net>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file COPYING in the main directory of the source code
|
||||
* for more details. */
|
||||
|
||||
#ifndef PRISMA_LOADER_H
|
||||
#define PRISMA_LOADER_H
|
||||
#include "SleepLib/machine_loader.h"
|
||||
#include "SleepLib/loader_plugins/edfparser.h"
|
||||
#include <QDir>
|
||||
|
||||
#ifdef UNITTEST_MODE
|
||||
#define private public
|
||||
#define protected public
|
||||
#endif
|
||||
|
||||
//********************************************************************************************
|
||||
/// IMPORTANT!!!
|
||||
//********************************************************************************************
|
||||
// Please INCREMENT the following value when making changes to this loaders implementation
|
||||
// BEFORE making a release
|
||||
const int prisma_data_version = 1;
|
||||
//
|
||||
//********************************************************************************************
|
||||
const QString prisma_class_name = STR_MACH_Prisma;
|
||||
|
||||
//********************************************************************************************
|
||||
|
||||
// NOTE: Prisma Smart and Prisma Line devices use distinct parameter id-s, but the correct solution
|
||||
// would be to transform these, into separate enums / parsers.
|
||||
enum Prisma_Parameters {
|
||||
PRISMA_SMART_MODE = 6,
|
||||
PRISMA_SMART_PRESSURE = 9,
|
||||
PRISMA_SMART_PRESSURE_MAX = 10,
|
||||
PRISMA_SMART_PSOFT_MIN = 11,
|
||||
PRISMA_SMART_PSOFT = 12,
|
||||
PRISMA_SMART_SOFTPAP = 13,
|
||||
PRISMA_SMART_APAP_DYNAMIC = 15,
|
||||
PRISMA_SMART_HUMIDLEVEL = 16,
|
||||
PRISMA_SMART_AUTOSTART = 17,
|
||||
PRISMA_SMART_SOFTSTART_TIME_MAX = 18,
|
||||
PRISMA_SMART_SOFTSTART_TIME = 19,
|
||||
PRISMA_SMART_TUBE_TYPE = 21,
|
||||
PRISMA_SMART_PMAXOA = 38,
|
||||
|
||||
PRISMA_LINE_MODE = 1003,
|
||||
PRISMA_LINE_TI = 1011,
|
||||
PRISMA_LINE_TE = 1012,
|
||||
PRISMA_LINE_TARGET_VOLUME = 1016,
|
||||
PRISMA_LINE_IPAP_SPEED = 1017,
|
||||
PRISMA_LINE_HUMIDLEVEL = 1083,
|
||||
PRISMA_LINE_AUTOSTART = 1084,
|
||||
PRISMA_LINE_TUBE_TYPE = 1091,
|
||||
PRISMA_LINE_BACTERIUMFILTER = 1092,
|
||||
PRISMA_LINE_SOFT_PAP_LEVEL = 1123,
|
||||
PRISMA_LINE_SOFT_START_PRESS = 1125,
|
||||
PRISMA_LINE_SOFT_START_TIME = 1127,
|
||||
PRISMA_LINE_EEPAP_MIN = 1138,
|
||||
PRISMA_LINE_EEPAP_MAX = 1139,
|
||||
PRISMA_LINE_PDIFF_NORM = 1140,
|
||||
PRISMA_LINE_PDIFF_MAX = 1141,
|
||||
PRISMA_LINE_IPAP_MAX = 1199,
|
||||
PRISMA_LINE_IPAP = 1200,
|
||||
PRISMA_LINE_EPAP = 1201,
|
||||
// PRISMA_LINE_ALARM_LEAK_ACTIVE = 1202,
|
||||
// PRISMA_LINE_ALARM_DISCONNECTION_ACTIVE = 1203,
|
||||
PRISMA_LINE_APAP_DYNAMIC = 1209
|
||||
|
||||
};
|
||||
|
||||
// NOTE: Modes should be reverse engineered. Based on the samples we had, for now I didn't saw any overlap,
|
||||
// so I assumed, the mode settings is generic between the two device lines. If you run into an overlap, the
|
||||
// above mentioned parsers should be introduced. Enum values are coming from the prisma data files.
|
||||
enum Prisma_Mode {
|
||||
// Prisma Smart
|
||||
PRISMA_MODE_CPAP = 1,
|
||||
PRISMA_MODE_APAP = 2,
|
||||
|
||||
// Prisma Line
|
||||
PRISMA_MODE_ACSV = 3,
|
||||
PRISMA_MODE_AUTO_S = 9,
|
||||
PRISMA_MODE_AUTO_ST = 10,
|
||||
};
|
||||
|
||||
enum Prisma_APAP_Mode {
|
||||
PRISMA_APAP_MODE_STANDARD = 1,
|
||||
PRISMA_APAP_MODE_DYNAMIC = 2,
|
||||
};
|
||||
|
||||
enum Prisma_SoftPAP_Mode {
|
||||
Prisma_SoftPAP_OFF = 0,
|
||||
Prisma_SoftPAP_SLIGHT = 1,
|
||||
Prisma_SoftPAP_STANDARD = 2
|
||||
};
|
||||
|
||||
// NOTE: This enum represents a "virtual mode" which combines the main mode of the device with the APAP submode,
|
||||
// if it makes sense. The reason for this is, that we can see the Standard and Dynamic APAP modes on the statistics
|
||||
// page. Enum values are internal to the loader. We use -1 to indicate a mode that is not recognized.
|
||||
enum Prisma_Combined_Mode {
|
||||
PRISMA_COMBINED_MODE_CPAP = 1,
|
||||
PRISMA_COMBINED_MODE_APAP_STD = 2,
|
||||
PRISMA_COMBINED_MODE_APAP_DYN = 3,
|
||||
|
||||
PRISMA_COMBINED_MODE_AUTO_S = 4,
|
||||
PRISMA_COMBINED_MODE_AUTO_ST = 5,
|
||||
PRISMA_COMBINED_MODE_ACSV = 6,
|
||||
|
||||
PRISMA_COMBINED_MODE_UNKNOWN = -1,
|
||||
};
|
||||
|
||||
enum Prisma_Event_Type {
|
||||
PRISMA_EVENT_EPOCH_SEVERE_OBSTRUCTION = 1,
|
||||
PRISMA_EVENT_EPOCH_MILD_OBSTRUCTION = 2,
|
||||
PRISMA_EVENT_EPOCH_FLOW_LIMITATION = 3,
|
||||
PRISMA_EVENT_EPOCH_SNORE = 4,
|
||||
PRISMA_EVENT_EPOCH_PERIODIC_BREATHING = 5,
|
||||
PRISMA_EVENT_OBSTRUCTIVE_APNEA = 101,
|
||||
PRISMA_EVENT_CENTRAL_APNEA = 102,
|
||||
PRISMA_EVENT_APNEA_LEAKAGE = 103,
|
||||
PRISMA_EVENT_APNEA_HIGH_PRESSURE = 105,
|
||||
PRISMA_EVENT_APNEA_MOVEMENT = 106,
|
||||
PRISMA_EVENT_OBSTRUCTIVE_HYPOPNEA= 111,
|
||||
PRISMA_EVENT_CENTRAL_HYPOPNEA = 112,
|
||||
PRISMA_EVENT_HYPOPNEA_LEAKAGE = 113,
|
||||
PRISMA_EVENT_RERA = 121,
|
||||
PRISMA_EVENT_SNORE = 131,
|
||||
PRISMA_EVENT_ARTIFACT = 141,
|
||||
PRISMA_EVENT_FLOW_LIMITATION = 151,
|
||||
PRISMA_EVENT_CRITICAL_LEAKAGE = 161,
|
||||
PRISMA_EVENT_CS_RESPIRATION = 181,
|
||||
PRISMA_EVENT_TIMED_BREATH = 221,
|
||||
PRISMA_EVENT_EPOCH_DEEPSLEEP = 261,
|
||||
};
|
||||
|
||||
|
||||
|
||||
//********************************************************************************************
|
||||
|
||||
// Prisma WMEDF differs from the original EDF, by introducing 8 bit signal data channels.
|
||||
class WMEDFInfo : public EDFInfo {
|
||||
virtual bool ParseSignalData();
|
||||
|
||||
protected:
|
||||
qint8 Read8S();
|
||||
quint8 Read8U();
|
||||
|
||||
};
|
||||
|
||||
//********************************************************************************************
|
||||
|
||||
class PrismaLoader;
|
||||
class PrismaEventFile;
|
||||
|
||||
/*! \class PrismaImport
|
||||
* \brief Contains the functions to parse a single session... multithreaded */
|
||||
class PrismaImport:public ImportTask
|
||||
{
|
||||
public:
|
||||
PrismaImport(PrismaLoader * l, const MachineInfo& m, SessionID s, QByteArray e, QByteArray d): loader(l), machineInfo(m), sessionid(s), eventData(e), signalData(d) {}
|
||||
virtual ~PrismaImport() {};
|
||||
|
||||
//! \brief PrismaImport thread starts execution here.
|
||||
virtual void run();
|
||||
|
||||
protected:
|
||||
PrismaLoader * loader;
|
||||
const MachineInfo & machineInfo;
|
||||
SessionID sessionid;
|
||||
QByteArray eventData;
|
||||
QByteArray signalData;
|
||||
qint64 startdate;
|
||||
qint64 enddate;
|
||||
WMEDFInfo wmedf;
|
||||
PrismaEventFile * eventFile;
|
||||
Session * session;
|
||||
|
||||
void AddWaveform(ChannelID code, QString edfLabel);
|
||||
void AddEvents(ChannelID channel, Prisma_Event_Type eventType) {
|
||||
QList<Prisma_Event_Type> eventTypes = { eventType };
|
||||
AddEvents(channel, eventTypes);
|
||||
}
|
||||
void AddEvents(ChannelID channel, QList<Prisma_Event_Type> eventTypes);
|
||||
|
||||
};
|
||||
|
||||
//********************************************************************************************
|
||||
|
||||
/*! \class PrismaLoader
|
||||
\brief Löwenstein Prisma Loader Module
|
||||
*/
|
||||
class PrismaLoader : public CPAPLoader
|
||||
{
|
||||
Q_OBJECT
|
||||
static bool initialized;
|
||||
public:
|
||||
PrismaLoader();
|
||||
virtual ~PrismaLoader();
|
||||
|
||||
//! \brief Detect if the given path contains a valid Folder structure
|
||||
virtual bool Detect(const QString & path);
|
||||
|
||||
//! \brief Load MachineInfo structure.
|
||||
virtual MachineInfo PeekInfo(const QString & path);
|
||||
|
||||
//! \brief Scans directory path for valid Prisma signature
|
||||
virtual int Open(const QString & path);
|
||||
|
||||
//! \brief Returns the database version of this loader
|
||||
virtual int Version() { return prisma_data_version; }
|
||||
|
||||
//! \brief Return the loaderName, in this case "Prisma"
|
||||
virtual const QString &loaderName() { return prisma_class_name; }
|
||||
|
||||
//! \brief Register this Module to the list of Loaders, so it knows to search for Prisma data.
|
||||
static void Register();
|
||||
|
||||
//! \brief Generate a generic MachineInfo structure, with basic Prisma info to be expanded upon.
|
||||
virtual MachineInfo newInfo() {
|
||||
return MachineInfo(MT_CPAP, 0, prisma_class_name, QObject::tr("Löwenstein"), QObject::tr("Prisma Smart"), QString(), QString(), QObject::tr(""), QDateTime::currentDateTime(), prisma_data_version);
|
||||
}
|
||||
|
||||
virtual QString PresReliefLabel();
|
||||
virtual ChannelID CPAPModeChannel();
|
||||
virtual ChannelID PresReliefMode();
|
||||
|
||||
|
||||
//! \brief Called at application init, to set up any custom Prisma Channels
|
||||
virtual void initChannels();
|
||||
|
||||
QHash<SessionID, PrismaImport*> sesstasks;
|
||||
|
||||
protected:
|
||||
|
||||
MachineInfo PeekInfoFromConfig(const QString & selectedPath);
|
||||
|
||||
void ImportDataDir(QDir& dataDir, QSet<SessionID>& sessions, QHash<SessionID, QString>& eventFiles, QHash<SessionID, QString>& signalFiles);
|
||||
|
||||
//! \brief Scans the given directories for session data and create an import task for each logical session.
|
||||
void ScanFiles(const MachineInfo& info, const QString & path);
|
||||
};
|
||||
|
||||
//********************************************************************************************
|
||||
class PrismaEvent
|
||||
{
|
||||
public:
|
||||
PrismaEvent(int endTime, int duration, int pressure, int strength) : m_endTime(endTime), m_duration(duration), m_pressure(pressure), m_strenght(strength) {}
|
||||
int endTime() { return m_endTime; }
|
||||
int duration() { return m_duration; }
|
||||
int strength() { return m_strenght; }
|
||||
protected:
|
||||
int m_endTime;
|
||||
int m_duration;
|
||||
int m_pressure;
|
||||
int m_strenght;
|
||||
};
|
||||
|
||||
class PrismaEventFile
|
||||
{
|
||||
public:
|
||||
PrismaEventFile(QByteArray &buffer);
|
||||
QHash<int, int> getParameters() {return m_parameters; }
|
||||
QList<PrismaEvent> getEvents(int eventId) {return m_events.contains(eventId) ? m_events[eventId] : QList<PrismaEvent>(); }
|
||||
|
||||
protected:
|
||||
QHash<int, int> m_parameters;
|
||||
QHash<int, QList<PrismaEvent>> m_events;
|
||||
};
|
||||
|
||||
//********************************************************************************************
|
||||
|
||||
class PrismaModelInfo
|
||||
{
|
||||
protected:
|
||||
QHash<QString,const char*> m_modelNames;
|
||||
|
||||
public:
|
||||
PrismaModelInfo();
|
||||
bool IsTested(const QString & deviceId) const;
|
||||
const char* Name(const QString & deviceId) const;
|
||||
};
|
||||
|
||||
#endif // PRISMA_LOADER_H
|
@ -134,10 +134,12 @@ static const PRS1TestedModel s_PRS1TestedModels[] = {
|
||||
{ "700X150", 0, 6, "DreamStation Auto BiPAP" },
|
||||
|
||||
{ "410X150C", 0, 6, "DreamStation 2 CPAP" },
|
||||
{ "420X150C", 0, 6, "DreamStation 2 Advanced CPAP" }, // from FDA filing
|
||||
{ "520X110C", 0, 6, "DreamStation 2 Auto CPAP Advanced" }, // based on bottom label, boot screen says "Advanced Auto CPAP"
|
||||
{ "520X130C", 0, 6, "DreamStation 2 Auto CPAP Advanced" }, // from user report
|
||||
{ "520X150C", 0, 6, "DreamStation 2 Auto CPAP Advanced" }, // from user report
|
||||
{ "521X120C", 0, 6, "DreamStation 2 Auto CPAP Advanced with P-Flex" }, // inferred from 501X120 and presence of "P-Flex" on bottom label
|
||||
{ "521X140C", 0, 6, "DreamStation 2 avec GSM + Humidificateur" }, // from brochure
|
||||
|
||||
{ "950P", 5, 0, "BiPAP AutoSV Advanced System One" },
|
||||
{ "951P", 5, 0, "BiPAP AutoSV Advanced System One" },
|
||||
|
@ -2078,7 +2078,7 @@ bool PRS1DataChunk::ParseSettingsF0V6(const unsigned char* data, int size)
|
||||
// TODO: Confirm that 4 is 12HT and update ParseTubingTypeV3.
|
||||
this->ParseTubingTypeV3(data[pos]);
|
||||
break;
|
||||
case 0x48: // ??? Seen on DreamStation 2 non-Advanced (410)
|
||||
case 0x48: // ??? Seen on DreamStation 2 non-Advanced (410) but not either Advanced (420 or 520)
|
||||
// Appears between 0x2C (ramp time) and 0x2E (flex mode), with a value of 0-4.
|
||||
CHECK_VALUE(len, 1);
|
||||
if (data[pos] > 4) {
|
||||
|
@ -52,7 +52,7 @@ void ResmedLoader::LogUnexpectedMessage(const QString & message)
|
||||
m_importMutex.unlock();
|
||||
}
|
||||
|
||||
static const QVector<int> AS11TestedModels {39420, 39423, 0};
|
||||
static const QVector<int> AS11TestedModels {39420, 39421, 39423, 39485, 0};
|
||||
|
||||
ResmedLoader::ResmedLoader() {
|
||||
#ifndef UNITTEST_MODE
|
||||
|
@ -418,19 +418,23 @@ QList<ViatomFile::Record> ViatomFile::ReadData()
|
||||
QList<ViatomFile::Record> dedup;
|
||||
bool all_are_duplicated = true;
|
||||
|
||||
CHECK_VALUE(records.size() % 2, 0);
|
||||
for (int i = 0; i < records.size(); i += 2) {
|
||||
auto & a = records.at(i);
|
||||
auto & b = records.at(i+1);
|
||||
if (a.spo2 != b.spo2
|
||||
|| a.hr != b.hr
|
||||
|| a.oximetry_invalid != b.oximetry_invalid
|
||||
|| a.motion != b.motion
|
||||
|| a.vibration != b.vibration) {
|
||||
all_are_duplicated = false;
|
||||
break;
|
||||
if ((records.size() % 2) != 0) {
|
||||
// An odd number of samples inherently can't be all duplicates.
|
||||
all_are_duplicated = false;
|
||||
} else {
|
||||
for (int i = 0; i < records.size(); i += 2) {
|
||||
auto & a = records.at(i);
|
||||
auto & b = records.at(i+1);
|
||||
if (a.spo2 != b.spo2
|
||||
|| a.hr != b.hr
|
||||
|| a.oximetry_invalid != b.oximetry_invalid
|
||||
|| a.motion != b.motion
|
||||
|| a.vibration != b.vibration) {
|
||||
all_are_duplicated = false;
|
||||
break;
|
||||
}
|
||||
dedup.append(a);
|
||||
}
|
||||
dedup.append(a);
|
||||
}
|
||||
if (m_sig == 5) {
|
||||
// Confirm that CheckMe O2 Max is a true 2s sample rate.
|
||||
|
@ -27,7 +27,7 @@ ChannelID CPAP_IPAP, CPAP_IPAPLo, CPAP_IPAPHi, CPAP_EPAP, CPAP_EPAPLo, CPAP_EPAP
|
||||
CPAP_UserFlag1, CPAP_UserFlag2, CPAP_UserFlag3, /*CPAP_BrokenSummary, CPAP_BrokenWaveform,*/ CPAP_RDI,
|
||||
CPAP_PresReliefMode, CPAP_PresReliefLevel, CPAP_PSMin, CPAP_PSMax, CPAP_Test1,
|
||||
CPAP_Test2, CPAP_HumidSetting,
|
||||
CPAP_PressureSet, CPAP_IPAPSet, CPAP_EPAPSet;
|
||||
CPAP_PressureSet, CPAP_IPAPSet, CPAP_EPAPSet, CPAP_EEPAP;
|
||||
|
||||
|
||||
ChannelID RMS9_E01, RMS9_E02, RMS9_SetPressure, RMS9_MaskOnTime;
|
||||
|
@ -149,7 +149,7 @@ extern ChannelID AllAhiChannels;
|
||||
extern QVector<ChannelID> ahiChannels;
|
||||
|
||||
extern ChannelID NoChannel, SESSION_ENABLED, CPAP_SummaryOnly;
|
||||
extern ChannelID CPAP_IPAP, CPAP_IPAPLo, CPAP_IPAPHi, CPAP_EPAP, CPAP_EPAPLo, CPAP_EPAPHi,
|
||||
extern ChannelID CPAP_IPAP, CPAP_IPAPLo, CPAP_IPAPHi, CPAP_EPAP, CPAP_EPAPLo, CPAP_EPAPHi, CPAP_EEPAP,
|
||||
CPAP_Pressure, CPAP_PS, CPAP_PSMin, CPAP_PSMax,
|
||||
CPAP_Mode, CPAP_AHI,
|
||||
CPAP_PressureMin, CPAP_PressureMax, CPAP_Ramp, CPAP_RampTime, CPAP_RampPressure, CPAP_Obstructive,
|
||||
|
@ -138,6 +138,7 @@ void init()
|
||||
schema::channel.add(GRP_CPAP, new Channel(CPAP_EPAP = 0x110E, WAVEFORM, MT_CPAP, SESSION, "EPAP", STR_TR_EPAP, QObject::tr("Expiratory Pressure"), STR_TR_EPAP, STR_UNIT_CMH2O, DEFAULT, QColor("green")));
|
||||
schema::channel.add(GRP_CPAP, new Channel(CPAP_EPAPLo = 0x111C, WAVEFORM, MT_CPAP, SESSION, "EPAPLo", STR_TR_EPAPLo, QObject::tr("Lower Expiratory Pressure"), STR_TR_EPAPLo, STR_UNIT_CMH2O, DEFAULT, QColor("light blue")));
|
||||
schema::channel.add(GRP_CPAP, new Channel(CPAP_EPAPHi = 0x111D, WAVEFORM, MT_CPAP, SESSION, "EPAPHi", STR_TR_EPAPHi, QObject::tr("Higher Expiratory Pressure"), STR_TR_EPAPHi, STR_UNIT_CMH2O, DEFAULT, QColor("aqua")));
|
||||
schema::channel.add(GRP_CPAP, new Channel(CPAP_EEPAP = 0x11A7, WAVEFORM, MT_CPAP, SESSION, "EEPAP", STR_TR_EEPAP, QObject::tr("End Expiratory Pressure"), STR_TR_EEPAP, STR_UNIT_CMH2O, DEFAULT, QColor("purple")));
|
||||
schema::channel.add(GRP_CPAP, new Channel(CPAP_PS = 0x110F, WAVEFORM, MT_CPAP, SESSION, "PS", STR_TR_PS, QObject::tr("Pressure Support"), STR_TR_PS, STR_UNIT_CMH2O, DEFAULT, QColor("grey")));
|
||||
schema::channel.add(GRP_CPAP, new Channel(CPAP_PSMin = 0x111A, SETTING, MT_CPAP, SESSION, "PSMin", QObject::tr("PS Min") , QObject::tr("Pressure Support Minimum"), QObject::tr("PS Min"), STR_UNIT_CMH2O, DEFAULT, QColor("dark cyan")));
|
||||
schema::channel.add(GRP_CPAP, new Channel(CPAP_PSMax = 0x111B, SETTING, MT_CPAP, SESSION, "PSMax", QObject::tr("PS Max"), QObject::tr("Pressure Support Maximum"), QObject::tr("PS Max"), STR_UNIT_CMH2O, DEFAULT, QColor("dark magenta")));
|
||||
@ -172,7 +173,7 @@ void init()
|
||||
schema::channel.add(GRP_CPAP, new Channel(CPAP_VSnore = 0x1007, FLAG, MT_CPAP, SESSION, "VSnore",
|
||||
QObject::tr("Vibratory Snore (VS)"), QObject::tr("A vibratory snore"), QObject::tr("VS"), STR_UNIT_EventsPerHour, DEFAULT, QColor("red")));
|
||||
schema::channel.add(GRP_CPAP, new Channel(CPAP_VSnore2 = 0x1008, FLAG, MT_CPAP, SESSION, "VSnore2",
|
||||
QObject::tr("Vibratory Snore (VS2) "),QObject::tr("A vibratory snore as detcted by a System One device"),QObject::tr("VS2"), STR_UNIT_EventsPerHour, DEFAULT, QColor("red")));
|
||||
QObject::tr("Vibratory Snore (VS2) "),QObject::tr("A vibratory snore as detected by a System One device"),QObject::tr("VS2"), STR_UNIT_EventsPerHour, DEFAULT, QColor("red")));
|
||||
// This Large Leak record is just a flag marker, used by Intellipap for one
|
||||
schema::channel.add(GRP_CPAP, new Channel(CPAP_LeakFlag = 0x100a, FLAG, MT_CPAP, SESSION, "LeakFlag",
|
||||
QObject::tr("Leak Flag (LF)"), QObject::tr("A large mask leak affecting device performance."), QObject::tr("LF"), STR_UNIT_EventsPerHour, DEFAULT, QColor("light gray")));
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Update the string below to set OSCAR's version and release status.
|
||||
// See https://semver.org/spec/v2.0.0.html for details on format.
|
||||
|
||||
#define VERSION "1.3.5-alpha.3"
|
||||
#define VERSION "1.4.1-alpha-1"
|
||||
|
@ -50,6 +50,13 @@ const QString STR_GRAPH_Oxi_Plethy = "Plethy";
|
||||
const QString STR_GRAPH_Oxi_Perf = "Perf. Index";
|
||||
const QString STR_GRAPH_Oxi_PulseChange = "PulseChange";
|
||||
const QString STR_GRAPH_Oxi_SPO2Drop = "SPO2Drop";
|
||||
const QString STR_GRAPH_ObstructLevel = "ObstructLevel";
|
||||
const QString STR_GRAPH_PressureMeasured = "PressureMeasured";
|
||||
const QString STR_GRAPH_rRMV = "rRMV";
|
||||
const QString STR_GRAPH_rMVFluctuation = "rMVFluctuation";
|
||||
const QString STR_GRAPH_FlowFull = "FlowFull";
|
||||
const QString STR_GRAPH_SPRStatus = "SPRStatus";
|
||||
|
||||
|
||||
//OXI_Pulse, OXI_SPO2, OXI_Perf, OXI_Plethy
|
||||
|
||||
|
@ -7,6 +7,9 @@
|
||||
* License. See the file COPYING in the main directory of the source code
|
||||
* for more details. */
|
||||
|
||||
#define TEST_MACROS_ENABLEDoff
|
||||
#include <test_macros.h>
|
||||
|
||||
#include <QTextCharFormat>
|
||||
#include <QPalette>
|
||||
#include <QTextBlock>
|
||||
@ -57,6 +60,7 @@ QString htmlLeftSessionInfo;
|
||||
QString htmlLeftFooter;
|
||||
|
||||
extern ChannelID PRS1_PeakFlow;
|
||||
extern ChannelID Prisma_ObstructLevel, Prisma_rMVFluctuation, Prisma_rRMV, Prisma_PressureMeasured, Prisma_FlowFull, Prisma_SPRStatus;
|
||||
|
||||
// This was Sean Stangl's idea.. but I couldn't apply that patch.
|
||||
inline QString channelInfo(ChannelID code) {
|
||||
@ -82,7 +86,8 @@ const QList<QString> standardGraphOrder = {STR_GRAPH_SleepFlags, STR_GRAPH_FlowR
|
||||
STR_GRAPH_PTB, STR_GRAPH_RespEvent, STR_GRAPH_Ti, STR_GRAPH_Te,
|
||||
STR_GRAPH_SleepStage, STR_GRAPH_Inclination, STR_GRAPH_Orientation, STR_GRAPH_Motion, STR_GRAPH_TestChan1,
|
||||
STR_GRAPH_Oxi_Pulse, STR_GRAPH_Oxi_SPO2, STR_GRAPH_Oxi_Perf, STR_GRAPH_Oxi_Plethy,
|
||||
STR_GRAPH_AHI, STR_GRAPH_TAP
|
||||
STR_GRAPH_AHI, STR_GRAPH_TAP, STR_GRAPH_ObstructLevel, STR_GRAPH_PressureMeasured, STR_GRAPH_rRMV, STR_GRAPH_rMVFluctuation,
|
||||
STR_GRAPH_FlowFull, STR_GRAPH_SPRStatus
|
||||
};
|
||||
|
||||
// Advanced graph order
|
||||
@ -91,7 +96,8 @@ const QList<QString> advancedGraphOrder = {STR_GRAPH_SleepFlags, STR_GRAPH_FlowR
|
||||
STR_GRAPH_RespRate, STR_GRAPH_PTB, STR_GRAPH_RespEvent,
|
||||
STR_GRAPH_SleepStage, STR_GRAPH_Inclination, STR_GRAPH_Orientation, STR_GRAPH_Motion, STR_GRAPH_TestChan1,
|
||||
STR_GRAPH_Oxi_Pulse, STR_GRAPH_Oxi_SPO2, STR_GRAPH_Oxi_Perf, STR_GRAPH_Oxi_Plethy,
|
||||
STR_GRAPH_AHI, STR_GRAPH_TAP
|
||||
STR_GRAPH_AHI, STR_GRAPH_TAP, STR_GRAPH_ObstructLevel, STR_GRAPH_PressureMeasured, STR_GRAPH_rRMV, STR_GRAPH_rMVFluctuation,
|
||||
STR_GRAPH_FlowFull, STR_GRAPH_SPRStatus
|
||||
};
|
||||
|
||||
// CPAP modes that should have Advanced graphs
|
||||
@ -240,7 +246,8 @@ Daily::Daily(QWidget *parent,gGraphView * shared)
|
||||
const ChannelID cpapcodes[] = {
|
||||
CPAP_FlowRate, CPAP_Pressure, CPAP_Leak, CPAP_FLG, CPAP_Snore, CPAP_TidalVolume,
|
||||
CPAP_MaskPressure, CPAP_RespRate, CPAP_MinuteVent, CPAP_PTB, PRS1_PeakFlow, CPAP_RespEvent, CPAP_Ti, CPAP_Te,
|
||||
/* CPAP_IE, */ ZEO_SleepStage, POS_Inclination, POS_Orientation, POS_Movement, CPAP_Test1
|
||||
/* CPAP_IE, */ ZEO_SleepStage, POS_Inclination, POS_Orientation, POS_Movement, CPAP_Test1,
|
||||
Prisma_ObstructLevel, Prisma_rRMV, Prisma_rMVFluctuation, Prisma_PressureMeasured, Prisma_FlowFull, Prisma_SPRStatus
|
||||
};
|
||||
|
||||
// Create graphs from the cpap code list
|
||||
@ -355,6 +362,7 @@ Daily::Daily(QWidget *parent,gGraphView * shared)
|
||||
pc->addPlot(CPAP_IPAPLo, square);
|
||||
pc->addPlot(CPAP_IPAP, square);
|
||||
pc->addPlot(CPAP_IPAPHi, square);
|
||||
pc->addPlot(CPAP_EEPAP, square);
|
||||
pc->addPlot(CPAP_PressureSet, false);
|
||||
pc->addPlot(CPAP_EPAPSet, false);
|
||||
pc->addPlot(CPAP_IPAPSet, false);
|
||||
@ -393,6 +401,14 @@ Daily::Daily(QWidget *parent,gGraphView * shared)
|
||||
|
||||
graphlist[schema::channel[CPAP_PTB].code()]->AddLayer(new gLineChart(CPAP_PTB, square));
|
||||
graphlist[schema::channel[PRS1_PeakFlow].code()]->AddLayer(new gLineChart(PRS1_PeakFlow, square));
|
||||
|
||||
graphlist[schema::channel[Prisma_ObstructLevel].code()]->AddLayer(new gLineChart(Prisma_ObstructLevel, square));
|
||||
graphlist[schema::channel[Prisma_PressureMeasured].code()]->AddLayer(new gLineChart(Prisma_PressureMeasured, square));
|
||||
graphlist[schema::channel[Prisma_rRMV].code()]->AddLayer(new gLineChart(Prisma_rRMV, square));
|
||||
graphlist[schema::channel[Prisma_rMVFluctuation].code()]->AddLayer(new gLineChart(Prisma_rMVFluctuation, square));
|
||||
graphlist[schema::channel[Prisma_FlowFull].code()]->AddLayer(new gLineChart(Prisma_FlowFull, square));
|
||||
graphlist[schema::channel[Prisma_SPRStatus].code()]->AddLayer(new gLineChart(Prisma_SPRStatus, square));
|
||||
|
||||
graphlist[schema::channel[CPAP_Test1].code()]->AddLayer(new gLineChart(CPAP_Test1, square));
|
||||
//graphlist[schema::channel[CPAP_Test2].code()]->AddLayer(new gLineChart(CPAP_Test2, square));
|
||||
|
||||
@ -1325,6 +1341,7 @@ QString Daily::getStatisticsInfo(Day * day)
|
||||
ChannelID chans[]={
|
||||
CPAP_Pressure,CPAP_PressureSet,CPAP_EPAP,CPAP_EPAPSet,CPAP_IPAP,CPAP_IPAPSet,CPAP_PS,CPAP_PTB,
|
||||
PRS1_PeakFlow,
|
||||
Prisma_ObstructLevel, Prisma_PressureMeasured, Prisma_rRMV, Prisma_rMVFluctuation,
|
||||
CPAP_MinuteVent, CPAP_RespRate, CPAP_RespEvent,CPAP_FLG,
|
||||
CPAP_Leak, CPAP_LeakTotal, CPAP_Snore, /* CPAP_IE, */ CPAP_Ti,CPAP_Te, CPAP_TgMV,
|
||||
CPAP_TidalVolume, OXI_Pulse, OXI_SPO2, POS_Inclination, POS_Orientation, POS_Movement
|
||||
@ -2644,6 +2661,7 @@ void Daily::on_graphCombo_activated(int index)
|
||||
|
||||
g=GraphView->findGraphTitle(s);
|
||||
g->setVisible(b);
|
||||
ui->graphCombo->showPopup();
|
||||
}
|
||||
ui->graphCombo->setCurrentIndex(0);
|
||||
|
||||
@ -2749,6 +2767,7 @@ void Daily::on_eventsCombo_activated(int index)
|
||||
bool b = !chan->enabled();
|
||||
chan->setEnabled(b);
|
||||
ui->eventsCombo->setItemIcon(index,b ? *icon_on : *icon_off);
|
||||
ui->eventsCombo->showPopup();
|
||||
}
|
||||
|
||||
ui->eventsCombo->setCurrentIndex(0);
|
||||
|
@ -23,23 +23,26 @@ void MyOutputHandler(QtMsgType type, const QMessageLogContext &context, const QS
|
||||
return;
|
||||
}
|
||||
|
||||
QString msg, typestr;
|
||||
QString msg, typestr, contextstr;
|
||||
#ifdef VERBOSE_LOGGING
|
||||
contextstr = QString(context.file) + " " + context.function + ":" + QString::number(context.line) + " ";
|
||||
#endif
|
||||
|
||||
switch (type) {
|
||||
case QtWarningMsg:
|
||||
typestr = QString("Warning: ");
|
||||
typestr = QString("Warning: ") + contextstr;
|
||||
break;
|
||||
|
||||
case QtFatalMsg:
|
||||
typestr = QString("Fatal: ");
|
||||
typestr = QString("Fatal: ") + contextstr;
|
||||
break;
|
||||
|
||||
case QtCriticalMsg:
|
||||
typestr = QString("Critical: ");
|
||||
typestr = QString("Critical: ") + contextstr;
|
||||
break;
|
||||
|
||||
default:
|
||||
typestr = QString("Debug: ");
|
||||
typestr = QString("Debug: ") + contextstr;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "SleepLib/loader_plugins/sleepstyle_loader.h"
|
||||
#include "SleepLib/loader_plugins/weinmann_loader.h"
|
||||
#include "SleepLib/loader_plugins/viatom_loader.h"
|
||||
#include "SleepLib/loader_plugins/prisma_loader.h"
|
||||
|
||||
MainWindow *mainwin = nullptr;
|
||||
|
||||
@ -691,6 +692,7 @@ int main(int argc, char *argv[]) {
|
||||
CMS50F37Loader::Register();
|
||||
MD300W1Loader::Register();
|
||||
ViatomLoader::Register();
|
||||
PrismaLoader::Register();
|
||||
|
||||
// Begin logging device connection activity.
|
||||
QString connectionsLogDir = GetLogDir() + "/connections";
|
||||
|
@ -1993,7 +1993,7 @@ void MainWindow::purgeMachine(Machine * mach)
|
||||
p_profile->StoreMachines();
|
||||
} else {
|
||||
QMessageBox::warning(this, STR_MessageBox_Error,
|
||||
tr("A file permission error casued the purge process to fail; you will have to delete the following folder manually:") +
|
||||
tr("A file permission error caused the purge process to fail; you will have to delete the following folder manually:") +
|
||||
"\n\n" + QDir::toNativeSeparators(mach->getDataPath()), QMessageBox::Ok, QMessageBox::Ok);
|
||||
|
||||
if (overview)
|
||||
@ -2553,9 +2553,15 @@ void MainWindow::on_actionDaily_Calendar_toggled(bool visible)
|
||||
|
||||
void MainWindow::on_actionShowPersonalData_toggled(bool visible)
|
||||
{
|
||||
AppSetting->setShowPersonalData(visible);
|
||||
if (!setupRunning)
|
||||
GenerateStatistics();
|
||||
// This uses the Prefs routines, which require p_profile to be set
|
||||
if ( p_profile != nullptr ) {
|
||||
AppSetting->setShowPersonalData(visible);
|
||||
if ( ! setupRunning )
|
||||
GenerateStatistics();
|
||||
} else {
|
||||
QMessageBox::information(this, "OSCAR", tr("You must select and open the profile you wish to modify"),
|
||||
QMessageBox::Ok);
|
||||
}
|
||||
}
|
||||
|
||||
#include "SleepLib/journal.h"
|
||||
|
@ -301,6 +301,7 @@ SOURCES += \
|
||||
SleepLib/loader_plugins/sleepstyle_EDFinfo.cpp \
|
||||
SleepLib/loader_plugins/intellipap_loader.cpp \
|
||||
SleepLib/loader_plugins/mseries_loader.cpp \
|
||||
SleepLib/loader_plugins/prisma_loader.cpp \
|
||||
SleepLib/loader_plugins/prs1_loader.cpp \
|
||||
SleepLib/loader_plugins/prs1_parser.cpp \
|
||||
SleepLib/loader_plugins/prs1_parser_xpap.cpp \
|
||||
@ -403,6 +404,7 @@ HEADERS += \
|
||||
SleepLib/loader_plugins/sleepstyle_EDFinfo.h \
|
||||
SleepLib/loader_plugins/intellipap_loader.h \
|
||||
SleepLib/loader_plugins/mseries_loader.h \
|
||||
SleepLib/loader_plugins/prisma_loader.h \
|
||||
SleepLib/loader_plugins/prs1_loader.h \
|
||||
SleepLib/loader_plugins/prs1_parser.h \
|
||||
SleepLib/loader_plugins/resmed_loader.h \
|
||||
|
@ -7,25 +7,8 @@
|
||||
* License. See the file COPYING in the main directory of the source code
|
||||
* for more details. */
|
||||
|
||||
#define NEWSTUFF
|
||||
|
||||
#define xDEBUG_FUNCTIONS
|
||||
#ifdef DEBUG_FUNCTIONS
|
||||
#include <QRegularExpression>
|
||||
#define DEBUGQ qDebug()
|
||||
#define DEBUGL qDebug()<<QString(basename( __FILE__)).remove(QRegularExpression("\\..*$")) << __LINE__
|
||||
#define DEBUGF qDebug()<< QString("%1[%2]%3").arg( QString(basename( __FILE__)).remove(QRegularExpression("\\..*$")) ).arg(__LINE__).arg(__func__)
|
||||
#define DEBUGT qDebug()<<QDateTime::currentDateTime().time().toString("hh:mm:ss.zzz")
|
||||
#define DEBUGTF qDebug()<<QDateTime::currentDateTime().time().toString("hh:mm:ss.zzz") << QString(basename( __FILE__)).remove(QRegularExpression("\\..*$")) << __LINE__ << __func__
|
||||
#define O( XX ) " " #XX ":" << XX
|
||||
#define Q( XX ) << #XX ":" << XX
|
||||
#define R( XX )
|
||||
#define OO( XX , YY ) " " #XX ":" << YY
|
||||
#define NAME( id) schema::channel[ id ].label()
|
||||
#define DATE( XX ) QDateTime::fromMSecsSinceEpoch(XX).toString("dd MMM yyyy")
|
||||
#define DATETIME( XX ) QDateTime::fromMSecsSinceEpoch(XX).toString("dd MMM yyyy hh:mm:ss.zzz")
|
||||
#endif
|
||||
|
||||
#define TEST_MACROS_ENABLEDoff
|
||||
#include <test_macros.h>
|
||||
|
||||
// Features enabled by conditional compilation.
|
||||
#define ENABLE_GENERAL_MODIFICATION_OF_CALENDARS
|
||||
@ -890,6 +873,7 @@ void Overview::on_graphCombo_activated(int index)
|
||||
|
||||
g = GraphView->findGraphTitle(s);
|
||||
g->setVisible(b);
|
||||
ui->graphCombo->showPopup();
|
||||
}
|
||||
ui->graphCombo->setCurrentIndex(0);
|
||||
updateCube();
|
||||
@ -939,3 +923,4 @@ void Overview::on_toggleVisibility_clicked(bool checked)
|
||||
GraphView->updateScale();
|
||||
GraphView->redraw();
|
||||
}
|
||||
|
||||
|
@ -38,74 +38,75 @@ To turn off the the test macros.
|
||||
#include <QRegularExpression>
|
||||
#include <QFileInfo>
|
||||
|
||||
#define DEBUGL qDebug() <<QString("%1[%2]").arg(QFileInfo( __FILE__).baseName()).arg(__LINE__)
|
||||
//example:
|
||||
//12361: Debug: "gGraphView[572]"
|
||||
#define DEBUGQ qDebug().noquote()
|
||||
#define DEBUGL DEBUGQ <<QString("%1[%2]").arg(QFileInfo( __FILE__).baseName()).arg(__LINE__)
|
||||
#define DEBUGF DEBUGQ <<QString("%1[%2]%3").arg(QFileInfo( __FILE__).baseName()).arg(__LINE__).arg(__func__)
|
||||
#define DEBUGT DEBUGQ <<QString("%1 %2[%3]%4").arg(QDateTime::currentDateTime().time().toString("hh:mm:ss.zzz")).arg(QFileInfo( __FILE__).baseName()).arg(__LINE__)
|
||||
#define DEBUGTF DEBUGQ <<QString("%1 %2[%3]%4").arg(QDateTime::currentDateTime().time().toString("hh:mm:ss.zzz")).arg(QFileInfo( __FILE__).baseName()).arg(__LINE__).arg(__func__)
|
||||
|
||||
|
||||
#define DEBUGF qDebug() <<QString("%1[%2]%3").arg(QFileInfo( __FILE__).baseName()).arg(__LINE__).arg(__func__)
|
||||
//example:
|
||||
//12361: Debug: "gGraphView[572]popoutGraph"
|
||||
|
||||
|
||||
#define DEBUGT qDebug() <<QString("%1 %2[%3]%4").arg(QDateTime::currentDateTime().time().toString("hh:mm:ss.zzz")).arg(QFileInfo( __FILE__).baseName()).arg(__LINE__)
|
||||
//example:
|
||||
//12645: Debug: "06:00:18.284 gGraphView[622]"
|
||||
|
||||
#define DEBUGTF qDebug() <<QString("%1 %2[%3]%4").arg(QDateTime::currentDateTime().time().toString("hh:mm:ss.zzz")).arg(QFileInfo( __FILE__).baseName()).arg(__LINE__).arg(__func__)
|
||||
//example:
|
||||
//12645: Debug: "06:00:18.284 gGraphView[622]popoutGraph"
|
||||
|
||||
// Macros to display variables
|
||||
// Do nothing
|
||||
#define Z( EXPRESSION ) /* comment out display of variable */
|
||||
#define ZZ( A ,EXPRESSION ) /* comment out display of variable */
|
||||
// Macros to display variables
|
||||
#define O( EXPRESSION ) << EXPRESSION
|
||||
|
||||
// return values from functions donr't work - QQ macro instead
|
||||
#define Q( VALUE ) << "" #VALUE ":" << VALUE
|
||||
//example:
|
||||
|
||||
//
|
||||
#define Q( VALUE ) << "" #VALUE ":" << VALUE
|
||||
#define QQ( TEXT , EXPRESSION) << #TEXT ":" << EXPRESSION
|
||||
//example:
|
||||
//#define Q( VALUE ) << QString("%1:%2").arg( "" #VALUE).arg(VALUE)
|
||||
//#define QQ( TEXT , EXPRESSION) << QString("%1:%2").arg( "" #TEXT).arg(VALUE)
|
||||
|
||||
#define NAME( SCHEMECODE ) << schema::channel[ SCHEMECODE ].label()
|
||||
//example:
|
||||
#define NAME( SCHEMACODE ) << schema::channel[ SCHEMACODE ].label()
|
||||
#define FULLNAME( SCHEMACODE ) << schema::channel[ SCHEMAcODE ].fullname()
|
||||
|
||||
#define FULLNAME( SCHEMECODE ) << schema::channel[ SCHEMEcODE ].fullname()
|
||||
//example:
|
||||
|
||||
//display the date of an epoch time stamp "qint64"
|
||||
//display the date of an epoch time stamp "qint64"
|
||||
#define DATE( EPOCH ) << QDateTime::fromMSecsSinceEpoch( EPOCH ).toString("dd MMM yyyy")
|
||||
|
||||
//display the date and Time of an epoch time stamp "qint64"
|
||||
//display the date and Time of an epoch time stamp "qint64"
|
||||
#define DATETIME( EPOCH ) << QDateTime::fromMSecsSinceEpoch( EPOCH ).toString("dd MMM yyyy hh:mm:ss.zzz")
|
||||
|
||||
/*
|
||||
sample Lines.
|
||||
|
||||
code
|
||||
DEBUGF Q(name) Q(title) QQ("UNITS",units) Q(height) Q(group);
|
||||
output
|
||||
00791: Debug: "gGraph[137]gGraph" name: "RespRate" title: "Respiratory Rate" "UNITS": "Rate of breaths per minute" height: 180 group: 0
|
||||
#ifdef __clang__
|
||||
#define COMPILER O(QString("clang++:%1").arg(__clang_version__) );
|
||||
#elif __GNUC_VERSION__
|
||||
#define COMPILER O(QString("GNUC++:%1").arg("GNUC").arg(__GNUC_VERSION__)) ;
|
||||
#else
|
||||
#define COMPILER
|
||||
#endif
|
||||
|
||||
|
||||
DEBUGTF Q(newname);
|
||||
12645: Debug: "06:00:18.284 gGraphView[622]popoutGraph" newname: "Pressure - Friday, April 15, 2022"
|
||||
|
||||
#if 0
|
||||
//example: DEBUGL;
|
||||
//12361: Debug: "gGraphView[572]"
|
||||
|
||||
DEBUGF NAME(dot.code) Q(dot.type) QQ(y,(int)y) Q(ratioX) O(QLine(left + 1, y, left + 1 + width, y)) Q(legendx) O(dot.value) ;
|
||||
92 00917: Debug: "gLineChart[568]paint" "Pressure" dot.type: 4 y: 341 ratioX: 1 QLine(QPoint(91,341),QPoint(464,341)) legendx: 463 12.04
|
||||
//example: DEBUGF;
|
||||
//12361: Debug: "gGraphView[572]popoutGraph"
|
||||
|
||||
//example: DEBUGT;
|
||||
//12645: Debug: "06:00:18.284 gGraphView[622]"
|
||||
|
||||
*/
|
||||
//example: DEBUGTF;
|
||||
//12645: Debug: "06:00:18.284 gGraphView[622]popoutGraph"
|
||||
|
||||
//example: DEBUGF Q(name) Q(title) QQ("UNITS",units) Q(height) Q(group);
|
||||
//00791: Debug: "gGraph[137]gGraph" name: "RespRate" title: "Respiratory Rate" "UNITS": "Rate of breaths per minute" height: 180 group: 0
|
||||
|
||||
//example: DEBUGTF Q(newname);
|
||||
//12645: Debug: "06:00:18.284 gGraphView[622]popoutGraph" newname:"Pressure - Friday, April 15, 2022"
|
||||
|
||||
//example: DEBUGF NAME(dot.code) Q(dot.type) QQ(y,(int)y) Q(ratioX) O(QLine(left + 1, y, left + 1 + width, y)) Q(legendx) O(dot.value) ;
|
||||
//92 00917: Debug: "gLineChart[568]paint" "Pressure" dot.type: 4 y: 341 ratioX: 1 QLine(QPoint(91,341),QPoint(464,341)) legendx: 463 12.04
|
||||
#endif
|
||||
|
||||
#else
|
||||
// Turn debugging off. macros expands to white space
|
||||
|
||||
#define DEBUGQ
|
||||
#define DEBUGL
|
||||
#define DEBUGF
|
||||
#define DEBUGT
|
||||
#define DEBUGTF
|
||||
|
||||
#define Z( XX )
|
||||
#define ZZ( XX , YY)
|
||||
#define O( XX )
|
||||
#define Q( XX )
|
||||
#define QQ( XX , YY )
|
||||
@ -113,6 +114,7 @@ DEBUGF NAME(dot.code) Q(dot.type) QQ(y,(int)y) Q(ratioX) O(QLine(left + 1, y, le
|
||||
#define FULLNAME( id)
|
||||
#define DATE( XX )
|
||||
#define DATETIME( XX )
|
||||
#define COMPILER
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -53,15 +53,16 @@ void initTranslations()
|
||||
langNames["fi"] = "Suomen kieli";
|
||||
langNames["fr"] = "Français";
|
||||
langNames["he"] = "\xd7\xa2\xd7\x91\xd7\xa8\xd7\x99\xd7\xaa";
|
||||
langNames["hu"] = "Magyar nyelv";
|
||||
langNames["hu"] = "Magyar";
|
||||
langNames["ja"] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e";
|
||||
langNames["ko"] = "\xed\x95\x9c\xea\xb5\xad\xec\x96\xb4";
|
||||
langNames["nl"] = "Nederlands";
|
||||
langNames["pt"] = "Português";
|
||||
langNames["pt_BR"] = "Português (Brazil)";
|
||||
langNames["ro"] = "Românește";
|
||||
langNames["tr"] = "Türkçe";
|
||||
langNames["ru"] = "\xd1\x80\xd1\x83\xd1\x81\xd1\x81\xd0\xba\xd0\xb8\xd0\xb9";
|
||||
langNames["th"] = "\xe0\xb8\xa0\xe0\xb8\xb2\xe0\xb8\xa9\xe0\xb8\xb2\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2";
|
||||
langNames["tr"] = "Türkçe";
|
||||
langNames["zh_CN"] = "\xe5\x8d\x8e\xe8\xaf\xad\xe7\xae\x80\xe4\xbd\x93\xe5\xad\x97 \x2d \xe4\xb8\xad\xe5\x9b\xbd";
|
||||
langNames["zh_TW"] = "\xe8\x8f\xaf\xe8\xaa\x9e\xe6\xad\xa3\xe9\xab\x94\xe5\xad\x97 \x2d \xe8\x87\xba\xe7\x81\xa3";
|
||||
|
||||
|
@ -179,6 +179,7 @@ QString Welcome::GenerateCPAPHTML()
|
||||
QString daystring;
|
||||
if (daysto == 1) daystring += tr("last night");
|
||||
else if (daysto == 2) daystring += tr("1 day ago");
|
||||
else if (daysto == 0) daystring += tr("today");
|
||||
else daystring += tr("%2 days ago").arg(daysto-1);
|
||||
|
||||
html += tr("was %1 (on %2)").arg(daystring).arg(date.toString(Qt::SystemLocaleLongDate)) + "<br/>";
|
||||
|
Loading…
Reference in New Issue
Block a user