Merge branch 'master' into translations

This commit is contained in:
ArieKlerk 2020-05-28 13:09:37 +02:00
commit a58ad16e38
13 changed files with 344 additions and 193 deletions

View File

@ -29,16 +29,12 @@ Run the installer, accepting options to install inno script studio (for possible
Go to <https://gitforwindows.org/> and click on the Download button. Run the installer, which presents lots of options:
- Select whichever editor you desire.
- Select “Use Git from the command line and also from 3rd-party software.”
- Select “Use the OpenSSL library.”
- Select “Checkout Windows-style, commit Unix-style line endings.”
- Select “Use Windows default console window.” I find the Windows default console to be satisfactory on Windows 10.
- Leave extra options as they default (enable file system caching, enable Git credential manager, but not symbolic links).
- Select "Enable symbolic links"
- Leave other extra options as they default (enable file system caching, enable Git credential manager).
GIT for Windows adds itself to your path.

View File

@ -106,7 +106,7 @@
</message>
<message>
<source> i </source>
<translation type="unfinished">Italique</translation>
<translation> Italique </translation>
</message>
<message>
<source>Big</source>
@ -266,7 +266,7 @@
</message>
<message>
<source>&quot;Nothing&apos;s here!&quot;</source>
<translation>Rien ici !</translation>
<translation>&quot;Rien ici !&quot;</translation>
</message>
<message>
<source>Awesome</source>
@ -442,7 +442,7 @@
</message>
<message>
<source>This bookmark is in a currently disabled area..</source>
<translation>Ce favori est actuellement en zone désactivée...</translation>
<translation>Ce favori est actuellement en zone désactivée..</translation>
</message>
</context>
<context>
@ -533,7 +533,7 @@
</message>
<message>
<source>Last Month</source>
<translation>Dernier mois</translation>
<translation>Mois dernier</translation>
</message>
<message>
<source>Last 6 Months</source>
@ -1507,7 +1507,7 @@
</message>
<message>
<source>D.O.B.</source>
<translation> le</translation>
<translation> le.</translation>
</message>
<message>
<source>Female</source>
@ -1743,7 +1743,7 @@ respiratoires</translation>
</message>
<message>
<source>Last Three Months</source>
<translation>Derniers 3 mois</translation>
<translation>3 derniers mois</translation>
</message>
<message>
<source>Total Time in Apnea
@ -1775,7 +1775,7 @@ respiratoires</translation>
</message>
<message>
<source>Last Month</source>
<translation>Dernier mois</translation>
<translation>Mois dernier</translation>
</message>
<message>
<source>Apnea
@ -1801,7 +1801,7 @@ corporelle</translation>
</message>
<message>
<source>Last Two Weeks</source>
<translation>Dernières 2 semaines</translation>
<translation>2 dernières semaines</translation>
</message>
<message>
<source>Everything</source>
@ -1813,7 +1813,7 @@ corporelle</translation>
</message>
<message>
<source>Last Year</source>
<translation>Dernière année</translation>
<translation>Année dernière</translation>
</message>
<message>
<source>Toggle Graph Visibility</source>
@ -1825,7 +1825,7 @@ corporelle</translation>
</message>
<message>
<source>Last Two Months</source>
<translation>Derniers 2 mois</translation>
<translation>2 derniers mois</translation>
</message>
</context>
<context>
@ -1884,7 +1884,7 @@ corporelle</translation>
</message>
<message>
<source>Oximeter import completed..</source>
<translation>Import terminé...</translation>
<translation>Import terminé..</translation>
</message>
<message>
<source>&amp;Retry</source>
@ -3241,7 +3241,7 @@ To use it with ResScan will require the .gz files to be uncompressed first..</so
Format courant sous Linux et Mac.
OSCAR peut importer de ce répertoire de sauvegarde compressé en mode natif.
Pour l&apos;utiliser avec ResScan, il faudra d&apos;abord décompresser les fichiers *.gz...</translation>
Pour l&apos;utiliser avec ResScan, il faudra d&apos;abord décompresser les fichiers *.gz..</translation>
</message>
<message>
<source>The following options affect the amount of disk space OSCAR uses, and have an effect on how long import takes.</source>
@ -3269,7 +3269,7 @@ OSCAR can keep a copy of this data if you ever need to reinstall.
<translation>Garde un copie de la carte SD des appareils ResMed.
Les appareils ResMed effacent les données précises après 7 jours, et les graphiques de plus de 30 jours...
OSCAR peut garder ces données au cas vous devriez réinstaller (Hautement recommandé, à moins que vous n&apos;ayez pas de place disque ou que les graphiques ne vous intéressent pas).</translation>
OSCAR peut garder ces données au cas vous devriez réinstaller (Hautement recommandé, à moins que vous n&apos;ayez pas de place disque ou que les graphiques ne vous intéressent pas)</translation>
</message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Makes starting OSCAR a bit slower, by pre-loading all the summary data in advance, which speeds up overview browsing and a few other calculations later on. &lt;/p&gt;&lt;p&gt;If you have a large amount of data, it might be worth keeping this switched off, but if you typically like to view &lt;span style=&quot; font-style:italic;&quot;&gt;everything&lt;/span&gt; in overview, all the summary data still has to be loaded anyway. &lt;/p&gt;&lt;p&gt;Note this setting doesn&apos;t affect waveform and event data, which is always demand loaded as needed.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
@ -3814,7 +3814,7 @@ p, li { white-space: pre-wrap; }
</message>
<message>
<source>Kg</source>
<translation> Kg</translation>
<translation>Kg</translation>
</message>
<message>
<source>O2</source>
@ -6844,7 +6844,7 @@ corporelle</translation>
</message>
<message>
<source>Last 30 Days</source>
<translation>Dernier mois</translation>
<translation>Mois dernier</translation>
</message>
<message>
<source>%1 Index</source>
@ -6892,7 +6892,7 @@ corporelle</translation>
</message>
<message>
<source>Last 6 Months</source>
<translation>6 Derniers mois</translation>
<translation>6 derniers mois</translation>
</message>
<message>
<source>Average %1</source>
@ -6924,7 +6924,7 @@ corporelle</translation>
</message>
<message>
<source>Last Year</source>
<translation>Dernière année</translation>
<translation>Année dernière</translation>
</message>
<message>
<source>Details</source>

View File

@ -116,7 +116,9 @@ void gLineChart::SetDay(Day *d)
Session *sess = d->sessions[i];
if (!sess->enabled()) continue;
CPAPMode mode = (CPAPMode)sess->settings[CPAP_Mode].toInt();
// Don't use operator[] here or else it will insert a default-constructed entry
// into sess->settings if it's not present.
CPAPMode mode = (CPAPMode)sess->settings.value(CPAP_Mode).toInt();
if (mode >= MODE_BILEVEL_FIXED) {
m_enabled[CPAP_Pressure] = true; // probably a confusion of Pressure and IPAP somewhere

View File

@ -223,7 +223,10 @@ void gLineOverlayBar::paint(QPainter &painter, gGraph &w, const QRegion &region)
painter.drawRect(rect);
// Queue tooltip
QString lab2 = QString("%1 (%2)").arg(schema::channel[m_code].fullname()).arg(raw);
QString lab2 = QString("%1").arg(schema::channel[m_code].fullname());
if (raw != 0) // Hide duration when it is zero
lab2 += QString(" (%1)").arg(raw);
w.ToolTip(lab2, x1 - 10, start_py + 24 + (3 * w.printScaleY()), TT_AlignRight, AppSetting->tooltipTimeout());
painter.setPen(QPen(col,3));

View File

@ -308,6 +308,13 @@ EventDataType Day::settings_wavg(ChannelID code)
auto set = sess->settings.find(code);
if (set != sess->settings.end()) {
if (code == CPAP_Mode && sess->type() != MT_CPAP) {
// There used to be a bug in gLineChart::SetDay that inserted a CPAP_Mode
// setting in any session that didn't already have one. That shouldn't
// happen any more, but leave this diagnostic message here in case it does.
qWarning() << sess->session() << "non-CPAP session with CPAP mode setting";
continue;
}
s0 = sess->hours();
tmp = set.value().toDouble();
s1 += tmp * s0;

View File

@ -16,6 +16,11 @@
#include <QDir>
#include <QMessageBox>
#define NEWXML
#ifdef NEWXML
#include <QXmlStreamWriter>
#endif
const int journal_data_version = 1;
JournalEntry::JournalEntry(QDate date)
@ -205,7 +210,105 @@ void JournalEntry::delBookmark(qint64 start, qint64 end)
// if I wanted to be nice above, I could add the note string to the search as well..
// (some users might be suprised to see the lot go with the same start and end index)
}
#ifdef NEWXML
void BackupJournal(QString filename)
{
QString outBuf;
QXmlStreamWriter stream(&outBuf);
stream.setAutoFormatting(true);
stream.setAutoFormattingIndent(2);
stream.writeStartDocument();
stream.writeStartElement("OSCAR");
stream.writeStartElement("Journal");
stream.writeAttribute("username", p_profile->user->userName());
QDate first = p_profile->FirstDay(MT_JOURNAL);
QDate last = p_profile->LastDay(MT_JOURNAL);
QDate date = first.addDays(-1);
do {
date = date.addDays(1);
Day * journal = p_profile->GetDay(date, MT_JOURNAL);
if (!journal) continue;
Session * sess = journal->firstSession(MT_JOURNAL);
if (!sess) continue;
if ( !journal->settingExists(Journal_Notes)
&& !journal->settingExists(Journal_Weight)
&& !journal->settingExists(Journal_ZombieMeter)
&& !journal->settingExists(LastUpdated)
&& !journal->settingExists(Bookmark_Start)) {
continue;
}
stream.writeStartElement("day");
stream.writeAttribute("date", date.toString());
if (journal->settingExists(Journal_Weight)) {
QString weight = sess->settings[Journal_Weight].toString();
stream.writeAttribute("weight", weight);
}
if (journal->settingExists(Journal_ZombieMeter)) {
QString zombie = sess->settings[Journal_ZombieMeter].toString();
stream.writeAttribute("zombie", zombie);
}
if (journal->settingExists(LastUpdated)) {
QDateTime dt = sess->settings[LastUpdated].toDateTime();
#if QT_VERSION < QT_VERSION_CHECK(5,8,0)
qint64 dtx = dt.toMSecsSinceEpoch()/1000L;
#else
qint64 dtx = dt.toSecsSinceEpoch();
#endif
QString dts = QString::number(dtx);
stream.writeAttribute("lastupdated", dts);
}
if (journal->settingExists(Journal_Notes)) {
stream.writeStartElement("note");
stream.writeTextElement("text", sess->settings[Journal_Notes].toString());
stream.writeEndElement(); // notes
}
if (journal->settingExists(Bookmark_Start)) {
QVariantList start=sess->settings[Bookmark_Start].toList();
QVariantList end=sess->settings[Bookmark_End].toList();
QStringList notes=sess->settings[Bookmark_Notes].toStringList();
stream.writeStartElement("bookmarks");
int size = start.size();
for (int i=0; i< size; i++) {
stream.writeStartElement("bookmark");
stream.writeAttribute("notes",notes.at(i));
stream.writeAttribute("start",start.at(i).toString());
stream.writeAttribute("end",end.at(i).toString());
stream.writeEndElement(); // bookmark
}
stream.writeEndElement(); // bookmarks
}
stream.writeEndElement(); // day
} while (date <= last);
stream.writeEndElement(); // Journal
stream.writeEndElement(); // OSCAR
stream.writeEndDocument();
QFile file(filename);
if (!file.open(QIODevice::WriteOnly)) {
return;
}
QTextStream ts(&file);
ts << outBuf;
file.close();
}
#else
void BackupJournal(QString filename)
{
QDomDocument doc("OSCAR Journal");
@ -281,6 +384,7 @@ void BackupJournal(QString filename)
ts << doc.toString();
file.close();
}
#endif
DayController::DayController()
{

View File

@ -145,7 +145,7 @@ public:
date=QDate();
}
STRRecord(const STRRecord & copy) = default;
STRRecord(const STRRecord & /*copy*/) = default;
// All the data members
@ -232,7 +232,7 @@ public:
filename(QString()), days(0), edf(nullptr) {}
STRFile(QString name, long int recCnt, ResMedEDFInfo *str) :
filename(name), days(recCnt), edf(str) {}
STRFile(const STRFile & copy) = default;
STRFile(const STRFile & /*copy*/) = default;
virtual ~STRFile() {}

View File

@ -245,9 +245,10 @@ MachineInfo ResmedLoader::PeekInfo(const QString & path)
long event_cnt = 0;
bool parseIdentTGT( QString path, MachineInfo * info, QHash<QString, QString> & idmap ); // forward
void BackupSTRfiles( const QString strpath, const QString path, const QString strBackupPath,
bool parseIdentTGT( QString path, MachineInfo * info, QHash<QString, QString> & idmap ); // forward
void backupSTRfiles( const QString strpath, const QString importPath, const QString backupPath,
MachineInfo & info, QMap<QDate, STRFile> & STRmap ); // forward
ResMedEDFInfo * fetchSTRandVerify( QString filename, QString serialNumber ); // forward
int ResmedLoader::Open(const QString & dirpath, ResDaySaveCallback s) // alternate for unit testing
{
@ -263,24 +264,24 @@ int ResmedLoader::Open(const QString & dirpath)
QString datalogPath;
QHash<QString, QString> idmap; // Temporary machine ID properties hash
QString path(dirpath);
path = path.replace("\\", "/");
QString importPath(dirpath);
importPath = importPath.replace("\\", "/");
// Strip off end "/" if any
if (path.endsWith("/")) {
path = path.section("/", 0, -2);
if (importPath.endsWith("/")) {
importPath = importPath.section("/", 0, -2);
}
// Strip off DATALOG from path, and set newpath to the path containing DATALOG
if (path.endsWith(RMS9_STR_datalog)) {
datalogPath = path + "/";
path = path.section("/", 0, -2);
// Strip off DATALOG from importPath, and set newimportPath to the importPath containing DATALOG
if (importPath.endsWith(RMS9_STR_datalog)) {
datalogPath = importPath + "/";
importPath = importPath.section("/", 0, -2);
} else {
datalogPath = path + "/" + RMS9_STR_datalog + "/";
datalogPath = importPath + "/" + RMS9_STR_datalog + "/";
}
// Add separator back
path += "/";
importPath += "/";
// Check DATALOG folder exists and is readable
if (!QDir().exists(datalogPath)) {
@ -291,7 +292,7 @@ int ResmedLoader::Open(const QString & dirpath)
m_abort = false;
MachineInfo info = newInfo();
if ( ! parseIdentTGT(path, & info, idmap) ) {
if ( ! parseIdentTGT(importPath, & info, idmap) ) {
qDebug() << "Failed to parse Identification.tgt";
return -1;
}
@ -311,7 +312,7 @@ int ResmedLoader::Open(const QString & dirpath)
}
// Early check for STR.edf file, so we can early exit before creating faulty machine record.
QString strpath = path + RMS9_STR_strfile + STR_ext_EDF; // STR.edf file
QString strpath = importPath + "STR.edf"; // STR.edf file
QFile f(strpath);
if (!f.exists()) { // No STR.edf.. Do we have a STR.edf.gz?
@ -348,27 +349,55 @@ int ResmedLoader::Open(const QString & dirpath)
firstImportDay = ignoreBefore.date();
qDebug() << "First day to import: " << firstImportDay.toString();
bool importing_backups = false;
bool rebuild_from_backups = false;
bool create_backups = p_profile->session->backupCardData();
bool compress_backups = p_profile->session->compressBackupData();
QString backup_path = mach->getBackupPath();
if (path == backup_path) {
if (importPath == backup_path) {
// Don't create backups if importing from backup folder
importing_backups = true;
rebuild_from_backups = true;
create_backups = false;
}
///////////////////////////////////////////////////////////////////////////////////
// Parse the idmap into machine objects properties, (overwriting any old values)
// Copy the idmap into machine objects properties, (overwriting any old values)
///////////////////////////////////////////////////////////////////////////////////
for (auto i=idmap.begin(), idend=idmap.end(); i != idend; i++) {
mach->properties[i.key()] = i.value();
}
///////////////////////////////////////////////////////////////////////////////////
// Open and Parse STR.edf files (including those listed in STR_Backup)
// Create the backup folder structure for storing a copy of everything in..
// (Unless we are importing from this backup folder)
///////////////////////////////////////////////////////////////////////////////////
QDir dir;
if (create_backups) {
if ( ! dir.exists(backup_path)) {
if ( ! dir.mkpath(backup_path) ) {
qDebug() << "Could not create ResMed backup directory :-/";
}
}
// Create the STR_Backup folder if it doesn't exist
QString strBackupPath = backup_path + "STR_Backup";
if ( ! dir.exists(strBackupPath) )
dir.mkpath(strBackupPath);
QString newpath = backup_path + "DATALOG";
if ( ! dir.exists(newpath) )
dir.mkpath(newpath);
// Copy Identification files to backup folder
QFile::copy(importPath + RMS9_STR_idfile + STR_ext_TGT, backup_path + RMS9_STR_idfile + STR_ext_TGT);
QFile::copy(importPath + RMS9_STR_idfile + STR_ext_CRC, backup_path + RMS9_STR_idfile + STR_ext_CRC);
}
///////////////////////////////////////////////////////////////////////////////////
// Open and Process STR.edf files (including those listed in STR_Backup)
///////////////////////////////////////////////////////////////////////////////////
resdayList.clear();
@ -380,45 +409,64 @@ int ResmedLoader::Open(const QString & dirpath)
QMap<QDate, STRFile> STRmap;
// Create the STR_Backup folder if it doesn't exist
QString strBackupPath = backup_path + "STR_Backup";
QDir dir;
if ( ! dir.exists(strBackupPath))
dir.mkpath(strBackupPath);
QString newpath = backup_path + "DATALOG";
if ( ! dir.exists(newpath) )
dir.mkpath(newpath);
if ( ! importing_backups ) {
BackupSTRfiles( strpath, path, strBackupPath, info, STRmap );
} else { // get the STR file that is in the BACKUP folder
ResMedEDFInfo * stredf = new ResMedEDFInfo();
if ( stredf->Open(strpath) ) {
if ( stredf->Parse()) {
if (stredf->serialnumber != info.serial) {
qDebug() << "Identification.tgt Serial number doesn't match" << strpath;
if ( ( ! rebuild_from_backups) /* && create_backups */ ) {
// first we copy any STR_yyyymmdd.edf files and the Backup/STR.edf into STR_Backup and the STRmap
backupSTRfiles( strpath, importPath, backup_path, info, STRmap );
//Then we copy the new imported STR.edf into Backup/STR.edf and add it to the STRmap
QString importFile(importPath+"STR.edf");
QString backupFile(backup_path + "STR.edf");
ResMedEDFInfo * stredf = fetchSTRandVerify( importFile, info.serial );
if ( stredf != nullptr ) {
bool addToSTRmap = true;
QDate date = stredf->edfHdr.startdate_orig.date();
long int days = stredf->GetNumDataRecords();
qDebug() << importFile.section("/",-2,-1) << "starts at" << date << "for" << days << "ends" << date.addDays(days-1);
if (STRmap.contains(date)) { // Keep the longer of the two STR files
qDebug() << importFile.section("/",-3,-1) << "overlaps" << STRmap[date].filename.section("/",-3,-1) << "for" << days << "ends" << date.addDays(days-1);
if (days > STRmap[date].days) {
qDebug() << "Removing" << STRmap[date].filename.section("/",-3,-1) << "with" << STRmap[date].days;
STRmap.remove(date);
} else {
qDebug() << "Skipping" << importFile.section("/",-3,-1);
qWarning() << "New import is shorter than exisiting files - should never happen";
delete stredf;
} else { // passed the tests, stuff it into the map
QDate date = stredf->edfHdr.startdate_orig.date();
long int days = stredf->GetNumDataRecords();
qDebug() << strpath.section("/",-2,-1) << "starts at" << date << "for" << days << "ends" << date.addDays(days-1);
STRmap[date] = STRFile(strpath, days, stredf);
addToSTRmap = false;
}
} else {
qDebug() << "Faulty STR file" << strpath;
delete stredf;
}
if ( addToSTRmap ) {
if ( compress_backups ) {
backupFile += ".gz";
if ( QFile::exists( backupFile ) )
QFile::remove( backupFile );
compressFile(importFile, backupFile);
}
else {
if ( QFile::exists( backupFile ) )
QFile::remove( backupFile );
if ( ! QFile::copy(importFile, backupFile) )
qWarning() << "Failed to copy" << importFile << "to" << backupFile;
}
STRmap[date] = STRFile(backupFile, days, stredf);
// Meh.. these can be calculated if ever needed for ResScan SDcard export
QFile::copy(importPath + "STR.crc", backup_path + "STR.crc");
}
}
} else { // get the STR file that is in the BACKUP folder that we are rebuilding from
ResMedEDFInfo * stredf = fetchSTRandVerify( strpath, info.serial );
if ( stredf != nullptr ) {
QDate date = stredf->edfHdr.startdate_orig.date();
long int days = stredf->GetNumDataRecords();
qDebug() << strpath.section("/",-2,-1) << "starts at" << date << "for" << days << "ends" << date.addDays(days-1);
STRmap[date] = STRFile(strpath, days, stredf);
} else {
qDebug() << "Failed to open" << strpath;
delete stredf;
}
} // end if not importing the backup files
#ifdef STR_DEBUG
qDebug() << "STRmap size is " << STRmap.size();
#endif
// Now we open the REAL STR_Backup, and open the rest for later parsing
// Now we open the REAL destination STR_Backup, and open the rest for later parsing
dir.setPath(backup_path + "STR_Backup");
dir.setFilter(QDir::Files | QDir::Hidden | QDir::Readable);
@ -429,6 +477,7 @@ int ResmedLoader::Open(const QString & dirpath)
qDebug() << "STR_Backup folder size is " << flist.size();
#endif
qDebug() << "Add files in STR_Backup to STRmap (unless they are already there)";
// Add any STR_Backup versions to the file list
for (auto & fi : flist) {
QString filename = fi.fileName();
@ -437,46 +486,27 @@ int ResmedLoader::Open(const QString & dirpath)
if (!(filename.endsWith("edf.gz", Qt::CaseInsensitive) || filename.endsWith("edf", Qt::CaseInsensitive)))
continue;
QString datestr = filename.section("STR-",-1).section(".edf",0,0); // +"01";
// date = QDate().fromString(datestr,"yyyyMMdd");
//
// if (STRmap.contains(date)) {
// qDebug() << filename << "overlaps anothor STR file";
// continue;
// }
ResMedEDFInfo * stredf = new ResMedEDFInfo();
if ( ! stredf->Open(fi.canonicalFilePath() ) ) {
qDebug() << "Failed to open" << fi.canonicalFilePath();
delete stredf;
ResMedEDFInfo * stredf = fetchSTRandVerify( fi.canonicalFilePath(), info.serial );
if ( stredf == nullptr )
continue;
}
if ( ! stredf->Parse()) {
qDebug() << "Faulty STR file" << filename;
delete stredf;
continue;
}
if (stredf->serialnumber != info.serial) {
qDebug() << "Identification.tgt Serial number doesn't match" << filename;
delete stredf;
continue;
}
// Don't trust the filename date, pick the one inside the STR...
date = stredf->edfHdr.startdate_orig.date();
days = stredf->GetNumDataRecords();
if (STRmap.contains(date)) { // Keep the longer of the two STR files
qDebug() << filename << "overlaps" << STRmap[date].filename.section("/",-2,-1) << "for" << days << "ends" << date.addDays(days-1);
qDebug() << fi.canonicalFilePath().section("/",-3,-1) << "overlaps" << STRmap[date].filename.section("/",-3,-1) << "for" << days << "ends" << date.addDays(days-1);
if (days <= STRmap[date].days) {
qDebug() << "Skipping" << filename;
qDebug() << "Skipping" << fi.canonicalFilePath().section("/",-3,-1);
delete stredf;
continue;
} else {
qDebug() << "Removing" << STRmap[date].filename.section("/",-3,-1);
STRmap.remove(date);
}
}
// qDebug() << "Resetting STR date from" << date.toString() << "to first of month ... WHY???";
// date = QDate(date.year(), date.month(), 1);
qDebug() << fi.canonicalFilePath().section("/", -2,-1) << "starts at" << date << "for" << days;
qDebug() << "Adding" << fi.canonicalFilePath().section("/", -2,-1) << "starts at" << date << "for" << days;
STRmap[date] = STRFile(fi.canonicalFilePath(), days, stredf);
} // end for walking the STR_Backup directory
#ifdef STR_DEBUG
@ -496,7 +526,7 @@ int ResmedLoader::Open(const QString & dirpath)
for (auto it=STRmap.begin(), end=STRmap.end(); it != end; ++it) {
QString fullname = it.value().filename;
#ifdef STR_DEBUG
qDebug() << "Deleting edf of" << fullname;
qDebug() << "Deleting edf object of" << fullname;
#endif
QString datepart = fullname.section("STR-",-1).section(".edf",0,0);
if (datepart.size() == 6 ) { // old style name, change to full date
@ -505,9 +535,9 @@ int ResmedLoader::Open(const QString & dirpath)
QString newName = fullname.replace(datepart, newdate);
qDebug() << "Renaming" << it.value().filename << "to" << newName;
if ( str.rename(newName) )
qDebug() << "Success";
qDebug() << "Rename Success";
else
qDebug() << "Failed";
qDebug() << "Rename Failed";
}
delete it.value().edf;
}
@ -515,31 +545,6 @@ int ResmedLoader::Open(const QString & dirpath)
qDebug() << "Finished STRmap cleanup";
#endif
///////////////////////////////////////////////////////////////////////////////////
// Create the backup folder for storing a copy of everything in..
// (Unless we are importing from this backup folder)
///////////////////////////////////////////////////////////////////////////////////
dir.setPath(datalogPath);
if (create_backups) {
if ( ! dir.exists(backup_path)) {
if ( ! dir.mkpath(backup_path + RMS9_STR_datalog)) {
qDebug() << "Could not create ResMed backup directory :-/";
}
}
if ( compress_backups )
compressFile(path + "STR.edf", backup_path + "STR.edf.gz");
else
QFile::copy(path + "STR.edf", backup_path + "STR.edf");
// Copy Identification files to backup folder
QFile::copy(path + RMS9_STR_idfile + STR_ext_TGT, backup_path + RMS9_STR_idfile + STR_ext_TGT);
QFile::copy(path + RMS9_STR_idfile + STR_ext_CRC, backup_path + RMS9_STR_idfile + STR_ext_CRC);
// Meh.. these can be calculated if ever needed for ResScan SDcard export
QFile::copy(path + "STR.crc", backup_path + "STR.crc");
}
///////////////////////////////////////////////////////////////////////////////////
// Scan DATALOG files, sort, and import any new sessions
///////////////////////////////////////////////////////////////////////////////////
@ -557,6 +562,7 @@ int ResmedLoader::Open(const QString & dirpath)
qDebug() << "Starting scan of DATALOG";
// sleep(1);
dir.setPath(datalogPath);
ScanFiles(mach, datalogPath, firstImportDay);
if (isAborted())
return 0;
@ -644,6 +650,28 @@ int ResmedLoader::Open(const QString & dirpath)
return num_new_sessions;
} // end Open()
ResMedEDFInfo * fetchSTRandVerify( QString filename, QString serialNumber)
{
ResMedEDFInfo * stredf = new ResMedEDFInfo();
if ( ! stredf->Open(filename ) ) {
qDebug() << "Failed to open" << filename;
delete stredf;
return nullptr;
}
if ( ! stredf->Parse()) {
qDebug() << "Faulty STR file" << filename;
delete stredf;
return nullptr;
}
if (stredf->serialnumber != serialNumber) {
qDebug() << "Identification.tgt Serial number doesn't match" << filename;
delete stredf;
return nullptr;
}
return stredf;
}
void StoreSettings(Session * sess, STRRecord & R); // forward
void ResmedLoader::checkSummaryDay( ResMedDay & resday, QDate date, Machine * mach )
{
@ -953,7 +981,7 @@ bool ResmedLoader::ProcessSTRfiles(Machine *mach, QMap<QDate, STRFile> & STRmap,
int days = str.GetNumDataRecords();
totalRecs += days;
#ifdef STR_DEBUG
qDebug() << "STR file is" << file.filename;
qDebug() << "STR file is" << file.filename.section("/", -3, -1);
qDebug() << "First day" << QDateTime::fromMSecsSinceEpoch(str.startdate, EDFInfo::localNoDST).date().toString() << "for" << days << "days";
#endif
}
@ -974,12 +1002,12 @@ bool ResmedLoader::ProcessSTRfiles(Machine *mach, QMap<QDate, STRFile> & STRmap,
QDate lastDay = date.addDays(size-1);
#ifdef STR_DEBUG
qDebug() << "Processing" << strfile << date.toString() << size << str.GetNumSignals();
qDebug() << "Processing" << strfile.section("/", -3, -1) << date.toString() << size << str.GetNumSignals();
qDebug() << "Last day is" << lastDay;
#endif
if ( lastDay < firstImport ) {
qDebug() << "LastDay before firstImport, skipping" << strfile;
qDebug() << "LastDay before firstImport, skipping" << strfile.section("/", -3, -1);
continue;
}
@ -1477,21 +1505,25 @@ bool parseIdentTGT( QString path, MachineInfo * info, QHash<QString, QString> &
return true;
}
void BackupSTRfiles( const QString strpath, const QString path, const QString strBackupPath,
void backupSTRfiles( const QString strpath, const QString importPath, const QString backupPath,
MachineInfo & info, QMap<QDate, STRFile> & STRmap )
{
QStringList strfiles;
// add primary STR.edf
strfiles.push_back(strpath);
// Just in case we are importing into a new folder, process OSCAR backup structures
Q_UNUSED(strpath);
qDebug() << "Entering backupSTRfiles during new IMPORT";
QDir dir;
dir.setPath(path + "STR_Backup");
// Qstring strBackupPath(backupPath+"STR_Backup");
QStringList strfiles;
// add Backup/STR.edf - make sure it ends up in the STRmap
strfiles.push_back(backupPath+"STR.edf");
// Just in case we are importing from a Backup folder in a different Profile, process OSCAR backup structures
QString strBackupPath(importPath + "STR_Backup");
dir.setPath(strBackupPath);
dir.setFilter(QDir::Files | QDir::Hidden | QDir::Readable);
QFileInfoList flist = dir.entryInfoList();
// Add any STR_Backup versions to the file list
for (auto & fi : flist) {
for (auto & fi : flist) { // this is empty if imprting from an SD card
QString filename = fi.fileName();
if ( ! filename.startsWith("STR", Qt::CaseInsensitive))
continue;
@ -1503,38 +1535,32 @@ void BackupSTRfiles( const QString strpath, const QString path, const QString st
qDebug() << "STR file list size is" << strfiles.size();
#endif
// Now place any of these files in the Backup folder sorted by the file date
// Now copy any of these files to the Backup folder adding the file date to the file name
// and put it into the STRmap structure
for (auto & filename : strfiles) {
ResMedEDFInfo * stredf = new ResMedEDFInfo();
if ( ! stredf->Open(filename) ) {
qDebug() << "Failed to open" << filename;
delete stredf;
QDate date;
long int days;
ResMedEDFInfo * stredf = fetchSTRandVerify( filename, info.serial );
if ( stredf == nullptr )
continue;
}
if ( ! stredf->Parse()) {
qDebug() << "Faulty STR file" << filename;
delete stredf;
continue;
}
if (stredf->serialnumber != info.serial) {
qDebug() << "Identification.tgt Serial number doesn't match" << filename;
delete stredf;
continue;
}
QDate date = stredf->edfHdr.startdate_orig.date();
long int days = stredf->GetNumDataRecords();
// date = QDate(date.year(), date.month(), 1);
date = stredf->edfHdr.startdate_orig.date();
days = stredf->GetNumDataRecords();
if (STRmap.contains(date)) {
qDebug() << "STRmap already contains" << date.toString("YYYY-MM-dd");
qDebug() << "STRmap already contains" << date.toString("yyyy-MM-dd") << "for" << STRmap[date].days << "ending" << date.addDays(STRmap[date].days-1);
qDebug() << filename.section("/",-2,-1) << "has" << days << "ending" << date.addDays(days-1);
if ( days <= STRmap[date].days ) {
qDebug() << "Skipping" << filename;
qDebug() << "Skipping" << filename.section("/",-2,-1) << "Keeping" << STRmap[date].filename.section("/",-2,-1);
delete stredf;
continue;
} else {
qDebug() << "Dropping" << STRmap[date].filename.section("/", -2, -1) << "Keeping" << filename.section("/",-2,-1);
delete STRmap[date].edf;
STRmap.remove(date); // new one gets added after we know its new name
}
}
// now create the new backup name
QString newname = "STR-"+date.toString("yyyyMMdd")+"."+STR_ext_EDF;
QString backupfile = strBackupPath+"/"+newname;
QString backupfile = backupPath+"/STR_Backup/"+newname;
QString gzfile = backupfile + STR_ext_gz;
QString nongzfile = backupfile;
@ -1542,35 +1568,39 @@ void BackupSTRfiles( const QString strpath, const QString path, const QString st
bool compress_backups = p_profile->session->compressBackupData();
backupfile = compress_backups ? gzfile : nongzfile;
if ( ! QFile::exists(backupfile)) {
#ifdef STR_DEBUG
qDebug() << "Copying" << filename << "to" << backupfile;
#endif
if (filename.endsWith(STR_ext_gz,Qt::CaseInsensitive)) { // we have a compressed file
if (compress_backups) { // fine, copy it to backup folder
QFile::copy(filename, backupfile);
} else { // oops, uncompress it to the backup folder
uncompressFile(filename, backupfile);
}
} else { // file is not compressed
if (compress_backups) { // so compress it into the backup folder
compressFile(filename, backupfile);
} else { // and that's OK, just copy it over
QFile::copy(filename, backupfile);
}
STRmap[date] = STRFile(backupfile, days, stredf);
qDebug() << "Adding" << filename.section("/",-3,-1) << "with" << days << "days as" << backupfile.section("/", -3, -1) << "to STRmap";
if ( QFile::exists(backupfile)) {
QFile::remove(backupfile);
}
// #ifdef STR_DEBUG
qDebug() << "Copying" << filename.section("/",-3,1) << "to" << backupfile.section("/",-3,-1);
// #endif
if (filename.endsWith(STR_ext_gz,Qt::CaseInsensitive)) { // we have a compressed file
if (compress_backups) { // fine, copy it to backup folder
QFile::copy(filename, backupfile);
} else { // oops, uncompress it to the backup folder
uncompressFile(filename, backupfile);
}
} else { // file is not compressed
if (compress_backups) { // so compress it into the backup folder
compressFile(filename, backupfile);
} else { // and that's OK, just copy it over
QFile::copy(filename, backupfile);
}
}
// Remove any duplicate compressed/uncompressed backup file
if (compress_backups)
QFile::exists(nongzfile) && QFile::remove(nongzfile);
else
QFile::exists(gzfile) && QFile::remove(gzfile);
STRmap[date] = STRFile(backupfile, days, stredf);
} // end for walking the STR files list
#ifdef STR_DEBUG
qDebug() << "STRmap has" << STRmap.size() << "entries";
#endif
qDebug() << "Leaving backupSTRfiles during new IMPORT";
}
QHash<QString, QString> parseIdentLine( const QString line, MachineInfo * info)
@ -2469,7 +2499,7 @@ bool ResmedLoader::LoadBRP(Session *sess, const QString & path)
QString filename = path.section(-2, -1);
ResMedEDFInfo edf;
if ( ! edf.Open(path) ) {
qDebug() << "LoadBRP failed to open" << filename;
qDebug() << "LoadBRP failed to open" << filename.section("/", -2, -1);
return false;
}
#ifdef DEBUG_EFFICIENCY
@ -2477,7 +2507,9 @@ bool ResmedLoader::LoadBRP(Session *sess, const QString & path)
time.start();
#endif
if (!edf.Parse()) {
qDebug() << "LoadBRP failed to parse" << filename;
#ifdef EDF_DEBUG
qDebug() << "LoadBRP failed to parse" << filename.section("/", -2, -1);
#endif
return false;
}
#ifdef DEBUG_EFFICIENCY
@ -2571,7 +2603,7 @@ bool ResmedLoader::LoadSAD(Session *sess, const QString & path)
QString filename = path.section(-2, -1);
ResMedEDFInfo edf;
if ( ! edf.Open(path) ) {
qDebug() << "LoadSAD failed to open" << filename;
qDebug() << "LoadSAD failed to open" << filename.section("/", -2, -1);
return false;
}
@ -2581,7 +2613,9 @@ bool ResmedLoader::LoadSAD(Session *sess, const QString & path)
#endif
if (!edf.Parse()) {
qDebug() << "LoadSAD failed to parse" << filename;
#ifdef EDF_DEBUG
qDebug() << "LoadSAD failed to parse" << filename.section("/", -2, -1);
#endif
return false;
}
@ -2646,7 +2680,7 @@ bool ResmedLoader::LoadPLD(Session *sess, const QString & path)
QString filename = path.section(-2, -1);
ResMedEDFInfo edf;
if ( ! edf.Open(path) ) {
qDebug() << "LoadPLD failed to open" << filename;
qDebug() << "LoadPLD failed to open" << filename.section("/", -2, -1);
return false;
}
#ifdef DEBUG_EFFICIENCY
@ -2655,7 +2689,9 @@ bool ResmedLoader::LoadPLD(Session *sess, const QString & path)
#endif
if (!edf.Parse()) {
qDebug() << "LoadPLD failed to parse" << filename;
#ifdef EDF_DEBUG
qDebug() << "LoadPLD failed to parse" << filename.section("/", -2, -1);
#endif
return false;
}

View File

@ -109,7 +109,7 @@ enum PRTimeModes { //:short
struct MachineInfo {
MachineInfo() { type = MT_UNKNOWN; version = 0; cap=0; }
MachineInfo(const MachineInfo & copy) = default;
MachineInfo(const MachineInfo & /*copy*/) = default;
MachineInfo(MachineType type, quint32 cap, QString loadername, QString brand, QString model, QString modelnumber, QString serial, QString series, QDateTime lastimported, int version) :
type(type), cap(cap), loadername(loadername), brand(brand), model(model), modelnumber(modelnumber), serial(serial), series(series), lastimported(lastimported), version(version) {}

View File

@ -27,7 +27,7 @@ public:
color = Qt::black;
type = Calc_Zero;
}
ChannelCalc(const ChannelCalc & copy) = default;
ChannelCalc(const ChannelCalc & /*copy*/) = default;
ChannelCalc(ChannelID code, ChannelCalcType type, QColor color, bool enabled):
code(code), type(type), color(color), enabled(enabled) {}

View File

@ -1,5 +1,5 @@
// 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.1.1-rc-1"
#define VERSION "1.1.1-rc-3"

View File

@ -233,7 +233,7 @@ void ExportCSV::on_exportButton_clicked()
ui->progressBar->setValue(ui->progressBar->value() + 1);
QApplication::processEvents();
Day *day = p_profile->GetDay(date, MT_CPAP);
Day *day = p_profile->GetDay(date, MT_CPAP); // Only export days with CPAP data.
if (day) {
QString data;
@ -280,6 +280,9 @@ void ExportCSV::on_exportButton_clicked()
} else if (ui->rb1_Sessions->isChecked()) {
for (int i = 0; i < day->size(); i++) {
Session *sess = (*day)[i];
if (sess->type() != MT_CPAP) {
continue; // Not every session in a day with CPAP data will be a CPAP session.
}
QDateTime start = QDateTime::fromTime_t(sess->first() / 1000L);
QDateTime end = QDateTime::fromTime_t(sess->last() / 1000L);

View File

@ -43,7 +43,7 @@ class Update
*/
struct Release {
Release() {}
Release(const Release &copy) = default;
Release(const Release & /*copy*/) = default;
Release(QString ver, QString code, UpdateStatus stat) { version = ver; codename = code; status = stat; }
QString version;
@ -87,7 +87,7 @@ class UpdateParser: public QXmlDefaultHandler
class PackageUpdate {
public:
PackageUpdate() {}
PackageUpdate(const PackageUpdate & copy) = default;
PackageUpdate(const PackageUpdate & /*copy*/) = default;
QString name;
QString displayName;