Initial overview real Usage Graph

This commit is contained in:
Mark Watkins 2011-07-12 17:10:34 +10:00
parent afb8065ca3
commit ecbe448741
9 changed files with 318 additions and 14 deletions

View File

@ -1,8 +1,8 @@
/********************************************************************
/*
gBarChart Header
Copyright (c)2011 Mark Watkins <jedimark@users.sourceforge.net>
License: GPL
*********************************************************************/
*/
#ifndef GBARCHART_H
#define GBARCHART_H

114
Graphs/gSessionTime.cpp Normal file
View File

@ -0,0 +1,114 @@
/*
gSessionTime Implementation
Copyright (c)2011 Mark Watkins <jedimark@users.sourceforge.net>
License: GPL
*/
#include <math.h>
#include <SleepLib/profiles.h>
#include "gSessionTime.h"
gSessionTime::gSessionTime(gPointData *d,QColor col,Qt::Orientation o)
:gLayer(d),m_orientation(o)
{
color.clear();
color.push_back(col);
Xaxis=new gXAxis();
}
gSessionTime::~gSessionTime()
{
delete Xaxis;
}
void gSessionTime::Plot(gGraphWindow & w,float scrx,float scry)
{
if (!m_visible) return;
if (!data) return;
if (!data->IsReady()) return;
int start_px=w.GetLeftMargin();
int start_py=w.GetBottomMargin();
int width=scrx-(w.GetLeftMargin()+w.GetRightMargin());
int height=scry-(w.GetTopMargin()+w.GetBottomMargin());
double maxx=w.max_x;
double minx=w.min_x;
double xx=maxx - minx;
int days=ceil(xx);
float barwidth=float(width-days)/float(days);
qint64 dy;
//double sd;
double px1,px2,py1,py2;
QColor & col1=color[0];
QColor col2("light grey");
QDateTime d;
QTime t;
double start,end,total;
for (int i=0;i<data->np[0];i++) {
QPointD & rp=data->point[0][i];
if (int(rp.x()) < int(minx)) continue;
if (int(rp.x()) > int(maxx+.5)) break;
d=QDateTime::fromTime_t(rp.x()*86400.0);
t=d.time();
start=t.hour()+(t.minute()/60.0)+(t.second()/3600.0);
d=QDateTime::fromTime_t(rp.y()*86400.0);
t=d.time();
end=t.hour()+(t.minute()/60.0)+(t.second()/3600.0);
total=(rp.y()-rp.x())*24;
dy=int(rp.x())-int(minx); // day number.
if (dy>=days) continue;
if (start>=12) {
// dy++;
start-=24;
}
start+=12;
if (start+total>24) {
// total=24-start;
}
if (total<0.25) continue; // Hide sessions less than 15 minutes
double sd=floor(rp.x());
px1=dy*(barwidth+1); // x position for this day
px2=px1+barwidth; // plus bar width
py1=height/24.0*start;
double h=height/24.0*(total);
QRect rect(start_px+px1,start_py+py1,barwidth,h);
glBegin(GL_QUADS);
glColor4ub(col1.red(),col1.green(),col1.blue(),col1.alpha());
glVertex2f(rect.x(), rect.y()+rect.height());
glVertex2f(rect.x(), rect.y());
glColor4ub(col2.red(),col2.green(),col2.blue(),col2.alpha());
glVertex2f(rect.x()+rect.width(),rect.y());
glVertex2f(rect.x()+rect.width(), rect.y()+rect.height());
glEnd();
glColor4ub(0,0,0,255);
glLineWidth (1);
glBegin(GL_LINE_LOOP);
glVertex2f(rect.x(), rect.y()+rect.height());
glVertex2f(rect.x(), rect.y());
glVertex2f(rect.x()+rect.width(),rect.y());
glVertex2f(rect.x()+rect.width(), rect.y()+rect.height());
glEnd();
}
glColor3f (0.0F, 0.0F, 0.0F);
glLineWidth(1);
glBegin (GL_LINES);
glVertex2f (start_px, start_py);
glVertex2f (start_px, start_py+height+1);
glVertex2f (start_px,start_py);
glVertex2f (start_px+width, start_py);
glEnd ();
Xaxis->Plot(w,scrx,scry);
}

32
Graphs/gSessionTime.h Normal file
View File

