/*************************************************************************** * Copyright (C) 2003-2007 by Oliver Saal * * osaal@gmx.de * * http://www.oliver-saal.de/software/afutrainer/ * * * * 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. * ***************************************************************************/ #include "plotwidget.h" #include void CPlotWidgetPoint::clear() { } void CPlotWidgetCurve::clear() { QList::clear(); } QRectF CPlotWidgetCurve::boundaries() const { QRectF rect; for (int i=0; i rect.right()) rect.setRight(p.x()); if (p.y() > rect.bottom()) rect.setBottom(p.y()); else if (p.y() < rect.top()) rect.setTop(p.y()); } } return rect; } CPlotWidgetTic::CPlotWidgetTic(const double dPos, const QString& strText) { clear(); m_dPos = dPos; m_strText = strText; } CPlotWidgetTic::CPlotWidgetTic(const double dPos, const double dWidth, const QString& strText) { clear(); m_dPos = dPos; m_dWidth = dWidth; m_strText = strText; } CPlotWidgetTic::CPlotWidgetTic(const double dPos, const QPixmap& pixmap) { clear(); m_dPos = dPos; m_pixmap = pixmap; } void CPlotWidgetTic::clear() { m_dPos = 0.0; m_dWidth = 0.0; m_pen = QPen(Qt::DashLine); m_pen.setColor(Qt::darkGray); m_penFont = QPen(Qt::black); m_pixmap = QPixmap(); m_strText.clear(); m_fillType = FillNone; m_lineType = LinePlot; m_iTextFlags = Qt::AlignHCenter | Qt::AlignTop; } void CPlotWidgetTic::paintX (QPainter *pPainter, CPlotWidget *pWidget) const { QPoint ptTL, ptBR; // TopLeft, BottomRight QRect rectText; if (m_fillType != FillNone && m_dWidth > 0.0) { ptTL = pWidget->mapToPlot(QPointF(m_dPos, pWidget->m_rectData.top())); ptBR = pWidget->mapToPlot(QPointF(m_dPos+m_dWidth, pWidget->m_rectData.bottom())); if (m_fillType == FillAll) { ptTL.setY(pWidget->m_rectPlot.top()); ptBR.setY(pWidget->m_rectPlot.bottom()); } if (ptTL.x() < pWidget->m_rectPlot.left()) ptTL.setX(pWidget->m_rectPlot.left()); if (ptBR.x() > pWidget->m_rectPlot.right()) ptBR.setX(pWidget->m_rectPlot.right()); pPainter->fillRect(QRect(ptTL, ptBR), m_brush); rectText = QRect( QPoint(ptTL.x(), pWidget->m_rectPlot.bottom() + 5), QPoint(ptBR.x(), pWidget->rect().bottom())); } else { rectText = QRect(); } if (m_lineType != LineNone) { pPainter->setPen(m_pen); pPainter->drawLine( pWidget->mapToPlot(QPointF(m_dPos, pWidget->m_rectData.top())), pWidget->mapToPlot(QPointF(m_dPos, pWidget->m_rectData.bottom()))); } if (!m_strText.isEmpty()) { pPainter->setPen(m_penFont); pPainter->drawText(rectText, m_iTextFlags, m_strText); } } void CPlotWidgetTic::paintY (QPainter *pPainter, CPlotWidget *pWidget) const { QPoint ptTL, ptBR; // TopLeft, BottomRight QRect rectText; if (m_fillType != FillNone && m_dWidth > 0.0) { ptTL = pWidget->mapToPlot(QPointF(pWidget->m_rectData.left(), m_dPos)); ptBR = pWidget->mapToPlot(QPointF(pWidget->m_rectData.right(), m_dPos+m_dWidth)); if (m_fillType == FillAll) { ptTL.setX(pWidget->m_rectPlot.left()); ptBR.setX(pWidget->m_rectPlot.right()); } if (ptTL.y() < pWidget->m_rectPlot.top()) ptTL.setY(pWidget->m_rectPlot.top()); if (ptBR.y() > pWidget->m_rectPlot.bottom()) ptBR.setY(pWidget->m_rectPlot.bottom()); pPainter->fillRect(QRect(ptTL, ptBR), m_brush); rectText = QRect( QPoint(3, ptTL.y()), QPoint(pWidget->m_rectPlot.left()-3, ptBR.y())); } else { QFontMetrics fm(m_font); QPoint pt = pWidget->mapToPlot(QPointF(pWidget->m_rectData.left(), m_dPos)); rectText = QRect( QPoint(3, pt.y()-fm.height()), QPoint(pWidget->m_rectPlot.left()-3, pt.y()+fm.height())); } if (m_lineType != LineNone) { pPainter->setPen(m_pen); pPainter->drawLine( pWidget->mapToPlot(QPointF(pWidget->m_rectData.left(), m_dPos)), pWidget->mapToPlot(QPointF(pWidget->m_rectData.right(), m_dPos))); } if (!m_pixmap.isNull()) { // Ziel-Mittelpunkt errechnen QPoint pt = pWidget->mapToPlot(QPointF(0, m_dPos)); pt.setX(pWidget->m_rectPlot.left() - m_pixmap.width()/2 - 5); // Linke obere Ecke errechnen und malen! pt -= QPoint (m_pixmap.width()/2, m_pixmap.height()/2); pPainter->drawPixmap(pt, m_pixmap); } if (!m_strText.isEmpty()) { pPainter->setPen(m_penFont); pPainter->drawText(rectText, m_iTextFlags, m_strText); } } CPlotWidget::CPlotWidget(QWidget *pParent) : QFrame(pParent) { clear(); } void CPlotWidget::clear() { m_type = PlotLines; m_bLimitAutoY = true; m_bLimitAutoX = true; m_dLimitXMin = 0.0; m_dLimitXMax = 10.0; m_dLimitYMin = 0.0; m_dLimitYMax = 10.0; m_dLimitXRound = 0.0; m_dLimitYRound = 0.0; m_dTicX = 0.0; m_penTicX = QPen(Qt::DashLine); m_penTicX.setColor(Qt::darkGray); m_dTicY = 0.0; m_penTicY = QPen(Qt::DashLine); m_penTicY.setColor(Qt::darkGray); m_iBorder = BorderLeft|BorderBottom; m_iBorderDistTop = 5; m_iBorderDistBottom = 5; m_iBorderDistLeft = 5; m_iBorderDistRight = 5; m_brushPlotBkg = QBrush(Qt::white); m_listTicX.clear(); m_listTicY.clear(); m_dBarWidth = 0.6; m_dBarOffset = 0.0; m_listCurves.clear(); } void CPlotWidget::setBorderDistance(const int iLeft, const int iRight, const int iTop, const int iBottom) { m_iBorderDistTop = iTop; m_iBorderDistBottom = iBottom; m_iBorderDistLeft = iLeft; m_iBorderDistRight = iRight; } void CPlotWidget::updateCache() { m_rectPlot = plotArea(); m_rectData = rectData(); } QRect CPlotWidget::plotArea() const { QRect rect = frameRect(); rect.adjust(m_iBorderDistLeft, m_iBorderDistTop, -m_iBorderDistRight, -m_iBorderDistBottom); return rect; } QRectF CPlotWidget::rectData() const { QRectF rect; if (m_bLimitAutoX || m_bLimitAutoY) { for (int i=0; i 0.0) { rect.setLeft((unsigned)(rect.left() / m_dLimitXRound) * m_dLimitXRound); rect.setRight((unsigned)(rect.right() / m_dLimitXRound + 1) * m_dLimitXRound); } if (!m_bLimitAutoY) { rect.setTop(m_dLimitYMin); rect.setBottom(m_dLimitYMax); } else if (m_dLimitYRound > 0.0) { rect.setTop((unsigned)(rect.top() / m_dLimitYRound) * m_dLimitYRound); rect.setBottom((unsigned)(rect.bottom() / m_dLimitYRound + 1) * m_dLimitYRound); } return rect; } QPoint CPlotWidget::mapToPlot (QPointF p) { QPointF ret; double m; // Umrechung X-Koordinate m = ((double) (m_rectPlot.left() - m_rectPlot.right())) / (m_rectData.left() - m_rectData.right()); ret.setX(m * (p.x() - m_rectData.left()) + m_rectPlot.left()); // Umrechnung Y-Koordinate (mit Spiegelung) m = ((double) (m_rectPlot.bottom() - m_rectPlot.top())) / (m_rectData.top() - m_rectData.bottom()); ret.setY(m * (p.y() - m_rectData.top()) + m_rectPlot.bottom()); return ret.toPoint(); } void CPlotWidget::paintEvent (QPaintEvent *e) { QList listPoints; QList listTicsX, listTicsY; double d=0.0; int i=0; QFrame::paintEvent(e); QPainter painter(this); updateCache(); // Draw Background if (m_brushPlotBkg.style() != Qt::NoBrush) { painter.fillRect(m_rectPlot, m_brushPlotBkg); } // Draw Tics listTicsX = m_listTicX; if (listTicsX.isEmpty() && m_dTicX > 0.0) { d = ((unsigned)(m_rectData.left() / m_dTicX)) * m_dTicX; if (d < m_rectData.left()) d+=m_dTicX; while (d <= m_rectData.right()) { CPlotWidgetTic tic(d, QString("%1").arg(d,0,'f',2)); tic.setPen(m_penTicX); listTicsX.append(tic); d += m_dTicX; } } listTicsY = m_listTicY; if (listTicsY.isEmpty() && m_dTicY > 0.0) { d = ((unsigned)(m_rectData.top() / m_dTicY)) * m_dTicY; if (d < m_rectData.top()) d+=m_dTicY; while (d <= m_rectData.bottom()) { CPlotWidgetTic tic(d, QString("%1").arg(d,0,'f',2)); tic.setPen(m_penTicY); listTicsY.append(tic); d += m_dTicY; } } for (i=0; i