/*************************************************************************** * Copyright (C) 2006 by Andreas Krumnow * * andreas@krumnow.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ /* * version 0.6.27 */ /* * TODO: - freundlicheres Verhalten beim horizontalen skalieren: * Datenpufferung bis zur Desktop-Auflösung (bei 'setNextValue()') * Werte bei Zeitintervall-Änderung umtransformieren: (bei 'drawValue()') langsam -> schnell : box(origZeit,0,(value * currentInterval / origInterval),(origInterval/currentInterval)) schnell -> langsam : die nun zusammenfallenden Werte addieren. - Angleichen der Textpositionen in den Ecken DONE: */ #include <QtGui> #include "plotterfield.h" PlotterField::PlotterField(QWidget *parent) : QWidget(parent) { curVal = maxValueInField = minVal = 0; aspectRatio = 1; scaleRange = 10; paneH = 20; paneW = 40; max_s_col = 408; // = 17 * 8 * 3 valueListRx.append(0); valueListTx.append(0); needNewScaleFactor = true; cbxHLines = false; cbxVLines = false; lineCol = new QColor(0,255,0,255); plotCol1 = new QColor(255,0,0,255); plotCol2 = new QColor(255,128,128,255); bkCol = new QColor(200,200,250,255); unitsHorizontalLeft = ""; unitsHorizontalRight = ""; unitsVerticalBelow = ""; unitsVerticalAbove = ""; setPalette( QPalette(*bkCol)); setBackgroundRole( QPalette::Window); setAutoFillBackground(true); resize(200, 100); } PlotterField::~ PlotterField() { delete lineCol; delete bkCol; delete plotCol1; delete plotCol2; } void PlotterField::paintEvent(QPaintEvent *) { paneH = this->height(); paneW = this->width(); aspectRatio = (double)(paneH) / scaleFactor(maxValueInField); // retrieve the new scale-factor stift = new QPainter(this); drawValue(stift); if(cbxHLines) drawHline(stift); if(cbxVLines) drawVline(stift); delete stift; needNewScaleFactor = false; } void PlotterField::drawValue(QPainter *stift) { int y1, y2, x, u, e; double rx, tx; // retrieve the scale-factor (scaleRange) only when needed if(needNewScaleFactor) aspectRatio = (double)(paneH) / scaleFactor(maxValueInField); //set the Value-drawing-Factor // draw the values of the List (with scaling-factor) e = valueListRx.size(); // count of value-samples in List x = paneW - e; // aktual X-Position u = paneH; // Koordinaten Y Ursprung unten for(int i = 0; i < e; i++) // draw all the values { y1 = y2 = paneH; rx = valueListRx.at(i); tx = valueListTx.at(i); if(tx > 0) { y1 = paneH - (int(tx * aspectRatio)); // translate the origin value into pixels stift->setPen(*plotCol2); // set current plot-color stift->drawLine(x,u,x,y1); } if(rx > 0) { y2 = y1 - (int(rx * aspectRatio)); // translate the origin value into pixels stift->setPen(*plotCol1); // set current plot-color stift->drawLine(x,y1-1,x,y2-1); } x++; } } void PlotterField::drawHline(QPainter *stift) { int x1, x2, anz=10; double v, step, scaleRangeTeiler; QString suffix; x1 = 0; x2 = paneW; v = maxValueInField; suffix = ""; if(needNewScaleFactor) scaleRange = (int)(scaleFactor(maxValueInField)); // berechne schrittweite scaleRangeTeiler = (double)(scaleRange)/10; step = (double)(paneH)/10; if(step < 10) { anz = int(step); if(anz > 1) { step = (double)(paneH) / anz; scaleRangeTeiler = (double)(scaleRange/anz); } else { step = paneH; scaleRangeTeiler = (double)(scaleRange); } } // Groessenordnung if(scaleRangeTeiler > 1000) { scaleRangeTeiler = scaleRangeTeiler / 1000; suffix = " k"; if(scaleRangeTeiler > 1000000) { scaleRangeTeiler = scaleRangeTeiler / 1000000; suffix = " M"; } } if(scaleRange < 10) { scaleRangeTeiler = 1; anz = scaleRange; step = paneH; if(anz > 0) step = paneH / anz; } stift->setPen(*lineCol); // malen ... for(int y=1; y < anz; y++) { int h = (int)(paneH - ( step * y)); stift->drawLine( x1,h,x2,h); if(cbxHtxt) { stift->drawText(2,h+10,QString::number( (double)(scaleRangeTeiler * y ),'F',0) + suffix); } } if(cbxHtxt) { stift->drawText(2,9,QString::number( (double)(scaleRangeTeiler * anz ),'F',0) + suffix + " " + unitsHorizontalLeft); if(180 < height()) stift->drawText(2,paneH,"0/"); } } void PlotterField::drawVline(QPainter *stift) { stift->setPen(*lineCol); int y1, y2, yt, xx, genau=3; double step, timeMark; y1=0; y2=paneH, yt = paneH - 2; step = (double)(paneW)/10; if (step < 10) step=10; if(intervalTime > 10) genau = 2; if(intervalTime > 100) genau = 1; if(intervalTime > 200) ; if(intervalTime > 500) genau = 0; if(cbxVtxt) { stift->drawText((int)(paneW-(2*step/5)),yt," " + unitsVerticalBelow); if((intervalTime > 200) && (599 < width())) stift->drawText((int)(paneW-(2*step/5)),9, unitsVerticalAbove); } for (int i = 1; i < 10; i++) { xx = paneW - (int)(step * i); stift->drawLine( xx,y1,xx,y2); timeMark = ((double)(paneW - xx) * intervalTime / 1000); if(cbxVtxt) { stift->drawText(xx,yt,QString::number((double) timeMark, 'F',genau)); if(intervalTime > 200) { int m = (int)(timeMark / 60); int s = ((int)(timeMark) % 60); QString f = ":"; if(s < 10) f = ":0"; stift->drawText(xx,9,QString::number(m) + f + QString::number(s)); } } } if(cbxVtxt && (499 < width())) { timeMark = ((double)(paneW) * intervalTime / 1000); // (double) (paneW * intervalTime / 1000) stift->drawText((int)(2*step/5),yt,QString::number(timeMark, 'F',genau)); if((intervalTime > 200) && (20 < height())) { int m = (int)(timeMark / 60); int s = ((int)(timeMark) % 60); QString f = ":"; if(s < 10) f = ":0"; stift->drawText(paneW/20,20,QString::number(m) + f + QString::number(s)); } } } double PlotterField::scaleFactor(const double maxV) { if(!needNewScaleFactor) return scaleRange; double dv, zehntel; dv = maxV; // temp-var scaleRange = 1; while(dv > 1) { dv = dv / 10; scaleRange *= 10; } dv = maxV; zehntel = scaleRange / 10; int i = 0; while(dv > 0) { dv -= zehntel; i++; } scaleRange = (int)(i * zehntel); needNewScaleFactor = false; return scaleRange; } void PlotterField::setNextValue(const double rxVal, const double txVal) { curVal = rxVal + txVal; ixMaxVal--; if(curVal > maxValueInField) { maxValueInField = curVal; ixMaxVal = valueListRx.size(); needNewScaleFactor = true; aspectRatio = (double)(paneH) / scaleFactor(maxValueInField); //set the Value-drawing-Factor } // Let the List Size not be larger than the drawing-pane if(valueListRx.size() >= paneW) { valueListRx.removeFirst(); valueListTx.removeFirst(); } valueListRx.append(rxVal); // store the current value at end of List valueListTx.append(txVal); // store the current value at end of List // if biggest value went out of visible pane ... if((ixMaxVal <= 0) && (paneW <= valueListRx.size())) { // determine the biggest value left in list maxValueInField = ixMaxVal = 0; for(int i=0 ; i < valueListRx.size() ; ++i) { if(maxValueInField < (valueListRx.at(i) + valueListTx.at(i))) { maxValueInField = (valueListRx.at(i) + valueListTx.at(i)); ixMaxVal = i; } } needNewScaleFactor = true; aspectRatio = (double)(paneH) / scaleFactor(maxValueInField); //set the Value-drawing-Factor } update(); } void PlotterField::setPaneColor(QRgb rgb) { bkCol->setRgb(rgb); setPalette( QPalette(rgb)); update(); } void PlotterField::setPlotColor1( QRgb rgb ) { plotCol1->setRgb(rgb); plotCol1->setAlpha(255); update(); } void PlotterField::setPlotColor2( QRgb rgb ) { plotCol2->setRgb(rgb); plotCol2->setAlpha(255); update(); } void PlotterField::setLinesColor( QRgb rgb ) { lineCol->setRgb(rgb); lineCol->setAlpha(s_alpha); update(); } void PlotterField::setLinesAlpha(int a) { // security... if (a == s_alpha) return; if (a < 0) a = 0; if (a > 255) a = 255; s_alpha = a; lineCol->setAlpha(s_alpha); update(); } void PlotterField::onCbxHLines(const int b) { cbxHLines = bool(b); update(); } void PlotterField::onCbxHTxt(const int b) { cbxHtxt = bool(b); update(); } void PlotterField::onCbxVLines(const int b) { cbxVLines = bool(b); update(); } void PlotterField::onCbxVTxt(const int b) { cbxVtxt = bool(b); update(); } void PlotterField::setNewScaleFactor() { needNewScaleFactor = true; } void PlotterField::setIntervalTime(const int ms) { intervalTime = ms; } void PlotterField::setUnitsHorizontalLeft(const QString & s) { unitsHorizontalLeft = s; } void PlotterField::setUnitsHorizontalRight(const QString & s) { unitsHorizontalRight = s; } void PlotterField::setUnitsVerticalBelow(const QString & s) { unitsVerticalBelow = s; } void PlotterField::setUnitsVerticalAbove(const QString & s) { unitsVerticalAbove = s; }