/* gBarChart Implementation Copyright (c)2011 Mark Watkins License: GPL */ #include #include #include #include "gYAxis.h" #include "gSummaryChart.h" extern QLabel * qstatus2; SummaryChart::SummaryChart(Profile *p,QString label,GraphType type) :Layer(""),m_profile(p),m_label(label),m_graphtype(type) { QColor color=Qt::black; addGLBuf(quads=new GLShortBuffer(20000,GL_QUADS)); addGLBuf(lines=new GLShortBuffer(20000,GL_LINES)); quads->forceAntiAlias(true); lines->setSize(2); lines->forceAntiAlias(false); m_empty=true; hl_day=-1; } SummaryChart::~SummaryChart() { } void SummaryChart::SetDay(Day * nullday) { if (!m_profile) { qWarning() << "Forgot to set profile for gBarChart dummy!"; m_day=NULL; return; } Day * day=nullday; Layer::SetDay(day); m_values.clear(); m_days.clear(); m_miny=9999999; m_maxy=-9999999; m_minx=0; m_maxx=0; int dn; EventDataType tmp,total; ChannelID code; m_fday=0; qint64 tt; m_empty=true; int suboffset; SummaryType type; for (QMap >::iterator d=m_profile->daylist.begin();d!=m_profile->daylist.end();d++) { tt=QDateTime(d.key(),QTime(0,0,0),Qt::UTC).toTime_t(); //tt=QDateTime(d.key(),QTime(12,0,0)).toTime_t(); dn=tt/86400; tt*=1000L; if (!m_minx || ttm_maxx) m_maxx=tt; total=0; bool fnd=false; for (int j=0;jchannelExists(code) || day->settingExists(code)) { // too many lookups happening here.. stop the crap.. m_days[dn]=day; switch(m_type[j]) { case ST_AVG: tmp=day->avg(code); break; case ST_SUM: tmp=day->sum(code); break; case ST_WAVG: tmp=day->wavg(code); break; case ST_90P: tmp=day->p90(code); break; case ST_MIN: tmp=day->min(code); break; case ST_MAX: tmp=day->max(code); break; case ST_CNT: tmp=day->count(code); break; case ST_CPH: tmp=day->cph(code); break; case ST_SPH: tmp=day->sph(code); break; case ST_HOURS: tmp=day->hours(); break; case ST_SETMIN: tmp=day->settings_min(code); break; case ST_SETMAX: tmp=day->settings_max(code); break; case ST_SETAVG: tmp=day->settings_avg(code); break; case ST_SETWAVG: tmp=day->settings_wavg(code); break; case ST_SETSUM: tmp=day->settings_sum(code); break; default: break; } if (suboffset>0) { tmp-=suboffset; if (tmp<0) tmp=0; } //if (tmp>0) { fnd=true; total+=tmp; m_values[dn][j+1]=tmp; if (tmpm_maxy) m_maxy=tmp; break; // } } } } if (fnd) { if (!m_fday) m_fday=dn; m_values[dn][0]=total; if (m_graphtype==GT_BAR) { if (totalm_maxy) m_maxy=total; } m_empty=false; } } if (m_graphtype==GT_BAR) { m_miny=0; } // m_minx=qint64(QDateTime(m_profile->FirstDay(),QTime(0,0,0),Qt::UTC).toTime_t())*1000L; m_maxx=qint64(QDateTime(m_profile->LastDay().addDays(1),QTime(0,0,0),Qt::UTC).toTime_t())*1000L; } QColor brighten(QColor color) { int cr,cg,cb; cr=color.red(); cg=color.green(); cb=color.blue(); if (cr<64) cr=64; if (cg<64) cg=64; if (cb<64) cb=64; cr*=2; cg*=2; cb*=2; if (cr>255) cr=255; if (cg>255) cg=255; if (cb>255) cb=255; return QColor(cr,cg,cb,255); } void SummaryChart::paint(gGraph & w,int left, int top, int width, int height) { if (!m_visible) return; rtop=top; GLShortBuffer *outlines=w.lines(); QColor blk=Qt::black; outlines->add(left, top, left, top+height, blk); outlines->add(left, top+height, left+width,top+height, blk); outlines->add(left+width,top+height, left+width, top, blk); outlines->add(left+width, top, left, top, blk); qint64 minx=w.min_x, maxx=w.max_x; //qint64 minx=m_minx, maxx=m_maxx; qint64 xx=maxx - minx; float days=double(xx)/86400000.0; EventDataType maxy=m_maxy; EventDataType miny=m_miny; w.roundY(miny,maxy); EventDataType yy=maxy-miny; EventDataType ymult=float(height-2)/yy; barw=(float(width)/float(days)); qint64 ts; graph=&w; float px=left; l_left=w.m_marginleft+gYAxis::Margin; l_top=w.m_margintop; l_width=width; l_height=height; float py; EventDataType total; int daynum=0; EventDataType h,tmp; l_offset=(minx) % 86400000L; offset=float(l_offset)/86400000.0; offset*=barw; px=left-offset; l_minx=minx; l_maxx=maxx+86400000L; //QHash lastvalues; int total_days=0; double total_val=0; qint64 lastQ=0; bool lastdaygood=false; QVector totalcounts; QVector totalvalues; //QVector lastvalues; QVector lastX; QVector lastY; int numcodes=m_codes.size(); totalcounts.resize(numcodes); totalvalues.resize(numcodes); //lastvalues.resize(numcodes); lastX.resize(numcodes); lastY.resize(numcodes); int zd=minx/86400000L; zd--; QHash >::iterator d=m_values.find(zd); // if (d==m_values.end()) { // d=m_values.find(zd--); // } lastdaygood=true; for (int i=0;ileft+width) x2=left+width; if (x20) { if (day) { total_val+=total; total_days++; } //} py=top+height; for (QHash::iterator g=d.value().begin();g!=d.value().end();g++) { short j=g.key(); if (!j) continue; j--; QColor col=m_colors[j]; if (zd==hl_day) { col=QColor("gold"); } tmp=g.value(); //if (!tmp) continue; if (m_type[j]==ST_MAX) { if (tmp>totalvalues[j]) totalvalues[j]=tmp; } else if (m_type[j]==ST_MIN) { if (tmpadd(x1,py,x1,py-h,col); quads->add(x2,py-h,x2,py,col2); if (barw>2) { outlines->add(x1,py,x1,py-h,blk); outlines->add(x1,py-h,x2,py-h,blk); outlines->add(x1,py,x2,py,blk); outlines->add(x2,py,x2,py-h,blk); } // if (bar py-=h; } else if (m_graphtype==GT_LINE) { // if (m_graphtype==GT_BAR col.setAlpha(128); short px2=px+barw; short py2=top+height-1-h; py2+=j; if (lastdaygood) { lines->add(lastX[j],lastY[j],px,py2,m_colors[j]); lines->add(px,py2,px2,py2,col); } else { lines->add(x1,py2,x2,py2,col); } lastX[j]=px2; lastY[j]=py2; //} } } // for(QHashmaxx+extra) break; } else lastdaygood=false; px+=barw; daynum++; lastQ=Q; } lines->scissor(left,w.flipY(top+height+2),width+1,height+1); // Draw Ledgend px=left+width-3; py=top+10; QString a; int x,y; for (int j=0;jadd(px+5,py-3,px+18,py-3,px+18,py+4,px+5,py+4,m_colors[j]); //lines->add(px,py,px+20,py,m_colors[j]); //lines->add(px,py+1,px+20,py+1,m_colors[j]); } if (m_graphtype==GT_BAR) { if (m_type.size()>1) { float val=total_val/float(total_days); a=m_label+"="+QString::number(val,'f',2)+" "; GetTextExtent(a,x,y); px-=20+x; w.renderText(a,px+24,py+5); // } } a=""; /*if (m_graphtype==GT_BAR) { if (m_type.size()>1) { float val=total_val/float(total_days); a+=m_label+"="+QString::number(val,'f',2)+" "; // } }*/ a+="Days="+QString::number(totalcounts[0],'f',0); GetTextExtent(a,x,y); px-=30+x; //w.renderText(a,px+24,py+5); w.renderText(a,left,top-3); } bool SummaryChart::mouseMoveEvent(QMouseEvent *event) { int x=event->x()-l_left; int y=event->y()-l_top; if ((x<0 || y<0 || x>l_width || y>l_height)) { hl_day=-1; //graph->timedRedraw(2000); return false; } double xx=l_maxx-l_minx; double xmult=xx/double(l_width+barw); qint64 mx=ceil(xmult*double(x-offset)); mx+=l_minx; mx=mx+l_offset;//-86400000L; int zd=mx/86400000L; Day * day; //if (hl_day!=zd) // This line is an optimization { hl_day=zd; QHash >::iterator d=m_values.find(hl_day); x+=gYAxis::Margin+gGraphView::titleWidth; //graph->m_marginleft+ int y=event->y()+rtop-15; QDateTime dt1=QDateTime::fromTime_t(hl_day*86400).toLocalTime(); QDateTime dt2=QDateTime::fromTime_t(hl_day*86400).toUTC(); QTime t1=dt1.time(); QTime t2=dt2.time(); QDate dt=dt2.date(); if (d!=m_values.end()) { day=m_days[zd]; QString z=dt.toString(Qt::SystemLocaleShortDate); // Day * day=m_days[hl_day]; //EventDataType val; QString val; if (m_graphtype==GT_BAR) { if (m_type[0]==ST_HOURS) { int t=d.value()[0]*3600.0; int h=t/3600; int m=(t / 60) % 60; int s=t % 60; val.sprintf("%02i:%02i",h,m); } else val=QString::number(d.value()[0],'f',2); z+="\r\n"+m_label+"="+val; //z+="\r\nMode="+QString::number(day->settings_min("FlexSet"),'f',0); } else { QString a; for (int i=0;ichannelExists(m_codes[i]) || day->settingExists(m_codes[i]))) { schema::Channel & chan=schema::channel[m_codes[i]]; val=QString::number(d.value()[i+1],'f',2); z+="\r\n"+chan.label()+" "+a+"="+val; } } } graph->ToolTip(z,x,y,2200); return true; } else { QString z=dt.toString(Qt::SystemLocaleShortDate)+"\r\nNo Data"; graph->ToolTip(z,x,y,2200); } } return false; } bool SummaryChart::mousePressEvent(QMouseEvent * event) { return false; } bool SummaryChart::mouseReleaseEvent(QMouseEvent * event) { hl_day=-1; graph->timedRedraw(2000); return false; }