Changeset View
Changeset View
Standalone View
Standalone View
signalplotter/ksignalplotter.cpp
Show All 31 Lines | |||||
32 | #include "ksignalplotter_p.h" | 32 | #include "ksignalplotter_p.h" | ||
33 | #include "ksignalplotter_debug.h" | 33 | #include "ksignalplotter_debug.h" | ||
34 | 34 | | |||
35 | #include <QPainter> | 35 | #include <QPainter> | ||
36 | #include <QPixmap> | 36 | #include <QPixmap> | ||
37 | #include <QPainterPath> | 37 | #include <QPainterPath> | ||
38 | #include <QPaintEvent> | 38 | #include <QPaintEvent> | ||
39 | #include <QEvent> | 39 | #include <QEvent> | ||
40 | #include <QGuiApplication> | ||||
40 | #include <QDebug> | 41 | #include <QDebug> | ||
41 | 42 | | |||
42 | #ifdef GRAPHICS_SIGNAL_PLOTTER | 43 | #ifdef GRAPHICS_SIGNAL_PLOTTER | ||
43 | #include <QGraphicsSceneResizeEvent> | 44 | #include <QGraphicsSceneResizeEvent> | ||
44 | #include <QStyleOptionGraphicsItem> | 45 | #include <QStyleOptionGraphicsItem> | ||
45 | #include <Plasma/Theme> | 46 | #include <Plasma/Theme> | ||
46 | #endif | 47 | #endif | ||
47 | 48 | | |||
▲ Show 20 Lines • Show All 623 Lines • ▼ Show 20 Line(s) | 666 | #ifdef SVG_SUPPORT | |||
671 | } | 672 | } | ||
672 | #endif | 673 | #endif | ||
673 | 674 | | |||
674 | if( mScrollableImage.isNull() ) | 675 | if( mScrollableImage.isNull() ) | ||
675 | redrawScrollableImage(); | 676 | redrawScrollableImage(); | ||
676 | 677 | | |||
677 | //We draw the pixmap in two halves, wrapping around the window | 678 | //We draw the pixmap in two halves, wrapping around the window | ||
678 | if(mScrollOffset > 1) { | 679 | if(mScrollOffset > 1) { | ||
680 | const auto dpr = mScrollableImage.devicePixelRatio(); | ||||
681 | const QPointF point = boundingBox.topRight() - QPointF(mScrollOffset - 2, 0); | ||||
682 | const QRectF sourceRect(0, 0, (mScrollOffset - 1) * dpr, boundingBox.height() * dpr); | ||||
zzag: Can be const. | |||||
679 | #ifdef USE_QIMAGE | 683 | #ifdef USE_QIMAGE | ||
680 | p->drawImage(boundingBox.right() - mScrollOffset+2, boundingBox.top(), mScrollableImage, 0, 0, mScrollOffset-1, boundingBox.height()); | 684 | p->drawImage(point, mScrollableImage, sourceRect); | ||
681 | #else | 685 | #else | ||
682 | p->drawPixmap(boundingBox.right() - mScrollOffset+2, boundingBox.top(), mScrollableImage, 0, 0, mScrollOffset-1, boundingBox.height()); | 686 | p->drawPixmap(point, mScrollableImage, sourceRect); | ||
683 | #endif | 687 | #endif | ||
684 | } | 688 | } | ||
685 | int widthOfSecondHalf = boundingBox.width() - mScrollOffset + 1; | 689 | int widthOfSecondHalf = boundingBox.width() - mScrollOffset + 1; | ||
686 | if(widthOfSecondHalf > 0) { | 690 | if(widthOfSecondHalf > 0) { | ||
691 | const auto dpr = mScrollableImage.devicePixelRatio(); | ||||
zzag: Don't abuse `auto`. | |||||
692 | const QRectF sourceRect(mScrollableImage.width() - (widthOfSecondHalf + 1) * dpr, 0, widthOfSecondHalf * dpr, boundingBox.height() * dpr); | ||||
687 | #ifdef USE_QIMAGE | 693 | #ifdef USE_QIMAGE | ||
688 | p->drawImage(boundingBox.left(), boundingBox.top(), mScrollableImage, mScrollableImage.width() - widthOfSecondHalf-1, 0, widthOfSecondHalf, boundingBox.height()); | 694 | p->drawImage(boundingBox.topLeft(), mScrollableImage, sourceRect); | ||
689 | #else | 695 | #else | ||
690 | p->drawPixmap(boundingBox.left(), boundingBox.top(), mScrollableImage, mScrollableImage.width() - widthOfSecondHalf-1, 0, widthOfSecondHalf, boundingBox.height()); | 696 | p->drawPixmap(boundingBox.topLeft(), mScrollableImage, sourceRect); | ||
691 | #endif | 697 | #endif | ||
692 | } | 698 | } | ||
693 | 699 | | |||
694 | /* Draw scope-like grid vertical lines if it doesn't move. If it does move, draw it in the dynamic part of the code*/ | 700 | /* Draw scope-like grid vertical lines if it doesn't move. If it does move, draw it in the dynamic part of the code*/ | ||
695 | if(mShowVerticalLines && !mVerticalLinesScroll) | 701 | if(mShowVerticalLines && !mVerticalLinesScroll) | ||
696 | drawVerticalLines(p, boundingBox); | 702 | drawVerticalLines(p, boundingBox); | ||
697 | } | 703 | } | ||
698 | void KSignalPlotterPrivate::drawBackground(QPainter *p, const QRect &boundingBox) const | 704 | void KSignalPlotterPrivate::drawBackground(QPainter *p, const QRect &boundingBox) const | ||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Line(s) | |||||
742 | 748 | | |||
743 | } | 749 | } | ||
744 | #endif | 750 | #endif | ||
745 | void KSignalPlotterPrivate::redrawScrollableImage() | 751 | void KSignalPlotterPrivate::redrawScrollableImage() | ||
746 | { | 752 | { | ||
747 | //Align width of bounding box to the size of the horizontal scale | 753 | //Align width of bounding box to the size of the horizontal scale | ||
748 | int alignedWidth = ((mPlottingArea.width() + 1) / mHorizontalScale + 1) * mHorizontalScale; | 754 | int alignedWidth = ((mPlottingArea.width() + 1) / mHorizontalScale + 1) * mHorizontalScale; | ||
749 | //Redraw the whole thing | 755 | //Redraw the whole thing | ||
756 | const auto dpr = qApp->devicePixelRatio(); | ||||
757 | const QSize size = QSize(alignedWidth, mPlottingArea.height()); | ||||
750 | #ifdef USE_QIMAGE | 758 | #ifdef USE_QIMAGE | ||
751 | mScrollableImage = QImage(alignedWidth, mPlottingArea.height(),QImage::Format_ARGB32_Premultiplied); | 759 | mScrollableImage = QImage(size * dpr, QImage::Format_ARGB32_Premultiplied); | ||
752 | #else | 760 | #else | ||
753 | mScrollableImage = QPixmap(alignedWidth, mPlottingArea.height()); | 761 | mScrollableImage = QPixmap(size * dpr); | ||
754 | #endif | 762 | #endif | ||
755 | Q_ASSERT(!mScrollableImage.isNull()); | 763 | Q_ASSERT(!mScrollableImage.isNull()); | ||
764 | mScrollableImage.setDevicePixelRatio(dpr); | ||||
756 | 765 | | |||
757 | mScrollOffset = 0; | 766 | mScrollOffset = 0; | ||
758 | mVerticalLinesOffset = mVerticalLinesDistance - mHorizontalScale+1; // mVerticalLinesDistance - alignedWidth % mVerticalLinesDistance; | 767 | mVerticalLinesOffset = mVerticalLinesDistance - mHorizontalScale+1; // mVerticalLinesDistance - alignedWidth % mVerticalLinesDistance; | ||
759 | //We need to draw the background for areas without a beam | 768 | //We need to draw the background for areas without a beam | ||
760 | int withoutBeamWidth = qMax(mBeamData.size()-1, 0) * mHorizontalScale; | 769 | int withoutBeamWidth = qMax(mBeamData.size()-1, 0) * mHorizontalScale; | ||
761 | QPainter pCache(&mScrollableImage); | 770 | QPainter pCache(&mScrollableImage); | ||
762 | if(withoutBeamWidth < mScrollableImage.width()) | 771 | if(withoutBeamWidth < size.width()) | ||
763 | drawBackground(&pCache, QRect(withoutBeamWidth, 0, alignedWidth - withoutBeamWidth, mScrollableImage.height())); | 772 | drawBackground(&pCache, QRect(withoutBeamWidth, 0, alignedWidth - withoutBeamWidth, size.height())); | ||
764 | 773 | | |||
765 | /* Draw scope-like grid vertical lines */ | 774 | /* Draw scope-like grid vertical lines */ | ||
766 | mVerticalLinesOffset = 0; | 775 | mVerticalLinesOffset = 0; | ||
767 | if(mBeamData.size() > 2) { | 776 | if(mBeamData.size() > 2) { | ||
768 | for(int i = mBeamData.size()-2; i >= 0; i--) | 777 | for(int i = mBeamData.size()-2; i >= 0; i--) | ||
769 | drawBeamToScrollableImage(&pCache, i); | 778 | drawBeamToScrollableImage(&pCache, i); | ||
770 | } | 779 | } | ||
771 | } | 780 | } | ||
▲ Show 20 Lines • Show All 88 Lines • ▼ Show 20 Line(s) | 863 | { | |||
860 | p->setRenderHint(QPainter::Antialiasing, false); | 869 | p->setRenderHint(QPainter::Antialiasing, false); | ||
861 | for ( int x = boundingBox.right() - ( offset % mVerticalLinesDistance); x >= boundingBox.left(); x -= mVerticalLinesDistance ) | 870 | for ( int x = boundingBox.right() - ( offset % mVerticalLinesDistance); x >= boundingBox.left(); x -= mVerticalLinesDistance ) | ||
862 | p->drawLine( x, boundingBox.top(), x, boundingBox.bottom() ); | 871 | p->drawLine( x, boundingBox.top(), x, boundingBox.bottom() ); | ||
863 | p->setRenderHint(QPainter::Antialiasing, true); | 872 | p->setRenderHint(QPainter::Antialiasing, true); | ||
864 | } | 873 | } | ||
865 | 874 | | |||
866 | void KSignalPlotterPrivate::drawBeamToScrollableImage(QPainter *p, int index) | 875 | void KSignalPlotterPrivate::drawBeamToScrollableImage(QPainter *p, int index) | ||
867 | { | 876 | { | ||
868 | QRect cacheBoundingBox = QRect(mScrollOffset, 0, mHorizontalScale, mScrollableImage.height()); | 877 | const QSize dipSize = mScrollableImage.size() / mScrollableImage.devicePixelRatio(); | ||
878 | QRect cacheBoundingBox = QRect(mScrollOffset, 0, mHorizontalScale, dipSize.height()); | ||||
869 | 879 | | |||
870 | drawBackground(p, cacheBoundingBox); | 880 | drawBackground(p, cacheBoundingBox); | ||
871 | drawBeam(p, cacheBoundingBox, mHorizontalScale, index); | 881 | drawBeam(p, cacheBoundingBox, mHorizontalScale, index); | ||
872 | 882 | | |||
873 | mScrollOffset += mHorizontalScale; | 883 | mScrollOffset += mHorizontalScale; | ||
874 | mVerticalLinesOffset = (mVerticalLinesOffset + mHorizontalScale) % mVerticalLinesDistance; | 884 | mVerticalLinesOffset = (mVerticalLinesOffset + mHorizontalScale) % mVerticalLinesDistance; | ||
875 | if(mScrollOffset >= mScrollableImage.width()-1) { | 885 | if(mScrollOffset >= dipSize.width()-1) { | ||
876 | mScrollOffset = 0; | 886 | mScrollOffset = 0; | ||
877 | mVerticalLinesOffset--; //We skip over the last pixel drawn | 887 | mVerticalLinesOffset--; //We skip over the last pixel drawn | ||
878 | } | 888 | } | ||
879 | } | 889 | } | ||
880 | 890 | | |||
881 | void KSignalPlotterPrivate::drawBeam(QPainter *p, const QRect &boundingBox, int horizontalScale, int index) | 891 | void KSignalPlotterPrivate::drawBeam(QPainter *p, const QRect &boundingBox, int horizontalScale, int index) | ||
882 | { | 892 | { | ||
883 | if(mNiceRange == 0) return; | 893 | if(mNiceRange == 0) return; | ||
884 | QPen pen; | 894 | QPen pen; | ||
895 | const auto dpr = qApp->devicePixelRatio(); | ||||
885 | if(mHorizontalScale == 1) //Don't use a pen width of 2 if there's only 1 pixel between points | 896 | if(mHorizontalScale == 1) //Don't use a pen width of 2 if there's only 1 pixel between points | ||
886 | pen.setWidth(1); | 897 | pen.setWidthF(1.0 / dpr); | ||
887 | else | 898 | else | ||
888 | pen.setWidth(2); | 899 | pen.setWidthF(2.0 / dpr); | ||
zzag: Could you please explain why we have to do this? | |||||
volkov: To avoid artifacts when painting beams. | |||||
889 | 900 | | |||
890 | pen.setCapStyle(Qt::FlatCap); | 901 | pen.setCapStyle(Qt::FlatCap); | ||
891 | 902 | | |||
892 | qreal scaleFac = (boundingBox.height()-2) / mNiceRange; | 903 | qreal scaleFac = (boundingBox.height()-2) / mNiceRange; | ||
893 | if(mBeamData.size() - 1 <= index ) | 904 | if(mBeamData.size() - 1 <= index ) | ||
894 | return; // Something went wrong? | 905 | return; // Something went wrong? | ||
895 | 906 | | |||
896 | const QList<qreal> &datapoints = mBeamData[index]; | 907 | const QList<qreal> &datapoints = mBeamData[index]; | ||
▲ Show 20 Lines • Show All 254 Lines • Show Last 20 Lines |
Can be const.