Initial ZEO CSV support.. New ZEO CSV import menu, only line graphs for now.

This commit is contained in:
Mark Watkins 2012-01-11 23:55:46 +10:00
parent 3a8adbdf63
commit e3ff868cf1
15 changed files with 335 additions and 20 deletions

View File

@ -14,6 +14,7 @@ License: GPL
#include <QDir>
#include <QTextStream>
#include "zeo_loader.h"
#include "SleepLib/machine.h"
@ -34,6 +35,9 @@ int ZEOLoader::Open(QString & path,Profile *profile)
QString newpath;
QString dirtag="zeo";
// Could Scan the ZEO folder for a list of CSVs
if (path.toLower().endsWith(QDir::separator()+dirtag)) {
return 0;
//newpath=path;
@ -43,11 +47,6 @@ int ZEOLoader::Open(QString & path,Profile *profile)
QString filename;
if (path.toLower().endsWith(".csv")) {
} else if (path.toLower().endsWith(".dat")) {
// not supported.
}
// ZEO folder structure detection stuff here.
return 0; // number of machines affected
@ -72,19 +71,194 @@ Machine *ZEOLoader::CreateMachine(Profile *profile)
qDebug("Create ZEO Machine Record");
Machine *m=new SleepStage(profile,0);
m->SetType(MT_SLEEPSTAGE);
m->SetClass(zeo_class_name);
m->properties[STR_PROP_Brand]="ZEO";
m->properties[STR_PROP_Model]="Personal Sleep Coach";
QString s;
s.sprintf("%i",zeo_data_version);
m->properties[STR_PROP_DataVersion]=s;
m->properties[STR_PROP_DataVersion]=QString::number(zeo_data_version);
profile->AddMachine(m);
m->properties[STR_PROP_Path]="{"+STR_GEN_DataFolder+"}/"+m->GetClass()+"_"+m->hexid()+"/";
QString path="{"+STR_GEN_DataFolder+"}/"+m->GetClass()+"_"+m->hexid()+"/";
m->properties[STR_PROP_Path]=path;
m->properties[STR_PROP_BackupPath]=path+"Backup/";
return m;
}
/*15233: "Sleep Date"
15234: "ZQ"
15236: "Total Z"
15237: "Time to Z"
15237: "Time in Wake"
15238: "Time in REM"
15238: "Time in Light"
15241: "Time in Deep"
15242: "Awakenings"
15245: "Start of Night"
15246: "End of Night"
15246: "Rise Time"
15247: "Alarm Reason"
15247: "Snooze Time"
15254: "Wake Tone"
15259: "Wake Window"
15259: "Alarm Type"
15260: "First Alarm Ring"
15261: "Last Alarm Ring"
15261: "First Snooze Time"
15265: "Last Snooze Time"
15266: "Set Alarm Time"
15266: "Morning Feel"
15267: "Sleep Graph"
15267: "Detailed Sleep Graph"
15268: "Firmware Version" */
int ZEOLoader::OpenFile(QString filename)
{
QFile file(filename);
if (filename.toLower().endsWith(".csv")) {
if (!file.open(QFile::ReadOnly)) {
qDebug() << "Couldn't open zeo file" << filename;
return 0;
}
} else {// if (filename.toLower().endsWith(".dat")) {
return 0;
// not supported.
}
QTextStream text(&file);
QString headerdata=text.readLine();
QStringList header=headerdata.split(",");
QString line;
QStringList linecomp;
QDateTime start_of_night, end_of_night, rise_time;
SessionID sid;
const qint64 WindowSize=30000;
qint64 st,tt;
int stage;
int ZQ, TotalZ, TimeToZ, TimeInWake, TimeInREM, TimeInLight, TimeInDeep, Awakenings;
int AlarmReason, SnoozeTime, WakeTone, WakeWindow, AlarmType, MorningFeel, FirmwareVersion;
QDateTime FirstAlarmRing, LastAlarmRing, FirstSnoozeTime, LastSnoozeTime, SetAlarmTime;
QStringList SG, DSG;
Machine *mach=CreateMachine(p_profile);
bool ok;
bool dodgy;
do {
line=text.readLine();
dodgy=false;
if (line.isEmpty()) continue;
linecomp=line.split(",");
ZQ=linecomp[1].toInt(&ok);
if (!ok) dodgy=true;
TotalZ=linecomp[2].toInt(&ok);
if (!ok) dodgy=true;
TimeToZ=linecomp[3].toInt(&ok);
if (!ok) dodgy=true;
TimeInWake=linecomp[4].toInt(&ok);
if (!ok) dodgy=true;
TimeInREM=linecomp[5].toInt(&ok);
if (!ok) dodgy=true;
TimeInLight=linecomp[6].toInt(&ok);
if (!ok) dodgy=true;
TimeInDeep=linecomp[7].toInt(&ok);
if (!ok) dodgy=true;
Awakenings=linecomp[8].toInt(&ok);
if (!ok) dodgy=true;
start_of_night=QDateTime::fromString(linecomp[9],"MM/dd/yyyy HH:mm");
if (!start_of_night.isValid()) dodgy=true;
end_of_night=QDateTime::fromString(linecomp[10],"MM/dd/yyyy HH:mm");
if (!end_of_night.isValid()) dodgy=true;
rise_time=QDateTime::fromString(linecomp[11],"MM/dd/yyyy HH:mm");
if (!rise_time.isValid()) dodgy=true;
AlarmReason=linecomp[12].toInt(&ok);
if (!ok) dodgy=true;
SnoozeTime=linecomp[13].toInt(&ok);
if (!ok) dodgy=true;
WakeTone=linecomp[14].toInt(&ok);
if (!ok) dodgy=true;
WakeWindow=linecomp[15].toInt(&ok);
if (!ok) dodgy=true;
AlarmType=linecomp[16].toInt(&ok);
if (!ok) dodgy=true;
if (!linecomp[17].isEmpty()) {
FirstAlarmRing=QDateTime::fromString(linecomp[9],"MM/dd/yyyy HH:mm");
if (!FirstAlarmRing.isValid()) dodgy=true;
}
if (!linecomp[18].isEmpty()) {
LastAlarmRing=QDateTime::fromString(linecomp[9],"MM/dd/yyyy HH:mm");
if (!LastAlarmRing.isValid()) dodgy=true;
}
if (!linecomp[19].isEmpty()) {
FirstSnoozeTime=QDateTime::fromString(linecomp[9],"MM/dd/yyyy HH:mm");
if (!FirstSnoozeTime.isValid()) dodgy=true;
}
if (!linecomp[20].isEmpty()) {
LastSnoozeTime=QDateTime::fromString(linecomp[9],"MM/dd/yyyy HH:mm");
if (!LastSnoozeTime.isValid()) dodgy=true;
}
if (!linecomp[21].isEmpty()) {
SetAlarmTime=QDateTime::fromString(linecomp[9],"MM/dd/yyyy HH:mm");
if (!SetAlarmTime.isValid()) dodgy=true;
}
MorningFeel=linecomp[22].toInt(&ok);
if (!ok) dodgy=true;
FirmwareVersion=linecomp[25].toInt(&ok);
if (!ok) dodgy=true;
if (dodgy)
continue;
SG=linecomp[23].split(" ");
DSG=linecomp[24].split(" ");
const int WindowSize=30000;
sid=start_of_night.toTime_t();
if (DSG.size()==0)
continue;
if (mach->SessionExists(sid))
continue;
Session *sess=new Session(mach,sid);
sess->settings[ZEO_Awakenings]=Awakenings;
sess->settings[ZEO_MorningFeel]=MorningFeel;
sess->settings[ZEO_TimeToZ]=TimeToZ;
sess->settings[ZEO_ZQ]=ZQ;
sess->settings[ZEO_TimeInWake]=TimeInWake;
sess->settings[ZEO_TimeInREM]=TimeInREM;
sess->settings[ZEO_TimeInLight]=TimeInLight;
sess->settings[ZEO_TimeInDeep]=TimeInDeep;
st=qint64(start_of_night.toTime_t()) * 1000L;
sess->really_set_first(st);
tt=st;
EventList * sleepstage=sess->AddEventList(ZEO_SleepStage,EVL_Event,1,0,0,4);
for (int i=0;i<DSG.size();i++) {
stage=DSG[i].toInt(&ok);
if (ok) {
sleepstage->AddEvent(tt,stage);
}
tt+=WindowSize;
}
sess->really_set_last(tt);
int size=DSG.size();
sess->SetChanged(true);
mach->AddSession(sess,p_profile);
qDebug() << linecomp[0] << start_of_night << end_of_night << rise_time << size << "30 second chunks";
} while (!line.isNull());
mach->Save();
return true;
}
static bool zeo_initialized=false;

