diff --git a/signalplotter/ksignalplotter.cpp b/signalplotter/ksignalplotter.cpp --- a/signalplotter/ksignalplotter.cpp +++ b/signalplotter/ksignalplotter.cpp @@ -6,7 +6,7 @@ published by the Free Software Foundation; either version 2 of the License or (at your option) version 3 or any later version accepted by the membership of KDE e.V. (or its successor approved - by the membership of KDE e.V.), which shall act as a proxy + by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of version 3 of the license. This program is distributed in the hope that it will be useful, @@ -32,6 +32,7 @@ #include "ksignalplotter_p.h" #include "ksignalplotter_debug.h" +#include #include #include #include @@ -388,12 +389,12 @@ #ifdef GRAPHICS_SIGNAL_PLOTTER void KGraphicsSignalPlotter::resizeEvent( QGraphicsSceneResizeEvent* event ) { - QRect boundingBox(QPoint(0,0), event->newSize().toSize()); + QRectF boundingBox(QPointF(0,0), event->newSize().toSize()); int fontHeight = QFontMetrics(font()).height(); #else void KSignalPlotter::resizeEvent( QResizeEvent* event ) { - QRect boundingBox(QPoint(0,0), event->size()); + QRectF boundingBox(QPointF(0,0), event->size()); int fontHeight = fontMetrics().height(); #endif if( d->mShowAxis && d->mAxisTextWidth != 0 && boundingBox.width() > (d->mAxisTextWidth*1.10+2) && boundingBox.height() > fontHeight ) { //if there's room to draw the labels, then draw them! @@ -435,7 +436,7 @@ #ifdef USE_SEPERATE_WIDGET d->mGraphWidget->setVisible(true); - d->mGraphWidget->setGeometry(boundingBox); + d->mGraphWidget->setGeometry(boundingBox.toRect()); #endif d->updateDataBuffers(); @@ -632,7 +633,7 @@ int fontheight = fontMetrics().height(); #endif if( d->mPlottingArea.height() > fontheight ) { //if there's room to draw the labels, then draw them! - d->drawAxisText(painter, QRect(0,0,w,h)); + d->drawAxisText(painter, QRectF(0,0,w,h)); } } } @@ -649,18 +650,18 @@ return; QPainter p(this); - signalPlotterPrivate->drawWidget(&p, QRect(0,0,w,h)); + signalPlotterPrivate->drawWidget(&p, QRectF(0,0,w,h)); if(signalPlotterPrivate->mAxisTextOverlapsPlotter && signalPlotterPrivate->mShowAxis) { uint fontheight = signalPlotterPrivate->q->fontMetrics().height(); if( h > fontheight ) { //if there's room to draw the labels, then draw them! QSize originalSize = signalPlotterPrivate->q->size(); - signalPlotterPrivate->drawAxisText(&p, QRect(-signalPlotterPrivate->mPlottingArea.topLeft(), originalSize)); + signalPlotterPrivate->drawAxisText(&p, QRectF(-signalPlotterPrivate->mPlottingArea.topLeft(), originalSize)); } } } #endif -void KSignalPlotterPrivate::drawWidget(QPainter *p, const QRect &boundingBox) +void KSignalPlotterPrivate::drawWidget(QPainter *p, const QRectF &boundingBox) { #ifdef SVG_SUPPORT if(!mSvgFilename.isEmpty()) { @@ -676,26 +677,31 @@ //We draw the pixmap in two halves, wrapping around the window if(mScrollOffset > 1) { + QPointF o(boundingBox.right() - mScrollOffset+2, boundingBox.top()); + QRectF rect(0, 0, mScrollOffset-1, boundingBox.height()); #ifdef USE_QIMAGE - p->drawImage(boundingBox.right() - mScrollOffset+2, boundingBox.top(), mScrollableImage, 0, 0, mScrollOffset-1, boundingBox.height()); + p->drawImage(o, mScrollableImage, rect); #else - p->drawPixmap(boundingBox.right() - mScrollOffset+2, boundingBox.top(), mScrollableImage, 0, 0, mScrollOffset-1, boundingBox.height()); + p->drawPixmap(o, mScrollableImage, rect); #endif } - int widthOfSecondHalf = boundingBox.width() - mScrollOffset + 1; + qreal widthOfSecondHalf = boundingBox.width() - mScrollOffset + 1; if(widthOfSecondHalf > 0) { + const qreal dpr = qApp->devicePixelRatio(); + QPointF o = boundingBox.topLeft(); + QRectF rect(mScrollableImage.width() / dpr - widthOfSecondHalf-1, 0, widthOfSecondHalf, boundingBox.height()); #ifdef USE_QIMAGE - p->drawImage(boundingBox.left(), boundingBox.top(), mScrollableImage, mScrollableImage.width() - widthOfSecondHalf-1, 0, widthOfSecondHalf, boundingBox.height()); + p->drawImage(o, mScrollableImage, rect); #else - p->drawPixmap(boundingBox.left(), boundingBox.top(), mScrollableImage, mScrollableImage.width() - widthOfSecondHalf-1, 0, widthOfSecondHalf, boundingBox.height()); + p->drawPixmap(o, mScrollableImage, rect); #endif } /* Draw scope-like grid vertical lines if it doesn't move. If it does move, draw it in the dynamic part of the code*/ if(mShowVerticalLines && !mVerticalLinesScroll) drawVerticalLines(p, boundingBox); } -void KSignalPlotterPrivate::drawBackground(QPainter *p, const QRect &boundingBox) const +void KSignalPlotterPrivate::drawBackground(QPainter *p, const QRectF &boundingBox) const { p->setRenderHint(QPainter::Antialiasing, false); #ifdef SVG_SUPPORT @@ -728,39 +734,42 @@ } #ifdef SVG_SUPPORT -void KSignalPlotterPrivate::updateSvgBackground(const QRect &boundingBox) +void KSignalPlotterPrivate::updateSvgBackground(const QRectF &boundingBox) { + const qreal dpr = qApp->devicePixelRatio(); Q_ASSERT(!mSvgFilename.isEmpty()); Q_ASSERT(boundingBox.isNull()); - mBackgroundImage = QPixmap(boundingBox.width(), boundingBox.height()); + mBackgroundImage = QPixmap(boundingBox.width() * dpr, boundingBox.height() * dpr); + mBackgroundImage.setDevicePixelRatio(dpr); Q_ASSERT(!mBackgroundImage.isNull()); QPainter pCache(&mBackgroundImage); pCache.fill( q->palette().color(QPalette::Base) ); svgRenderer->resize(boundingBox.size()); svgRenderer->paint(&pCache, 0, 0); - } #endif void KSignalPlotterPrivate::redrawScrollableImage() { + qreal dpr = qApp->devicePixelRatio(); //Align width of bounding box to the size of the horizontal scale - int alignedWidth = ((mPlottingArea.width() + 1) / mHorizontalScale + 1) * mHorizontalScale; + qreal alignedWidth = ((mPlottingArea.width() + 1) / mHorizontalScale + 1) * mHorizontalScale; //Redraw the whole thing #ifdef USE_QIMAGE - mScrollableImage = QImage(alignedWidth, mPlottingArea.height(),QImage::Format_ARGB32_Premultiplied); + mScrollableImage = QImage(alignedWidth * dpr, mPlottingArea.height() * dpr, QImage::Format_ARGB32_Premultiplied); #else - mScrollableImage = QPixmap(alignedWidth, mPlottingArea.height()); + mScrollableImage = QPixmap(alignedWidth * dpr, mPlottingArea.height() * dpr); #endif + mScrollableImage.setDevicePixelRatio(dpr); Q_ASSERT(!mScrollableImage.isNull()); mScrollOffset = 0; mVerticalLinesOffset = mVerticalLinesDistance - mHorizontalScale+1; // mVerticalLinesDistance - alignedWidth % mVerticalLinesDistance; //We need to draw the background for areas without a beam - int withoutBeamWidth = qMax(mBeamData.size()-1, 0) * mHorizontalScale; + qreal withoutBeamWidth = qMax(mBeamData.size()-1, 0) * mHorizontalScale; QPainter pCache(&mScrollableImage); - if(withoutBeamWidth < mScrollableImage.width()) - drawBackground(&pCache, QRect(withoutBeamWidth, 0, alignedWidth - withoutBeamWidth, mScrollableImage.height())); + if(withoutBeamWidth < mScrollableImage.width() / dpr) + drawBackground(&pCache, QRectF(withoutBeamWidth * dpr, 0, (alignedWidth - withoutBeamWidth) * dpr, mScrollableImage.height())); /* Draw scope-like grid vertical lines */ mVerticalLinesOffset = 0; @@ -770,12 +779,12 @@ } } -void KSignalPlotterPrivate::drawThinFrame(QPainter *p, const QRect &boundingBox) +void KSignalPlotterPrivate::drawThinFrame(QPainter *p, const QRectF &boundingBox) { /* Draw a line along the bottom and the right side of the * widget to create a 3D like look. */ p->setRenderHint(QPainter::Antialiasing, false); - p->setPen( QPen(q->palette().color( QPalette::Light ), 0) ); + p->setPen( QPen(q->palette().color( QPalette::Light ), qreal(1)) ); p->drawLine( boundingBox.bottomLeft(), boundingBox.bottomRight()); p->drawLine( boundingBox.bottomRight(), boundingBox.topRight()); p->setRenderHint(QPainter::Antialiasing, true); @@ -850,22 +859,22 @@ q->update(); } -void KSignalPlotterPrivate::drawVerticalLines(QPainter *p, const QRect &boundingBox, int offset) const +void KSignalPlotterPrivate::drawVerticalLines(QPainter *p, const QRectF &boundingBox, int offset) const { QColor color = q->palette().color(QPalette::Window); if(!mVerticalLinesScroll) color.setAlpha(127); - p->setPen( QPen(color, 0) ); + p->setPen( QPen(color, qreal(1)) ); p->setRenderHint(QPainter::Antialiasing, false); - for ( int x = boundingBox.right() - ( offset % mVerticalLinesDistance); x >= boundingBox.left(); x -= mVerticalLinesDistance ) - p->drawLine( x, boundingBox.top(), x, boundingBox.bottom() ); + for ( qreal x = boundingBox.right() - ( offset % mVerticalLinesDistance); x >= boundingBox.left(); x -= mVerticalLinesDistance ) + p->drawLine( QPointF(x, boundingBox.top()), QPointF(x, boundingBox.bottom()) ); p->setRenderHint(QPainter::Antialiasing, true); } void KSignalPlotterPrivate::drawBeamToScrollableImage(QPainter *p, int index) { - QRect cacheBoundingBox = QRect(mScrollOffset, 0, mHorizontalScale, mScrollableImage.height()); + QRectF cacheBoundingBox = QRectF(mScrollOffset, 0, mHorizontalScale, mScrollableImage.height()); drawBackground(p, cacheBoundingBox); drawBeam(p, cacheBoundingBox, mHorizontalScale, index); @@ -878,14 +887,14 @@ } } -void KSignalPlotterPrivate::drawBeam(QPainter *p, const QRect &boundingBox, int horizontalScale, int index) +void KSignalPlotterPrivate::drawBeam(QPainter *p, const QRectF &boundingBox, int horizontalScale, int index) { if(mNiceRange == 0) return; QPen pen; if(mHorizontalScale == 1) //Don't use a pen width of 2 if there's only 1 pixel between points - pen.setWidth(1); + pen.setWidth(qreal(1)); else - pen.setWidth(2); + pen.setWidth(qreal(2)); pen.setCapStyle(Qt::FlatCap); @@ -899,7 +908,7 @@ const QList &prev_prev_datapoints = hasPrevPrevDatapoints?mBeamData[index+2]:prev_datapoints; qreal x0 = boundingBox.right(); - qreal x1 = qMax(boundingBox.right() - horizontalScale, 0); + qreal x1 = qMax(boundingBox.right() - horizontalScale, qreal(0)); qreal xaxis = boundingBox.bottom(); if( mNiceMinValue < 0) @@ -983,15 +992,15 @@ p->strokePath(paths.at(j),pen); } } -void KSignalPlotterPrivate::drawAxisText(QPainter *p, const QRect &boundingBox) +void KSignalPlotterPrivate::drawAxisText(QPainter *p, const QRectF &boundingBox) { if(mHorizontalLinesCount < 0) return; p->setFont( q->font() ); qreal stepsize = mNiceRange/(mScaleDownBy*(mHorizontalLinesCount+1)); if(mActualAxisTextWidth == 0) //If we are drawing completely inside the plotter area, using the Text color - p->setPen( QPen( q->palette().brush(QPalette::Text), 0) ); + p->setPen( QPen( q->palette().brush(QPalette::Text), qreal(1)) ); else - p->setPen( QPen( q->palette().brush(QPalette::WindowText), 0) ); + p->setPen( QPen( q->palette().brush(QPalette::WindowText), qreal(1)) ); int axisTitleIndex=1; QString val; int numItems = mHorizontalLinesCount +2; @@ -1008,26 +1017,26 @@ value = mNiceMaxValue/mScaleDownBy - y * stepsize; val = scaledValueAsString(value, mPrecision); - QRect textBoundingRect = p->fontMetrics().boundingRect(val); + QRectF textBoundingRect = p->fontMetrics().boundingRect(val); if(textBoundingRect.width() > mActualAxisTextWidth) mAxisTextOverlapsPlotter = true; int offset = qMax(mActualAxisTextWidth - textBoundingRect.right(), -textBoundingRect.left()); if ( q->layoutDirection() == Qt::RightToLeft ) - p->drawText( boundingBox.left(), y_coord, boundingBox.width() - offset , fontHeight+1, Qt::AlignLeft | Qt::AlignTop, val); + p->drawText( QRectF(boundingBox.left(), y_coord, boundingBox.width() - offset , fontHeight+1), Qt::AlignLeft | Qt::AlignTop, val); else - p->drawText( boundingBox.left() + offset, y_coord, boundingBox.width() - offset, fontHeight+1, Qt::AlignLeft | Qt::AlignTop, val); + p->drawText( QRectF(boundingBox.left() + offset, y_coord, boundingBox.width() - offset, fontHeight+1), Qt::AlignLeft | Qt::AlignTop, val); } } -void KSignalPlotterPrivate::drawHorizontalLines(QPainter *p, const QRect &boundingBox) const +void KSignalPlotterPrivate::drawHorizontalLines(QPainter *p, const QRectF &boundingBox) const { if(mHorizontalLinesCount <= 0) return; - p->setPen( QPen(q->palette().color(QPalette::Window) )); + p->setPen( QPen(q->palette().color(QPalette::Window), qreal(1) )); for ( int y = 0; y <= mHorizontalLinesCount+1; y++ ) { //note that the y_coord starts from 0. so we draw from pixel number 0 to h-1. Thus the -1 in the y_coord int y_coord = boundingBox.top() + (y * (boundingBox.height()-1)) / (mHorizontalLinesCount+1); //Make sure it's y*h first to avoid rounding bugs - p->drawLine( boundingBox.left(), y_coord, boundingBox.right() - 1, y_coord); + p->drawLine( QPointF(boundingBox.left(), y_coord), QPointF(boundingBox.right() - 1, y_coord) ); } } @@ -1102,7 +1111,6 @@ #else d->mScrollableImage = QPixmap(); #endif - } int KSignalPlotter::fillOpacity() const @@ -1117,7 +1125,6 @@ #else d->mScrollableImage = QPixmap(); #endif - } #ifdef GRAPHICS_SIGNAL_PLOTTER diff --git a/signalplotter/ksignalplotter_p.h b/signalplotter/ksignalplotter_p.h --- a/signalplotter/ksignalplotter_p.h +++ b/signalplotter/ksignalplotter_p.h @@ -8,7 +8,7 @@ published by the Free Software Foundation; either version 2 of the License or (at your option) version 3 or any later version accepted by the membership of KDE e.V. (or its successor approved - by the membership of KDE e.V.), which shall act as a proxy + by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of version 3 of the license. This program is distributed in the hope that it will be useful, @@ -50,15 +50,15 @@ public: KSignalPlotterPrivate( KSignalPlotter * q_ptr ); - void drawWidget(QPainter *p, const QRect &boundingBox); - void drawBackground(QPainter *p, const QRect & boundingBox) const; - void drawThinFrame(QPainter *p, const QRect &boundingBox); + void drawWidget(QPainter *p, const QRectF &boundingBox); + void drawBackground(QPainter *p, const QRectF & boundingBox) const; + void drawThinFrame(QPainter *p, const QRectF &boundingBox); void calculateNiceRange(); void drawBeamToScrollableImage(QPainter *p, int index); - void drawBeam(QPainter *p, const QRect &boundingBox, int horizontalScale, int index); - void drawAxisText(QPainter *p, const QRect &boundingBox); - void drawHorizontalLines(QPainter *p, const QRect &boundingBox) const; - void drawVerticalLines(QPainter *p, const QRect &boundingBox, int correction=0) const; + void drawBeam(QPainter *p, const QRectF &boundingBox, int horizontalScale, int index); + void drawAxisText(QPainter *p, const QRectF &boundingBox); + void drawHorizontalLines(QPainter *p, const QRectF &boundingBox) const; + void drawVerticalLines(QPainter *p, const QRectF &boundingBox, int correction=0) const; void redrawScrollableImage(); void reorderBeams( const QList& newOrder ); @@ -74,7 +74,7 @@ QString scaledValueAsString( qreal value, int precision) const; void addSample( const QList& sampleBuf ); #ifdef SVG_SUPPORT - void updateSvgBackground(const QRect &boundingBox); + void updateSvgBackground(const QRectF &boundingBox); Plasma::SVG* mSvgRenderer; #endif QString mSvgFilename; @@ -129,7 +129,7 @@ int mAxisTextWidth; int mActualAxisTextWidth; // Sometimes there just is not enough room for all the requested axisTextWidth - QRect mPlottingArea; /// The area in which the beams are drawn. Saved to make update() more efficient + QRectF mPlottingArea; /// The area in which the beams are drawn. Saved to make update() more efficient bool mSmoothGraph; /// Whether to smooth the graph by averaging using the formula (value*2 + last_value)/3. KSignalPlotter *q;