@ -0,0 +1,32 @@
/*
gSessionTime Header
Copyright (c)2011 Mark Watkins <jedimark@users.sourceforge.net>
License: GPL
*/
#ifndef GSESSIONTIME_H
#define GSESSIONTIME_H
#include "graphlayer.h"
#include "gXAxis.h"
class gSessionTime:public gLayer
{
public:
gSessionTime(gPointData *d=NULL,QColor col=QColor("blue"),Qt::Orientation o=Qt::Horizontal);
virtual ~gSessionTime();
virtual void Plot(gGraphWindow & w,float scrx,float scry);
protected:
Qt::Orientation m_orientation;
virtual const QString & FormatX(double v) { static QString t; QDateTime d; d=d.fromMSecsSinceEpoch(v*86400000.0); t=d.toString("dd MMM"); return t; };
//virtual const wxString & FormatX(double v) { static wxString t; wxDateTime d; d.Set(vi*86400000.0); t=d.Format(wxT("HH:mm")); return t; };
//virtual const wxString & FormatX(double v) { static wxString t; t=wxString::Format(wxT("%.1f"),v); return t; };
virtual const QString & FormatY(double v) { static QString t; t.sprintf("%.1f",v); return t; };
gXAxis *Xaxis;
};
#endif // GSESSIONTIME_H

View File

@ -81,9 +81,9 @@ inline void RDrawText(QPainter & painter, QString text, int x, int y, float ang
} else {
GetTextExtent(text, w, h, font);
painter.translate(floor(x),floor(y));
painter.rotate(-90);
painter.rotate(-angle);
painter.drawText(floor(-w/2.0),floor(-h/2.0),text);
painter.rotate(+90);
painter.rotate(+angle);
painter.translate(floor(-x),floor(-y));
}

View File