View File

@ -10,7 +10,7 @@ License: GPL
#include "SleepLib/machine_loader.h"
const QString zeo_class_name="CMS50";
const QString zeo_class_name="ZEO";
const int zeo_data_version=1;
@ -23,6 +23,7 @@ class ZEOLoader : public MachineLoader
ZEOLoader();
virtual ~ZEOLoader();
virtual int Open(QString & path,Profile *profile);
virtual int OpenFile(QString filename);
static void Register();
virtual int Version() { return zeo_data_version; }

View File

@ -467,4 +467,7 @@ ChannelID OXI_Pulse, OXI_SPO2, OXI_PulseChange, OXI_SPO2Drop, OXI_Plethy;
ChannelID Journal_Notes, Journal_Weight, Journal_BMI, Journal_ZombieMeter, Bookmark_Start, Bookmark_End, Bookmark_Notes;
ChannelID ZEO_SleepStage, ZEO_ZQ, ZEO_TotalZ, ZEO_TimeToZ, ZEO_TimeInWake, ZEO_TimeInREM, ZEO_TimeInLight, ZEO_TimeInDeep, ZEO_Awakenings,
ZEO_AlarmReason, ZEO_SnoozeTime, ZEO_WakeTone, ZEO_WakeWindow, ZEO_AlarmType, ZEO_MorningFeel, ZEO_FirmwareVersion,
ZEO_FirstAlarmRing, ZEO_LastAlarmRing, ZEO_FirstSnoozeTime, ZEO_LastSnoozeTime, ZEO_SetAlarmTime, ZEO_RiseTime;

