#include #include #include #include #include "Graphs/gYAxis.h" #include "Graphs/gXAxis.h" #include "oximeterimport.h" #include "ui_oximeterimport.h" #include "SleepLib/loader_plugins/cms50_loader.h" Qt::DayOfWeek firstDayOfWeekFromLocale(); OximeterImport::OximeterImport(QWidget *parent) : QDialog(parent), ui(new Ui::OximeterImport) { ui->setupUi(this); setWindowTitle(tr("Oximeter Import Wizard")); ui->stackedWidget->setCurrentIndex(0); oximodule = nullptr; ui->retryButton->setVisible(false); liveView = new gGraphView(this); liveView->setVisible(false); ui->stopButton->setVisible(false); ui->syncSaveButton->setVisible(false); QVBoxLayout * lvlayout = new QVBoxLayout; lvlayout->setMargin(0); ui->liveViewFrame->setLayout(lvlayout); lvlayout->addWidget(liveView); PLETHY = new gGraph(liveView, STR_TR_Plethy, STR_UNIT_Hz); PLETHY->AddLayer(new gYAxis(), LayerLeft, gYAxis::Margin); PLETHY->AddLayer(new gXAxis(), LayerBottom, 0, 20); PLETHY->AddLayer(plethyChart = new gLineChart(OXI_Plethy)); ui->calendarWidget->setFirstDayOfWeek(Qt::Sunday); QTextCharFormat format = ui->calendarWidget->weekdayTextFormat(Qt::Saturday); format.setForeground(QBrush(Qt::black, Qt::SolidPattern)); ui->calendarWidget->setWeekdayTextFormat(Qt::Saturday, format); ui->calendarWidget->setWeekdayTextFormat(Qt::Sunday, format); ui->calendarWidget->setVerticalHeaderFormat(QCalendarWidget::NoVerticalHeader); Qt::DayOfWeek dow=firstDayOfWeekFromLocale(); ui->calendarWidget->setFirstDayOfWeek(dow); ui->dateTimeEdit->setMinimumHeight(ui->dateTimeEdit->height() + 10); ui->syncCPAPGroup->setVisible(false); QVBoxLayout * layout = new QVBoxLayout; layout->setMargin(0); ui->sessBarFrame->setLayout(layout); sessbar = new SessionBar(this); sessbar->setSelectMode(true); sessbar->setMouseTracking(true); sessbar->setMinimumHeight(40); connect(sessbar, SIGNAL(sessionClicked(Session*)), this, SLOT(onSessionSelected(Session*))); layout->addWidget(sessbar, 1); } OximeterImport::~OximeterImport() { disconnect(sessbar, SIGNAL(sessionClicked(Session*)), this, SLOT(onSessionSelected(Session*))); delete ui; } void OximeterImport::on_nextButton_clicked() { int i = ui->stackedWidget->currentIndex(); i++; if (i >= ui->stackedWidget->count()) i = 0; switch (i) { case 0: ui->nextButton->setVisible(true); ui->nextButton->setText("&Start"); break; case 1: ui->nextButton->setVisible(false); break; default: ui->nextButton->setVisible(true); } ui->stackedWidget->setCurrentIndex(i); } void OximeterImport::updateStatus(QString msg) { ui->logBox->appendPlainText(msg); ui->directImportStatus->setText(msg); ui->liveStatusLabel->setText(msg); } MachineLoader * OximeterImport::detectOximeter() { const int PORTSCAN_TIMEOUT=30000; const int delay=100; ui->retryButton->setVisible(false); QList loaders = GetLoaders(MT_OXIMETER); updateStatus(tr("Scanning for compatible oximeters")); ui->progressBar->setMaximum(PORTSCAN_TIMEOUT); QTime time; time.start(); oximodule = nullptr; int elapsed=0; do { for (int i=0; i < loaders.size(); ++i) { MachineLoader * loader = loaders[i]; if (loader->openDevice()) { oximodule = loader; break; } } if (oximodule) break; QThread::msleep(delay); elapsed = time.elapsed(); ui->progressBar->setValue(elapsed); QApplication::processEvents(); if (!isVisible()) { return oximodule = nullptr; } } while (elapsed < PORTSCAN_TIMEOUT); if (!oximodule) { updateStatus(tr("Could not detect any connected oximeter devices.")); return nullptr; } updateStatus(tr("Connecting to %1 Oximeter").arg(oximodule->ClassName())); return oximodule; } void OximeterImport::on_directImportButton_clicked() { ui->stackedWidget->setCurrentWidget(ui->directImportPage); oximodule = detectOximeter(); if (!oximodule) return; ui->connectLabel->setText("