@ -300,13 +300,13 @@ void FlagData::Reload(Day *day)
int c=0;
vc=0;
double v1,v2;
bool first;
//bool first;
min_x=day->first()/86400000.0;
max_x=day->last()/86400000.0;
for (vector<Session *>::iterator s=day->begin();s!=day->end();s++) {
if ((*s)->events.find(code)==(*s)->events.end()) continue;
first=true;
//first=true;
for (vector<Event *>::iterator e=(*s)->events[code].begin(); e!=(*s)->events[code].end(); e++) {
Event & ev =(*(*e));
v2=v1=ev.time()/86400000.0;
@ -339,6 +339,116 @@ void FlagData::Reload(Day *day)
real_max_y=max_y;
m_ready=true;
}
////////////////////////////////////////////////////////////////////////////////////////////
// Session Times Implementation
////////////////////////////////////////////////////////////////////////////////////////////
SessionTimes::SessionTimes(Profile * _profile)
:gPointData(2048),profile(_profile)
{
AddSegment(max_points);
if (profile->LastDay().isValid()) {
QDateTime tmp;
tmp.setDate(profile->FirstDay());
real_min_x=tmp.toMSecsSinceEpoch()/86400000.0;
tmp.setDate(profile->LastDay());
real_max_x=(tmp.toMSecsSinceEpoch()/86400000.0)+1;
}
real_min_y=real_max_y=0;
}
SessionTimes::~SessionTimes()
{
}
void SessionTimes::ResetDateRange()
{
if (profile->LastDay().isValid()) {
QDateTime tmp;
tmp.setDate(profile->FirstDay());
real_min_x=tmp.toMSecsSinceEpoch()/86400000.0;
tmp.setDate(profile->LastDay());
real_max_x=(tmp.toMSecsSinceEpoch()/86400000.0)+1;
}
}
double SessionTimes::GetAverage()
{
double x,val=0;
int cnt=0;
for (int i=0;i<np[0];i++) {
x=point[0][i].x();
if ((x<min_x) || (x>max_x)) continue;
val+=point[0][i].y()-point[0][i].x();
cnt++;
}
if (!cnt) return 0;
val/=cnt;
return val;
}
void SessionTimes::SetDateRange(QDate start,QDate end)
{
qint64 x1=QDateTime(start).toMSecsSinceEpoch()/86400000.0;
qint64 x2=QDateTime(end.addDays(1)).toMSecsSinceEpoch()/86400000.0;
if (x1 < real_min_x) x1=real_min_x;
if (x2 > (real_max_x)) x2=(real_max_x);
min_x=x1;
max_x=x2;
for (list<gLayer *>::iterator i=notify_layers.begin();i!=notify_layers.end();i++) {
(*i)->DataChanged(this);
} // Do nothing else.. Callers responsibility to Refresh window.
}
void SessionTimes::Reload(Day *day)
{
day=day; //shuttup warnings.. we don't use this.
QDateTime date;
vc=0;
bool done=false;
double st,et;
min_y=max_y=0;
min_x=max_x=0;
if (real_min_x<0) return;
if (real_max_x<0) return;
int i=0;
for (double x=floor(real_min_x);x<=ceil(real_max_x);x++) {
date=QDateTime::fromMSecsSinceEpoch(x*86400000.0L); // Ouch.. QDateTime conversions are slow as hell..
// date.setTime(QTime(0,0,0));
//if (profile->daylist.find(date.date())==profile->daylist.end()) continue;
Day *dy=profile->GetDay(date.date(),MT_CPAP);
if (!dy) continue;
//vector<Day *> & daylist=profile->daylist[date.date()];
for (vector<Session *>::iterator dd=dy->begin(); dd!=dy->end(); dd++) { // average any multiple data sets
st=double((*dd)->first())/86400000.0;
et=double((*dd)->last())/86400000.0;
point[vc][i].setX(st);
point[vc][i].setY(et);
i++;
if (i>max_points) {
qWarning("max_points is not enough in HistoryData");
done=true;
break;
}
}
if (done)
break;
}
np[vc]=i;
vc++;
min_x=real_min_x;
max_x=real_max_x;
if (force_min_y!=force_max_y) {
min_y=force_min_y;
max_y=force_max_y;
} else {
min_y=-12;
max_y=+12;
}
real_min_y=min_y;
real_max_y=max_y;
m_ready=true;
}
////////////////////////////////////////////////////////////////////////////////////////////
// HistoryData Implementation
@ -389,7 +499,7 @@ void HistoryData::Reload(Day *day)
int i=0;
bool first=true;
bool done=false;
double y,lasty=0;
double y,lasty;
min_y=max_y=0;
min_x=max_x=0;
if (real_min_x<0) return;

View File

@ -70,14 +70,31 @@ public:
virtual void Reload(Day *day=NULL);
};
class SessionTimes:public gPointData
{
public:
SessionTimes(Profile * _profile);
virtual ~SessionTimes();
void SetProfile(Profile *_profile) { profile=_profile; Reload(); }
Profile * GetProfile() { return profile; }
double GetAverage(); // length??
virtual void Reload(Day *day=NULL);
virtual void ResetDateRange();
virtual void SetDateRange(QDate start,QDate end);
protected:
Profile * profile;
};
class HistoryData:public gPointData
{
public:
HistoryData(Profile * _profile);
virtual ~HistoryData();
void SetProfile(Profile *_profile) { profile=_profile; Reload(); };
Profile * GetProfile() { return profile; };
void SetProfile(Profile *_profile) { profile=_profile; Reload(); }
Profile * GetProfile() { return profile; }
double GetAverage();
virtual double Calc(Day *day);

View File

@ -59,7 +59,8 @@ SOURCES += main.cpp\
Graphs/gBarChart.cpp \
SleepLib/loader_plugins/resmed_loader.cpp \
Graphs/gpiechart.cpp \
SleepLib/loader_plugins/sleep_database.cpp
SleepLib/loader_plugins/sleep_database.cpp \
Graphs/gSessionTime.cpp
HEADERS += \
SleepLib/binary_file.h \
@ -96,7 +97,8 @@ HEADERS += \
Graphs/gBarChart.h \
SleepLib/loader_plugins/resmed_loader.h \
Graphs/gpiechart.h \
SleepLib/loader_plugins/sleep_database.h
SleepLib/loader_plugins/sleep_database.h \
Graphs/gSessionTime.h
FORMS += \
daily.ui \

View File

@ -14,6 +14,7 @@
#include "Graphs/gLineChart.h"
#include "Graphs/gYAxis.h"
#include "Graphs/gFooBar.h"
#include "Graphs/gSessionTime.h"
Overview::Overview(QWidget *parent,QGLContext *context) :
QWidget(parent),
@ -31,6 +32,8 @@ Overview::Overview(QWidget *parent,QGLContext *context) :
AddData(pressure_eap=new HistoryCodeData(profile,BIPAP_EAPAverage));
AddData(pressure_iap=new HistoryCodeData(profile,BIPAP_IAPAverage));
session_times=new SessionTimes(profile);
// pressure->ForceMinY(3);
// pressure->ForceMaxY(12);
AddData(leak=new HistoryCodeData(profile,CPAP_LeakMedian));
@ -86,24 +89,44 @@ Overview::Overview(QWidget *parent,QGLContext *context) :
//USAGE->AddLayer(new gLineChart(usage,QColor("green")));
USAGE->setMinimumHeight(170);
AddGraph(SESSTIMES=new gGraphWindow(ui->SummaryGraphWindow,tr("Session Times"),AHI));
//SESSTIMES->SetMargins(10,15,65,80);
SESSTIMES->AddLayer(new gFooBar(7));
SESSTIMES->AddLayer(new gYAxis());
SESSTIMES->AddLayer(new gSessionTime(session_times,QColor("green")));
SESSTIMES->SetBottomMargin(SESSTIMES->GetBottomMargin()+gXAxis::Margin+25);
//SESSTIMES->AddLayer(new gXAxis());
SESSTIMES->setMinimumHeight(270);
AHI->LinkZoom(PRESSURE);
AHI->LinkZoom(LEAK);
AHI->LinkZoom(USAGE);
AHI->LinkZoom(SESSTIMES);
PRESSURE->LinkZoom(AHI);
PRESSURE->LinkZoom(LEAK);
PRESSURE->LinkZoom(USAGE);
PRESSURE->LinkZoom(SESSTIMES);
LEAK->LinkZoom(AHI);
LEAK->LinkZoom(PRESSURE);
LEAK->LinkZoom(USAGE);
LEAK->LinkZoom(SESSTIMES);
USAGE->LinkZoom(AHI);
USAGE->LinkZoom(PRESSURE);
USAGE->LinkZoom(LEAK);
USAGE->LinkZoom(SESSTIMES);
SESSTIMES->LinkZoom(AHI);
SESSTIMES->LinkZoom(PRESSURE);
SESSTIMES->LinkZoom(LEAK);
SESSTIMES->LinkZoom(USAGE);
gSplitter->addWidget(SESSTIMES);
gSplitter->addWidget(AHI);
gSplitter->addWidget(PRESSURE);
gSplitter->addWidget(LEAK);
gSplitter->addWidget(USAGE);
dummyday=new Day(NULL);
ReloadGraphs();
@ -119,6 +142,7 @@ void Overview::RedrawGraphs()
for (list<gGraphWindow *>::iterator g=Graphs.begin();g!=Graphs.end();g++) {
(*g)->updateGL();
}
SESSTIMES->updateGL();
}
void Overview::ReloadGraphs()
{
@ -127,6 +151,9 @@ void Overview::ReloadGraphs()
(*h)->ResetDateRange();
(*h)->Reload(NULL);
}
session_times->SetProfile(profile);
session_times->ResetDateRange();
session_times->Reload(NULL);
on_rbLastWeek_clicked();
}
@ -138,6 +165,7 @@ void Overview::UpdateGraphs()
//(*h)->Update(dummyday);
(*h)->SetDateRange(first,last);
}
session_times->SetDateRange(first,last);
RedrawGraphs();
}

View File

@ -12,6 +12,7 @@
#include <QSplitter>
#include <SleepLib/profiles.h>
#include <Graphs/graphdata_custom.h>
namespace Ui {
class Overview;
}
@ -56,10 +57,10 @@ private:
HistoryData *ahidata,*pressure,*leak,*usage,*bedtime,*waketime,*pressure_iap,*pressure_eap;
HistoryData *pressure_min,*pressure_max;
SessionTimes *session_times;
gGraphWindow *AHI,*PRESSURE,*LEAK,*USAGE,*SESSTIMES;
gGraphWindow *AHI,*PRESSURE,*LEAK,*USAGE;
gLayer *prmax,*prmin,*iap,*eap,*pr;
gLayer *prmax,*prmin,*iap,*eap,*pr,*sesstime;
list<HistoryData *> Data;
list<gGraphWindow *> Graphs;