View File

@ -105,6 +105,9 @@ extern ChannelID OXI_Pulse, OXI_SPO2, OXI_PulseChange, OXI_SPO2Drop, OXI_Plethy;
extern ChannelID Journal_Notes, Journal_Weight, Journal_BMI, Journal_ZombieMeter, Bookmark_Start, Bookmark_End, Bookmark_Notes;
extern ChannelID ZEO_SleepStage, ZEO_ZQ, ZEO_TotalZ, ZEO_TimeToZ, ZEO_TimeInWake, ZEO_TimeInREM, ZEO_TimeInLight, ZEO_TimeInDeep, ZEO_Awakenings,
ZEO_AlarmReason, ZEO_SnoozeTime, ZEO_WakeTone, ZEO_WakeWindow, ZEO_AlarmType, ZEO_MorningFeel, ZEO_FirmwareVersion,
ZEO_FirstAlarmRing, ZEO_LastAlarmRing, ZEO_FirstSnoozeTime, ZEO_LastSnoozeTime, ZEO_SetAlarmTime, ZEO_RiseTime;
#endif // MACHINE_COMMON_H

View File

@ -163,6 +163,15 @@ void init()
Bookmark_End=schema::channel["BookmarkEnd"].id();
Bookmark_Notes=schema::channel["BookmarkNotes"].id();
ZEO_SleepStage=schema::channel["SleepStage"].id();
ZEO_ZQ=schema::channel["ZeoZQ"].id();
ZEO_Awakenings=schema::channel["Awakenings"].id();
ZEO_MorningFeel=schema::channel["MorningFeel"].id();
ZEO_TimeInWake=schema::channel["TimeInWake"].id();
ZEO_TimeInREM=schema::channel["TimeInREM"].id();
ZEO_TimeInLight=schema::channel["TimeInLight"].id();
ZEO_TimeInDeep=schema::channel["TimeInDeep"].id();
ZEO_TimeToZ=schema::channel["TimeToZ"].id();
}
Channel::Channel(int id, ChanType type, ScopeType scope, QString name, QString description, QString label, QString unit, DataType datatype, QColor color, int link):