"+tr("Select upload option on %1").arg(oximodule->ClassName())+"

"); updateStatus(tr("Waiting for you to start the upload process...")); connect(oximodule, SIGNAL(updateProgress(int,int)), this, SLOT(doUpdateProgress(int,int))); oximodule->Open("import", p_profile); // Wait to start import streaming.. while (!oximodule->isImporting() && !oximodule->isAborted()) { QThread::msleep(100); QApplication::processEvents(); if (!isVisible()) { disconnect(oximodule, SIGNAL(updateProgress(int,int)), this, SLOT(doUpdateProgress(int,int))); oximodule->abort(); break; } } if (!oximodule->isStreaming()) { disconnect(oximodule, SIGNAL(updateProgress(int,int)), this, SLOT(doUpdateProgress(int,int))); ui->retryButton->setVisible(true); ui->progressBar->setValue(0); oximodule->abort(); return; } ui->connectLabel->setText("

"+tr("%1 device is uploading data...").arg(oximodule->ClassName())+"

"); updateStatus(tr("Please wait until oximeter upload process completes. Do not unplug your oximeter.")); // Wait for import streaming to finish // Can't abort this bit or the oximeter will get confused... ui->cancelButton->setVisible(false); while (oximodule->isImporting() && !oximodule->isAborted()) { QThread::msleep(50); QApplication::processEvents(); } ui->cancelButton->setVisible(true); updateStatus(tr("Oximeter import completed.. Processing data")); oximodule->process(); disconnect(oximodule, SIGNAL(updateProgress(int,int)), this, SLOT(doUpdateProgress(int,int))); ui->stackedWidget->setCurrentWidget(ui->syncPage); ui->syncSaveButton->setVisible(true); ui->calendarWidget->setMinimumDate(PROFILE.FirstDay()); ui->calendarWidget->setMaximumDate(PROFILE.LastDay()); on_calendarWidget_clicked(PROFILE.LastDay()); } void OximeterImport::doUpdateProgress(int v, int t) { ui->progressBar->setMaximum(t); ui->progressBar->setValue(v); QApplication::processEvents(); } void OximeterImport::on_fileImportButton_clicked() { #if QT_VERSION < QT_VERSION_CHECK(5,0,0) const QString documentsFolder = QDesktopServices::storageLocation( QDesktopServices::DocumentsLocation); #else const QString documentsFolder = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); #endif QString filename = QFileDialog::getOpenFileName(this, tr("Select a valid oximetry data file"), documentsFolder, "Oximetry Files (*.spo *.spor *.spo2)"); if (filename.isEmpty()) return; QList loaders = GetLoaders(MT_OXIMETER); bool success = false; oximodule = nullptr; Q_FOREACH(MachineLoader * loader, loaders) { if (loader->Open(filename,p_profile)) { success = true; oximodule = loader; break; } } if (!success) { QMessageBox::warning(this, STR_MessageBox_Warning, tr("No Oximetery module could parse the given file:")+QString("\n\n%1").arg(filename), QMessageBox::Ok); return; } ui->stackedWidget->setCurrentWidget(ui->syncPage); ui->syncSaveButton->setVisible(true); ui->calendarWidget->setMinimumDate(PROFILE.FirstDay()); ui->calendarWidget->setMaximumDate(PROFILE.LastDay()); on_calendarWidget_clicked(PROFILE.LastDay()); } void OximeterImport::on_liveImportButton_clicked() { ui->stackedWidget->setCurrentWidget(ui->liveImportPage); ui->liveImportPage->layout()->addWidget(ui->progressBar); QApplication::processEvents(); liveView->setEmptyText(tr("Oximeter not detected")); liveView->setVisible(true); QApplication::processEvents(); MachineLoader * oximodule = detectOximeter(); if (!oximodule) { updateStatus("Couldn't access oximeter"); ui->retryButton->setVisible(true); ui->progressBar->setValue(0); return; } ui->liveConnectLabel->setText("Live Oximetery Mode"); liveView->setEmptyText(tr("Still Under Construction")); // Recording... ui->progressBar->hide(); liveView->update(); oximodule->Open("live",p_profile); ui->stopButton->setVisible(true); while (oximodule->isStreaming() && !oximodule->isAborted()) { QThread::msleep(50); QApplication::processEvents(); } ui->stopButton->setVisible(false); ui->liveConnectLabel->setText("Live Import Stopped"); liveView->setEmptyText(tr("Live Oximetery Stopped")); updateStatus(tr("Live Oximetery import has been stopped")); oximodule->closeDevice(); // detect oximeter } void OximeterImport::on_retryButton_clicked() { if (ui->stackedWidget->currentWidget() == ui->directImportPage) { on_directImportButton_clicked(); } else if (ui->stackedWidget->currentWidget() == ui->liveImportPage) { on_liveImportButton_clicked(); } } void OximeterImport::on_stopButton_clicked() { if (oximodule) { oximodule->abort(); } } void OximeterImport::on_calendarWidget_clicked(const QDate &date) { Day * day = PROFILE.GetGoodDay(date, MT_CPAP); sessbar->clear(); if (day) { QDateTime time=QDateTime::fromMSecsSinceEpoch(day->first()); sessbar->clear(); QList colors; colors.push_back("#ffffe0"); colors.push_back("#ffe0ff"); colors.push_back("#e0ffff"); QList::iterator i; int j=0; for (i=day->begin(); i != day->end(); ++i) { sessbar->add((*i),colors.at(j++ % colors.size())); } sessbar->setVisible(true); ui->sessbarLabel->setText(QString("%1 session(s), starting at %2").arg(day->size()).arg(time.time().toString("hh:mm:ssap"))); // sessbar->setSelected(0); // ui->dateTimeEdit->setDateTime(time); } else { ui->sessbarLabel->setText("No CPAP Data available for this date"); // sessbar->setVisible(false); } sessbar->update(); } void OximeterImport::on_calendarWidget_selectionChanged() { on_calendarWidget_clicked(ui->calendarWidget->selectedDate()); } void OximeterImport::onSessionSelected(Session * session) { QDateTime time=QDateTime::fromMSecsSinceEpoch(session->first()); ui->dateTimeEdit->setDateTime(time); } void OximeterImport::on_sessionBackButton_clicked() { int idx = (sessbar->selected()-1); if (idx >= 0) { sessbar->setSelected(idx); QDateTime datetime = QDateTime::fromMSecsSinceEpoch(sessbar->session(idx)->first()); ui->dateTimeEdit->setDateTime(datetime); sessbar->update(); } } void OximeterImport::on_sessionForwardButton_clicked() { int idx = (sessbar->selected()+1); if (idx < sessbar->count()) { sessbar->setSelected(idx); QDateTime datetime = QDateTime::fromMSecsSinceEpoch(sessbar->session(idx)->first()); ui->dateTimeEdit->setDateTime(datetime); sessbar->update(); } } void OximeterImport::on_radioSyncCPAP_clicked() { if (!ui->syncCPAPGroup->isVisible()) { if (sessbar->selected() < 0) { int idx = 0; if (idx < sessbar->count()) { sessbar->setSelected(idx); QDateTime datetime = QDateTime::fromMSecsSinceEpoch(sessbar->session(idx)->first()); ui->dateTimeEdit->setDateTime(datetime); sessbar->update(); } } } ui->syncCPAPGroup->setVisible(true); } void OximeterImport::on_radioSyncOximeter_clicked() { ui->syncCPAPGroup->setVisible(false); } void OximeterImport::on_radioSyncManually_clicked() { ui->syncCPAPGroup->setVisible(false); } void OximeterImport::on_syncSaveButton_clicked() { }