/* user graph settings Implementation * * Copyright (c) 2019-2022 The OSCAR Team * Copyright (c) 2011-2018 Mark Watkins * * 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. */ #define TEST_MACROS_ENABLEDoff #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dailySearchTab.h" #include "SleepLib/day.h" #include "SleepLib/profiles.h" #include "daily.h" #define OT_NONE 0 #define OT_DISABLED_SESSIONS 1 #define OT_NOTES 2 #define OT_NOTES_STRING 3 #define OT_BOOK_MARKS 4 #define OT_AHI 5 #define OT_SHORT_SESSIONS 6 #define OT_SESSIONS_QTY 7 #define OT_DAILY_USAGE 8 DailySearchTab::DailySearchTab(Daily* daily , QWidget* searchTabWidget , QTabWidget* dailyTabWidget) : daily(daily) , parent(daily) , searchTabWidget(searchTabWidget) ,dailyTabWidget(dailyTabWidget) { icon_on = new QIcon(":/icons/session-on.png"); icon_off = new QIcon(":/icons/session-off.png"); #if 0 // method of find the daily tabWidgets works for english. // the question will it work for all other langauges??? // Right now they are const int in the header file. int maxIndex = dailyTabWidget->count(); for (int index=0 ; indextabText(index); if (title.contains("detail",Qt::CaseInsensitive) ) {TW_DETAILED = index; continue;}; if (title.contains("event",Qt::CaseInsensitive) ) {TW_EVENTS = index; continue;}; if (title.contains("note",Qt::CaseInsensitive) ) {TW_NOTES = index; continue;}; if (title.contains("bookmark",Qt::CaseInsensitive) ) {TW_BOOKMARK = index; continue;}; if (title.contains("search",Qt::CaseInsensitive) ) {TW_SEARCH = index; continue;}; } #endif createUi(); daily->connect(enterString, SIGNAL(textEdited(QString)), this, SLOT(on_textEdited(QString)) ); daily->connect(enterInteger, SIGNAL(valueChanged(int)), this, SLOT(on_intValueChanged(int)) ); daily->connect(enterDouble, SIGNAL(valueChanged(double)), this, SLOT(on_doubleValueChanged(double)) ); daily->connect(startButton, SIGNAL(clicked()), this, SLOT(on_startButton_clicked()) ); daily->connect(continueButton, SIGNAL(clicked()), this, SLOT(on_continueButton_clicked()) ); //daily->connect(guiDisplayTable, SIGNAL(itemActivated(QTableWidgetItem*)), this, SLOT(on_itemActivated(QTableWidgetItem*) )); daily->connect(guiDisplayTable, SIGNAL(itemClicked(QTableWidgetItem*)), this, SLOT(on_itemActivated(QTableWidgetItem*) )); daily->connect(guiDisplayTable, SIGNAL(itemDoubleClicked(QTableWidgetItem*)), this, SLOT(on_itemActivated(QTableWidgetItem*) )); daily->connect(selectCommand, SIGNAL(activated(int)), this, SLOT(on_selectCommand_activated(int) )); daily->connect(dailyTabWidget, SIGNAL(currentChanged(int)), this, SLOT(on_dailyTabWidgetCurrentChanged(int) )); } DailySearchTab::~DailySearchTab() { daily->disconnect(enterString, SIGNAL(textEdited(QString)), this, SLOT(on_textEdited(QString)) ); daily->disconnect(dailyTabWidget, SIGNAL(currentChanged(int)), this, SLOT(on_dailyTabWidgetCurrentChanged(int) )); daily->disconnect(enterInteger, SIGNAL(valueChanged(int)), this, SLOT(on_intValueChanged(int)) ); daily->disconnect(enterDouble, SIGNAL(valueChanged(double)), this, SLOT(on_doubleValueChanged(double)) ); daily->disconnect(selectCommand, SIGNAL(activated(int)), this, SLOT(on_selectCommand_activated(int) )); //daily->disconnect(guiDisplayTable, SIGNAL(itemActivated(QTableWidgetItem*)), this, SLOT(on_itemActivated(QTableWidgetItem*) )); daily->disconnect(guiDisplayTable, SIGNAL(itemClicked(QTableWidgetItem*)), this, SLOT(on_itemActivated(QTableWidgetItem*) )); daily->disconnect(guiDisplayTable, SIGNAL(itemDoubleClicked(QTableWidgetItem*)), this, SLOT(on_itemActivated(QTableWidgetItem*) )); daily->disconnect(continueButton, SIGNAL(clicked()), this, SLOT(on_continueButton_clicked()) ); daily->disconnect(startButton, SIGNAL(clicked()), this, SLOT(on_startButton_clicked()) ); delete icon_on ; delete icon_off ; }; void DailySearchTab::createUi() { QFont baseFont =*defaultfont; baseFont.setPointSize(1+baseFont.pointSize()); searchTabWidget ->setFont(baseFont); searchTabLayout = new QVBoxLayout(searchTabWidget); criteriaLayout = new QHBoxLayout(); searchLayout = new QHBoxLayout(); statusLayout = new QHBoxLayout(); summaryLayout = new QHBoxLayout(); searchTabLayout ->setObjectName(QString::fromUtf8("verticalLayout_21")); searchTabLayout ->setContentsMargins(4, 4, 4, 4); introduction = new QLabel(this); selectLabel = new QLabel(this); selectCommand = new QComboBox(this); startButton = new QPushButton(this); continueButton = new QPushButton(this); guiDisplayTable = new QTableWidget(this); enterDouble = new QDoubleSpinBox(this); enterInteger = new QSpinBox(this); enterString = new QLineEdit(this); criteriaOperation = new QLabel(this); statusA = new QLabel(this); statusB = new QLabel(this); statusC = new QLabel(this); summaryStatsA = new QLabel(this); summaryStatsB = new QLabel(this); summaryStatsC = new QLabel(this); searchTabLayout ->addWidget(introduction); criteriaLayout ->addWidget(selectLabel); criteriaLayout ->insertStretch(1,5); criteriaLayout ->addWidget(selectCommand); criteriaLayout ->addWidget(criteriaOperation); criteriaLayout ->addWidget(enterInteger); criteriaLayout ->addWidget(enterString); criteriaLayout ->addWidget(enterDouble); criteriaLayout ->insertStretch(-1,5); searchTabLayout ->addLayout(criteriaLayout); searchLayout ->addWidget(startButton); searchLayout ->addWidget(continueButton); searchTabLayout ->addLayout(searchLayout); statusLayout ->insertStretch(0,1); statusLayout ->addWidget(statusA); statusLayout ->addWidget(statusB); statusLayout ->addWidget(statusC); statusLayout ->insertStretch(-1,1); searchTabLayout ->addLayout(statusLayout); summaryLayout ->addWidget(summaryStatsA); summaryLayout ->addWidget(summaryStatsB); summaryLayout ->addWidget(summaryStatsC); searchTabLayout ->addLayout(summaryLayout); DEBUGFW ; // searchTabLayout ->addWidget(guiDisplayList); searchTabLayout ->addWidget(guiDisplayTable); DEBUGFW ; searchTabWidget ->setFont(baseFont); guiDisplayTable->setFont(baseFont); guiDisplayTable->setColumnCount(2); guiDisplayTable->setObjectName(QString::fromUtf8("guiDisplayTable")); //guiDisplayTable->setAlternatingRowColors(true); guiDisplayTable->setSelectionMode(QAbstractItemView::SingleSelection); guiDisplayTable->setSelectionBehavior(QAbstractItemView::SelectRows); guiDisplayTable->setSortingEnabled(true); QHeaderView* horizontalHeader = guiDisplayTable->horizontalHeader(); QHeaderView* verticalHeader = guiDisplayTable->verticalHeader(); horizontalHeader->setStretchLastSection(true); horizontalHeader->setVisible(false); horizontalHeader->setSectionResizeMode(QHeaderView::Stretch); //guiDisplayTable->horizontalHeader()->setDefaultSectionSize(QFontMetrics(baseFont).height()); verticalHeader->setVisible(false); verticalHeader->setSectionResizeMode(QHeaderView::Fixed); verticalHeader->setDefaultSectionSize(24); introduction ->setText(introductionStr()); introduction ->setFont(baseFont); statusA ->show(); //statusB ->show(); //statusC ->show(); summaryStatsA ->setFont(baseFont); summaryStatsB ->setFont(baseFont); summaryStatsC ->setFont(baseFont); summaryStatsA ->show(); summaryStatsB ->show(); summaryStatsC ->show(); enterDouble ->hide(); enterInteger ->hide(); enterString ->hide(); enterString->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum); enterDouble->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum); enterInteger->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum); selectCommand->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum); startButton->setObjectName(QString::fromUtf8("startButton")); startButton->setText(tr("Start Search")); continueButton->setObjectName(QString::fromUtf8("continueButton")); continueButton->setText(tr("Continue Search")); continueButton->setEnabled(false); startButton->setEnabled(false); selectCommand->setObjectName(QString::fromUtf8("selectCommand")); selectCommand->setFont(baseFont); } void DailySearchTab::delayedCreateUi() { // meed delay to insure days are populated. if (createUiFinished) return; #if 0 // to change alignment of a combo box selectCommand->setEditable(true); QLineEdit* lineEdit = selectCommand->lineEdit(); lineEdit->setAlignment(Qt::AlignCenter); if (lineEdit) { lineEdit->setReadOnly(true); } #endif createUiFinished = true; selectLabel->setText(tr("Match:")); selectCommand->clear(); selectCommand->addItem(tr("Select Match"),OT_NONE); selectCommand->insertSeparator(selectCommand->count()); selectCommand->addItem(tr("Notes"),OT_NOTES); selectCommand->addItem(tr("Notes containng"),OT_NOTES_STRING); selectCommand->addItem(tr("BookMarks"),OT_BOOK_MARKS); selectCommand->addItem(tr("Disabled Sessions"),OT_DISABLED_SESSIONS); selectCommand->addItem(tr("Session Duration" ),OT_SHORT_SESSIONS); selectCommand->addItem(tr("Number of Sessions"),OT_SESSIONS_QTY); selectCommand->addItem(tr("Daily Usage"),OT_DAILY_USAGE); selectCommand->addItem(tr("AHI "),OT_AHI); selectCommand->insertSeparator(selectCommand->count()); // Now add events QDate date = p_profile->LastDay(MT_CPAP); if ( !date.isValid()) return; Day* day = p_profile->GetDay(date); if (!day) return; // the following is copied from daily. quint32 chans = schema::SPAN | schema::FLAG | schema::MINOR_FLAG; if (p_profile->general->showUnknownFlags()) chans |= schema::UNKNOWN; QList available; available.append(day->getSortedMachineChannels(chans)); for (int i=0; i < available.size(); ++i) { ChannelID id = available.at(i); schema::Channel chan = schema::channel[ id ]; // new stuff now //QString displayName= chan.code(); QString displayName= chan.fullname(); //QString item = QString("%1 :%2").arg(displayName).arg(tr("")); selectCommand->addItem(displayName,id); } } void DailySearchTab::selectAligment(bool withParameters) { if (withParameters) { // operand is right justified and value is left justified. } { // only operand and it is centered. } } void DailySearchTab::on_selectCommand_activated(int index) { int item = selectCommand->itemData(index).toInt(); enterDouble->hide(); enterDouble->setDecimals(3); enterInteger->hide(); enterString->hide(); criteriaOperation->hide(); minMaxValid = false; minMaxMode = none; minMaxUnit = noUnit; minMaxInteger=0; minMaxDouble=0.0; searchType = OT_NONE; switch (item) { case OT_NONE : break; case OT_DISABLED_SESSIONS : searchType = item; break; case OT_NOTES : searchType = item; break; case OT_BOOK_MARKS : searchType = item; break; case OT_NOTES_STRING : searchType = item; enterString->clear(); enterString->show(); criteriaOperation->setText(QChar(0x2208)); // use either 0x220B or 0x2208 criteriaOperation->show(); break; case OT_AHI : searchType = item; enterDouble->setRange(0,999); enterDouble->setValue(5.0); enterDouble->setDecimals(2); criteriaOperation->setText(">"); criteriaOperation->show(); enterDouble->show(); minMaxMode = maxDouble; break; case OT_SHORT_SESSIONS : searchType = item; enterDouble->setRange(0,2000); enterDouble->setSuffix(" Miniutes"); enterDouble->setDecimals(2); criteriaOperation->setText("<"); criteriaOperation->show(); enterDouble->setValue(5); enterDouble->show(); minMaxUnit = time; minMaxMode = minInteger; break; case OT_SESSIONS_QTY : searchType = item; enterInteger->setRange(0,99); enterInteger->setSuffix(""); enterInteger->setValue(1); criteriaOperation->setText(">"); criteriaOperation->show(); minMaxMode = maxInteger; enterInteger->show(); break; case OT_DAILY_USAGE : searchType = item; enterDouble->setRange(0,999); enterDouble->setSuffix(" Hours"); enterDouble->setDecimals(2); criteriaOperation->setText("<"); criteriaOperation->show(); enterDouble->setValue(p_profile->cpap->complianceHours()); enterDouble->show(); minMaxUnit = time; minMaxMode = minInteger; break; default: // Have an Event enterInteger->setRange(0,999); enterInteger->setSuffix(""); enterInteger->setValue(0); criteriaOperation->setText(">"); criteriaOperation->show(); minMaxMode = maxInteger; enterInteger->show(); searchType = item; //item is channel id which is >= 0x1000 break; } criteriaChanged(); if (searchType == OT_NONE) { statusA->show(); statusA->setText(centerLine("Please select a Match")); //statusB->hide(); summaryStatsA->clear(); summaryStatsB->clear(); summaryStatsC->clear(); continueButton->setEnabled(false); startButton->setEnabled(false); return; } } bool DailySearchTab::find(QDate& date,Day* day) { if (!day) return false; bool found=false; QString extra=""; switch (searchType) { case OT_DISABLED_SESSIONS : { QList sessions = day->getSessions(MT_CPAP,true); for (auto & sess : sessions) { if (!sess->enabled()) { found=true; nextTab = TW_DETAILED ; } } } break; case OT_NOTES : { Session* journal=daily->GetJournalSession(date); if (journal && journal->settings.contains(Journal_Notes)) { QString jcontents = convertRichText2Plain(journal->settings[Journal_Notes].toString()); extra = jcontents.trimmed().left(20); found=true; nextTab = TW_NOTES ; } } break; case OT_BOOK_MARKS : { Session* journal=daily->GetJournalSession(date); if (journal && journal->settings.contains(Bookmark_Start)) { found=true; nextTab = TW_BOOKMARK ; } } break; case OT_NOTES_STRING : { Session* journal=daily->GetJournalSession(date); if (journal && journal->settings.contains(Journal_Notes)) { QString jcontents = convertRichText2Plain(journal->settings[Journal_Notes].toString()); QString findStr = enterString->text(); if (jcontents.contains(findStr,Qt::CaseInsensitive) ) { found=true; extra = jcontents.trimmed().left(20); nextTab = TW_NOTES ; } } } break; case OT_AHI : { EventDataType ahi = calculateAhi(day); EventDataType limit = enterDouble->value(); if (!minMaxValid || ahi > minMaxDouble ) { minMaxDouble = ahi; minMaxValid = true; } if (ahi > limit ) { found=true; nextTab = TW_EVENTS ; nextTab = TW_DETAILED ; extra = QString::number(ahi,'f', 2); } } break; case OT_SHORT_SESSIONS : { QList sessions = day->getSessions(MT_CPAP); for (auto & sess : sessions) { qint64 ms = sess->length(); double minutes= ((double)ms)/60000.0; if (!minMaxValid || ms < minMaxInteger ) { minMaxInteger = ms; minMaxValid = true; } if (minutes < enterDouble->value()) { found=true; nextTab = TW_DETAILED ; extra = formatTime(ms); } } } break; case OT_SESSIONS_QTY : { QList sessions = day->getSessions(MT_CPAP); quint32 size = sessions.size(); if (!minMaxValid || size > minMaxInteger ) { minMaxInteger = size; minMaxValid = true; } if (size > (quint32)enterInteger->value()) { found=true; nextTab = TW_DETAILED ; extra = QString::number(size); } } break; case OT_DAILY_USAGE : { QList sessions = day->getSessions(MT_CPAP); qint64 sum = 0 ; for (auto & sess : sessions) { sum += sess->length(); } double hours= ((double)sum)/3600000.0; if (!minMaxValid || sum < minMaxInteger ) { minMaxInteger = sum; minMaxValid = true; } if (hours < enterDouble->value()) { found=true; nextTab = TW_DETAILED ; extra = formatTime(sum); } } break; default : { quint32 count = day->count(searchType); if (count<=0) break; //DEBUGFW Q(count) Q(minMaxInteger) Q(minMaxValid) ; if (!minMaxValid || (quint32)count > minMaxInteger ) { //DEBUGFW Q(count) Q(minMaxInteger) Q(minMaxValid) ; minMaxInteger = count; minMaxValid = true; } if (count > (quint32) enterInteger->value()) { found=true; extra = QString::number(count); nextTab = TW_EVENTS ; } } break; case OT_NONE : return false; break; } if (found) { addItem(date , extra ); return true; } return false; }; void DailySearchTab::findall(QDate date, bool start) { Q_UNUSED(start); guiDisplayTable->clear(); passFound=0; int count = 0; int no_data = 0; Day*day; while (true) { count++; nextDate = date; if (passFound >= passDisplayLimit) { break; } if (date < firstDate) { break; } if (date > lastDate) { break; } daysSearched++; if (date.isValid()) { // use date // find and add //daysSearched++; day= p_profile->GetDay(date); if (day) { if (find(date, day) ) { passFound++; daysFound++; } } else { no_data++; daysSkipped++; // Skip day. maybe no sleep or sdcard was no inserted. } } else { qWarning() << "DailySearchTab::findall invalid date." << date; break; } date=date.addDays(-1); } endOfPass(); return ; }; void DailySearchTab::addItem(QDate date, QString value) { int row = passFound; QTableWidgetItem *item = new QTableWidgetItem(*icon_off,date.toString()); item->setData(dateRole,date); item->setData(valueRole,value); item->setIcon (*icon_off); item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); QTableWidgetItem *item2 = new QTableWidgetItem(value); item2->setTextAlignment(Qt::AlignCenter); //item2->setData(dateRole,date); //item2->setData(valueRole,value); item2->setFlags(Qt::NoItemFlags); if (guiDisplayTable->rowCount()<(row+1)) { guiDisplayTable->insertRow(row); } guiDisplayTable->setItem(row,0,item); guiDisplayTable->setItem(row,1,item2); } void DailySearchTab::endOfPass() { QString display; if ((passFound >= passDisplayLimit) && (daysSearchedsetText(centerLine(tr("More to Search"))); //statusB->setText(""); //statusC->setText(centerLine(tr("Continue or Change Match"))); statusA->show(); //statusB->hide(); //statusC->show(); continueButton->setEnabled(true); startButton->setEnabled(false); } else if (daysFound>0) { DEBUGFW ; statusA->setText(centerLine(tr("End of Search"))); //statusB->setText(""); //statusC->setText(centerLine(tr("Change Match"))); statusA->show(); //statusB->hide(); //statusC->show(); continueButton->setEnabled(false); startButton->setEnabled(false); } else { DEBUGFW ; statusA->setText(centerLine(tr("No Matching Criteria"))); //statusB->setText(""); //statusC->setText(centerLine(tr("Change Match"))); statusA->show(); //statusB->hide(); //statusC->show(); continueButton->setEnabled(false); } //status->setText(centerLine( display )); //status->show(); displayStatistics(); } void DailySearchTab::search(QDate date, bool start) { findall(date,start); }; void DailySearchTab::on_itemActivated(QTableWidgetItem *item) { if (item->column()!=0) { item=guiDisplayTable->item(item->row(),0); } QDate date = item->data(dateRole).toDate(); item->setIcon (*icon_on); guiDisplayTable->setCurrentItem(item,QItemSelectionModel::Clear); daily->LoadDate( date ); if (nextTab>=0 && nextTab < dailyTabWidget->count()) { dailyTabWidget->setCurrentIndex(nextTab); // 0 = details ; 1=events =2 notes ; 3=bookarks; } } void DailySearchTab::on_continueButton_clicked() { search (nextDate , false); } void DailySearchTab::on_startButton_clicked() { firstDate = p_profile->FirstDay(MT_CPAP); lastDate = p_profile->LastDay(MT_CPAP); daysTotal= 1+firstDate.daysTo(lastDate); daysFound=0; daysSkipped=0; daysSearched=0; search (lastDate ,true); } void DailySearchTab::on_intValueChanged(int ) { enterInteger->findChild()->deselect(); criteriaChanged(); } void DailySearchTab::on_doubleValueChanged(double ) { enterDouble->findChild()->deselect(); criteriaChanged(); } void DailySearchTab::on_textEdited(QString ) { criteriaChanged(); } void DailySearchTab::on_dailyTabWidgetCurrentChanged(int ) { delayedCreateUi(); } void DailySearchTab::displayStatistics() { QString extra; QString space(""); if (minMaxValid) switch (minMaxMode) { case minInteger: if (minMaxUnit == time) { extra = QString("%1%2%3").arg(space).arg(tr("Min: ")).arg( formatTime(minMaxInteger)); } else { extra = QString("%1%2%3").arg(space).arg(tr("Min: ")).arg(minMaxInteger); } break; case maxInteger: extra = QString("%1%2%3").arg(space).arg(tr("Max: ")).arg(minMaxInteger); break; case minDouble: extra = QString("%1%2%3").arg(space).arg(tr("Min: ")).arg(minMaxDouble,0,'f',1); break; case maxDouble: extra = QString("%1%2%3").arg(space).arg(tr("Max: ")).arg(minMaxDouble,0,'f',1); break; default: extra=""; break; } summaryStatsA->setText(centerLine(QString(tr("Searched %1/%2 days.")).arg(daysSearched).arg(daysTotal) )); summaryStatsB->setText(centerLine(QString(tr("Found %1.")).arg(daysFound) )); if (extra.size()>0) { summaryStatsC->setText(extra); summaryStatsC->show(); } else { summaryStatsC->hide(); } } void DailySearchTab::criteriaChanged() { statusA->setText(centerLine(" ----- ")); statusA->clear(); statusB->clear(); statusC->clear(); summaryStatsA->clear(); summaryStatsB->clear(); summaryStatsC->clear(); startButton->setEnabled( true); continueButton->setEnabled(false); guiDisplayTable->clear(); } // inputs character string. // outputs cwa centered html string. // converts \n to
QString DailySearchTab::centerLine(QString line) { return QString( "
%1
").arg(line).replace("\n","
"); } QString DailySearchTab::introductionStr() { return centerLine( "Finds days that match specified criteria\n" "Searches from last day to first day\n" "-----\n" "Find Days with:" ); //"Searching starts on the lastDay to the firstDay\n" } QString DailySearchTab::formatTime (quint32 ms) { DEBUGFW Q(ms) ; ms += 500; // round to nearest second DEBUGFW Q(ms) ; quint32 hours = ms / 3600000; ms = ms % 3600000; DEBUGFW Q(ms) Q(hours) ; quint32 minutes = ms / 60000; DEBUGFW Q(ms) Q(hours) Q(minutes) ; ms = ms % 60000; quint32 seconds = ms /1000; DEBUGFW Q(ms) Q(hours) Q(minutes) Q(seconds); return QString("%1h %2m %3s").arg(hours).arg(minutes).arg(seconds); #if 0 double seconds = minutes*60; if (seconds<100) { //display seconds } else { // display tenths of minutes. return QString("%1 minutes").arg(seconds,0,'f',1); } #endif } QString DailySearchTab::convertRichText2Plain (QString rich) { richText.setHtml(rich); return richText.toPlainText(); } EventDataType DailySearchTab::calculateAhi(Day* day) { if (!day) return 0.0; double tmphours=day->hours(MT_CPAP); if (tmphours<=0) return 0; EventDataType ahi=day->count(AllAhiChannels); if (p_profile->general->calculateRDI()) ahi+=day->count(CPAP_RERA); ahi/=tmphours; return ahi; } #if 0 quint32 chantype = schema::FLAG | schema::SPAN | schema::MINOR_FLAG; if (p_profile->general->showUnknownFlags()) chantype |= schema::UNKNOWN; QList chans = day->getSortedMachineChannels(chantype); // Go through all the enabled sessions of the day for (QList::iterator s=day->begin();s!=day->end();++s) { Session * sess = *s; if (!sess->enabled()) continue; // For each session, go through all the channels QHash >::iterator m; for (int c=0; c < chans.size(); ++c) { ChannelID code = chans.at(c); m = sess->eventlist.find(code); if (m == sess->eventlist.end()) continue; drift=(sess->type() == MT_CPAP) ? clockdrift : 0; // Prepare title for this code, if there are any events QTreeWidgetItem *mcr; if (mcroot.find(code)==mcroot.end()) { int cnt=day->count(code); if (!cnt) continue; // If no events than don't bother showing.. total_events+=cnt; QString st=schema::channel[code].fullname(); if (st.isEmpty()) { st=QString("Fixme %1").arg(code); } st+=" "; if (cnt==1) st+=tr("%1 event").arg(cnt); else st+=tr("%1 events").arg(cnt); QStringList l(st); l.append(""); mcroot[code]=mcr=new QTreeWidgetItem(root,l); mccnt[code]=0; } else { mcr=mcroot[code]; } // number of digits required for count depends on total for day int numDigits = ceil(log10(day->count(code)+1)); // Now we go through the event list for the *session* (not for the day) for (int z=0;zraw(o) > 0) s += QString(" (%3)").arg(m.value()[z]->raw(o)); a.append(s); QTreeWidgetItem *item=new QTreeWidgetItem(a); item->setData(0,Qt::UserRole,t); mcr->addChild(item); } } } } #endif