View File

@ -187,7 +187,8 @@ OTHER_FILES += \
LICENSE.txt \
docs/tooltips.css \
docs/script.js \
update.xml
update.xml \
docs/changelog.txt

View File

@ -113,6 +113,7 @@ Daily::Daily(QWidget *parent,gGraphView * shared)
TE=new gGraph(GraphView,tr("Exp. Time"),schema::channel[CPAP_Te].description()+"\n("+schema::channel[CPAP_Te].units()+")",default_height);
IE=new gGraph(GraphView,tr("IE"),schema::channel[CPAP_IE].description()+"\n("+schema::channel[CPAP_IE].units()+")",default_height);
STAGE=new gGraph(GraphView,tr("Sleep Stage"),schema::channel[ZEO_SleepStage].description()+"\n("+schema::channel[ZEO_SleepStage].units()+")",default_height);
int oxigrp=PROFILE.ExistsAndTrue("SyncOximetry") ? 0 : 1;
PULSE=new gGraph(GraphView,STR_TR_PulseRate,schema::channel[OXI_Pulse].description()+"\n("+schema::channel[OXI_Pulse].units()+")",default_height,oxigrp);
SPO2=new gGraph(GraphView,STR_TR_SpO2,schema::channel[OXI_SPO2].description()+"\n("+schema::channel[OXI_SPO2].units()+")",default_height,oxigrp);
@ -205,7 +206,7 @@ Daily::Daily(QWidget *parent,gGraphView * shared)
FRW->AddLayer(AddCPAP(los));
gGraph *graphs[]={ PRD, LEAK, AHI, SNORE, PTB, MP, RR, MV, TV, FLG, IE, TI, TE, TgMV, SPO2, PLETHY, PULSE };
gGraph *graphs[]={ PRD, LEAK, AHI, SNORE, PTB, MP, RR, MV, TV, FLG, IE, TI, TE, TgMV, SPO2, PLETHY, PULSE, STAGE };
int ng=sizeof(graphs)/sizeof(gGraph*);
for (int i=0;i<ng;i++){
graphs[i]->AddLayer(new gXGrid());
@ -273,6 +274,8 @@ Daily::Daily(QWidget *parent,gGraphView * shared)
//INTPULSE->AddLayer(AddCPAP(new gLineChart(OXI_Pulse,Qt::red,square)));
//INTSPO2->AddLayer(AddCPAP(new gLineChart(OXI_SPO2,Qt::blue,square)));
STAGE->AddLayer(AddSTAGE(new gLineChart(ZEO_SleepStage,Qt::gray,true)));
gLineOverlaySummary *los1=new gLineOverlaySummary(tr("Events/hour"),5,-4);
gLineOverlaySummary *los2=new gLineOverlaySummary(tr("Events/hour"),5,-4);
PULSE->AddLayer(AddOXI(los1->add(new gLineOverlayBar(OXI_PulseChange,QColor("light gray"),tr("PD"),FT_Span))));
@ -645,7 +648,7 @@ void Daily::Load(QDate date)
previous_date=date;
Day *cpap=PROFILE.GetDay(date,MT_CPAP);
Day *oxi=PROFILE.GetDay(date,MT_OXIMETER);
// Day *sleepstage=profile->GetDay(date,MT_SLEEPSTAGE);
Day *stage=PROFILE.GetDay(date,MT_SLEEPSTAGE);
if (!PROFILE.session->cacheSessions()) {
if (lastcpapday && (lastcpapday!=cpap)) {
@ -687,6 +690,7 @@ void Daily::Load(QDate date)
UpdateOXIGraphs(oxi);
UpdateCPAPGraphs(cpap);
UpdateSTAGEGraphs(stage);
UpdateEventsTree(ui->treeWidget,cpap);
mainwin->refreshStatistics();
@ -1117,6 +1121,37 @@ void Daily::Load(QDate date)
//html+=tmp;
}
}
if (stage) {
html+=QString("<tr><td align=left colspan=5><i>%1</i></td></tr>").arg(tr("Sleep Stage Sessions"));
for (QVector<Session *>::iterator s=stage->begin();s!=stage->end();s++) {
fd=QDateTime::fromTime_t((*s)->first()/1000L);
ld=QDateTime::fromTime_t((*s)->last()/1000L);
int len=(*s)->length()/1000L;
int h=len/3600;
int m=(len/60) % 60;
int s1=len % 60;
tooltip=stage->machine->GetClass()+" "+tr("Sleep Stage")+" "+QString().sprintf("%2ih,&nbsp;%2im,&nbsp;%2is",h,m,s1);
Session *sess=*s;
if (!sess->settings.contains(SESSION_ENABLED)) {
sess->settings[SESSION_ENABLED]=true;
}
bool b=sess->settings[SESSION_ENABLED].toBool();
QHash<ChannelID,QVariant>::iterator i=(*s)->settings.find(CPAP_BrokenWaveform);
corrupted_waveform=(i!=(*s)->settings.end()) && i.value().toBool();
html+=QString("<tr><td align=left><a class=info href='stage=%1'>%3<span>%2</span></a></td><td width=26><a href='toggleoxisession=%1'><img src='qrc:/icons/session-%4.png' width=24px></a></td><td align=center>%5</td><td align=center>%6</td><td align=center>%7</td></tr>")
.arg((*s)->session())
.arg(tooltip)
.arg((*s)->session(),8,10,QChar('0'))
.arg((b ? "on" : "off"))
.arg(fd.date().toString(Qt::SystemLocaleShortDate))
.arg(fd.toString("HH:mm"))
.arg(ld.toString("HH:mm"));
//tmp.sprintf(("<tr><td align=left><a href='stage=%i' title='"+tooltip+"'>%08i</a></td><td align=center>"+fd.date().toString(Qt::SystemLocaleShortDate)+"</td><td align=center>"+fd.toString("HH:mm ")+"</td><td align=center>"+ld.toString("HH:mm")+"</td></tr>").toLatin1(),(*s)->session(),(*s)->session());
//html+=tmp;
}
}
if (corrupted_waveform) {
html+=QString("<tr><td colspan=5 align=center><i>%1</i></td></tr>").arg(tr("One or more waveform record for this session had faulty source data. Some waveform overlay points may not match up correctly."));
}
@ -1412,6 +1447,16 @@ void Daily::UpdateCPAPGraphs(Day *day)
(*g)->SetDay(day);
}
}
void Daily::UpdateSTAGEGraphs(Day *day)
{
//if (!day) return;
if (day) {
day->OpenEvents();
}
for (QList<Layer *>::iterator g=STAGEData.begin();g!=STAGEData.end();g++) {
(*g)->SetDay(day);
}
}
void Daily::UpdateOXIGraphs(Day *day)
{

View File

@ -265,20 +265,23 @@ private:
gGraph *PRD,*FRW,*GAHI,*TAP,*LEAK,*SF,*TAP_EAP,*TAP_IAP,*PULSE,*SPO2,
*SNORE,*RR,*MP,*MV,*TV,*FLG,*PTB,*OF, *THPR,
*PLETHY,*TI,*TE, *RE, *IE, *TgMV, *AHI, *RDI;
*PLETHY,*TI,*TE, *RE, *IE, *TgMV, *AHI, *RDI, *STAGE;
QList<Layer *> OXIData;
QList<Layer *> CPAPData;
QList<Layer *> STAGEData;
QHash<QString,QPushButton *> GraphToggles;
QVector<QAction *> GraphAction;
QGLContext *offscreen_context;
QList<int> splitter_sizes;
Layer * AddCPAP(Layer *d) { CPAPData.push_back(d); return d; }
Layer * AddSTAGE(Layer *d) { STAGEData.push_back(d); return d; }
Layer * AddOXI(Layer *d) { OXIData.push_back(d); return d; }
void UpdateCPAPGraphs(Day *day);
void UpdateOXIGraphs(Day *day);
void UpdateSTAGEGraphs(Day *day);
Ui::Daily *ui;
QDate previous_date;

0
docs/changelog.txt Normal file
View File

View File

@ -119,7 +119,15 @@ Important: One id code per item, DO NOT CHANGE ID NUMBERS!!!
</group>
<group name="SLEEP">
<channel id="0x2000" class="data" name="SleepStage" details="Sleep Stage" label="Sleep Stage" color="dark grey"/>
<channel id="0x2001" class="data" name="ZEOBW" details="Zeo Brainwave" label="ZeoWave" color="black"/>
<channel id="0x2001" class="data" name="ZeoBW" details="Zeo Brainwave" label="ZeoWave" color="black"/>
<channel id="0x2002" class="data" name="Awakenings" details="Awakenings" label="Awakenings" color="black"/>
<channel id="0x2003" class="data" name="MorningFeel" details="ZEO Morning Feel" label="Morning Feel" color="black"/>
<channel id="0x2004" class="data" name="TimeInWake" details="Time In Wake" label="Time In Wake" color="red"/>
<channel id="0x2005" class="data" name="TimeInREM" details="Time In REM Sleep" label="Time In REM" color="green"/>
<channel id="0x2006" class="data" name="TimeInLight" details="Time In Light Sleep" label="Time In Light" color="blue"/>
<channel id="0x2007" class="data" name="TimeInDeep" details="Time In Deep Sleep" label="Time In Deep" color="magenta"/>
<channel id="0x2008" class="data" name="TimeToZ" details="Time To Sleep" label="Time To Z" color="magenta"/>
<channel id="0x2009" class="data" name="ZeoZQ" details="ZEO ZQ" label="ZEO ZQ" color="magenta"/>
</group>
<group name="GENERAL">
<channel id="0x0800" class="data" name="BPSys" details="Blood Pressure Systolic" label="BPS" unit="mmHg" color="red"/>

View File

@ -111,7 +111,7 @@ int main(int argc, char *argv[])
////////////////////////////////////////////////////////////////////////////////////////////
PRS1Loader::Register();
CMS50Loader::Register();
//ZEOLoader::Register();
//ZEOLoader::Register(); // Use outside of directory importer..
ResmedLoader::Register();
IntellipapLoader::Register();

View File

@ -24,6 +24,7 @@
#include <QPainter>
#include <QProcess>
#include <QFontMetrics>
#include <SleepLib/loader_plugins/zeo_loader.h>
#include <cmath>
#include "mainwindow.h"
@ -482,6 +483,41 @@ enum RXSortMode { RX_first, RX_last, RX_days, RX_ahi, RX_mode, RX_min, RX_max, R
RXSortMode RXsort=RX_first;
bool RXorder=false;
bool operator<(const RXChange & c1, const RXChange & c2) {
const RXChange * comp1=&c1;
const RXChange * comp2=&c2;
if (RXorder) {
switch (RXsort) {
case RX_ahi: return comp1->ahi < comp2->ahi;
case RX_days: return comp1->days < comp2->days;
case RX_first: return comp1->first < comp2->first;
case RX_last: return comp1->last < comp2->last;
case RX_mode: return comp1->mode < comp2->mode;
case RX_min: return comp1->min < comp2->min;
case RX_max: return comp1->max < comp2->max;
case RX_maxhi: return comp1->maxhi < comp2->maxhi;
case RX_per1: return comp1->per1 < comp2->per1;
case RX_per2: return comp1->per2 < comp2->per2;
case RX_weighted: return comp1->weighted < comp2->weighted;
};
} else {
switch (RXsort) {
case RX_ahi: return comp1->ahi > comp2->ahi;
case RX_days: return comp1->days > comp2->days;
case RX_first: return comp1->first > comp2->first;
case RX_last: return comp1->last > comp2->last;
case RX_mode: return comp1->mode > comp2->mode;
case RX_min: return comp1->min > comp2->min;
case RX_max: return comp1->max > comp2->max;
case RX_maxhi: return comp1->maxhi > comp2->maxhi;
case RX_per1: return comp1->per1 > comp2->per1;
case RX_per2: return comp1->per2 > comp2->per2;
case RX_weighted: return comp1->weighted > comp2->weighted;
};
}
return true;
}
bool RXSort(const RXChange * comp1, const RXChange * comp2) {
if (RXorder) {
switch (RXsort) {
@ -1113,6 +1149,9 @@ void MainWindow::on_summaryButton_clicked()
recbox+="</body></html>";
ui->recordsBox->setHtml(recbox);
RXsort=RX_min;
RXorder=true;
qSort(rxchange.begin(),rxchange.end());
html+="<div align=center>";
html+=QString("<br/><b>Changes to Prescription Settings</b>");
html+=QString("<table cellpadding=2 cellspacing=0 border=1 width=90%>");
@ -2593,3 +2632,25 @@ void MainWindow::doReprocessEvents()
if (overview) overview->ReloadGraphs();
}
}
void MainWindow::on_actionImport_ZEO_Data_triggered()
{
QFileDialog w;
w.setFileMode(QFileDialog::ExistingFiles);
w.setOption(QFileDialog::ShowDirsOnly, false);
w.setOption(QFileDialog::DontUseNativeDialog,true);
w.setFilters(QStringList("Zeo CSV File (*.csv)"));
ZEOLoader zeo;
if (w.exec()==QFileDialog::Accepted) {
QString filename=w.selectedFiles()[0];
if (!zeo.OpenFile(filename)) {
Notify("There was a problem opening ZEO File: "+filename);
return;
}
Notify("Zeo CSV Import complete");
daily->LoadDate(daily->getDate());
}
}

View File

@ -290,6 +290,8 @@ private slots:
void on_filterBookmarksButton_clicked();
void on_actionImport_ZEO_Data_triggered();
private:
void FreeSessions();

View File

@ -1559,6 +1559,7 @@
<string>&amp;File</string>
</property>
<addaction name="action_Import_Data"/>
<addaction name="actionImport_ZEO_Data"/>
<addaction name="action_Preferences"/>
<addaction name="action_Edit_Profile"/>
<addaction name="separator"/>
@ -1815,6 +1816,11 @@
<string>F4</string>
</property>
</action>
<action name="actionImport_ZEO_Data">
<property name="text">
<string>Import &amp;ZEO Data</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>

View File

@ -10,7 +10,7 @@
<x>0</x>
<y>0</y>
<width>640</width>
<height>414</height>
<height>421</height>
</rect>
</property>
<property name="maximumSize">
@ -42,7 +42,7 @@
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>1</number>
<number>5</number>
</property>
<widget class="QWidget" name="importTab">
<attribute name="title">
@ -884,8 +884,7 @@ Defaults to 60 minutes.. Highly recommend it's left at this value.</string>
<item row="0" column="2">
<widget class="QCheckBox" name="ahiGraphZeroReset">
<property name="toolTip">
<string>Reset the counter to zero at beginning of each (time) window.
Note: Unless you purge and reimport after changing this, you won't see the changes.</string>
<string>Reset the counter to zero at beginning of each (time) window.</string>
</property>
<property name="text">
<string>Zero Reset</string>