182void SignalPlotter::addSample(
const QList<double>& sampleBuf)
184 if (d->samples < 4) {
187 kDebug() <<
"Error - d->samples is only " << d->samples;
189 kDebug() <<
"d->samples is now " << d->samples;
190 if (d->samples < 4) {
194 d->plotData.prepend(sampleBuf);
195 Q_ASSERT(sampleBuf.count() == d->plotColors.count());
196 if ((uint)d->plotData.size() > d->samples) {
197 d->plotData.removeLast();
198 if ((uint)d->plotData.size() > d->samples) {
201 d->plotData.removeLast();
205 if (d->bezierCurveOffset >= 2) {
206 d->bezierCurveOffset = 0;
208 d->bezierCurveOffset++;
211 Q_ASSERT((uint)d->plotData.size() >= d->bezierCurveOffset);
215 if (d->verticalLinesScroll) {
216 d->verticalLinesOffset =
217 (d->verticalLinesOffset + d->horizontalScale) % d->verticalLinesDistance;
606void SignalPlotter::drawWidget(QPainter *p, uint w, uint height,
int horizontalScale)
611 uint fontheight = p->fontMetrics().height();
612 if (d->verticalMin < d->niceVertMin ||
613 d->verticalMax > d->niceVertMax ||
614 d->verticalMax < (d->niceVertRange * 0.75 + d->niceVertMin) ||
615 d->niceVertRange == 0) {
620 pen.setCapStyle(Qt::RoundCap);
623 uint top = p->pen().width() / 2;
629 bool showTopBar = d->showTopBar && h > (fontheight +5);
634 if (d->backgroundPixmap.isNull() ||
635 (uint)d->backgroundPixmap.size().height() != height ||
636 (uint)d->backgroundPixmap.size().width() != w) {
638 d->backgroundPixmap = QPixmap(w, height);
639 d->backgroundPixmap.fill(Qt::transparent);
640 QPainter pCache(&d->backgroundPixmap);
641 pCache.setRenderHint(QPainter::Antialiasing,
false);
642 pCache.setFont(d->font);
646 if (d->showThinFrame) {
651 pCache.setClipRect(0, 0, w, height-1);
655 int separatorX = w / 2;
661 if (!d->verticalLinesScroll && d->showVerticalLines && w > 60) {
665 if (d->showHorizontalLines) {
670 if (d->showThinFrame) {
676 p->drawPixmap(0, 0, d->backgroundPixmap);
677 p->setRenderHint(QPainter::Antialiasing,
true);
680 int separatorX = w / 2;
681 int topBarWidth = w - separatorX -2;
685 p->setClipRect(0, top, w, h, Qt::IntersectClip);
687 if (d->verticalLinesScroll && d->showVerticalLines && w > 60) {
693 if (d->showLabels && w > 60 && h > (fontheight + 1)) {
718void SignalPlotter::calculateNiceRange()
720 d->niceVertRange = d->verticalMax - d->verticalMin;
723 if (d->niceVertRange < 0.000001) {
724 d->niceVertRange = 1.0;
727 d->niceVertMin = d->verticalMin;
728 if (d->verticalMin != 0.0) {
729 double dim = pow(10, floor(log10(fabs(d->verticalMin)))) / 2;
730 if (d->verticalMin < 0.0) {
731 d->niceVertMin = dim * floor(d->verticalMin / dim);
733 d->niceVertMin = dim * ceil(d->verticalMin / dim);
735 d->niceVertRange = d->verticalMax - d->niceVertMin;
736 if (d->niceVertRange < 0.000001) {
737 d->niceVertRange = 1.0;
741 double step = d->niceVertRange / (d->scaledBy * (d->horizontalLinesCount + 1));
742 int logdim = (int)floor(log10(step));
743 double dim = pow((
double)10.0, logdim) / 2;
744 int a = (int)ceil(step / dim);
747 }
else if (a % 2 == 0) {
748 d->precision = -logdim;
750 d->precision = 1 - logdim;
752 d->niceVertRange = d->scaledBy * dim * a * (d->horizontalLinesCount + 1);
753 d->niceVertMax = d->niceVertMin + d->niceVertRange;
768void SignalPlotter::drawTopBarContents(QPainter *p,
int x,
int width,
int height)
772 double bias = -d->niceVertMin;
773 double scaleFac = width / d->niceVertRange;
776 if (!d->plotData.isEmpty()) {
777 QList<double> newestData = d->plotData.first();
778 for (
int i = newestData.count()-1; i >= 0; --i) {
779 double newest_datapoint = newestData.at(i);
780 int start = x + (int)(bias * scaleFac);
781 int end = x + (int)((bias += newest_datapoint) * scaleFac);
782 int start2 = qMin(start, end);
783 end = qMax(start, end);
790 p->setPen(Qt::NoPen);
791 QLinearGradient linearGrad(QPointF(start, 1), QPointF(end, 1));
792 linearGrad.setColorAt(0, d->plotColors[i].darkColor);
793 linearGrad.setColorAt(1, d->plotColors[i].color);
794 p->fillRect(start, 1, end - start, height-1, QBrush(linearGrad));
807void SignalPlotter::drawPlots(QPainter *p,
int top,
int w,
int h,
int horizontalScale)
809 Q_ASSERT(d->niceVertRange != 0);
811 if (d->niceVertRange == 0) {
812 d->niceVertRange = 1;
814 double scaleFac = (h - 1) / d->niceVertRange;
817 QList< QList<double> >::Iterator it = d->plotData.begin();
819 p->setPen(Qt::NoPen);
832 if (d->useAutoRange) {
833 d->verticalMin = d->verticalMax = 0.0;
848 for (uint i = 0; it != d->plotData.end() && i < d->samples; ++i) {
851 pen.setCapStyle(Qt::FlatCap);
857 QList<double> datapoints = *it;
858 QList<double> prev_datapoints = datapoints;
859 QList<double> prev_prev_datapoints = datapoints;
860 QList<double> prev_prev_prev_datapoints = datapoints;
862 if (i == 0 && d->bezierCurveOffset > 0) {
866 if (d->bezierCurveOffset == 1) {
867 prev_datapoints = *it;
869 if (it != d->plotData.end()) {
870 prev_prev_prev_datapoints = prev_prev_datapoints = *it;
872 prev_prev_prev_datapoints = prev_prev_datapoints = prev_datapoints;
876 prev_datapoints = *it;
877 Q_ASSERT(it != d->plotData.end());
879 prev_prev_datapoints = *it;
880 Q_ASSERT(it != d->plotData.end());
882 if (it != d->plotData.end()) {
883 prev_prev_prev_datapoints = *it;
885 prev_prev_prev_datapoints = prev_prev_datapoints;
892 if (it != d->plotData.end()) {
893 prev_datapoints = *it;
895 if (it != d->plotData.end()) {
896 prev_prev_datapoints = *it;
898 if (it != d->plotData.end()) {
900 prev_prev_prev_datapoints = *it;
904 prev_prev_prev_datapoints = prev_prev_datapoints;
907 prev_prev_prev_datapoints = prev_prev_datapoints = prev_datapoints;
910 prev_prev_prev_datapoints = prev_prev_datapoints = prev_datapoints = datapoints;
918 float y0 = h - 1 + top;
926 for (
int j = qMin(datapoints.size(), d->plotColors.size()) - 1; j >=0; --j) {
927 if (d->useAutoRange) {
930 double current_maxvalue =
932 qMax(prev_datapoints[j],
933 qMax(prev_prev_datapoints[j],
934 prev_prev_prev_datapoints[j])));
935 double current_minvalue =
936 qMin<double>(datapoints[j],
937 qMin(prev_datapoints[j],
938 qMin(prev_prev_datapoints[j],
939 prev_prev_prev_datapoints[j])));
940 d->verticalMax = qMax(d->verticalMax, current_maxvalue);
941 d->verticalMin = qMin(d->verticalMin, current_maxvalue);
943 max_y += current_maxvalue;
944 min_y += current_minvalue;
949 if (j < prev_prev_prev_datapoints.count() &&
950 j < prev_prev_datapoints.count() &&
951 j < prev_datapoints.count()) {
959 delta_y0 = (datapoints[j] - d->niceVertMin) * scaleFac;
962 delta_y1 = (prev_datapoints[j] - d->niceVertMin) * scaleFac;
965 delta_y2 = (prev_prev_datapoints[j] - d->niceVertMin) * scaleFac;
968 delta_y3 = (prev_prev_prev_datapoints[j] - d->niceVertMin) * scaleFac;
971 if (d->stackPlots && offset) {
987 path.moveTo(x0, y0 - delta_y0);
988 path.cubicTo(x1, y1 - delta_y1, x2, y2 - delta_y2, x3, y3 - delta_y3);
991 QPainterPath path2(path);
992 QLinearGradient myGradient(0,(h - 1 + top), 0, (h - 1 + top) / 5);
993 Q_ASSERT(d->plotColors.size() >= j);
994 QColor c0(d->plotColors[j].darkColor);
995 QColor c1(d->plotColors[j].color);
998 myGradient.setColorAt(0, c0);
999 myGradient.setColorAt(1, c1);
1001 path2.lineTo(x3, y3 - offset);
1002 if (d->stackPlots) {
1005 path2.cubicTo(x2, y2 - offset, x1, y1 - offset, x0, y0 - offset);
1007 path2.lineTo(x0, y0 - 1);
1009 p->setBrush(myGradient);
1010 p->setPen(Qt::NoPen);
1013 p->setBrush(Qt::NoBrush);
1014 Q_ASSERT(d->plotColors.size() >= j);
1015 pen.setColor(d->plotColors[j].color);
1019 if (d->stackPlots) {
1030 if (d->useAutoRange && d->stackPlots) {
1031 d->verticalMax = qMax(max_y, d->verticalMax);
1032 d->verticalMin = qMin(min_y, d->verticalMin);
1038void SignalPlotter::drawAxisText(QPainter *p,
int top,
int h)
1048 p->setPen(d->fontColor);
1049 double stepsize = d->niceVertRange / (d->scaledBy * (d->horizontalLinesCount + 1));
1051 (int)ceil((d->horizontalLinesCount+1) *
1052 (p->fontMetrics().height() + p->fontMetrics().leading() / 2.0) / h);
1056 for (
int y = d->horizontalLinesCount + 1; y >= 1; y-= step) {
1058 top + (y * (h - 1)) / (d->horizontalLinesCount + 1);
1059 if (y_coord - p->fontMetrics().ascent() < top) {
1065 if ((uint)y == d->horizontalLinesCount + 1) {
1066 value = d->niceVertMin;
1068 value = d->niceVertMax / d->scaledBy - y * stepsize;
1071 QString number = KGlobal::locale()->formatNumber(value, d->precision);
1072 val = QString(
"%1 %2").arg(number, d->unit);
1073 p->drawText(6, y_coord - 3, val);