# HG changeset patch # User Alexis Jeandet # Date 2015-03-12 21:12:39 # Node ID 6e23aedd1ca889ccfd57ce07e1abe7861ce29e69 # Parent 665de41c4c7431f379aef339f81ae85c7209b23a Removed hack from QCustomPlot, moved to QCustomPlotVect class. diff --git a/QLop.pro b/QLop.pro --- a/QLop.pro +++ b/QLop.pro @@ -30,9 +30,7 @@ SOURCES += src/main.cpp\ src/mainwindow.cpp \ src/SocExplorerPlot.cpp \ src/QCustomPlot/qcustomplot.cpp \ - src/folderview.cpp \ src/toolbarcontainer.cpp \ - src/folderlistwidget.cpp \ src/Core/abstractfileloader.cpp \ src/Core/filedownloader.cpp \ src/Core/filedownloadertask.cpp \ @@ -52,14 +50,13 @@ SOURCES += src/main.cpp\ src/Core/Widgets/PyWdgt/pythonqtscriptingconsoledandd.cpp \ src/QCustomPlot/qcpdocumentobject.cpp \ src/Core/Widgets/filebrowser.cpp \ - src/Core/Widgets/filesystemmodel.cpp + src/Core/Widgets/filesystemmodel.cpp \ + src/Core/Widgets/qcustomplotvect.cpp HEADERS += src/mainwindow.h \ src/SocExplorerPlot.h \ src/QCustomPlot/qcustomplot.h \ - src/folderview.h \ src/toolbarcontainer.h \ - src/folderlistwidget.h \ src/Core/abstractfileloader.h \ src/Core/filedownloader.h \ src/Core/filedownloadertask.h \ @@ -81,10 +78,10 @@ HEADERS += src/mainwindow.h \ src/Core/pyqlop.h \ src/QCustomPlot/qcpdocumentobject.h \ src/Core/Widgets/filebrowser.h \ - src/Core/Widgets/filesystemmodel.h + src/Core/Widgets/filesystemmodel.h \ + src/Core/Widgets/qcustomplotvect.h FORMS += src/mainwindow.ui \ - src/folderview.ui \ src/Core/Widgets/downloadhistory.ui \ src/Core/Widgets/downloadhistoryelement.ui \ src/Cassini/cassinidatadownloader.ui \ diff --git a/src/Cassini/cassinitools.cpp b/src/Cassini/cassinitools.cpp --- a/src/Cassini/cassinitools.cpp +++ b/src/Cassini/cassinitools.cpp @@ -55,7 +55,7 @@ void CassiniTools::makePlot() plot->setXaxisTickLabelType(QCPAxis::ltDateTime); plot->setXaxisDateTimeFormat("hh:mm:ss.zzz"); plot->setContextMenuPolicy(Qt::ActionsContextMenu); - QAction* action=new QAction("export view",_self); + SocExplorerPlotActions* action=new SocExplorerPlotActions("export view",plot->PID(),_self); plot->addAction(action); QObject::connect(action,SIGNAL(triggered()),_self,SLOT(export_view())); } @@ -104,15 +104,11 @@ void CassiniTools::plot_TAB_File(const Q plotFile(fileName); } -void CassiniTools::export_view() +void CassiniTools::export_view(int PID) { - SocExplorerPlot* plot = QLopPlots::getPlot(m_defaultPlot); + SocExplorerPlot* plot = QLopPlots::getPlot(PID); if(plot==NULL) - { - makePlot(); - plot = QLopPlots::getPlot(m_defaultPlot); - } - if(plot) + return; { QString fileName = QFileDialog::getSaveFileName(); } diff --git a/src/Cassini/cassinitools.h b/src/Cassini/cassinitools.h --- a/src/Cassini/cassinitools.h +++ b/src/Cassini/cassinitools.h @@ -31,7 +31,7 @@ public: static void plotFile(const QString &File); public slots: void plot_TAB_File(const QString& fileName); - void export_view(); + void export_view(int PID); private slots: void dataReady(QLopDataList data); }; diff --git a/src/Cassini/cassinitoolsgui.h b/src/Cassini/cassinitoolsgui.h --- a/src/Cassini/cassinitoolsgui.h +++ b/src/Cassini/cassinitoolsgui.h @@ -2,7 +2,6 @@ #define CASSINITOOLSGUI_H #include -#include #include namespace Ui { diff --git a/src/Core/Widgets/qcustomplotvect.cpp b/src/Core/Widgets/qcustomplotvect.cpp new file mode 100644 --- /dev/null +++ b/src/Core/Widgets/qcustomplotvect.cpp @@ -0,0 +1,619 @@ +#include "qcustomplotvect.h" +#include +#include +QCustomPlotVect::QCustomPlotVect(QWidget *parent) + :QCustomPlot(parent) +{ + +} + +QCustomPlotVect::~QCustomPlotVect() +{ + +} + +QCPGraphVect *QCustomPlotVect::addGraph(QCPAxis *keyAxis, QCPAxis *valueAxis) +{ + if (!keyAxis) keyAxis = xAxis; + if (!valueAxis) valueAxis = yAxis; + if (!keyAxis || !valueAxis) + { + qDebug() << Q_FUNC_INFO << "can't use default QCustomPlot xAxis or yAxis, because at least one is invalid (has been deleted)"; + return 0; + } + if (keyAxis->parentPlot() != this || valueAxis->parentPlot() != this) + { + qDebug() << Q_FUNC_INFO << "passed keyAxis or valueAxis doesn't have this QCustomPlot as parent"; + return 0; + } + + QCPGraphVect *newGraph = new QCPGraphVect(keyAxis, valueAxis); + if (addPlottable(newGraph)) + { + newGraph->setName(QLatin1String("Graph ")+QString::number(mGraphs.size())); + return newGraph; + } else + { + delete newGraph; + return 0; + } +} + + +QCPGraphVect::QCPGraphVect(QCPAxis *keyAxis, QCPAxis *valueAxis) + :QCPGraph(keyAxis,valueAxis) +{ + mData = new QVector(); +} + +QCPGraphVect::~QCPGraphVect() +{ + +} + +void QCPGraphVect::setData(QVector *data) +{ + if(data!=mData) + { + delete this->mData; + this->mData = data; + } +} + +void QCPGraphVect::draw(QCPPainter *painter) +{ + if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + int test = mKeyAxis.data()->range().size(); + test = mData->count(); + if (mKeyAxis.data()->range().size() <= 0 || mData->isEmpty()) return; + if (mLineStyle == lsNone && mScatterStyle.isNone()) return; + + // allocate line and (if necessary) point vectors: + QVector *lineData = new QVector; + QVector *scatterData = 0; + if (!mScatterStyle.isNone()) + scatterData = new QVector; + + // fill vectors with data appropriate to plot style: + getPlotData(lineData, scatterData); + + // check data validity if flag set: +#ifdef QCUSTOMPLOT_CHECK_DATA + QCPDataMap::const_iterator it; + for (it = mData->constBegin(); it != mData->constEnd(); ++it) + { + if (QCP::isInvalidData(it.value().key, it.value().value) || + QCP::isInvalidData(it.value().keyErrorPlus, it.value().keyErrorMinus) || + QCP::isInvalidData(it.value().valueErrorPlus, it.value().valueErrorPlus)) + qDebug() << Q_FUNC_INFO << "Data point at" << it.key() << "invalid." << "Plottable name:" << name(); + } +#endif + + // draw fill of graph: + drawFill(painter, lineData); + + // draw line: + if (mLineStyle == lsImpulse) + drawImpulsePlot(painter, lineData); + else if (mLineStyle != lsNone) + drawLinePlot(painter, lineData); // also step plots can be drawn as a line plot + + // draw scatters: + if (scatterData) + drawScatterPlot(painter, scatterData); + + // free allocated line and point vectors: + delete lineData; + if (scatterData) + delete scatterData; +} + +void QCPGraphVect::getPlotData(QVector *lineData, QVector *scatterData) const +{ + switch(mLineStyle) + { + case lsNone: getScatterPlotData(scatterData); break; + case lsLine: getLinePlotData(lineData, scatterData); break; + case lsStepLeft: getStepLeftPlotData(lineData, scatterData); break; + case lsStepRight: getStepRightPlotData(lineData, scatterData); break; + case lsStepCenter: getStepCenterPlotData(lineData, scatterData); break; + case lsImpulse: getImpulsePlotData(lineData, scatterData); break; + } +} + +void QCPGraphVect::getLinePlotData(QVector *linePixelData, QVector *scatterData) const +{ + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as linePixelData"; return; } + + QVector lineData; + getPreparedData(&lineData, scatterData); + linePixelData->reserve(lineData.size()+2); // added 2 to reserve memory for lower/upper fill base points that might be needed for fill + linePixelData->resize(lineData.size()); + + // transform lineData points to pixels: + if (keyAxis->orientation() == Qt::Vertical) + { + for (int i=0; icoordToPixel(lineData.at(i).value)); + (*linePixelData)[i].setY(keyAxis->coordToPixel(lineData.at(i).key)); + } + } else // key axis is horizontal + { + for (int i=0; icoordToPixel(lineData.at(i).key)); + (*linePixelData)[i].setY(valueAxis->coordToPixel(lineData.at(i).value)); + } + } +} + +QCPRange QCPGraphVect::getKeyRange(bool &foundRange, QCPAbstractPlottable::SignDomain inSignDomain, bool includeErrors) const +{ + + QCPRange range; + bool haveLower = false; + bool haveUpper = false; + + double current, currentErrorMinus, currentErrorPlus; + + if (inSignDomain == sdBoth) // range may be anywhere + { + QVector::const_iterator it = mData->constBegin(); + while (it != mData->constEnd()) + { + current = (*it).key; + currentErrorMinus = (includeErrors ? (*it).keyErrorMinus : 0); + currentErrorPlus = (includeErrors ? (*it).keyErrorPlus : 0); + if (current-currentErrorMinus < range.lower || !haveLower) + { + range.lower = current-currentErrorMinus; + haveLower = true; + } + if (current+currentErrorPlus > range.upper || !haveUpper) + { + range.upper = current+currentErrorPlus; + haveUpper = true; + } + ++it; + } + } else if (inSignDomain == sdNegative) // range may only be in the negative sign domain + { + QVector::const_iterator it = mData->constBegin(); + while (it != mData->constEnd()) + { + current = (*it).key; + currentErrorMinus = (includeErrors ? (*it).keyErrorMinus : 0); + currentErrorPlus = (includeErrors ? (*it).keyErrorPlus : 0); + if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus < 0) + { + range.lower = current-currentErrorMinus; + haveLower = true; + } + if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus < 0) + { + range.upper = current+currentErrorPlus; + haveUpper = true; + } + if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to geht that point. + { + if ((current < range.lower || !haveLower) && current < 0) + { + range.lower = current; + haveLower = true; + } + if ((current > range.upper || !haveUpper) && current < 0) + { + range.upper = current; + haveUpper = true; + } + } + ++it; + } + } else if (inSignDomain == sdPositive) // range may only be in the positive sign domain + { + QVector::const_iterator it = mData->constBegin(); + while (it != mData->constEnd()) + { + current = (*it).key; + currentErrorMinus = (includeErrors ? (*it).keyErrorMinus : 0); + currentErrorPlus = (includeErrors ? (*it).keyErrorPlus : 0); + if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus > 0) + { + range.lower = current-currentErrorMinus; + haveLower = true; + } + if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus > 0) + { + range.upper = current+currentErrorPlus; + haveUpper = true; + } + if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to get that point. + { + if ((current < range.lower || !haveLower) && current > 0) + { + range.lower = current; + haveLower = true; + } + if ((current > range.upper || !haveUpper) && current > 0) + { + range.upper = current; + haveUpper = true; + } + } + ++it; + } + } + + foundRange = haveLower && haveUpper; + return range; +} + +QCPRange QCPGraphVect::getValueRange(bool &foundRange, QCPAbstractPlottable::SignDomain inSignDomain, bool includeErrors) const +{ + QCPRange range; + bool haveLower = false; + bool haveUpper = false; + + double current, currentErrorMinus, currentErrorPlus; + + if (inSignDomain == sdBoth) // range may be anywhere + { + QVector::const_iterator it = mData->constBegin(); + while (it != mData->constEnd()) + { + current = (*it).value; + currentErrorMinus = (includeErrors ? (*it).valueErrorMinus : 0); + currentErrorPlus = (includeErrors ? (*it).valueErrorPlus : 0); + if (current-currentErrorMinus < range.lower || !haveLower) + { + range.lower = current-currentErrorMinus; + haveLower = true; + } + if (current+currentErrorPlus > range.upper || !haveUpper) + { + range.upper = current+currentErrorPlus; + haveUpper = true; + } + ++it; + } + } else if (inSignDomain == sdNegative) // range may only be in the negative sign domain + { + QVector::const_iterator it = mData->constBegin(); + while (it != mData->constEnd()) + { + current = (*it).value; + currentErrorMinus = (includeErrors ? (*it).valueErrorMinus : 0); + currentErrorPlus = (includeErrors ? (*it).valueErrorPlus : 0); + if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus < 0) + { + range.lower = current-currentErrorMinus; + haveLower = true; + } + if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus < 0) + { + range.upper = current+currentErrorPlus; + haveUpper = true; + } + if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to get that point. + { + if ((current < range.lower || !haveLower) && current < 0) + { + range.lower = current; + haveLower = true; + } + if ((current > range.upper || !haveUpper) && current < 0) + { + range.upper = current; + haveUpper = true; + } + } + ++it; + } + } else if (inSignDomain == sdPositive) // range may only be in the positive sign domain + { + QVector::const_iterator it = mData->constBegin(); + while (it != mData->constEnd()) + { + current = (*it).value; + currentErrorMinus = (includeErrors ? (*it).valueErrorMinus : 0); + currentErrorPlus = (includeErrors ? (*it).valueErrorPlus : 0); + if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus > 0) + { + range.lower = current-currentErrorMinus; + haveLower = true; + } + if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus > 0) + { + range.upper = current+currentErrorPlus; + haveUpper = true; + } + if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to geht that point. + { + if ((current < range.lower || !haveLower) && current > 0) + { + range.lower = current; + haveLower = true; + } + if ((current > range.upper || !haveUpper) && current > 0) + { + range.upper = current; + haveUpper = true; + } + } + ++it; + } + } + + foundRange = haveLower && haveUpper; + return range; +} + +void QCPGraphVect::getPreparedData(QVector *lineData, QVector *scatterData) const +{ + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + // get visible data range: + QVector::const_iterator lower, upper; // note that upper is the actual upper point, and not 1 step after the upper point + getVisibleDataBounds(lower, upper); + if (lower == mData->constEnd() || upper == mData->constEnd()) + return; + + // count points in visible range, taking into account that we only need to count to the limit maxCount if using adaptive sampling: + int maxCount = std::numeric_limits::max(); + if (mAdaptiveSampling) + { + int keyPixelSpan = qAbs(keyAxis->coordToPixel((*lower).key)-keyAxis->coordToPixel((*upper).key)); + maxCount = 2*keyPixelSpan+2; + } + int dataCount = countDataInBounds(lower, upper, maxCount); + + if (mAdaptiveSampling && dataCount >= maxCount) // use adaptive sampling only if there are at least two points per pixel on average + { + if (lineData) + { + QVector::const_iterator it = lower; + QVector::const_iterator upperEnd = upper+1; + double minValue = (*it).value; + double maxValue = (*it).value; + QVector::const_iterator currentIntervalFirstPoint = it; + int reversedFactor = keyAxis->rangeReversed() != (keyAxis->orientation()==Qt::Vertical) ? -1 : 1; // is used to calculate keyEpsilon pixel into the correct direction + int reversedRound = keyAxis->rangeReversed() != (keyAxis->orientation()==Qt::Vertical) ? 1 : 0; // is used to switch between floor (normal) and ceil (reversed) rounding of currentIntervalStartKey + double currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel((*lower).key)+reversedRound)); + double lastIntervalEndKey = currentIntervalStartKey; + double keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); // interval of one pixel on screen when mapped to plot key coordinates + bool keyEpsilonVariable = keyAxis->scaleType() == QCPAxis::stLogarithmic; // indicates whether keyEpsilon needs to be updated after every interval (for log axes) + int intervalDataCount = 1; + ++it; // advance iterator to second data point because adaptive sampling works in 1 point retrospect + while (it != upperEnd) + { + if ((*it).key < currentIntervalStartKey+keyEpsilon) // data point is still within same pixel, so skip it and expand value span of this cluster if necessary + { + if ((*it).value < minValue) + minValue = (*it).value; + else if ((*it).value > maxValue) + maxValue = (*it).value; + ++intervalDataCount; + } else // new pixel interval started + { + if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them to a cluster + { + if (lastIntervalEndKey < currentIntervalStartKey-keyEpsilon) // last point is further away, so first point of this cluster must be at a real data point + lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.2, (*currentIntervalFirstPoint).value)); + lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.25, minValue)); + lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.75, maxValue)); + if ((*it).key > currentIntervalStartKey+keyEpsilon*2) // new pixel started further away from previous cluster, so make sure the last point of the cluster is at a real data point + lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.8, (*(it-1)).value)); + } else + lineData->append(QCPData((*currentIntervalFirstPoint).key, (*currentIntervalFirstPoint).value)); + lastIntervalEndKey = (*(it-1)).key; + minValue = (*it).value; + maxValue = (*it).value; + currentIntervalFirstPoint = it; + currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel((*it).key)+reversedRound)); + if (keyEpsilonVariable) + keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); + intervalDataCount = 1; + } + ++it; + } + // handle last interval: + if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them to a cluster + { + if (lastIntervalEndKey < currentIntervalStartKey-keyEpsilon) // last point wasn't a cluster, so first point of this cluster must be at a real data point + lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.2, (*currentIntervalFirstPoint).value)); + lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.25, minValue)); + lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.75, maxValue)); + } else + lineData->append(QCPData((*currentIntervalFirstPoint).key, (*currentIntervalFirstPoint).value)); + } + + if (scatterData) + { + double valueMaxRange = valueAxis->range().upper; + double valueMinRange = valueAxis->range().lower; + QVector::const_iterator it = lower; + QVector::const_iterator upperEnd = upper+1; + double minValue = (*it).value; + double maxValue = (*it).value; + QVector::const_iterator minValueIt = it; + QVector::const_iterator maxValueIt = it; + QVector::const_iterator currentIntervalStart = it; + int reversedFactor = keyAxis->rangeReversed() ? -1 : 1; // is used to calculate keyEpsilon pixel into the correct direction + int reversedRound = keyAxis->rangeReversed() ? 1 : 0; // is used to switch between floor (normal) and ceil (reversed) rounding of currentIntervalStartKey + double currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel((*lower).key)+reversedRound)); + double keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); // interval of one pixel on screen when mapped to plot key coordinates + bool keyEpsilonVariable = keyAxis->scaleType() == QCPAxis::stLogarithmic; // indicates whether keyEpsilon needs to be updated after every interval (for log axes) + int intervalDataCount = 1; + ++it; // advance iterator to second data point because adaptive sampling works in 1 point retrospect + while (it != upperEnd) + { + if ((*it).key < currentIntervalStartKey+keyEpsilon) // data point is still within same pixel, so skip it and expand value span of this pixel if necessary + { + if ((*it).value < minValue && (*it).value > valueMinRange && (*it).value < valueMaxRange) + { + minValue = (*it).value; + minValueIt = it; + } else if ((*it).value > maxValue && (*it).value > valueMinRange && (*it).value < valueMaxRange) + { + maxValue = (*it).value; + maxValueIt = it; + } + ++intervalDataCount; + } else // new pixel started + { + if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them + { + // determine value pixel span and add as many points in interval to maintain certain vertical data density (this is specific to scatter plot): + double valuePixelSpan = qAbs(valueAxis->coordToPixel(minValue)-valueAxis->coordToPixel(maxValue)); + int dataModulo = qMax(1, qRound(intervalDataCount/(valuePixelSpan/4.0))); // approximately every 4 value pixels one data point on average + QVector::const_iterator intervalIt = currentIntervalStart; + int c = 0; + while (intervalIt != it) + { + if ((c % dataModulo == 0 || intervalIt == minValueIt || intervalIt == maxValueIt) && (*intervalIt).value > valueMinRange && (*intervalIt).value < valueMaxRange) + scatterData->append((*intervalIt)); + ++c; + ++intervalIt; + } + } else if ((*currentIntervalStart).value > valueMinRange && (*currentIntervalStart).value < valueMaxRange) + scatterData->append((*currentIntervalStart)); + minValue = (*it).value; + maxValue = (*it).value; + currentIntervalStart = it; + currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel((*it).key)+reversedRound)); + if (keyEpsilonVariable) + keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); + intervalDataCount = 1; + } + ++it; + } + // handle last interval: + if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them + { + // determine value pixel span and add as many points in interval to maintain certain vertical data density (this is specific to scatter plot): + double valuePixelSpan = qAbs(valueAxis->coordToPixel(minValue)-valueAxis->coordToPixel(maxValue)); + int dataModulo = qMax(1, qRound(intervalDataCount/(valuePixelSpan/4.0))); // approximately every 4 value pixels one data point on average + QVector::const_iterator intervalIt = currentIntervalStart; + int c = 0; + while (intervalIt != it) + { + if ((c % dataModulo == 0 || intervalIt == minValueIt || intervalIt == maxValueIt) && (*intervalIt).value > valueMinRange && (*intervalIt).value < valueMaxRange) + scatterData->append((*intervalIt)); + ++c; + ++intervalIt; + } + } else if ((*currentIntervalStart).value > valueMinRange && (*currentIntervalStart).value < valueMaxRange) + scatterData->append(*currentIntervalStart); + } + } else // don't use adaptive sampling algorithm, transfer points one-to-one from the map into the output parameters + { + QVector *dataVector = 0; + if (lineData) + { + dataVector = lineData; + } + else if (scatterData) + dataVector = scatterData; + if (dataVector) + { + QVector::const_iterator it = lower; + QVector::const_iterator upperEnd = upper+1; + dataVector->reserve(dataCount+2); // +2 for possible fill end points + while (it != upperEnd) + { + dataVector->append(*it); + ++it; + } + } + if (lineData && scatterData) + *scatterData = *dataVector; + } +} + +QVector::const_iterator __lowerBoundDico_vect(QVector* vector,double key) +{ + int DX=vector->size()/2; + int pos=DX; +// double test=(*vector)[vector->length()-1].key; + if(key>((*vector)[vector->length()-1].key)) + return vector->constEnd(); + if(key<((*vector)[0].key)) + return vector->constBegin(); + while (DX>1) + { + DX=DX/2; + if((*vector)[pos].key > key) + { + pos-=DX; + } + else + { + pos+=DX; + } + } + if((*vector)[pos].key >= key) + return vector->constBegin()+pos; + return vector->constBegin()+pos+1; +} + + +QVector::const_iterator __upperBoundDico_vect(QVector* vector,double key) +{ + int DX=vector->size()/2; + int pos=DX; + if(key>((*vector)[vector->length()-1].key)) + return vector->constEnd(); + if(key<((*vector)[0].key)) + return vector->constBegin(); + while (DX>1) + { + DX=DX/2; + if((*vector)[pos].key > key) + { + pos-=DX; + } + else + { + pos+=DX; + } + } + return vector->constBegin()+pos+1; +} + + +void QCPGraphVect::getVisibleDataBounds(QVector::const_iterator &lower, QVector::const_iterator &upper) const +{ + if (!mKeyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; } + if (mData->isEmpty()) + { + lower = mData->constEnd(); + upper = mData->constEnd(); + return; + } + QVector::const_iterator lbound = __lowerBoundDico_vect(mData,mKeyAxis.data()->range().lower); + QVector::const_iterator ubound = __upperBoundDico_vect(mData,mKeyAxis.data()->range().upper); + bool lowoutlier = lbound != mData->constBegin(); // indicates whether there exist points below axis range + bool highoutlier = ubound != mData->constEnd(); // indicates whether there exist points above axis range + + lower = (lowoutlier ? lbound-1 : lbound); // data point range that will be actually drawn + upper = (highoutlier ? ubound : ubound-1); // data point range that will be actually drawn +} + +int QCPGraphVect::countDataInBounds(const QVector::const_iterator &lower, const QVector::const_iterator &upper, int maxCount) const +{ + if (upper == mData->constEnd() && lower == mData->constEnd()) + return 0; + QVector::const_iterator it = lower; + int count = 1; + while (it != upper && count < maxCount) + { + ++it; + ++count; + } + return count; +} diff --git a/src/Core/Widgets/qcustomplotvect.h b/src/Core/Widgets/qcustomplotvect.h new file mode 100644 --- /dev/null +++ b/src/Core/Widgets/qcustomplotvect.h @@ -0,0 +1,38 @@ +#ifndef QCUSTOMPLOTVECT_H +#define QCUSTOMPLOTVECT_H + +#include +#include + +class QCPGraphVect : public QCPGraph +{ + Q_OBJECT +public: + explicit QCPGraphVect(QCPAxis *keyAxis, QCPAxis *valueAxis); + ~QCPGraphVect(); + QVector *data() const { return mData; } + void setData(QVector *data); +protected: + QVector* mData; + virtual void draw(QCPPainter *painter); + virtual QCPRange getKeyRange(bool &foundRange, SignDomain inSignDomain, bool includeErrors) const; // overloads base class interface + virtual QCPRange getValueRange(bool &foundRange, SignDomain inSignDomain, bool includeErrors) const; + void getPreparedData(QVector *lineData, QVector *scatterData) const; + void getVisibleDataBounds(QVector::const_iterator &lower, QVector::const_iterator &upper) const; + int countDataInBounds(const QVector::const_iterator &lower, const QVector::const_iterator &upper, int maxCount) const; + + void getPlotData(QVector *lineData, QVector *scatterData) const; + void getLinePlotData(QVector *linePixelData, QVector *scatterData) const; +}; + +class QCustomPlotVect : public QCustomPlot +{ + Q_OBJECT +public: + QCustomPlotVect(QWidget *parent = 0); + ~QCustomPlotVect(); + QCPGraphVect *addGraph(QCPAxis *keyAxis=0, QCPAxis *valueAxis=0); +protected: +}; + +#endif // QCUSTOMPLOTVECT_H diff --git a/src/Core/Widgets/qlopplots.cpp b/src/Core/Widgets/qlopplots.cpp --- a/src/Core/Widgets/qlopplots.cpp +++ b/src/Core/Widgets/qlopplots.cpp @@ -79,6 +79,7 @@ int QLopPlots::addPlot() if(pid!=-1) { SocExplorerPlot* plot=new SocExplorerPlot(); + plot->setPID(pid); m_plots->insert(pid,plot); QDockWidget* dock = new QDockWidget(); dock->setWidget(plot); diff --git a/src/Core/pythonQtOut/generated_cpp/PyQLop/PyQLop0.cpp b/src/Core/pythonQtOut/generated_cpp/PyQLop/PyQLop0.cpp --- a/src/Core/pythonQtOut/generated_cpp/PyQLop/PyQLop0.cpp +++ b/src/Core/pythonQtOut/generated_cpp/PyQLop/PyQLop0.cpp @@ -4629,7 +4629,7 @@ void PythonQtWrapper_QCPGraph::setErrorP void PythonQtWrapper_QCPGraph::setUseFastVectors(QCPGraph* theWrappedObject, bool useFastVectors) { - ( theWrappedObject->setUseFastVectors(useFastVectors)); +// ( theWrappedObject->setUseFastVectors(useFastVectors)); } QPointF PythonQtWrapper_QCPGraph::upperFillBasePoint(QCPGraph* theWrappedObject, double upperKey) const @@ -4639,7 +4639,7 @@ QPointF PythonQtWrapper_QCPGraph::upper bool PythonQtWrapper_QCPGraph::useFastVectors(QCPGraph* theWrappedObject) const { - return ( theWrappedObject->useFastVectors()); + return true;//( theWrappedObject->useFastVectors()); } diff --git a/src/QCustomPlot/qcustomplot.cpp b/src/QCustomPlot/qcustomplot.cpp --- a/src/QCustomPlot/qcustomplot.cpp +++ b/src/QCustomPlot/qcustomplot.cpp @@ -48,12 +48,12 @@ Creates a new QCPPainter instance and sets default values */ QCPPainter::QCPPainter() : - QPainter(), - mModes(pmDefault), - mIsAntialiasing(false) -{ - // don't setRenderHint(QPainter::NonCosmeticDefautPen) here, because painter isn't active yet and - // a call to begin() will follow + QPainter(), + mModes(pmDefault), + mIsAntialiasing(false) +{ + // don't setRenderHint(QPainter::NonCosmeticDefautPen) here, because painter isn't active yet and + // a call to begin() will follow } /*! @@ -63,13 +63,13 @@ QCPPainter::QCPPainter() : Like \ref begin, this method sets QPainter::NonCosmeticDefaultPen in Qt versions before Qt5. */ QCPPainter::QCPPainter(QPaintDevice *device) : - QPainter(device), - mModes(pmDefault), - mIsAntialiasing(false) + QPainter(device), + mModes(pmDefault), + mIsAntialiasing(false) { #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) // before Qt5, default pens used to be cosmetic if NonCosmeticDefaultPen flag isn't set. So we set it to get consistency across Qt versions. - if (isActive()) - setRenderHint(QPainter::NonCosmeticDefaultPen); + if (isActive()) + setRenderHint(QPainter::NonCosmeticDefaultPen); #endif } @@ -85,9 +85,9 @@ QCPPainter::~QCPPainter() */ void QCPPainter::setPen(const QPen &pen) { - QPainter::setPen(pen); - if (mModes.testFlag(pmNonCosmetic)) - makeNonCosmetic(); + QPainter::setPen(pen); + if (mModes.testFlag(pmNonCosmetic)) + makeNonCosmetic(); } /*! \overload @@ -99,9 +99,9 @@ void QCPPainter::setPen(const QPen &pen) */ void QCPPainter::setPen(const QColor &color) { - QPainter::setPen(color); - if (mModes.testFlag(pmNonCosmetic)) - makeNonCosmetic(); + QPainter::setPen(color); + if (mModes.testFlag(pmNonCosmetic)) + makeNonCosmetic(); } /*! \overload @@ -113,9 +113,9 @@ void QCPPainter::setPen(const QColor &co */ void QCPPainter::setPen(Qt::PenStyle penStyle) { - QPainter::setPen(penStyle); - if (mModes.testFlag(pmNonCosmetic)) - makeNonCosmetic(); + QPainter::setPen(penStyle); + if (mModes.testFlag(pmNonCosmetic)) + makeNonCosmetic(); } /*! \overload @@ -128,10 +128,10 @@ void QCPPainter::setPen(Qt::PenStyle pen */ void QCPPainter::drawLine(const QLineF &line) { - if (mIsAntialiasing || mModes.testFlag(pmVectorized)) - QPainter::drawLine(line); - else - QPainter::drawLine(line.toLine()); + if (mIsAntialiasing || mModes.testFlag(pmVectorized)) + QPainter::drawLine(line); + else + QPainter::drawLine(line.toLine()); } /*! @@ -142,16 +142,16 @@ void QCPPainter::drawLine(const QLineF & */ void QCPPainter::setAntialiasing(bool enabled) { - setRenderHint(QPainter::Antialiasing, enabled); - if (mIsAntialiasing != enabled) - { - mIsAntialiasing = enabled; - if (!mModes.testFlag(pmVectorized)) // antialiasing half-pixel shift only needed for rasterized outputs - { - if (mIsAntialiasing) - translate(0.5, 0.5); - else - translate(-0.5, -0.5); + setRenderHint(QPainter::Antialiasing, enabled); + if (mIsAntialiasing != enabled) + { + mIsAntialiasing = enabled; + if (!mModes.testFlag(pmVectorized)) // antialiasing half-pixel shift only needed for rasterized outputs + { + if (mIsAntialiasing) + translate(0.5, 0.5); + else + translate(-0.5, -0.5); } } } @@ -162,7 +162,7 @@ void QCPPainter::setAntialiasing(bool en */ void QCPPainter::setModes(QCPPainter::PainterModes modes) { - mModes = modes; + mModes = modes; } /*! @@ -178,12 +178,12 @@ void QCPPainter::setModes(QCPPainter::Pa */ bool QCPPainter::begin(QPaintDevice *device) { - bool result = QPainter::begin(device); + bool result = QPainter::begin(device); #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) // before Qt5, default pens used to be cosmetic if NonCosmeticDefaultPen flag isn't set. So we set it to get consistency across Qt versions. - if (result) - setRenderHint(QPainter::NonCosmeticDefaultPen); + if (result) + setRenderHint(QPainter::NonCosmeticDefaultPen); #endif - return result; + return result; } /*! \overload @@ -193,10 +193,10 @@ bool QCPPainter::begin(QPaintDevice *dev */ void QCPPainter::setMode(QCPPainter::PainterMode mode, bool enabled) { - if (!enabled && mModes.testFlag(mode)) - mModes &= ~mode; - else if (enabled && !mModes.testFlag(mode)) - mModes |= mode; + if (!enabled && mModes.testFlag(mode)) + mModes &= ~mode; + else if (enabled && !mModes.testFlag(mode)) + mModes |= mode; } /*! @@ -209,8 +209,8 @@ void QCPPainter::setMode(QCPPainter::Pai */ void QCPPainter::save() { - mAntialiasingStack.push(mIsAntialiasing); - QPainter::save(); + mAntialiasingStack.push(mIsAntialiasing); + QPainter::save(); } /*! @@ -223,11 +223,11 @@ void QCPPainter::save() */ void QCPPainter::restore() { - if (!mAntialiasingStack.isEmpty()) - mIsAntialiasing = mAntialiasingStack.pop(); - else - qDebug() << Q_FUNC_INFO << "Unbalanced save/restore"; - QPainter::restore(); + if (!mAntialiasingStack.isEmpty()) + mIsAntialiasing = mAntialiasingStack.pop(); + else + qDebug() << Q_FUNC_INFO << "Unbalanced save/restore"; + QPainter::restore(); } /*! @@ -236,11 +236,11 @@ void QCPPainter::restore() */ void QCPPainter::makeNonCosmetic() { - if (qFuzzyIsNull(pen().widthF())) - { - QPen p = pen(); - p.setWidth(1); - QPainter::setPen(p); + if (qFuzzyIsNull(pen().widthF())) + { + QPen p = pen(); + p.setWidth(1); + QPainter::setPen(p); } } @@ -340,11 +340,11 @@ void QCPPainter::makeNonCosmetic() from the plottable that uses this scatter style. */ QCPScatterStyle::QCPScatterStyle() : - mSize(6), - mShape(ssNone), - mPen(Qt::NoPen), - mBrush(Qt::NoBrush), - mPenDefined(false) + mSize(6), + mShape(ssNone), + mPen(Qt::NoPen), + mBrush(Qt::NoBrush), + mPenDefined(false) { } @@ -356,11 +356,11 @@ QCPScatterStyle::QCPScatterStyle() : from the plottable that uses this scatter style. */ QCPScatterStyle::QCPScatterStyle(ScatterShape shape, double size) : - mSize(size), - mShape(shape), - mPen(Qt::NoPen), - mBrush(Qt::NoBrush), - mPenDefined(false) + mSize(size), + mShape(shape), + mPen(Qt::NoPen), + mBrush(Qt::NoBrush), + mPenDefined(false) { } @@ -369,11 +369,11 @@ QCPScatterStyle::QCPScatterStyle(Scatter and size to \a size. No brush is defined, i.e. the scatter point will not be filled. */ QCPScatterStyle::QCPScatterStyle(ScatterShape shape, const QColor &color, double size) : - mSize(size), - mShape(shape), - mPen(QPen(color)), - mBrush(Qt::NoBrush), - mPenDefined(true) + mSize(size), + mShape(shape), + mPen(QPen(color)), + mBrush(Qt::NoBrush), + mPenDefined(true) { } @@ -382,11 +382,11 @@ QCPScatterStyle::QCPScatterStyle(Scatter the brush color to \a fill (with a solid pattern), and size to \a size. */ QCPScatterStyle::QCPScatterStyle(ScatterShape shape, const QColor &color, const QColor &fill, double size) : - mSize(size), - mShape(shape), - mPen(QPen(color)), - mBrush(QBrush(fill)), - mPenDefined(true) + mSize(size), + mShape(shape), + mPen(QPen(color)), + mBrush(QBrush(fill)), + mPenDefined(true) { } @@ -406,11 +406,11 @@ QCPScatterStyle::QCPScatterStyle(Scatter wanted. */ QCPScatterStyle::QCPScatterStyle(ScatterShape shape, const QPen &pen, const QBrush &brush, double size) : - mSize(size), - mShape(shape), - mPen(pen), - mBrush(brush), - mPenDefined(pen.style() != Qt::NoPen) + mSize(size), + mShape(shape), + mPen(pen), + mBrush(brush), + mPenDefined(pen.style() != Qt::NoPen) { } @@ -419,12 +419,12 @@ QCPScatterStyle::QCPScatterStyle(Scatter is set to \ref ssPixmap. */ QCPScatterStyle::QCPScatterStyle(const QPixmap &pixmap) : - mSize(5), - mShape(ssPixmap), - mPen(Qt::NoPen), - mBrush(Qt::NoBrush), - mPixmap(pixmap), - mPenDefined(false) + mSize(5), + mShape(ssPixmap), + mPen(Qt::NoPen), + mBrush(Qt::NoBrush), + mPixmap(pixmap), + mPenDefined(false) { } @@ -438,12 +438,12 @@ QCPScatterStyle::QCPScatterStyle(const Q natural size by default. To double the size of the path for example, set \a size to 12. */ QCPScatterStyle::QCPScatterStyle(const QPainterPath &customPath, const QPen &pen, const QBrush &brush, double size) : - mSize(size), - mShape(ssCustom), - mPen(pen), - mBrush(brush), - mCustomPath(customPath), - mPenDefined(pen.style() != Qt::NoPen) + mSize(size), + mShape(ssCustom), + mPen(pen), + mBrush(brush), + mCustomPath(customPath), + mPenDefined(pen.style() != Qt::NoPen) { } @@ -454,7 +454,7 @@ QCPScatterStyle::QCPScatterStyle(const Q */ void QCPScatterStyle::setSize(double size) { - mSize = size; + mSize = size; } /*! @@ -467,7 +467,7 @@ void QCPScatterStyle::setSize(double siz */ void QCPScatterStyle::setShape(QCPScatterStyle::ScatterShape shape) { - mShape = shape; + mShape = shape; } /*! @@ -480,8 +480,8 @@ void QCPScatterStyle::setShape(QCPScatte */ void QCPScatterStyle::setPen(const QPen &pen) { - mPenDefined = true; - mPen = pen; + mPenDefined = true; + mPen = pen; } /*! @@ -492,7 +492,7 @@ void QCPScatterStyle::setPen(const QPen */ void QCPScatterStyle::setBrush(const QBrush &brush) { - mBrush = brush; + mBrush = brush; } /*! @@ -504,8 +504,8 @@ void QCPScatterStyle::setBrush(const QBr */ void QCPScatterStyle::setPixmap(const QPixmap &pixmap) { - setShape(ssPixmap); - mPixmap = pixmap; + setShape(ssPixmap); + mPixmap = pixmap; } /*! @@ -515,8 +515,8 @@ void QCPScatterStyle::setPixmap(const QP */ void QCPScatterStyle::setCustomPath(const QPainterPath &customPath) { - setShape(ssCustom); - mCustomPath = customPath; + setShape(ssCustom); + mCustomPath = customPath; } /*! @@ -530,8 +530,8 @@ void QCPScatterStyle::setCustomPath(cons */ void QCPScatterStyle::applyTo(QCPPainter *painter, const QPen &defaultPen) const { - painter->setPen(mPenDefined ? mPen : defaultPen); - painter->setBrush(mBrush); + painter->setPen(mPenDefined ? mPen : defaultPen); + painter->setBrush(mBrush); } /*! @@ -544,7 +544,7 @@ void QCPScatterStyle::applyTo(QCPPainter */ void QCPScatterStyle::drawShape(QCPPainter *painter, QPointF pos) const { - drawShape(painter, pos.x(), pos.y()); + drawShape(painter, pos.x(), pos.y()); } /*! \overload @@ -552,125 +552,125 @@ void QCPScatterStyle::drawShape(QCPPaint */ void QCPScatterStyle::drawShape(QCPPainter *painter, double x, double y) const { - double w = mSize/2.0; - switch (mShape) + double w = mSize/2.0; + switch (mShape) { case ssNone: break; case ssDot: - { + { painter->drawLine(QPointF(x, y), QPointF(x+0.0001, y)); break; - } + } case ssCross: - { + { painter->drawLine(QLineF(x-w, y-w, x+w, y+w)); painter->drawLine(QLineF(x-w, y+w, x+w, y-w)); break; - } + } case ssPlus: - { + { painter->drawLine(QLineF(x-w, y, x+w, y)); painter->drawLine(QLineF( x, y+w, x, y-w)); break; - } + } case ssCircle: - { + { painter->drawEllipse(QPointF(x , y), w, w); break; - } + } case ssDisc: - { + { QBrush b = painter->brush(); painter->setBrush(painter->pen().color()); painter->drawEllipse(QPointF(x , y), w, w); painter->setBrush(b); break; - } + } case ssSquare: - { + { painter->drawRect(QRectF(x-w, y-w, mSize, mSize)); break; - } + } case ssDiamond: - { + { painter->drawLine(QLineF(x-w, y, x, y-w)); painter->drawLine(QLineF( x, y-w, x+w, y)); painter->drawLine(QLineF(x+w, y, x, y+w)); painter->drawLine(QLineF( x, y+w, x-w, y)); break; - } + } case ssStar: - { + { painter->drawLine(QLineF(x-w, y, x+w, y)); painter->drawLine(QLineF( x, y+w, x, y-w)); painter->drawLine(QLineF(x-w*0.707, y-w*0.707, x+w*0.707, y+w*0.707)); painter->drawLine(QLineF(x-w*0.707, y+w*0.707, x+w*0.707, y-w*0.707)); break; - } + } case ssTriangle: - { + { painter->drawLine(QLineF(x-w, y+0.755*w, x+w, y+0.755*w)); painter->drawLine(QLineF(x+w, y+0.755*w, x, y-0.977*w)); painter->drawLine(QLineF( x, y-0.977*w, x-w, y+0.755*w)); break; - } + } case ssTriangleInverted: - { + { painter->drawLine(QLineF(x-w, y-0.755*w, x+w, y-0.755*w)); painter->drawLine(QLineF(x+w, y-0.755*w, x, y+0.977*w)); painter->drawLine(QLineF( x, y+0.977*w, x-w, y-0.755*w)); break; - } + } case ssCrossSquare: - { + { painter->drawLine(QLineF(x-w, y-w, x+w*0.95, y+w*0.95)); painter->drawLine(QLineF(x-w, y+w*0.95, x+w*0.95, y-w)); painter->drawRect(QRectF(x-w, y-w, mSize, mSize)); break; - } + } case ssPlusSquare: - { + { painter->drawLine(QLineF(x-w, y, x+w*0.95, y)); painter->drawLine(QLineF( x, y+w, x, y-w)); painter->drawRect(QRectF(x-w, y-w, mSize, mSize)); break; - } + } case ssCrossCircle: - { + { painter->drawLine(QLineF(x-w*0.707, y-w*0.707, x+w*0.670, y+w*0.670)); painter->drawLine(QLineF(x-w*0.707, y+w*0.670, x+w*0.670, y-w*0.707)); painter->drawEllipse(QPointF(x, y), w, w); break; - } + } case ssPlusCircle: - { + { painter->drawLine(QLineF(x-w, y, x+w, y)); painter->drawLine(QLineF( x, y+w, x, y-w)); painter->drawEllipse(QPointF(x, y), w, w); break; - } + } case ssPeace: - { + { painter->drawLine(QLineF(x, y-w, x, y+w)); painter->drawLine(QLineF(x, y, x-w*0.707, y+w*0.707)); painter->drawLine(QLineF(x, y, x+w*0.707, y+w*0.707)); painter->drawEllipse(QPointF(x, y), w, w); break; - } + } case ssPixmap: - { + { painter->drawPixmap(x-mPixmap.width()*0.5, y-mPixmap.height()*0.5, mPixmap); break; - } + } case ssCustom: - { + { QTransform oldTransform = painter->transform(); painter->translate(x, y); painter->scale(mSize/6.0, mSize/6.0); painter->drawPath(mCustomPath); painter->setTransform(oldTransform); break; - } + } } } @@ -748,28 +748,28 @@ void QCPScatterStyle::drawShape(QCPPaint This check is only performed by \ref QCustomPlot::addLayer. */ QCPLayer::QCPLayer(QCustomPlot *parentPlot, const QString &layerName) : - QObject(parentPlot), - mParentPlot(parentPlot), - mName(layerName), - mIndex(-1), // will be set to a proper value by the QCustomPlot layer creation function - mVisible(true) -{ - // Note: no need to make sure layerName is unique, because layer - // management is done with QCustomPlot functions. + QObject(parentPlot), + mParentPlot(parentPlot), + mName(layerName), + mIndex(-1), // will be set to a proper value by the QCustomPlot layer creation function + mVisible(true) +{ + // Note: no need to make sure layerName is unique, because layer + // management is done with QCustomPlot functions. } QCPLayer::~QCPLayer() { - // If child layerables are still on this layer, detach them, so they don't try to reach back to this - // then invalid layer once they get deleted/moved themselves. This only happens when layers are deleted - // directly, like in the QCustomPlot destructor. (The regular layer removal procedure for the user is to - // call QCustomPlot::removeLayer, which moves all layerables off this layer before deleting it.) - - while (!mChildren.isEmpty()) - mChildren.last()->setLayer(0); // removes itself from mChildren via removeChild() - - if (mParentPlot->currentLayer() == this) - qDebug() << Q_FUNC_INFO << "The parent plot's mCurrentLayer will be a dangling pointer. Should have been set to a valid layer or 0 beforehand."; + // If child layerables are still on this layer, detach them, so they don't try to reach back to this + // then invalid layer once they get deleted/moved themselves. This only happens when layers are deleted + // directly, like in the QCustomPlot destructor. (The regular layer removal procedure for the user is to + // call QCustomPlot::removeLayer, which moves all layerables off this layer before deleting it.) + + while (!mChildren.isEmpty()) + mChildren.last()->setLayer(0); // removes itself from mChildren via removeChild() + + if (mParentPlot->currentLayer() == this) + qDebug() << Q_FUNC_INFO << "The parent plot's mCurrentLayer will be a dangling pointer. Should have been set to a valid layer or 0 beforehand."; } /*! @@ -782,7 +782,7 @@ QCPLayer::~QCPLayer() */ void QCPLayer::setVisible(bool visible) { - mVisible = visible; + mVisible = visible; } /*! \internal @@ -797,14 +797,14 @@ void QCPLayer::setVisible(bool visible) */ void QCPLayer::addChild(QCPLayerable *layerable, bool prepend) { - if (!mChildren.contains(layerable)) - { - if (prepend) - mChildren.prepend(layerable); - else - mChildren.append(layerable); - } else - qDebug() << Q_FUNC_INFO << "layerable is already child of this layer" << reinterpret_cast(layerable); + if (!mChildren.contains(layerable)) + { + if (prepend) + mChildren.prepend(layerable); + else + mChildren.append(layerable); + } else + qDebug() << Q_FUNC_INFO << "layerable is already child of this layer" << reinterpret_cast(layerable); } /*! \internal @@ -818,8 +818,8 @@ void QCPLayer::addChild(QCPLayerable *la */ void QCPLayer::removeChild(QCPLayerable *layerable) { - if (!mChildren.removeOne(layerable)) - qDebug() << Q_FUNC_INFO << "layerable is not child of this layer" << reinterpret_cast(layerable); + if (!mChildren.removeOne(layerable)) + qDebug() << Q_FUNC_INFO << "layerable is not child of this layer" << reinterpret_cast(layerable); } @@ -929,28 +929,28 @@ void QCPLayer::removeChild(QCPLayerable not become the QObject-parent (for memory management) of this layerable, \a plot does. */ QCPLayerable::QCPLayerable(QCustomPlot *plot, QString targetLayer, QCPLayerable *parentLayerable) : - QObject(plot), - mVisible(true), - mParentPlot(plot), - mParentLayerable(parentLayerable), - mLayer(0), - mAntialiased(true) -{ - if (mParentPlot) - { - if (targetLayer.isEmpty()) - setLayer(mParentPlot->currentLayer()); - else if (!setLayer(targetLayer)) - qDebug() << Q_FUNC_INFO << "setting QCPlayerable initial layer to" << targetLayer << "failed."; + QObject(plot), + mVisible(true), + mParentPlot(plot), + mParentLayerable(parentLayerable), + mLayer(0), + mAntialiased(true) +{ + if (mParentPlot) + { + if (targetLayer.isEmpty()) + setLayer(mParentPlot->currentLayer()); + else if (!setLayer(targetLayer)) + qDebug() << Q_FUNC_INFO << "setting QCPlayerable initial layer to" << targetLayer << "failed."; } } QCPLayerable::~QCPLayerable() { - if (mLayer) - { - mLayer->removeChild(this); - mLayer = 0; + if (mLayer) + { + mLayer->removeChild(this); + mLayer = 0; } } @@ -961,7 +961,7 @@ QCPLayerable::~QCPLayerable() */ void QCPLayerable::setVisible(bool on) { - mVisible = on; + mVisible = on; } /*! @@ -972,7 +972,7 @@ void QCPLayerable::setVisible(bool on) */ bool QCPLayerable::setLayer(QCPLayer *layer) { - return moveToLayer(layer, false); + return moveToLayer(layer, false); } /*! \overload @@ -982,18 +982,18 @@ bool QCPLayerable::setLayer(QCPLayer *la */ bool QCPLayerable::setLayer(const QString &layerName) { - if (!mParentPlot) - { - qDebug() << Q_FUNC_INFO << "no parent QCustomPlot set"; - return false; - } - if (QCPLayer *layer = mParentPlot->layer(layerName)) - { - return setLayer(layer); - } else - { - qDebug() << Q_FUNC_INFO << "there is no layer with name" << layerName; - return false; + if (!mParentPlot) + { + qDebug() << Q_FUNC_INFO << "no parent QCustomPlot set"; + return false; + } + if (QCPLayer *layer = mParentPlot->layer(layerName)) + { + return setLayer(layer); + } else + { + qDebug() << Q_FUNC_INFO << "there is no layer with name" << layerName; + return false; } } @@ -1005,7 +1005,7 @@ bool QCPLayerable::setLayer(const QStrin */ void QCPLayerable::setAntialiased(bool enabled) { - mAntialiased = enabled; + mAntialiased = enabled; } /*! @@ -1023,7 +1023,7 @@ void QCPLayerable::setAntialiased(bool e */ bool QCPLayerable::realVisibility() const { - return mVisible && (!mLayer || mLayer->visible()) && (!mParentLayerable || mParentLayerable.data()->realVisibility()); + return mVisible && (!mLayer || mLayer->visible()) && (!mParentLayerable || mParentLayerable.data()->realVisibility()); } /*! @@ -1062,10 +1062,10 @@ bool QCPLayerable::realVisibility() cons */ double QCPLayerable::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - Q_UNUSED(pos) - Q_UNUSED(onlySelectable) - Q_UNUSED(details) - return -1.0; + Q_UNUSED(pos) + Q_UNUSED(onlySelectable) + Q_UNUSED(details) + return -1.0; } /*! \internal @@ -1087,17 +1087,17 @@ double QCPLayerable::selectTest(const QP */ void QCPLayerable::initializeParentPlot(QCustomPlot *parentPlot) { - if (mParentPlot) - { - qDebug() << Q_FUNC_INFO << "called with mParentPlot already initialized"; - return; - } - - if (!parentPlot) - qDebug() << Q_FUNC_INFO << "called with parentPlot zero"; - - mParentPlot = parentPlot; - parentPlotInitialized(mParentPlot); + if (mParentPlot) + { + qDebug() << Q_FUNC_INFO << "called with mParentPlot already initialized"; + return; + } + + if (!parentPlot) + qDebug() << Q_FUNC_INFO << "called with parentPlot zero"; + + mParentPlot = parentPlot; + parentPlotInitialized(mParentPlot); } /*! \internal @@ -1113,7 +1113,7 @@ void QCPLayerable::initializeParentPlot( */ void QCPLayerable::setParentLayerable(QCPLayerable *parentLayerable) { - mParentLayerable = parentLayerable; + mParentLayerable = parentLayerable; } /*! \internal @@ -1126,26 +1126,26 @@ void QCPLayerable::setParentLayerable(QC */ bool QCPLayerable::moveToLayer(QCPLayer *layer, bool prepend) { - if (layer && !mParentPlot) - { - qDebug() << Q_FUNC_INFO << "no parent QCustomPlot set"; - return false; - } - if (layer && layer->parentPlot() != mParentPlot) - { - qDebug() << Q_FUNC_INFO << "layer" << layer->name() << "is not in same QCustomPlot as this layerable"; - return false; - } - - QCPLayer *oldLayer = mLayer; - if (mLayer) - mLayer->removeChild(this); - mLayer = layer; - if (mLayer) - mLayer->addChild(this, prepend); - if (mLayer != oldLayer) - emit layerChanged(mLayer); - return true; + if (layer && !mParentPlot) + { + qDebug() << Q_FUNC_INFO << "no parent QCustomPlot set"; + return false; + } + if (layer && layer->parentPlot() != mParentPlot) + { + qDebug() << Q_FUNC_INFO << "layer" << layer->name() << "is not in same QCustomPlot as this layerable"; + return false; + } + + QCPLayer *oldLayer = mLayer; + if (mLayer) + mLayer->removeChild(this); + mLayer = layer; + if (mLayer) + mLayer->addChild(this, prepend); + if (mLayer != oldLayer) + emit layerChanged(mLayer); + return true; } /*! \internal @@ -1157,12 +1157,12 @@ bool QCPLayerable::moveToLayer(QCPLayer */ void QCPLayerable::applyAntialiasingHint(QCPPainter *painter, bool localAntialiased, QCP::AntialiasedElement overrideElement) const { - if (mParentPlot && mParentPlot->notAntialiasedElements().testFlag(overrideElement)) - painter->setAntialiasing(false); - else if (mParentPlot && mParentPlot->antialiasedElements().testFlag(overrideElement)) - painter->setAntialiasing(true); - else - painter->setAntialiasing(localAntialiased); + if (mParentPlot && mParentPlot->notAntialiasedElements().testFlag(overrideElement)) + painter->setAntialiasing(false); + else if (mParentPlot && mParentPlot->antialiasedElements().testFlag(overrideElement)) + painter->setAntialiasing(true); + else + painter->setAntialiasing(localAntialiased); } /*! \internal @@ -1183,7 +1183,7 @@ void QCPLayerable::applyAntialiasingHint */ void QCPLayerable::parentPlotInitialized(QCustomPlot *parentPlot) { - Q_UNUSED(parentPlot) + Q_UNUSED(parentPlot) } /*! \internal @@ -1199,7 +1199,7 @@ void QCPLayerable::parentPlotInitialized */ QCP::Interaction QCPLayerable::selectionCategory() const { - return QCP::iSelectOther; + return QCP::iSelectOther; } /*! \internal @@ -1213,10 +1213,10 @@ QCP::Interaction QCPLayerable::selection */ QRect QCPLayerable::clipRect() const { - if (mParentPlot) - return mParentPlot->viewport(); - else - return QRect(); + if (mParentPlot) + return mParentPlot->viewport(); + else + return QRect(); } /*! \internal @@ -1249,10 +1249,10 @@ QRect QCPLayerable::clipRect() const */ void QCPLayerable::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) { - Q_UNUSED(event) - Q_UNUSED(additive) - Q_UNUSED(details) - Q_UNUSED(selectionStateChanged) + Q_UNUSED(event) + Q_UNUSED(additive) + Q_UNUSED(details) + Q_UNUSED(selectionStateChanged) } /*! \internal @@ -1269,7 +1269,7 @@ void QCPLayerable::selectEvent(QMouseEve */ void QCPLayerable::deselectEvent(bool *selectionStateChanged) { - Q_UNUSED(selectionStateChanged) + Q_UNUSED(selectionStateChanged) } @@ -1307,8 +1307,8 @@ const double QCPRange::maxRange = 1e250; Constructs a range with \a lower and \a upper set to zero. */ QCPRange::QCPRange() : - lower(0), - upper(0) + lower(0), + upper(0) { } @@ -1316,10 +1316,10 @@ QCPRange::QCPRange() : Constructs a range with the specified \a lower and \a upper values. */ QCPRange::QCPRange(double lower, double upper) : - lower(lower), - upper(upper) -{ - normalize(); + lower(lower), + upper(upper) +{ + normalize(); } /*! @@ -1327,7 +1327,7 @@ QCPRange::QCPRange(double lower, double */ double QCPRange::size() const { - return upper-lower; + return upper-lower; } /*! @@ -1335,7 +1335,7 @@ double QCPRange::size() const */ double QCPRange::center() const { - return (upper+lower)*0.5; + return (upper+lower)*0.5; } /*! @@ -1344,8 +1344,8 @@ double QCPRange::center() const */ void QCPRange::normalize() { - if (lower > upper) - qSwap(lower, upper); + if (lower > upper) + qSwap(lower, upper); } /*! @@ -1358,10 +1358,10 @@ void QCPRange::normalize() */ void QCPRange::expand(const QCPRange &otherRange) { - if (lower > otherRange.lower) - lower = otherRange.lower; - if (upper < otherRange.upper) - upper = otherRange.upper; + if (lower > otherRange.lower) + lower = otherRange.lower; + if (upper < otherRange.upper) + upper = otherRange.upper; } @@ -1373,9 +1373,9 @@ void QCPRange::expand(const QCPRange &ot */ QCPRange QCPRange::expanded(const QCPRange &otherRange) const { - QCPRange result = *this; - result.expand(otherRange); - return result; + QCPRange result = *this; + result.expand(otherRange); + return result; } /*! @@ -1392,47 +1392,47 @@ QCPRange QCPRange::expanded(const QCPRan */ QCPRange QCPRange::sanitizedForLogScale() const { - double rangeFac = 1e-3; - QCPRange sanitizedRange(lower, upper); - sanitizedRange.normalize(); - // can't have range spanning negative and positive values in log plot, so change range to fix it - //if (qFuzzyCompare(sanitizedRange.lower+1, 1) && !qFuzzyCompare(sanitizedRange.upper+1, 1)) - if (sanitizedRange.lower == 0.0 && sanitizedRange.upper != 0.0) - { - // case lower is 0 - if (rangeFac < sanitizedRange.upper*rangeFac) - sanitizedRange.lower = rangeFac; - else - sanitizedRange.lower = sanitizedRange.upper*rangeFac; + double rangeFac = 1e-3; + QCPRange sanitizedRange(lower, upper); + sanitizedRange.normalize(); + // can't have range spanning negative and positive values in log plot, so change range to fix it + //if (qFuzzyCompare(sanitizedRange.lower+1, 1) && !qFuzzyCompare(sanitizedRange.upper+1, 1)) + if (sanitizedRange.lower == 0.0 && sanitizedRange.upper != 0.0) + { + // case lower is 0 + if (rangeFac < sanitizedRange.upper*rangeFac) + sanitizedRange.lower = rangeFac; + else + sanitizedRange.lower = sanitizedRange.upper*rangeFac; } //else if (!qFuzzyCompare(lower+1, 1) && qFuzzyCompare(upper+1, 1)) - else if (sanitizedRange.lower != 0.0 && sanitizedRange.upper == 0.0) - { - // case upper is 0 - if (-rangeFac > sanitizedRange.lower*rangeFac) - sanitizedRange.upper = -rangeFac; - else - sanitizedRange.upper = sanitizedRange.lower*rangeFac; + else if (sanitizedRange.lower != 0.0 && sanitizedRange.upper == 0.0) + { + // case upper is 0 + if (-rangeFac > sanitizedRange.lower*rangeFac) + sanitizedRange.upper = -rangeFac; + else + sanitizedRange.upper = sanitizedRange.lower*rangeFac; } else if (sanitizedRange.lower < 0 && sanitizedRange.upper > 0) { - // find out whether negative or positive interval is wider to decide which sign domain will be chosen - if (-sanitizedRange.lower > sanitizedRange.upper) - { - // negative is wider, do same as in case upper is 0 - if (-rangeFac > sanitizedRange.lower*rangeFac) - sanitizedRange.upper = -rangeFac; - else - sanitizedRange.upper = sanitizedRange.lower*rangeFac; + // find out whether negative or positive interval is wider to decide which sign domain will be chosen + if (-sanitizedRange.lower > sanitizedRange.upper) + { + // negative is wider, do same as in case upper is 0 + if (-rangeFac > sanitizedRange.lower*rangeFac) + sanitizedRange.upper = -rangeFac; + else + sanitizedRange.upper = sanitizedRange.lower*rangeFac; } else { - // positive is wider, do same as in case lower is 0 - if (rangeFac < sanitizedRange.upper*rangeFac) - sanitizedRange.lower = rangeFac; - else - sanitizedRange.lower = sanitizedRange.upper*rangeFac; - } - } - // due to normalization, case lower>0 && upper<0 should never occur, because that implies upper0 && upper<0 should never occur, because that implies upper= lower && value <= upper; + return value >= lower && value <= upper; } /*! @@ -1464,17 +1464,17 @@ bool QCPRange::contains(double value) co */ bool QCPRange::validRange(double lower, double upper) { - /* + /* return (lower > -maxRange && upper < maxRange && qAbs(lower-upper) > minRange && (lower < -minRange || lower > minRange) && (upper < -minRange || upper > minRange)); */ - return (lower > -maxRange && - upper < maxRange && - qAbs(lower-upper) > minRange && - qAbs(lower-upper) < maxRange); + return (lower > -maxRange && + upper < maxRange && + qAbs(lower-upper) > minRange && + qAbs(lower-upper) < maxRange); } /*! @@ -1488,7 +1488,7 @@ bool QCPRange::validRange(double lower, */ bool QCPRange::validRange(const QCPRange &range) { - /* + /* return (range.lower > -maxRange && range.upper < maxRange && qAbs(range.lower-range.upper) > minRange && @@ -1496,10 +1496,10 @@ bool QCPRange::validRange(const QCPRange (range.lower < -minRange || range.lower > minRange) && (range.upper < -minRange || range.upper > minRange)); */ - return (range.lower > -maxRange && - range.upper < maxRange && - qAbs(range.lower-range.upper) > minRange && - qAbs(range.lower-range.upper) < maxRange); + return (range.lower > -maxRange && + range.upper < maxRange && + qAbs(range.lower-range.upper) > minRange && + qAbs(range.lower-range.upper) < maxRange); } @@ -1557,18 +1557,18 @@ bool QCPRange::validRange(const QCPRange Creates a new QCPMarginGroup instance in \a parentPlot. */ QCPMarginGroup::QCPMarginGroup(QCustomPlot *parentPlot) : - QObject(parentPlot), - mParentPlot(parentPlot) -{ - mChildren.insert(QCP::msLeft, QList()); - mChildren.insert(QCP::msRight, QList()); - mChildren.insert(QCP::msTop, QList()); - mChildren.insert(QCP::msBottom, QList()); + QObject(parentPlot), + mParentPlot(parentPlot) +{ + mChildren.insert(QCP::msLeft, QList()); + mChildren.insert(QCP::msRight, QList()); + mChildren.insert(QCP::msTop, QList()); + mChildren.insert(QCP::msBottom, QList()); } QCPMarginGroup::~QCPMarginGroup() { - clear(); + clear(); } /*! @@ -1577,14 +1577,14 @@ QCPMarginGroup::~QCPMarginGroup() */ bool QCPMarginGroup::isEmpty() const { - QHashIterator > it(mChildren); - while (it.hasNext()) - { - it.next(); - if (!it.value().isEmpty()) - return false; - } - return true; + QHashIterator > it(mChildren); + while (it.hasNext()) + { + it.next(); + if (!it.value().isEmpty()) + return false; + } + return true; } /*! @@ -1593,14 +1593,14 @@ bool QCPMarginGroup::isEmpty() const */ void QCPMarginGroup::clear() { - // make all children remove themselves from this margin group: - QHashIterator > it(mChildren); - while (it.hasNext()) - { - it.next(); - const QList elements = it.value(); - for (int i=elements.size()-1; i>=0; --i) - elements.at(i)->setMarginGroup(it.key(), 0); // removes itself from mChildren via removeChild + // make all children remove themselves from this margin group: + QHashIterator > it(mChildren); + while (it.hasNext()) + { + it.next(); + const QList elements = it.value(); + for (int i=elements.size()-1; i>=0; --i) + elements.at(i)->setMarginGroup(it.key(), 0); // removes itself from mChildren via removeChild } } @@ -1616,18 +1616,18 @@ void QCPMarginGroup::clear() */ int QCPMarginGroup::commonMargin(QCP::MarginSide side) const { - // query all automatic margins of the layout elements in this margin group side and find maximum: - int result = 0; - const QList elements = mChildren.value(side); - for (int i=0; iautoMargins().testFlag(side)) - continue; - int m = qMax(elements.at(i)->calculateAutoMargin(side), QCP::getMarginValue(elements.at(i)->minimumMargins(), side)); - if (m > result) - result = m; - } - return result; + // query all automatic margins of the layout elements in this margin group side and find maximum: + int result = 0; + const QList elements = mChildren.value(side); + for (int i=0; iautoMargins().testFlag(side)) + continue; + int m = qMax(elements.at(i)->calculateAutoMargin(side), QCP::getMarginValue(elements.at(i)->minimumMargins(), side)); + if (m > result) + result = m; + } + return result; } /*! \internal @@ -1638,10 +1638,10 @@ int QCPMarginGroup::commonMargin(QCP::Ma */ void QCPMarginGroup::addChild(QCP::MarginSide side, QCPLayoutElement *element) { - if (!mChildren[side].contains(element)) - mChildren[side].append(element); - else - qDebug() << Q_FUNC_INFO << "element is already child of this margin group side" << reinterpret_cast(element); + if (!mChildren[side].contains(element)) + mChildren[side].append(element); + else + qDebug() << Q_FUNC_INFO << "element is already child of this margin group side" << reinterpret_cast(element); } /*! \internal @@ -1652,8 +1652,8 @@ void QCPMarginGroup::addChild(QCP::Margi */ void QCPMarginGroup::removeChild(QCP::MarginSide side, QCPLayoutElement *element) { - if (!mChildren[side].removeOne(element)) - qDebug() << Q_FUNC_INFO << "element is not child of this margin group side" << reinterpret_cast(element); + if (!mChildren[side].removeOne(element)) + qDebug() << Q_FUNC_INFO << "element is not child of this margin group side" << reinterpret_cast(element); } @@ -1742,24 +1742,24 @@ void QCPMarginGroup::removeChild(QCP::Ma Creates an instance of QCPLayoutElement and sets default values. */ QCPLayoutElement::QCPLayoutElement(QCustomPlot *parentPlot) : - QCPLayerable(parentPlot), // parenthood is changed as soon as layout element gets inserted into a layout (except for top level layout) - mParentLayout(0), - mMinimumSize(), - mMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX), - mRect(0, 0, 0, 0), - mOuterRect(0, 0, 0, 0), - mMargins(0, 0, 0, 0), - mMinimumMargins(0, 0, 0, 0), - mAutoMargins(QCP::msAll) + QCPLayerable(parentPlot), // parenthood is changed as soon as layout element gets inserted into a layout (except for top level layout) + mParentLayout(0), + mMinimumSize(), + mMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX), + mRect(0, 0, 0, 0), + mOuterRect(0, 0, 0, 0), + mMargins(0, 0, 0, 0), + mMinimumMargins(0, 0, 0, 0), + mAutoMargins(QCP::msAll) { } QCPLayoutElement::~QCPLayoutElement() { - setMarginGroup(QCP::msAll, 0); // unregister at margin groups, if there are any - // unregister at layout: - if (qobject_cast(mParentLayout)) // the qobject_cast is just a safeguard in case the layout forgets to call clear() in its dtor and this dtor is called by QObject dtor - mParentLayout->take(this); + setMarginGroup(QCP::msAll, 0); // unregister at margin groups, if there are any + // unregister at layout: + if (qobject_cast(mParentLayout)) // the qobject_cast is just a safeguard in case the layout forgets to call clear() in its dtor and this dtor is called by QObject dtor + mParentLayout->take(this); } /*! @@ -1775,10 +1775,10 @@ QCPLayoutElement::~QCPLayoutElement() */ void QCPLayoutElement::setOuterRect(const QRect &rect) { - if (mOuterRect != rect) - { - mOuterRect = rect; - mRect = mOuterRect.adjusted(mMargins.left(), mMargins.top(), -mMargins.right(), -mMargins.bottom()); + if (mOuterRect != rect) + { + mOuterRect = rect; + mRect = mOuterRect.adjusted(mMargins.left(), mMargins.top(), -mMargins.right(), -mMargins.bottom()); } } @@ -1795,10 +1795,10 @@ void QCPLayoutElement::setOuterRect(cons */ void QCPLayoutElement::setMargins(const QMargins &margins) { - if (mMargins != margins) - { - mMargins = margins; - mRect = mOuterRect.adjusted(mMargins.left(), mMargins.top(), -mMargins.right(), -mMargins.bottom()); + if (mMargins != margins) + { + mMargins = margins; + mRect = mOuterRect.adjusted(mMargins.left(), mMargins.top(), -mMargins.right(), -mMargins.bottom()); } } @@ -1813,9 +1813,9 @@ void QCPLayoutElement::setMargins(const */ void QCPLayoutElement::setMinimumMargins(const QMargins &margins) { - if (mMinimumMargins != margins) - { - mMinimumMargins = margins; + if (mMinimumMargins != margins) + { + mMinimumMargins = margins; } } @@ -1831,7 +1831,7 @@ void QCPLayoutElement::setMinimumMargins */ void QCPLayoutElement::setAutoMargins(QCP::MarginSides sides) { - mAutoMargins = sides; + mAutoMargins = sides; } /*! @@ -1845,11 +1845,11 @@ void QCPLayoutElement::setAutoMargins(QC */ void QCPLayoutElement::setMinimumSize(const QSize &size) { - if (mMinimumSize != size) - { - mMinimumSize = size; - if (mParentLayout) - mParentLayout->sizeConstraintsChanged(); + if (mMinimumSize != size) + { + mMinimumSize = size; + if (mParentLayout) + mParentLayout->sizeConstraintsChanged(); } } @@ -1859,7 +1859,7 @@ void QCPLayoutElement::setMinimumSize(co */ void QCPLayoutElement::setMinimumSize(int width, int height) { - setMinimumSize(QSize(width, height)); + setMinimumSize(QSize(width, height)); } /*! @@ -1868,11 +1868,11 @@ void QCPLayoutElement::setMinimumSize(in */ void QCPLayoutElement::setMaximumSize(const QSize &size) { - if (mMaximumSize != size) - { - mMaximumSize = size; - if (mParentLayout) - mParentLayout->sizeConstraintsChanged(); + if (mMaximumSize != size) + { + mMaximumSize = size; + if (mParentLayout) + mParentLayout->sizeConstraintsChanged(); } } @@ -1882,7 +1882,7 @@ void QCPLayoutElement::setMaximumSize(co */ void QCPLayoutElement::setMaximumSize(int width, int height) { - setMaximumSize(QSize(width, height)); + setMaximumSize(QSize(width, height)); } /*! @@ -1898,28 +1898,28 @@ void QCPLayoutElement::setMaximumSize(in */ void QCPLayoutElement::setMarginGroup(QCP::MarginSides sides, QCPMarginGroup *group) { - QVector sideVector; - if (sides.testFlag(QCP::msLeft)) sideVector.append(QCP::msLeft); - if (sides.testFlag(QCP::msRight)) sideVector.append(QCP::msRight); - if (sides.testFlag(QCP::msTop)) sideVector.append(QCP::msTop); - if (sides.testFlag(QCP::msBottom)) sideVector.append(QCP::msBottom); - - for (int i=0; iremoveChild(side, this); - - if (!group) // if setting to 0, remove hash entry. Else set hash entry to new group and register there - { - mMarginGroups.remove(side); + QVector sideVector; + if (sides.testFlag(QCP::msLeft)) sideVector.append(QCP::msLeft); + if (sides.testFlag(QCP::msRight)) sideVector.append(QCP::msRight); + if (sides.testFlag(QCP::msTop)) sideVector.append(QCP::msTop); + if (sides.testFlag(QCP::msBottom)) sideVector.append(QCP::msBottom); + + for (int i=0; iremoveChild(side, this); + + if (!group) // if setting to 0, remove hash entry. Else set hash entry to new group and register there + { + mMarginGroups.remove(side); } else // setting to a new group { - mMarginGroups[side] = group; - group->addChild(side, this); + mMarginGroups[side] = group; + group->addChild(side, this); } } } @@ -1939,26 +1939,26 @@ void QCPLayoutElement::setMarginGroup(QC */ void QCPLayoutElement::update(UpdatePhase phase) { - if (phase == upMargins) - { - if (mAutoMargins != QCP::msNone) - { - // set the margins of this layout element according to automatic margin calculation, either directly or via a margin group: - QMargins newMargins = mMargins; - foreach (QCP::MarginSide side, QList() << QCP::msLeft << QCP::msRight << QCP::msTop << QCP::msBottom) - { - if (mAutoMargins.testFlag(side)) // this side's margin shall be calculated automatically + if (phase == upMargins) + { + if (mAutoMargins != QCP::msNone) + { + // set the margins of this layout element according to automatic margin calculation, either directly or via a margin group: + QMargins newMargins = mMargins; + foreach (QCP::MarginSide side, QList() << QCP::msLeft << QCP::msRight << QCP::msTop << QCP::msBottom) + { + if (mAutoMargins.testFlag(side)) // this side's margin shall be calculated automatically { - if (mMarginGroups.contains(side)) - QCP::setMarginValue(newMargins, side, mMarginGroups[side]->commonMargin(side)); // this side is part of a margin group, so get the margin value from that group - else - QCP::setMarginValue(newMargins, side, calculateAutoMargin(side)); // this side is not part of a group, so calculate the value directly - // apply minimum margin restrictions: - if (QCP::getMarginValue(newMargins, side) < QCP::getMarginValue(mMinimumMargins, side)) - QCP::setMarginValue(newMargins, side, QCP::getMarginValue(mMinimumMargins, side)); + if (mMarginGroups.contains(side)) + QCP::setMarginValue(newMargins, side, mMarginGroups[side]->commonMargin(side)); // this side is part of a margin group, so get the margin value from that group + else + QCP::setMarginValue(newMargins, side, calculateAutoMargin(side)); // this side is not part of a group, so calculate the value directly + // apply minimum margin restrictions: + if (QCP::getMarginValue(newMargins, side) < QCP::getMarginValue(mMinimumMargins, side)) + QCP::setMarginValue(newMargins, side, QCP::getMarginValue(mMinimumMargins, side)); } } - setMargins(newMargins); + setMargins(newMargins); } } } @@ -1972,7 +1972,7 @@ void QCPLayoutElement::update(UpdatePhas */ QSize QCPLayoutElement::minimumSizeHint() const { - return mMinimumSize; + return mMinimumSize; } /*! @@ -1984,7 +1984,7 @@ QSize QCPLayoutElement::minimumSizeHint( */ QSize QCPLayoutElement::maximumSizeHint() const { - return mMaximumSize; + return mMaximumSize; } /*! @@ -1996,8 +1996,8 @@ QSize QCPLayoutElement::maximumSizeHint( */ QList QCPLayoutElement::elements(bool recursive) const { - Q_UNUSED(recursive) - return QList(); + Q_UNUSED(recursive) + return QList(); } /*! @@ -2013,22 +2013,22 @@ QList QCPLayoutElemen */ double QCPLayoutElement::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - Q_UNUSED(details) - - if (onlySelectable) - return -1; - - if (QRectF(mOuterRect).contains(pos)) - { - if (mParentPlot) - return mParentPlot->selectionTolerance()*0.99; - else - { - qDebug() << Q_FUNC_INFO << "parent plot not defined"; - return -1; - } - } else - return -1; + Q_UNUSED(details) + + if (onlySelectable) + return -1; + + if (QRectF(mOuterRect).contains(pos)) + { + if (mParentPlot) + return mParentPlot->selectionTolerance()*0.99; + else + { + qDebug() << Q_FUNC_INFO << "parent plot not defined"; + return -1; + } + } else + return -1; } /*! \internal @@ -2038,10 +2038,10 @@ double QCPLayoutElement::selectTest(cons */ void QCPLayoutElement::parentPlotInitialized(QCustomPlot *parentPlot) { - foreach (QCPLayoutElement* el, elements(false)) - { - if (!el->parentPlot()) - el->initializeParentPlot(parentPlot); + foreach (QCPLayoutElement* el, elements(false)) + { + if (!el->parentPlot()) + el->initializeParentPlot(parentPlot); } } @@ -2056,7 +2056,7 @@ void QCPLayoutElement::parentPlotInitial */ int QCPLayoutElement::calculateAutoMargin(QCP::MarginSide side) { - return qMax(QCP::getMarginValue(mMargins, side), QCP::getMarginValue(mMinimumMargins, side)); + return qMax(QCP::getMarginValue(mMargins, side), QCP::getMarginValue(mMinimumMargins, side)); } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -2150,40 +2150,40 @@ QCPLayout::QCPLayout() */ void QCPLayout::update(UpdatePhase phase) { - QCPLayoutElement::update(phase); - - // set child element rects according to layout: - if (phase == upLayout) - updateLayout(); - - // propagate update call to child elements: - const int elCount = elementCount(); - for (int i=0; iupdate(phase); + QCPLayoutElement::update(phase); + + // set child element rects according to layout: + if (phase == upLayout) + updateLayout(); + + // propagate update call to child elements: + const int elCount = elementCount(); + for (int i=0; iupdate(phase); } } /* inherits documentation from base class */ QList QCPLayout::elements(bool recursive) const { - const int c = elementCount(); - QList result; + const int c = elementCount(); + QList result; #if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) - result.reserve(c); + result.reserve(c); #endif - for (int i=0; ielements(recursive); - } - } - return result; + for (int i=0; ielements(recursive); + } + } + return result; } /*! @@ -2208,12 +2208,12 @@ void QCPLayout::simplify() */ bool QCPLayout::removeAt(int index) { - if (QCPLayoutElement *el = takeAt(index)) - { - delete el; - return true; - } else - return false; + if (QCPLayoutElement *el = takeAt(index)) + { + delete el; + return true; + } else + return false; } /*! @@ -2227,12 +2227,12 @@ bool QCPLayout::removeAt(int index) */ bool QCPLayout::remove(QCPLayoutElement *element) { - if (take(element)) - { - delete element; - return true; - } else - return false; + if (take(element)) + { + delete element; + return true; + } else + return false; } /*! @@ -2242,12 +2242,12 @@ bool QCPLayout::remove(QCPLayoutElement */ void QCPLayout::clear() { - for (int i=elementCount()-1; i>=0; --i) - { - if (elementAt(i)) - removeAt(i); - } - simplify(); + for (int i=elementCount()-1; i>=0; --i) + { + if (elementAt(i)) + removeAt(i); + } + simplify(); } /*! @@ -2260,10 +2260,10 @@ void QCPLayout::clear() */ void QCPLayout::sizeConstraintsChanged() const { - if (QWidget *w = qobject_cast(parent())) - w->updateGeometry(); - else if (QCPLayout *l = qobject_cast(parent())) - l->sizeConstraintsChanged(); + if (QWidget *w = qobject_cast(parent())) + w->updateGeometry(); + else if (QCPLayout *l = qobject_cast(parent())) + l->sizeConstraintsChanged(); } /*! \internal @@ -2297,15 +2297,15 @@ void QCPLayout::updateLayout() */ void QCPLayout::adoptElement(QCPLayoutElement *el) { - if (el) - { - el->mParentLayout = this; - el->setParentLayerable(this); - el->setParent(this); - if (!el->parentPlot()) - el->initializeParentPlot(mParentPlot); - } else - qDebug() << Q_FUNC_INFO << "Null element passed"; + if (el) + { + el->mParentLayout = this; + el->setParentLayerable(this); + el->setParent(this); + if (!el->parentPlot()) + el->initializeParentPlot(mParentPlot); + } else + qDebug() << Q_FUNC_INFO << "Null element passed"; } /*! \internal @@ -2320,14 +2320,14 @@ void QCPLayout::adoptElement(QCPLayoutEl */ void QCPLayout::releaseElement(QCPLayoutElement *el) { - if (el) - { - el->mParentLayout = 0; - el->setParentLayerable(0); - el->setParent(mParentPlot); - // Note: Don't initializeParentPlot(0) here, because layout element will stay in same parent plot - } else - qDebug() << Q_FUNC_INFO << "Null element passed"; + if (el) + { + el->mParentLayout = 0; + el->setParentLayerable(0); + el->setParent(mParentPlot); + // Note: Don't initializeParentPlot(0) here, because layout element will stay in same parent plot + } else + qDebug() << Q_FUNC_INFO << "Null element passed"; } /*! \internal @@ -2361,115 +2361,115 @@ void QCPLayout::releaseElement(QCPLayout */ QVector QCPLayout::getSectionSizes(QVector maxSizes, QVector minSizes, QVector stretchFactors, int totalSize) const { - if (maxSizes.size() != minSizes.size() || minSizes.size() != stretchFactors.size()) - { - qDebug() << Q_FUNC_INFO << "Passed vector sizes aren't equal:" << maxSizes << minSizes << stretchFactors; - return QVector(); - } - if (stretchFactors.isEmpty()) - return QVector(); - int sectionCount = stretchFactors.size(); - QVector sectionSizes(sectionCount); - // if provided total size is forced smaller than total minimum size, ignore minimum sizes (squeeze sections): - int minSizeSum = 0; - for (int i=0; i minimumLockedSections; - QList unfinishedSections; - for (int i=0; i(); + } + if (stretchFactors.isEmpty()) + return QVector(); + int sectionCount = stretchFactors.size(); + QVector sectionSizes(sectionCount); + // if provided total size is forced smaller than total minimum size, ignore minimum sizes (squeeze sections): + int minSizeSum = 0; + for (int i=0; i minimumLockedSections; + QList unfinishedSections; + for (int i=0; i result(sectionCount); - for (int i=0; i result(sectionCount); + for (int i=0; i QCPLayout::getSectionSizes( Creates an instance of QCPLayoutGrid and sets default values. */ QCPLayoutGrid::QCPLayoutGrid() : - mColumnSpacing(5), - mRowSpacing(5) + mColumnSpacing(5), + mRowSpacing(5) { } QCPLayoutGrid::~QCPLayoutGrid() { - // clear all child layout elements. This is important because only the specific layouts know how - // to handle removing elements (clear calls virtual removeAt method to do that). - clear(); + // clear all child layout elements. This is important because only the specific layouts know how + // to handle removing elements (clear calls virtual removeAt method to do that). + clear(); } /*! @@ -2519,19 +2519,19 @@ QCPLayoutGrid::~QCPLayoutGrid() */ QCPLayoutElement *QCPLayoutGrid::element(int row, int column) const { - if (row >= 0 && row < mElements.size()) - { - if (column >= 0 && column < mElements.first().size()) - { - if (QCPLayoutElement *result = mElements.at(row).at(column)) - return result; - else - qDebug() << Q_FUNC_INFO << "Requested cell is empty. Row:" << row << "Column:" << column; + if (row >= 0 && row < mElements.size()) + { + if (column >= 0 && column < mElements.first().size()) + { + if (QCPLayoutElement *result = mElements.at(row).at(column)) + return result; + else + qDebug() << Q_FUNC_INFO << "Requested cell is empty. Row:" << row << "Column:" << column; } else - qDebug() << Q_FUNC_INFO << "Invalid column. Row:" << row << "Column:" << column; - } else - qDebug() << Q_FUNC_INFO << "Invalid row. Row:" << row << "Column:" << column; - return 0; + qDebug() << Q_FUNC_INFO << "Invalid column. Row:" << row << "Column:" << column; + } else + qDebug() << Q_FUNC_INFO << "Invalid row. Row:" << row << "Column:" << column; + return 0; } /*! @@ -2541,7 +2541,7 @@ QCPLayoutElement *QCPLayoutGrid::element */ int QCPLayoutGrid::rowCount() const { - return mElements.size(); + return mElements.size(); } /*! @@ -2551,10 +2551,10 @@ int QCPLayoutGrid::rowCount() const */ int QCPLayoutGrid::columnCount() const { - if (mElements.size() > 0) - return mElements.first().size(); - else - return 0; + if (mElements.size() > 0) + return mElements.first().size(); + else + return 0; } /*! @@ -2569,21 +2569,21 @@ int QCPLayoutGrid::columnCount() const */ bool QCPLayoutGrid::addElement(int row, int column, QCPLayoutElement *element) { - if (element) - { - if (!hasElement(row, column)) - { - if (element->layout()) // remove from old layout first - element->layout()->take(element); - expandTo(row+1, column+1); - mElements[row][column] = element; - adoptElement(element); - return true; + if (element) + { + if (!hasElement(row, column)) + { + if (element->layout()) // remove from old layout first + element->layout()->take(element); + expandTo(row+1, column+1); + mElements[row][column] = element; + adoptElement(element); + return true; } else - qDebug() << Q_FUNC_INFO << "There is already an element in the specified row/column:" << row << column; - } else - qDebug() << Q_FUNC_INFO << "Can't add null element to row/column:" << row << column; - return false; + qDebug() << Q_FUNC_INFO << "There is already an element in the specified row/column:" << row << column; + } else + qDebug() << Q_FUNC_INFO << "Can't add null element to row/column:" << row << column; + return false; } /*! @@ -2594,10 +2594,10 @@ bool QCPLayoutGrid::addElement(int row, */ bool QCPLayoutGrid::hasElement(int row, int column) { - if (row >= 0 && row < rowCount() && column >= 0 && column < columnCount()) - return mElements.at(row).at(column); - else - return false; + if (row >= 0 && row < rowCount() && column >= 0 && column < columnCount()) + return mElements.at(row).at(column); + else + return false; } /*! @@ -2613,14 +2613,14 @@ bool QCPLayoutGrid::hasElement(int row, */ void QCPLayoutGrid::setColumnStretchFactor(int column, double factor) { - if (column >= 0 && column < columnCount()) - { - if (factor > 0) - mColumnStretchFactors[column] = factor; - else - qDebug() << Q_FUNC_INFO << "Invalid stretch factor, must be positive:" << factor; - } else - qDebug() << Q_FUNC_INFO << "Invalid column:" << column; + if (column >= 0 && column < columnCount()) + { + if (factor > 0) + mColumnStretchFactors[column] = factor; + else + qDebug() << Q_FUNC_INFO << "Invalid stretch factor, must be positive:" << factor; + } else + qDebug() << Q_FUNC_INFO << "Invalid column:" << column; } /*! @@ -2636,19 +2636,19 @@ void QCPLayoutGrid::setColumnStretchFact */ void QCPLayoutGrid::setColumnStretchFactors(const QList &factors) { - if (factors.size() == mColumnStretchFactors.size()) - { - mColumnStretchFactors = factors; - for (int i=0; i= 0 && row < rowCount()) - { - if (factor > 0) - mRowStretchFactors[row] = factor; - else - qDebug() << Q_FUNC_INFO << "Invalid stretch factor, must be positive:" << factor; - } else - qDebug() << Q_FUNC_INFO << "Invalid row:" << row; + if (row >= 0 && row < rowCount()) + { + if (factor > 0) + mRowStretchFactors[row] = factor; + else + qDebug() << Q_FUNC_INFO << "Invalid stretch factor, must be positive:" << factor; + } else + qDebug() << Q_FUNC_INFO << "Invalid row:" << row; } /*! @@ -2687,19 +2687,19 @@ void QCPLayoutGrid::setRowStretchFactor( */ void QCPLayoutGrid::setRowStretchFactors(const QList &factors) { - if (factors.size() == mRowStretchFactors.size()) - { - mRowStretchFactors = factors; - for (int i=0; i()); - mRowStretchFactors.append(1); - } - // go through rows and expand columns as necessary: - int newColCount = qMax(columnCount(), newColumnCount); - for (int i=0; i()); + mRowStretchFactors.append(1); + } + // go through rows and expand columns as necessary: + int newColCount = qMax(columnCount(), newColumnCount); + for (int i=0; i rowCount()) - newIndex = rowCount(); - - mRowStretchFactors.insert(newIndex, 1); - QList newRow; - for (int col=0; col rowCount()) + newIndex = rowCount(); + + mRowStretchFactors.insert(newIndex, 1); + QList newRow; + for (int col=0; col columnCount()) - newIndex = columnCount(); - - mColumnStretchFactors.insert(newIndex, 1); - for (int row=0; row columnCount()) + newIndex = columnCount(); + + mColumnStretchFactors.insert(newIndex, 1); + for (int row=0; row minColWidths, minRowHeights, maxColWidths, maxRowHeights; - getMinimumRowColSizes(&minColWidths, &minRowHeights); - getMaximumRowColSizes(&maxColWidths, &maxRowHeights); - - int totalRowSpacing = (rowCount()-1) * mRowSpacing; - int totalColSpacing = (columnCount()-1) * mColumnSpacing; - QVector colWidths = getSectionSizes(maxColWidths, minColWidths, mColumnStretchFactors.toVector(), mRect.width()-totalColSpacing); - QVector rowHeights = getSectionSizes(maxRowHeights, minRowHeights, mRowStretchFactors.toVector(), mRect.height()-totalRowSpacing); - - // go through cells and set rects accordingly: - int yOffset = mRect.top(); - for (int row=0; row 0) - yOffset += rowHeights.at(row-1)+mRowSpacing; - int xOffset = mRect.left(); - for (int col=0; col 0) - xOffset += colWidths.at(col-1)+mColumnSpacing; - if (mElements.at(row).at(col)) - mElements.at(row).at(col)->setOuterRect(QRect(xOffset, yOffset, colWidths.at(col), rowHeights.at(row))); + QVector minColWidths, minRowHeights, maxColWidths, maxRowHeights; + getMinimumRowColSizes(&minColWidths, &minRowHeights); + getMaximumRowColSizes(&maxColWidths, &maxRowHeights); + + int totalRowSpacing = (rowCount()-1) * mRowSpacing; + int totalColSpacing = (columnCount()-1) * mColumnSpacing; + QVector colWidths = getSectionSizes(maxColWidths, minColWidths, mColumnStretchFactors.toVector(), mRect.width()-totalColSpacing); + QVector rowHeights = getSectionSizes(maxRowHeights, minRowHeights, mRowStretchFactors.toVector(), mRect.height()-totalRowSpacing); + + // go through cells and set rects accordingly: + int yOffset = mRect.top(); + for (int row=0; row 0) + yOffset += rowHeights.at(row-1)+mRowSpacing; + int xOffset = mRect.left(); + for (int col=0; col 0) + xOffset += colWidths.at(col-1)+mColumnSpacing; + if (mElements.at(row).at(col)) + mElements.at(row).at(col)->setOuterRect(QRect(xOffset, yOffset, colWidths.at(col), rowHeights.at(row))); } } } @@ -2837,78 +2837,78 @@ void QCPLayoutGrid::updateLayout() /* inherits documentation from base class */ int QCPLayoutGrid::elementCount() const { - return rowCount()*columnCount(); + return rowCount()*columnCount(); } /* inherits documentation from base class */ QCPLayoutElement *QCPLayoutGrid::elementAt(int index) const { - if (index >= 0 && index < elementCount()) - return mElements.at(index / columnCount()).at(index % columnCount()); - else - return 0; + if (index >= 0 && index < elementCount()) + return mElements.at(index / columnCount()).at(index % columnCount()); + else + return 0; } /* inherits documentation from base class */ QCPLayoutElement *QCPLayoutGrid::takeAt(int index) { - if (QCPLayoutElement *el = elementAt(index)) - { - releaseElement(el); - mElements[index / columnCount()][index % columnCount()] = 0; - return el; - } else - { - qDebug() << Q_FUNC_INFO << "Attempt to take invalid index:" << index; - return 0; + if (QCPLayoutElement *el = elementAt(index)) + { + releaseElement(el); + mElements[index / columnCount()][index % columnCount()] = 0; + return el; + } else + { + qDebug() << Q_FUNC_INFO << "Attempt to take invalid index:" << index; + return 0; } } /* inherits documentation from base class */ bool QCPLayoutGrid::take(QCPLayoutElement *element) { - if (element) - { - for (int i=0; i QCPLayoutGrid::elements(bool recursive) const { - QList result; - int colC = columnCount(); - int rowC = rowCount(); + QList result; + int colC = columnCount(); + int rowC = rowCount(); #if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) - result.reserve(colC*rowC); + result.reserve(colC*rowC); #endif - for (int row=0; rowelements(recursive); - } - } - return result; + for (int row=0; rowelements(recursive); + } + } + return result; } /*! @@ -2916,44 +2916,44 @@ QList QCPLayoutGrid:: */ void QCPLayoutGrid::simplify() { - // remove rows with only empty cells: - for (int row=rowCount()-1; row>=0; --row) - { - bool hasElements = false; - for (int col=0; col=0; --col) - { - bool hasElements = false; - for (int row=0; row=0; --row) + { + bool hasElements = false; + for (int col=0; col=0; --col) + { + bool hasElements = false; + for (int row=0; row minColWidths, minRowHeights; - getMinimumRowColSizes(&minColWidths, &minRowHeights); - QSize result(0, 0); - for (int i=0; i minColWidths, minRowHeights; + getMinimumRowColSizes(&minColWidths, &minRowHeights); + QSize result(0, 0); + for (int i=0; i maxColWidths, maxRowHeights; - getMaximumRowColSizes(&maxColWidths, &maxRowHeights); - - QSize result(0, 0); - for (int i=0; i maxColWidths, maxRowHeights; + getMaximumRowColSizes(&maxColWidths, &maxRowHeights); + + QSize result(0, 0); + for (int i=0; i *minColWidths, QVector *minRowHeights) const { - *minColWidths = QVector(columnCount(), 0); - *minRowHeights = QVector(rowCount(), 0); - for (int row=0; rowminimumSizeHint(); - QSize min = mElements.at(row).at(col)->minimumSize(); - QSize final(min.width() > 0 ? min.width() : minHint.width(), min.height() > 0 ? min.height() : minHint.height()); - if (minColWidths->at(col) < final.width()) - (*minColWidths)[col] = final.width(); - if (minRowHeights->at(row) < final.height()) - (*minRowHeights)[row] = final.height(); + *minColWidths = QVector(columnCount(), 0); + *minRowHeights = QVector(rowCount(), 0); + for (int row=0; rowminimumSizeHint(); + QSize min = mElements.at(row).at(col)->minimumSize(); + QSize final(min.width() > 0 ? min.width() : minHint.width(), min.height() > 0 ? min.height() : minHint.height()); + if (minColWidths->at(col) < final.width()) + (*minColWidths)[col] = final.width(); + if (minRowHeights->at(row) < final.height()) + (*minRowHeights)[row] = final.height(); } } } @@ -3037,21 +3037,21 @@ void QCPLayoutGrid::getMinimumRowColSize */ void QCPLayoutGrid::getMaximumRowColSizes(QVector *maxColWidths, QVector *maxRowHeights) const { - *maxColWidths = QVector(columnCount(), QWIDGETSIZE_MAX); - *maxRowHeights = QVector(rowCount(), QWIDGETSIZE_MAX); - for (int row=0; rowmaximumSizeHint(); - QSize max = mElements.at(row).at(col)->maximumSize(); - QSize final(max.width() < QWIDGETSIZE_MAX ? max.width() : maxHint.width(), max.height() < QWIDGETSIZE_MAX ? max.height() : maxHint.height()); - if (maxColWidths->at(col) > final.width()) - (*maxColWidths)[col] = final.width(); - if (maxRowHeights->at(row) > final.height()) - (*maxRowHeights)[row] = final.height(); + *maxColWidths = QVector(columnCount(), QWIDGETSIZE_MAX); + *maxRowHeights = QVector(rowCount(), QWIDGETSIZE_MAX); + for (int row=0; rowmaximumSizeHint(); + QSize max = mElements.at(row).at(col)->maximumSize(); + QSize final(max.width() < QWIDGETSIZE_MAX ? max.width() : maxHint.width(), max.height() < QWIDGETSIZE_MAX ? max.height() : maxHint.height()); + if (maxColWidths->at(col) > final.width()) + (*maxColWidths)[col] = final.width(); + if (maxRowHeights->at(row) > final.height()) + (*maxRowHeights)[row] = final.height(); } } } @@ -3098,9 +3098,9 @@ QCPLayoutInset::QCPLayoutInset() QCPLayoutInset::~QCPLayoutInset() { - // clear all child layout elements. This is important because only the specific layouts know how - // to handle removing elements (clear calls virtual removeAt method to do that). - clear(); + // clear all child layout elements. This is important because only the specific layouts know how + // to handle removing elements (clear calls virtual removeAt method to do that). + clear(); } /*! @@ -3108,12 +3108,12 @@ QCPLayoutInset::~QCPLayoutInset() */ QCPLayoutInset::InsetPlacement QCPLayoutInset::insetPlacement(int index) const { - if (elementAt(index)) - return mInsetPlacement.at(index); - else - { - qDebug() << Q_FUNC_INFO << "Invalid element index:" << index; - return ipFree; + if (elementAt(index)) + return mInsetPlacement.at(index); + else + { + qDebug() << Q_FUNC_INFO << "Invalid element index:" << index; + return ipFree; } } @@ -3123,12 +3123,12 @@ QCPLayoutInset::InsetPlacement QCPLayout */ Qt::Alignment QCPLayoutInset::insetAlignment(int index) const { - if (elementAt(index)) - return mInsetAlignment.at(index); - else - { - qDebug() << Q_FUNC_INFO << "Invalid element index:" << index; - return 0; + if (elementAt(index)) + return mInsetAlignment.at(index); + else + { + qDebug() << Q_FUNC_INFO << "Invalid element index:" << index; + return 0; } } @@ -3138,12 +3138,12 @@ Qt::Alignment QCPLayoutInset::insetAlign */ QRectF QCPLayoutInset::insetRect(int index) const { - if (elementAt(index)) - return mInsetRect.at(index); - else - { - qDebug() << Q_FUNC_INFO << "Invalid element index:" << index; - return QRectF(); + if (elementAt(index)) + return mInsetRect.at(index); + else + { + qDebug() << Q_FUNC_INFO << "Invalid element index:" << index; + return QRectF(); } } @@ -3154,10 +3154,10 @@ QRectF QCPLayoutInset::insetRect(int ind */ void QCPLayoutInset::setInsetPlacement(int index, QCPLayoutInset::InsetPlacement placement) { - if (elementAt(index)) - mInsetPlacement[index] = placement; - else - qDebug() << Q_FUNC_INFO << "Invalid element index:" << index; + if (elementAt(index)) + mInsetPlacement[index] = placement; + else + qDebug() << Q_FUNC_INFO << "Invalid element index:" << index; } /*! @@ -3170,10 +3170,10 @@ void QCPLayoutInset::setInsetPlacement(i */ void QCPLayoutInset::setInsetAlignment(int index, Qt::Alignment alignment) { - if (elementAt(index)) - mInsetAlignment[index] = alignment; - else - qDebug() << Q_FUNC_INFO << "Invalid element index:" << index; + if (elementAt(index)) + mInsetAlignment[index] = alignment; + else + qDebug() << Q_FUNC_INFO << "Invalid element index:" << index; } /*! @@ -3189,104 +3189,104 @@ void QCPLayoutInset::setInsetAlignment(i */ void QCPLayoutInset::setInsetRect(int index, const QRectF &rect) { - if (elementAt(index)) - mInsetRect[index] = rect; - else - qDebug() << Q_FUNC_INFO << "Invalid element index:" << index; + if (elementAt(index)) + mInsetRect[index] = rect; + else + qDebug() << Q_FUNC_INFO << "Invalid element index:" << index; } /* inherits documentation from base class */ void QCPLayoutInset::updateLayout() { - for (int i=0; iminimumSizeHint(); - QSize maxSizeHint = mElements.at(i)->maximumSizeHint(); - finalMinSize.setWidth(mElements.at(i)->minimumSize().width() > 0 ? mElements.at(i)->minimumSize().width() : minSizeHint.width()); - finalMinSize.setHeight(mElements.at(i)->minimumSize().height() > 0 ? mElements.at(i)->minimumSize().height() : minSizeHint.height()); - finalMaxSize.setWidth(mElements.at(i)->maximumSize().width() < QWIDGETSIZE_MAX ? mElements.at(i)->maximumSize().width() : maxSizeHint.width()); - finalMaxSize.setHeight(mElements.at(i)->maximumSize().height() < QWIDGETSIZE_MAX ? mElements.at(i)->maximumSize().height() : maxSizeHint.height()); - if (mInsetPlacement.at(i) == ipFree) - { - insetRect = QRect(rect().x()+rect().width()*mInsetRect.at(i).x(), - rect().y()+rect().height()*mInsetRect.at(i).y(), - rect().width()*mInsetRect.at(i).width(), - rect().height()*mInsetRect.at(i).height()); - if (insetRect.size().width() < finalMinSize.width()) - insetRect.setWidth(finalMinSize.width()); - if (insetRect.size().height() < finalMinSize.height()) - insetRect.setHeight(finalMinSize.height()); - if (insetRect.size().width() > finalMaxSize.width()) - insetRect.setWidth(finalMaxSize.width()); - if (insetRect.size().height() > finalMaxSize.height()) - insetRect.setHeight(finalMaxSize.height()); + for (int i=0; iminimumSizeHint(); + QSize maxSizeHint = mElements.at(i)->maximumSizeHint(); + finalMinSize.setWidth(mElements.at(i)->minimumSize().width() > 0 ? mElements.at(i)->minimumSize().width() : minSizeHint.width()); + finalMinSize.setHeight(mElements.at(i)->minimumSize().height() > 0 ? mElements.at(i)->minimumSize().height() : minSizeHint.height()); + finalMaxSize.setWidth(mElements.at(i)->maximumSize().width() < QWIDGETSIZE_MAX ? mElements.at(i)->maximumSize().width() : maxSizeHint.width()); + finalMaxSize.setHeight(mElements.at(i)->maximumSize().height() < QWIDGETSIZE_MAX ? mElements.at(i)->maximumSize().height() : maxSizeHint.height()); + if (mInsetPlacement.at(i) == ipFree) + { + insetRect = QRect(rect().x()+rect().width()*mInsetRect.at(i).x(), + rect().y()+rect().height()*mInsetRect.at(i).y(), + rect().width()*mInsetRect.at(i).width(), + rect().height()*mInsetRect.at(i).height()); + if (insetRect.size().width() < finalMinSize.width()) + insetRect.setWidth(finalMinSize.width()); + if (insetRect.size().height() < finalMinSize.height()) + insetRect.setHeight(finalMinSize.height()); + if (insetRect.size().width() > finalMaxSize.width()) + insetRect.setWidth(finalMaxSize.width()); + if (insetRect.size().height() > finalMaxSize.height()) + insetRect.setHeight(finalMaxSize.height()); } else if (mInsetPlacement.at(i) == ipBorderAligned) { - insetRect.setSize(finalMinSize); - Qt::Alignment al = mInsetAlignment.at(i); - if (al.testFlag(Qt::AlignLeft)) insetRect.moveLeft(rect().x()); - else if (al.testFlag(Qt::AlignRight)) insetRect.moveRight(rect().x()+rect().width()); - else insetRect.moveLeft(rect().x()+rect().width()*0.5-finalMinSize.width()*0.5); // default to Qt::AlignHCenter - if (al.testFlag(Qt::AlignTop)) insetRect.moveTop(rect().y()); - else if (al.testFlag(Qt::AlignBottom)) insetRect.moveBottom(rect().y()+rect().height()); - else insetRect.moveTop(rect().y()+rect().height()*0.5-finalMinSize.height()*0.5); // default to Qt::AlignVCenter - } - mElements.at(i)->setOuterRect(insetRect); + insetRect.setSize(finalMinSize); + Qt::Alignment al = mInsetAlignment.at(i); + if (al.testFlag(Qt::AlignLeft)) insetRect.moveLeft(rect().x()); + else if (al.testFlag(Qt::AlignRight)) insetRect.moveRight(rect().x()+rect().width()); + else insetRect.moveLeft(rect().x()+rect().width()*0.5-finalMinSize.width()*0.5); // default to Qt::AlignHCenter + if (al.testFlag(Qt::AlignTop)) insetRect.moveTop(rect().y()); + else if (al.testFlag(Qt::AlignBottom)) insetRect.moveBottom(rect().y()+rect().height()); + else insetRect.moveTop(rect().y()+rect().height()*0.5-finalMinSize.height()*0.5); // default to Qt::AlignVCenter + } + mElements.at(i)->setOuterRect(insetRect); } } /* inherits documentation from base class */ int QCPLayoutInset::elementCount() const { - return mElements.size(); + return mElements.size(); } /* inherits documentation from base class */ QCPLayoutElement *QCPLayoutInset::elementAt(int index) const { - if (index >= 0 && index < mElements.size()) - return mElements.at(index); - else - return 0; + if (index >= 0 && index < mElements.size()) + return mElements.at(index); + else + return 0; } /* inherits documentation from base class */ QCPLayoutElement *QCPLayoutInset::takeAt(int index) { - if (QCPLayoutElement *el = elementAt(index)) - { - releaseElement(el); - mElements.removeAt(index); - mInsetPlacement.removeAt(index); - mInsetAlignment.removeAt(index); - mInsetRect.removeAt(index); - return el; - } else - { - qDebug() << Q_FUNC_INFO << "Attempt to take invalid index:" << index; - return 0; + if (QCPLayoutElement *el = elementAt(index)) + { + releaseElement(el); + mElements.removeAt(index); + mInsetPlacement.removeAt(index); + mInsetAlignment.removeAt(index); + mInsetRect.removeAt(index); + return el; + } else + { + qDebug() << Q_FUNC_INFO << "Attempt to take invalid index:" << index; + return 0; } } /* inherits documentation from base class */ bool QCPLayoutInset::take(QCPLayoutElement *element) { - if (element) - { - for (int i=0; irealVisibility() && mElements.at(i)->selectTest(pos, onlySelectable) >= 0) + return mParentPlot->selectionTolerance()*0.99; + } return -1; - - for (int i=0; irealVisibility() && mElements.at(i)->selectTest(pos, onlySelectable) >= 0) - return mParentPlot->selectionTolerance()*0.99; - } - return -1; } /*! @@ -3327,17 +3327,17 @@ double QCPLayoutInset::selectTest(const */ void QCPLayoutInset::addElement(QCPLayoutElement *element, Qt::Alignment alignment) { - if (element) - { - if (element->layout()) // remove from old layout first - element->layout()->take(element); - mElements.append(element); - mInsetPlacement.append(ipBorderAligned); - mInsetAlignment.append(alignment); - mInsetRect.append(QRectF(0.6, 0.6, 0.4, 0.4)); - adoptElement(element); - } else - qDebug() << Q_FUNC_INFO << "Can't add null element"; + if (element) + { + if (element->layout()) // remove from old layout first + element->layout()->take(element); + mElements.append(element); + mInsetPlacement.append(ipBorderAligned); + mInsetAlignment.append(alignment); + mInsetRect.append(QRectF(0.6, 0.6, 0.4, 0.4)); + adoptElement(element); + } else + qDebug() << Q_FUNC_INFO << "Can't add null element"; } /*! @@ -3353,17 +3353,17 @@ void QCPLayoutInset::addElement(QCPLayou */ void QCPLayoutInset::addElement(QCPLayoutElement *element, const QRectF &rect) { - if (element) - { - if (element->layout()) // remove from old layout first - element->layout()->take(element); - mElements.append(element); - mInsetPlacement.append(ipFree); - mInsetAlignment.append(Qt::AlignRight|Qt::AlignTop); - mInsetRect.append(rect); - adoptElement(element); - } else - qDebug() << Q_FUNC_INFO << "Can't add null element"; + if (element) + { + if (element->layout()) // remove from old layout first + element->layout()->take(element); + mElements.append(element); + mInsetPlacement.append(ipFree); + mInsetAlignment.append(Qt::AlignRight|Qt::AlignTop); + mInsetRect.append(rect); + adoptElement(element); + } else + qDebug() << Q_FUNC_INFO << "Can't add null element"; } @@ -3395,10 +3395,10 @@ void QCPLayoutInset::addElement(QCPLayou Creates a QCPLineEnding instance with default values (style \ref esNone). */ QCPLineEnding::QCPLineEnding() : - mStyle(esNone), - mWidth(8), - mLength(10), - mInverted(false) + mStyle(esNone), + mWidth(8), + mLength(10), + mInverted(false) { } @@ -3406,10 +3406,10 @@ QCPLineEnding::QCPLineEnding() : Creates a QCPLineEnding instance with the specified values. */ QCPLineEnding::QCPLineEnding(QCPLineEnding::EndingStyle style, double width, double length, bool inverted) : - mStyle(style), - mWidth(width), - mLength(length), - mInverted(inverted) + mStyle(style), + mWidth(width), + mLength(length), + mInverted(inverted) { } @@ -3418,7 +3418,7 @@ QCPLineEnding::QCPLineEnding(QCPLineEndi */ void QCPLineEnding::setStyle(QCPLineEnding::EndingStyle style) { - mStyle = style; + mStyle = style; } /*! @@ -3429,7 +3429,7 @@ void QCPLineEnding::setStyle(QCPLineEndi */ void QCPLineEnding::setWidth(double width) { - mWidth = width; + mWidth = width; } /*! @@ -3440,7 +3440,7 @@ void QCPLineEnding::setWidth(double widt */ void QCPLineEnding::setLength(double length) { - mLength = length; + mLength = length; } /*! @@ -3453,7 +3453,7 @@ void QCPLineEnding::setLength(double len */ void QCPLineEnding::setInverted(bool inverted) { - mInverted = inverted; + mInverted = inverted; } /*! \internal @@ -3467,26 +3467,26 @@ void QCPLineEnding::setInverted(bool inv */ double QCPLineEnding::boundingDistance() const { - switch (mStyle) + switch (mStyle) { case esNone: - return 0; - + return 0; + case esFlatArrow: case esSpikeArrow: case esLineArrow: case esSkewedBar: - return qSqrt(mWidth*mWidth+mLength*mLength); // items that have width and length - + return qSqrt(mWidth*mWidth+mLength*mLength); // items that have width and length + case esDisc: case esSquare: case esDiamond: case esBar: case esHalfBar: - return mWidth*1.42; // items that only have a width -> width*sqrt(2) - - } - return 0; + return mWidth*1.42; // items that only have a width -> width*sqrt(2) + + } + return 0; } /*! @@ -3502,27 +3502,27 @@ double QCPLineEnding::boundingDistance() */ double QCPLineEnding::realLength() const { - switch (mStyle) + switch (mStyle) { case esNone: case esLineArrow: case esSkewedBar: case esBar: case esHalfBar: - return 0; - + return 0; + case esFlatArrow: - return mLength; - + return mLength; + case esDisc: case esSquare: case esDiamond: - return mWidth*0.5; - + return mWidth*0.5; + case esSpikeArrow: - return mLength*0.8; - } - return 0; + return mLength*0.8; + } + return 0; } /*! \internal @@ -3532,26 +3532,26 @@ double QCPLineEnding::realLength() const */ void QCPLineEnding::draw(QCPPainter *painter, const QVector2D &pos, const QVector2D &dir) const { - if (mStyle == esNone) - return; - - QVector2D lengthVec(dir.normalized()); - if (lengthVec.isNull()) - lengthVec = QVector2D(1, 0); - QVector2D widthVec(-lengthVec.y(), lengthVec.x()); - lengthVec *= (float)(mLength*(mInverted ? -1 : 1)); - widthVec *= (float)(mWidth*0.5*(mInverted ? -1 : 1)); - - QPen penBackup = painter->pen(); - QBrush brushBackup = painter->brush(); - QPen miterPen = penBackup; - miterPen.setJoinStyle(Qt::MiterJoin); // to make arrow heads spikey - QBrush brush(painter->pen().color(), Qt::SolidPattern); - switch (mStyle) + if (mStyle == esNone) + return; + + QVector2D lengthVec(dir.normalized()); + if (lengthVec.isNull()) + lengthVec = QVector2D(1, 0); + QVector2D widthVec(-lengthVec.y(), lengthVec.x()); + lengthVec *= (float)(mLength*(mInverted ? -1 : 1)); + widthVec *= (float)(mWidth*0.5*(mInverted ? -1 : 1)); + + QPen penBackup = painter->pen(); + QBrush brushBackup = painter->brush(); + QPen miterPen = penBackup; + miterPen.setJoinStyle(Qt::MiterJoin); // to make arrow heads spikey + QBrush brush(painter->pen().color(), Qt::SolidPattern); + switch (mStyle) { case esNone: break; case esFlatArrow: - { + { QPointF points[3] = {pos.toPointF(), (pos-lengthVec+widthVec).toPointF(), (pos-lengthVec-widthVec).toPointF() @@ -3562,9 +3562,9 @@ void QCPLineEnding::draw(QCPPainter *pai painter->setBrush(brushBackup); painter->setPen(penBackup); break; - } + } case esSpikeArrow: - { + { QPointF points[4] = {pos.toPointF(), (pos-lengthVec+widthVec).toPointF(), (pos-lengthVec*0.8f).toPointF(), @@ -3576,9 +3576,9 @@ void QCPLineEnding::draw(QCPPainter *pai painter->setBrush(brushBackup); painter->setPen(penBackup); break; - } + } case esLineArrow: - { + { QPointF points[3] = {(pos-lengthVec+widthVec).toPointF(), pos.toPointF(), (pos-lengthVec-widthVec).toPointF() @@ -3587,16 +3587,16 @@ void QCPLineEnding::draw(QCPPainter *pai painter->drawPolyline(points, 3); painter->setPen(penBackup); break; - } + } case esDisc: - { + { painter->setBrush(brush); painter->drawEllipse(pos.toPointF(), mWidth*0.5, mWidth*0.5); painter->setBrush(brushBackup); break; - } + } case esSquare: - { + { QVector2D widthVecPerp(-widthVec.y(), widthVec.x()); QPointF points[4] = {(pos-widthVecPerp+widthVec).toPointF(), (pos-widthVecPerp-widthVec).toPointF(), @@ -3609,9 +3609,9 @@ void QCPLineEnding::draw(QCPPainter *pai painter->setBrush(brushBackup); painter->setPen(penBackup); break; - } + } case esDiamond: - { + { QVector2D widthVecPerp(-widthVec.y(), widthVec.x()); QPointF points[4] = {(pos-widthVecPerp).toPointF(), (pos-widthVec).toPointF(), @@ -3624,32 +3624,32 @@ void QCPLineEnding::draw(QCPPainter *pai painter->setBrush(brushBackup); painter->setPen(penBackup); break; - } + } case esBar: - { + { painter->drawLine((pos+widthVec).toPointF(), (pos-widthVec).toPointF()); break; - } + } case esHalfBar: - { + { painter->drawLine((pos+widthVec).toPointF(), pos.toPointF()); break; - } + } case esSkewedBar: - { + { if (qFuzzyIsNull(painter->pen().widthF()) && !painter->modes().testFlag(QCPPainter::pmNonCosmetic)) - { + { // if drawing with cosmetic pen (perfectly thin stroke, happens only in vector exports), draw bar exactly on tip of line painter->drawLine((pos+widthVec+lengthVec*0.2f*(mInverted?-1:1)).toPointF(), (pos-widthVec-lengthVec*0.2f*(mInverted?-1:1)).toPointF()); - } else - { + } else + { // if drawing with thick (non-cosmetic) pen, shift bar a little in line direction to prevent line from sticking through bar slightly painter->drawLine((pos+widthVec+lengthVec*0.2f*(mInverted?-1:1)+dir.normalized()*qMax(1.0f, (float)painter->pen().widthF())*0.5f).toPointF(), (pos-widthVec-lengthVec*0.2f*(mInverted?-1:1)+dir.normalized()*qMax(1.0f, (float)painter->pen().widthF())*0.5f).toPointF()); - } - break; - } + } + break; + } } } @@ -3660,7 +3660,7 @@ void QCPLineEnding::draw(QCPPainter *pai */ void QCPLineEnding::draw(QCPPainter *painter, const QVector2D &pos, double angle) const { - draw(painter, pos, QVector2D(qCos(angle), qSin(angle))); + draw(painter, pos, QVector2D(qCos(angle), qSin(angle))); } @@ -3687,18 +3687,18 @@ void QCPLineEnding::draw(QCPPainter *pai You shouldn't instantiate grids on their own, since every QCPAxis brings its own QCPGrid. */ QCPGrid::QCPGrid(QCPAxis *parentAxis) : - QCPLayerable(parentAxis->parentPlot(), QString(), parentAxis), - mParentAxis(parentAxis) -{ - // warning: this is called in QCPAxis constructor, so parentAxis members should not be accessed/called - setParent(parentAxis); - setPen(QPen(QColor(200,200,200), 0, Qt::DotLine)); - setSubGridPen(QPen(QColor(220,220,220), 0, Qt::DotLine)); - setZeroLinePen(QPen(QColor(200,200,200), 0, Qt::SolidLine)); - setSubGridVisible(false); - setAntialiased(false); - setAntialiasedSubGrid(false); - setAntialiasedZeroLine(false); + QCPLayerable(parentAxis->parentPlot(), QString(), parentAxis), + mParentAxis(parentAxis) +{ + // warning: this is called in QCPAxis constructor, so parentAxis members should not be accessed/called + setParent(parentAxis); + setPen(QPen(QColor(200,200,200), 0, Qt::DotLine)); + setSubGridPen(QPen(QColor(220,220,220), 0, Qt::DotLine)); + setZeroLinePen(QPen(QColor(200,200,200), 0, Qt::SolidLine)); + setSubGridVisible(false); + setAntialiased(false); + setAntialiasedSubGrid(false); + setAntialiasedZeroLine(false); } /*! @@ -3708,7 +3708,7 @@ QCPGrid::QCPGrid(QCPAxis *parentAxis) : */ void QCPGrid::setSubGridVisible(bool visible) { - mSubGridVisible = visible; + mSubGridVisible = visible; } /*! @@ -3716,7 +3716,7 @@ void QCPGrid::setSubGridVisible(bool vis */ void QCPGrid::setAntialiasedSubGrid(bool enabled) { - mAntialiasedSubGrid = enabled; + mAntialiasedSubGrid = enabled; } /*! @@ -3724,7 +3724,7 @@ void QCPGrid::setAntialiasedSubGrid(bool */ void QCPGrid::setAntialiasedZeroLine(bool enabled) { - mAntialiasedZeroLine = enabled; + mAntialiasedZeroLine = enabled; } /*! @@ -3732,7 +3732,7 @@ void QCPGrid::setAntialiasedZeroLine(boo */ void QCPGrid::setPen(const QPen &pen) { - mPen = pen; + mPen = pen; } /*! @@ -3740,7 +3740,7 @@ void QCPGrid::setPen(const QPen &pen) */ void QCPGrid::setSubGridPen(const QPen &pen) { - mSubGridPen = pen; + mSubGridPen = pen; } /*! @@ -3751,7 +3751,7 @@ void QCPGrid::setSubGridPen(const QPen & */ void QCPGrid::setZeroLinePen(const QPen &pen) { - mZeroLinePen = pen; + mZeroLinePen = pen; } /*! \internal @@ -3769,7 +3769,7 @@ void QCPGrid::setZeroLinePen(const QPen */ void QCPGrid::applyDefaultAntialiasingHint(QCPPainter *painter) const { - applyAntialiasingHint(painter, mAntialiased, QCP::aeGrid); + applyAntialiasingHint(painter, mAntialiased, QCP::aeGrid); } /*! \internal @@ -3779,11 +3779,11 @@ void QCPGrid::applyDefaultAntialiasingHi */ void QCPGrid::draw(QCPPainter *painter) { - if (!mParentAxis) { qDebug() << Q_FUNC_INFO << "invalid parent axis"; return; } - - if (mSubGridVisible) - drawSubGridLines(painter); - drawGridLines(painter); + if (!mParentAxis) { qDebug() << Q_FUNC_INFO << "invalid parent axis"; return; } + + if (mSubGridVisible) + drawSubGridLines(painter); + drawGridLines(painter); } /*! \internal @@ -3794,68 +3794,68 @@ void QCPGrid::draw(QCPPainter *painter) */ void QCPGrid::drawGridLines(QCPPainter *painter) const { - if (!mParentAxis) { qDebug() << Q_FUNC_INFO << "invalid parent axis"; return; } - - int lowTick = mParentAxis->mLowestVisibleTick; - int highTick = mParentAxis->mHighestVisibleTick; - double t; // helper variable, result of coordinate-to-pixel transforms - if (mParentAxis->orientation() == Qt::Horizontal) - { - // draw zeroline: - int zeroLineIndex = -1; - if (mZeroLinePen.style() != Qt::NoPen && mParentAxis->mRange.lower < 0 && mParentAxis->mRange.upper > 0) - { - applyAntialiasingHint(painter, mAntialiasedZeroLine, QCP::aeZeroLine); - painter->setPen(mZeroLinePen); - double epsilon = mParentAxis->range().size()*1E-6; // for comparing double to zero - for (int i=lowTick; i <= highTick; ++i) - { - if (qAbs(mParentAxis->mTickVector.at(i)) < epsilon) + if (!mParentAxis) { qDebug() << Q_FUNC_INFO << "invalid parent axis"; return; } + + int lowTick = mParentAxis->mLowestVisibleTick; + int highTick = mParentAxis->mHighestVisibleTick; + double t; // helper variable, result of coordinate-to-pixel transforms + if (mParentAxis->orientation() == Qt::Horizontal) + { + // draw zeroline: + int zeroLineIndex = -1; + if (mZeroLinePen.style() != Qt::NoPen && mParentAxis->mRange.lower < 0 && mParentAxis->mRange.upper > 0) + { + applyAntialiasingHint(painter, mAntialiasedZeroLine, QCP::aeZeroLine); + painter->setPen(mZeroLinePen); + double epsilon = mParentAxis->range().size()*1E-6; // for comparing double to zero + for (int i=lowTick; i <= highTick; ++i) + { + if (qAbs(mParentAxis->mTickVector.at(i)) < epsilon) { - zeroLineIndex = i; - t = mParentAxis->coordToPixel(mParentAxis->mTickVector.at(i)); // x - painter->drawLine(QLineF(t, mParentAxis->mAxisRect->bottom(), t, mParentAxis->mAxisRect->top())); - break; + zeroLineIndex = i; + t = mParentAxis->coordToPixel(mParentAxis->mTickVector.at(i)); // x + painter->drawLine(QLineF(t, mParentAxis->mAxisRect->bottom(), t, mParentAxis->mAxisRect->top())); + break; } } } - // draw grid lines: - applyDefaultAntialiasingHint(painter); - painter->setPen(mPen); - for (int i=lowTick; i <= highTick; ++i) - { - if (i == zeroLineIndex) continue; // don't draw a gridline on top of the zeroline - t = mParentAxis->coordToPixel(mParentAxis->mTickVector.at(i)); // x - painter->drawLine(QLineF(t, mParentAxis->mAxisRect->bottom(), t, mParentAxis->mAxisRect->top())); - } - } else - { - // draw zeroline: - int zeroLineIndex = -1; - if (mZeroLinePen.style() != Qt::NoPen && mParentAxis->mRange.lower < 0 && mParentAxis->mRange.upper > 0) - { - applyAntialiasingHint(painter, mAntialiasedZeroLine, QCP::aeZeroLine); - painter->setPen(mZeroLinePen); - double epsilon = mParentAxis->mRange.size()*1E-6; // for comparing double to zero - for (int i=lowTick; i <= highTick; ++i) - { - if (qAbs(mParentAxis->mTickVector.at(i)) < epsilon) + // draw grid lines: + applyDefaultAntialiasingHint(painter); + painter->setPen(mPen); + for (int i=lowTick; i <= highTick; ++i) + { + if (i == zeroLineIndex) continue; // don't draw a gridline on top of the zeroline + t = mParentAxis->coordToPixel(mParentAxis->mTickVector.at(i)); // x + painter->drawLine(QLineF(t, mParentAxis->mAxisRect->bottom(), t, mParentAxis->mAxisRect->top())); + } + } else + { + // draw zeroline: + int zeroLineIndex = -1; + if (mZeroLinePen.style() != Qt::NoPen && mParentAxis->mRange.lower < 0 && mParentAxis->mRange.upper > 0) + { + applyAntialiasingHint(painter, mAntialiasedZeroLine, QCP::aeZeroLine); + painter->setPen(mZeroLinePen); + double epsilon = mParentAxis->mRange.size()*1E-6; // for comparing double to zero + for (int i=lowTick; i <= highTick; ++i) + { + if (qAbs(mParentAxis->mTickVector.at(i)) < epsilon) { - zeroLineIndex = i; - t = mParentAxis->coordToPixel(mParentAxis->mTickVector.at(i)); // y - painter->drawLine(QLineF(mParentAxis->mAxisRect->left(), t, mParentAxis->mAxisRect->right(), t)); - break; + zeroLineIndex = i; + t = mParentAxis->coordToPixel(mParentAxis->mTickVector.at(i)); // y + painter->drawLine(QLineF(mParentAxis->mAxisRect->left(), t, mParentAxis->mAxisRect->right(), t)); + break; } } } - // draw grid lines: - applyDefaultAntialiasingHint(painter); - painter->setPen(mPen); - for (int i=lowTick; i <= highTick; ++i) - { - if (i == zeroLineIndex) continue; // don't draw a gridline on top of the zeroline - t = mParentAxis->coordToPixel(mParentAxis->mTickVector.at(i)); // y - painter->drawLine(QLineF(mParentAxis->mAxisRect->left(), t, mParentAxis->mAxisRect->right(), t)); + // draw grid lines: + applyDefaultAntialiasingHint(painter); + painter->setPen(mPen); + for (int i=lowTick; i <= highTick; ++i) + { + if (i == zeroLineIndex) continue; // don't draw a gridline on top of the zeroline + t = mParentAxis->coordToPixel(mParentAxis->mTickVector.at(i)); // y + painter->drawLine(QLineF(mParentAxis->mAxisRect->left(), t, mParentAxis->mAxisRect->right(), t)); } } } @@ -3868,24 +3868,24 @@ void QCPGrid::drawGridLines(QCPPainter * */ void QCPGrid::drawSubGridLines(QCPPainter *painter) const { - if (!mParentAxis) { qDebug() << Q_FUNC_INFO << "invalid parent axis"; return; } - - applyAntialiasingHint(painter, mAntialiasedSubGrid, QCP::aeSubGrid); - double t; // helper variable, result of coordinate-to-pixel transforms - painter->setPen(mSubGridPen); - if (mParentAxis->orientation() == Qt::Horizontal) - { - for (int i=0; imSubTickVector.size(); ++i) - { - t = mParentAxis->coordToPixel(mParentAxis->mSubTickVector.at(i)); // x - painter->drawLine(QLineF(t, mParentAxis->mAxisRect->bottom(), t, mParentAxis->mAxisRect->top())); - } - } else - { - for (int i=0; imSubTickVector.size(); ++i) - { - t = mParentAxis->coordToPixel(mParentAxis->mSubTickVector.at(i)); // y - painter->drawLine(QLineF(mParentAxis->mAxisRect->left(), t, mParentAxis->mAxisRect->right(), t)); + if (!mParentAxis) { qDebug() << Q_FUNC_INFO << "invalid parent axis"; return; } + + applyAntialiasingHint(painter, mAntialiasedSubGrid, QCP::aeSubGrid); + double t; // helper variable, result of coordinate-to-pixel transforms + painter->setPen(mSubGridPen); + if (mParentAxis->orientation() == Qt::Horizontal) + { + for (int i=0; imSubTickVector.size(); ++i) + { + t = mParentAxis->coordToPixel(mParentAxis->mSubTickVector.at(i)); // x + painter->drawLine(QLineF(t, mParentAxis->mAxisRect->bottom(), t, mParentAxis->mAxisRect->top())); + } + } else + { + for (int i=0; imSubTickVector.size(); ++i) + { + t = mParentAxis->coordToPixel(mParentAxis->mSubTickVector.at(i)); // y + painter->drawLine(QLineF(mParentAxis->mAxisRect->left(), t, mParentAxis->mAxisRect->right(), t)); } } } @@ -3994,167 +3994,167 @@ void QCPGrid::drawSubGridLines(QCPPainte create them manually and then inject them also via \ref QCPAxisRect::addAxis. */ QCPAxis::QCPAxis(QCPAxisRect *parent, AxisType type) : - QCPLayerable(parent->parentPlot(), QString(), parent), - // axis base: - mAxisType(type), - mAxisRect(parent), - mPadding(5), - mOrientation(orientation(type)), - mSelectableParts(spAxis | spTickLabels | spAxisLabel), - mSelectedParts(spNone), - mBasePen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)), - mSelectedBasePen(QPen(Qt::blue, 2)), - // axis label: - mLabel(), - mLabelFont(mParentPlot->font()), - mSelectedLabelFont(QFont(mLabelFont.family(), mLabelFont.pointSize(), QFont::Bold)), - mLabelColor(Qt::black), - mSelectedLabelColor(Qt::blue), - // tick labels: - mTickLabels(true), - mAutoTickLabels(true), - mTickLabelType(ltNumber), - mTickLabelFont(mParentPlot->font()), - mSelectedTickLabelFont(QFont(mTickLabelFont.family(), mTickLabelFont.pointSize(), QFont::Bold)), - mTickLabelColor(Qt::black), - mSelectedTickLabelColor(Qt::blue), - mDateTimeFormat(QLatin1String("hh:mm:ss\ndd.MM.yy")), - mDateTimeSpec(Qt::LocalTime), - mNumberPrecision(6), - mNumberFormatChar('g'), - mNumberBeautifulPowers(true), - // ticks and subticks: - mTicks(true), - mTickStep(1), - mSubTickCount(4), - mAutoTickCount(6), - mAutoTicks(true), - mAutoTickStep(true), - mAutoSubTicks(true), - mTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)), - mSelectedTickPen(QPen(Qt::blue, 2)), - mSubTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)), - mSelectedSubTickPen(QPen(Qt::blue, 2)), - // scale and range: - mRange(0, 5), - mRangeReversed(false), - mScaleType(stLinear), - mScaleLogBase(10), - mScaleLogBaseLogInv(1.0/qLn(mScaleLogBase)), - // internal members: - mGrid(new QCPGrid(this)), - mAxisPainter(new QCPAxisPainterPrivate(parent->parentPlot())), - mLowestVisibleTick(0), - mHighestVisibleTick(-1), - mCachedMarginValid(false), - mCachedMargin(0) -{ - mGrid->setVisible(false); - setAntialiased(false); - setLayer(mParentPlot->currentLayer()); // it's actually on that layer already, but we want it in front of the grid, so we place it on there again - - if (type == atTop) - { - setTickLabelPadding(3); - setLabelPadding(6); + QCPLayerable(parent->parentPlot(), QString(), parent), + // axis base: + mAxisType(type), + mAxisRect(parent), + mPadding(5), + mOrientation(orientation(type)), + mSelectableParts(spAxis | spTickLabels | spAxisLabel), + mSelectedParts(spNone), + mBasePen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)), + mSelectedBasePen(QPen(Qt::blue, 2)), + // axis label: + mLabel(), + mLabelFont(mParentPlot->font()), + mSelectedLabelFont(QFont(mLabelFont.family(), mLabelFont.pointSize(), QFont::Bold)), + mLabelColor(Qt::black), + mSelectedLabelColor(Qt::blue), + // tick labels: + mTickLabels(true), + mAutoTickLabels(true), + mTickLabelType(ltNumber), + mTickLabelFont(mParentPlot->font()), + mSelectedTickLabelFont(QFont(mTickLabelFont.family(), mTickLabelFont.pointSize(), QFont::Bold)), + mTickLabelColor(Qt::black), + mSelectedTickLabelColor(Qt::blue), + mDateTimeFormat(QLatin1String("hh:mm:ss\ndd.MM.yy")), + mDateTimeSpec(Qt::LocalTime), + mNumberPrecision(6), + mNumberFormatChar('g'), + mNumberBeautifulPowers(true), + // ticks and subticks: + mTicks(true), + mTickStep(1), + mSubTickCount(4), + mAutoTickCount(6), + mAutoTicks(true), + mAutoTickStep(true), + mAutoSubTicks(true), + mTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)), + mSelectedTickPen(QPen(Qt::blue, 2)), + mSubTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)), + mSelectedSubTickPen(QPen(Qt::blue, 2)), + // scale and range: + mRange(0, 5), + mRangeReversed(false), + mScaleType(stLinear), + mScaleLogBase(10), + mScaleLogBaseLogInv(1.0/qLn(mScaleLogBase)), + // internal members: + mGrid(new QCPGrid(this)), + mAxisPainter(new QCPAxisPainterPrivate(parent->parentPlot())), + mLowestVisibleTick(0), + mHighestVisibleTick(-1), + mCachedMarginValid(false), + mCachedMargin(0) +{ + mGrid->setVisible(false); + setAntialiased(false); + setLayer(mParentPlot->currentLayer()); // it's actually on that layer already, but we want it in front of the grid, so we place it on there again + + if (type == atTop) + { + setTickLabelPadding(3); + setLabelPadding(6); } else if (type == atRight) { - setTickLabelPadding(7); - setLabelPadding(12); + setTickLabelPadding(7); + setLabelPadding(12); } else if (type == atBottom) { - setTickLabelPadding(3); - setLabelPadding(3); + setTickLabelPadding(3); + setLabelPadding(3); } else if (type == atLeft) { - setTickLabelPadding(5); - setLabelPadding(10); + setTickLabelPadding(5); + setLabelPadding(10); } } QCPAxis::~QCPAxis() { - delete mAxisPainter; + delete mAxisPainter; } /* No documentation as it is a property getter */ int QCPAxis::tickLabelPadding() const { - return mAxisPainter->tickLabelPadding; + return mAxisPainter->tickLabelPadding; } /* No documentation as it is a property getter */ double QCPAxis::tickLabelRotation() const { - return mAxisPainter->tickLabelRotation; + return mAxisPainter->tickLabelRotation; } /* No documentation as it is a property getter */ QCPAxis::LabelSide QCPAxis::tickLabelSide() const { - return mAxisPainter->tickLabelSide; + return mAxisPainter->tickLabelSide; } /* No documentation as it is a property getter */ QString QCPAxis::numberFormat() const { - QString result; - result.append(mNumberFormatChar); - if (mNumberBeautifulPowers) - { - result.append(QLatin1Char('b')); - if (mAxisPainter->numberMultiplyCross) - result.append(QLatin1Char('c')); - } - return result; + QString result; + result.append(mNumberFormatChar); + if (mNumberBeautifulPowers) + { + result.append(QLatin1Char('b')); + if (mAxisPainter->numberMultiplyCross) + result.append(QLatin1Char('c')); + } + return result; } /* No documentation as it is a property getter */ int QCPAxis::tickLengthIn() const { - return mAxisPainter->tickLengthIn; + return mAxisPainter->tickLengthIn; } /* No documentation as it is a property getter */ int QCPAxis::tickLengthOut() const { - return mAxisPainter->tickLengthOut; + return mAxisPainter->tickLengthOut; } /* No documentation as it is a property getter */ int QCPAxis::subTickLengthIn() const { - return mAxisPainter->subTickLengthIn; + return mAxisPainter->subTickLengthIn; } /* No documentation as it is a property getter */ int QCPAxis::subTickLengthOut() const { - return mAxisPainter->subTickLengthOut; + return mAxisPainter->subTickLengthOut; } /* No documentation as it is a property getter */ int QCPAxis::labelPadding() const { - return mAxisPainter->labelPadding; + return mAxisPainter->labelPadding; } /* No documentation as it is a property getter */ int QCPAxis::offset() const { - return mAxisPainter->offset; + return mAxisPainter->offset; } /* No documentation as it is a property getter */ QCPLineEnding QCPAxis::lowerEnding() const { - return mAxisPainter->lowerEnding; + return mAxisPainter->lowerEnding; } /* No documentation as it is a property getter */ QCPLineEnding QCPAxis::upperEnding() const { - return mAxisPainter->upperEnding; + return mAxisPainter->upperEnding; } /*! @@ -4172,13 +4172,13 @@ QCPLineEnding QCPAxis::upperEnding() con */ void QCPAxis::setScaleType(QCPAxis::ScaleType type) { - if (mScaleType != type) - { - mScaleType = type; - if (mScaleType == stLogarithmic) - setRange(mRange.sanitizedForLogScale()); - mCachedMarginValid = false; - emit scaleTypeChanged(mScaleType); + if (mScaleType != type) + { + mScaleType = type; + if (mScaleType == stLogarithmic) + setRange(mRange.sanitizedForLogScale()); + mCachedMarginValid = false; + emit scaleTypeChanged(mScaleType); } } @@ -4191,13 +4191,13 @@ void QCPAxis::setScaleType(QCPAxis::Scal */ void QCPAxis::setScaleLogBase(double base) { - if (base > 1) - { - mScaleLogBase = base; - mScaleLogBaseLogInv = 1.0/qLn(mScaleLogBase); // buffer for faster baseLog() calculation - mCachedMarginValid = false; - } else - qDebug() << Q_FUNC_INFO << "Invalid logarithmic scale base (must be greater 1):" << base; + if (base > 1) + { + mScaleLogBase = base; + mScaleLogBaseLogInv = 1.0/qLn(mScaleLogBase); // buffer for faster baseLog() calculation + mCachedMarginValid = false; + } else + qDebug() << Q_FUNC_INFO << "Invalid logarithmic scale base (must be greater 1):" << base; } /*! @@ -4210,21 +4210,21 @@ void QCPAxis::setScaleLogBase(double bas */ void QCPAxis::setRange(const QCPRange &range) { - if (range.lower == mRange.lower && range.upper == mRange.upper) - return; - - if (!QCPRange::validRange(range)) return; - QCPRange oldRange = mRange; - if (mScaleType == stLogarithmic) - { - mRange = range.sanitizedForLogScale(); - } else - { - mRange = range.sanitizedForLinScale(); - } - mCachedMarginValid = false; - emit rangeChanged(mRange); - emit rangeChanged(mRange, oldRange); + if (range.lower == mRange.lower && range.upper == mRange.upper) + return; + + if (!QCPRange::validRange(range)) return; + QCPRange oldRange = mRange; + if (mScaleType == stLogarithmic) + { + mRange = range.sanitizedForLogScale(); + } else + { + mRange = range.sanitizedForLinScale(); + } + mCachedMarginValid = false; + emit rangeChanged(mRange); + emit rangeChanged(mRange, oldRange); } /*! @@ -4239,10 +4239,10 @@ void QCPAxis::setRange(const QCPRange &r */ void QCPAxis::setSelectableParts(const SelectableParts &selectable) { - if (mSelectableParts != selectable) - { - mSelectableParts = selectable; - emit selectableChanged(mSelectableParts); + if (mSelectableParts != selectable) + { + mSelectableParts = selectable; + emit selectableChanged(mSelectableParts); } } @@ -4263,10 +4263,10 @@ void QCPAxis::setSelectableParts(const S */ void QCPAxis::setSelectedParts(const SelectableParts &selected) { - if (mSelectedParts != selected) - { - mSelectedParts = selected; - emit selectionChanged(mSelectedParts); + if (mSelectedParts != selected) + { + mSelectedParts = selected; + emit selectionChanged(mSelectedParts); } } @@ -4281,23 +4281,23 @@ void QCPAxis::setSelectedParts(const Sel */ void QCPAxis::setRange(double lower, double upper) { - if (lower == mRange.lower && upper == mRange.upper) - return; - - if (!QCPRange::validRange(lower, upper)) return; - QCPRange oldRange = mRange; - mRange.lower = lower; - mRange.upper = upper; - if (mScaleType == stLogarithmic) - { - mRange = mRange.sanitizedForLogScale(); - } else - { - mRange = mRange.sanitizedForLinScale(); - } - mCachedMarginValid = false; - emit rangeChanged(mRange); - emit rangeChanged(mRange, oldRange); + if (lower == mRange.lower && upper == mRange.upper) + return; + + if (!QCPRange::validRange(lower, upper)) return; + QCPRange oldRange = mRange; + mRange.lower = lower; + mRange.upper = upper; + if (mScaleType == stLogarithmic) + { + mRange = mRange.sanitizedForLogScale(); + } else + { + mRange = mRange.sanitizedForLinScale(); + } + mCachedMarginValid = false; + emit rangeChanged(mRange); + emit rangeChanged(mRange, oldRange); } /*! @@ -4313,12 +4313,12 @@ void QCPAxis::setRange(double lower, dou */ void QCPAxis::setRange(double position, double size, Qt::AlignmentFlag alignment) { - if (alignment == Qt::AlignLeft) - setRange(position, position+size); - else if (alignment == Qt::AlignRight) - setRange(position-size, position); - else // alignment == Qt::AlignCenter - setRange(position-size/2.0, position+size/2.0); + if (alignment == Qt::AlignLeft) + setRange(position, position+size); + else if (alignment == Qt::AlignRight) + setRange(position-size, position); + else // alignment == Qt::AlignCenter + setRange(position-size/2.0, position+size/2.0); } /*! @@ -4327,21 +4327,21 @@ void QCPAxis::setRange(double position, */ void QCPAxis::setRangeLower(double lower) { - if (mRange.lower == lower) - return; - - QCPRange oldRange = mRange; - mRange.lower = lower; - if (mScaleType == stLogarithmic) - { - mRange = mRange.sanitizedForLogScale(); - } else - { - mRange = mRange.sanitizedForLinScale(); - } - mCachedMarginValid = false; - emit rangeChanged(mRange); - emit rangeChanged(mRange, oldRange); + if (mRange.lower == lower) + return; + + QCPRange oldRange = mRange; + mRange.lower = lower; + if (mScaleType == stLogarithmic) + { + mRange = mRange.sanitizedForLogScale(); + } else + { + mRange = mRange.sanitizedForLinScale(); + } + mCachedMarginValid = false; + emit rangeChanged(mRange); + emit rangeChanged(mRange, oldRange); } /*! @@ -4350,21 +4350,21 @@ void QCPAxis::setRangeLower(double lower */ void QCPAxis::setRangeUpper(double upper) { - if (mRange.upper == upper) - return; - - QCPRange oldRange = mRange; - mRange.upper = upper; - if (mScaleType == stLogarithmic) - { - mRange = mRange.sanitizedForLogScale(); - } else - { - mRange = mRange.sanitizedForLinScale(); - } - mCachedMarginValid = false; - emit rangeChanged(mRange); - emit rangeChanged(mRange, oldRange); + if (mRange.upper == upper) + return; + + QCPRange oldRange = mRange; + mRange.upper = upper; + if (mScaleType == stLogarithmic) + { + mRange = mRange.sanitizedForLogScale(); + } else + { + mRange = mRange.sanitizedForLinScale(); + } + mCachedMarginValid = false; + emit rangeChanged(mRange); + emit rangeChanged(mRange, oldRange); } /*! @@ -4378,10 +4378,10 @@ void QCPAxis::setRangeUpper(double upper */ void QCPAxis::setRangeReversed(bool reversed) { - if (mRangeReversed != reversed) - { - mRangeReversed = reversed; - mCachedMarginValid = false; + if (mRangeReversed != reversed) + { + mRangeReversed = reversed; + mCachedMarginValid = false; } } @@ -4402,10 +4402,10 @@ void QCPAxis::setRangeReversed(bool reve */ void QCPAxis::setAutoTicks(bool on) { - if (mAutoTicks != on) - { - mAutoTicks = on; - mCachedMarginValid = false; + if (mAutoTicks != on) + { + mAutoTicks = on; + mCachedMarginValid = false; } } @@ -4422,14 +4422,14 @@ void QCPAxis::setAutoTicks(bool on) */ void QCPAxis::setAutoTickCount(int approximateCount) { - if (mAutoTickCount != approximateCount) - { - if (approximateCount > 0) - { - mAutoTickCount = approximateCount; - mCachedMarginValid = false; + if (mAutoTickCount != approximateCount) + { + if (approximateCount > 0) + { + mAutoTickCount = approximateCount; + mCachedMarginValid = false; } else - qDebug() << Q_FUNC_INFO << "approximateCount must be greater than zero:" << approximateCount; + qDebug() << Q_FUNC_INFO << "approximateCount must be greater than zero:" << approximateCount; } } @@ -4450,10 +4450,10 @@ void QCPAxis::setAutoTickCount(int appro */ void QCPAxis::setAutoTickLabels(bool on) { - if (mAutoTickLabels != on) - { - mAutoTickLabels = on; - mCachedMarginValid = false; + if (mAutoTickLabels != on) + { + mAutoTickLabels = on; + mCachedMarginValid = false; } } @@ -4471,10 +4471,10 @@ void QCPAxis::setAutoTickLabels(bool on) */ void QCPAxis::setAutoTickStep(bool on) { - if (mAutoTickStep != on) - { - mAutoTickStep = on; - mCachedMarginValid = false; + if (mAutoTickStep != on) + { + mAutoTickStep = on; + mCachedMarginValid = false; } } @@ -4489,10 +4489,10 @@ void QCPAxis::setAutoTickStep(bool on) */ void QCPAxis::setAutoSubTicks(bool on) { - if (mAutoSubTicks != on) - { - mAutoSubTicks = on; - mCachedMarginValid = false; + if (mAutoSubTicks != on) + { + mAutoSubTicks = on; + mCachedMarginValid = false; } } @@ -4504,10 +4504,10 @@ void QCPAxis::setAutoSubTicks(bool on) */ void QCPAxis::setTicks(bool show) { - if (mTicks != show) - { - mTicks = show; - mCachedMarginValid = false; + if (mTicks != show) + { + mTicks = show; + mCachedMarginValid = false; } } @@ -4516,10 +4516,10 @@ void QCPAxis::setTicks(bool show) */ void QCPAxis::setTickLabels(bool show) { - if (mTickLabels != show) - { - mTickLabels = show; - mCachedMarginValid = false; + if (mTickLabels != show) + { + mTickLabels = show; + mCachedMarginValid = false; } } @@ -4529,10 +4529,10 @@ void QCPAxis::setTickLabels(bool show) */ void QCPAxis::setTickLabelPadding(int padding) { - if (mAxisPainter->tickLabelPadding != padding) - { - mAxisPainter->tickLabelPadding = padding; - mCachedMarginValid = false; + if (mAxisPainter->tickLabelPadding != padding) + { + mAxisPainter->tickLabelPadding = padding; + mCachedMarginValid = false; } } @@ -4559,10 +4559,10 @@ void QCPAxis::setTickLabelPadding(int pa */ void QCPAxis::setTickLabelType(LabelType type) { - if (mTickLabelType != type) - { - mTickLabelType = type; - mCachedMarginValid = false; + if (mTickLabelType != type) + { + mTickLabelType = type; + mCachedMarginValid = false; } } @@ -4573,10 +4573,10 @@ void QCPAxis::setTickLabelType(LabelType */ void QCPAxis::setTickLabelFont(const QFont &font) { - if (font != mTickLabelFont) - { - mTickLabelFont = font; - mCachedMarginValid = false; + if (font != mTickLabelFont) + { + mTickLabelFont = font; + mCachedMarginValid = false; } } @@ -4587,10 +4587,10 @@ void QCPAxis::setTickLabelFont(const QFo */ void QCPAxis::setTickLabelColor(const QColor &color) { - if (color != mTickLabelColor) - { - mTickLabelColor = color; - mCachedMarginValid = false; + if (color != mTickLabelColor) + { + mTickLabelColor = color; + mCachedMarginValid = false; } } @@ -4605,10 +4605,10 @@ void QCPAxis::setTickLabelColor(const QC */ void QCPAxis::setTickLabelRotation(double degrees) { - if (!qFuzzyIsNull(degrees-mAxisPainter->tickLabelRotation)) - { - mAxisPainter->tickLabelRotation = qBound(-90.0, degrees, 90.0); - mCachedMarginValid = false; + if (!qFuzzyIsNull(degrees-mAxisPainter->tickLabelRotation)) + { + mAxisPainter->tickLabelRotation = qBound(-90.0, degrees, 90.0); + mCachedMarginValid = false; } } @@ -4621,8 +4621,8 @@ void QCPAxis::setTickLabelRotation(doubl */ void QCPAxis::setTickLabelSide(LabelSide side) { - mAxisPainter->tickLabelSide = side; - mCachedMarginValid = false; + mAxisPainter->tickLabelSide = side; + mCachedMarginValid = false; } /*! @@ -4635,10 +4635,10 @@ void QCPAxis::setTickLabelSide(LabelSide */ void QCPAxis::setDateTimeFormat(const QString &format) { - if (mDateTimeFormat != format) - { - mDateTimeFormat = format; - mCachedMarginValid = false; + if (mDateTimeFormat != format) + { + mDateTimeFormat = format; + mCachedMarginValid = false; } } @@ -4654,7 +4654,7 @@ void QCPAxis::setDateTimeFormat(const QS */ void QCPAxis::setDateTimeSpec(const Qt::TimeSpec &timeSpec) { - mDateTimeSpec = timeSpec; + mDateTimeSpec = timeSpec; } /*! @@ -4695,56 +4695,56 @@ void QCPAxis::setDateTimeSpec(const Qt:: */ void QCPAxis::setNumberFormat(const QString &formatCode) { - if (formatCode.isEmpty()) - { - qDebug() << Q_FUNC_INFO << "Passed formatCode is empty"; - return; - } - mCachedMarginValid = false; - - // interpret first char as number format char: - QString allowedFormatChars(QLatin1String("eEfgG")); - if (allowedFormatChars.contains(formatCode.at(0))) - { - mNumberFormatChar = QLatin1Char(formatCode.at(0).toLatin1()); - } else - { - qDebug() << Q_FUNC_INFO << "Invalid number format code (first char not in 'eEfgG'):" << formatCode; - return; - } - if (formatCode.length() < 2) - { - mNumberBeautifulPowers = false; - mAxisPainter->numberMultiplyCross = false; - return; - } - - // interpret second char as indicator for beautiful decimal powers: - if (formatCode.at(1) == QLatin1Char('b') && (mNumberFormatChar == QLatin1Char('e') || mNumberFormatChar == QLatin1Char('g'))) - { - mNumberBeautifulPowers = true; - } else - { - qDebug() << Q_FUNC_INFO << "Invalid number format code (second char not 'b' or first char neither 'e' nor 'g'):" << formatCode; - return; - } - if (formatCode.length() < 3) - { - mAxisPainter->numberMultiplyCross = false; - return; - } - - // interpret third char as indicator for dot or cross multiplication symbol: - if (formatCode.at(2) == QLatin1Char('c')) - { - mAxisPainter->numberMultiplyCross = true; + if (formatCode.isEmpty()) + { + qDebug() << Q_FUNC_INFO << "Passed formatCode is empty"; + return; + } + mCachedMarginValid = false; + + // interpret first char as number format char: + QString allowedFormatChars(QLatin1String("eEfgG")); + if (allowedFormatChars.contains(formatCode.at(0))) + { + mNumberFormatChar = QLatin1Char(formatCode.at(0).toLatin1()); + } else + { + qDebug() << Q_FUNC_INFO << "Invalid number format code (first char not in 'eEfgG'):" << formatCode; + return; + } + if (formatCode.length() < 2) + { + mNumberBeautifulPowers = false; + mAxisPainter->numberMultiplyCross = false; + return; + } + + // interpret second char as indicator for beautiful decimal powers: + if (formatCode.at(1) == QLatin1Char('b') && (mNumberFormatChar == QLatin1Char('e') || mNumberFormatChar == QLatin1Char('g'))) + { + mNumberBeautifulPowers = true; + } else + { + qDebug() << Q_FUNC_INFO << "Invalid number format code (second char not 'b' or first char neither 'e' nor 'g'):" << formatCode; + return; + } + if (formatCode.length() < 3) + { + mAxisPainter->numberMultiplyCross = false; + return; + } + + // interpret third char as indicator for dot or cross multiplication symbol: + if (formatCode.at(2) == QLatin1Char('c')) + { + mAxisPainter->numberMultiplyCross = true; } else if (formatCode.at(2) == QLatin1Char('d')) { - mAxisPainter->numberMultiplyCross = false; - } else - { - qDebug() << Q_FUNC_INFO << "Invalid number format code (third char neither 'c' nor 'd'):" << formatCode; - return; + mAxisPainter->numberMultiplyCross = false; + } else + { + qDebug() << Q_FUNC_INFO << "Invalid number format code (third char neither 'c' nor 'd'):" << formatCode; + return; } } @@ -4761,10 +4761,10 @@ void QCPAxis::setNumberFormat(const QStr */ void QCPAxis::setNumberPrecision(int precision) { - if (mNumberPrecision != precision) - { - mNumberPrecision = precision; - mCachedMarginValid = false; + if (mNumberPrecision != precision) + { + mNumberPrecision = precision; + mCachedMarginValid = false; } } @@ -4775,10 +4775,10 @@ void QCPAxis::setNumberPrecision(int pre */ void QCPAxis::setTickStep(double step) { - if (mTickStep != step) - { - mTickStep = step; - mCachedMarginValid = false; + if (mTickStep != step) + { + mTickStep = step; + mCachedMarginValid = false; } } @@ -4797,9 +4797,9 @@ void QCPAxis::setTickStep(double step) */ void QCPAxis::setTickVector(const QVector &vec) { - // don't check whether mTickVector != vec here, because it takes longer than we would save - mTickVector = vec; - mCachedMarginValid = false; + // don't check whether mTickVector != vec here, because it takes longer than we would save + mTickVector = vec; + mCachedMarginValid = false; } /*! @@ -4815,9 +4815,9 @@ void QCPAxis::setTickVector(const QVecto */ void QCPAxis::setTickVectorLabels(const QVector &vec) { - // don't check whether mTickVectorLabels != vec here, because it takes longer than we would save - mTickVectorLabels = vec; - mCachedMarginValid = false; + // don't check whether mTickVectorLabels != vec here, because it takes longer than we would save + mTickVectorLabels = vec; + mCachedMarginValid = false; } /*! @@ -4830,8 +4830,8 @@ void QCPAxis::setTickVectorLabels(const */ void QCPAxis::setTickLength(int inside, int outside) { - setTickLengthIn(inside); - setTickLengthOut(outside); + setTickLengthIn(inside); + setTickLengthOut(outside); } /*! @@ -4842,9 +4842,9 @@ void QCPAxis::setTickLength(int inside, */ void QCPAxis::setTickLengthIn(int inside) { - if (mAxisPainter->tickLengthIn != inside) - { - mAxisPainter->tickLengthIn = inside; + if (mAxisPainter->tickLengthIn != inside) + { + mAxisPainter->tickLengthIn = inside; } } @@ -4857,10 +4857,10 @@ void QCPAxis::setTickLengthIn(int inside */ void QCPAxis::setTickLengthOut(int outside) { - if (mAxisPainter->tickLengthOut != outside) - { - mAxisPainter->tickLengthOut = outside; - mCachedMarginValid = false; // only outside tick length can change margin + if (mAxisPainter->tickLengthOut != outside) + { + mAxisPainter->tickLengthOut = outside; + mCachedMarginValid = false; // only outside tick length can change margin } } @@ -4877,7 +4877,7 @@ void QCPAxis::setTickLengthOut(int outsi */ void QCPAxis::setSubTickCount(int count) { - mSubTickCount = count; + mSubTickCount = count; } /*! @@ -4890,8 +4890,8 @@ void QCPAxis::setSubTickCount(int count) */ void QCPAxis::setSubTickLength(int inside, int outside) { - setSubTickLengthIn(inside); - setSubTickLengthOut(outside); + setSubTickLengthIn(inside); + setSubTickLengthOut(outside); } /*! @@ -4902,9 +4902,9 @@ void QCPAxis::setSubTickLength(int insid */ void QCPAxis::setSubTickLengthIn(int inside) { - if (mAxisPainter->subTickLengthIn != inside) - { - mAxisPainter->subTickLengthIn = inside; + if (mAxisPainter->subTickLengthIn != inside) + { + mAxisPainter->subTickLengthIn = inside; } } @@ -4917,10 +4917,10 @@ void QCPAxis::setSubTickLengthIn(int ins */ void QCPAxis::setSubTickLengthOut(int outside) { - if (mAxisPainter->subTickLengthOut != outside) - { - mAxisPainter->subTickLengthOut = outside; - mCachedMarginValid = false; // only outside tick length can change margin + if (mAxisPainter->subTickLengthOut != outside) + { + mAxisPainter->subTickLengthOut = outside; + mCachedMarginValid = false; // only outside tick length can change margin } } @@ -4931,7 +4931,7 @@ void QCPAxis::setSubTickLengthOut(int ou */ void QCPAxis::setBasePen(const QPen &pen) { - mBasePen = pen; + mBasePen = pen; } /*! @@ -4941,7 +4941,7 @@ void QCPAxis::setBasePen(const QPen &pen */ void QCPAxis::setTickPen(const QPen &pen) { - mTickPen = pen; + mTickPen = pen; } /*! @@ -4951,7 +4951,7 @@ void QCPAxis::setTickPen(const QPen &pen */ void QCPAxis::setSubTickPen(const QPen &pen) { - mSubTickPen = pen; + mSubTickPen = pen; } /*! @@ -4961,10 +4961,10 @@ void QCPAxis::setSubTickPen(const QPen & */ void QCPAxis::setLabelFont(const QFont &font) { - if (mLabelFont != font) - { - mLabelFont = font; - mCachedMarginValid = false; + if (mLabelFont != font) + { + mLabelFont = font; + mCachedMarginValid = false; } } @@ -4975,7 +4975,7 @@ void QCPAxis::setLabelFont(const QFont & */ void QCPAxis::setLabelColor(const QColor &color) { - mLabelColor = color; + mLabelColor = color; } /*! @@ -4984,10 +4984,10 @@ void QCPAxis::setLabelColor(const QColor */ void QCPAxis::setLabel(const QString &str) { - if (mLabel != str) - { - mLabel = str; - mCachedMarginValid = false; + if (mLabel != str) + { + mLabel = str; + mCachedMarginValid = false; } } @@ -4998,10 +4998,10 @@ void QCPAxis::setLabel(const QString &st */ void QCPAxis::setLabelPadding(int padding) { - if (mAxisPainter->labelPadding != padding) - { - mAxisPainter->labelPadding = padding; - mCachedMarginValid = false; + if (mAxisPainter->labelPadding != padding) + { + mAxisPainter->labelPadding = padding; + mCachedMarginValid = false; } } @@ -5017,10 +5017,10 @@ void QCPAxis::setLabelPadding(int paddin */ void QCPAxis::setPadding(int padding) { - if (mPadding != padding) - { - mPadding = padding; - mCachedMarginValid = false; + if (mPadding != padding) + { + mPadding = padding; + mCachedMarginValid = false; } } @@ -5034,7 +5034,7 @@ void QCPAxis::setPadding(int padding) */ void QCPAxis::setOffset(int offset) { - mAxisPainter->offset = offset; + mAxisPainter->offset = offset; } /*! @@ -5044,10 +5044,10 @@ void QCPAxis::setOffset(int offset) */ void QCPAxis::setSelectedTickLabelFont(const QFont &font) { - if (font != mSelectedTickLabelFont) - { - mSelectedTickLabelFont = font; - // don't set mCachedMarginValid to false here because margin calculation is always done with non-selected fonts + if (font != mSelectedTickLabelFont) + { + mSelectedTickLabelFont = font; + // don't set mCachedMarginValid to false here because margin calculation is always done with non-selected fonts } } @@ -5058,8 +5058,8 @@ void QCPAxis::setSelectedTickLabelFont(c */ void QCPAxis::setSelectedLabelFont(const QFont &font) { - mSelectedLabelFont = font; - // don't set mCachedMarginValid to false here because margin calculation is always done with non-selected fonts + mSelectedLabelFont = font; + // don't set mCachedMarginValid to false here because margin calculation is always done with non-selected fonts } /*! @@ -5069,9 +5069,9 @@ void QCPAxis::setSelectedLabelFont(const */ void QCPAxis::setSelectedTickLabelColor(const QColor &color) { - if (color != mSelectedTickLabelColor) - { - mSelectedTickLabelColor = color; + if (color != mSelectedTickLabelColor) + { + mSelectedTickLabelColor = color; } } @@ -5082,7 +5082,7 @@ void QCPAxis::setSelectedTickLabelColor( */ void QCPAxis::setSelectedLabelColor(const QColor &color) { - mSelectedLabelColor = color; + mSelectedLabelColor = color; } /*! @@ -5092,7 +5092,7 @@ void QCPAxis::setSelectedLabelColor(cons */ void QCPAxis::setSelectedBasePen(const QPen &pen) { - mSelectedBasePen = pen; + mSelectedBasePen = pen; } /*! @@ -5102,7 +5102,7 @@ void QCPAxis::setSelectedBasePen(const Q */ void QCPAxis::setSelectedTickPen(const QPen &pen) { - mSelectedTickPen = pen; + mSelectedTickPen = pen; } /*! @@ -5112,7 +5112,7 @@ void QCPAxis::setSelectedTickPen(const Q */ void QCPAxis::setSelectedSubTickPen(const QPen &pen) { - mSelectedSubTickPen = pen; + mSelectedSubTickPen = pen; } /*! @@ -5127,7 +5127,7 @@ void QCPAxis::setSelectedSubTickPen(cons */ void QCPAxis::setLowerEnding(const QCPLineEnding &ending) { - mAxisPainter->lowerEnding = ending; + mAxisPainter->lowerEnding = ending; } /*! @@ -5142,7 +5142,7 @@ void QCPAxis::setLowerEnding(const QCPLi */ void QCPAxis::setUpperEnding(const QCPLineEnding &ending) { - mAxisPainter->upperEnding = ending; + mAxisPainter->upperEnding = ending; } /*! @@ -5154,19 +5154,19 @@ void QCPAxis::setUpperEnding(const QCPLi */ void QCPAxis::moveRange(double diff) { - QCPRange oldRange = mRange; - if (mScaleType == stLinear) - { - mRange.lower += diff; - mRange.upper += diff; + QCPRange oldRange = mRange; + if (mScaleType == stLinear) + { + mRange.lower += diff; + mRange.upper += diff; } else // mScaleType == stLogarithmic { - mRange.lower *= diff; - mRange.upper *= diff; - } - mCachedMarginValid = false; - emit rangeChanged(mRange); - emit rangeChanged(mRange, oldRange); + mRange.lower *= diff; + mRange.upper *= diff; + } + mCachedMarginValid = false; + emit rangeChanged(mRange); + emit rangeChanged(mRange, oldRange); } /*! @@ -5177,29 +5177,29 @@ void QCPAxis::moveRange(double diff) */ void QCPAxis::scaleRange(double factor, double center) { - QCPRange oldRange = mRange; - if (mScaleType == stLinear) - { - QCPRange newRange; - newRange.lower = (mRange.lower-center)*factor + center; - newRange.upper = (mRange.upper-center)*factor + center; - if (QCPRange::validRange(newRange)) - mRange = newRange.sanitizedForLinScale(); + QCPRange oldRange = mRange; + if (mScaleType == stLinear) + { + QCPRange newRange; + newRange.lower = (mRange.lower-center)*factor + center; + newRange.upper = (mRange.upper-center)*factor + center; + if (QCPRange::validRange(newRange)) + mRange = newRange.sanitizedForLinScale(); } else // mScaleType == stLogarithmic { - if ((mRange.upper < 0 && center < 0) || (mRange.upper > 0 && center > 0)) // make sure center has same sign as range - { - QCPRange newRange; - newRange.lower = qPow(mRange.lower/center, factor)*center; - newRange.upper = qPow(mRange.upper/center, factor)*center; - if (QCPRange::validRange(newRange)) - mRange = newRange.sanitizedForLogScale(); + if ((mRange.upper < 0 && center < 0) || (mRange.upper > 0 && center > 0)) // make sure center has same sign as range + { + QCPRange newRange; + newRange.lower = qPow(mRange.lower/center, factor)*center; + newRange.upper = qPow(mRange.upper/center, factor)*center; + if (QCPRange::validRange(newRange)) + mRange = newRange.sanitizedForLogScale(); } else - qDebug() << Q_FUNC_INFO << "Center of scaling operation doesn't lie in same logarithmic sign domain as range:" << center; - } - mCachedMarginValid = false; - emit rangeChanged(mRange); - emit rangeChanged(mRange, oldRange); + qDebug() << Q_FUNC_INFO << "Center of scaling operation doesn't lie in same logarithmic sign domain as range:" << center; + } + mCachedMarginValid = false; + emit rangeChanged(mRange); + emit rangeChanged(mRange, oldRange); } /*! @@ -5217,20 +5217,20 @@ void QCPAxis::scaleRange(double factor, */ void QCPAxis::setScaleRatio(const QCPAxis *otherAxis, double ratio) { - int otherPixelSize, ownPixelSize; - - if (otherAxis->orientation() == Qt::Horizontal) - otherPixelSize = otherAxis->axisRect()->width(); - else - otherPixelSize = otherAxis->axisRect()->height(); - - if (orientation() == Qt::Horizontal) - ownPixelSize = axisRect()->width(); - else - ownPixelSize = axisRect()->height(); - - double newRangeSize = ratio*otherAxis->range().size()*ownPixelSize/(double)otherPixelSize; - setRange(range().center(), newRangeSize, Qt::AlignCenter); + int otherPixelSize, ownPixelSize; + + if (otherAxis->orientation() == Qt::Horizontal) + otherPixelSize = otherAxis->axisRect()->width(); + else + otherPixelSize = otherAxis->axisRect()->height(); + + if (orientation() == Qt::Horizontal) + ownPixelSize = axisRect()->width(); + else + ownPixelSize = axisRect()->height(); + + double newRangeSize = ratio*otherAxis->range().size()*ownPixelSize/(double)otherPixelSize; + setRange(range().center(), newRangeSize, Qt::AlignCenter); } /*! @@ -5241,47 +5241,47 @@ void QCPAxis::setScaleRatio(const QCPAxi */ void QCPAxis::rescale(bool onlyVisiblePlottables) { - QList p = plottables(); - QCPRange newRange; - bool haveRange = false; - for (int i=0; irealVisibility() && onlyVisiblePlottables) - continue; - QCPRange plottableRange; - bool currentFoundRange; - QCPAbstractPlottable::SignDomain signDomain = QCPAbstractPlottable::sdBoth; - if (mScaleType == stLogarithmic) - signDomain = (mRange.upper < 0 ? QCPAbstractPlottable::sdNegative : QCPAbstractPlottable::sdPositive); - if (p.at(i)->keyAxis() == this) - plottableRange = p.at(i)->getKeyRange(currentFoundRange, signDomain); - else - plottableRange = p.at(i)->getValueRange(currentFoundRange, signDomain); - if (currentFoundRange) - { - if (!haveRange) - newRange = plottableRange; - else - newRange.expand(plottableRange); - haveRange = true; - } - } - if (haveRange) - { - if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable - { - double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason - if (mScaleType == stLinear) - { - newRange.lower = center-mRange.size()/2.0; - newRange.upper = center+mRange.size()/2.0; + QList p = plottables(); + QCPRange newRange; + bool haveRange = false; + for (int i=0; irealVisibility() && onlyVisiblePlottables) + continue; + QCPRange plottableRange; + bool currentFoundRange; + QCPAbstractPlottable::SignDomain signDomain = QCPAbstractPlottable::sdBoth; + if (mScaleType == stLogarithmic) + signDomain = (mRange.upper < 0 ? QCPAbstractPlottable::sdNegative : QCPAbstractPlottable::sdPositive); + if (p.at(i)->keyAxis() == this) + plottableRange = p.at(i)->getKeyRange(currentFoundRange, signDomain); + else + plottableRange = p.at(i)->getValueRange(currentFoundRange, signDomain); + if (currentFoundRange) + { + if (!haveRange) + newRange = plottableRange; + else + newRange.expand(plottableRange); + haveRange = true; + } + } + if (haveRange) + { + if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable + { + double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason + if (mScaleType == stLinear) + { + newRange.lower = center-mRange.size()/2.0; + newRange.upper = center+mRange.size()/2.0; } else // mScaleType == stLogarithmic { - newRange.lower = center/qSqrt(mRange.upper/mRange.lower); - newRange.upper = center*qSqrt(mRange.upper/mRange.lower); - } - } - setRange(newRange); + newRange.lower = center/qSqrt(mRange.upper/mRange.lower); + newRange.upper = center*qSqrt(mRange.upper/mRange.lower); + } + } + setRange(newRange); } } @@ -5290,35 +5290,35 @@ void QCPAxis::rescale(bool onlyVisiblePl */ double QCPAxis::pixelToCoord(double value) const { - if (orientation() == Qt::Horizontal) - { - if (mScaleType == stLinear) - { - if (!mRangeReversed) - return (value-mAxisRect->left())/(double)mAxisRect->width()*mRange.size()+mRange.lower; - else - return -(value-mAxisRect->left())/(double)mAxisRect->width()*mRange.size()+mRange.upper; + if (orientation() == Qt::Horizontal) + { + if (mScaleType == stLinear) + { + if (!mRangeReversed) + return (value-mAxisRect->left())/(double)mAxisRect->width()*mRange.size()+mRange.lower; + else + return -(value-mAxisRect->left())/(double)mAxisRect->width()*mRange.size()+mRange.upper; } else // mScaleType == stLogarithmic { - if (!mRangeReversed) - return qPow(mRange.upper/mRange.lower, (value-mAxisRect->left())/(double)mAxisRect->width())*mRange.lower; - else - return qPow(mRange.upper/mRange.lower, (mAxisRect->left()-value)/(double)mAxisRect->width())*mRange.upper; + if (!mRangeReversed) + return qPow(mRange.upper/mRange.lower, (value-mAxisRect->left())/(double)mAxisRect->width())*mRange.lower; + else + return qPow(mRange.upper/mRange.lower, (mAxisRect->left()-value)/(double)mAxisRect->width())*mRange.upper; } } else // orientation() == Qt::Vertical { - if (mScaleType == stLinear) - { - if (!mRangeReversed) - return (mAxisRect->bottom()-value)/(double)mAxisRect->height()*mRange.size()+mRange.lower; - else - return -(mAxisRect->bottom()-value)/(double)mAxisRect->height()*mRange.size()+mRange.upper; + if (mScaleType == stLinear) + { + if (!mRangeReversed) + return (mAxisRect->bottom()-value)/(double)mAxisRect->height()*mRange.size()+mRange.lower; + else + return -(mAxisRect->bottom()-value)/(double)mAxisRect->height()*mRange.size()+mRange.upper; } else // mScaleType == stLogarithmic { - if (!mRangeReversed) - return qPow(mRange.upper/mRange.lower, (mAxisRect->bottom()-value)/(double)mAxisRect->height())*mRange.lower; - else - return qPow(mRange.upper/mRange.lower, (value-mAxisRect->bottom())/(double)mAxisRect->height())*mRange.upper; + if (!mRangeReversed) + return qPow(mRange.upper/mRange.lower, (mAxisRect->bottom()-value)/(double)mAxisRect->height())*mRange.lower; + else + return qPow(mRange.upper/mRange.lower, (value-mAxisRect->bottom())/(double)mAxisRect->height())*mRange.upper; } } } @@ -5328,48 +5328,48 @@ double QCPAxis::pixelToCoord(double valu */ double QCPAxis::coordToPixel(double value) const { - if (orientation() == Qt::Horizontal) - { - if (mScaleType == stLinear) - { - if (!mRangeReversed) - return (value-mRange.lower)/mRange.size()*mAxisRect->width()+mAxisRect->left(); - else - return (mRange.upper-value)/mRange.size()*mAxisRect->width()+mAxisRect->left(); + if (orientation() == Qt::Horizontal) + { + if (mScaleType == stLinear) + { + if (!mRangeReversed) + return (value-mRange.lower)/mRange.size()*mAxisRect->width()+mAxisRect->left(); + else + return (mRange.upper-value)/mRange.size()*mAxisRect->width()+mAxisRect->left(); } else // mScaleType == stLogarithmic { - if (value >= 0 && mRange.upper < 0) // invalid value for logarithmic scale, just draw it outside visible range - return !mRangeReversed ? mAxisRect->right()+200 : mAxisRect->left()-200; - else if (value <= 0 && mRange.upper > 0) // invalid value for logarithmic scale, just draw it outside visible range - return !mRangeReversed ? mAxisRect->left()-200 : mAxisRect->right()+200; - else - { - if (!mRangeReversed) - return baseLog(value/mRange.lower)/baseLog(mRange.upper/mRange.lower)*mAxisRect->width()+mAxisRect->left(); - else - return baseLog(mRange.upper/value)/baseLog(mRange.upper/mRange.lower)*mAxisRect->width()+mAxisRect->left(); + if (value >= 0 && mRange.upper < 0) // invalid value for logarithmic scale, just draw it outside visible range + return !mRangeReversed ? mAxisRect->right()+200 : mAxisRect->left()-200; + else if (value <= 0 && mRange.upper > 0) // invalid value for logarithmic scale, just draw it outside visible range + return !mRangeReversed ? mAxisRect->left()-200 : mAxisRect->right()+200; + else + { + if (!mRangeReversed) + return baseLog(value/mRange.lower)/baseLog(mRange.upper/mRange.lower)*mAxisRect->width()+mAxisRect->left(); + else + return baseLog(mRange.upper/value)/baseLog(mRange.upper/mRange.lower)*mAxisRect->width()+mAxisRect->left(); } } } else // orientation() == Qt::Vertical { - if (mScaleType == stLinear) - { - if (!mRangeReversed) - return mAxisRect->bottom()-(value-mRange.lower)/mRange.size()*mAxisRect->height(); - else - return mAxisRect->bottom()-(mRange.upper-value)/mRange.size()*mAxisRect->height(); + if (mScaleType == stLinear) + { + if (!mRangeReversed) + return mAxisRect->bottom()-(value-mRange.lower)/mRange.size()*mAxisRect->height(); + else + return mAxisRect->bottom()-(mRange.upper-value)/mRange.size()*mAxisRect->height(); } else // mScaleType == stLogarithmic { - if (value >= 0 && mRange.upper < 0) // invalid value for logarithmic scale, just draw it outside visible range - return !mRangeReversed ? mAxisRect->top()-200 : mAxisRect->bottom()+200; - else if (value <= 0 && mRange.upper > 0) // invalid value for logarithmic scale, just draw it outside visible range - return !mRangeReversed ? mAxisRect->bottom()+200 : mAxisRect->top()-200; - else - { - if (!mRangeReversed) - return mAxisRect->bottom()-baseLog(value/mRange.lower)/baseLog(mRange.upper/mRange.lower)*mAxisRect->height(); - else - return mAxisRect->bottom()-baseLog(mRange.upper/value)/baseLog(mRange.upper/mRange.lower)*mAxisRect->height(); + if (value >= 0 && mRange.upper < 0) // invalid value for logarithmic scale, just draw it outside visible range + return !mRangeReversed ? mAxisRect->top()-200 : mAxisRect->bottom()+200; + else if (value <= 0 && mRange.upper > 0) // invalid value for logarithmic scale, just draw it outside visible range + return !mRangeReversed ? mAxisRect->bottom()+200 : mAxisRect->top()-200; + else + { + if (!mRangeReversed) + return mAxisRect->bottom()-baseLog(value/mRange.lower)/baseLog(mRange.upper/mRange.lower)*mAxisRect->height(); + else + return mAxisRect->bottom()-baseLog(mRange.upper/value)/baseLog(mRange.upper/mRange.lower)*mAxisRect->height(); } } } @@ -5386,30 +5386,30 @@ double QCPAxis::coordToPixel(double valu */ QCPAxis::SelectablePart QCPAxis::getPartAt(const QPointF &pos) const { - if (!mVisible) - return spNone; - - if (mAxisPainter->axisSelectionBox().contains(pos.toPoint())) - return spAxis; - else if (mAxisPainter->tickLabelsSelectionBox().contains(pos.toPoint())) - return spTickLabels; - else if (mAxisPainter->labelSelectionBox().contains(pos.toPoint())) - return spAxisLabel; - else - return spNone; + if (!mVisible) + return spNone; + + if (mAxisPainter->axisSelectionBox().contains(pos.toPoint())) + return spAxis; + else if (mAxisPainter->tickLabelsSelectionBox().contains(pos.toPoint())) + return spTickLabels; + else if (mAxisPainter->labelSelectionBox().contains(pos.toPoint())) + return spAxisLabel; + else + return spNone; } /* inherits documentation from base class */ double QCPAxis::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - if (!mParentPlot) return -1; - SelectablePart part = getPartAt(pos); - if ((onlySelectable && !mSelectableParts.testFlag(part)) || part == spNone) - return -1; - - if (details) - details->setValue(part); - return mParentPlot->selectionTolerance()*0.99; + if (!mParentPlot) return -1; + SelectablePart part = getPartAt(pos); + if ((onlySelectable && !mSelectableParts.testFlag(part)) || part == spNone) + return -1; + + if (details) + details->setValue(part); + return mParentPlot->selectionTolerance()*0.99; } /*! @@ -5421,15 +5421,15 @@ double QCPAxis::selectTest(const QPointF */ QList QCPAxis::plottables() const { - QList result; - if (!mParentPlot) return result; - - for (int i=0; imPlottables.size(); ++i) - { - if (mParentPlot->mPlottables.at(i)->keyAxis() == this ||mParentPlot->mPlottables.at(i)->valueAxis() == this) - result.append(mParentPlot->mPlottables.at(i)); - } - return result; + QList result; + if (!mParentPlot) return result; + + for (int i=0; imPlottables.size(); ++i) + { + if (mParentPlot->mPlottables.at(i)->keyAxis() == this ||mParentPlot->mPlottables.at(i)->valueAxis() == this) + result.append(mParentPlot->mPlottables.at(i)); + } + return result; } /*! @@ -5439,15 +5439,15 @@ QList QCPAxis::pl */ QList QCPAxis::graphs() const { - QList result; - if (!mParentPlot) return result; - - for (int i=0; imGraphs.size(); ++i) - { - if (mParentPlot->mGraphs.at(i)->keyAxis() == this || mParentPlot->mGraphs.at(i)->valueAxis() == this) - result.append(mParentPlot->mGraphs.at(i)); - } - return result; + QList result; + if (!mParentPlot) return result; + + for (int i=0; imGraphs.size(); ++i) + { + if (mParentPlot->mGraphs.at(i)->keyAxis() == this || mParentPlot->mGraphs.at(i)->valueAxis() == this) + result.append(mParentPlot->mGraphs.at(i)); + } + return result; } /*! @@ -5458,22 +5458,22 @@ QList QCPAxis::graphs() const */ QList QCPAxis::items() const { - QList result; - if (!mParentPlot) return result; - - for (int itemId=0; itemIdmItems.size(); ++itemId) - { - QList positions = mParentPlot->mItems.at(itemId)->positions(); - for (int posId=0; posIdkeyAxis() == this || positions.at(posId)->valueAxis() == this) - { - result.append(mParentPlot->mItems.at(itemId)); - break; - } - } - } - return result; + QList result; + if (!mParentPlot) return result; + + for (int itemId=0; itemIdmItems.size(); ++itemId) + { + QList positions = mParentPlot->mItems.at(itemId)->positions(); + for (int posId=0; posIdkeyAxis() == this || positions.at(posId)->valueAxis() == this) + { + result.append(mParentPlot->mItems.at(itemId)); + break; + } + } + } + return result; } /*! @@ -5482,7 +5482,7 @@ QList QCPAxis::items() */ QCPAxis::AxisType QCPAxis::marginSideToAxisType(QCP::MarginSide side) { - switch (side) + switch (side) { case QCP::msLeft: return atLeft; case QCP::msRight: return atRight; @@ -5490,8 +5490,8 @@ QCPAxis::AxisType QCPAxis::marginSideToA case QCP::msBottom: return atBottom; default: break; } - qDebug() << Q_FUNC_INFO << "Invalid margin side passed:" << (int)side; - return atLeft; + qDebug() << Q_FUNC_INFO << "Invalid margin side passed:" << (int)side; + return atLeft; } /*! @@ -5499,7 +5499,7 @@ QCPAxis::AxisType QCPAxis::marginSideToA */ QCPAxis::AxisType QCPAxis::opposite(QCPAxis::AxisType type) { - switch (type) + switch (type) { case atLeft: return atRight; break; case atRight: return atLeft; break; @@ -5518,85 +5518,85 @@ QCPAxis::AxisType QCPAxis::opposite(QCPA */ void QCPAxis::setupTickVectors() { - if (!mParentPlot) return; - if ((!mTicks && !mTickLabels && !mGrid->visible()) || mRange.size() <= 0) return; - - // fill tick vectors, either by auto generating or by notifying user to fill the vectors himself - if (mAutoTicks) - { - generateAutoTicks(); - } else - { - emit ticksRequest(); - } - - visibleTickBounds(mLowestVisibleTick, mHighestVisibleTick); - if (mTickVector.isEmpty()) - { - mSubTickVector.clear(); - return; - } - - // generate subticks between ticks: - mSubTickVector.resize((mTickVector.size()-1)*mSubTickCount); - if (mSubTickCount > 0) - { - double subTickStep = 0; - double subTickPosition = 0; - int subTickIndex = 0; - bool done = false; - int lowTick = mLowestVisibleTick > 0 ? mLowestVisibleTick-1 : mLowestVisibleTick; - int highTick = mHighestVisibleTick < mTickVector.size()-1 ? mHighestVisibleTick+1 : mHighestVisibleTick; - for (int i=lowTick+1; i<=highTick; ++i) - { - subTickStep = (mTickVector.at(i)-mTickVector.at(i-1))/(double)(mSubTickCount+1); - for (int k=1; k<=mSubTickCount; ++k) - { - subTickPosition = mTickVector.at(i-1) + k*subTickStep; - if (subTickPosition < mRange.lower) - continue; - if (subTickPosition > mRange.upper) + if (!mParentPlot) return; + if ((!mTicks && !mTickLabels && !mGrid->visible()) || mRange.size() <= 0) return; + + // fill tick vectors, either by auto generating or by notifying user to fill the vectors himself + if (mAutoTicks) + { + generateAutoTicks(); + } else + { + emit ticksRequest(); + } + + visibleTickBounds(mLowestVisibleTick, mHighestVisibleTick); + if (mTickVector.isEmpty()) + { + mSubTickVector.clear(); + return; + } + + // generate subticks between ticks: + mSubTickVector.resize((mTickVector.size()-1)*mSubTickCount); + if (mSubTickCount > 0) + { + double subTickStep = 0; + double subTickPosition = 0; + int subTickIndex = 0; + bool done = false; + int lowTick = mLowestVisibleTick > 0 ? mLowestVisibleTick-1 : mLowestVisibleTick; + int highTick = mHighestVisibleTick < mTickVector.size()-1 ? mHighestVisibleTick+1 : mHighestVisibleTick; + for (int i=lowTick+1; i<=highTick; ++i) + { + subTickStep = (mTickVector.at(i)-mTickVector.at(i-1))/(double)(mSubTickCount+1); + for (int k=1; k<=mSubTickCount; ++k) + { + subTickPosition = mTickVector.at(i-1) + k*subTickStep; + if (subTickPosition < mRange.lower) + continue; + if (subTickPosition > mRange.upper) { - done = true; - break; + done = true; + break; } - mSubTickVector[subTickIndex] = subTickPosition; - subTickIndex++; - } - if (done) break; - } - mSubTickVector.resize(subTickIndex); - } - - // generate tick labels according to tick positions: - if (mAutoTickLabels) - { - int vecsize = mTickVector.size(); - mTickVectorLabels.resize(vecsize); - if (mTickLabelType == ltNumber) - { - for (int i=mLowestVisibleTick; i<=mHighestVisibleTick; ++i) - mTickVectorLabels[i] = mParentPlot->locale().toString(mTickVector.at(i), mNumberFormatChar.toLatin1(), mNumberPrecision); + mSubTickVector[subTickIndex] = subTickPosition; + subTickIndex++; + } + if (done) break; + } + mSubTickVector.resize(subTickIndex); + } + + // generate tick labels according to tick positions: + if (mAutoTickLabels) + { + int vecsize = mTickVector.size(); + mTickVectorLabels.resize(vecsize); + if (mTickLabelType == ltNumber) + { + for (int i=mLowestVisibleTick; i<=mHighestVisibleTick; ++i) + mTickVectorLabels[i] = mParentPlot->locale().toString(mTickVector.at(i), mNumberFormatChar.toLatin1(), mNumberPrecision); } else if (mTickLabelType == ltDateTime) { - for (int i=mLowestVisibleTick; i<=mHighestVisibleTick; ++i) + for (int i=mLowestVisibleTick; i<=mHighestVisibleTick; ++i) { #if QT_VERSION < QT_VERSION_CHECK(4, 7, 0) // use fromMSecsSinceEpoch function if available, to gain sub-second accuracy on tick labels (e.g. for format "hh:mm:ss:zzz") - mTickVectorLabels[i] = mParentPlot->locale().toString(QDateTime::fromTime_t(mTickVector.at(i)).toTimeSpec(mDateTimeSpec), mDateTimeFormat); + mTickVectorLabels[i] = mParentPlot->locale().toString(QDateTime::fromTime_t(mTickVector.at(i)).toTimeSpec(mDateTimeSpec), mDateTimeFormat); #else - mTickVectorLabels[i] = mParentPlot->locale().toString(QDateTime::fromMSecsSinceEpoch(mTickVector.at(i)*1000).toTimeSpec(mDateTimeSpec), mDateTimeFormat); + mTickVectorLabels[i] = mParentPlot->locale().toString(QDateTime::fromMSecsSinceEpoch(mTickVector.at(i)*1000).toTimeSpec(mDateTimeSpec), mDateTimeFormat); #endif } } } else // mAutoTickLabels == false { - if (mAutoTicks) // ticks generated automatically, but not ticklabels, so emit ticksRequest here for labels - { - emit ticksRequest(); - } - // make sure provided tick label vector has correct (minimal) length: - if (mTickVectorLabels.size() < mTickVector.size()) - mTickVectorLabels.resize(mTickVector.size()); + if (mAutoTicks) // ticks generated automatically, but not ticklabels, so emit ticksRequest here for labels + { + emit ticksRequest(); + } + // make sure provided tick label vector has correct (minimal) length: + if (mTickVectorLabels.size() < mTickVector.size()) + mTickVectorLabels.resize(mTickVector.size()); } } @@ -5611,63 +5611,63 @@ void QCPAxis::setupTickVectors() */ void QCPAxis::generateAutoTicks() { - if (mScaleType == stLinear) - { - if (mAutoTickStep) - { - // Generate tick positions according to linear scaling: - mTickStep = mRange.size()/(double)(mAutoTickCount+1e-10); // mAutoTickCount ticks on average, the small addition is to prevent jitter on exact integers - double magnitudeFactor = qPow(10.0, qFloor(qLn(mTickStep)/qLn(10.0))); // get magnitude factor e.g. 0.01, 1, 10, 1000 etc. - double tickStepMantissa = mTickStep/magnitudeFactor; - if (tickStepMantissa < 5) - { - // round digit after decimal point to 0.5 - mTickStep = (int)(tickStepMantissa*2)/2.0*magnitudeFactor; + if (mScaleType == stLinear) + { + if (mAutoTickStep) + { + // Generate tick positions according to linear scaling: + mTickStep = mRange.size()/(double)(mAutoTickCount+1e-10); // mAutoTickCount ticks on average, the small addition is to prevent jitter on exact integers + double magnitudeFactor = qPow(10.0, qFloor(qLn(mTickStep)/qLn(10.0))); // get magnitude factor e.g. 0.01, 1, 10, 1000 etc. + double tickStepMantissa = mTickStep/magnitudeFactor; + if (tickStepMantissa < 5) + { + // round digit after decimal point to 0.5 + mTickStep = (int)(tickStepMantissa*2)/2.0*magnitudeFactor; } else { - // round to first digit in multiples of 2 - mTickStep = (int)(tickStepMantissa/2.0)*2.0*magnitudeFactor; - } - } - if (mAutoSubTicks) - mSubTickCount = calculateAutoSubTickCount(mTickStep); - // Generate tick positions according to mTickStep: - qint64 firstStep = floor(mRange.lower/mTickStep); // do not use qFloor here, or we'll lose 64 bit precision - qint64 lastStep = ceil(mRange.upper/mTickStep); // do not use qCeil here, or we'll lose 64 bit precision - int tickcount = lastStep-firstStep+1; - if (tickcount < 0) tickcount = 0; - mTickVector.resize(tickcount); - for (int i=0; i 0 && mRange.upper > 0) // positive range - { - double lowerMag = basePow(qFloor(baseLog(mRange.lower))); - double currentMag = lowerMag; - mTickVector.clear(); - mTickVector.append(currentMag); - while (currentMag < mRange.upper && currentMag > 0) // currentMag might be zero for ranges ~1e-300, just cancel in that case - { - currentMag *= mScaleLogBase; - mTickVector.append(currentMag); + // Generate tick positions according to logbase scaling: + if (mRange.lower > 0 && mRange.upper > 0) // positive range + { + double lowerMag = basePow(qFloor(baseLog(mRange.lower))); + double currentMag = lowerMag; + mTickVector.clear(); + mTickVector.append(currentMag); + while (currentMag < mRange.upper && currentMag > 0) // currentMag might be zero for ranges ~1e-300, just cancel in that case + { + currentMag *= mScaleLogBase; + mTickVector.append(currentMag); } } else if (mRange.lower < 0 && mRange.upper < 0) // negative range { - double lowerMag = -basePow(qCeil(baseLog(-mRange.lower))); - double currentMag = lowerMag; - mTickVector.clear(); - mTickVector.append(currentMag); - while (currentMag < mRange.upper && currentMag < 0) // currentMag might be zero for ranges ~1e-300, just cancel in that case - { - currentMag /= mScaleLogBase; - mTickVector.append(currentMag); + double lowerMag = -basePow(qCeil(baseLog(-mRange.lower))); + double currentMag = lowerMag; + mTickVector.clear(); + mTickVector.append(currentMag); + while (currentMag < mRange.upper && currentMag < 0) // currentMag might be zero for ranges ~1e-300, just cancel in that case + { + currentMag /= mScaleLogBase; + mTickVector.append(currentMag); } } else // invalid range for logarithmic scale, because lower and upper have different sign { - mTickVector.clear(); - qDebug() << Q_FUNC_INFO << "Invalid range for logarithmic plot: " << mRange.lower << "-" << mRange.upper; + mTickVector.clear(); + qDebug() << Q_FUNC_INFO << "Invalid range for logarithmic plot: " << mRange.lower << "-" << mRange.upper; } } } @@ -5687,25 +5687,25 @@ void QCPAxis::generateAutoTicks() */ int QCPAxis::calculateAutoSubTickCount(double tickStep) const { - int result = mSubTickCount; // default to current setting, if no proper value can be found - - // get mantissa of tickstep: - double magnitudeFactor = qPow(10.0, qFloor(qLn(tickStep)/qLn(10.0))); // get magnitude factor e.g. 0.01, 1, 10, 1000 etc. - double tickStepMantissa = tickStep/magnitudeFactor; - - // separate integer and fractional part of mantissa: - double epsilon = 0.01; - double intPartf; - int intPart; - double fracPart = modf(tickStepMantissa, &intPartf); - intPart = intPartf; - - // handle cases with (almost) integer mantissa: - if (fracPart < epsilon || 1.0-fracPart < epsilon) - { - if (1.0-fracPart < epsilon) - ++intPart; - switch (intPart) + int result = mSubTickCount; // default to current setting, if no proper value can be found + + // get mantissa of tickstep: + double magnitudeFactor = qPow(10.0, qFloor(qLn(tickStep)/qLn(10.0))); // get magnitude factor e.g. 0.01, 1, 10, 1000 etc. + double tickStepMantissa = tickStep/magnitudeFactor; + + // separate integer and fractional part of mantissa: + double epsilon = 0.01; + double intPartf; + int intPart; + double fracPart = modf(tickStepMantissa, &intPartf); + intPart = intPartf; + + // handle cases with (almost) integer mantissa: + if (fracPart < epsilon || 1.0-fracPart < epsilon) + { + if (1.0-fracPart < epsilon) + ++intPart; + switch (intPart) { case 1: result = 4; break; // 1.0 -> 0.2 substep case 2: result = 3; break; // 2.0 -> 0.5 substep @@ -5719,10 +5719,10 @@ int QCPAxis::calculateAutoSubTickCount(d } } else { - // handle cases with significantly fractional mantissa: - if (qAbs(fracPart-0.5) < epsilon) // *.5 mantissa - { - switch (intPart) + // handle cases with significantly fractional mantissa: + if (qAbs(fracPart-0.5) < epsilon) // *.5 mantissa + { + switch (intPart) { case 1: result = 2; break; // 1.5 -> 0.5 substep case 2: result = 4; break; // 2.5 -> 0.5 substep @@ -5735,33 +5735,33 @@ int QCPAxis::calculateAutoSubTickCount(d case 9: result = 4; break; // 9.5 -> 1.9 substep } } - // if mantissa fraction isnt 0.0 or 0.5, don't bother finding good sub tick marks, leave default - } - - return result; + // if mantissa fraction isnt 0.0 or 0.5, don't bother finding good sub tick marks, leave default + } + + return result; } /* inherits documentation from base class */ void QCPAxis::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) { - Q_UNUSED(event) - SelectablePart part = details.value(); - if (mSelectableParts.testFlag(part)) - { - SelectableParts selBefore = mSelectedParts; - setSelectedParts(additive ? mSelectedParts^part : part); - if (selectionStateChanged) - *selectionStateChanged = mSelectedParts != selBefore; + Q_UNUSED(event) + SelectablePart part = details.value(); + if (mSelectableParts.testFlag(part)) + { + SelectableParts selBefore = mSelectedParts; + setSelectedParts(additive ? mSelectedParts^part : part); + if (selectionStateChanged) + *selectionStateChanged = mSelectedParts != selBefore; } } /* inherits documentation from base class */ void QCPAxis::deselectEvent(bool *selectionStateChanged) { - SelectableParts selBefore = mSelectedParts; - setSelectedParts(mSelectedParts & ~mSelectableParts); - if (selectionStateChanged) - *selectionStateChanged = mSelectedParts != selBefore; + SelectableParts selBefore = mSelectedParts; + setSelectedParts(mSelectedParts & ~mSelectableParts); + if (selectionStateChanged) + *selectionStateChanged = mSelectedParts != selBefore; } /*! \internal @@ -5779,7 +5779,7 @@ void QCPAxis::deselectEvent(bool *select */ void QCPAxis::applyDefaultAntialiasingHint(QCPPainter *painter) const { - applyAntialiasingHint(painter, mAntialiased, QCP::aeAxes); + applyAntialiasingHint(painter, mAntialiased, QCP::aeAxes); } /*! \internal @@ -5789,51 +5789,51 @@ void QCPAxis::applyDefaultAntialiasingHi */ void QCPAxis::draw(QCPPainter *painter) { - const int lowTick = mLowestVisibleTick; - const int highTick = mHighestVisibleTick; - QVector subTickPositions; // the final coordToPixel transformed vector passed to QCPAxisPainter - QVector tickPositions; // the final coordToPixel transformed vector passed to QCPAxisPainter - QVector tickLabels; // the final vector passed to QCPAxisPainter - tickPositions.reserve(highTick-lowTick+1); - tickLabels.reserve(highTick-lowTick+1); - subTickPositions.reserve(mSubTickVector.size()); - - if (mTicks) - { - for (int i=lowTick; i<=highTick; ++i) - { - tickPositions.append(coordToPixel(mTickVector.at(i))); - if (mTickLabels) - tickLabels.append(mTickVectorLabels.at(i)); - } - - if (mSubTickCount > 0) - { - const int subTickCount = mSubTickVector.size(); - for (int i=0; itype = mAxisType; - mAxisPainter->basePen = getBasePen(); - mAxisPainter->labelFont = getLabelFont(); - mAxisPainter->labelColor = getLabelColor(); - mAxisPainter->label = mLabel; - mAxisPainter->substituteExponent = mAutoTickLabels && mNumberBeautifulPowers && mTickLabelType == ltNumber; - mAxisPainter->tickPen = getTickPen(); - mAxisPainter->subTickPen = getSubTickPen(); - mAxisPainter->tickLabelFont = getTickLabelFont(); - mAxisPainter->tickLabelColor = getTickLabelColor(); - mAxisPainter->axisRect = mAxisRect->rect(); - mAxisPainter->viewportRect = mParentPlot->viewport(); - mAxisPainter->abbreviateDecimalPowers = mScaleType == stLogarithmic; - mAxisPainter->reversedEndings = mRangeReversed; - mAxisPainter->tickPositions = tickPositions; - mAxisPainter->tickLabels = tickLabels; - mAxisPainter->subTickPositions = subTickPositions; - mAxisPainter->draw(painter); + const int lowTick = mLowestVisibleTick; + const int highTick = mHighestVisibleTick; + QVector subTickPositions; // the final coordToPixel transformed vector passed to QCPAxisPainter + QVector tickPositions; // the final coordToPixel transformed vector passed to QCPAxisPainter + QVector tickLabels; // the final vector passed to QCPAxisPainter + tickPositions.reserve(highTick-lowTick+1); + tickLabels.reserve(highTick-lowTick+1); + subTickPositions.reserve(mSubTickVector.size()); + + if (mTicks) + { + for (int i=lowTick; i<=highTick; ++i) + { + tickPositions.append(coordToPixel(mTickVector.at(i))); + if (mTickLabels) + tickLabels.append(mTickVectorLabels.at(i)); + } + + if (mSubTickCount > 0) + { + const int subTickCount = mSubTickVector.size(); + for (int i=0; itype = mAxisType; + mAxisPainter->basePen = getBasePen(); + mAxisPainter->labelFont = getLabelFont(); + mAxisPainter->labelColor = getLabelColor(); + mAxisPainter->label = mLabel; + mAxisPainter->substituteExponent = mAutoTickLabels && mNumberBeautifulPowers && mTickLabelType == ltNumber; + mAxisPainter->tickPen = getTickPen(); + mAxisPainter->subTickPen = getSubTickPen(); + mAxisPainter->tickLabelFont = getTickLabelFont(); + mAxisPainter->tickLabelColor = getTickLabelColor(); + mAxisPainter->axisRect = mAxisRect->rect(); + mAxisPainter->viewportRect = mParentPlot->viewport(); + mAxisPainter->abbreviateDecimalPowers = mScaleType == stLogarithmic; + mAxisPainter->reversedEndings = mRangeReversed; + mAxisPainter->tickPositions = tickPositions; + mAxisPainter->tickLabels = tickLabels; + mAxisPainter->subTickPositions = subTickPositions; + mAxisPainter->draw(painter); } /*! \internal @@ -5854,34 +5854,34 @@ void QCPAxis::draw(QCPPainter *painter) */ void QCPAxis::visibleTickBounds(int &lowIndex, int &highIndex) const { - bool lowFound = false; - bool highFound = false; - lowIndex = 0; - highIndex = -1; - - for (int i=0; i < mTickVector.size(); ++i) - { - if (mTickVector.at(i) >= mRange.lower) - { - lowFound = true; - lowIndex = i; - break; - } - } - for (int i=mTickVector.size()-1; i >= 0; --i) - { - if (mTickVector.at(i) <= mRange.upper) - { - highFound = true; - highIndex = i; - break; - } - } - - if (!lowFound && highFound) - lowIndex = highIndex+1; - else if (lowFound && !highFound) - highIndex = lowIndex-1; + bool lowFound = false; + bool highFound = false; + lowIndex = 0; + highIndex = -1; + + for (int i=0; i < mTickVector.size(); ++i) + { + if (mTickVector.at(i) >= mRange.lower) + { + lowFound = true; + lowIndex = i; + break; + } + } + for (int i=mTickVector.size()-1; i >= 0; --i) + { + if (mTickVector.at(i) <= mRange.upper) + { + highFound = true; + highIndex = i; + break; + } + } + + if (!lowFound && highFound) + lowIndex = highIndex+1; + else if (lowFound && !highFound) + highIndex = lowIndex-1; } /*! \internal @@ -5894,7 +5894,7 @@ void QCPAxis::visibleTickBounds(int &low */ double QCPAxis::baseLog(double value) const { - return qLn(value)*mScaleLogBaseLogInv; + return qLn(value)*mScaleLogBaseLogInv; } /*! \internal @@ -5906,7 +5906,7 @@ double QCPAxis::baseLog(double value) co */ double QCPAxis::basePow(double value) const { - return qPow(mScaleLogBase, value); + return qPow(mScaleLogBase, value); } /*! \internal @@ -5916,7 +5916,7 @@ double QCPAxis::basePow(double value) co */ QPen QCPAxis::getBasePen() const { - return mSelectedParts.testFlag(spAxis) ? mSelectedBasePen : mBasePen; + return mSelectedParts.testFlag(spAxis) ? mSelectedBasePen : mBasePen; } /*! \internal @@ -5926,7 +5926,7 @@ QPen QCPAxis::getBasePen() const */ QPen QCPAxis::getTickPen() const { - return mSelectedParts.testFlag(spAxis) ? mSelectedTickPen : mTickPen; + return mSelectedParts.testFlag(spAxis) ? mSelectedTickPen : mTickPen; } /*! \internal @@ -5936,7 +5936,7 @@ QPen QCPAxis::getTickPen() const */ QPen QCPAxis::getSubTickPen() const { - return mSelectedParts.testFlag(spAxis) ? mSelectedSubTickPen : mSubTickPen; + return mSelectedParts.testFlag(spAxis) ? mSelectedSubTickPen : mSubTickPen; } /*! \internal @@ -5946,7 +5946,7 @@ QPen QCPAxis::getSubTickPen() const */ QFont QCPAxis::getTickLabelFont() const { - return mSelectedParts.testFlag(spTickLabels) ? mSelectedTickLabelFont : mTickLabelFont; + return mSelectedParts.testFlag(spTickLabels) ? mSelectedTickLabelFont : mTickLabelFont; } /*! \internal @@ -5956,7 +5956,7 @@ QFont QCPAxis::getTickLabelFont() const */ QFont QCPAxis::getLabelFont() const { - return mSelectedParts.testFlag(spAxisLabel) ? mSelectedLabelFont : mLabelFont; + return mSelectedParts.testFlag(spAxisLabel) ? mSelectedLabelFont : mLabelFont; } /*! \internal @@ -5966,7 +5966,7 @@ QFont QCPAxis::getLabelFont() const */ QColor QCPAxis::getTickLabelColor() const { - return mSelectedParts.testFlag(spTickLabels) ? mSelectedTickLabelColor : mTickLabelColor; + return mSelectedParts.testFlag(spTickLabels) ? mSelectedTickLabelColor : mTickLabelColor; } /*! \internal @@ -5976,7 +5976,7 @@ QColor QCPAxis::getTickLabelColor() cons */ QColor QCPAxis::getLabelColor() const { - return mSelectedParts.testFlag(spAxisLabel) ? mSelectedLabelColor : mLabelColor; + return mSelectedParts.testFlag(spAxisLabel) ? mSelectedLabelColor : mLabelColor; } /*! \internal @@ -5995,52 +5995,52 @@ QColor QCPAxis::getLabelColor() const */ int QCPAxis::calculateMargin() { - if (!mVisible) // if not visible, directly return 0, don't cache 0 because we can't react to setVisible in QCPAxis - return 0; - - if (mCachedMarginValid) - return mCachedMargin; - - // run through similar steps as QCPAxis::draw, and caluclate margin needed to fit axis and its labels - int margin = 0; - - int lowTick, highTick; - visibleTickBounds(lowTick, highTick); - QVector tickPositions; // the final coordToPixel transformed vector passed to QCPAxisPainter - QVector tickLabels; // the final vector passed to QCPAxisPainter - tickPositions.reserve(highTick-lowTick+1); - tickLabels.reserve(highTick-lowTick+1); - if (mTicks) - { - for (int i=lowTick; i<=highTick; ++i) - { - tickPositions.append(coordToPixel(mTickVector.at(i))); - if (mTickLabels) - tickLabels.append(mTickVectorLabels.at(i)); - } - } - // transfer all properties of this axis to QCPAxisPainterPrivate which it needs to calculate the size. - // Note that some axis painter properties are already set by direct feed-through with QCPAxis setters - mAxisPainter->type = mAxisType; - mAxisPainter->labelFont = getLabelFont(); - mAxisPainter->label = mLabel; - mAxisPainter->tickLabelFont = mTickLabelFont; - mAxisPainter->axisRect = mAxisRect->rect(); - mAxisPainter->viewportRect = mParentPlot->viewport(); - mAxisPainter->tickPositions = tickPositions; - mAxisPainter->tickLabels = tickLabels; - margin += mAxisPainter->size(); - margin += mPadding; - - mCachedMargin = margin; - mCachedMarginValid = true; - return margin; + if (!mVisible) // if not visible, directly return 0, don't cache 0 because we can't react to setVisible in QCPAxis + return 0; + + if (mCachedMarginValid) + return mCachedMargin; + + // run through similar steps as QCPAxis::draw, and caluclate margin needed to fit axis and its labels + int margin = 0; + + int lowTick, highTick; + visibleTickBounds(lowTick, highTick); + QVector tickPositions; // the final coordToPixel transformed vector passed to QCPAxisPainter + QVector tickLabels; // the final vector passed to QCPAxisPainter + tickPositions.reserve(highTick-lowTick+1); + tickLabels.reserve(highTick-lowTick+1); + if (mTicks) + { + for (int i=lowTick; i<=highTick; ++i) + { + tickPositions.append(coordToPixel(mTickVector.at(i))); + if (mTickLabels) + tickLabels.append(mTickVectorLabels.at(i)); + } + } + // transfer all properties of this axis to QCPAxisPainterPrivate which it needs to calculate the size. + // Note that some axis painter properties are already set by direct feed-through with QCPAxis setters + mAxisPainter->type = mAxisType; + mAxisPainter->labelFont = getLabelFont(); + mAxisPainter->label = mLabel; + mAxisPainter->tickLabelFont = mTickLabelFont; + mAxisPainter->axisRect = mAxisRect->rect(); + mAxisPainter->viewportRect = mParentPlot->viewport(); + mAxisPainter->tickPositions = tickPositions; + mAxisPainter->tickLabels = tickLabels; + margin += mAxisPainter->size(); + margin += mPadding; + + mCachedMargin = margin; + mCachedMarginValid = true; + return margin; } /* inherits documentation from base class */ QCP::Interaction QCPAxis::selectionCategory() const { - return QCP::iSelectAxes; + return QCP::iSelectAxes; } @@ -6065,27 +6065,27 @@ QCP::Interaction QCPAxis::selectionCateg redraw, to utilize the caching mechanisms. */ QCPAxisPainterPrivate::QCPAxisPainterPrivate(QCustomPlot *parentPlot) : - type(QCPAxis::atLeft), - basePen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)), - lowerEnding(QCPLineEnding::esNone), - upperEnding(QCPLineEnding::esNone), - labelPadding(0), - tickLabelPadding(0), - tickLabelRotation(0), - tickLabelSide(QCPAxis::lsOutside), - substituteExponent(true), - numberMultiplyCross(false), - tickLengthIn(5), - tickLengthOut(0), - subTickLengthIn(2), - subTickLengthOut(0), - tickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)), - subTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)), - offset(0), - abbreviateDecimalPowers(false), - reversedEndings(false), - mParentPlot(parentPlot), - mLabelCache(16) // cache at most 16 (tick) labels + type(QCPAxis::atLeft), + basePen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)), + lowerEnding(QCPLineEnding::esNone), + upperEnding(QCPLineEnding::esNone), + labelPadding(0), + tickLabelPadding(0), + tickLabelRotation(0), + tickLabelSide(QCPAxis::lsOutside), + substituteExponent(true), + numberMultiplyCross(false), + tickLengthIn(5), + tickLengthOut(0), + subTickLengthIn(2), + subTickLengthOut(0), + tickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)), + subTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)), + offset(0), + abbreviateDecimalPowers(false), + reversedEndings(false), + mParentPlot(parentPlot), + mLabelCache(16) // cache at most 16 (tick) labels { } @@ -6102,15 +6102,15 @@ QCPAxisPainterPrivate::~QCPAxisPainterPr */ void QCPAxisPainterPrivate::draw(QCPPainter *painter) { - QByteArray newHash = generateLabelParameterHash(); - if (newHash != mLabelParameterHash) - { - mLabelCache.clear(); - mLabelParameterHash = newHash; - } - - QPoint origin; - switch (type) + QByteArray newHash = generateLabelParameterHash(); + if (newHash != mLabelParameterHash) + { + mLabelCache.clear(); + mLabelParameterHash = newHash; + } + + QPoint origin; + switch (type) { case QCPAxis::atLeft: origin = axisRect.bottomLeft() +QPoint(-offset, 0); break; case QCPAxis::atRight: origin = axisRect.bottomRight()+QPoint(+offset, 0); break; @@ -6118,175 +6118,175 @@ void QCPAxisPainterPrivate::draw(QCPPain case QCPAxis::atBottom: origin = axisRect.bottomLeft() +QPoint(0, +offset); break; } - double xCor = 0, yCor = 0; // paint system correction, for pixel exact matches (affects baselines and ticks of top/right axes) - switch (type) + double xCor = 0, yCor = 0; // paint system correction, for pixel exact matches (affects baselines and ticks of top/right axes) + switch (type) { case QCPAxis::atTop: yCor = -1; break; case QCPAxis::atRight: xCor = 1; break; default: break; } - int margin = 0; - // draw baseline: - QLineF baseLine; - painter->setPen(basePen); - if (QCPAxis::orientation(type) == Qt::Horizontal) - baseLine.setPoints(origin+QPointF(xCor, yCor), origin+QPointF(axisRect.width()+xCor, yCor)); - else - baseLine.setPoints(origin+QPointF(xCor, yCor), origin+QPointF(xCor, -axisRect.height()+yCor)); - if (reversedEndings) - baseLine = QLineF(baseLine.p2(), baseLine.p1()); // won't make a difference for line itself, but for line endings later - painter->drawLine(baseLine); - - // draw ticks: - if (!tickPositions.isEmpty()) - { - painter->setPen(tickPen); - int tickDir = (type == QCPAxis::atBottom || type == QCPAxis::atRight) ? -1 : 1; // direction of ticks ("inward" is right for left axis and left for right axis) - if (QCPAxis::orientation(type) == Qt::Horizontal) - { - for (int i=0; idrawLine(QLineF(tickPositions.at(i)+xCor, origin.y()-tickLengthOut*tickDir+yCor, tickPositions.at(i)+xCor, origin.y()+tickLengthIn*tickDir+yCor)); + int margin = 0; + // draw baseline: + QLineF baseLine; + painter->setPen(basePen); + if (QCPAxis::orientation(type) == Qt::Horizontal) + baseLine.setPoints(origin+QPointF(xCor, yCor), origin+QPointF(axisRect.width()+xCor, yCor)); + else + baseLine.setPoints(origin+QPointF(xCor, yCor), origin+QPointF(xCor, -axisRect.height()+yCor)); + if (reversedEndings) + baseLine = QLineF(baseLine.p2(), baseLine.p1()); // won't make a difference for line itself, but for line endings later + painter->drawLine(baseLine); + + // draw ticks: + if (!tickPositions.isEmpty()) + { + painter->setPen(tickPen); + int tickDir = (type == QCPAxis::atBottom || type == QCPAxis::atRight) ? -1 : 1; // direction of ticks ("inward" is right for left axis and left for right axis) + if (QCPAxis::orientation(type) == Qt::Horizontal) + { + for (int i=0; idrawLine(QLineF(tickPositions.at(i)+xCor, origin.y()-tickLengthOut*tickDir+yCor, tickPositions.at(i)+xCor, origin.y()+tickLengthIn*tickDir+yCor)); } else { - for (int i=0; idrawLine(QLineF(origin.x()-tickLengthOut*tickDir+xCor, tickPositions.at(i)+yCor, origin.x()+tickLengthIn*tickDir+xCor, tickPositions.at(i)+yCor)); - } - } - - // draw subticks: - if (!subTickPositions.isEmpty()) - { - painter->setPen(subTickPen); - // direction of ticks ("inward" is right for left axis and left for right axis) - int tickDir = (type == QCPAxis::atBottom || type == QCPAxis::atRight) ? -1 : 1; - if (QCPAxis::orientation(type) == Qt::Horizontal) - { - for (int i=0; idrawLine(QLineF(subTickPositions.at(i)+xCor, origin.y()-subTickLengthOut*tickDir+yCor, subTickPositions.at(i)+xCor, origin.y()+subTickLengthIn*tickDir+yCor)); + for (int i=0; idrawLine(QLineF(origin.x()-tickLengthOut*tickDir+xCor, tickPositions.at(i)+yCor, origin.x()+tickLengthIn*tickDir+xCor, tickPositions.at(i)+yCor)); + } + } + + // draw subticks: + if (!subTickPositions.isEmpty()) + { + painter->setPen(subTickPen); + // direction of ticks ("inward" is right for left axis and left for right axis) + int tickDir = (type == QCPAxis::atBottom || type == QCPAxis::atRight) ? -1 : 1; + if (QCPAxis::orientation(type) == Qt::Horizontal) + { + for (int i=0; idrawLine(QLineF(subTickPositions.at(i)+xCor, origin.y()-subTickLengthOut*tickDir+yCor, subTickPositions.at(i)+xCor, origin.y()+subTickLengthIn*tickDir+yCor)); } else { - for (int i=0; idrawLine(QLineF(origin.x()-subTickLengthOut*tickDir+xCor, subTickPositions.at(i)+yCor, origin.x()+subTickLengthIn*tickDir+xCor, subTickPositions.at(i)+yCor)); - } - } - margin += qMax(0, qMax(tickLengthOut, subTickLengthOut)); - - // draw axis base endings: - bool antialiasingBackup = painter->antialiasing(); - painter->setAntialiasing(true); // always want endings to be antialiased, even if base and ticks themselves aren't - painter->setBrush(QBrush(basePen.color())); - QVector2D baseLineVector(baseLine.dx(), baseLine.dy()); - if (lowerEnding.style() != QCPLineEnding::esNone) - lowerEnding.draw(painter, QVector2D(baseLine.p1())-baseLineVector.normalized()*lowerEnding.realLength()*(lowerEnding.inverted()?-1:1), -baseLineVector); - if (upperEnding.style() != QCPLineEnding::esNone) - upperEnding.draw(painter, QVector2D(baseLine.p2())+baseLineVector.normalized()*upperEnding.realLength()*(upperEnding.inverted()?-1:1), baseLineVector); - painter->setAntialiasing(antialiasingBackup); - - // tick labels: - QRect oldClipRect; - if (tickLabelSide == QCPAxis::lsInside) // if using inside labels, clip them to the axis rect - { - oldClipRect = painter->clipRegion().boundingRect(); - painter->setClipRect(axisRect); - } - QSize tickLabelsSize(0, 0); // size of largest tick label, for offset calculation of axis label - if (!tickLabels.isEmpty()) - { - if (tickLabelSide == QCPAxis::lsOutside) - margin += tickLabelPadding; - painter->setFont(tickLabelFont); - painter->setPen(QPen(tickLabelColor)); - const int maxLabelIndex = qMin(tickPositions.size(), tickLabels.size()); - int distanceToAxis = margin; - if (tickLabelSide == QCPAxis::lsInside) - distanceToAxis = -(qMax(tickLengthIn, subTickLengthIn)+tickLabelPadding); - for (int i=0; isetClipRect(oldClipRect); - - // axis label: - QRect labelBounds; - if (!label.isEmpty()) - { - margin += labelPadding; - painter->setFont(labelFont); - painter->setPen(QPen(labelColor)); - labelBounds = painter->fontMetrics().boundingRect(0, 0, 0, 0, Qt::TextDontClip, label); - if (type == QCPAxis::atLeft) - { - QTransform oldTransform = painter->transform(); - painter->translate((origin.x()-margin-labelBounds.height()), origin.y()); - painter->rotate(-90); - painter->drawText(0, 0, axisRect.height(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label); - painter->setTransform(oldTransform); - } - else if (type == QCPAxis::atRight) - { - QTransform oldTransform = painter->transform(); - painter->translate((origin.x()+margin+labelBounds.height()), origin.y()-axisRect.height()); - painter->rotate(90); - painter->drawText(0, 0, axisRect.height(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label); - painter->setTransform(oldTransform); - } - else if (type == QCPAxis::atTop) - painter->drawText(origin.x(), origin.y()-margin-labelBounds.height(), axisRect.width(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label); - else if (type == QCPAxis::atBottom) - painter->drawText(origin.x(), origin.y()+margin, axisRect.width(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label); - } - - // set selection boxes: - int selectionTolerance = 0; - if (mParentPlot) - selectionTolerance = mParentPlot->selectionTolerance(); - else - qDebug() << Q_FUNC_INFO << "mParentPlot is null"; - int selAxisOutSize = qMax(qMax(tickLengthOut, subTickLengthOut), selectionTolerance); - int selAxisInSize = selectionTolerance; - int selTickLabelSize; - int selTickLabelOffset; - if (tickLabelSide == QCPAxis::lsOutside) - { - selTickLabelSize = (QCPAxis::orientation(type) == Qt::Horizontal ? tickLabelsSize.height() : tickLabelsSize.width()); - selTickLabelOffset = qMax(tickLengthOut, subTickLengthOut)+tickLabelPadding; - } else - { - selTickLabelSize = -(QCPAxis::orientation(type) == Qt::Horizontal ? tickLabelsSize.height() : tickLabelsSize.width()); - selTickLabelOffset = -(qMax(tickLengthIn, subTickLengthIn)+tickLabelPadding); - } - int selLabelSize = labelBounds.height(); - int selLabelOffset = qMax(tickLengthOut, subTickLengthOut)+(!tickLabels.isEmpty() && tickLabelSide == QCPAxis::lsOutside ? tickLabelPadding+selTickLabelSize : 0)+labelPadding; - if (type == QCPAxis::atLeft) - { - mAxisSelectionBox.setCoords(origin.x()-selAxisOutSize, axisRect.top(), origin.x()+selAxisInSize, axisRect.bottom()); - mTickLabelsSelectionBox.setCoords(origin.x()-selTickLabelOffset-selTickLabelSize, axisRect.top(), origin.x()-selTickLabelOffset, axisRect.bottom()); - mLabelSelectionBox.setCoords(origin.x()-selLabelOffset-selLabelSize, axisRect.top(), origin.x()-selLabelOffset, axisRect.bottom()); + for (int i=0; idrawLine(QLineF(origin.x()-subTickLengthOut*tickDir+xCor, subTickPositions.at(i)+yCor, origin.x()+subTickLengthIn*tickDir+xCor, subTickPositions.at(i)+yCor)); + } + } + margin += qMax(0, qMax(tickLengthOut, subTickLengthOut)); + + // draw axis base endings: + bool antialiasingBackup = painter->antialiasing(); + painter->setAntialiasing(true); // always want endings to be antialiased, even if base and ticks themselves aren't + painter->setBrush(QBrush(basePen.color())); + QVector2D baseLineVector(baseLine.dx(), baseLine.dy()); + if (lowerEnding.style() != QCPLineEnding::esNone) + lowerEnding.draw(painter, QVector2D(baseLine.p1())-baseLineVector.normalized()*lowerEnding.realLength()*(lowerEnding.inverted()?-1:1), -baseLineVector); + if (upperEnding.style() != QCPLineEnding::esNone) + upperEnding.draw(painter, QVector2D(baseLine.p2())+baseLineVector.normalized()*upperEnding.realLength()*(upperEnding.inverted()?-1:1), baseLineVector); + painter->setAntialiasing(antialiasingBackup); + + // tick labels: + QRect oldClipRect; + if (tickLabelSide == QCPAxis::lsInside) // if using inside labels, clip them to the axis rect + { + oldClipRect = painter->clipRegion().boundingRect(); + painter->setClipRect(axisRect); + } + QSize tickLabelsSize(0, 0); // size of largest tick label, for offset calculation of axis label + if (!tickLabels.isEmpty()) + { + if (tickLabelSide == QCPAxis::lsOutside) + margin += tickLabelPadding; + painter->setFont(tickLabelFont); + painter->setPen(QPen(tickLabelColor)); + const int maxLabelIndex = qMin(tickPositions.size(), tickLabels.size()); + int distanceToAxis = margin; + if (tickLabelSide == QCPAxis::lsInside) + distanceToAxis = -(qMax(tickLengthIn, subTickLengthIn)+tickLabelPadding); + for (int i=0; isetClipRect(oldClipRect); + + // axis label: + QRect labelBounds; + if (!label.isEmpty()) + { + margin += labelPadding; + painter->setFont(labelFont); + painter->setPen(QPen(labelColor)); + labelBounds = painter->fontMetrics().boundingRect(0, 0, 0, 0, Qt::TextDontClip, label); + if (type == QCPAxis::atLeft) + { + QTransform oldTransform = painter->transform(); + painter->translate((origin.x()-margin-labelBounds.height()), origin.y()); + painter->rotate(-90); + painter->drawText(0, 0, axisRect.height(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label); + painter->setTransform(oldTransform); + } + else if (type == QCPAxis::atRight) + { + QTransform oldTransform = painter->transform(); + painter->translate((origin.x()+margin+labelBounds.height()), origin.y()-axisRect.height()); + painter->rotate(90); + painter->drawText(0, 0, axisRect.height(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label); + painter->setTransform(oldTransform); + } + else if (type == QCPAxis::atTop) + painter->drawText(origin.x(), origin.y()-margin-labelBounds.height(), axisRect.width(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label); + else if (type == QCPAxis::atBottom) + painter->drawText(origin.x(), origin.y()+margin, axisRect.width(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label); + } + + // set selection boxes: + int selectionTolerance = 0; + if (mParentPlot) + selectionTolerance = mParentPlot->selectionTolerance(); + else + qDebug() << Q_FUNC_INFO << "mParentPlot is null"; + int selAxisOutSize = qMax(qMax(tickLengthOut, subTickLengthOut), selectionTolerance); + int selAxisInSize = selectionTolerance; + int selTickLabelSize; + int selTickLabelOffset; + if (tickLabelSide == QCPAxis::lsOutside) + { + selTickLabelSize = (QCPAxis::orientation(type) == Qt::Horizontal ? tickLabelsSize.height() : tickLabelsSize.width()); + selTickLabelOffset = qMax(tickLengthOut, subTickLengthOut)+tickLabelPadding; + } else + { + selTickLabelSize = -(QCPAxis::orientation(type) == Qt::Horizontal ? tickLabelsSize.height() : tickLabelsSize.width()); + selTickLabelOffset = -(qMax(tickLengthIn, subTickLengthIn)+tickLabelPadding); + } + int selLabelSize = labelBounds.height(); + int selLabelOffset = qMax(tickLengthOut, subTickLengthOut)+(!tickLabels.isEmpty() && tickLabelSide == QCPAxis::lsOutside ? tickLabelPadding+selTickLabelSize : 0)+labelPadding; + if (type == QCPAxis::atLeft) + { + mAxisSelectionBox.setCoords(origin.x()-selAxisOutSize, axisRect.top(), origin.x()+selAxisInSize, axisRect.bottom()); + mTickLabelsSelectionBox.setCoords(origin.x()-selTickLabelOffset-selTickLabelSize, axisRect.top(), origin.x()-selTickLabelOffset, axisRect.bottom()); + mLabelSelectionBox.setCoords(origin.x()-selLabelOffset-selLabelSize, axisRect.top(), origin.x()-selLabelOffset, axisRect.bottom()); } else if (type == QCPAxis::atRight) { - mAxisSelectionBox.setCoords(origin.x()-selAxisInSize, axisRect.top(), origin.x()+selAxisOutSize, axisRect.bottom()); - mTickLabelsSelectionBox.setCoords(origin.x()+selTickLabelOffset+selTickLabelSize, axisRect.top(), origin.x()+selTickLabelOffset, axisRect.bottom()); - mLabelSelectionBox.setCoords(origin.x()+selLabelOffset+selLabelSize, axisRect.top(), origin.x()+selLabelOffset, axisRect.bottom()); + mAxisSelectionBox.setCoords(origin.x()-selAxisInSize, axisRect.top(), origin.x()+selAxisOutSize, axisRect.bottom()); + mTickLabelsSelectionBox.setCoords(origin.x()+selTickLabelOffset+selTickLabelSize, axisRect.top(), origin.x()+selTickLabelOffset, axisRect.bottom()); + mLabelSelectionBox.setCoords(origin.x()+selLabelOffset+selLabelSize, axisRect.top(), origin.x()+selLabelOffset, axisRect.bottom()); } else if (type == QCPAxis::atTop) { - mAxisSelectionBox.setCoords(axisRect.left(), origin.y()-selAxisOutSize, axisRect.right(), origin.y()+selAxisInSize); - mTickLabelsSelectionBox.setCoords(axisRect.left(), origin.y()-selTickLabelOffset-selTickLabelSize, axisRect.right(), origin.y()-selTickLabelOffset); - mLabelSelectionBox.setCoords(axisRect.left(), origin.y()-selLabelOffset-selLabelSize, axisRect.right(), origin.y()-selLabelOffset); + mAxisSelectionBox.setCoords(axisRect.left(), origin.y()-selAxisOutSize, axisRect.right(), origin.y()+selAxisInSize); + mTickLabelsSelectionBox.setCoords(axisRect.left(), origin.y()-selTickLabelOffset-selTickLabelSize, axisRect.right(), origin.y()-selTickLabelOffset); + mLabelSelectionBox.setCoords(axisRect.left(), origin.y()-selLabelOffset-selLabelSize, axisRect.right(), origin.y()-selLabelOffset); } else if (type == QCPAxis::atBottom) { - mAxisSelectionBox.setCoords(axisRect.left(), origin.y()-selAxisInSize, axisRect.right(), origin.y()+selAxisOutSize); - mTickLabelsSelectionBox.setCoords(axisRect.left(), origin.y()+selTickLabelOffset+selTickLabelSize, axisRect.right(), origin.y()+selTickLabelOffset); - mLabelSelectionBox.setCoords(axisRect.left(), origin.y()+selLabelOffset+selLabelSize, axisRect.right(), origin.y()+selLabelOffset); - } - mAxisSelectionBox = mAxisSelectionBox.normalized(); - mTickLabelsSelectionBox = mTickLabelsSelectionBox.normalized(); - mLabelSelectionBox = mLabelSelectionBox.normalized(); - // draw hitboxes for debug purposes: - //painter->setBrush(Qt::NoBrush); - //painter->drawRects(QVector() << mAxisSelectionBox << mTickLabelsSelectionBox << mLabelSelectionBox); + mAxisSelectionBox.setCoords(axisRect.left(), origin.y()-selAxisInSize, axisRect.right(), origin.y()+selAxisOutSize); + mTickLabelsSelectionBox.setCoords(axisRect.left(), origin.y()+selTickLabelOffset+selTickLabelSize, axisRect.right(), origin.y()+selTickLabelOffset); + mLabelSelectionBox.setCoords(axisRect.left(), origin.y()+selLabelOffset+selLabelSize, axisRect.right(), origin.y()+selLabelOffset); + } + mAxisSelectionBox = mAxisSelectionBox.normalized(); + mTickLabelsSelectionBox = mTickLabelsSelectionBox.normalized(); + mLabelSelectionBox = mLabelSelectionBox.normalized(); + // draw hitboxes for debug purposes: + //painter->setBrush(Qt::NoBrush); + //painter->drawRects(QVector() << mAxisSelectionBox << mTickLabelsSelectionBox << mLabelSelectionBox); } /*! \internal @@ -6296,35 +6296,35 @@ void QCPAxisPainterPrivate::draw(QCPPain */ int QCPAxisPainterPrivate::size() const { - int result = 0; - - // get length of tick marks pointing outwards: - if (!tickPositions.isEmpty()) - result += qMax(0, qMax(tickLengthOut, subTickLengthOut)); - - // calculate size of tick labels: - if (tickLabelSide == QCPAxis::lsOutside) - { - QSize tickLabelsSize(0, 0); - if (!tickLabels.isEmpty()) - { - for (int i=0; iplottingHints().testFlag(QCP::phCacheLabels) && !painter->modes().testFlag(QCPPainter::pmNoCaching)) // label caching enabled - { - if (!mLabelCache.contains(text)) // no cached label exists, create it - { - CachedLabel *newCachedLabel = new CachedLabel; - TickLabelData labelData = getTickLabelData(painter->font(), text); - newCachedLabel->offset = getTickLabelDrawOffset(labelData)+labelData.rotatedTotalBounds.topLeft(); - newCachedLabel->pixmap = QPixmap(labelData.rotatedTotalBounds.size()); - newCachedLabel->pixmap.fill(Qt::transparent); - QCPPainter cachePainter(&newCachedLabel->pixmap); - cachePainter.setPen(painter->pen()); - drawTickLabel(&cachePainter, -labelData.rotatedTotalBounds.topLeft().x(), -labelData.rotatedTotalBounds.topLeft().y(), labelData); - mLabelCache.insert(text, newCachedLabel, 1); - } - // draw cached label: - const CachedLabel *cachedLabel = mLabelCache.object(text); - // if label would be partly clipped by widget border on sides, don't draw it (only for outside tick labels): - if (tickLabelSide == QCPAxis::lsOutside) - { - if (QCPAxis::orientation(type) == Qt::Horizontal) - { - if (labelAnchor.x()+cachedLabel->offset.x()+cachedLabel->pixmap.width() > viewportRect.right() || - labelAnchor.x()+cachedLabel->offset.x() < viewportRect.left()) - return; + if (mParentPlot->plottingHints().testFlag(QCP::phCacheLabels) && !painter->modes().testFlag(QCPPainter::pmNoCaching)) // label caching enabled + { + if (!mLabelCache.contains(text)) // no cached label exists, create it + { + CachedLabel *newCachedLabel = new CachedLabel; + TickLabelData labelData = getTickLabelData(painter->font(), text); + newCachedLabel->offset = getTickLabelDrawOffset(labelData)+labelData.rotatedTotalBounds.topLeft(); + newCachedLabel->pixmap = QPixmap(labelData.rotatedTotalBounds.size()); + newCachedLabel->pixmap.fill(Qt::transparent); + QCPPainter cachePainter(&newCachedLabel->pixmap); + cachePainter.setPen(painter->pen()); + drawTickLabel(&cachePainter, -labelData.rotatedTotalBounds.topLeft().x(), -labelData.rotatedTotalBounds.topLeft().y(), labelData); + mLabelCache.insert(text, newCachedLabel, 1); + } + // draw cached label: + const CachedLabel *cachedLabel = mLabelCache.object(text); + // if label would be partly clipped by widget border on sides, don't draw it (only for outside tick labels): + if (tickLabelSide == QCPAxis::lsOutside) + { + if (QCPAxis::orientation(type) == Qt::Horizontal) + { + if (labelAnchor.x()+cachedLabel->offset.x()+cachedLabel->pixmap.width() > viewportRect.right() || + labelAnchor.x()+cachedLabel->offset.x() < viewportRect.left()) + return; } else { - if (labelAnchor.y()+cachedLabel->offset.y()+cachedLabel->pixmap.height() >viewportRect.bottom() || - labelAnchor.y()+cachedLabel->offset.y() < viewportRect.top()) - return; - } - } - painter->drawPixmap(labelAnchor+cachedLabel->offset, cachedLabel->pixmap); - finalSize = cachedLabel->pixmap.size(); + if (labelAnchor.y()+cachedLabel->offset.y()+cachedLabel->pixmap.height() >viewportRect.bottom() || + labelAnchor.y()+cachedLabel->offset.y() < viewportRect.top()) + return; + } + } + painter->drawPixmap(labelAnchor+cachedLabel->offset, cachedLabel->pixmap); + finalSize = cachedLabel->pixmap.size(); } else // label caching disabled, draw text directly on surface: { - TickLabelData labelData = getTickLabelData(painter->font(), text); - QPointF finalPosition = labelAnchor + getTickLabelDrawOffset(labelData); - // if label would be partly clipped by widget border on sides, don't draw it (only for outside tick labels): - if (tickLabelSide == QCPAxis::lsOutside) - { - if (QCPAxis::orientation(type) == Qt::Horizontal) - { - if (finalPosition.x()+(labelData.rotatedTotalBounds.width()+labelData.rotatedTotalBounds.left()) > viewportRect.right() || - finalPosition.x()+labelData.rotatedTotalBounds.left() < viewportRect.left()) - return; + TickLabelData labelData = getTickLabelData(painter->font(), text); + QPointF finalPosition = labelAnchor + getTickLabelDrawOffset(labelData); + // if label would be partly clipped by widget border on sides, don't draw it (only for outside tick labels): + if (tickLabelSide == QCPAxis::lsOutside) + { + if (QCPAxis::orientation(type) == Qt::Horizontal) + { + if (finalPosition.x()+(labelData.rotatedTotalBounds.width()+labelData.rotatedTotalBounds.left()) > viewportRect.right() || + finalPosition.x()+labelData.rotatedTotalBounds.left() < viewportRect.left()) + return; } else { - if (finalPosition.y()+(labelData.rotatedTotalBounds.height()+labelData.rotatedTotalBounds.top()) > viewportRect.bottom() || - finalPosition.y()+labelData.rotatedTotalBounds.top() < viewportRect.top()) - return; - } - } - drawTickLabel(painter, finalPosition.x(), finalPosition.y(), labelData); - finalSize = labelData.rotatedTotalBounds.size(); - } - - // expand passed tickLabelsSize if current tick label is larger: - if (finalSize.width() > tickLabelsSize->width()) - tickLabelsSize->setWidth(finalSize.width()); - if (finalSize.height() > tickLabelsSize->height()) - tickLabelsSize->setHeight(finalSize.height()); + if (finalPosition.y()+(labelData.rotatedTotalBounds.height()+labelData.rotatedTotalBounds.top()) > viewportRect.bottom() || + finalPosition.y()+labelData.rotatedTotalBounds.top() < viewportRect.top()) + return; + } + } + drawTickLabel(painter, finalPosition.x(), finalPosition.y(), labelData); + finalSize = labelData.rotatedTotalBounds.size(); + } + + // expand passed tickLabelsSize if current tick label is larger: + if (finalSize.width() > tickLabelsSize->width()) + tickLabelsSize->setWidth(finalSize.width()); + if (finalSize.height() > tickLabelsSize->height()) + tickLabelsSize->setHeight(finalSize.height()); } /*! \internal @@ -6463,31 +6463,31 @@ void QCPAxisPainterPrivate::placeTickLab */ void QCPAxisPainterPrivate::drawTickLabel(QCPPainter *painter, double x, double y, const TickLabelData &labelData) const { - // backup painter settings that we're about to change: - QTransform oldTransform = painter->transform(); - QFont oldFont = painter->font(); - - // transform painter to position/rotation: - painter->translate(x, y); - if (!qFuzzyIsNull(tickLabelRotation)) - painter->rotate(tickLabelRotation); - - // draw text: - if (!labelData.expPart.isEmpty()) // indicator that beautiful powers must be used - { - painter->setFont(labelData.baseFont); - painter->drawText(0, 0, 0, 0, Qt::TextDontClip, labelData.basePart); - painter->setFont(labelData.expFont); - painter->drawText(labelData.baseBounds.width()+1, 0, labelData.expBounds.width(), labelData.expBounds.height(), Qt::TextDontClip, labelData.expPart); - } else - { - painter->setFont(labelData.baseFont); - painter->drawText(0, 0, labelData.totalBounds.width(), labelData.totalBounds.height(), Qt::TextDontClip | Qt::AlignHCenter, labelData.basePart); - } - - // reset painter settings to what it was before: - painter->setTransform(oldTransform); - painter->setFont(oldFont); + // backup painter settings that we're about to change: + QTransform oldTransform = painter->transform(); + QFont oldFont = painter->font(); + + // transform painter to position/rotation: + painter->translate(x, y); + if (!qFuzzyIsNull(tickLabelRotation)) + painter->rotate(tickLabelRotation); + + // draw text: + if (!labelData.expPart.isEmpty()) // indicator that beautiful powers must be used + { + painter->setFont(labelData.baseFont); + painter->drawText(0, 0, 0, 0, Qt::TextDontClip, labelData.basePart); + painter->setFont(labelData.expFont); + painter->drawText(labelData.baseBounds.width()+1, 0, labelData.expBounds.width(), labelData.expBounds.height(), Qt::TextDontClip, labelData.expPart); + } else + { + painter->setFont(labelData.baseFont); + painter->drawText(0, 0, labelData.totalBounds.width(), labelData.totalBounds.height(), Qt::TextDontClip | Qt::AlignHCenter, labelData.basePart); + } + + // reset painter settings to what it was before: + painter->setTransform(oldTransform); + painter->setFont(oldFont); } /*! \internal @@ -6500,61 +6500,61 @@ void QCPAxisPainterPrivate::drawTickLabe */ QCPAxisPainterPrivate::TickLabelData QCPAxisPainterPrivate::getTickLabelData(const QFont &font, const QString &text) const { - TickLabelData result; - - // determine whether beautiful decimal powers should be used - bool useBeautifulPowers = false; - int ePos = -1; - if (substituteExponent) - { - ePos = text.indexOf(QLatin1Char('e')); - if (ePos > -1) - useBeautifulPowers = true; - } - - // calculate text bounding rects and do string preparation for beautiful decimal powers: - result.baseFont = font; - if (result.baseFont.pointSizeF() > 0) // On some rare systems, this sometimes is initialized with -1 (Qt bug?), so we check here before possibly setting a negative value in the next line - result.baseFont.setPointSizeF(result.baseFont.pointSizeF()+0.05); // QFontMetrics.boundingRect has a bug for exact point sizes that make the results oscillate due to internal rounding - if (useBeautifulPowers) - { - // split text into parts of number/symbol that will be drawn normally and part that will be drawn as exponent: - result.basePart = text.left(ePos); - // in log scaling, we want to turn "1*10^n" into "10^n", else add multiplication sign and decimal base: - if (abbreviateDecimalPowers && result.basePart == QLatin1String("1")) - result.basePart = QLatin1String("10"); - else - result.basePart += (numberMultiplyCross ? QString(QChar(215)) : QString(QChar(183))) + QLatin1String("10"); - result.expPart = text.mid(ePos+1); - // clip "+" and leading zeros off expPart: - while (result.expPart.length() > 2 && result.expPart.at(1) == QLatin1Char('0')) // length > 2 so we leave one zero when numberFormatChar is 'e' - result.expPart.remove(1, 1); - if (!result.expPart.isEmpty() && result.expPart.at(0) == QLatin1Char('+')) - result.expPart.remove(0, 1); - // prepare smaller font for exponent: - result.expFont = font; - result.expFont.setPointSize(result.expFont.pointSize()*0.75); - // calculate bounding rects of base part, exponent part and total one: - result.baseBounds = QFontMetrics(result.baseFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip, result.basePart); - result.expBounds = QFontMetrics(result.expFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip, result.expPart); - result.totalBounds = result.baseBounds.adjusted(0, 0, result.expBounds.width()+2, 0); // +2 consists of the 1 pixel spacing between base and exponent (see drawTickLabel) and an extra pixel to include AA + TickLabelData result; + + // determine whether beautiful decimal powers should be used + bool useBeautifulPowers = false; + int ePos = -1; + if (substituteExponent) + { + ePos = text.indexOf(QLatin1Char('e')); + if (ePos > -1) + useBeautifulPowers = true; + } + + // calculate text bounding rects and do string preparation for beautiful decimal powers: + result.baseFont = font; + if (result.baseFont.pointSizeF() > 0) // On some rare systems, this sometimes is initialized with -1 (Qt bug?), so we check here before possibly setting a negative value in the next line + result.baseFont.setPointSizeF(result.baseFont.pointSizeF()+0.05); // QFontMetrics.boundingRect has a bug for exact point sizes that make the results oscillate due to internal rounding + if (useBeautifulPowers) + { + // split text into parts of number/symbol that will be drawn normally and part that will be drawn as exponent: + result.basePart = text.left(ePos); + // in log scaling, we want to turn "1*10^n" into "10^n", else add multiplication sign and decimal base: + if (abbreviateDecimalPowers && result.basePart == QLatin1String("1")) + result.basePart = QLatin1String("10"); + else + result.basePart += (numberMultiplyCross ? QString(QChar(215)) : QString(QChar(183))) + QLatin1String("10"); + result.expPart = text.mid(ePos+1); + // clip "+" and leading zeros off expPart: + while (result.expPart.length() > 2 && result.expPart.at(1) == QLatin1Char('0')) // length > 2 so we leave one zero when numberFormatChar is 'e' + result.expPart.remove(1, 1); + if (!result.expPart.isEmpty() && result.expPart.at(0) == QLatin1Char('+')) + result.expPart.remove(0, 1); + // prepare smaller font for exponent: + result.expFont = font; + result.expFont.setPointSize(result.expFont.pointSize()*0.75); + // calculate bounding rects of base part, exponent part and total one: + result.baseBounds = QFontMetrics(result.baseFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip, result.basePart); + result.expBounds = QFontMetrics(result.expFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip, result.expPart); + result.totalBounds = result.baseBounds.adjusted(0, 0, result.expBounds.width()+2, 0); // +2 consists of the 1 pixel spacing between base and exponent (see drawTickLabel) and an extra pixel to include AA } else // useBeautifulPowers == false { - result.basePart = text; - result.totalBounds = QFontMetrics(result.baseFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip | Qt::AlignHCenter, result.basePart); - } - result.totalBounds.moveTopLeft(QPoint(0, 0)); // want bounding box aligned top left at origin, independent of how it was created, to make further processing simpler - - // calculate possibly different bounding rect after rotation: - result.rotatedTotalBounds = result.totalBounds; - if (!qFuzzyIsNull(tickLabelRotation)) - { - QTransform transform; - transform.rotate(tickLabelRotation); - result.rotatedTotalBounds = transform.mapRect(result.rotatedTotalBounds); - } - - return result; + result.basePart = text; + result.totalBounds = QFontMetrics(result.baseFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip | Qt::AlignHCenter, result.basePart); + } + result.totalBounds.moveTopLeft(QPoint(0, 0)); // want bounding box aligned top left at origin, independent of how it was created, to make further processing simpler + + // calculate possibly different bounding rect after rotation: + result.rotatedTotalBounds = result.totalBounds; + if (!qFuzzyIsNull(tickLabelRotation)) + { + QTransform transform; + transform.rotate(tickLabelRotation); + result.rotatedTotalBounds = transform.mapRect(result.rotatedTotalBounds); + } + + return result; } /*! \internal @@ -6569,7 +6569,7 @@ QCPAxisPainterPrivate::TickLabelData QCP */ QPointF QCPAxisPainterPrivate::getTickLabelDrawOffset(const TickLabelData &labelData) const { - /* + /* calculate label offset from base point at tick (non-trivial, for best visual appearance): short explanation for bottom axis: The anchor, i.e. the point in the label that is placed horizontally under the corresponding tick is always on the label side that is closer to the @@ -6579,85 +6579,85 @@ QPointF QCPAxisPainterPrivate::getTickLa time, a 45 degree rotated text will "point toward" its tick, as is typical for rotated tick labels. */ - bool doRotation = !qFuzzyIsNull(tickLabelRotation); - bool flip = qFuzzyCompare(qAbs(tickLabelRotation), 90.0); // perfect +/-90 degree flip. Indicates vertical label centering on vertical axes. - double radians = tickLabelRotation/180.0*M_PI; - int x=0, y=0; - if ((type == QCPAxis::atLeft && tickLabelSide == QCPAxis::lsOutside) || (type == QCPAxis::atRight && tickLabelSide == QCPAxis::lsInside)) // Anchor at right side of tick label - { - if (doRotation) - { - if (tickLabelRotation > 0) - { - x = -qCos(radians)*labelData.totalBounds.width(); - y = flip ? -labelData.totalBounds.width()/2.0 : -qSin(radians)*labelData.totalBounds.width()-qCos(radians)*labelData.totalBounds.height()/2.0; + bool doRotation = !qFuzzyIsNull(tickLabelRotation); + bool flip = qFuzzyCompare(qAbs(tickLabelRotation), 90.0); // perfect +/-90 degree flip. Indicates vertical label centering on vertical axes. + double radians = tickLabelRotation/180.0*M_PI; + int x=0, y=0; + if ((type == QCPAxis::atLeft && tickLabelSide == QCPAxis::lsOutside) || (type == QCPAxis::atRight && tickLabelSide == QCPAxis::lsInside)) // Anchor at right side of tick label + { + if (doRotation) + { + if (tickLabelRotation > 0) + { + x = -qCos(radians)*labelData.totalBounds.width(); + y = flip ? -labelData.totalBounds.width()/2.0 : -qSin(radians)*labelData.totalBounds.width()-qCos(radians)*labelData.totalBounds.height()/2.0; } else { - x = -qCos(-radians)*labelData.totalBounds.width()-qSin(-radians)*labelData.totalBounds.height(); - y = flip ? +labelData.totalBounds.width()/2.0 : +qSin(-radians)*labelData.totalBounds.width()-qCos(-radians)*labelData.totalBounds.height()/2.0; + x = -qCos(-radians)*labelData.totalBounds.width()-qSin(-radians)*labelData.totalBounds.height(); + y = flip ? +labelData.totalBounds.width()/2.0 : +qSin(-radians)*labelData.totalBounds.width()-qCos(-radians)*labelData.totalBounds.height()/2.0; } } else { - x = -labelData.totalBounds.width(); - y = -labelData.totalBounds.height()/2.0; + x = -labelData.totalBounds.width(); + y = -labelData.totalBounds.height()/2.0; } } else if ((type == QCPAxis::atRight && tickLabelSide == QCPAxis::lsOutside) || (type == QCPAxis::atLeft && tickLabelSide == QCPAxis::lsInside)) // Anchor at left side of tick label { - if (doRotation) - { - if (tickLabelRotation > 0) - { - x = +qSin(radians)*labelData.totalBounds.height(); - y = flip ? -labelData.totalBounds.width()/2.0 : -qCos(radians)*labelData.totalBounds.height()/2.0; + if (doRotation) + { + if (tickLabelRotation > 0) + { + x = +qSin(radians)*labelData.totalBounds.height(); + y = flip ? -labelData.totalBounds.width()/2.0 : -qCos(radians)*labelData.totalBounds.height()/2.0; } else { - x = 0; - y = flip ? +labelData.totalBounds.width()/2.0 : -qCos(-radians)*labelData.totalBounds.height()/2.0; + x = 0; + y = flip ? +labelData.totalBounds.width()/2.0 : -qCos(-radians)*labelData.totalBounds.height()/2.0; } } else { - x = 0; - y = -labelData.totalBounds.height()/2.0; + x = 0; + y = -labelData.totalBounds.height()/2.0; } } else if ((type == QCPAxis::atTop && tickLabelSide == QCPAxis::lsOutside) || (type == QCPAxis::atBottom && tickLabelSide == QCPAxis::lsInside)) // Anchor at bottom side of tick label { - if (doRotation) - { - if (tickLabelRotation > 0) - { - x = -qCos(radians)*labelData.totalBounds.width()+qSin(radians)*labelData.totalBounds.height()/2.0; - y = -qSin(radians)*labelData.totalBounds.width()-qCos(radians)*labelData.totalBounds.height(); + if (doRotation) + { + if (tickLabelRotation > 0) + { + x = -qCos(radians)*labelData.totalBounds.width()+qSin(radians)*labelData.totalBounds.height()/2.0; + y = -qSin(radians)*labelData.totalBounds.width()-qCos(radians)*labelData.totalBounds.height(); } else { - x = -qSin(-radians)*labelData.totalBounds.height()/2.0; - y = -qCos(-radians)*labelData.totalBounds.height(); + x = -qSin(-radians)*labelData.totalBounds.height()/2.0; + y = -qCos(-radians)*labelData.totalBounds.height(); } } else { - x = -labelData.totalBounds.width()/2.0; - y = -labelData.totalBounds.height(); + x = -labelData.totalBounds.width()/2.0; + y = -labelData.totalBounds.height(); } } else if ((type == QCPAxis::atBottom && tickLabelSide == QCPAxis::lsOutside) || (type == QCPAxis::atTop && tickLabelSide == QCPAxis::lsInside)) // Anchor at top side of tick label { - if (doRotation) - { - if (tickLabelRotation > 0) - { - x = +qSin(radians)*labelData.totalBounds.height()/2.0; - y = 0; + if (doRotation) + { + if (tickLabelRotation > 0) + { + x = +qSin(radians)*labelData.totalBounds.height()/2.0; + y = 0; } else { - x = -qCos(-radians)*labelData.totalBounds.width()-qSin(-radians)*labelData.totalBounds.height()/2.0; - y = +qSin(-radians)*labelData.totalBounds.width(); + x = -qCos(-radians)*labelData.totalBounds.width()-qSin(-radians)*labelData.totalBounds.height()/2.0; + y = +qSin(-radians)*labelData.totalBounds.width(); } } else { - x = -labelData.totalBounds.width()/2.0; - y = 0; - } - } - - return QPointF(x, y); + x = -labelData.totalBounds.width()/2.0; + y = 0; + } + } + + return QPointF(x, y); } /*! \internal @@ -6669,23 +6669,23 @@ QPointF QCPAxisPainterPrivate::getTickLa */ void QCPAxisPainterPrivate::getMaxTickLabelSize(const QFont &font, const QString &text, QSize *tickLabelsSize) const { - // note: this function must return the same tick label sizes as the placeTickLabel function. - QSize finalSize; - if (mParentPlot->plottingHints().testFlag(QCP::phCacheLabels) && mLabelCache.contains(text)) // label caching enabled and have cached label - { - const CachedLabel *cachedLabel = mLabelCache.object(text); - finalSize = cachedLabel->pixmap.size(); + // note: this function must return the same tick label sizes as the placeTickLabel function. + QSize finalSize; + if (mParentPlot->plottingHints().testFlag(QCP::phCacheLabels) && mLabelCache.contains(text)) // label caching enabled and have cached label + { + const CachedLabel *cachedLabel = mLabelCache.object(text); + finalSize = cachedLabel->pixmap.size(); } else // label caching disabled or no label with this text cached: { - TickLabelData labelData = getTickLabelData(font, text); - finalSize = labelData.rotatedTotalBounds.size(); - } - - // expand passed tickLabelsSize if current tick label is larger: - if (finalSize.width() > tickLabelsSize->width()) - tickLabelsSize->setWidth(finalSize.width()); - if (finalSize.height() > tickLabelsSize->height()) - tickLabelsSize->setHeight(finalSize.height()); + TickLabelData labelData = getTickLabelData(font, text); + finalSize = labelData.rotatedTotalBounds.size(); + } + + // expand passed tickLabelsSize if current tick label is larger: + if (finalSize.width() > tickLabelsSize->width()) + tickLabelsSize->setWidth(finalSize.width()); + if (finalSize.height() > tickLabelsSize->height()) + tickLabelsSize->setHeight(finalSize.height()); } @@ -6838,24 +6838,24 @@ void QCPAxisPainterPrivate::getMaxTickLa You probably want one of the subclasses like \ref QCPGraph or \ref QCPCurve instead. */ QCPAbstractPlottable::QCPAbstractPlottable(QCPAxis *keyAxis, QCPAxis *valueAxis) : - QCPLayerable(keyAxis->parentPlot(), QString(), keyAxis->axisRect()), - mName(), - mAntialiasedFill(true), - mAntialiasedScatters(true), - mAntialiasedErrorBars(false), - mPen(Qt::black), - mSelectedPen(Qt::black), - mBrush(Qt::NoBrush), - mSelectedBrush(Qt::NoBrush), - mKeyAxis(keyAxis), - mValueAxis(valueAxis), - mSelectable(true), - mSelected(false) -{ - if (keyAxis->parentPlot() != valueAxis->parentPlot()) - qDebug() << Q_FUNC_INFO << "Parent plot of keyAxis is not the same as that of valueAxis."; - if (keyAxis->orientation() == valueAxis->orientation()) - qDebug() << Q_FUNC_INFO << "keyAxis and valueAxis must be orthogonal to each other."; + QCPLayerable(keyAxis->parentPlot(), QString(), keyAxis->axisRect()), + mName(), + mAntialiasedFill(true), + mAntialiasedScatters(true), + mAntialiasedErrorBars(false), + mPen(Qt::black), + mSelectedPen(Qt::black), + mBrush(Qt::NoBrush), + mSelectedBrush(Qt::NoBrush), + mKeyAxis(keyAxis), + mValueAxis(valueAxis), + mSelectable(true), + mSelected(false) +{ + if (keyAxis->parentPlot() != valueAxis->parentPlot()) + qDebug() << Q_FUNC_INFO << "Parent plot of keyAxis is not the same as that of valueAxis."; + if (keyAxis->orientation() == valueAxis->orientation()) + qDebug() << Q_FUNC_INFO << "keyAxis and valueAxis must be orthogonal to each other."; } /*! @@ -6864,7 +6864,7 @@ QCPAbstractPlottable::QCPAbstractPlottab */ void QCPAbstractPlottable::setName(const QString &name) { - mName = name; + mName = name; } /*! @@ -6875,7 +6875,7 @@ void QCPAbstractPlottable::setName(const */ void QCPAbstractPlottable::setAntialiasedFill(bool enabled) { - mAntialiasedFill = enabled; + mAntialiasedFill = enabled; } /*! @@ -6886,7 +6886,7 @@ void QCPAbstractPlottable::setAntialiase */ void QCPAbstractPlottable::setAntialiasedScatters(bool enabled) { - mAntialiasedScatters = enabled; + mAntialiasedScatters = enabled; } /*! @@ -6897,7 +6897,7 @@ void QCPAbstractPlottable::setAntialiase */ void QCPAbstractPlottable::setAntialiasedErrorBars(bool enabled) { - mAntialiasedErrorBars = enabled; + mAntialiasedErrorBars = enabled; } @@ -6912,7 +6912,7 @@ void QCPAbstractPlottable::setAntialiase */ void QCPAbstractPlottable::setPen(const QPen &pen) { - mPen = pen; + mPen = pen; } /*! @@ -6923,7 +6923,7 @@ void QCPAbstractPlottable::setPen(const */ void QCPAbstractPlottable::setSelectedPen(const QPen &pen) { - mSelectedPen = pen; + mSelectedPen = pen; } /*! @@ -6937,7 +6937,7 @@ void QCPAbstractPlottable::setSelectedPe */ void QCPAbstractPlottable::setBrush(const QBrush &brush) { - mBrush = brush; + mBrush = brush; } /*! @@ -6948,7 +6948,7 @@ void QCPAbstractPlottable::setBrush(cons */ void QCPAbstractPlottable::setSelectedBrush(const QBrush &brush) { - mSelectedBrush = brush; + mSelectedBrush = brush; } /*! @@ -6964,7 +6964,7 @@ void QCPAbstractPlottable::setSelectedBr */ void QCPAbstractPlottable::setKeyAxis(QCPAxis *axis) { - mKeyAxis = axis; + mKeyAxis = axis; } /*! @@ -6980,7 +6980,7 @@ void QCPAbstractPlottable::setKeyAxis(QC */ void QCPAbstractPlottable::setValueAxis(QCPAxis *axis) { - mValueAxis = axis; + mValueAxis = axis; } /*! @@ -6994,10 +6994,10 @@ void QCPAbstractPlottable::setValueAxis( */ void QCPAbstractPlottable::setSelectable(bool selectable) { - if (mSelectable != selectable) - { - mSelectable = selectable; - emit selectableChanged(mSelectable); + if (mSelectable != selectable) + { + mSelectable = selectable; + emit selectableChanged(mSelectable); } } @@ -7017,10 +7017,10 @@ void QCPAbstractPlottable::setSelectable */ void QCPAbstractPlottable::setSelected(bool selected) { - if (mSelected != selected) - { - mSelected = selected; - emit selectionChanged(mSelected); + if (mSelected != selected) + { + mSelected = selected; + emit selectionChanged(mSelected); } } @@ -7039,8 +7039,8 @@ void QCPAbstractPlottable::setSelected(b */ void QCPAbstractPlottable::rescaleAxes(bool onlyEnlarge) const { - rescaleKeyAxis(onlyEnlarge); - rescaleValueAxis(onlyEnlarge); + rescaleKeyAxis(onlyEnlarge); + rescaleValueAxis(onlyEnlarge); } /*! @@ -7050,33 +7050,33 @@ void QCPAbstractPlottable::rescaleAxes(b */ void QCPAbstractPlottable::rescaleKeyAxis(bool onlyEnlarge) const { - QCPAxis *keyAxis = mKeyAxis.data(); - if (!keyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; } - - SignDomain signDomain = sdBoth; - if (keyAxis->scaleType() == QCPAxis::stLogarithmic) - signDomain = (keyAxis->range().upper < 0 ? sdNegative : sdPositive); - - bool foundRange; - QCPRange newRange = getKeyRange(foundRange, signDomain); - if (foundRange) - { - if (onlyEnlarge) - newRange.expand(keyAxis->range()); - if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable - { - double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason - if (keyAxis->scaleType() == QCPAxis::stLinear) - { - newRange.lower = center-keyAxis->range().size()/2.0; - newRange.upper = center+keyAxis->range().size()/2.0; + QCPAxis *keyAxis = mKeyAxis.data(); + if (!keyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; } + + SignDomain signDomain = sdBoth; + if (keyAxis->scaleType() == QCPAxis::stLogarithmic) + signDomain = (keyAxis->range().upper < 0 ? sdNegative : sdPositive); + + bool foundRange; + QCPRange newRange = getKeyRange(foundRange, signDomain); + if (foundRange) + { + if (onlyEnlarge) + newRange.expand(keyAxis->range()); + if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable + { + double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason + if (keyAxis->scaleType() == QCPAxis::stLinear) + { + newRange.lower = center-keyAxis->range().size()/2.0; + newRange.upper = center+keyAxis->range().size()/2.0; } else // scaleType() == stLogarithmic { - newRange.lower = center/qSqrt(keyAxis->range().upper/keyAxis->range().lower); - newRange.upper = center*qSqrt(keyAxis->range().upper/keyAxis->range().lower); - } - } - keyAxis->setRange(newRange); + newRange.lower = center/qSqrt(keyAxis->range().upper/keyAxis->range().lower); + newRange.upper = center*qSqrt(keyAxis->range().upper/keyAxis->range().lower); + } + } + keyAxis->setRange(newRange); } } @@ -7090,33 +7090,33 @@ void QCPAbstractPlottable::rescaleKeyAxi */ void QCPAbstractPlottable::rescaleValueAxis(bool onlyEnlarge) const { - QCPAxis *valueAxis = mValueAxis.data(); - if (!valueAxis) { qDebug() << Q_FUNC_INFO << "invalid value axis"; return; } - - SignDomain signDomain = sdBoth; - if (valueAxis->scaleType() == QCPAxis::stLogarithmic) - signDomain = (valueAxis->range().upper < 0 ? sdNegative : sdPositive); - - bool foundRange; - QCPRange newRange = getValueRange(foundRange, signDomain); - if (foundRange) - { - if (onlyEnlarge) - newRange.expand(valueAxis->range()); - if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable - { - double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason - if (valueAxis->scaleType() == QCPAxis::stLinear) - { - newRange.lower = center-valueAxis->range().size()/2.0; - newRange.upper = center+valueAxis->range().size()/2.0; + QCPAxis *valueAxis = mValueAxis.data(); + if (!valueAxis) { qDebug() << Q_FUNC_INFO << "invalid value axis"; return; } + + SignDomain signDomain = sdBoth; + if (valueAxis->scaleType() == QCPAxis::stLogarithmic) + signDomain = (valueAxis->range().upper < 0 ? sdNegative : sdPositive); + + bool foundRange; + QCPRange newRange = getValueRange(foundRange, signDomain); + if (foundRange) + { + if (onlyEnlarge) + newRange.expand(valueAxis->range()); + if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable + { + double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason + if (valueAxis->scaleType() == QCPAxis::stLinear) + { + newRange.lower = center-valueAxis->range().size()/2.0; + newRange.upper = center+valueAxis->range().size()/2.0; } else // scaleType() == stLogarithmic { - newRange.lower = center/qSqrt(valueAxis->range().upper/valueAxis->range().lower); - newRange.upper = center*qSqrt(valueAxis->range().upper/valueAxis->range().lower); - } - } - valueAxis->setRange(newRange); + newRange.lower = center/qSqrt(valueAxis->range().upper/valueAxis->range().lower); + newRange.upper = center*qSqrt(valueAxis->range().upper/valueAxis->range().lower); + } + } + valueAxis->setRange(newRange); } } @@ -7134,15 +7134,15 @@ void QCPAbstractPlottable::rescaleValueA */ bool QCPAbstractPlottable::addToLegend() { - if (!mParentPlot || !mParentPlot->legend) - return false; - - if (!mParentPlot->legend->hasItemWithPlottable(this)) - { - mParentPlot->legend->addItem(new QCPPlottableLegendItem(mParentPlot->legend, this)); - return true; - } else - return false; + if (!mParentPlot || !mParentPlot->legend) + return false; + + if (!mParentPlot->legend->hasItemWithPlottable(this)) + { + mParentPlot->legend->addItem(new QCPPlottableLegendItem(mParentPlot->legend, this)); + return true; + } else + return false; } /*! @@ -7157,28 +7157,28 @@ bool QCPAbstractPlottable::addToLegend() */ bool QCPAbstractPlottable::removeFromLegend() const { - if (!mParentPlot->legend) - return false; - - if (QCPPlottableLegendItem *lip = mParentPlot->legend->itemWithPlottable(this)) - return mParentPlot->legend->removeItem(lip); - else - return false; + if (!mParentPlot->legend) + return false; + + if (QCPPlottableLegendItem *lip = mParentPlot->legend->itemWithPlottable(this)) + return mParentPlot->legend->removeItem(lip); + else + return false; } /* inherits documentation from base class */ QRect QCPAbstractPlottable::clipRect() const { - if (mKeyAxis && mValueAxis) - return mKeyAxis.data()->axisRect()->rect() & mValueAxis.data()->axisRect()->rect(); - else - return QRect(); + if (mKeyAxis && mValueAxis) + return mKeyAxis.data()->axisRect()->rect() & mValueAxis.data()->axisRect()->rect(); + else + return QRect(); } /* inherits documentation from base class */ QCP::Interaction QCPAbstractPlottable::selectionCategory() const { - return QCP::iSelectPlottables; + return QCP::iSelectPlottables; } /*! \internal @@ -7193,18 +7193,18 @@ QCP::Interaction QCPAbstractPlottable::s */ void QCPAbstractPlottable::coordsToPixels(double key, double value, double &x, double &y) const { - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - - if (keyAxis->orientation() == Qt::Horizontal) - { - x = keyAxis->coordToPixel(key); - y = valueAxis->coordToPixel(value); - } else - { - y = keyAxis->coordToPixel(key); - x = valueAxis->coordToPixel(value); + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + + if (keyAxis->orientation() == Qt::Horizontal) + { + x = keyAxis->coordToPixel(key); + y = valueAxis->coordToPixel(value); + } else + { + y = keyAxis->coordToPixel(key); + x = valueAxis->coordToPixel(value); } } @@ -7215,14 +7215,14 @@ void QCPAbstractPlottable::coordsToPixel */ const QPointF QCPAbstractPlottable::coordsToPixels(double key, double value) const { - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPointF(); } - - if (keyAxis->orientation() == Qt::Horizontal) - return QPointF(keyAxis->coordToPixel(key), valueAxis->coordToPixel(value)); - else - return QPointF(valueAxis->coordToPixel(value), keyAxis->coordToPixel(key)); + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPointF(); } + + if (keyAxis->orientation() == Qt::Horizontal) + return QPointF(keyAxis->coordToPixel(key), valueAxis->coordToPixel(value)); + else + return QPointF(valueAxis->coordToPixel(value), keyAxis->coordToPixel(key)); } /*! \internal @@ -7237,18 +7237,18 @@ const QPointF QCPAbstractPlottable::coor */ void QCPAbstractPlottable::pixelsToCoords(double x, double y, double &key, double &value) const { - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - - if (keyAxis->orientation() == Qt::Horizontal) - { - key = keyAxis->pixelToCoord(x); - value = valueAxis->pixelToCoord(y); - } else - { - key = keyAxis->pixelToCoord(y); - value = valueAxis->pixelToCoord(x); + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + + if (keyAxis->orientation() == Qt::Horizontal) + { + key = keyAxis->pixelToCoord(x); + value = valueAxis->pixelToCoord(y); + } else + { + key = keyAxis->pixelToCoord(y); + value = valueAxis->pixelToCoord(x); } } @@ -7259,7 +7259,7 @@ void QCPAbstractPlottable::pixelsToCoord */ void QCPAbstractPlottable::pixelsToCoords(const QPointF &pixelPos, double &key, double &value) const { - pixelsToCoords(pixelPos.x(), pixelPos.y(), key, value); + pixelsToCoords(pixelPos.x(), pixelPos.y(), key, value); } /*! \internal @@ -7269,7 +7269,7 @@ void QCPAbstractPlottable::pixelsToCoord */ QPen QCPAbstractPlottable::mainPen() const { - return mSelected ? mSelectedPen : mPen; + return mSelected ? mSelectedPen : mPen; } /*! \internal @@ -7279,7 +7279,7 @@ QPen QCPAbstractPlottable::mainPen() con */ QBrush QCPAbstractPlottable::mainBrush() const { - return mSelected ? mSelectedBrush : mBrush; + return mSelected ? mSelectedBrush : mBrush; } /*! \internal @@ -7297,7 +7297,7 @@ QBrush QCPAbstractPlottable::mainBrush() */ void QCPAbstractPlottable::applyDefaultAntialiasingHint(QCPPainter *painter) const { - applyAntialiasingHint(painter, mAntialiased, QCP::aePlottables); + applyAntialiasingHint(painter, mAntialiased, QCP::aePlottables); } /*! \internal @@ -7313,7 +7313,7 @@ void QCPAbstractPlottable::applyDefaultA */ void QCPAbstractPlottable::applyFillAntialiasingHint(QCPPainter *painter) const { - applyAntialiasingHint(painter, mAntialiasedFill, QCP::aeFills); + applyAntialiasingHint(painter, mAntialiasedFill, QCP::aeFills); } /*! \internal @@ -7329,7 +7329,7 @@ void QCPAbstractPlottable::applyFillAnti */ void QCPAbstractPlottable::applyScattersAntialiasingHint(QCPPainter *painter) const { - applyAntialiasingHint(painter, mAntialiasedScatters, QCP::aeScatters); + applyAntialiasingHint(painter, mAntialiasedScatters, QCP::aeScatters); } /*! \internal @@ -7345,7 +7345,7 @@ void QCPAbstractPlottable::applyScatters */ void QCPAbstractPlottable::applyErrorBarsAntialiasingHint(QCPPainter *painter) const { - applyAntialiasingHint(painter, mAntialiasedErrorBars, QCP::aeErrorBars); + applyAntialiasingHint(painter, mAntialiasedErrorBars, QCP::aeErrorBars); } /*! \internal @@ -7360,48 +7360,48 @@ void QCPAbstractPlottable::applyErrorBar */ double QCPAbstractPlottable::distSqrToLine(const QPointF &start, const QPointF &end, const QPointF &point) const { - QVector2D a(start); - QVector2D b(end); - QVector2D p(point); - QVector2D v(b-a); - - double vLengthSqr = v.lengthSquared(); - if (!qFuzzyIsNull(vLengthSqr)) - { - double mu = QVector2D::dotProduct(p-a, v)/vLengthSqr; - if (mu < 0) + QVector2D a(start); + QVector2D b(end); + QVector2D p(point); + QVector2D v(b-a); + + double vLengthSqr = v.lengthSquared(); + if (!qFuzzyIsNull(vLengthSqr)) + { + double mu = QVector2D::dotProduct(p-a, v)/vLengthSqr; + if (mu < 0) + return (a-p).lengthSquared(); + else if (mu > 1) + return (b-p).lengthSquared(); + else + return ((a + mu*v)-p).lengthSquared(); + } else return (a-p).lengthSquared(); - else if (mu > 1) - return (b-p).lengthSquared(); - else - return ((a + mu*v)-p).lengthSquared(); - } else - return (a-p).lengthSquared(); } /* inherits documentation from base class */ void QCPAbstractPlottable::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) { - Q_UNUSED(event) - Q_UNUSED(details) - if (mSelectable) - { - bool selBefore = mSelected; - setSelected(additive ? !mSelected : true); - if (selectionStateChanged) - *selectionStateChanged = mSelected != selBefore; + Q_UNUSED(event) + Q_UNUSED(details) + if (mSelectable) + { + bool selBefore = mSelected; + setSelected(additive ? !mSelected : true); + if (selectionStateChanged) + *selectionStateChanged = mSelected != selBefore; } } /* inherits documentation from base class */ void QCPAbstractPlottable::deselectEvent(bool *selectionStateChanged) { - if (mSelectable) - { - bool selBefore = mSelected; - setSelected(false); - if (selectionStateChanged) - *selectionStateChanged = mSelected != selBefore; + if (mSelectable) + { + bool selBefore = mSelected; + setSelected(false); + if (selectionStateChanged) + *selectionStateChanged = mSelected != selBefore; } } @@ -7451,25 +7451,25 @@ void QCPAbstractPlottable::deselectEvent explained in the subclassing section of the QCPAbstractItem documentation. */ QCPItemAnchor::QCPItemAnchor(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString name, int anchorId) : - mName(name), - mParentPlot(parentPlot), - mParentItem(parentItem), - mAnchorId(anchorId) + mName(name), + mParentPlot(parentPlot), + mParentItem(parentItem), + mAnchorId(anchorId) { } QCPItemAnchor::~QCPItemAnchor() { - // unregister as parent at children: - foreach (QCPItemPosition *child, mChildrenX.toList()) - { - if (child->parentAnchorX() == this) - child->setParentAnchorX(0); // this acts back on this anchor and child removes itself from mChildrenX - } - foreach (QCPItemPosition *child, mChildrenY.toList()) - { - if (child->parentAnchorY() == this) - child->setParentAnchorY(0); // this acts back on this anchor and child removes itself from mChildrenY + // unregister as parent at children: + foreach (QCPItemPosition *child, mChildrenX.toList()) + { + if (child->parentAnchorX() == this) + child->setParentAnchorX(0); // this acts back on this anchor and child removes itself from mChildrenX + } + foreach (QCPItemPosition *child, mChildrenY.toList()) + { + if (child->parentAnchorY() == this) + child->setParentAnchorY(0); // this acts back on this anchor and child removes itself from mChildrenY } } @@ -7481,20 +7481,20 @@ QCPItemAnchor::~QCPItemAnchor() */ QPointF QCPItemAnchor::pixelPoint() const { - if (mParentItem) - { - if (mAnchorId > -1) - { - return mParentItem->anchorPixelPoint(mAnchorId); + if (mParentItem) + { + if (mAnchorId > -1) + { + return mParentItem->anchorPixelPoint(mAnchorId); } else { - qDebug() << Q_FUNC_INFO << "no valid anchor id set:" << mAnchorId; - return QPointF(); - } - } else - { - qDebug() << Q_FUNC_INFO << "no parent item set"; - return QPointF(); + qDebug() << Q_FUNC_INFO << "no valid anchor id set:" << mAnchorId; + return QPointF(); + } + } else + { + qDebug() << Q_FUNC_INFO << "no parent item set"; + return QPointF(); } } @@ -7508,10 +7508,10 @@ QPointF QCPItemAnchor::pixelPoint() cons */ void QCPItemAnchor::addChildX(QCPItemPosition *pos) { - if (!mChildrenX.contains(pos)) - mChildrenX.insert(pos); - else - qDebug() << Q_FUNC_INFO << "provided pos is child already" << reinterpret_cast(pos); + if (!mChildrenX.contains(pos)) + mChildrenX.insert(pos); + else + qDebug() << Q_FUNC_INFO << "provided pos is child already" << reinterpret_cast(pos); } /*! \internal @@ -7522,8 +7522,8 @@ void QCPItemAnchor::addChildX(QCPItemPos */ void QCPItemAnchor::removeChildX(QCPItemPosition *pos) { - if (!mChildrenX.remove(pos)) - qDebug() << Q_FUNC_INFO << "provided pos isn't child" << reinterpret_cast(pos); + if (!mChildrenX.remove(pos)) + qDebug() << Q_FUNC_INFO << "provided pos isn't child" << reinterpret_cast(pos); } /*! \internal @@ -7536,10 +7536,10 @@ void QCPItemAnchor::removeChildX(QCPItem */ void QCPItemAnchor::addChildY(QCPItemPosition *pos) { - if (!mChildrenY.contains(pos)) - mChildrenY.insert(pos); - else - qDebug() << Q_FUNC_INFO << "provided pos is child already" << reinterpret_cast(pos); + if (!mChildrenY.contains(pos)) + mChildrenY.insert(pos); + else + qDebug() << Q_FUNC_INFO << "provided pos is child already" << reinterpret_cast(pos); } /*! \internal @@ -7550,8 +7550,8 @@ void QCPItemAnchor::addChildY(QCPItemPos */ void QCPItemAnchor::removeChildY(QCPItemPosition *pos) { - if (!mChildrenY.remove(pos)) - qDebug() << Q_FUNC_INFO << "provided pos isn't child" << reinterpret_cast(pos); + if (!mChildrenY.remove(pos)) + qDebug() << Q_FUNC_INFO << "provided pos isn't child" << reinterpret_cast(pos); } @@ -7624,42 +7624,42 @@ void QCPItemAnchor::removeChildY(QCPItem explained in the subclassing section of the QCPAbstractItem documentation. */ QCPItemPosition::QCPItemPosition(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString name) : - QCPItemAnchor(parentPlot, parentItem, name), - mPositionTypeX(ptAbsolute), - mPositionTypeY(ptAbsolute), - mKey(0), - mValue(0), - mParentAnchorX(0), - mParentAnchorY(0) + QCPItemAnchor(parentPlot, parentItem, name), + mPositionTypeX(ptAbsolute), + mPositionTypeY(ptAbsolute), + mKey(0), + mValue(0), + mParentAnchorX(0), + mParentAnchorY(0) { } QCPItemPosition::~QCPItemPosition() { - // unregister as parent at children: - // Note: this is done in ~QCPItemAnchor again, but it's important QCPItemPosition does it itself, because only then - // the setParentAnchor(0) call the correct QCPItemPosition::pixelPoint function instead of QCPItemAnchor::pixelPoint - foreach (QCPItemPosition *child, mChildrenX.toList()) - { - if (child->parentAnchorX() == this) - child->setParentAnchorX(0); // this acts back on this anchor and child removes itself from mChildrenX - } - foreach (QCPItemPosition *child, mChildrenY.toList()) - { - if (child->parentAnchorY() == this) - child->setParentAnchorY(0); // this acts back on this anchor and child removes itself from mChildrenY - } - // unregister as child in parent: - if (mParentAnchorX) - mParentAnchorX->removeChildX(this); - if (mParentAnchorY) - mParentAnchorY->removeChildY(this); + // unregister as parent at children: + // Note: this is done in ~QCPItemAnchor again, but it's important QCPItemPosition does it itself, because only then + // the setParentAnchor(0) call the correct QCPItemPosition::pixelPoint function instead of QCPItemAnchor::pixelPoint + foreach (QCPItemPosition *child, mChildrenX.toList()) + { + if (child->parentAnchorX() == this) + child->setParentAnchorX(0); // this acts back on this anchor and child removes itself from mChildrenX + } + foreach (QCPItemPosition *child, mChildrenY.toList()) + { + if (child->parentAnchorY() == this) + child->setParentAnchorY(0); // this acts back on this anchor and child removes itself from mChildrenY + } + // unregister as child in parent: + if (mParentAnchorX) + mParentAnchorX->removeChildX(this); + if (mParentAnchorY) + mParentAnchorY->removeChildY(this); } /* can't make this a header inline function, because QPointer breaks with forward declared types, see QTBUG-29588 */ QCPAxisRect *QCPItemPosition::axisRect() const { - return mAxisRect.data(); + return mAxisRect.data(); } /*! @@ -7689,8 +7689,8 @@ QCPAxisRect *QCPItemPosition::axisRect() */ void QCPItemPosition::setType(QCPItemPosition::PositionType type) { - setTypeX(type); - setTypeY(type); + setTypeX(type); + setTypeY(type); } /*! @@ -7702,24 +7702,24 @@ void QCPItemPosition::setType(QCPItemPos */ void QCPItemPosition::setTypeX(QCPItemPosition::PositionType type) { - if (mPositionTypeX != type) - { - // if switching from or to coordinate type that isn't valid (e.g. because axes or axis rect - // were deleted), don't try to recover the pixelPoint() because it would output a qDebug warning. - bool retainPixelPosition = true; - if ((mPositionTypeX == ptPlotCoords || type == ptPlotCoords) && (!mKeyAxis || !mValueAxis)) - retainPixelPosition = false; - if ((mPositionTypeX == ptAxisRectRatio || type == ptAxisRectRatio) && (!mAxisRect)) - retainPixelPosition = false; - - QPointF pixel; - if (retainPixelPosition) - pixel = pixelPoint(); - - mPositionTypeX = type; - - if (retainPixelPosition) - setPixelPoint(pixel); + if (mPositionTypeX != type) + { + // if switching from or to coordinate type that isn't valid (e.g. because axes or axis rect + // were deleted), don't try to recover the pixelPoint() because it would output a qDebug warning. + bool retainPixelPosition = true; + if ((mPositionTypeX == ptPlotCoords || type == ptPlotCoords) && (!mKeyAxis || !mValueAxis)) + retainPixelPosition = false; + if ((mPositionTypeX == ptAxisRectRatio || type == ptAxisRectRatio) && (!mAxisRect)) + retainPixelPosition = false; + + QPointF pixel; + if (retainPixelPosition) + pixel = pixelPoint(); + + mPositionTypeX = type; + + if (retainPixelPosition) + setPixelPoint(pixel); } } @@ -7732,24 +7732,24 @@ void QCPItemPosition::setTypeX(QCPItemPo */ void QCPItemPosition::setTypeY(QCPItemPosition::PositionType type) { - if (mPositionTypeY != type) - { - // if switching from or to coordinate type that isn't valid (e.g. because axes or axis rect - // were deleted), don't try to recover the pixelPoint() because it would output a qDebug warning. - bool retainPixelPosition = true; - if ((mPositionTypeY == ptPlotCoords || type == ptPlotCoords) && (!mKeyAxis || !mValueAxis)) - retainPixelPosition = false; - if ((mPositionTypeY == ptAxisRectRatio || type == ptAxisRectRatio) && (!mAxisRect)) - retainPixelPosition = false; - - QPointF pixel; - if (retainPixelPosition) - pixel = pixelPoint(); - - mPositionTypeY = type; - - if (retainPixelPosition) - setPixelPoint(pixel); + if (mPositionTypeY != type) + { + // if switching from or to coordinate type that isn't valid (e.g. because axes or axis rect + // were deleted), don't try to recover the pixelPoint() because it would output a qDebug warning. + bool retainPixelPosition = true; + if ((mPositionTypeY == ptPlotCoords || type == ptPlotCoords) && (!mKeyAxis || !mValueAxis)) + retainPixelPosition = false; + if ((mPositionTypeY == ptAxisRectRatio || type == ptAxisRectRatio) && (!mAxisRect)) + retainPixelPosition = false; + + QPointF pixel; + if (retainPixelPosition) + pixel = pixelPoint(); + + mPositionTypeY = type; + + if (retainPixelPosition) + setPixelPoint(pixel); } } @@ -7773,9 +7773,9 @@ void QCPItemPosition::setTypeY(QCPItemPo */ bool QCPItemPosition::setParentAnchor(QCPItemAnchor *parentAnchor, bool keepPixelPosition) { - bool successX = setParentAnchorX(parentAnchor, keepPixelPosition); - bool successY = setParentAnchorY(parentAnchor, keepPixelPosition); - return successX && successY; + bool successX = setParentAnchorX(parentAnchor, keepPixelPosition); + bool successY = setParentAnchorY(parentAnchor, keepPixelPosition); + return successX && successY; } /*! @@ -7787,60 +7787,60 @@ bool QCPItemPosition::setParentAnchor(QC */ bool QCPItemPosition::setParentAnchorX(QCPItemAnchor *parentAnchor, bool keepPixelPosition) { - // make sure self is not assigned as parent: - if (parentAnchor == this) - { - qDebug() << Q_FUNC_INFO << "can't set self as parent anchor" << reinterpret_cast(parentAnchor); - return false; - } - // make sure no recursive parent-child-relationships are created: - QCPItemAnchor *currentParent = parentAnchor; - while (currentParent) - { - if (QCPItemPosition *currentParentPos = currentParent->toQCPItemPosition()) - { - // is a QCPItemPosition, might have further parent, so keep iterating - if (currentParentPos == this) - { - qDebug() << Q_FUNC_INFO << "can't create recursive parent-child-relationship" << reinterpret_cast(parentAnchor); - return false; - } - currentParent = currentParentPos->parentAnchorX(); + // make sure self is not assigned as parent: + if (parentAnchor == this) + { + qDebug() << Q_FUNC_INFO << "can't set self as parent anchor" << reinterpret_cast(parentAnchor); + return false; + } + // make sure no recursive parent-child-relationships are created: + QCPItemAnchor *currentParent = parentAnchor; + while (currentParent) + { + if (QCPItemPosition *currentParentPos = currentParent->toQCPItemPosition()) + { + // is a QCPItemPosition, might have further parent, so keep iterating + if (currentParentPos == this) + { + qDebug() << Q_FUNC_INFO << "can't create recursive parent-child-relationship" << reinterpret_cast(parentAnchor); + return false; + } + currentParent = currentParentPos->parentAnchorX(); } else { - // is a QCPItemAnchor, can't have further parent. Now make sure the parent items aren't the - // same, to prevent a position being child of an anchor which itself depends on the position, - // because they're both on the same item: - if (currentParent->mParentItem == mParentItem) - { - qDebug() << Q_FUNC_INFO << "can't set parent to be an anchor which itself depends on this position" << reinterpret_cast(parentAnchor); - return false; - } - break; - } - } - - // if previously no parent set and PosType is still ptPlotCoords, set to ptAbsolute: - if (!mParentAnchorX && mPositionTypeX == ptPlotCoords) - setTypeX(ptAbsolute); - - // save pixel position: - QPointF pixelP; - if (keepPixelPosition) - pixelP = pixelPoint(); - // unregister at current parent anchor: - if (mParentAnchorX) - mParentAnchorX->removeChildX(this); - // register at new parent anchor: - if (parentAnchor) - parentAnchor->addChildX(this); - mParentAnchorX = parentAnchor; - // restore pixel position under new parent: - if (keepPixelPosition) - setPixelPoint(pixelP); - else - setCoords(0, coords().y()); - return true; + // is a QCPItemAnchor, can't have further parent. Now make sure the parent items aren't the + // same, to prevent a position being child of an anchor which itself depends on the position, + // because they're both on the same item: + if (currentParent->mParentItem == mParentItem) + { + qDebug() << Q_FUNC_INFO << "can't set parent to be an anchor which itself depends on this position" << reinterpret_cast(parentAnchor); + return false; + } + break; + } + } + + // if previously no parent set and PosType is still ptPlotCoords, set to ptAbsolute: + if (!mParentAnchorX && mPositionTypeX == ptPlotCoords) + setTypeX(ptAbsolute); + + // save pixel position: + QPointF pixelP; + if (keepPixelPosition) + pixelP = pixelPoint(); + // unregister at current parent anchor: + if (mParentAnchorX) + mParentAnchorX->removeChildX(this); + // register at new parent anchor: + if (parentAnchor) + parentAnchor->addChildX(this); + mParentAnchorX = parentAnchor; + // restore pixel position under new parent: + if (keepPixelPosition) + setPixelPoint(pixelP); + else + setCoords(0, coords().y()); + return true; } /*! @@ -7852,60 +7852,60 @@ bool QCPItemPosition::setParentAnchorX(Q */ bool QCPItemPosition::setParentAnchorY(QCPItemAnchor *parentAnchor, bool keepPixelPosition) { - // make sure self is not assigned as parent: - if (parentAnchor == this) - { - qDebug() << Q_FUNC_INFO << "can't set self as parent anchor" << reinterpret_cast(parentAnchor); - return false; - } - // make sure no recursive parent-child-relationships are created: - QCPItemAnchor *currentParent = parentAnchor; - while (currentParent) - { - if (QCPItemPosition *currentParentPos = currentParent->toQCPItemPosition()) - { - // is a QCPItemPosition, might have further parent, so keep iterating - if (currentParentPos == this) - { - qDebug() << Q_FUNC_INFO << "can't create recursive parent-child-relationship" << reinterpret_cast(parentAnchor); - return false; - } - currentParent = currentParentPos->parentAnchorY(); + // make sure self is not assigned as parent: + if (parentAnchor == this) + { + qDebug() << Q_FUNC_INFO << "can't set self as parent anchor" << reinterpret_cast(parentAnchor); + return false; + } + // make sure no recursive parent-child-relationships are created: + QCPItemAnchor *currentParent = parentAnchor; + while (currentParent) + { + if (QCPItemPosition *currentParentPos = currentParent->toQCPItemPosition()) + { + // is a QCPItemPosition, might have further parent, so keep iterating + if (currentParentPos == this) + { + qDebug() << Q_FUNC_INFO << "can't create recursive parent-child-relationship" << reinterpret_cast(parentAnchor); + return false; + } + currentParent = currentParentPos->parentAnchorY(); } else { - // is a QCPItemAnchor, can't have further parent. Now make sure the parent items aren't the - // same, to prevent a position being child of an anchor which itself depends on the position, - // because they're both on the same item: - if (currentParent->mParentItem == mParentItem) - { - qDebug() << Q_FUNC_INFO << "can't set parent to be an anchor which itself depends on this position" << reinterpret_cast(parentAnchor); - return false; - } - break; - } - } - - // if previously no parent set and PosType is still ptPlotCoords, set to ptAbsolute: - if (!mParentAnchorY && mPositionTypeY == ptPlotCoords) - setTypeY(ptAbsolute); - - // save pixel position: - QPointF pixelP; - if (keepPixelPosition) - pixelP = pixelPoint(); - // unregister at current parent anchor: - if (mParentAnchorY) - mParentAnchorY->removeChildY(this); - // register at new parent anchor: - if (parentAnchor) - parentAnchor->addChildY(this); - mParentAnchorY = parentAnchor; - // restore pixel position under new parent: - if (keepPixelPosition) - setPixelPoint(pixelP); - else - setCoords(coords().x(), 0); - return true; + // is a QCPItemAnchor, can't have further parent. Now make sure the parent items aren't the + // same, to prevent a position being child of an anchor which itself depends on the position, + // because they're both on the same item: + if (currentParent->mParentItem == mParentItem) + { + qDebug() << Q_FUNC_INFO << "can't set parent to be an anchor which itself depends on this position" << reinterpret_cast(parentAnchor); + return false; + } + break; + } + } + + // if previously no parent set and PosType is still ptPlotCoords, set to ptAbsolute: + if (!mParentAnchorY && mPositionTypeY == ptPlotCoords) + setTypeY(ptAbsolute); + + // save pixel position: + QPointF pixelP; + if (keepPixelPosition) + pixelP = pixelPoint(); + // unregister at current parent anchor: + if (mParentAnchorY) + mParentAnchorY->removeChildY(this); + // register at new parent anchor: + if (parentAnchor) + parentAnchor->addChildY(this); + mParentAnchorY = parentAnchor; + // restore pixel position under new parent: + if (keepPixelPosition) + setPixelPoint(pixelP); + else + setCoords(coords().x(), 0); + return true; } /*! @@ -7927,8 +7927,8 @@ bool QCPItemPosition::setParentAnchorY(Q */ void QCPItemPosition::setCoords(double key, double value) { - mKey = key; - mValue = value; + mKey = key; + mValue = value; } /*! \overload @@ -7938,7 +7938,7 @@ void QCPItemPosition::setCoords(double k */ void QCPItemPosition::setCoords(const QPointF &pos) { - setCoords(pos.x(), pos.y()); + setCoords(pos.x(), pos.y()); } /*! @@ -7949,97 +7949,97 @@ void QCPItemPosition::setCoords(const QP */ QPointF QCPItemPosition::pixelPoint() const { - QPointF result; - - // determine X: - switch (mPositionTypeX) + QPointF result; + + // determine X: + switch (mPositionTypeX) { case ptAbsolute: - { + { result.rx() = mKey; if (mParentAnchorX) - result.rx() += mParentAnchorX->pixelPoint().x(); - break; - } + result.rx() += mParentAnchorX->pixelPoint().x(); + break; + } case ptViewportRatio: - { + { result.rx() = mKey*mParentPlot->viewport().width(); if (mParentAnchorX) - result.rx() += mParentAnchorX->pixelPoint().x(); + result.rx() += mParentAnchorX->pixelPoint().x(); else - result.rx() += mParentPlot->viewport().left(); - break; - } + result.rx() += mParentPlot->viewport().left(); + break; + } case ptAxisRectRatio: - { + { if (mAxisRect) - { + { result.rx() = mKey*mAxisRect.data()->width(); if (mParentAnchorX) - result.rx() += mParentAnchorX->pixelPoint().x(); + result.rx() += mParentAnchorX->pixelPoint().x(); else - result.rx() += mAxisRect.data()->left(); - } else - qDebug() << Q_FUNC_INFO << "Item position type x is ptAxisRectRatio, but no axis rect was defined"; - break; - } + result.rx() += mAxisRect.data()->left(); + } else + qDebug() << Q_FUNC_INFO << "Item position type x is ptAxisRectRatio, but no axis rect was defined"; + break; + } case ptPlotCoords: - { + { if (mKeyAxis && mKeyAxis.data()->orientation() == Qt::Horizontal) - result.rx() = mKeyAxis.data()->coordToPixel(mKey); + result.rx() = mKeyAxis.data()->coordToPixel(mKey); else if (mValueAxis && mValueAxis.data()->orientation() == Qt::Horizontal) - result.rx() = mValueAxis.data()->coordToPixel(mValue); + result.rx() = mValueAxis.data()->coordToPixel(mValue); else - qDebug() << Q_FUNC_INFO << "Item position type x is ptPlotCoords, but no axes were defined"; - break; - } - } - - // determine Y: - switch (mPositionTypeY) + qDebug() << Q_FUNC_INFO << "Item position type x is ptPlotCoords, but no axes were defined"; + break; + } + } + + // determine Y: + switch (mPositionTypeY) { case ptAbsolute: - { + { result.ry() = mValue; if (mParentAnchorY) - result.ry() += mParentAnchorY->pixelPoint().y(); - break; - } + result.ry() += mParentAnchorY->pixelPoint().y(); + break; + } case ptViewportRatio: - { + { result.ry() = mValue*mParentPlot->viewport().height(); if (mParentAnchorY) - result.ry() += mParentAnchorY->pixelPoint().y(); + result.ry() += mParentAnchorY->pixelPoint().y(); else - result.ry() += mParentPlot->viewport().top(); - break; - } + result.ry() += mParentPlot->viewport().top(); + break; + } case ptAxisRectRatio: - { + { if (mAxisRect) - { + { result.ry() = mValue*mAxisRect.data()->height(); if (mParentAnchorY) - result.ry() += mParentAnchorY->pixelPoint().y(); + result.ry() += mParentAnchorY->pixelPoint().y(); else - result.ry() += mAxisRect.data()->top(); - } else - qDebug() << Q_FUNC_INFO << "Item position type y is ptAxisRectRatio, but no axis rect was defined"; - break; - } + result.ry() += mAxisRect.data()->top(); + } else + qDebug() << Q_FUNC_INFO << "Item position type y is ptAxisRectRatio, but no axis rect was defined"; + break; + } case ptPlotCoords: - { + { if (mKeyAxis && mKeyAxis.data()->orientation() == Qt::Vertical) - result.ry() = mKeyAxis.data()->coordToPixel(mKey); + result.ry() = mKeyAxis.data()->coordToPixel(mKey); else if (mValueAxis && mValueAxis.data()->orientation() == Qt::Vertical) - result.ry() = mValueAxis.data()->coordToPixel(mValue); + result.ry() = mValueAxis.data()->coordToPixel(mValue); else - qDebug() << Q_FUNC_INFO << "Item position type y is ptPlotCoords, but no axes were defined"; - break; - } - } - - return result; + qDebug() << Q_FUNC_INFO << "Item position type y is ptPlotCoords, but no axes were defined"; + break; + } + } + + return result; } /*! @@ -8049,8 +8049,8 @@ QPointF QCPItemPosition::pixelPoint() co */ void QCPItemPosition::setAxes(QCPAxis *keyAxis, QCPAxis *valueAxis) { - mKeyAxis = keyAxis; - mValueAxis = valueAxis; + mKeyAxis = keyAxis; + mValueAxis = valueAxis; } /*! @@ -8060,7 +8060,7 @@ void QCPItemPosition::setAxes(QCPAxis *k */ void QCPItemPosition::setAxisRect(QCPAxisRect *axisRect) { - mAxisRect = axisRect; + mAxisRect = axisRect; } /*! @@ -8075,94 +8075,94 @@ void QCPItemPosition::setAxisRect(QCPAxi */ void QCPItemPosition::setPixelPoint(const QPointF &pixelPoint) { - double x = pixelPoint.x(); - double y = pixelPoint.y(); - - switch (mPositionTypeX) + double x = pixelPoint.x(); + double y = pixelPoint.y(); + + switch (mPositionTypeX) { case ptAbsolute: - { + { if (mParentAnchorX) - x -= mParentAnchorX->pixelPoint().x(); - break; - } + x -= mParentAnchorX->pixelPoint().x(); + break; + } case ptViewportRatio: - { + { if (mParentAnchorX) - x -= mParentAnchorX->pixelPoint().x(); + x -= mParentAnchorX->pixelPoint().x(); else - x -= mParentPlot->viewport().left(); + x -= mParentPlot->viewport().left(); x /= (double)mParentPlot->viewport().width(); break; - } + } case ptAxisRectRatio: - { + { if (mAxisRect) - { + { if (mParentAnchorX) - x -= mParentAnchorX->pixelPoint().x(); + x -= mParentAnchorX->pixelPoint().x(); else - x -= mAxisRect.data()->left(); + x -= mAxisRect.data()->left(); x /= (double)mAxisRect.data()->width(); - } else - qDebug() << Q_FUNC_INFO << "Item position type x is ptAxisRectRatio, but no axis rect was defined"; - break; - } + } else + qDebug() << Q_FUNC_INFO << "Item position type x is ptAxisRectRatio, but no axis rect was defined"; + break; + } case ptPlotCoords: - { + { if (mKeyAxis && mKeyAxis.data()->orientation() == Qt::Horizontal) - x = mKeyAxis.data()->pixelToCoord(x); + x = mKeyAxis.data()->pixelToCoord(x); else if (mValueAxis && mValueAxis.data()->orientation() == Qt::Horizontal) - y = mValueAxis.data()->pixelToCoord(x); + y = mValueAxis.data()->pixelToCoord(x); else - qDebug() << Q_FUNC_INFO << "Item position type x is ptPlotCoords, but no axes were defined"; - break; - } - } - - switch (mPositionTypeY) + qDebug() << Q_FUNC_INFO << "Item position type x is ptPlotCoords, but no axes were defined"; + break; + } + } + + switch (mPositionTypeY) { case ptAbsolute: - { + { if (mParentAnchorY) - y -= mParentAnchorY->pixelPoint().y(); - break; - } + y -= mParentAnchorY->pixelPoint().y(); + break; + } case ptViewportRatio: - { + { if (mParentAnchorY) - y -= mParentAnchorY->pixelPoint().y(); + y -= mParentAnchorY->pixelPoint().y(); else - y -= mParentPlot->viewport().top(); + y -= mParentPlot->viewport().top(); y /= (double)mParentPlot->viewport().height(); break; - } + } case ptAxisRectRatio: - { + { if (mAxisRect) - { + { if (mParentAnchorY) - y -= mParentAnchorY->pixelPoint().y(); + y -= mParentAnchorY->pixelPoint().y(); else - y -= mAxisRect.data()->top(); + y -= mAxisRect.data()->top(); y /= (double)mAxisRect.data()->height(); - } else - qDebug() << Q_FUNC_INFO << "Item position type y is ptAxisRectRatio, but no axis rect was defined"; - break; - } + } else + qDebug() << Q_FUNC_INFO << "Item position type y is ptAxisRectRatio, but no axis rect was defined"; + break; + } case ptPlotCoords: - { + { if (mKeyAxis && mKeyAxis.data()->orientation() == Qt::Vertical) - x = mKeyAxis.data()->pixelToCoord(y); + x = mKeyAxis.data()->pixelToCoord(y); else if (mValueAxis && mValueAxis.data()->orientation() == Qt::Vertical) - y = mValueAxis.data()->pixelToCoord(y); + y = mValueAxis.data()->pixelToCoord(y); else - qDebug() << Q_FUNC_INFO << "Item position type y is ptPlotCoords, but no axes were defined"; - break; - } - } - - setCoords(x, y); + qDebug() << Q_FUNC_INFO << "Item position type y is ptPlotCoords, but no axes were defined"; + break; + } + } + + setCoords(x, y); } @@ -8353,29 +8353,29 @@ void QCPItemPosition::setPixelPoint(cons Base class constructor which initializes base class members. */ QCPAbstractItem::QCPAbstractItem(QCustomPlot *parentPlot) : - QCPLayerable(parentPlot), - mClipToAxisRect(false), - mSelectable(true), - mSelected(false) -{ - QList rects = parentPlot->axisRects(); - if (rects.size() > 0) - { - setClipToAxisRect(true); - setClipAxisRect(rects.first()); + QCPLayerable(parentPlot), + mClipToAxisRect(false), + mSelectable(true), + mSelected(false) +{ + QList rects = parentPlot->axisRects(); + if (rects.size() > 0) + { + setClipToAxisRect(true); + setClipAxisRect(rects.first()); } } QCPAbstractItem::~QCPAbstractItem() { - // don't delete mPositions because every position is also an anchor and thus in mAnchors - qDeleteAll(mAnchors); + // don't delete mPositions because every position is also an anchor and thus in mAnchors + qDeleteAll(mAnchors); } /* can't make this a header inline function, because QPointer breaks with forward declared types, see QTBUG-29588 */ QCPAxisRect *QCPAbstractItem::clipAxisRect() const { - return mClipAxisRect.data(); + return mClipAxisRect.data(); } /*! @@ -8386,9 +8386,9 @@ QCPAxisRect *QCPAbstractItem::clipAxisRe */ void QCPAbstractItem::setClipToAxisRect(bool clip) { - mClipToAxisRect = clip; - if (mClipToAxisRect) - setParentLayerable(mClipAxisRect.data()); + mClipToAxisRect = clip; + if (mClipToAxisRect) + setParentLayerable(mClipAxisRect.data()); } /*! @@ -8399,9 +8399,9 @@ void QCPAbstractItem::setClipToAxisRect( */ void QCPAbstractItem::setClipAxisRect(QCPAxisRect *rect) { - mClipAxisRect = rect; - if (mClipToAxisRect) - setParentLayerable(mClipAxisRect.data()); + mClipAxisRect = rect; + if (mClipToAxisRect) + setParentLayerable(mClipAxisRect.data()); } /*! @@ -8415,10 +8415,10 @@ void QCPAbstractItem::setClipAxisRect(QC */ void QCPAbstractItem::setSelectable(bool selectable) { - if (mSelectable != selectable) - { - mSelectable = selectable; - emit selectableChanged(mSelectable); + if (mSelectable != selectable) + { + mSelectable = selectable; + emit selectableChanged(mSelectable); } } @@ -8438,10 +8438,10 @@ void QCPAbstractItem::setSelectable(bool */ void QCPAbstractItem::setSelected(bool selected) { - if (mSelected != selected) - { - mSelected = selected; - emit selectionChanged(mSelected); + if (mSelected != selected) + { + mSelected = selected; + emit selectionChanged(mSelected); } } @@ -8457,13 +8457,13 @@ void QCPAbstractItem::setSelected(bool s */ QCPItemPosition *QCPAbstractItem::position(const QString &name) const { - for (int i=0; iname() == name) - return mPositions.at(i); - } - qDebug() << Q_FUNC_INFO << "position with name not found:" << name; - return 0; + for (int i=0; iname() == name) + return mPositions.at(i); + } + qDebug() << Q_FUNC_INFO << "position with name not found:" << name; + return 0; } /*! @@ -8478,13 +8478,13 @@ QCPItemPosition *QCPAbstractItem::positi */ QCPItemAnchor *QCPAbstractItem::anchor(const QString &name) const { - for (int i=0; iname() == name) - return mAnchors.at(i); - } - qDebug() << Q_FUNC_INFO << "anchor with name not found:" << name; - return 0; + for (int i=0; iname() == name) + return mAnchors.at(i); + } + qDebug() << Q_FUNC_INFO << "anchor with name not found:" << name; + return 0; } /*! @@ -8497,12 +8497,12 @@ QCPItemAnchor *QCPAbstractItem::anchor(c */ bool QCPAbstractItem::hasAnchor(const QString &name) const { - for (int i=0; iname() == name) - return true; - } - return false; + for (int i=0; iname() == name) + return true; + } + return false; } /*! \internal @@ -8516,10 +8516,10 @@ bool QCPAbstractItem::hasAnchor(const QS */ QRect QCPAbstractItem::clipRect() const { - if (mClipToAxisRect && mClipAxisRect) - return mClipAxisRect.data()->rect(); - else - return mParentPlot->viewport(); + if (mClipToAxisRect && mClipAxisRect) + return mClipAxisRect.data()->rect(); + else + return mParentPlot->viewport(); } /*! \internal @@ -8537,7 +8537,7 @@ QRect QCPAbstractItem::clipRect() const */ void QCPAbstractItem::applyDefaultAntialiasingHint(QCPPainter *painter) const { - applyAntialiasingHint(painter, mAntialiased, QCP::aeItems); + applyAntialiasingHint(painter, mAntialiased, QCP::aeItems); } /*! \internal @@ -8554,23 +8554,23 @@ void QCPAbstractItem::applyDefaultAntial */ double QCPAbstractItem::distSqrToLine(const QPointF &start, const QPointF &end, const QPointF &point) const { - QVector2D a(start); - QVector2D b(end); - QVector2D p(point); - QVector2D v(b-a); - - double vLengthSqr = v.lengthSquared(); - if (!qFuzzyIsNull(vLengthSqr)) - { - double mu = QVector2D::dotProduct(p-a, v)/vLengthSqr; - if (mu < 0) + QVector2D a(start); + QVector2D b(end); + QVector2D p(point); + QVector2D v(b-a); + + double vLengthSqr = v.lengthSquared(); + if (!qFuzzyIsNull(vLengthSqr)) + { + double mu = QVector2D::dotProduct(p-a, v)/vLengthSqr; + if (mu < 0) + return (a-p).lengthSquared(); + else if (mu > 1) + return (b-p).lengthSquared(); + else + return ((a + mu*v)-p).lengthSquared(); + } else return (a-p).lengthSquared(); - else if (mu > 1) - return (b-p).lengthSquared(); - else - return ((a + mu*v)-p).lengthSquared(); - } else - return (a-p).lengthSquared(); } /*! \internal @@ -8592,28 +8592,28 @@ double QCPAbstractItem::distSqrToLine(co */ double QCPAbstractItem::rectSelectTest(const QRectF &rect, const QPointF &pos, bool filledRect) const { - double result = -1; - - // distance to border: - QList lines; - lines << QLineF(rect.topLeft(), rect.topRight()) << QLineF(rect.bottomLeft(), rect.bottomRight()) - << QLineF(rect.topLeft(), rect.bottomLeft()) << QLineF(rect.topRight(), rect.bottomRight()); - double minDistSqr = std::numeric_limits::max(); - for (int i=0; i mParentPlot->selectionTolerance()*0.99) - { - if (rect.contains(pos)) - result = mParentPlot->selectionTolerance()*0.99; - } - return result; + double result = -1; + + // distance to border: + QList lines; + lines << QLineF(rect.topLeft(), rect.topRight()) << QLineF(rect.bottomLeft(), rect.bottomRight()) + << QLineF(rect.topLeft(), rect.bottomLeft()) << QLineF(rect.topRight(), rect.bottomRight()); + double minDistSqr = std::numeric_limits::max(); + for (int i=0; i mParentPlot->selectionTolerance()*0.99) + { + if (rect.contains(pos)) + result = mParentPlot->selectionTolerance()*0.99; + } + return result; } /*! \internal @@ -8628,8 +8628,8 @@ double QCPAbstractItem::rectSelectTest(c */ QPointF QCPAbstractItem::anchorPixelPoint(int anchorId) const { - qDebug() << Q_FUNC_INFO << "called on item which shouldn't have any anchors (this method not reimplemented). anchorId" << anchorId; - return QPointF(); + qDebug() << Q_FUNC_INFO << "called on item which shouldn't have any anchors (this method not reimplemented). anchorId" << anchorId; + return QPointF(); } /*! \internal @@ -8648,17 +8648,17 @@ QPointF QCPAbstractItem::anchorPixelPoin */ QCPItemPosition *QCPAbstractItem::createPosition(const QString &name) { - if (hasAnchor(name)) - qDebug() << Q_FUNC_INFO << "anchor/position with name exists already:" << name; - QCPItemPosition *newPosition = new QCPItemPosition(mParentPlot, this, name); - mPositions.append(newPosition); - mAnchors.append(newPosition); // every position is also an anchor - newPosition->setAxes(mParentPlot->xAxis, mParentPlot->yAxis); - newPosition->setType(QCPItemPosition::ptPlotCoords); - if (mParentPlot->axisRect()) - newPosition->setAxisRect(mParentPlot->axisRect()); - newPosition->setCoords(0, 0); - return newPosition; + if (hasAnchor(name)) + qDebug() << Q_FUNC_INFO << "anchor/position with name exists already:" << name; + QCPItemPosition *newPosition = new QCPItemPosition(mParentPlot, this, name); + mPositions.append(newPosition); + mAnchors.append(newPosition); // every position is also an anchor + newPosition->setAxes(mParentPlot->xAxis, mParentPlot->yAxis); + newPosition->setType(QCPItemPosition::ptPlotCoords); + if (mParentPlot->axisRect()) + newPosition->setAxisRect(mParentPlot->axisRect()); + newPosition->setCoords(0, 0); + return newPosition; } /*! \internal @@ -8682,43 +8682,43 @@ QCPItemPosition *QCPAbstractItem::create */ QCPItemAnchor *QCPAbstractItem::createAnchor(const QString &name, int anchorId) { - if (hasAnchor(name)) - qDebug() << Q_FUNC_INFO << "anchor/position with name exists already:" << name; - QCPItemAnchor *newAnchor = new QCPItemAnchor(mParentPlot, this, name, anchorId); - mAnchors.append(newAnchor); - return newAnchor; + if (hasAnchor(name)) + qDebug() << Q_FUNC_INFO << "anchor/position with name exists already:" << name; + QCPItemAnchor *newAnchor = new QCPItemAnchor(mParentPlot, this, name, anchorId); + mAnchors.append(newAnchor); + return newAnchor; } /* inherits documentation from base class */ void QCPAbstractItem::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) { - Q_UNUSED(event) - Q_UNUSED(details) - if (mSelectable) - { - bool selBefore = mSelected; - setSelected(additive ? !mSelected : true); - if (selectionStateChanged) - *selectionStateChanged = mSelected != selBefore; + Q_UNUSED(event) + Q_UNUSED(details) + if (mSelectable) + { + bool selBefore = mSelected; + setSelected(additive ? !mSelected : true); + if (selectionStateChanged) + *selectionStateChanged = mSelected != selBefore; } } /* inherits documentation from base class */ void QCPAbstractItem::deselectEvent(bool *selectionStateChanged) { - if (mSelectable) - { - bool selBefore = mSelected; - setSelected(false); - if (selectionStateChanged) - *selectionStateChanged = mSelected != selBefore; + if (mSelectable) + { + bool selBefore = mSelected; + setSelected(false); + if (selectionStateChanged) + *selectionStateChanged = mSelected != selBefore; } } /* inherits documentation from base class */ QCP::Interaction QCPAbstractItem::selectionCategory() const { - return QCP::iSelectItems; + return QCP::iSelectItems; } @@ -9032,91 +9032,91 @@ QCP::Interaction QCPAbstractItem::select Constructs a QCustomPlot and sets reasonable default values. */ QCustomPlot::QCustomPlot(QWidget *parent) : - QWidget(parent), - xAxis(0), - yAxis(0), - xAxis2(0), - yAxis2(0), - legend(0), - mPlotLayout(0), - mAutoAddPlottableToLegend(true), - mAntialiasedElements(QCP::aeNone), - mNotAntialiasedElements(QCP::aeNone), - mInteractions(0), - mSelectionTolerance(8), - mNoAntialiasingOnDrag(false), - mBackgroundBrush(Qt::white, Qt::SolidPattern), - mBackgroundScaled(true), - mBackgroundScaledMode(Qt::KeepAspectRatioByExpanding), - mCurrentLayer(0), - mPlottingHints(QCP::phCacheLabels|QCP::phForceRepaint), - mMultiSelectModifier(Qt::ControlModifier), - mPaintBuffer(size()), - mMouseEventElement(0), - mReplotting(false) -{ - setAttribute(Qt::WA_NoMousePropagation); - setAttribute(Qt::WA_OpaquePaintEvent); - setMouseTracking(true); - QLocale currentLocale = locale(); - currentLocale.setNumberOptions(QLocale::OmitGroupSeparator); - setLocale(currentLocale); - - // create initial layers: - mLayers.append(new QCPLayer(this, QLatin1String("background"))); - mLayers.append(new QCPLayer(this, QLatin1String("grid"))); - mLayers.append(new QCPLayer(this, QLatin1String("main"))); - mLayers.append(new QCPLayer(this, QLatin1String("axes"))); - mLayers.append(new QCPLayer(this, QLatin1String("legend"))); - updateLayerIndices(); - setCurrentLayer(QLatin1String("main")); - - // create initial layout, axis rect and legend: - mPlotLayout = new QCPLayoutGrid; - mPlotLayout->initializeParentPlot(this); - mPlotLayout->setParent(this); // important because if parent is QWidget, QCPLayout::sizeConstraintsChanged will call QWidget::updateGeometry - mPlotLayout->setLayer(QLatin1String("main")); - QCPAxisRect *defaultAxisRect = new QCPAxisRect(this, true); - mPlotLayout->addElement(0, 0, defaultAxisRect); - xAxis = defaultAxisRect->axis(QCPAxis::atBottom); - yAxis = defaultAxisRect->axis(QCPAxis::atLeft); - xAxis2 = defaultAxisRect->axis(QCPAxis::atTop); - yAxis2 = defaultAxisRect->axis(QCPAxis::atRight); - legend = new QCPLegend; - legend->setVisible(false); - defaultAxisRect->insetLayout()->addElement(legend, Qt::AlignRight|Qt::AlignTop); - defaultAxisRect->insetLayout()->setMargins(QMargins(12, 12, 12, 12)); - - defaultAxisRect->setLayer(QLatin1String("background")); - xAxis->setLayer(QLatin1String("axes")); - yAxis->setLayer(QLatin1String("axes")); - xAxis2->setLayer(QLatin1String("axes")); - yAxis2->setLayer(QLatin1String("axes")); - xAxis->grid()->setLayer(QLatin1String("grid")); - yAxis->grid()->setLayer(QLatin1String("grid")); - xAxis2->grid()->setLayer(QLatin1String("grid")); - yAxis2->grid()->setLayer(QLatin1String("grid")); - legend->setLayer(QLatin1String("legend")); - - setViewport(rect()); // needs to be called after mPlotLayout has been created - - replot(); + QWidget(parent), + xAxis(0), + yAxis(0), + xAxis2(0), + yAxis2(0), + legend(0), + mPlotLayout(0), + mAutoAddPlottableToLegend(true), + mAntialiasedElements(QCP::aeNone), + mNotAntialiasedElements(QCP::aeNone), + mInteractions(0), + mSelectionTolerance(8), + mNoAntialiasingOnDrag(false), + mBackgroundBrush(Qt::white, Qt::SolidPattern), + mBackgroundScaled(true), + mBackgroundScaledMode(Qt::KeepAspectRatioByExpanding), + mCurrentLayer(0), + mPlottingHints(QCP::phCacheLabels|QCP::phForceRepaint), + mMultiSelectModifier(Qt::ControlModifier), + mPaintBuffer(size()), + mMouseEventElement(0), + mReplotting(false) +{ + setAttribute(Qt::WA_NoMousePropagation); + setAttribute(Qt::WA_OpaquePaintEvent); + setMouseTracking(true); + QLocale currentLocale = locale(); + currentLocale.setNumberOptions(QLocale::OmitGroupSeparator); + setLocale(currentLocale); + + // create initial layers: + mLayers.append(new QCPLayer(this, QLatin1String("background"))); + mLayers.append(new QCPLayer(this, QLatin1String("grid"))); + mLayers.append(new QCPLayer(this, QLatin1String("main"))); + mLayers.append(new QCPLayer(this, QLatin1String("axes"))); + mLayers.append(new QCPLayer(this, QLatin1String("legend"))); + updateLayerIndices(); + setCurrentLayer(QLatin1String("main")); + + // create initial layout, axis rect and legend: + mPlotLayout = new QCPLayoutGrid; + mPlotLayout->initializeParentPlot(this); + mPlotLayout->setParent(this); // important because if parent is QWidget, QCPLayout::sizeConstraintsChanged will call QWidget::updateGeometry + mPlotLayout->setLayer(QLatin1String("main")); + QCPAxisRect *defaultAxisRect = new QCPAxisRect(this, true); + mPlotLayout->addElement(0, 0, defaultAxisRect); + xAxis = defaultAxisRect->axis(QCPAxis::atBottom); + yAxis = defaultAxisRect->axis(QCPAxis::atLeft); + xAxis2 = defaultAxisRect->axis(QCPAxis::atTop); + yAxis2 = defaultAxisRect->axis(QCPAxis::atRight); + legend = new QCPLegend; + legend->setVisible(false); + defaultAxisRect->insetLayout()->addElement(legend, Qt::AlignRight|Qt::AlignTop); + defaultAxisRect->insetLayout()->setMargins(QMargins(12, 12, 12, 12)); + + defaultAxisRect->setLayer(QLatin1String("background")); + xAxis->setLayer(QLatin1String("axes")); + yAxis->setLayer(QLatin1String("axes")); + xAxis2->setLayer(QLatin1String("axes")); + yAxis2->setLayer(QLatin1String("axes")); + xAxis->grid()->setLayer(QLatin1String("grid")); + yAxis->grid()->setLayer(QLatin1String("grid")); + xAxis2->grid()->setLayer(QLatin1String("grid")); + yAxis2->grid()->setLayer(QLatin1String("grid")); + legend->setLayer(QLatin1String("legend")); + + setViewport(rect()); // needs to be called after mPlotLayout has been created + + replot(); } QCustomPlot::~QCustomPlot() { - clearPlottables(); - clearItems(); - - if (mPlotLayout) - { - delete mPlotLayout; - mPlotLayout = 0; - } - - mCurrentLayer = 0; - qDeleteAll(mLayers); // don't use removeLayer, because it would prevent the last layer to be removed - mLayers.clear(); + clearPlottables(); + clearItems(); + + if (mPlotLayout) + { + delete mPlotLayout; + mPlotLayout = 0; + } + + mCurrentLayer = 0; + qDeleteAll(mLayers); // don't use removeLayer, because it would prevent the last layer to be removed + mLayers.clear(); } /*! @@ -9138,11 +9138,11 @@ QCustomPlot::~QCustomPlot() */ void QCustomPlot::setAntialiasedElements(const QCP::AntialiasedElements &antialiasedElements) { - mAntialiasedElements = antialiasedElements; - - // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously: - if ((mNotAntialiasedElements & mAntialiasedElements) != 0) - mNotAntialiasedElements |= ~mAntialiasedElements; + mAntialiasedElements = antialiasedElements; + + // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously: + if ((mNotAntialiasedElements & mAntialiasedElements) != 0) + mNotAntialiasedElements |= ~mAntialiasedElements; } /*! @@ -9154,14 +9154,14 @@ void QCustomPlot::setAntialiasedElements */ void QCustomPlot::setAntialiasedElement(QCP::AntialiasedElement antialiasedElement, bool enabled) { - if (!enabled && mAntialiasedElements.testFlag(antialiasedElement)) - mAntialiasedElements &= ~antialiasedElement; - else if (enabled && !mAntialiasedElements.testFlag(antialiasedElement)) - mAntialiasedElements |= antialiasedElement; - - // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously: - if ((mNotAntialiasedElements & mAntialiasedElements) != 0) - mNotAntialiasedElements |= ~mAntialiasedElements; + if (!enabled && mAntialiasedElements.testFlag(antialiasedElement)) + mAntialiasedElements &= ~antialiasedElement; + else if (enabled && !mAntialiasedElements.testFlag(antialiasedElement)) + mAntialiasedElements |= antialiasedElement; + + // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously: + if ((mNotAntialiasedElements & mAntialiasedElements) != 0) + mNotAntialiasedElements |= ~mAntialiasedElements; } /*! @@ -9184,11 +9184,11 @@ void QCustomPlot::setAntialiasedElement( */ void QCustomPlot::setNotAntialiasedElements(const QCP::AntialiasedElements ¬AntialiasedElements) { - mNotAntialiasedElements = notAntialiasedElements; - - // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously: - if ((mNotAntialiasedElements & mAntialiasedElements) != 0) - mAntialiasedElements |= ~mNotAntialiasedElements; + mNotAntialiasedElements = notAntialiasedElements; + + // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously: + if ((mNotAntialiasedElements & mAntialiasedElements) != 0) + mAntialiasedElements |= ~mNotAntialiasedElements; } /*! @@ -9200,14 +9200,14 @@ void QCustomPlot::setNotAntialiasedEleme */ void QCustomPlot::setNotAntialiasedElement(QCP::AntialiasedElement notAntialiasedElement, bool enabled) { - if (!enabled && mNotAntialiasedElements.testFlag(notAntialiasedElement)) - mNotAntialiasedElements &= ~notAntialiasedElement; - else if (enabled && !mNotAntialiasedElements.testFlag(notAntialiasedElement)) - mNotAntialiasedElements |= notAntialiasedElement; - - // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously: - if ((mNotAntialiasedElements & mAntialiasedElements) != 0) - mAntialiasedElements |= ~mNotAntialiasedElements; + if (!enabled && mNotAntialiasedElements.testFlag(notAntialiasedElement)) + mNotAntialiasedElements &= ~notAntialiasedElement; + else if (enabled && !mNotAntialiasedElements.testFlag(notAntialiasedElement)) + mNotAntialiasedElements |= notAntialiasedElement; + + // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously: + if ((mNotAntialiasedElements & mAntialiasedElements) != 0) + mAntialiasedElements |= ~mNotAntialiasedElements; } /*! @@ -9218,7 +9218,7 @@ void QCustomPlot::setNotAntialiasedEleme */ void QCustomPlot::setAutoAddPlottableToLegend(bool on) { - mAutoAddPlottableToLegend = on; + mAutoAddPlottableToLegend = on; } /*! @@ -9277,7 +9277,7 @@ void QCustomPlot::setAutoAddPlottableToL */ void QCustomPlot::setInteractions(const QCP::Interactions &interactions) { - mInteractions = interactions; + mInteractions = interactions; } /*! @@ -9289,10 +9289,10 @@ void QCustomPlot::setInteractions(const */ void QCustomPlot::setInteraction(const QCP::Interaction &interaction, bool enabled) { - if (!enabled && mInteractions.testFlag(interaction)) - mInteractions &= ~interaction; - else if (enabled && !mInteractions.testFlag(interaction)) - mInteractions |= interaction; + if (!enabled && mInteractions.testFlag(interaction)) + mInteractions &= ~interaction; + else if (enabled && !mInteractions.testFlag(interaction)) + mInteractions |= interaction; } /*! @@ -9310,7 +9310,7 @@ void QCustomPlot::setInteraction(const Q */ void QCustomPlot::setSelectionTolerance(int pixels) { - mSelectionTolerance = pixels; + mSelectionTolerance = pixels; } /*! @@ -9324,7 +9324,7 @@ void QCustomPlot::setSelectionTolerance( */ void QCustomPlot::setNoAntialiasingOnDrag(bool enabled) { - mNoAntialiasingOnDrag = enabled; + mNoAntialiasingOnDrag = enabled; } /*! @@ -9334,7 +9334,7 @@ void QCustomPlot::setNoAntialiasingOnDra */ void QCustomPlot::setPlottingHints(const QCP::PlottingHints &hints) { - mPlottingHints = hints; + mPlottingHints = hints; } /*! @@ -9344,14 +9344,14 @@ void QCustomPlot::setPlottingHints(const */ void QCustomPlot::setPlottingHint(QCP::PlottingHint hint, bool enabled) { - QCP::PlottingHints newHints = mPlottingHints; - if (!enabled) - newHints &= ~hint; - else - newHints |= hint; - - if (newHints != mPlottingHints) - setPlottingHints(newHints); + QCP::PlottingHints newHints = mPlottingHints; + if (!enabled) + newHints &= ~hint; + else + newHints |= hint; + + if (newHints != mPlottingHints) + setPlottingHints(newHints); } /*! @@ -9366,9 +9366,8 @@ void QCustomPlot::setPlottingHint(QCP::P */ void QCustomPlot::setMultiSelectModifier(Qt::KeyboardModifier modifier) { - mMultiSelectModifier = modifier; -} - + mMultiSelectModifier = modifier; +} /*! Sets the viewport of this QCustomPlot. The Viewport is the area that the top level layout @@ -9379,9 +9378,9 @@ void QCustomPlot::setMultiSelectModifier */ void QCustomPlot::setViewport(const QRect &rect) { - mViewport = rect; - if (mPlotLayout) - mPlotLayout->setOuterRect(mViewport); + mViewport = rect; + if (mPlotLayout) + mPlotLayout->setOuterRect(mViewport); } /*! @@ -9401,8 +9400,8 @@ void QCustomPlot::setViewport(const QRec */ void QCustomPlot::setBackground(const QPixmap &pm) { - mBackgroundPixmap = pm; - mScaledBackgroundPixmap = QPixmap(); + mBackgroundPixmap = pm; + mScaledBackgroundPixmap = QPixmap(); } /*! @@ -9420,7 +9419,7 @@ void QCustomPlot::setBackground(const QP */ void QCustomPlot::setBackground(const QBrush &brush) { - mBackgroundBrush = brush; + mBackgroundBrush = brush; } /*! \overload @@ -9432,10 +9431,10 @@ void QCustomPlot::setBackground(const QB */ void QCustomPlot::setBackground(const QPixmap &pm, bool scaled, Qt::AspectRatioMode mode) { - mBackgroundPixmap = pm; - mScaledBackgroundPixmap = QPixmap(); - mBackgroundScaled = scaled; - mBackgroundScaledMode = mode; + mBackgroundPixmap = pm; + mScaledBackgroundPixmap = QPixmap(); + mBackgroundScaled = scaled; + mBackgroundScaledMode = mode; } /*! @@ -9450,7 +9449,7 @@ void QCustomPlot::setBackground(const QP */ void QCustomPlot::setBackgroundScaled(bool scaled) { - mBackgroundScaled = scaled; + mBackgroundScaled = scaled; } /*! @@ -9461,7 +9460,7 @@ void QCustomPlot::setBackgroundScaled(bo */ void QCustomPlot::setBackgroundScaledMode(Qt::AspectRatioMode mode) { - mBackgroundScaledMode = mode; + mBackgroundScaledMode = mode; } /*! @@ -9474,13 +9473,13 @@ void QCustomPlot::setBackgroundScaledMod */ QCPAbstractPlottable *QCustomPlot::plottable(int index) { - if (index >= 0 && index < mPlottables.size()) - { - return mPlottables.at(index); - } else - { - qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; - return 0; + if (index >= 0 && index < mPlottables.size()) + { + return mPlottables.at(index); + } else + { + qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; + return 0; } } @@ -9493,11 +9492,11 @@ QCPAbstractPlottable *QCustomPlot::plott */ QCPAbstractPlottable *QCustomPlot::plottable() { - if (!mPlottables.isEmpty()) - { - return mPlottables.last(); - } else - return 0; + if (!mPlottables.isEmpty()) + { + return mPlottables.last(); + } else + return 0; } /*! @@ -9512,27 +9511,27 @@ QCPAbstractPlottable *QCustomPlot::plott */ bool QCustomPlot::addPlottable(QCPAbstractPlottable *plottable) { - if (mPlottables.contains(plottable)) - { - qDebug() << Q_FUNC_INFO << "plottable already added to this QCustomPlot:" << reinterpret_cast(plottable); - return false; - } - if (plottable->parentPlot() != this) - { - qDebug() << Q_FUNC_INFO << "plottable not created with this QCustomPlot as parent:" << reinterpret_cast(plottable); - return false; - } - - mPlottables.append(plottable); - // possibly add plottable to legend: - if (mAutoAddPlottableToLegend) - plottable->addToLegend(); - // special handling for QCPGraphs to maintain the simple graph interface: - if (QCPGraph *graph = qobject_cast(plottable)) - mGraphs.append(graph); - if (!plottable->layer()) // usually the layer is already set in the constructor of the plottable (via QCPLayerable constructor) - plottable->setLayer(currentLayer()); - return true; + if (mPlottables.contains(plottable)) + { + qDebug() << Q_FUNC_INFO << "plottable already added to this QCustomPlot:" << reinterpret_cast(plottable); + return false; + } + if (plottable->parentPlot() != this) + { + qDebug() << Q_FUNC_INFO << "plottable not created with this QCustomPlot as parent:" << reinterpret_cast(plottable); + return false; + } + + mPlottables.append(plottable); + // possibly add plottable to legend: + if (mAutoAddPlottableToLegend) + plottable->addToLegend(); + // special handling for QCPGraphs to maintain the simple graph interface: + if (QCPGraph *graph = qobject_cast(plottable)) + mGraphs.append(graph); + if (!plottable->layer()) // usually the layer is already set in the constructor of the plottable (via QCPLayerable constructor) + plottable->setLayer(currentLayer()); + return true; } /*! @@ -9544,21 +9543,21 @@ bool QCustomPlot::addPlottable(QCPAbstra */ bool QCustomPlot::removePlottable(QCPAbstractPlottable *plottable) { - if (!mPlottables.contains(plottable)) - { - qDebug() << Q_FUNC_INFO << "plottable not in list:" << reinterpret_cast(plottable); - return false; - } - - // remove plottable from legend: - plottable->removeFromLegend(); - // special handling for QCPGraphs to maintain the simple graph interface: - if (QCPGraph *graph = qobject_cast(plottable)) - mGraphs.removeOne(graph); - // remove plottable: - delete plottable; - mPlottables.removeOne(plottable); - return true; + if (!mPlottables.contains(plottable)) + { + qDebug() << Q_FUNC_INFO << "plottable not in list:" << reinterpret_cast(plottable); + return false; + } + + // remove plottable from legend: + plottable->removeFromLegend(); + // special handling for QCPGraphs to maintain the simple graph interface: + if (QCPGraph *graph = qobject_cast(plottable)) + mGraphs.removeOne(graph); + // remove plottable: + delete plottable; + mPlottables.removeOne(plottable); + return true; } /*! \overload @@ -9567,12 +9566,12 @@ bool QCustomPlot::removePlottable(QCPAbs */ bool QCustomPlot::removePlottable(int index) { - if (index >= 0 && index < mPlottables.size()) - return removePlottable(mPlottables[index]); - else - { - qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; - return false; + if (index >= 0 && index < mPlottables.size()) + return removePlottable(mPlottables[index]); + else + { + qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; + return false; } } @@ -9585,10 +9584,10 @@ bool QCustomPlot::removePlottable(int in */ int QCustomPlot::clearPlottables() { - int c = mPlottables.size(); - for (int i=c-1; i >= 0; --i) - removePlottable(mPlottables[i]); - return c; + int c = mPlottables.size(); + for (int i=c-1; i >= 0; --i) + removePlottable(mPlottables[i]); + return c; } /*! @@ -9598,7 +9597,7 @@ int QCustomPlot::clearPlottables() */ int QCustomPlot::plottableCount() const { - return mPlottables.size(); + return mPlottables.size(); } /*! @@ -9610,13 +9609,13 @@ int QCustomPlot::plottableCount() const */ QList QCustomPlot::selectedPlottables() const { - QList result; - foreach (QCPAbstractPlottable *plottable, mPlottables) - { - if (plottable->selected()) - result.append(plottable); - } - return result; + QList result; + foreach (QCPAbstractPlottable *plottable, mPlottables) + { + if (plottable->selected()) + result.append(plottable); + } + return result; } /*! @@ -9633,25 +9632,25 @@ QList QCustomPlot */ QCPAbstractPlottable *QCustomPlot::plottableAt(const QPointF &pos, bool onlySelectable) const { - QCPAbstractPlottable *resultPlottable = 0; - double resultDistance = mSelectionTolerance; // only regard clicks with distances smaller than mSelectionTolerance as selections, so initialize with that value - - foreach (QCPAbstractPlottable *plottable, mPlottables) - { - if (onlySelectable && !plottable->selectable()) // we could have also passed onlySelectable to the selectTest function, but checking here is faster, because we have access to QCPabstractPlottable::selectable - continue; - if ((plottable->keyAxis()->axisRect()->rect() & plottable->valueAxis()->axisRect()->rect()).contains(pos.toPoint())) // only consider clicks inside the rect that is spanned by the plottable's key/value axes - { - double currentDistance = plottable->selectTest(pos, false); - if (currentDistance >= 0 && currentDistance < resultDistance) - { - resultPlottable = plottable; - resultDistance = currentDistance; - } - } - } - - return resultPlottable; + QCPAbstractPlottable *resultPlottable = 0; + double resultDistance = mSelectionTolerance; // only regard clicks with distances smaller than mSelectionTolerance as selections, so initialize with that value + + foreach (QCPAbstractPlottable *plottable, mPlottables) + { + if (onlySelectable && !plottable->selectable()) // we could have also passed onlySelectable to the selectTest function, but checking here is faster, because we have access to QCPabstractPlottable::selectable + continue; + if ((plottable->keyAxis()->axisRect()->rect() & plottable->valueAxis()->axisRect()->rect()).contains(pos.toPoint())) // only consider clicks inside the rect that is spanned by the plottable's key/value axes + { + double currentDistance = plottable->selectTest(pos, false); + if (currentDistance >= 0 && currentDistance < resultDistance) + { + resultPlottable = plottable; + resultDistance = currentDistance; + } + } + } + + return resultPlottable; } /*! @@ -9661,7 +9660,7 @@ QCPAbstractPlottable *QCustomPlot::plott */ bool QCustomPlot::hasPlottable(QCPAbstractPlottable *plottable) const { - return mPlottables.contains(plottable); + return mPlottables.contains(plottable); } /*! @@ -9674,13 +9673,13 @@ bool QCustomPlot::hasPlottable(QCPAbstra */ QCPGraph *QCustomPlot::graph(int index) const { - if (index >= 0 && index < mGraphs.size()) - { - return mGraphs.at(index); - } else - { - qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; - return 0; + if (index >= 0 && index < mGraphs.size()) + { + return mGraphs.at(index); + } else + { + qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; + return 0; } } @@ -9693,11 +9692,11 @@ QCPGraph *QCustomPlot::graph(int index) */ QCPGraph *QCustomPlot::graph() const { - if (!mGraphs.isEmpty()) - { - return mGraphs.last(); - } else - return 0; + if (!mGraphs.isEmpty()) + { + return mGraphs.last(); + } else + return 0; } /*! @@ -9714,28 +9713,28 @@ QCPGraph *QCustomPlot::graph() const */ QCPGraph *QCustomPlot::addGraph(QCPAxis *keyAxis, QCPAxis *valueAxis) { - if (!keyAxis) keyAxis = xAxis; - if (!valueAxis) valueAxis = yAxis; - if (!keyAxis || !valueAxis) - { - qDebug() << Q_FUNC_INFO << "can't use default QCustomPlot xAxis or yAxis, because at least one is invalid (has been deleted)"; - return 0; - } - if (keyAxis->parentPlot() != this || valueAxis->parentPlot() != this) - { - qDebug() << Q_FUNC_INFO << "passed keyAxis or valueAxis doesn't have this QCustomPlot as parent"; - return 0; - } - - QCPGraph *newGraph = new QCPGraph(keyAxis, valueAxis); - if (addPlottable(newGraph)) - { - newGraph->setName(QLatin1String("Graph ")+QString::number(mGraphs.size())); - return newGraph; - } else - { - delete newGraph; - return 0; + if (!keyAxis) keyAxis = xAxis; + if (!valueAxis) valueAxis = yAxis; + if (!keyAxis || !valueAxis) + { + qDebug() << Q_FUNC_INFO << "can't use default QCustomPlot xAxis or yAxis, because at least one is invalid (has been deleted)"; + return 0; + } + if (keyAxis->parentPlot() != this || valueAxis->parentPlot() != this) + { + qDebug() << Q_FUNC_INFO << "passed keyAxis or valueAxis doesn't have this QCustomPlot as parent"; + return 0; + } + + QCPGraph *newGraph = new QCPGraph(keyAxis, valueAxis); + if (addPlottable(newGraph)) + { + newGraph->setName(QLatin1String("Graph ")+QString::number(mGraphs.size())); + return newGraph; + } else + { + delete newGraph; + return 0; } } @@ -9750,7 +9749,7 @@ QCPGraph *QCustomPlot::addGraph(QCPAxis */ bool QCustomPlot::removeGraph(QCPGraph *graph) { - return removePlottable(graph); + return removePlottable(graph); } /*! \overload @@ -9759,10 +9758,10 @@ bool QCustomPlot::removeGraph(QCPGraph * */ bool QCustomPlot::removeGraph(int index) { - if (index >= 0 && index < mGraphs.size()) - return removeGraph(mGraphs[index]); - else - return false; + if (index >= 0 && index < mGraphs.size()) + return removeGraph(mGraphs[index]); + else + return false; } /*! @@ -9774,10 +9773,10 @@ bool QCustomPlot::removeGraph(int index) */ int QCustomPlot::clearGraphs() { - int c = mGraphs.size(); - for (int i=c-1; i >= 0; --i) - removeGraph(mGraphs[i]); - return c; + int c = mGraphs.size(); + for (int i=c-1; i >= 0; --i) + removeGraph(mGraphs[i]); + return c; } /*! @@ -9787,7 +9786,7 @@ int QCustomPlot::clearGraphs() */ int QCustomPlot::graphCount() const { - return mGraphs.size(); + return mGraphs.size(); } /*! @@ -9800,13 +9799,13 @@ int QCustomPlot::graphCount() const */ QList QCustomPlot::selectedGraphs() const { - QList result; - foreach (QCPGraph *graph, mGraphs) - { - if (graph->selected()) - result.append(graph); - } - return result; + QList result; + foreach (QCPGraph *graph, mGraphs) + { + if (graph->selected()) + result.append(graph); + } + return result; } /*! @@ -9819,13 +9818,13 @@ QList QCustomPlot::selectedGr */ QCPAbstractItem *QCustomPlot::item(int index) const { - if (index >= 0 && index < mItems.size()) - { - return mItems.at(index); - } else - { - qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; - return 0; + if (index >= 0 && index < mItems.size()) + { + return mItems.at(index); + } else + { + qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; + return 0; } } @@ -9838,11 +9837,11 @@ QCPAbstractItem *QCustomPlot::item(int i */ QCPAbstractItem *QCustomPlot::item() const { - if (!mItems.isEmpty()) - { - return mItems.last(); - } else - return 0; + if (!mItems.isEmpty()) + { + return mItems.last(); + } else + return 0; } /*! @@ -9855,14 +9854,14 @@ QCPAbstractItem *QCustomPlot::item() con */ bool QCustomPlot::addItem(QCPAbstractItem *item) { - if (!mItems.contains(item) && item->parentPlot() == this) - { - mItems.append(item); - return true; - } else - { - qDebug() << Q_FUNC_INFO << "item either already in list or not created with this QCustomPlot as parent:" << reinterpret_cast(item); - return false; + if (!mItems.contains(item) && item->parentPlot() == this) + { + mItems.append(item); + return true; + } else + { + qDebug() << Q_FUNC_INFO << "item either already in list or not created with this QCustomPlot as parent:" << reinterpret_cast(item); + return false; } } @@ -9875,15 +9874,15 @@ bool QCustomPlot::addItem(QCPAbstractIte */ bool QCustomPlot::removeItem(QCPAbstractItem *item) { - if (mItems.contains(item)) - { - delete item; - mItems.removeOne(item); - return true; - } else - { - qDebug() << Q_FUNC_INFO << "item not in list:" << reinterpret_cast(item); - return false; + if (mItems.contains(item)) + { + delete item; + mItems.removeOne(item); + return true; + } else + { + qDebug() << Q_FUNC_INFO << "item not in list:" << reinterpret_cast(item); + return false; } } @@ -9893,12 +9892,12 @@ bool QCustomPlot::removeItem(QCPAbstract */ bool QCustomPlot::removeItem(int index) { - if (index >= 0 && index < mItems.size()) - return removeItem(mItems[index]); - else - { - qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; - return false; + if (index >= 0 && index < mItems.size()) + return removeItem(mItems[index]); + else + { + qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; + return false; } } @@ -9911,10 +9910,10 @@ bool QCustomPlot::removeItem(int index) */ int QCustomPlot::clearItems() { - int c = mItems.size(); - for (int i=c-1; i >= 0; --i) - removeItem(mItems[i]); - return c; + int c = mItems.size(); + for (int i=c-1; i >= 0; --i) + removeItem(mItems[i]); + return c; } /*! @@ -9924,7 +9923,7 @@ int QCustomPlot::clearItems() */ int QCustomPlot::itemCount() const { - return mItems.size(); + return mItems.size(); } /*! @@ -9934,13 +9933,13 @@ int QCustomPlot::itemCount() const */ QList QCustomPlot::selectedItems() const { - QList result; - foreach (QCPAbstractItem *item, mItems) - { - if (item->selected()) - result.append(item); - } - return result; + QList result; + foreach (QCPAbstractItem *item, mItems) + { + if (item->selected()) + result.append(item); + } + return result; } /*! @@ -9958,25 +9957,25 @@ QList QCustomPlot::sel */ QCPAbstractItem *QCustomPlot::itemAt(const QPointF &pos, bool onlySelectable) const { - QCPAbstractItem *resultItem = 0; - double resultDistance = mSelectionTolerance; // only regard clicks with distances smaller than mSelectionTolerance as selections, so initialize with that value - - foreach (QCPAbstractItem *item, mItems) - { - if (onlySelectable && !item->selectable()) // we could have also passed onlySelectable to the selectTest function, but checking here is faster, because we have access to QCPAbstractItem::selectable - continue; - if (!item->clipToAxisRect() || item->clipRect().contains(pos.toPoint())) // only consider clicks inside axis cliprect of the item if actually clipped to it - { - double currentDistance = item->selectTest(pos, false); - if (currentDistance >= 0 && currentDistance < resultDistance) - { - resultItem = item; - resultDistance = currentDistance; - } - } - } - - return resultItem; + QCPAbstractItem *resultItem = 0; + double resultDistance = mSelectionTolerance; // only regard clicks with distances smaller than mSelectionTolerance as selections, so initialize with that value + + foreach (QCPAbstractItem *item, mItems) + { + if (onlySelectable && !item->selectable()) // we could have also passed onlySelectable to the selectTest function, but checking here is faster, because we have access to QCPAbstractItem::selectable + continue; + if (!item->clipToAxisRect() || item->clipRect().contains(pos.toPoint())) // only consider clicks inside axis cliprect of the item if actually clipped to it + { + double currentDistance = item->selectTest(pos, false); + if (currentDistance >= 0 && currentDistance < resultDistance) + { + resultItem = item; + resultDistance = currentDistance; + } + } + } + + return resultItem; } /*! @@ -9986,7 +9985,7 @@ QCPAbstractItem *QCustomPlot::itemAt(con */ bool QCustomPlot::hasItem(QCPAbstractItem *item) const { - return mItems.contains(item); + return mItems.contains(item); } /*! @@ -9999,12 +9998,12 @@ bool QCustomPlot::hasItem(QCPAbstractIte */ QCPLayer *QCustomPlot::layer(const QString &name) const { - foreach (QCPLayer *layer, mLayers) - { - if (layer->name() == name) - return layer; - } - return 0; + foreach (QCPLayer *layer, mLayers) + { + if (layer->name() == name) + return layer; + } + return 0; } /*! \overload @@ -10015,13 +10014,13 @@ QCPLayer *QCustomPlot::layer(const QStri */ QCPLayer *QCustomPlot::layer(int index) const { - if (index >= 0 && index < mLayers.size()) - { - return mLayers.at(index); - } else - { - qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; - return 0; + if (index >= 0 && index < mLayers.size()) + { + return mLayers.at(index); + } else + { + qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; + return 0; } } @@ -10030,7 +10029,7 @@ QCPLayer *QCustomPlot::layer(int index) */ QCPLayer *QCustomPlot::currentLayer() const { - return mCurrentLayer; + return mCurrentLayer; } /*! @@ -10045,13 +10044,13 @@ QCPLayer *QCustomPlot::currentLayer() co */ bool QCustomPlot::setCurrentLayer(const QString &name) { - if (QCPLayer *newCurrentLayer = layer(name)) - { - return setCurrentLayer(newCurrentLayer); - } else - { - qDebug() << Q_FUNC_INFO << "layer with name doesn't exist:" << name; - return false; + if (QCPLayer *newCurrentLayer = layer(name)) + { + return setCurrentLayer(newCurrentLayer); + } else + { + qDebug() << Q_FUNC_INFO << "layer with name doesn't exist:" << name; + return false; } } @@ -10065,14 +10064,14 @@ bool QCustomPlot::setCurrentLayer(const */ bool QCustomPlot::setCurrentLayer(QCPLayer *layer) { - if (!mLayers.contains(layer)) - { - qDebug() << Q_FUNC_INFO << "layer not a layer of this QCustomPlot:" << reinterpret_cast(layer); - return false; - } - - mCurrentLayer = layer; - return true; + if (!mLayers.contains(layer)) + { + qDebug() << Q_FUNC_INFO << "layer not a layer of this QCustomPlot:" << reinterpret_cast(layer); + return false; + } + + mCurrentLayer = layer; + return true; } /*! @@ -10082,7 +10081,7 @@ bool QCustomPlot::setCurrentLayer(QCPLay */ int QCustomPlot::layerCount() const { - return mLayers.size(); + return mLayers.size(); } /*! @@ -10100,23 +10099,23 @@ int QCustomPlot::layerCount() const */ bool QCustomPlot::addLayer(const QString &name, QCPLayer *otherLayer, QCustomPlot::LayerInsertMode insertMode) { - if (!otherLayer) - otherLayer = mLayers.last(); - if (!mLayers.contains(otherLayer)) - { - qDebug() << Q_FUNC_INFO << "otherLayer not a layer of this QCustomPlot:" << reinterpret_cast(otherLayer); - return false; - } - if (layer(name)) - { - qDebug() << Q_FUNC_INFO << "A layer exists already with the name" << name; - return false; - } - - QCPLayer *newLayer = new QCPLayer(this, name); - mLayers.insert(otherLayer->index() + (insertMode==limAbove ? 1:0), newLayer); - updateLayerIndices(); - return true; + if (!otherLayer) + otherLayer = mLayers.last(); + if (!mLayers.contains(otherLayer)) + { + qDebug() << Q_FUNC_INFO << "otherLayer not a layer of this QCustomPlot:" << reinterpret_cast(otherLayer); + return false; + } + if (layer(name)) + { + qDebug() << Q_FUNC_INFO << "A layer exists already with the name" << name; + return false; + } + + QCPLayer *newLayer = new QCPLayer(this, name); + mLayers.insert(otherLayer->index() + (insertMode==limAbove ? 1:0), newLayer); + updateLayerIndices(); + return true; } /*! @@ -10135,39 +10134,39 @@ bool QCustomPlot::addLayer(const QString */ bool QCustomPlot::removeLayer(QCPLayer *layer) { - if (!mLayers.contains(layer)) - { - qDebug() << Q_FUNC_INFO << "layer not a layer of this QCustomPlot:" << reinterpret_cast(layer); - return false; - } - if (mLayers.size() < 2) - { - qDebug() << Q_FUNC_INFO << "can't remove last layer"; - return false; - } - - // append all children of this layer to layer below (if this is lowest layer, prepend to layer above) - int removedIndex = layer->index(); - bool isFirstLayer = removedIndex==0; - QCPLayer *targetLayer = isFirstLayer ? mLayers.at(removedIndex+1) : mLayers.at(removedIndex-1); - QList children = layer->children(); - if (isFirstLayer) // prepend in reverse order (so order relative to each other stays the same) - { - for (int i=children.size()-1; i>=0; --i) - children.at(i)->moveToLayer(targetLayer, true); + if (!mLayers.contains(layer)) + { + qDebug() << Q_FUNC_INFO << "layer not a layer of this QCustomPlot:" << reinterpret_cast(layer); + return false; + } + if (mLayers.size() < 2) + { + qDebug() << Q_FUNC_INFO << "can't remove last layer"; + return false; + } + + // append all children of this layer to layer below (if this is lowest layer, prepend to layer above) + int removedIndex = layer->index(); + bool isFirstLayer = removedIndex==0; + QCPLayer *targetLayer = isFirstLayer ? mLayers.at(removedIndex+1) : mLayers.at(removedIndex-1); + QList children = layer->children(); + if (isFirstLayer) // prepend in reverse order (so order relative to each other stays the same) + { + for (int i=children.size()-1; i>=0; --i) + children.at(i)->moveToLayer(targetLayer, true); } else // append normally { - for (int i=0; imoveToLayer(targetLayer, false); - } - // if removed layer is current layer, change current layer to layer below/above: - if (layer == mCurrentLayer) - setCurrentLayer(targetLayer); - // remove layer: - delete layer; - mLayers.removeOne(layer); - updateLayerIndices(); - return true; + for (int i=0; imoveToLayer(targetLayer, false); + } + // if removed layer is current layer, change current layer to layer below/above: + if (layer == mCurrentLayer) + setCurrentLayer(targetLayer); + // remove layer: + delete layer; + mLayers.removeOne(layer); + updateLayerIndices(); + return true; } /*! @@ -10181,20 +10180,20 @@ bool QCustomPlot::removeLayer(QCPLayer * */ bool QCustomPlot::moveLayer(QCPLayer *layer, QCPLayer *otherLayer, QCustomPlot::LayerInsertMode insertMode) { - if (!mLayers.contains(layer)) - { - qDebug() << Q_FUNC_INFO << "layer not a layer of this QCustomPlot:" << reinterpret_cast(layer); - return false; - } - if (!mLayers.contains(otherLayer)) - { - qDebug() << Q_FUNC_INFO << "otherLayer not a layer of this QCustomPlot:" << reinterpret_cast(otherLayer); - return false; - } - - mLayers.move(layer->index(), otherLayer->index() + (insertMode==limAbove ? 1:0)); - updateLayerIndices(); - return true; + if (!mLayers.contains(layer)) + { + qDebug() << Q_FUNC_INFO << "layer not a layer of this QCustomPlot:" << reinterpret_cast(layer); + return false; + } + if (!mLayers.contains(otherLayer)) + { + qDebug() << Q_FUNC_INFO << "otherLayer not a layer of this QCustomPlot:" << reinterpret_cast(otherLayer); + return false; + } + + mLayers.move(layer->index(), otherLayer->index() + (insertMode==limAbove ? 1:0)); + updateLayerIndices(); + return true; } /*! @@ -10208,7 +10207,7 @@ bool QCustomPlot::moveLayer(QCPLayer *la */ int QCustomPlot::axisRectCount() const { - return axisRects().size(); + return axisRects().size(); } /*! @@ -10222,14 +10221,14 @@ int QCustomPlot::axisRectCount() const */ QCPAxisRect *QCustomPlot::axisRect(int index) const { - const QList rectList = axisRects(); - if (index >= 0 && index < rectList.size()) - { - return rectList.at(index); - } else - { - qDebug() << Q_FUNC_INFO << "invalid axis rect index" << index; - return 0; + const QList rectList = axisRects(); + if (index >= 0 && index < rectList.size()) + { + return rectList.at(index); + } else + { + qDebug() << Q_FUNC_INFO << "invalid axis rect index" << index; + return 0; } } @@ -10240,25 +10239,25 @@ QCPAxisRect *QCustomPlot::axisRect(int i */ QList QCustomPlot::axisRects() const { - QList result; - QStack elementStack; - if (mPlotLayout) - elementStack.push(mPlotLayout); - - while (!elementStack.isEmpty()) - { - foreach (QCPLayoutElement *element, elementStack.pop()->elements(false)) - { - if (element) - { - elementStack.push(element); - if (QCPAxisRect *ar = qobject_cast(element)) - result.append(ar); - } - } - } - - return result; + QList result; + QStack elementStack; + if (mPlotLayout) + elementStack.push(mPlotLayout); + + while (!elementStack.isEmpty()) + { + foreach (QCPLayoutElement *element, elementStack.pop()->elements(false)) + { + if (element) + { + elementStack.push(element); + if (QCPAxisRect *ar = qobject_cast(element)) + result.append(ar); + } + } + } + + return result; } /*! @@ -10272,22 +10271,22 @@ QList QCustomPlot::axisRec */ QCPLayoutElement *QCustomPlot::layoutElementAt(const QPointF &pos) const { - QCPLayoutElement *currentElement = mPlotLayout; - bool searchSubElements = true; - while (searchSubElements && currentElement) - { - searchSubElements = false; - foreach (QCPLayoutElement *subElement, currentElement->elements(false)) - { - if (subElement && subElement->realVisibility() && subElement->selectTest(pos, false) >= 0) - { - currentElement = subElement; - searchSubElements = true; - break; - } - } - } - return currentElement; + QCPLayoutElement *currentElement = mPlotLayout; + bool searchSubElements = true; + while (searchSubElements && currentElement) + { + searchSubElements = false; + foreach (QCPLayoutElement *subElement, currentElement->elements(false)) + { + if (subElement && subElement->realVisibility() && subElement->selectTest(pos, false) >= 0) + { + currentElement = subElement; + searchSubElements = true; + break; + } + } + } + return currentElement; } /*! @@ -10299,17 +10298,17 @@ QCPLayoutElement *QCustomPlot::layoutEle */ QList QCustomPlot::selectedAxes() const { - QList result, allAxes; - foreach (QCPAxisRect *rect, axisRects()) - allAxes << rect->axes(); - - foreach (QCPAxis *axis, allAxes) - { - if (axis->selectedParts() != QCPAxis::spNone) - result.append(axis); - } - - return result; + QList result, allAxes; + foreach (QCPAxisRect *rect, axisRects()) + allAxes << rect->axes(); + + foreach (QCPAxis *axis, allAxes) + { + if (axis->selectedParts() != QCPAxis::spNone) + result.append(axis); + } + + return result; } /*! @@ -10321,29 +10320,29 @@ QList QCustomPlot::selectedAxe */ QList QCustomPlot::selectedLegends() const { - QList result; - - QStack elementStack; - if (mPlotLayout) - elementStack.push(mPlotLayout); - - while (!elementStack.isEmpty()) - { - foreach (QCPLayoutElement *subElement, elementStack.pop()->elements(false)) - { - if (subElement) - { - elementStack.push(subElement); - if (QCPLegend *leg = qobject_cast(subElement)) + QList result; + + QStack elementStack; + if (mPlotLayout) + elementStack.push(mPlotLayout); + + while (!elementStack.isEmpty()) + { + foreach (QCPLayoutElement *subElement, elementStack.pop()->elements(false)) + { + if (subElement) + { + elementStack.push(subElement); + if (QCPLegend *leg = qobject_cast(subElement)) { - if (leg->selectedParts() != QCPLegend::spNone) - result.append(leg); + if (leg->selectedParts() != QCPLegend::spNone) + result.append(leg); } } } } - - return result; + + return result; } /*! @@ -10357,10 +10356,10 @@ QList QCustomPlot::selectedL */ void QCustomPlot::deselectAll() { - foreach (QCPLayer *layer, mLayers) - { - foreach (QCPLayerable *layerable, layer->children()) - layerable->deselectEvent(0); + foreach (QCPLayer *layer, mLayers) + { + foreach (QCPLayerable *layerable, layer->children()) + layerable->deselectEvent(0); } } @@ -10379,30 +10378,30 @@ void QCustomPlot::deselectAll() */ void QCustomPlot::replot(QCustomPlot::RefreshPriority refreshPriority) { - if (mReplotting) // incase signals loop back to replot slot - return; - mReplotting = true; - emit beforeReplot(); - - mPaintBuffer.fill(mBackgroundBrush.style() == Qt::SolidPattern ? mBackgroundBrush.color() : Qt::transparent); - QCPPainter painter; - painter.begin(&mPaintBuffer); - if (painter.isActive()) - { - painter.setRenderHint(QPainter::HighQualityAntialiasing); // to make Antialiasing look good if using the OpenGL graphicssystem - if (mBackgroundBrush.style() != Qt::SolidPattern && mBackgroundBrush.style() != Qt::NoBrush) - painter.fillRect(mViewport, mBackgroundBrush); - draw(&painter); - painter.end(); - if ((refreshPriority == rpHint && mPlottingHints.testFlag(QCP::phForceRepaint)) || refreshPriority==rpImmediate) - repaint(); - else - update(); + if (mReplotting) // incase signals loop back to replot slot + return; + mReplotting = true; + emit beforeReplot(); + + mPaintBuffer.fill(mBackgroundBrush.style() == Qt::SolidPattern ? mBackgroundBrush.color() : Qt::transparent); + QCPPainter painter; + painter.begin(&mPaintBuffer); + if (painter.isActive()) + { + painter.setRenderHint(QPainter::HighQualityAntialiasing); // to make Antialiasing look good if using the OpenGL graphicssystem + if (mBackgroundBrush.style() != Qt::SolidPattern && mBackgroundBrush.style() != Qt::NoBrush) + painter.fillRect(mViewport, mBackgroundBrush); + draw(&painter); + painter.end(); + if ((refreshPriority == rpHint && mPlottingHints.testFlag(QCP::phForceRepaint)) || refreshPriority==rpImmediate) + repaint(); + else + update(); } else // might happen if QCustomPlot has width or height zero - qDebug() << Q_FUNC_INFO << "Couldn't activate painter on buffer. This usually happens because QCustomPlot has width or height zero."; - - emit afterReplot(); - mReplotting = false; + qDebug() << Q_FUNC_INFO << "Couldn't activate painter on buffer. This usually happens because QCustomPlot has width or height zero."; + + emit afterReplot(); + mReplotting = false; } /*! @@ -10415,12 +10414,12 @@ void QCustomPlot::replot(QCustomPlot::Re */ void QCustomPlot::rescaleAxes(bool onlyVisiblePlottables) { - QList allAxes; - foreach (QCPAxisRect *rect, axisRects()) - allAxes << rect->axes(); - - foreach (QCPAxis *axis, allAxes) - axis->rescale(onlyVisiblePlottables); + QList allAxes; + foreach (QCPAxisRect *rect, axisRects()) + allAxes << rect->axes(); + + foreach (QCPAxis *axis, allAxes) + axis->rescale(onlyVisiblePlottables); } /*! @@ -10462,63 +10461,63 @@ void QCustomPlot::rescaleAxes(bool onlyV */ bool QCustomPlot::savePdf(const QString &fileName, bool noCosmeticPen, int width, int height, const QString &pdfCreator, const QString &pdfTitle) { - bool success = false; + bool success = false; #ifdef QT_NO_PRINTER - Q_UNUSED(fileName) - Q_UNUSED(noCosmeticPen) - Q_UNUSED(width) - Q_UNUSED(height) - qDebug() << Q_FUNC_INFO << "Qt was built without printer support (QT_NO_PRINTER). PDF not created."; + Q_UNUSED(fileName) + Q_UNUSED(noCosmeticPen) + Q_UNUSED(width) + Q_UNUSED(height) + qDebug() << Q_FUNC_INFO << "Qt was built without printer support (QT_NO_PRINTER). PDF not created."; #else - int newWidth, newHeight; - if (width == 0 || height == 0) - { - newWidth = this->width(); - newHeight = this->height(); - } else - { - newWidth = width; - newHeight = height; - } - - QPrinter printer(QPrinter::ScreenResolution); - printer.setOutputFileName(fileName); - printer.setOutputFormat(QPrinter::PdfFormat); - printer.setColorMode(QPrinter::Color); - printer.printEngine()->setProperty(QPrintEngine::PPK_Creator, pdfCreator); - printer.printEngine()->setProperty(QPrintEngine::PPK_DocumentName, pdfTitle); - QRect oldViewport = viewport(); - setViewport(QRect(0, 0, newWidth, newHeight)); + int newWidth, newHeight; + if (width == 0 || height == 0) + { + newWidth = this->width(); + newHeight = this->height(); + } else + { + newWidth = width; + newHeight = height; + } + + QPrinter printer(QPrinter::ScreenResolution); + printer.setOutputFileName(fileName); + printer.setOutputFormat(QPrinter::PdfFormat); + printer.setColorMode(QPrinter::Color); + printer.printEngine()->setProperty(QPrintEngine::PPK_Creator, pdfCreator); + printer.printEngine()->setProperty(QPrintEngine::PPK_DocumentName, pdfTitle); + QRect oldViewport = viewport(); + setViewport(QRect(0, 0, newWidth, newHeight)); #if QT_VERSION < QT_VERSION_CHECK(5, 3, 0) - printer.setFullPage(true); - printer.setPaperSize(viewport().size(), QPrinter::DevicePixel); + printer.setFullPage(true); + printer.setPaperSize(viewport().size(), QPrinter::DevicePixel); #else - QPageLayout pageLayout; - pageLayout.setMode(QPageLayout::FullPageMode); - pageLayout.setOrientation(QPageLayout::Portrait); - pageLayout.setMargins(QMarginsF(0, 0, 0, 0)); - pageLayout.setPageSize(QPageSize(viewport().size(), QPageSize::Point, QString(), QPageSize::ExactMatch)); - printer.setPageLayout(pageLayout); + QPageLayout pageLayout; + pageLayout.setMode(QPageLayout::FullPageMode); + pageLayout.setOrientation(QPageLayout::Portrait); + pageLayout.setMargins(QMarginsF(0, 0, 0, 0)); + pageLayout.setPageSize(QPageSize(viewport().size(), QPageSize::Point, QString(), QPageSize::ExactMatch)); + printer.setPageLayout(pageLayout); #endif - QCPPainter printpainter; - if (printpainter.begin(&printer)) - { - printpainter.setMode(QCPPainter::pmVectorized); - printpainter.setMode(QCPPainter::pmNoCaching); - printpainter.setMode(QCPPainter::pmNonCosmetic, noCosmeticPen); - printpainter.setWindow(mViewport); - if (mBackgroundBrush.style() != Qt::NoBrush && - mBackgroundBrush.color() != Qt::white && - mBackgroundBrush.color() != Qt::transparent && - mBackgroundBrush.color().alpha() > 0) // draw pdf background color if not white/transparent - printpainter.fillRect(viewport(), mBackgroundBrush); - draw(&printpainter); - printpainter.end(); - success = true; - } - setViewport(oldViewport); + QCPPainter printpainter; + if (printpainter.begin(&printer)) + { + printpainter.setMode(QCPPainter::pmVectorized); + printpainter.setMode(QCPPainter::pmNoCaching); + printpainter.setMode(QCPPainter::pmNonCosmetic, noCosmeticPen); + printpainter.setWindow(mViewport); + if (mBackgroundBrush.style() != Qt::NoBrush && + mBackgroundBrush.color() != Qt::white && + mBackgroundBrush.color() != Qt::transparent && + mBackgroundBrush.color().alpha() > 0) // draw pdf background color if not white/transparent + printpainter.fillRect(viewport(), mBackgroundBrush); + draw(&printpainter); + printpainter.end(); + success = true; + } + setViewport(oldViewport); #endif // QT_NO_PRINTER - return success; + return success; } /*! @@ -10560,7 +10559,7 @@ bool QCustomPlot::savePdf(const QString */ bool QCustomPlot::savePng(const QString &fileName, int width, int height, double scale, int quality) { - return saveRastered(fileName, width, height, scale, "PNG", quality); + return saveRastered(fileName, width, height, scale, "PNG", quality); } /*! @@ -10599,7 +10598,7 @@ bool QCustomPlot::savePng(const QString */ bool QCustomPlot::saveJpg(const QString &fileName, int width, int height, double scale, int quality) { - return saveRastered(fileName, width, height, scale, "JPG", quality); + return saveRastered(fileName, width, height, scale, "JPG", quality); } /*! @@ -10635,7 +10634,7 @@ bool QCustomPlot::saveJpg(const QString */ bool QCustomPlot::saveBmp(const QString &fileName, int width, int height, double scale) { - return saveRastered(fileName, width, height, scale, "BMP"); + return saveRastered(fileName, width, height, scale, "BMP"); } /*! \internal @@ -10648,7 +10647,7 @@ bool QCustomPlot::saveBmp(const QString */ QSize QCustomPlot::minimumSizeHint() const { - return mPlotLayout->minimumSizeHint(); + return mPlotLayout->minimumSizeHint(); } /*! \internal @@ -10658,7 +10657,7 @@ QSize QCustomPlot::minimumSizeHint() con */ QSize QCustomPlot::sizeHint() const { - return mPlotLayout->minimumSizeHint(); + return mPlotLayout->minimumSizeHint(); } /*! \internal @@ -10668,9 +10667,9 @@ QSize QCustomPlot::sizeHint() const */ void QCustomPlot::paintEvent(QPaintEvent *event) { - Q_UNUSED(event); - QPainter painter(this); - painter.drawPixmap(0, 0, mPaintBuffer); + Q_UNUSED(event); + QPainter painter(this); + painter.drawPixmap(0, 0, mPaintBuffer); } /*! \internal @@ -10681,17 +10680,10 @@ void QCustomPlot::paintEvent(QPaintEvent */ void QCustomPlot::resizeEvent(QResizeEvent *event) { - // resize and repaint the buffer: - mPaintBuffer = QPixmap(event->size()); - setViewport(rect()); - replot(rpQueued); // queued update is important here, to prevent painting issues in some contexts -// resize and repaint the buffer: -// QSize pbSize = event->size(); -// pbSize *= devicePixelRatio(); -// mPaintBuffer = QPixmap(pbSize); -// mPaintBuffer.setDevicePixelRatio(devicePixelRatio()); -// setViewport(rect()); -// replot(rpQueued); // queued update is important here, to prevent painting issues in some contexts + // resize and repaint the buffer: + mPaintBuffer = QPixmap(event->size()); + setViewport(rect()); + replot(rpQueued); // queued update is important here, to prevent painting issues in some contexts } /*! \internal @@ -10705,37 +10697,37 @@ void QCustomPlot::resizeEvent(QResizeEve */ void QCustomPlot::mouseDoubleClickEvent(QMouseEvent *event) { - emit mouseDoubleClick(event); - - QVariant details; - QCPLayerable *clickedLayerable = layerableAt(event->pos(), false, &details); - - // emit specialized object double click signals: - if (QCPAbstractPlottable *ap = qobject_cast(clickedLayerable)) - emit plottableDoubleClick(ap, event); - else if (QCPAxis *ax = qobject_cast(clickedLayerable)) - emit axisDoubleClick(ax, details.value(), event); - else if (QCPAbstractItem *ai = qobject_cast(clickedLayerable)) - emit itemDoubleClick(ai, event); - else if (QCPLegend *lg = qobject_cast(clickedLayerable)) - emit legendDoubleClick(lg, 0, event); - else if (QCPAbstractLegendItem *li = qobject_cast(clickedLayerable)) - emit legendDoubleClick(li->parentLegend(), li, event); - else if (QCPPlotTitle *pt = qobject_cast(clickedLayerable)) - emit titleDoubleClick(event, pt); - - // call double click event of affected layout element: - if (QCPLayoutElement *el = layoutElementAt(event->pos())) - el->mouseDoubleClickEvent(event); - - // call release event of affected layout element (as in mouseReleaseEvent, since the mouseDoubleClick replaces the second release event in double click case): - if (mMouseEventElement) - { - mMouseEventElement->mouseReleaseEvent(event); - mMouseEventElement = 0; - } - - //QWidget::mouseDoubleClickEvent(event); don't call base class implementation because it would just cause a mousePress/ReleaseEvent, which we don't want. + emit mouseDoubleClick(event); + + QVariant details; + QCPLayerable *clickedLayerable = layerableAt(event->pos(), false, &details); + + // emit specialized object double click signals: + if (QCPAbstractPlottable *ap = qobject_cast(clickedLayerable)) + emit plottableDoubleClick(ap, event); + else if (QCPAxis *ax = qobject_cast(clickedLayerable)) + emit axisDoubleClick(ax, details.value(), event); + else if (QCPAbstractItem *ai = qobject_cast(clickedLayerable)) + emit itemDoubleClick(ai, event); + else if (QCPLegend *lg = qobject_cast(clickedLayerable)) + emit legendDoubleClick(lg, 0, event); + else if (QCPAbstractLegendItem *li = qobject_cast(clickedLayerable)) + emit legendDoubleClick(li->parentLegend(), li, event); + else if (QCPPlotTitle *pt = qobject_cast(clickedLayerable)) + emit titleDoubleClick(event, pt); + + // call double click event of affected layout element: + if (QCPLayoutElement *el = layoutElementAt(event->pos())) + el->mouseDoubleClickEvent(event); + + // call release event of affected layout element (as in mouseReleaseEvent, since the mouseDoubleClick replaces the second release event in double click case): + if (mMouseEventElement) + { + mMouseEventElement->mouseReleaseEvent(event); + mMouseEventElement = 0; + } + + //QWidget::mouseDoubleClickEvent(event); don't call base class implementation because it would just cause a mousePress/ReleaseEvent, which we don't want. } /*! \internal @@ -10747,15 +10739,15 @@ void QCustomPlot::mouseDoubleClickEvent( */ void QCustomPlot::mousePressEvent(QMouseEvent *event) { - emit mousePress(event); - mMousePressPos = event->pos(); // need this to determine in releaseEvent whether it was a click (no position change between press and release) - - // call event of affected layout element: - mMouseEventElement = layoutElementAt(event->pos()); - if (mMouseEventElement) - mMouseEventElement->mousePressEvent(event); - - QWidget::mousePressEvent(event); + emit mousePress(event); + mMousePressPos = event->pos(); // need this to determine in releaseEvent whether it was a click (no position change between press and release) + + // call event of affected layout element: + mMouseEventElement = layoutElementAt(event->pos()); + if (mMouseEventElement) + mMouseEventElement->mousePressEvent(event); + + QWidget::mousePressEvent(event); } /*! \internal @@ -10769,13 +10761,13 @@ void QCustomPlot::mousePressEvent(QMouse */ void QCustomPlot::mouseMoveEvent(QMouseEvent *event) { - emit mouseMove(event); - - // call event of affected layout element: - if (mMouseEventElement) - mMouseEventElement->mouseMoveEvent(event); - - QWidget::mouseMoveEvent(event); + emit mouseMove(event); + + // call event of affected layout element: + if (mMouseEventElement) + mMouseEventElement->mouseMoveEvent(event); + + QWidget::mouseMoveEvent(event); } /*! \internal @@ -10794,74 +10786,74 @@ void QCustomPlot::mouseMoveEvent(QMouseE */ void QCustomPlot::mouseReleaseEvent(QMouseEvent *event) { - emit mouseRelease(event); - bool doReplot = false; - - if ((mMousePressPos-event->pos()).manhattanLength() < 5) // determine whether it was a click operation - { - if (event->button() == Qt::LeftButton) - { - // handle selection mechanism: - QVariant details; - QCPLayerable *clickedLayerable = layerableAt(event->pos(), true, &details); - bool selectionStateChanged = false; - bool additive = mInteractions.testFlag(QCP::iMultiSelect) && event->modifiers().testFlag(mMultiSelectModifier); - // deselect all other layerables if not additive selection: - if (!additive) - { - foreach (QCPLayer *layer, mLayers) + emit mouseRelease(event); + bool doReplot = false; + + if ((mMousePressPos-event->pos()).manhattanLength() < 5) // determine whether it was a click operation + { + if (event->button() == Qt::LeftButton) + { + // handle selection mechanism: + QVariant details; + QCPLayerable *clickedLayerable = layerableAt(event->pos(), true, &details); + bool selectionStateChanged = false; + bool additive = mInteractions.testFlag(QCP::iMultiSelect) && event->modifiers().testFlag(mMultiSelectModifier); + // deselect all other layerables if not additive selection: + if (!additive) + { + foreach (QCPLayer *layer, mLayers) { - foreach (QCPLayerable *layerable, layer->children()) + foreach (QCPLayerable *layerable, layer->children()) { - if (layerable != clickedLayerable && mInteractions.testFlag(layerable->selectionCategory())) + if (layerable != clickedLayerable && mInteractions.testFlag(layerable->selectionCategory())) { - bool selChanged = false; - layerable->deselectEvent(&selChanged); - selectionStateChanged |= selChanged; + bool selChanged = false; + layerable->deselectEvent(&selChanged); + selectionStateChanged |= selChanged; } } } } - if (clickedLayerable && mInteractions.testFlag(clickedLayerable->selectionCategory())) - { - // a layerable was actually clicked, call its selectEvent: - bool selChanged = false; - clickedLayerable->selectEvent(event, additive, details, &selChanged); - selectionStateChanged |= selChanged; - } - doReplot = true; - if (selectionStateChanged) - emit selectionChangedByUser(); - } - - // emit specialized object click signals: - QVariant details; - QCPLayerable *clickedLayerable = layerableAt(event->pos(), false, &details); // for these signals, selectability is ignored, that's why we call this again with onlySelectable set to false - if (QCPAbstractPlottable *ap = qobject_cast(clickedLayerable)) - emit plottableClick(ap, event); - else if (QCPAxis *ax = qobject_cast(clickedLayerable)) - emit axisClick(ax, details.value(), event); - else if (QCPAbstractItem *ai = qobject_cast(clickedLayerable)) - emit itemClick(ai, event); - else if (QCPLegend *lg = qobject_cast(clickedLayerable)) - emit legendClick(lg, 0, event); - else if (QCPAbstractLegendItem *li = qobject_cast(clickedLayerable)) - emit legendClick(li->parentLegend(), li, event); - else if (QCPPlotTitle *pt = qobject_cast(clickedLayerable)) - emit titleClick(event, pt); - } - - // call event of affected layout element: - if (mMouseEventElement) - { - mMouseEventElement->mouseReleaseEvent(event); - mMouseEventElement = 0; - } - - if (doReplot || noAntialiasingOnDrag()) - replot(); - - QWidget::mouseReleaseEvent(event); + if (clickedLayerable && mInteractions.testFlag(clickedLayerable->selectionCategory())) + { + // a layerable was actually clicked, call its selectEvent: + bool selChanged = false; + clickedLayerable->selectEvent(event, additive, details, &selChanged); + selectionStateChanged |= selChanged; + } + doReplot = true; + if (selectionStateChanged) + emit selectionChangedByUser(); + } + + // emit specialized object click signals: + QVariant details; + QCPLayerable *clickedLayerable = layerableAt(event->pos(), false, &details); // for these signals, selectability is ignored, that's why we call this again with onlySelectable set to false + if (QCPAbstractPlottable *ap = qobject_cast(clickedLayerable)) + emit plottableClick(ap, event); + else if (QCPAxis *ax = qobject_cast(clickedLayerable)) + emit axisClick(ax, details.value(), event); + else if (QCPAbstractItem *ai = qobject_cast(clickedLayerable)) + emit itemClick(ai, event); + else if (QCPLegend *lg = qobject_cast(clickedLayerable)) + emit legendClick(lg, 0, event); + else if (QCPAbstractLegendItem *li = qobject_cast(clickedLayerable)) + emit legendClick(li->parentLegend(), li, event); + else if (QCPPlotTitle *pt = qobject_cast(clickedLayerable)) + emit titleClick(event, pt); + } + + // call event of affected layout element: + if (mMouseEventElement) + { + mMouseEventElement->mouseReleaseEvent(event); + mMouseEventElement = 0; + } + + if (doReplot || noAntialiasingOnDrag()) + replot(); + + QWidget::mouseReleaseEvent(event); } /*! \internal @@ -10872,13 +10864,13 @@ void QCustomPlot::mouseReleaseEvent(QMou */ void QCustomPlot::wheelEvent(QWheelEvent *event) { - emit mouseWheel(event); - - // call event of affected layout element: - if (QCPLayoutElement *el = layoutElementAt(event->pos())) - el->wheelEvent(event); - - QWidget::wheelEvent(event); + emit mouseWheel(event); + + // call event of affected layout element: + if (QCPLayoutElement *el = layoutElementAt(event->pos())) + el->wheelEvent(event); + + QWidget::wheelEvent(event); } /*! \internal @@ -10890,31 +10882,31 @@ void QCustomPlot::wheelEvent(QWheelEvent */ void QCustomPlot::draw(QCPPainter *painter) { - // run through layout phases: - mPlotLayout->update(QCPLayoutElement::upPreparation); - mPlotLayout->update(QCPLayoutElement::upMargins); - mPlotLayout->update(QCPLayoutElement::upLayout); - - // draw viewport background pixmap: - drawBackground(painter); - - // draw all layered objects (grid, axes, plottables, items, legend,...): - foreach (QCPLayer *layer, mLayers) - { - foreach (QCPLayerable *child, layer->children()) - { - if (child->realVisibility()) - { - painter->save(); - painter->setClipRect(child->clipRect().translated(0, -1)); - child->applyDefaultAntialiasingHint(painter); - child->draw(painter); - painter->restore(); - } - } - } - - /* Debug code to draw all layout element rects + // run through layout phases: + mPlotLayout->update(QCPLayoutElement::upPreparation); + mPlotLayout->update(QCPLayoutElement::upMargins); + mPlotLayout->update(QCPLayoutElement::upLayout); + + // draw viewport background pixmap: + drawBackground(painter); + + // draw all layered objects (grid, axes, plottables, items, legend,...): + foreach (QCPLayer *layer, mLayers) + { + foreach (QCPLayerable *child, layer->children()) + { + if (child->realVisibility()) + { + painter->save(); + painter->setClipRect(child->clipRect().translated(0, -1)); + child->applyDefaultAntialiasingHint(painter); + child->draw(painter); + painter->restore(); + } + } + } + + /* Debug code to draw all layout element rects foreach (QCPLayoutElement* el, findChildren()) { painter->setBrush(Qt::NoBrush); @@ -10945,22 +10937,22 @@ void QCustomPlot::draw(QCPPainter *paint */ void QCustomPlot::drawBackground(QCPPainter *painter) { - // Note: background color is handled in individual replot/save functions - - // draw background pixmap (on top of fill, if brush specified): - if (!mBackgroundPixmap.isNull()) - { - if (mBackgroundScaled) - { - // check whether mScaledBackground needs to be updated: - QSize scaledSize(mBackgroundPixmap.size()); - scaledSize.scale(mViewport.size(), mBackgroundScaledMode); - if (mScaledBackgroundPixmap.size() != scaledSize) - mScaledBackgroundPixmap = mBackgroundPixmap.scaled(mViewport.size(), mBackgroundScaledMode, Qt::SmoothTransformation); - painter->drawPixmap(mViewport.topLeft(), mScaledBackgroundPixmap, QRect(0, 0, mViewport.width(), mViewport.height()) & mScaledBackgroundPixmap.rect()); + // Note: background color is handled in individual replot/save functions + + // draw background pixmap (on top of fill, if brush specified): + if (!mBackgroundPixmap.isNull()) + { + if (mBackgroundScaled) + { + // check whether mScaledBackground needs to be updated: + QSize scaledSize(mBackgroundPixmap.size()); + scaledSize.scale(mViewport.size(), mBackgroundScaledMode); + if (mScaledBackgroundPixmap.size() != scaledSize) + mScaledBackgroundPixmap = mBackgroundPixmap.scaled(mViewport.size(), mBackgroundScaledMode, Qt::SmoothTransformation); + painter->drawPixmap(mViewport.topLeft(), mScaledBackgroundPixmap, QRect(0, 0, mViewport.width(), mViewport.height()) & mScaledBackgroundPixmap.rect()); } else { - painter->drawPixmap(mViewport.topLeft(), mBackgroundPixmap, QRect(0, 0, mViewport.width(), mViewport.height())); + painter->drawPixmap(mViewport.topLeft(), mBackgroundPixmap, QRect(0, 0, mViewport.width(), mViewport.height())); } } } @@ -10973,16 +10965,16 @@ void QCustomPlot::drawBackground(QCPPain */ void QCustomPlot::axisRemoved(QCPAxis *axis) { - if (xAxis == axis) - xAxis = 0; - if (xAxis2 == axis) - xAxis2 = 0; - if (yAxis == axis) - yAxis = 0; - if (yAxis2 == axis) - yAxis2 = 0; - - // Note: No need to take care of range drag axes and range zoom axes, because they are stored in smart pointers + if (xAxis == axis) + xAxis = 0; + if (xAxis2 == axis) + xAxis2 = 0; + if (yAxis == axis) + yAxis = 0; + if (yAxis2 == axis) + yAxis2 = 0; + + // Note: No need to take care of range drag axes and range zoom axes, because they are stored in smart pointers } /*! \internal @@ -10992,8 +10984,8 @@ void QCustomPlot::axisRemoved(QCPAxis *a */ void QCustomPlot::legendRemoved(QCPLegend *legend) { - if (this->legend == legend) - this->legend = 0; + if (this->legend == legend) + this->legend = 0; } /*! \internal @@ -11004,8 +10996,8 @@ void QCustomPlot::legendRemoved(QCPLegen */ void QCustomPlot::updateLayerIndices() const { - for (int i=0; imIndex = i; + for (int i=0; imIndex = i; } /*! \internal @@ -11022,28 +11014,28 @@ void QCustomPlot::updateLayerIndices() c */ QCPLayerable *QCustomPlot::layerableAt(const QPointF &pos, bool onlySelectable, QVariant *selectionDetails) const { - for (int layerIndex=mLayers.size()-1; layerIndex>=0; --layerIndex) - { - const QList layerables = mLayers.at(layerIndex)->children(); - double minimumDistance = selectionTolerance()*1.1; - QCPLayerable *minimumDistanceLayerable = 0; - for (int i=layerables.size()-1; i>=0; --i) - { - if (!layerables.at(i)->realVisibility()) - continue; - QVariant details; - double dist = layerables.at(i)->selectTest(pos, onlySelectable, &details); - if (dist >= 0 && dist < minimumDistance) - { - minimumDistance = dist; - minimumDistanceLayerable = layerables.at(i); - if (selectionDetails) *selectionDetails = details; - } - } - if (minimumDistance < selectionTolerance()) - return minimumDistanceLayerable; - } - return 0; + for (int layerIndex=mLayers.size()-1; layerIndex>=0; --layerIndex) + { + const QList layerables = mLayers.at(layerIndex)->children(); + double minimumDistance = selectionTolerance()*1.1; + QCPLayerable *minimumDistanceLayerable = 0; + for (int i=layerables.size()-1; i>=0; --i) + { + if (!layerables.at(i)->realVisibility()) + continue; + QVariant details; + double dist = layerables.at(i)->selectTest(pos, onlySelectable, &details); + if (dist >= 0 && dist < minimumDistance) + { + minimumDistance = dist; + minimumDistanceLayerable = layerables.at(i); + if (selectionDetails) *selectionDetails = details; + } + } + if (minimumDistance < selectionTolerance()) + return minimumDistanceLayerable; + } + return 0; } /*! @@ -11059,11 +11051,11 @@ QCPLayerable *QCustomPlot::layerableAt(c */ bool QCustomPlot::saveRastered(const QString &fileName, int width, int height, double scale, const char *format, int quality) { - QPixmap buffer = toPixmap(width, height, scale); - if (!buffer.isNull()) - return buffer.save(fileName, format, quality); - else - return false; + QPixmap buffer = toPixmap(width, height, scale); + if (!buffer.isNull()) + return buffer.save(fileName, format, quality); + else + return false; } /*! @@ -11076,46 +11068,46 @@ bool QCustomPlot::saveRastered(const QSt */ QPixmap QCustomPlot::toPixmap(int width, int height, double scale) { - // this method is somewhat similar to toPainter. Change something here, and a change in toPainter might be necessary, too. - int newWidth, newHeight; - if (width == 0 || height == 0) - { - newWidth = this->width(); - newHeight = this->height(); - } else - { - newWidth = width; - newHeight = height; - } - int scaledWidth = qRound(scale*newWidth); - int scaledHeight = qRound(scale*newHeight); - - QPixmap result(scaledWidth, scaledHeight); - result.fill(mBackgroundBrush.style() == Qt::SolidPattern ? mBackgroundBrush.color() : Qt::transparent); // if using non-solid pattern, make transparent now and draw brush pattern later - QCPPainter painter; - painter.begin(&result); - if (painter.isActive()) - { - QRect oldViewport = viewport(); - setViewport(QRect(0, 0, newWidth, newHeight)); - painter.setMode(QCPPainter::pmNoCaching); - if (!qFuzzyCompare(scale, 1.0)) - { - if (scale > 1.0) // for scale < 1 we always want cosmetic pens where possible, because else lines might disappear for very small scales - painter.setMode(QCPPainter::pmNonCosmetic); - painter.scale(scale, scale); - } - if (mBackgroundBrush.style() != Qt::SolidPattern && mBackgroundBrush.style() != Qt::NoBrush) - painter.fillRect(mViewport, mBackgroundBrush); - draw(&painter); - setViewport(oldViewport); - painter.end(); + // this method is somewhat similar to toPainter. Change something here, and a change in toPainter might be necessary, too. + int newWidth, newHeight; + if (width == 0 || height == 0) + { + newWidth = this->width(); + newHeight = this->height(); + } else + { + newWidth = width; + newHeight = height; + } + int scaledWidth = qRound(scale*newWidth); + int scaledHeight = qRound(scale*newHeight); + + QPixmap result(scaledWidth, scaledHeight); + result.fill(mBackgroundBrush.style() == Qt::SolidPattern ? mBackgroundBrush.color() : Qt::transparent); // if using non-solid pattern, make transparent now and draw brush pattern later + QCPPainter painter; + painter.begin(&result); + if (painter.isActive()) + { + QRect oldViewport = viewport(); + setViewport(QRect(0, 0, newWidth, newHeight)); + painter.setMode(QCPPainter::pmNoCaching); + if (!qFuzzyCompare(scale, 1.0)) + { + if (scale > 1.0) // for scale < 1 we always want cosmetic pens where possible, because else lines might disappear for very small scales + painter.setMode(QCPPainter::pmNonCosmetic); + painter.scale(scale, scale); + } + if (mBackgroundBrush.style() != Qt::SolidPattern && mBackgroundBrush.style() != Qt::NoBrush) + painter.fillRect(mViewport, mBackgroundBrush); + draw(&painter); + setViewport(oldViewport); + painter.end(); } else // might happen if pixmap has width or height zero { - qDebug() << Q_FUNC_INFO << "Couldn't activate painter on pixmap"; - return QPixmap(); - } - return result; + qDebug() << Q_FUNC_INFO << "Couldn't activate painter on pixmap"; + return QPixmap(); + } + return result; } /*! @@ -11132,31 +11124,31 @@ QPixmap QCustomPlot::toPixmap(int width, */ void QCustomPlot::toPainter(QCPPainter *painter, int width, int height) { - // this method is somewhat similar to toPixmap. Change something here, and a change in toPixmap might be necessary, too. - int newWidth, newHeight; - if (width == 0 || height == 0) - { - newWidth = this->width(); - newHeight = this->height(); - } else - { - newWidth = width; - newHeight = height; - } - - if (painter->isActive()) - { - QRect oldViewport = viewport(); - setViewport(QRect(0, 0, newWidth, newHeight)); - painter->setMode(QCPPainter::pmNoCaching); - // warning: the following is different in toPixmap, because a solid background color is applied there via QPixmap::fill - // here, we need to do this via QPainter::fillRect. - if (mBackgroundBrush.style() != Qt::NoBrush) - painter->fillRect(mViewport, mBackgroundBrush); - draw(painter); - setViewport(oldViewport); - } else - qDebug() << Q_FUNC_INFO << "Passed painter is not active"; + // this method is somewhat similar to toPixmap. Change something here, and a change in toPixmap might be necessary, too. + int newWidth, newHeight; + if (width == 0 || height == 0) + { + newWidth = this->width(); + newHeight = this->height(); + } else + { + newWidth = width; + newHeight = height; + } + + if (painter->isActive()) + { + QRect oldViewport = viewport(); + setViewport(QRect(0, 0, newWidth, newHeight)); + painter->setMode(QCPPainter::pmNoCaching); + // warning: the following is different in toPixmap, because a solid background color is applied there via QPixmap::fill + // here, we need to do this via QPainter::fillRect. + if (mBackgroundBrush.style() != Qt::NoBrush) + painter->fillRect(mViewport, mBackgroundBrush); + draw(painter); + setViewport(oldViewport); + } else + qDebug() << Q_FUNC_INFO << "Passed painter is not active"; } @@ -11197,22 +11189,22 @@ void QCustomPlot::toPainter(QCPPainter * The color level count is initialized to 350. */ QCPColorGradient::QCPColorGradient(GradientPreset preset) : - mLevelCount(350), - mColorInterpolation(ciRGB), - mPeriodic(false), - mColorBufferInvalidated(true) -{ - mColorBuffer.fill(qRgb(0, 0, 0), mLevelCount); - loadPreset(preset); + mLevelCount(350), + mColorInterpolation(ciRGB), + mPeriodic(false), + mColorBufferInvalidated(true) +{ + mColorBuffer.fill(qRgb(0, 0, 0), mLevelCount); + loadPreset(preset); } /* undocumented operator */ bool QCPColorGradient::operator==(const QCPColorGradient &other) const { - return ((other.mLevelCount == this->mLevelCount) && - (other.mColorInterpolation == this->mColorInterpolation) && - (other.mPeriodic == this->mPeriodic) && - (other.mColorStops == this->mColorStops)); + return ((other.mLevelCount == this->mLevelCount) && + (other.mColorInterpolation == this->mColorInterpolation) && + (other.mPeriodic == this->mPeriodic) && + (other.mColorStops == this->mColorStops)); } /*! @@ -11223,15 +11215,15 @@ bool QCPColorGradient::operator==(const */ void QCPColorGradient::setLevelCount(int n) { - if (n < 2) - { - qDebug() << Q_FUNC_INFO << "n must be greater or equal 2 but was" << n; - n = 2; - } - if (n != mLevelCount) - { - mLevelCount = n; - mColorBufferInvalidated = true; + if (n < 2) + { + qDebug() << Q_FUNC_INFO << "n must be greater or equal 2 but was" << n; + n = 2; + } + if (n != mLevelCount) + { + mLevelCount = n; + mColorBufferInvalidated = true; } } @@ -11247,8 +11239,8 @@ void QCPColorGradient::setLevelCount(int */ void QCPColorGradient::setColorStops(const QMap &colorStops) { - mColorStops = colorStops; - mColorBufferInvalidated = true; + mColorStops = colorStops; + mColorBufferInvalidated = true; } /*! @@ -11259,8 +11251,8 @@ void QCPColorGradient::setColorStops(con */ void QCPColorGradient::setColorStopAt(double position, const QColor &color) { - mColorStops.insert(position, color); - mColorBufferInvalidated = true; + mColorStops.insert(position, color); + mColorBufferInvalidated = true; } /*! @@ -11272,10 +11264,10 @@ void QCPColorGradient::setColorStopAt(do */ void QCPColorGradient::setColorInterpolation(QCPColorGradient::ColorInterpolation interpolation) { - if (interpolation != mColorInterpolation) - { - mColorInterpolation = interpolation; - mColorBufferInvalidated = true; + if (interpolation != mColorInterpolation) + { + mColorInterpolation = interpolation; + mColorBufferInvalidated = true; } } @@ -11296,7 +11288,7 @@ void QCPColorGradient::setColorInterpola */ void QCPColorGradient::setPeriodic(bool enabled) { - mPeriodic = enabled; + mPeriodic = enabled; } /*! @@ -11313,65 +11305,65 @@ void QCPColorGradient::setPeriodic(bool */ void QCPColorGradient::colorize(const double *data, const QCPRange &range, QRgb *scanLine, int n, int dataIndexFactor, bool logarithmic) { - // If you change something here, make sure to also adapt ::color() - if (!data) - { - qDebug() << Q_FUNC_INFO << "null pointer given as data"; - return; - } - if (!scanLine) - { - qDebug() << Q_FUNC_INFO << "null pointer given as scanLine"; - return; - } - if (mColorBufferInvalidated) - updateColorBuffer(); - - if (!logarithmic) - { - const double posToIndexFactor = (mLevelCount-1)/range.size(); - if (mPeriodic) - { - for (int i=0; i= mLevelCount) - index = mLevelCount-1; - scanLine[i] = mColorBuffer.at(index); + for (int i=0; i= mLevelCount) + index = mLevelCount-1; + scanLine[i] = mColorBuffer.at(index); } } } else // logarithmic == true { - if (mPeriodic) - { - for (int i=0; i= mLevelCount) - index = mLevelCount-1; - scanLine[i] = mColorBuffer.at(index); + for (int i=0; i= mLevelCount) + index = mLevelCount-1; + scanLine[i] = mColorBuffer.at(index); } } } @@ -11388,27 +11380,27 @@ void QCPColorGradient::colorize(const do */ QRgb QCPColorGradient::color(double position, const QCPRange &range, bool logarithmic) { - // If you change something here, make sure to also adapt ::colorize() - if (mColorBufferInvalidated) - updateColorBuffer(); - int index = 0; - if (!logarithmic) - index = (position-range.lower)*(mLevelCount-1)/range.size(); - else - index = qLn(position/range.lower)/qLn(range.upper/range.lower)*(mLevelCount-1); - if (mPeriodic) - { - index = index % mLevelCount; - if (index < 0) - index += mLevelCount; - } else - { - if (index < 0) - index = 0; - else if (index >= mLevelCount) - index = mLevelCount-1; - } - return mColorBuffer.at(index); + // If you change something here, make sure to also adapt ::colorize() + if (mColorBufferInvalidated) + updateColorBuffer(); + int index = 0; + if (!logarithmic) + index = (position-range.lower)*(mLevelCount-1)/range.size(); + else + index = qLn(position/range.lower)/qLn(range.upper/range.lower)*(mLevelCount-1); + if (mPeriodic) + { + index = index % mLevelCount; + if (index < 0) + index += mLevelCount; + } else + { + if (index < 0) + index = 0; + else if (index >= mLevelCount) + index = mLevelCount-1; + } + return mColorBuffer.at(index); } /*! @@ -11420,105 +11412,105 @@ QRgb QCPColorGradient::color(double posi */ void QCPColorGradient::loadPreset(GradientPreset preset) { - clearColorStops(); - switch (preset) + clearColorStops(); + switch (preset) { case gpGrayscale: - setColorInterpolation(ciRGB); - setColorStopAt(0, Qt::black); - setColorStopAt(1, Qt::white); - break; + setColorInterpolation(ciRGB); + setColorStopAt(0, Qt::black); + setColorStopAt(1, Qt::white); + break; case gpHot: - setColorInterpolation(ciRGB); - setColorStopAt(0, QColor(50, 0, 0)); - setColorStopAt(0.2, QColor(180, 10, 0)); - setColorStopAt(0.4, QColor(245, 50, 0)); - setColorStopAt(0.6, QColor(255, 150, 10)); - setColorStopAt(0.8, QColor(255, 255, 50)); - setColorStopAt(1, QColor(255, 255, 255)); - break; + setColorInterpolation(ciRGB); + setColorStopAt(0, QColor(50, 0, 0)); + setColorStopAt(0.2, QColor(180, 10, 0)); + setColorStopAt(0.4, QColor(245, 50, 0)); + setColorStopAt(0.6, QColor(255, 150, 10)); + setColorStopAt(0.8, QColor(255, 255, 50)); + setColorStopAt(1, QColor(255, 255, 255)); + break; case gpCold: - setColorInterpolation(ciRGB); - setColorStopAt(0, QColor(0, 0, 50)); - setColorStopAt(0.2, QColor(0, 10, 180)); - setColorStopAt(0.4, QColor(0, 50, 245)); - setColorStopAt(0.6, QColor(10, 150, 255)); - setColorStopAt(0.8, QColor(50, 255, 255)); - setColorStopAt(1, QColor(255, 255, 255)); - break; + setColorInterpolation(ciRGB); + setColorStopAt(0, QColor(0, 0, 50)); + setColorStopAt(0.2, QColor(0, 10, 180)); + setColorStopAt(0.4, QColor(0, 50, 245)); + setColorStopAt(0.6, QColor(10, 150, 255)); + setColorStopAt(0.8, QColor(50, 255, 255)); + setColorStopAt(1, QColor(255, 255, 255)); + break; case gpNight: - setColorInterpolation(ciHSV); - setColorStopAt(0, QColor(10, 20, 30)); - setColorStopAt(1, QColor(250, 255, 250)); - break; + setColorInterpolation(ciHSV); + setColorStopAt(0, QColor(10, 20, 30)); + setColorStopAt(1, QColor(250, 255, 250)); + break; case gpCandy: - setColorInterpolation(ciHSV); - setColorStopAt(0, QColor(0, 0, 255)); - setColorStopAt(1, QColor(255, 250, 250)); - break; + setColorInterpolation(ciHSV); + setColorStopAt(0, QColor(0, 0, 255)); + setColorStopAt(1, QColor(255, 250, 250)); + break; case gpGeography: - setColorInterpolation(ciRGB); - setColorStopAt(0, QColor(70, 170, 210)); - setColorStopAt(0.20, QColor(90, 160, 180)); - setColorStopAt(0.25, QColor(45, 130, 175)); - setColorStopAt(0.30, QColor(100, 140, 125)); - setColorStopAt(0.5, QColor(100, 140, 100)); - setColorStopAt(0.6, QColor(130, 145, 120)); - setColorStopAt(0.7, QColor(140, 130, 120)); - setColorStopAt(0.9, QColor(180, 190, 190)); - setColorStopAt(1, QColor(210, 210, 230)); - break; + setColorInterpolation(ciRGB); + setColorStopAt(0, QColor(70, 170, 210)); + setColorStopAt(0.20, QColor(90, 160, 180)); + setColorStopAt(0.25, QColor(45, 130, 175)); + setColorStopAt(0.30, QColor(100, 140, 125)); + setColorStopAt(0.5, QColor(100, 140, 100)); + setColorStopAt(0.6, QColor(130, 145, 120)); + setColorStopAt(0.7, QColor(140, 130, 120)); + setColorStopAt(0.9, QColor(180, 190, 190)); + setColorStopAt(1, QColor(210, 210, 230)); + break; case gpIon: - setColorInterpolation(ciHSV); - setColorStopAt(0, QColor(50, 10, 10)); - setColorStopAt(0.45, QColor(0, 0, 255)); - setColorStopAt(0.8, QColor(0, 255, 255)); - setColorStopAt(1, QColor(0, 255, 0)); - break; + setColorInterpolation(ciHSV); + setColorStopAt(0, QColor(50, 10, 10)); + setColorStopAt(0.45, QColor(0, 0, 255)); + setColorStopAt(0.8, QColor(0, 255, 255)); + setColorStopAt(1, QColor(0, 255, 0)); + break; case gpThermal: - setColorInterpolation(ciRGB); - setColorStopAt(0, QColor(0, 0, 50)); - setColorStopAt(0.15, QColor(20, 0, 120)); - setColorStopAt(0.33, QColor(200, 30, 140)); - setColorStopAt(0.6, QColor(255, 100, 0)); - setColorStopAt(0.85, QColor(255, 255, 40)); - setColorStopAt(1, QColor(255, 255, 255)); - break; + setColorInterpolation(ciRGB); + setColorStopAt(0, QColor(0, 0, 50)); + setColorStopAt(0.15, QColor(20, 0, 120)); + setColorStopAt(0.33, QColor(200, 30, 140)); + setColorStopAt(0.6, QColor(255, 100, 0)); + setColorStopAt(0.85, QColor(255, 255, 40)); + setColorStopAt(1, QColor(255, 255, 255)); + break; case gpPolar: - setColorInterpolation(ciRGB); - setColorStopAt(0, QColor(50, 255, 255)); - setColorStopAt(0.18, QColor(10, 70, 255)); - setColorStopAt(0.28, QColor(10, 10, 190)); - setColorStopAt(0.5, QColor(0, 0, 0)); - setColorStopAt(0.72, QColor(190, 10, 10)); - setColorStopAt(0.82, QColor(255, 70, 10)); - setColorStopAt(1, QColor(255, 255, 50)); - break; + setColorInterpolation(ciRGB); + setColorStopAt(0, QColor(50, 255, 255)); + setColorStopAt(0.18, QColor(10, 70, 255)); + setColorStopAt(0.28, QColor(10, 10, 190)); + setColorStopAt(0.5, QColor(0, 0, 0)); + setColorStopAt(0.72, QColor(190, 10, 10)); + setColorStopAt(0.82, QColor(255, 70, 10)); + setColorStopAt(1, QColor(255, 255, 50)); + break; case gpSpectrum: - setColorInterpolation(ciHSV); - setColorStopAt(0, QColor(50, 0, 50)); - setColorStopAt(0.15, QColor(0, 0, 255)); - setColorStopAt(0.35, QColor(0, 255, 255)); - setColorStopAt(0.6, QColor(255, 255, 0)); - setColorStopAt(0.75, QColor(255, 30, 0)); - setColorStopAt(1, QColor(50, 0, 0)); - break; + setColorInterpolation(ciHSV); + setColorStopAt(0, QColor(50, 0, 50)); + setColorStopAt(0.15, QColor(0, 0, 255)); + setColorStopAt(0.35, QColor(0, 255, 255)); + setColorStopAt(0.6, QColor(255, 255, 0)); + setColorStopAt(0.75, QColor(255, 30, 0)); + setColorStopAt(1, QColor(50, 0, 0)); + break; case gpJet: - setColorInterpolation(ciRGB); - setColorStopAt(0, QColor(0, 0, 100)); - setColorStopAt(0.15, QColor(0, 50, 255)); - setColorStopAt(0.35, QColor(0, 255, 255)); - setColorStopAt(0.65, QColor(255, 255, 0)); - setColorStopAt(0.85, QColor(255, 30, 0)); - setColorStopAt(1, QColor(100, 0, 0)); - break; + setColorInterpolation(ciRGB); + setColorStopAt(0, QColor(0, 0, 100)); + setColorStopAt(0.15, QColor(0, 50, 255)); + setColorStopAt(0.35, QColor(0, 255, 255)); + setColorStopAt(0.65, QColor(255, 255, 0)); + setColorStopAt(0.85, QColor(255, 30, 0)); + setColorStopAt(1, QColor(100, 0, 0)); + break; case gpHues: - setColorInterpolation(ciHSV); - setColorStopAt(0, QColor(255, 0, 0)); - setColorStopAt(1.0/3.0, QColor(0, 0, 255)); - setColorStopAt(2.0/3.0, QColor(0, 255, 0)); - setColorStopAt(1, QColor(255, 0, 0)); - break; + setColorInterpolation(ciHSV); + setColorStopAt(0, QColor(255, 0, 0)); + setColorStopAt(1.0/3.0, QColor(0, 0, 255)); + setColorStopAt(2.0/3.0, QColor(0, 255, 0)); + setColorStopAt(1, QColor(255, 0, 0)); + break; } } @@ -11529,8 +11521,8 @@ void QCPColorGradient::loadPreset(Gradie */ void QCPColorGradient::clearColorStops() { - mColorStops.clear(); - mColorBufferInvalidated = true; + mColorStops.clear(); + mColorBufferInvalidated = true; } /*! @@ -11541,11 +11533,11 @@ void QCPColorGradient::clearColorStops() */ QCPColorGradient QCPColorGradient::inverted() const { - QCPColorGradient result(*this); - result.clearColorStops(); - for (QMap::const_iterator it=mColorStops.constBegin(); it!=mColorStops.constEnd(); ++it) - result.setColorStopAt(1.0-it.key(), it.value()); - return result; + QCPColorGradient result(*this); + result.clearColorStops(); + for (QMap::const_iterator it=mColorStops.constBegin(); it!=mColorStops.constEnd(); ++it) + result.setColorStopAt(1.0-it.key(), it.value()); + return result; } /*! \internal @@ -11555,63 +11547,63 @@ QCPColorGradient QCPColorGradient::inver */ void QCPColorGradient::updateColorBuffer() { - if (mColorBuffer.size() != mLevelCount) - mColorBuffer.resize(mLevelCount); - if (mColorStops.size() > 1) - { - double indexToPosFactor = 1.0/(double)(mLevelCount-1); - for (int i=0; i::const_iterator it = mColorStops.lowerBound(position); - if (it == mColorStops.constEnd()) // position is on or after last stop, use color of last stop - { - mColorBuffer[i] = (it-1).value().rgb(); + if (mColorBuffer.size() != mLevelCount) + mColorBuffer.resize(mLevelCount); + if (mColorStops.size() > 1) + { + double indexToPosFactor = 1.0/(double)(mLevelCount-1); + for (int i=0; i::const_iterator it = mColorStops.lowerBound(position); + if (it == mColorStops.constEnd()) // position is on or after last stop, use color of last stop + { + mColorBuffer[i] = (it-1).value().rgb(); } else if (it == mColorStops.constBegin()) // position is on or before first stop, use color of first stop { - mColorBuffer[i] = it.value().rgb(); + mColorBuffer[i] = it.value().rgb(); } else // position is in between stops (or on an intermediate stop), interpolate color { - QMap::const_iterator high = it; - QMap::const_iterator low = it-1; - double t = (position-low.key())/(high.key()-low.key()); // interpolation factor 0..1 - switch (mColorInterpolation) + QMap::const_iterator high = it; + QMap::const_iterator low = it-1; + double t = (position-low.key())/(high.key()-low.key()); // interpolation factor 0..1 + switch (mColorInterpolation) { case ciRGB: - { + { mColorBuffer[i] = qRgb((1-t)*low.value().red() + t*high.value().red(), (1-t)*low.value().green() + t*high.value().green(), (1-t)*low.value().blue() + t*high.value().blue()); break; - } + } case ciHSV: - { + { QColor lowHsv = low.value().toHsv(); QColor highHsv = high.value().toHsv(); double hue = 0; double hueDiff = highHsv.hueF()-lowHsv.hueF(); if (hueDiff > 0.5) - hue = lowHsv.hueF() - t*(1.0-hueDiff); + hue = lowHsv.hueF() - t*(1.0-hueDiff); else if (hueDiff < -0.5) - hue = lowHsv.hueF() + t*(1.0+hueDiff); + hue = lowHsv.hueF() + t*(1.0+hueDiff); else - hue = lowHsv.hueF() + t*hueDiff; + hue = lowHsv.hueF() + t*hueDiff; if (hue < 0) hue += 1.0; else if (hue >= 1.0) hue -= 1.0; mColorBuffer[i] = QColor::fromHsvF(hue, (1-t)*lowHsv.saturationF() + t*highHsv.saturationF(), (1-t)*lowHsv.valueF() + t*highHsv.valueF()).rgb(); break; - } + } } } } } else if (mColorStops.size() == 1) { - mColorBuffer.fill(mColorStops.constBegin().value().rgb()); + mColorBuffer.fill(mColorStops.constBegin().value().rgb()); } else // mColorStops is empty, fill color buffer with black { - mColorBuffer.fill(qRgb(0, 0, 0)); - } - mColorBufferInvalidated = false; + mColorBuffer.fill(qRgb(0, 0, 0)); + } + mColorBufferInvalidated = false; } @@ -11745,57 +11737,57 @@ void QCPColorGradient::updateColorBuffer sides, the top and right axes are set invisible initially. */ QCPAxisRect::QCPAxisRect(QCustomPlot *parentPlot, bool setupDefaultAxes) : - QCPLayoutElement(parentPlot), - mBackgroundBrush(Qt::NoBrush), - mBackgroundScaled(true), - mBackgroundScaledMode(Qt::KeepAspectRatioByExpanding), - mInsetLayout(new QCPLayoutInset), - mRangeDrag(Qt::Horizontal|Qt::Vertical), - mRangeZoom(Qt::Horizontal|Qt::Vertical), - mRangeZoomFactorHorz(0.85), - mRangeZoomFactorVert(0.85), - mDragging(false) -{ - mInsetLayout->initializeParentPlot(mParentPlot); - mInsetLayout->setParentLayerable(this); - mInsetLayout->setParent(this); - - setMinimumSize(50, 50); - setMinimumMargins(QMargins(15, 15, 15, 15)); - mAxes.insert(QCPAxis::atLeft, QList()); - mAxes.insert(QCPAxis::atRight, QList()); - mAxes.insert(QCPAxis::atTop, QList()); - mAxes.insert(QCPAxis::atBottom, QList()); - - if (setupDefaultAxes) - { - QCPAxis *xAxis = addAxis(QCPAxis::atBottom); - QCPAxis *yAxis = addAxis(QCPAxis::atLeft); - QCPAxis *xAxis2 = addAxis(QCPAxis::atTop); - QCPAxis *yAxis2 = addAxis(QCPAxis::atRight); - setRangeDragAxes(xAxis, yAxis); - setRangeZoomAxes(xAxis, yAxis); - xAxis2->setVisible(false); - yAxis2->setVisible(false); - xAxis->grid()->setVisible(true); - yAxis->grid()->setVisible(true); - xAxis2->grid()->setVisible(false); - yAxis2->grid()->setVisible(false); - xAxis2->grid()->setZeroLinePen(Qt::NoPen); - yAxis2->grid()->setZeroLinePen(Qt::NoPen); - xAxis2->grid()->setVisible(false); - yAxis2->grid()->setVisible(false); + QCPLayoutElement(parentPlot), + mBackgroundBrush(Qt::NoBrush), + mBackgroundScaled(true), + mBackgroundScaledMode(Qt::KeepAspectRatioByExpanding), + mInsetLayout(new QCPLayoutInset), + mRangeDrag(Qt::Horizontal|Qt::Vertical), + mRangeZoom(Qt::Horizontal|Qt::Vertical), + mRangeZoomFactorHorz(0.85), + mRangeZoomFactorVert(0.85), + mDragging(false) +{ + mInsetLayout->initializeParentPlot(mParentPlot); + mInsetLayout->setParentLayerable(this); + mInsetLayout->setParent(this); + + setMinimumSize(50, 50); + setMinimumMargins(QMargins(15, 15, 15, 15)); + mAxes.insert(QCPAxis::atLeft, QList()); + mAxes.insert(QCPAxis::atRight, QList()); + mAxes.insert(QCPAxis::atTop, QList()); + mAxes.insert(QCPAxis::atBottom, QList()); + + if (setupDefaultAxes) + { + QCPAxis *xAxis = addAxis(QCPAxis::atBottom); + QCPAxis *yAxis = addAxis(QCPAxis::atLeft); + QCPAxis *xAxis2 = addAxis(QCPAxis::atTop); + QCPAxis *yAxis2 = addAxis(QCPAxis::atRight); + setRangeDragAxes(xAxis, yAxis); + setRangeZoomAxes(xAxis, yAxis); + xAxis2->setVisible(false); + yAxis2->setVisible(false); + xAxis->grid()->setVisible(true); + yAxis->grid()->setVisible(true); + xAxis2->grid()->setVisible(false); + yAxis2->grid()->setVisible(false); + xAxis2->grid()->setZeroLinePen(Qt::NoPen); + yAxis2->grid()->setZeroLinePen(Qt::NoPen); + xAxis2->grid()->setVisible(false); + yAxis2->grid()->setVisible(false); } } QCPAxisRect::~QCPAxisRect() { - delete mInsetLayout; - mInsetLayout = 0; - - QList axesList = axes(); - for (int i=0; i axesList = axes(); + for (int i=0; i ax(mAxes.value(type)); - if (index >= 0 && index < ax.size()) - { - return ax.at(index); - } else - { - qDebug() << Q_FUNC_INFO << "Axis index out of bounds:" << index; - return 0; + QList ax(mAxes.value(type)); + if (index >= 0 && index < ax.size()) + { + return ax.at(index); + } else + { + qDebug() << Q_FUNC_INFO << "Axis index out of bounds:" << index; + return 0; } } @@ -11836,16 +11828,16 @@ QCPAxis *QCPAxisRect::axis(QCPAxis::Axis */ QList QCPAxisRect::axes(QCPAxis::AxisTypes types) const { - QList result; - if (types.testFlag(QCPAxis::atLeft)) - result << mAxes.value(QCPAxis::atLeft); - if (types.testFlag(QCPAxis::atRight)) - result << mAxes.value(QCPAxis::atRight); - if (types.testFlag(QCPAxis::atTop)) - result << mAxes.value(QCPAxis::atTop); - if (types.testFlag(QCPAxis::atBottom)) - result << mAxes.value(QCPAxis::atBottom); - return result; + QList result; + if (types.testFlag(QCPAxis::atLeft)) + result << mAxes.value(QCPAxis::atLeft); + if (types.testFlag(QCPAxis::atRight)) + result << mAxes.value(QCPAxis::atRight); + if (types.testFlag(QCPAxis::atTop)) + result << mAxes.value(QCPAxis::atTop); + if (types.testFlag(QCPAxis::atBottom)) + result << mAxes.value(QCPAxis::atBottom); + return result; } /*! \overload @@ -11854,14 +11846,14 @@ QList QCPAxisRect::axes(QCPAxi */ QList QCPAxisRect::axes() const { - QList result; - QHashIterator > it(mAxes); - while (it.hasNext()) - { - it.next(); - result << it.value(); - } - return result; + QList result; + QHashIterator > it(mAxes); + while (it.hasNext()) + { + it.next(); + result << it.value(); + } + return result; } /*! @@ -11885,36 +11877,36 @@ QList QCPAxisRect::axes() cons */ QCPAxis *QCPAxisRect::addAxis(QCPAxis::AxisType type, QCPAxis *axis) { - QCPAxis *newAxis = axis; - if (!newAxis) - { - newAxis = new QCPAxis(this, type); + QCPAxis *newAxis = axis; + if (!newAxis) + { + newAxis = new QCPAxis(this, type); } else // user provided existing axis instance, do some sanity checks { - if (newAxis->axisType() != type) - { - qDebug() << Q_FUNC_INFO << "passed axis has different axis type than specified in type parameter"; - return 0; - } - if (newAxis->axisRect() != this) - { - qDebug() << Q_FUNC_INFO << "passed axis doesn't have this axis rect as parent axis rect"; - return 0; - } - if (axes().contains(newAxis)) - { - qDebug() << Q_FUNC_INFO << "passed axis is already owned by this axis rect"; - return 0; - } - } - if (mAxes[type].size() > 0) // multiple axes on one side, add half-bar axis ending to additional axes with offset - { - bool invert = (type == QCPAxis::atRight) || (type == QCPAxis::atBottom); - newAxis->setLowerEnding(QCPLineEnding(QCPLineEnding::esHalfBar, 6, 10, !invert)); - newAxis->setUpperEnding(QCPLineEnding(QCPLineEnding::esHalfBar, 6, 10, invert)); - } - mAxes[type].append(newAxis); - return newAxis; + if (newAxis->axisType() != type) + { + qDebug() << Q_FUNC_INFO << "passed axis has different axis type than specified in type parameter"; + return 0; + } + if (newAxis->axisRect() != this) + { + qDebug() << Q_FUNC_INFO << "passed axis doesn't have this axis rect as parent axis rect"; + return 0; + } + if (axes().contains(newAxis)) + { + qDebug() << Q_FUNC_INFO << "passed axis is already owned by this axis rect"; + return 0; + } + } + if (mAxes[type].size() > 0) // multiple axes on one side, add half-bar axis ending to additional axes with offset + { + bool invert = (type == QCPAxis::atRight) || (type == QCPAxis::atBottom); + newAxis->setLowerEnding(QCPLineEnding(QCPLineEnding::esHalfBar, 6, 10, !invert)); + newAxis->setUpperEnding(QCPLineEnding(QCPLineEnding::esHalfBar, 6, 10, invert)); + } + mAxes[type].append(newAxis); + return newAxis; } /*! @@ -11927,16 +11919,16 @@ QCPAxis *QCPAxisRect::addAxis(QCPAxis::A */ QList QCPAxisRect::addAxes(QCPAxis::AxisTypes types) { - QList result; - if (types.testFlag(QCPAxis::atLeft)) - result << addAxis(QCPAxis::atLeft); - if (types.testFlag(QCPAxis::atRight)) - result << addAxis(QCPAxis::atRight); - if (types.testFlag(QCPAxis::atTop)) - result << addAxis(QCPAxis::atTop); - if (types.testFlag(QCPAxis::atBottom)) - result << addAxis(QCPAxis::atBottom); - return result; + QList result; + if (types.testFlag(QCPAxis::atLeft)) + result << addAxis(QCPAxis::atLeft); + if (types.testFlag(QCPAxis::atRight)) + result << addAxis(QCPAxis::atRight); + if (types.testFlag(QCPAxis::atTop)) + result << addAxis(QCPAxis::atTop); + if (types.testFlag(QCPAxis::atBottom)) + result << addAxis(QCPAxis::atBottom); + return result; } /*! @@ -11948,22 +11940,22 @@ QList QCPAxisRect::addAxes(QCP */ bool QCPAxisRect::removeAxis(QCPAxis *axis) { - // don't access axis->axisType() to provide safety when axis is an invalid pointer, rather go through all axis containers: - QHashIterator > it(mAxes); - while (it.hasNext()) - { - it.next(); - if (it.value().contains(axis)) - { - mAxes[it.key()].removeOne(axis); - if (qobject_cast(parentPlot())) // make sure this isn't called from QObject dtor when QCustomPlot is already destructed (happens when the axis rect is not in any layout and thus QObject-child of QCustomPlot) - parentPlot()->axisRemoved(axis); - delete axis; - return true; - } - } - qDebug() << Q_FUNC_INFO << "Axis isn't in axis rect:" << reinterpret_cast(axis); - return false; + // don't access axis->axisType() to provide safety when axis is an invalid pointer, rather go through all axis containers: + QHashIterator > it(mAxes); + while (it.hasNext()) + { + it.next(); + if (it.value().contains(axis)) + { + mAxes[it.key()].removeOne(axis); + if (qobject_cast(parentPlot())) // make sure this isn't called from QObject dtor when QCustomPlot is already destructed (happens when the axis rect is not in any layout and thus QObject-child of QCustomPlot) + parentPlot()->axisRemoved(axis); + delete axis; + return true; + } + } + qDebug() << Q_FUNC_INFO << "Axis isn't in axis rect:" << reinterpret_cast(axis); + return false; } /*! @@ -11994,70 +11986,70 @@ bool QCPAxisRect::removeAxis(QCPAxis *ax */ void QCPAxisRect::setupFullAxesBox(bool connectRanges) { - QCPAxis *xAxis, *yAxis, *xAxis2, *yAxis2; - if (axisCount(QCPAxis::atBottom) == 0) - xAxis = addAxis(QCPAxis::atBottom); - else - xAxis = axis(QCPAxis::atBottom); - - if (axisCount(QCPAxis::atLeft) == 0) - yAxis = addAxis(QCPAxis::atLeft); - else - yAxis = axis(QCPAxis::atLeft); - - if (axisCount(QCPAxis::atTop) == 0) - xAxis2 = addAxis(QCPAxis::atTop); - else - xAxis2 = axis(QCPAxis::atTop); - - if (axisCount(QCPAxis::atRight) == 0) - yAxis2 = addAxis(QCPAxis::atRight); - else - yAxis2 = axis(QCPAxis::atRight); - - xAxis->setVisible(true); - yAxis->setVisible(true); - xAxis2->setVisible(true); - yAxis2->setVisible(true); - xAxis2->setTickLabels(false); - yAxis2->setTickLabels(false); - - xAxis2->setRange(xAxis->range()); - xAxis2->setRangeReversed(xAxis->rangeReversed()); - xAxis2->setScaleType(xAxis->scaleType()); - xAxis2->setScaleLogBase(xAxis->scaleLogBase()); - xAxis2->setTicks(xAxis->ticks()); - xAxis2->setAutoTickCount(xAxis->autoTickCount()); - xAxis2->setSubTickCount(xAxis->subTickCount()); - xAxis2->setAutoSubTicks(xAxis->autoSubTicks()); - xAxis2->setTickStep(xAxis->tickStep()); - xAxis2->setAutoTickStep(xAxis->autoTickStep()); - xAxis2->setNumberFormat(xAxis->numberFormat()); - xAxis2->setNumberPrecision(xAxis->numberPrecision()); - xAxis2->setTickLabelType(xAxis->tickLabelType()); - xAxis2->setDateTimeFormat(xAxis->dateTimeFormat()); - xAxis2->setDateTimeSpec(xAxis->dateTimeSpec()); - - yAxis2->setRange(yAxis->range()); - yAxis2->setRangeReversed(yAxis->rangeReversed()); - yAxis2->setScaleType(yAxis->scaleType()); - yAxis2->setScaleLogBase(yAxis->scaleLogBase()); - yAxis2->setTicks(yAxis->ticks()); - yAxis2->setAutoTickCount(yAxis->autoTickCount()); - yAxis2->setSubTickCount(yAxis->subTickCount()); - yAxis2->setAutoSubTicks(yAxis->autoSubTicks()); - yAxis2->setTickStep(yAxis->tickStep()); - yAxis2->setAutoTickStep(yAxis->autoTickStep()); - yAxis2->setNumberFormat(yAxis->numberFormat()); - yAxis2->setNumberPrecision(yAxis->numberPrecision()); - yAxis2->setTickLabelType(yAxis->tickLabelType()); - yAxis2->setDateTimeFormat(yAxis->dateTimeFormat()); - yAxis2->setDateTimeSpec(yAxis->dateTimeSpec()); - - if (connectRanges) - { - connect(xAxis, SIGNAL(rangeChanged(QCPRange)), xAxis2, SLOT(setRange(QCPRange))); - connect(yAxis, SIGNAL(rangeChanged(QCPRange)), yAxis2, SLOT(setRange(QCPRange))); + QCPAxis *xAxis, *yAxis, *xAxis2, *yAxis2; + if (axisCount(QCPAxis::atBottom) == 0) + xAxis = addAxis(QCPAxis::atBottom); + else + xAxis = axis(QCPAxis::atBottom); + + if (axisCount(QCPAxis::atLeft) == 0) + yAxis = addAxis(QCPAxis::atLeft); + else + yAxis = axis(QCPAxis::atLeft); + + if (axisCount(QCPAxis::atTop) == 0) + xAxis2 = addAxis(QCPAxis::atTop); + else + xAxis2 = axis(QCPAxis::atTop); + + if (axisCount(QCPAxis::atRight) == 0) + yAxis2 = addAxis(QCPAxis::atRight); + else + yAxis2 = axis(QCPAxis::atRight); + + xAxis->setVisible(true); + yAxis->setVisible(true); + xAxis2->setVisible(true); + yAxis2->setVisible(true); + xAxis2->setTickLabels(false); + yAxis2->setTickLabels(false); + + xAxis2->setRange(xAxis->range()); + xAxis2->setRangeReversed(xAxis->rangeReversed()); + xAxis2->setScaleType(xAxis->scaleType()); + xAxis2->setScaleLogBase(xAxis->scaleLogBase()); + xAxis2->setTicks(xAxis->ticks()); + xAxis2->setAutoTickCount(xAxis->autoTickCount()); + xAxis2->setSubTickCount(xAxis->subTickCount()); + xAxis2->setAutoSubTicks(xAxis->autoSubTicks()); + xAxis2->setTickStep(xAxis->tickStep()); + xAxis2->setAutoTickStep(xAxis->autoTickStep()); + xAxis2->setNumberFormat(xAxis->numberFormat()); + xAxis2->setNumberPrecision(xAxis->numberPrecision()); + xAxis2->setTickLabelType(xAxis->tickLabelType()); + xAxis2->setDateTimeFormat(xAxis->dateTimeFormat()); + xAxis2->setDateTimeSpec(xAxis->dateTimeSpec()); + + yAxis2->setRange(yAxis->range()); + yAxis2->setRangeReversed(yAxis->rangeReversed()); + yAxis2->setScaleType(yAxis->scaleType()); + yAxis2->setScaleLogBase(yAxis->scaleLogBase()); + yAxis2->setTicks(yAxis->ticks()); + yAxis2->setAutoTickCount(yAxis->autoTickCount()); + yAxis2->setSubTickCount(yAxis->subTickCount()); + yAxis2->setAutoSubTicks(yAxis->autoSubTicks()); + yAxis2->setTickStep(yAxis->tickStep()); + yAxis2->setAutoTickStep(yAxis->autoTickStep()); + yAxis2->setNumberFormat(yAxis->numberFormat()); + yAxis2->setNumberPrecision(yAxis->numberPrecision()); + yAxis2->setTickLabelType(yAxis->tickLabelType()); + yAxis2->setDateTimeFormat(yAxis->dateTimeFormat()); + yAxis2->setDateTimeSpec(yAxis->dateTimeSpec()); + + if (connectRanges) + { + connect(xAxis, SIGNAL(rangeChanged(QCPRange)), xAxis2, SLOT(setRange(QCPRange))); + connect(yAxis, SIGNAL(rangeChanged(QCPRange)), yAxis2, SLOT(setRange(QCPRange))); } } @@ -12071,14 +12063,14 @@ void QCPAxisRect::setupFullAxesBox(bool */ QList QCPAxisRect::plottables() const { - // Note: don't append all QCPAxis::plottables() into a list, because we might get duplicate entries - QList result; - for (int i=0; imPlottables.size(); ++i) - { - if (mParentPlot->mPlottables.at(i)->keyAxis()->axisRect() == this ||mParentPlot->mPlottables.at(i)->valueAxis()->axisRect() == this) - result.append(mParentPlot->mPlottables.at(i)); - } - return result; + // Note: don't append all QCPAxis::plottables() into a list, because we might get duplicate entries + QList result; + for (int i=0; imPlottables.size(); ++i) + { + if (mParentPlot->mPlottables.at(i)->keyAxis()->axisRect() == this ||mParentPlot->mPlottables.at(i)->valueAxis()->axisRect() == this) + result.append(mParentPlot->mPlottables.at(i)); + } + return result; } /*! @@ -12091,14 +12083,14 @@ QList QCPAxisRect */ QList QCPAxisRect::graphs() const { - // Note: don't append all QCPAxis::graphs() into a list, because we might get duplicate entries - QList result; - for (int i=0; imGraphs.size(); ++i) - { - if (mParentPlot->mGraphs.at(i)->keyAxis()->axisRect() == this || mParentPlot->mGraphs.at(i)->valueAxis()->axisRect() == this) - result.append(mParentPlot->mGraphs.at(i)); - } - return result; + // Note: don't append all QCPAxis::graphs() into a list, because we might get duplicate entries + QList result; + for (int i=0; imGraphs.size(); ++i) + { + if (mParentPlot->mGraphs.at(i)->keyAxis()->axisRect() == this || mParentPlot->mGraphs.at(i)->valueAxis()->axisRect() == this) + result.append(mParentPlot->mGraphs.at(i)); + } + return result; } /*! @@ -12113,29 +12105,29 @@ QList QCPAxisRect::graphs() c */ QList QCPAxisRect::items() const { - // Note: don't just append all QCPAxis::items() into a list, because we might get duplicate entries - // and miss those items that have this axis rect as clipAxisRect. - QList result; - for (int itemId=0; itemIdmItems.size(); ++itemId) - { - if (mParentPlot->mItems.at(itemId)->clipAxisRect() == this) - { - result.append(mParentPlot->mItems.at(itemId)); - continue; - } - QList positions = mParentPlot->mItems.at(itemId)->positions(); - for (int posId=0; posIdaxisRect() == this || - positions.at(posId)->keyAxis()->axisRect() == this || - positions.at(posId)->valueAxis()->axisRect() == this) - { - result.append(mParentPlot->mItems.at(itemId)); - break; - } - } - } - return result; + // Note: don't just append all QCPAxis::items() into a list, because we might get duplicate entries + // and miss those items that have this axis rect as clipAxisRect. + QList result; + for (int itemId=0; itemIdmItems.size(); ++itemId) + { + if (mParentPlot->mItems.at(itemId)->clipAxisRect() == this) + { + result.append(mParentPlot->mItems.at(itemId)); + continue; + } + QList positions = mParentPlot->mItems.at(itemId)->positions(); + for (int posId=0; posIdaxisRect() == this || + positions.at(posId)->keyAxis()->axisRect() == this || + positions.at(posId)->valueAxis()->axisRect() == this) + { + result.append(mParentPlot->mItems.at(itemId)); + break; + } + } + } + return result; } /*! @@ -12148,52 +12140,52 @@ QList QCPAxisRect::it */ void QCPAxisRect::update(UpdatePhase phase) { - QCPLayoutElement::update(phase); - - switch (phase) + QCPLayoutElement::update(phase); + + switch (phase) { case upPreparation: - { + { QList allAxes = axes(); for (int i=0; isetupTickVectors(); - break; - } + allAxes.at(i)->setupTickVectors(); + break; + } case upLayout: - { + { mInsetLayout->setOuterRect(rect()); break; - } + } default: break; } - - // pass update call on to inset layout (doesn't happen automatically, because QCPAxisRect doesn't derive from QCPLayout): - mInsetLayout->update(phase); + + // pass update call on to inset layout (doesn't happen automatically, because QCPAxisRect doesn't derive from QCPLayout): + mInsetLayout->update(phase); } /* inherits documentation from base class */ QList QCPAxisRect::elements(bool recursive) const { - QList result; - if (mInsetLayout) - { - result << mInsetLayout; - if (recursive) - result << mInsetLayout->elements(recursive); - } - return result; + QList result; + if (mInsetLayout) + { + result << mInsetLayout; + if (recursive) + result << mInsetLayout->elements(recursive); + } + return result; } /* inherits documentation from base class */ void QCPAxisRect::applyDefaultAntialiasingHint(QCPPainter *painter) const { - painter->setAntialiasing(false); + painter->setAntialiasing(false); } /* inherits documentation from base class */ void QCPAxisRect::draw(QCPPainter *painter) { - drawBackground(painter); + drawBackground(painter); } /*! @@ -12213,8 +12205,8 @@ void QCPAxisRect::draw(QCPPainter *paint */ void QCPAxisRect::setBackground(const QPixmap &pm) { - mBackgroundPixmap = pm; - mScaledBackgroundPixmap = QPixmap(); + mBackgroundPixmap = pm; + mScaledBackgroundPixmap = QPixmap(); } /*! \overload @@ -12232,7 +12224,7 @@ void QCPAxisRect::setBackground(const QP */ void QCPAxisRect::setBackground(const QBrush &brush) { - mBackgroundBrush = brush; + mBackgroundBrush = brush; } /*! \overload @@ -12244,10 +12236,10 @@ void QCPAxisRect::setBackground(const QB */ void QCPAxisRect::setBackground(const QPixmap &pm, bool scaled, Qt::AspectRatioMode mode) { - mBackgroundPixmap = pm; - mScaledBackgroundPixmap = QPixmap(); - mBackgroundScaled = scaled; - mBackgroundScaledMode = mode; + mBackgroundPixmap = pm; + mScaledBackgroundPixmap = QPixmap(); + mBackgroundScaled = scaled; + mBackgroundScaledMode = mode; } /*! @@ -12262,7 +12254,7 @@ void QCPAxisRect::setBackground(const QP */ void QCPAxisRect::setBackgroundScaled(bool scaled) { - mBackgroundScaled = scaled; + mBackgroundScaled = scaled; } /*! @@ -12272,7 +12264,7 @@ void QCPAxisRect::setBackgroundScaled(bo */ void QCPAxisRect::setBackgroundScaledMode(Qt::AspectRatioMode mode) { - mBackgroundScaledMode = mode; + mBackgroundScaledMode = mode; } /*! @@ -12282,7 +12274,7 @@ void QCPAxisRect::setBackgroundScaledMod */ QCPAxis *QCPAxisRect::rangeDragAxis(Qt::Orientation orientation) { - return (orientation == Qt::Horizontal ? mRangeDragHorzAxis.data() : mRangeDragVertAxis.data()); + return (orientation == Qt::Horizontal ? mRangeDragHorzAxis.data() : mRangeDragVertAxis.data()); } /*! @@ -12292,7 +12284,7 @@ QCPAxis *QCPAxisRect::rangeDragAxis(Qt:: */ QCPAxis *QCPAxisRect::rangeZoomAxis(Qt::Orientation orientation) { - return (orientation == Qt::Horizontal ? mRangeZoomHorzAxis.data() : mRangeZoomVertAxis.data()); + return (orientation == Qt::Horizontal ? mRangeZoomHorzAxis.data() : mRangeZoomVertAxis.data()); } /*! @@ -12302,7 +12294,7 @@ QCPAxis *QCPAxisRect::rangeZoomAxis(Qt:: */ double QCPAxisRect::rangeZoomFactor(Qt::Orientation orientation) { - return (orientation == Qt::Horizontal ? mRangeZoomFactorHorz : mRangeZoomFactorVert); + return (orientation == Qt::Horizontal ? mRangeZoomFactorHorz : mRangeZoomFactorVert); } /*! @@ -12323,7 +12315,7 @@ double QCPAxisRect::rangeZoomFactor(Qt:: */ void QCPAxisRect::setRangeDrag(Qt::Orientations orientations) { - mRangeDrag = orientations; + mRangeDrag = orientations; } /*! @@ -12343,7 +12335,7 @@ void QCPAxisRect::setRangeDrag(Qt::Orien */ void QCPAxisRect::setRangeZoom(Qt::Orientations orientations) { - mRangeZoom = orientations; + mRangeZoom = orientations; } /*! @@ -12354,8 +12346,8 @@ void QCPAxisRect::setRangeZoom(Qt::Orien */ void QCPAxisRect::setRangeDragAxes(QCPAxis *horizontal, QCPAxis *vertical) { - mRangeDragHorzAxis = horizontal; - mRangeDragVertAxis = vertical; + mRangeDragHorzAxis = horizontal; + mRangeDragVertAxis = vertical; } /*! @@ -12367,8 +12359,8 @@ void QCPAxisRect::setRangeDragAxes(QCPAx */ void QCPAxisRect::setRangeZoomAxes(QCPAxis *horizontal, QCPAxis *vertical) { - mRangeZoomHorzAxis = horizontal; - mRangeZoomVertAxis = vertical; + mRangeZoomHorzAxis = horizontal; + mRangeZoomVertAxis = vertical; } /*! @@ -12383,8 +12375,8 @@ void QCPAxisRect::setRangeZoomAxes(QCPAx */ void QCPAxisRect::setRangeZoomFactor(double horizontalFactor, double verticalFactor) { - mRangeZoomFactorHorz = horizontalFactor; - mRangeZoomFactorVert = verticalFactor; + mRangeZoomFactorHorz = horizontalFactor; + mRangeZoomFactorVert = verticalFactor; } /*! \overload @@ -12393,8 +12385,8 @@ void QCPAxisRect::setRangeZoomFactor(dou */ void QCPAxisRect::setRangeZoomFactor(double factor) { - mRangeZoomFactorHorz = factor; - mRangeZoomFactorVert = factor; + mRangeZoomFactorHorz = factor; + mRangeZoomFactorVert = factor; } /*! \internal @@ -12417,24 +12409,24 @@ void QCPAxisRect::setRangeZoomFactor(dou */ void QCPAxisRect::drawBackground(QCPPainter *painter) { - // draw background fill: - if (mBackgroundBrush != Qt::NoBrush) - painter->fillRect(mRect, mBackgroundBrush); - - // draw background pixmap (on top of fill, if brush specified): - if (!mBackgroundPixmap.isNull()) - { - if (mBackgroundScaled) - { - // check whether mScaledBackground needs to be updated: - QSize scaledSize(mBackgroundPixmap.size()); - scaledSize.scale(mRect.size(), mBackgroundScaledMode); - if (mScaledBackgroundPixmap.size() != scaledSize) - mScaledBackgroundPixmap = mBackgroundPixmap.scaled(mRect.size(), mBackgroundScaledMode, Qt::SmoothTransformation); - painter->drawPixmap(mRect.topLeft(), mScaledBackgroundPixmap, QRect(0, 0, mRect.width(), mRect.height()) & mScaledBackgroundPixmap.rect()); + // draw background fill: + if (mBackgroundBrush != Qt::NoBrush) + painter->fillRect(mRect, mBackgroundBrush); + + // draw background pixmap (on top of fill, if brush specified): + if (!mBackgroundPixmap.isNull()) + { + if (mBackgroundScaled) + { + // check whether mScaledBackground needs to be updated: + QSize scaledSize(mBackgroundPixmap.size()); + scaledSize.scale(mRect.size(), mBackgroundScaledMode); + if (mScaledBackgroundPixmap.size() != scaledSize) + mScaledBackgroundPixmap = mBackgroundPixmap.scaled(mRect.size(), mBackgroundScaledMode, Qt::SmoothTransformation); + painter->drawPixmap(mRect.topLeft(), mScaledBackgroundPixmap, QRect(0, 0, mRect.width(), mRect.height()) & mScaledBackgroundPixmap.rect()); } else { - painter->drawPixmap(mRect.topLeft(), mBackgroundPixmap, QRect(0, 0, mRect.width(), mRect.height())); + painter->drawPixmap(mRect.topLeft(), mBackgroundPixmap, QRect(0, 0, mRect.width(), mRect.height())); } } } @@ -12451,38 +12443,38 @@ void QCPAxisRect::drawBackground(QCPPain */ void QCPAxisRect::updateAxesOffset(QCPAxis::AxisType type) { - const QList axesList = mAxes.value(type); - if (axesList.isEmpty()) - return; - - bool isFirstVisible = !axesList.first()->visible(); // if the first axis is visible, the second axis (which is where the loop starts) isn't the first visible axis, so initialize with false - for (int i=1; ioffset() + axesList.at(i-1)->calculateMargin(); - if (axesList.at(i)->visible()) // only add inner tick length to offset if this axis is visible and it's not the first visible one (might happen if true first axis is invisible) - { - if (!isFirstVisible) - offset += axesList.at(i)->tickLengthIn(); - isFirstVisible = false; - } - axesList.at(i)->setOffset(offset); + const QList axesList = mAxes.value(type); + if (axesList.isEmpty()) + return; + + bool isFirstVisible = !axesList.first()->visible(); // if the first axis is visible, the second axis (which is where the loop starts) isn't the first visible axis, so initialize with false + for (int i=1; ioffset() + axesList.at(i-1)->calculateMargin(); + if (axesList.at(i)->visible()) // only add inner tick length to offset if this axis is visible and it's not the first visible one (might happen if true first axis is invisible) + { + if (!isFirstVisible) + offset += axesList.at(i)->tickLengthIn(); + isFirstVisible = false; + } + axesList.at(i)->setOffset(offset); } } /* inherits documentation from base class */ int QCPAxisRect::calculateAutoMargin(QCP::MarginSide side) { - if (!mAutoMargins.testFlag(side)) - qDebug() << Q_FUNC_INFO << "Called with side that isn't specified as auto margin"; - - updateAxesOffset(QCPAxis::marginSideToAxisType(side)); - - // note: only need to look at the last (outer most) axis to determine the total margin, due to updateAxisOffset call - const QList axesList = mAxes.value(QCPAxis::marginSideToAxisType(side)); - if (axesList.size() > 0) - return axesList.last()->offset() + axesList.last()->calculateMargin(); - else - return 0; + if (!mAutoMargins.testFlag(side)) + qDebug() << Q_FUNC_INFO << "Called with side that isn't specified as auto margin"; + + updateAxesOffset(QCPAxis::marginSideToAxisType(side)); + + // note: only need to look at the last (outer most) axis to determine the total margin, due to updateAxisOffset call + const QList axesList = mAxes.value(QCPAxis::marginSideToAxisType(side)); + if (axesList.size() > 0) + return axesList.last()->offset() + axesList.last()->calculateMargin(); + else + return 0; } /*! \internal @@ -12498,23 +12490,23 @@ int QCPAxisRect::calculateAutoMargin(QCP */ void QCPAxisRect::mousePressEvent(QMouseEvent *event) { - mDragStart = event->pos(); // need this even when not LeftButton is pressed, to determine in releaseEvent whether it was a full click (no position change between press and release) - if (event->buttons() & Qt::LeftButton) - { - mDragging = true; - // initialize antialiasing backup in case we start dragging: - if (mParentPlot->noAntialiasingOnDrag()) - { - mAADragBackup = mParentPlot->antialiasedElements(); - mNotAADragBackup = mParentPlot->notAntialiasedElements(); - } - // Mouse range dragging interaction: - if (mParentPlot->interactions().testFlag(QCP::iRangeDrag)) - { - if (mRangeDragHorzAxis) - mDragStartHorzRange = mRangeDragHorzAxis.data()->range(); - if (mRangeDragVertAxis) - mDragStartVertRange = mRangeDragVertAxis.data()->range(); + mDragStart = event->pos(); // need this even when not LeftButton is pressed, to determine in releaseEvent whether it was a full click (no position change between press and release) + if (event->buttons() & Qt::LeftButton) + { + mDragging = true; + // initialize antialiasing backup in case we start dragging: + if (mParentPlot->noAntialiasingOnDrag()) + { + mAADragBackup = mParentPlot->antialiasedElements(); + mNotAADragBackup = mParentPlot->notAntialiasedElements(); + } + // Mouse range dragging interaction: + if (mParentPlot->interactions().testFlag(QCP::iRangeDrag)) + { + if (mRangeDragHorzAxis) + mDragStartHorzRange = mRangeDragHorzAxis.data()->range(); + if (mRangeDragVertAxis) + mDragStartVertRange = mRangeDragVertAxis.data()->range(); } } } @@ -12528,44 +12520,44 @@ void QCPAxisRect::mousePressEvent(QMouse */ void QCPAxisRect::mouseMoveEvent(QMouseEvent *event) { - // Mouse range dragging interaction: - if (mDragging && mParentPlot->interactions().testFlag(QCP::iRangeDrag)) - { - if (mRangeDrag.testFlag(Qt::Horizontal)) - { - if (QCPAxis *rangeDragHorzAxis = mRangeDragHorzAxis.data()) - { - if (rangeDragHorzAxis->mScaleType == QCPAxis::stLinear) + // Mouse range dragging interaction: + if (mDragging && mParentPlot->interactions().testFlag(QCP::iRangeDrag)) + { + if (mRangeDrag.testFlag(Qt::Horizontal)) + { + if (QCPAxis *rangeDragHorzAxis = mRangeDragHorzAxis.data()) + { + if (rangeDragHorzAxis->mScaleType == QCPAxis::stLinear) { - double diff = rangeDragHorzAxis->pixelToCoord(mDragStart.x()) - rangeDragHorzAxis->pixelToCoord(event->pos().x()); - rangeDragHorzAxis->setRange(mDragStartHorzRange.lower+diff, mDragStartHorzRange.upper+diff); + double diff = rangeDragHorzAxis->pixelToCoord(mDragStart.x()) - rangeDragHorzAxis->pixelToCoord(event->pos().x()); + rangeDragHorzAxis->setRange(mDragStartHorzRange.lower+diff, mDragStartHorzRange.upper+diff); } else if (rangeDragHorzAxis->mScaleType == QCPAxis::stLogarithmic) { - double diff = rangeDragHorzAxis->pixelToCoord(mDragStart.x()) / rangeDragHorzAxis->pixelToCoord(event->pos().x()); - rangeDragHorzAxis->setRange(mDragStartHorzRange.lower*diff, mDragStartHorzRange.upper*diff); + double diff = rangeDragHorzAxis->pixelToCoord(mDragStart.x()) / rangeDragHorzAxis->pixelToCoord(event->pos().x()); + rangeDragHorzAxis->setRange(mDragStartHorzRange.lower*diff, mDragStartHorzRange.upper*diff); } } } - if (mRangeDrag.testFlag(Qt::Vertical)) - { - if (QCPAxis *rangeDragVertAxis = mRangeDragVertAxis.data()) - { - if (rangeDragVertAxis->mScaleType == QCPAxis::stLinear) + if (mRangeDrag.testFlag(Qt::Vertical)) + { + if (QCPAxis *rangeDragVertAxis = mRangeDragVertAxis.data()) + { + if (rangeDragVertAxis->mScaleType == QCPAxis::stLinear) { - double diff = rangeDragVertAxis->pixelToCoord(mDragStart.y()) - rangeDragVertAxis->pixelToCoord(event->pos().y()); - rangeDragVertAxis->setRange(mDragStartVertRange.lower+diff, mDragStartVertRange.upper+diff); + double diff = rangeDragVertAxis->pixelToCoord(mDragStart.y()) - rangeDragVertAxis->pixelToCoord(event->pos().y()); + rangeDragVertAxis->setRange(mDragStartVertRange.lower+diff, mDragStartVertRange.upper+diff); } else if (rangeDragVertAxis->mScaleType == QCPAxis::stLogarithmic) { - double diff = rangeDragVertAxis->pixelToCoord(mDragStart.y()) / rangeDragVertAxis->pixelToCoord(event->pos().y()); - rangeDragVertAxis->setRange(mDragStartVertRange.lower*diff, mDragStartVertRange.upper*diff); + double diff = rangeDragVertAxis->pixelToCoord(mDragStart.y()) / rangeDragVertAxis->pixelToCoord(event->pos().y()); + rangeDragVertAxis->setRange(mDragStartVertRange.lower*diff, mDragStartVertRange.upper*diff); } } } - if (mRangeDrag != 0) // if either vertical or horizontal drag was enabled, do a replot - { - if (mParentPlot->noAntialiasingOnDrag()) - mParentPlot->setNotAntialiasedElements(QCP::aeAll); - mParentPlot->replot(); + if (mRangeDrag != 0) // if either vertical or horizontal drag was enabled, do a replot + { + if (mParentPlot->noAntialiasingOnDrag()) + mParentPlot->setNotAntialiasedElements(QCP::aeAll); + mParentPlot->replot(); } } } @@ -12573,12 +12565,12 @@ void QCPAxisRect::mouseMoveEvent(QMouseE /* inherits documentation from base class */ void QCPAxisRect::mouseReleaseEvent(QMouseEvent *event) { - Q_UNUSED(event) - mDragging = false; - if (mParentPlot->noAntialiasingOnDrag()) - { - mParentPlot->setAntialiasedElements(mAADragBackup); - mParentPlot->setNotAntialiasedElements(mNotAADragBackup); + Q_UNUSED(event) + mDragging = false; + if (mParentPlot->noAntialiasingOnDrag()) + { + mParentPlot->setAntialiasedElements(mAADragBackup); + mParentPlot->setNotAntialiasedElements(mNotAADragBackup); } } @@ -12598,26 +12590,26 @@ void QCPAxisRect::mouseReleaseEvent(QMou */ void QCPAxisRect::wheelEvent(QWheelEvent *event) { - // Mouse range zooming interaction: - if (mParentPlot->interactions().testFlag(QCP::iRangeZoom)) - { - if (mRangeZoom != 0) - { - double factor; - double wheelSteps = event->delta()/120.0; // a single step delta is +/-120 usually - if (mRangeZoom.testFlag(Qt::Horizontal)) - { - factor = qPow(mRangeZoomFactorHorz, wheelSteps); - if (mRangeZoomHorzAxis.data()) - mRangeZoomHorzAxis.data()->scaleRange(factor, mRangeZoomHorzAxis.data()->pixelToCoord(event->pos().x())); - } - if (mRangeZoom.testFlag(Qt::Vertical)) - { - factor = qPow(mRangeZoomFactorVert, wheelSteps); - if (mRangeZoomVertAxis.data()) - mRangeZoomVertAxis.data()->scaleRange(factor, mRangeZoomVertAxis.data()->pixelToCoord(event->pos().y())); - } - mParentPlot->replot(); + // Mouse range zooming interaction: + if (mParentPlot->interactions().testFlag(QCP::iRangeZoom)) + { + if (mRangeZoom != 0) + { + double factor; + double wheelSteps = event->delta()/120.0; // a single step delta is +/-120 usually + if (mRangeZoom.testFlag(Qt::Horizontal)) + { + factor = qPow(mRangeZoomFactorHorz, wheelSteps); + if (mRangeZoomHorzAxis.data()) + mRangeZoomHorzAxis.data()->scaleRange(factor, mRangeZoomHorzAxis.data()->pixelToCoord(event->pos().x())); + } + if (mRangeZoom.testFlag(Qt::Vertical)) + { + factor = qPow(mRangeZoomFactorVert, wheelSteps); + if (mRangeZoomVertAxis.data()) + mRangeZoomVertAxis.data()->scaleRange(factor, mRangeZoomVertAxis.data()->pixelToCoord(event->pos().y())); + } + mParentPlot->replot(); } } } @@ -12666,17 +12658,17 @@ void QCPAxisRect::wheelEvent(QWheelEvent cause the item to be added to \a parent, so \ref QCPLegend::addItem must be called separately. */ QCPAbstractLegendItem::QCPAbstractLegendItem(QCPLegend *parent) : - QCPLayoutElement(parent->parentPlot()), - mParentLegend(parent), - mFont(parent->font()), - mTextColor(parent->textColor()), - mSelectedFont(parent->selectedFont()), - mSelectedTextColor(parent->selectedTextColor()), - mSelectable(true), - mSelected(false) -{ - setLayer(QLatin1String("legend")); - setMargins(QMargins(8, 2, 8, 2)); + QCPLayoutElement(parent->parentPlot()), + mParentLegend(parent), + mFont(parent->font()), + mTextColor(parent->textColor()), + mSelectedFont(parent->selectedFont()), + mSelectedTextColor(parent->selectedTextColor()), + mSelectable(true), + mSelected(false) +{ + setLayer(QLatin1String("legend")); + setMargins(QMargins(8, 2, 8, 2)); } /*! @@ -12686,7 +12678,7 @@ QCPAbstractLegendItem::QCPAbstractLegend */ void QCPAbstractLegendItem::setFont(const QFont &font) { - mFont = font; + mFont = font; } /*! @@ -12696,7 +12688,7 @@ void QCPAbstractLegendItem::setFont(cons */ void QCPAbstractLegendItem::setTextColor(const QColor &color) { - mTextColor = color; + mTextColor = color; } /*! @@ -12707,7 +12699,7 @@ void QCPAbstractLegendItem::setTextColor */ void QCPAbstractLegendItem::setSelectedFont(const QFont &font) { - mSelectedFont = font; + mSelectedFont = font; } /*! @@ -12718,7 +12710,7 @@ void QCPAbstractLegendItem::setSelectedF */ void QCPAbstractLegendItem::setSelectedTextColor(const QColor &color) { - mSelectedTextColor = color; + mSelectedTextColor = color; } /*! @@ -12728,10 +12720,10 @@ void QCPAbstractLegendItem::setSelectedT */ void QCPAbstractLegendItem::setSelectable(bool selectable) { - if (mSelectable != selectable) - { - mSelectable = selectable; - emit selectableChanged(mSelectable); + if (mSelectable != selectable) + { + mSelectable = selectable; + emit selectableChanged(mSelectable); } } @@ -12745,62 +12737,62 @@ void QCPAbstractLegendItem::setSelectabl */ void QCPAbstractLegendItem::setSelected(bool selected) { - if (mSelected != selected) - { - mSelected = selected; - emit selectionChanged(mSelected); + if (mSelected != selected) + { + mSelected = selected; + emit selectionChanged(mSelected); } } /* inherits documentation from base class */ double QCPAbstractLegendItem::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - Q_UNUSED(details) - if (!mParentPlot) return -1; - if (onlySelectable && (!mSelectable || !mParentLegend->selectableParts().testFlag(QCPLegend::spItems))) - return -1; - - if (mRect.contains(pos.toPoint())) - return mParentPlot->selectionTolerance()*0.99; - else - return -1; + Q_UNUSED(details) + if (!mParentPlot) return -1; + if (onlySelectable && (!mSelectable || !mParentLegend->selectableParts().testFlag(QCPLegend::spItems))) + return -1; + + if (mRect.contains(pos.toPoint())) + return mParentPlot->selectionTolerance()*0.99; + else + return -1; } /* inherits documentation from base class */ void QCPAbstractLegendItem::applyDefaultAntialiasingHint(QCPPainter *painter) const { - applyAntialiasingHint(painter, mAntialiased, QCP::aeLegendItems); + applyAntialiasingHint(painter, mAntialiased, QCP::aeLegendItems); } /* inherits documentation from base class */ QRect QCPAbstractLegendItem::clipRect() const { - return mOuterRect; + return mOuterRect; } /* inherits documentation from base class */ void QCPAbstractLegendItem::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) { - Q_UNUSED(event) - Q_UNUSED(details) - if (mSelectable && mParentLegend->selectableParts().testFlag(QCPLegend::spItems)) - { - bool selBefore = mSelected; - setSelected(additive ? !mSelected : true); - if (selectionStateChanged) - *selectionStateChanged = mSelected != selBefore; + Q_UNUSED(event) + Q_UNUSED(details) + if (mSelectable && mParentLegend->selectableParts().testFlag(QCPLegend::spItems)) + { + bool selBefore = mSelected; + setSelected(additive ? !mSelected : true); + if (selectionStateChanged) + *selectionStateChanged = mSelected != selBefore; } } /* inherits documentation from base class */ void QCPAbstractLegendItem::deselectEvent(bool *selectionStateChanged) { - if (mSelectable && mParentLegend->selectableParts().testFlag(QCPLegend::spItems)) - { - bool selBefore = mSelected; - setSelected(false); - if (selectionStateChanged) - *selectionStateChanged = mSelected != selBefore; + if (mSelectable && mParentLegend->selectableParts().testFlag(QCPLegend::spItems)) + { + bool selBefore = mSelected; + setSelected(false); + if (selectionStateChanged) + *selectionStateChanged = mSelected != selBefore; } } @@ -12842,8 +12834,8 @@ void QCPAbstractLegendItem::deselectEven QCPAbstractPlottable::addToLegend and \ref QCPAbstractPlottable::removeFromLegend. */ QCPPlottableLegendItem::QCPPlottableLegendItem(QCPLegend *parent, QCPAbstractPlottable *plottable) : - QCPAbstractLegendItem(parent), - mPlottable(plottable) + QCPAbstractLegendItem(parent), + mPlottable(plottable) { } @@ -12854,7 +12846,7 @@ QCPPlottableLegendItem::QCPPlottableLege */ QPen QCPPlottableLegendItem::getIconBorderPen() const { - return mSelected ? mParentLegend->selectedIconBorderPen() : mParentLegend->iconBorderPen(); + return mSelected ? mParentLegend->selectedIconBorderPen() : mParentLegend->iconBorderPen(); } /*! \internal @@ -12864,7 +12856,7 @@ QPen QCPPlottableLegendItem::getIconBord */ QColor QCPPlottableLegendItem::getTextColor() const { - return mSelected ? mSelectedTextColor : mTextColor; + return mSelected ? mSelectedTextColor : mTextColor; } /*! \internal @@ -12874,7 +12866,7 @@ QColor QCPPlottableLegendItem::getTextCo */ QFont QCPPlottableLegendItem::getFont() const { - return mSelected ? mSelectedFont : mFont; + return mSelected ? mSelectedFont : mFont; } /*! \internal @@ -12885,25 +12877,25 @@ QFont QCPPlottableLegendItem::getFont() */ void QCPPlottableLegendItem::draw(QCPPainter *painter) { - if (!mPlottable) return; - painter->setFont(getFont()); - painter->setPen(QPen(getTextColor())); - QSizeF iconSize = mParentLegend->iconSize(); - QRectF textRect = painter->fontMetrics().boundingRect(0, 0, 0, iconSize.height(), Qt::TextDontClip, mPlottable->name()); - QRectF iconRect(mRect.topLeft(), iconSize); - int textHeight = qMax(textRect.height(), iconSize.height()); // if text has smaller height than icon, center text vertically in icon height, else align tops - painter->drawText(mRect.x()+iconSize.width()+mParentLegend->iconTextPadding(), mRect.y(), textRect.width(), textHeight, Qt::TextDontClip, mPlottable->name()); - // draw icon: - painter->save(); - painter->setClipRect(iconRect, Qt::IntersectClip); - mPlottable->drawLegendIcon(painter, iconRect); - painter->restore(); - // draw icon border: - if (getIconBorderPen().style() != Qt::NoPen) - { - painter->setPen(getIconBorderPen()); - painter->setBrush(Qt::NoBrush); - painter->drawRect(iconRect); + if (!mPlottable) return; + painter->setFont(getFont()); + painter->setPen(QPen(getTextColor())); + QSizeF iconSize = mParentLegend->iconSize(); + QRectF textRect = painter->fontMetrics().boundingRect(0, 0, 0, iconSize.height(), Qt::TextDontClip, mPlottable->name()); + QRectF iconRect(mRect.topLeft(), iconSize); + int textHeight = qMax(textRect.height(), iconSize.height()); // if text has smaller height than icon, center text vertically in icon height, else align tops + painter->drawText(mRect.x()+iconSize.width()+mParentLegend->iconTextPadding(), mRect.y(), textRect.width(), textHeight, Qt::TextDontClip, mPlottable->name()); + // draw icon: + painter->save(); + painter->setClipRect(iconRect, Qt::IntersectClip); + mPlottable->drawLegendIcon(painter, iconRect); + painter->restore(); + // draw icon border: + if (getIconBorderPen().style() != Qt::NoPen) + { + painter->setPen(getIconBorderPen()); + painter->setBrush(Qt::NoBrush); + painter->drawRect(iconRect); } } @@ -12914,15 +12906,15 @@ void QCPPlottableLegendItem::draw(QCPPai */ QSize QCPPlottableLegendItem::minimumSizeHint() const { - if (!mPlottable) return QSize(); - QSize result(0, 0); - QRect textRect; - QFontMetrics fontMetrics(getFont()); - QSize iconSize = mParentLegend->iconSize(); - textRect = fontMetrics.boundingRect(0, 0, 0, iconSize.height(), Qt::TextDontClip, mPlottable->name()); - result.setWidth(iconSize.width() + mParentLegend->iconTextPadding() + textRect.width() + mMargins.left() + mMargins.right()); - result.setHeight(qMax(textRect.height(), iconSize.height()) + mMargins.top() + mMargins.bottom()); - return result; + if (!mPlottable) return QSize(); + QSize result(0, 0); + QRect textRect; + QFontMetrics fontMetrics(getFont()); + QSize iconSize = mParentLegend->iconSize(); + textRect = fontMetrics.boundingRect(0, 0, 0, iconSize.height(), Qt::TextDontClip, mPlottable->name()); + result.setWidth(iconSize.width() + mParentLegend->iconTextPadding() + textRect.width() + mMargins.left() + mMargins.right()); + result.setHeight(qMax(textRect.height(), iconSize.height()) + mMargins.top() + mMargins.bottom()); + return result; } @@ -12973,51 +12965,51 @@ QSize QCPPlottableLegendItem::minimumSiz */ QCPLegend::QCPLegend() { - setRowSpacing(0); - setColumnSpacing(10); - setMargins(QMargins(2, 3, 2, 2)); - setAntialiased(false); - setIconSize(32, 18); - - setIconTextPadding(7); - - setSelectableParts(spLegendBox | spItems); - setSelectedParts(spNone); - - setBorderPen(QPen(Qt::black)); - setSelectedBorderPen(QPen(Qt::blue, 2)); - setIconBorderPen(Qt::NoPen); - setSelectedIconBorderPen(QPen(Qt::blue, 2)); - setBrush(Qt::white); - setSelectedBrush(Qt::white); - setTextColor(Qt::black); - setSelectedTextColor(Qt::blue); + setRowSpacing(0); + setColumnSpacing(10); + setMargins(QMargins(2, 3, 2, 2)); + setAntialiased(false); + setIconSize(32, 18); + + setIconTextPadding(7); + + setSelectableParts(spLegendBox | spItems); + setSelectedParts(spNone); + + setBorderPen(QPen(Qt::black)); + setSelectedBorderPen(QPen(Qt::blue, 2)); + setIconBorderPen(Qt::NoPen); + setSelectedIconBorderPen(QPen(Qt::blue, 2)); + setBrush(Qt::white); + setSelectedBrush(Qt::white); + setTextColor(Qt::black); + setSelectedTextColor(Qt::blue); } QCPLegend::~QCPLegend() { - clearItems(); - if (qobject_cast(mParentPlot)) // make sure this isn't called from QObject dtor when QCustomPlot is already destructed (happens when the legend is not in any layout and thus QObject-child of QCustomPlot) - mParentPlot->legendRemoved(this); + clearItems(); + if (qobject_cast(mParentPlot)) // make sure this isn't called from QObject dtor when QCustomPlot is already destructed (happens when the legend is not in any layout and thus QObject-child of QCustomPlot) + mParentPlot->legendRemoved(this); } /* no doc for getter, see setSelectedParts */ QCPLegend::SelectableParts QCPLegend::selectedParts() const { - // check whether any legend elements selected, if yes, add spItems to return value - bool hasSelectedItems = false; - for (int i=0; iselected()) - { - hasSelectedItems = true; - break; - } - } - if (hasSelectedItems) - return mSelectedParts | spItems; - else - return mSelectedParts & ~spItems; + // check whether any legend elements selected, if yes, add spItems to return value + bool hasSelectedItems = false; + for (int i=0; iselected()) + { + hasSelectedItems = true; + break; + } + } + if (hasSelectedItems) + return mSelectedParts | spItems; + else + return mSelectedParts & ~spItems; } /*! @@ -13025,7 +13017,7 @@ QCPLegend::SelectableParts QCPLegend::se */ void QCPLegend::setBorderPen(const QPen &pen) { - mBorderPen = pen; + mBorderPen = pen; } /*! @@ -13033,7 +13025,7 @@ void QCPLegend::setBorderPen(const QPen */ void QCPLegend::setBrush(const QBrush &brush) { - mBrush = brush; + mBrush = brush; } /*! @@ -13047,11 +13039,11 @@ void QCPLegend::setBrush(const QBrush &b */ void QCPLegend::setFont(const QFont &font) { - mFont = font; - for (int i=0; isetFont(mFont); + mFont = font; + for (int i=0; isetFont(mFont); } } @@ -13066,11 +13058,11 @@ void QCPLegend::setFont(const QFont &fon */ void QCPLegend::setTextColor(const QColor &color) { - mTextColor = color; - for (int i=0; isetTextColor(color); + mTextColor = color; + for (int i=0; isetTextColor(color); } } @@ -13080,15 +13072,15 @@ void QCPLegend::setTextColor(const QColo */ void QCPLegend::setIconSize(const QSize &size) { - mIconSize = size; + mIconSize = size; } /*! \overload */ void QCPLegend::setIconSize(int width, int height) { - mIconSize.setWidth(width); - mIconSize.setHeight(height); + mIconSize.setWidth(width); + mIconSize.setHeight(height); } /*! @@ -13098,7 +13090,7 @@ void QCPLegend::setIconSize(int width, i */ void QCPLegend::setIconTextPadding(int padding) { - mIconTextPadding = padding; + mIconTextPadding = padding; } /*! @@ -13109,7 +13101,7 @@ void QCPLegend::setIconTextPadding(int p */ void QCPLegend::setIconBorderPen(const QPen &pen) { - mIconBorderPen = pen; + mIconBorderPen = pen; } /*! @@ -13124,10 +13116,10 @@ void QCPLegend::setIconBorderPen(const Q */ void QCPLegend::setSelectableParts(const SelectableParts &selectable) { - if (mSelectableParts != selectable) - { - mSelectableParts = selectable; - emit selectableChanged(mSelectableParts); + if (mSelectableParts != selectable) + { + mSelectableParts = selectable; + emit selectableChanged(mSelectableParts); } } @@ -13154,26 +13146,26 @@ void QCPLegend::setSelectableParts(const */ void QCPLegend::setSelectedParts(const SelectableParts &selected) { - SelectableParts newSelected = selected; - mSelectedParts = this->selectedParts(); // update mSelectedParts in case item selection changed - - if (mSelectedParts != newSelected) - { - if (!mSelectedParts.testFlag(spItems) && newSelected.testFlag(spItems)) // attempt to set spItems flag (can't do that) - { - qDebug() << Q_FUNC_INFO << "spItems flag can not be set, it can only be unset with this function"; - newSelected &= ~spItems; - } - if (mSelectedParts.testFlag(spItems) && !newSelected.testFlag(spItems)) // spItems flag was unset, so clear item selection - { - for (int i=0; isetSelected(false); - } - } - mSelectedParts = newSelected; - emit selectionChanged(mSelectedParts); + SelectableParts newSelected = selected; + mSelectedParts = this->selectedParts(); // update mSelectedParts in case item selection changed + + if (mSelectedParts != newSelected) + { + if (!mSelectedParts.testFlag(spItems) && newSelected.testFlag(spItems)) // attempt to set spItems flag (can't do that) + { + qDebug() << Q_FUNC_INFO << "spItems flag can not be set, it can only be unset with this function"; + newSelected &= ~spItems; + } + if (mSelectedParts.testFlag(spItems) && !newSelected.testFlag(spItems)) // spItems flag was unset, so clear item selection + { + for (int i=0; isetSelected(false); + } + } + mSelectedParts = newSelected; + emit selectionChanged(mSelectedParts); } } @@ -13185,7 +13177,7 @@ void QCPLegend::setSelectedParts(const S */ void QCPLegend::setSelectedBorderPen(const QPen &pen) { - mSelectedBorderPen = pen; + mSelectedBorderPen = pen; } /*! @@ -13195,7 +13187,7 @@ void QCPLegend::setSelectedBorderPen(con */ void QCPLegend::setSelectedIconBorderPen(const QPen &pen) { - mSelectedIconBorderPen = pen; + mSelectedIconBorderPen = pen; } /*! @@ -13206,7 +13198,7 @@ void QCPLegend::setSelectedIconBorderPen */ void QCPLegend::setSelectedBrush(const QBrush &brush) { - mSelectedBrush = brush; + mSelectedBrush = brush; } /*! @@ -13218,11 +13210,11 @@ void QCPLegend::setSelectedBrush(const Q */ void QCPLegend::setSelectedFont(const QFont &font) { - mSelectedFont = font; - for (int i=0; isetSelectedFont(font); + mSelectedFont = font; + for (int i=0; isetSelectedFont(font); } } @@ -13235,11 +13227,11 @@ void QCPLegend::setSelectedFont(const QF */ void QCPLegend::setSelectedTextColor(const QColor &color) { - mSelectedTextColor = color; - for (int i=0; isetSelectedTextColor(color); + mSelectedTextColor = color; + for (int i=0; isetSelectedTextColor(color); } } @@ -13250,7 +13242,7 @@ void QCPLegend::setSelectedTextColor(con */ QCPAbstractLegendItem *QCPLegend::item(int index) const { - return qobject_cast(elementAt(index)); + return qobject_cast(elementAt(index)); } /*! @@ -13261,15 +13253,15 @@ QCPAbstractLegendItem *QCPLegend::item(i */ QCPPlottableLegendItem *QCPLegend::itemWithPlottable(const QCPAbstractPlottable *plottable) const { - for (int i=0; i(item(i))) - { - if (pli->plottable() == plottable) - return pli; - } - } - return 0; + for (int i=0; i(item(i))) + { + if (pli->plottable() == plottable) + return pli; + } + } + return 0; } /*! @@ -13278,7 +13270,7 @@ QCPPlottableLegendItem *QCPLegend::itemW */ int QCPLegend::itemCount() const { - return elementCount(); + return elementCount(); } /*! @@ -13286,12 +13278,12 @@ int QCPLegend::itemCount() const */ bool QCPLegend::hasItem(QCPAbstractLegendItem *item) const { - for (int i=0; iitem(i)) - return true; - } - return false; + for (int i=0; iitem(i)) + return true; + } + return false; } /*! @@ -13302,7 +13294,7 @@ bool QCPLegend::hasItem(QCPAbstractLegen */ bool QCPLegend::hasItemWithPlottable(const QCPAbstractPlottable *plottable) const { - return itemWithPlottable(plottable); + return itemWithPlottable(plottable); } /*! @@ -13314,11 +13306,11 @@ bool QCPLegend::hasItemWithPlottable(con */ bool QCPLegend::addItem(QCPAbstractLegendItem *item) { - if (!hasItem(item)) - { - return addElement(rowCount(), 0, item); - } else - return false; + if (!hasItem(item)) + { + return addElement(rowCount(), 0, item); + } else + return false; } /*! @@ -13330,13 +13322,13 @@ bool QCPLegend::addItem(QCPAbstractLegen */ bool QCPLegend::removeItem(int index) { - if (QCPAbstractLegendItem *ali = item(index)) - { - bool success = remove(ali); - simplify(); - return success; - } else - return false; + if (QCPAbstractLegendItem *ali = item(index)) + { + bool success = remove(ali); + simplify(); + return success; + } else + return false; } /*! \overload @@ -13349,9 +13341,9 @@ bool QCPLegend::removeItem(int index) */ bool QCPLegend::removeItem(QCPAbstractLegendItem *item) { - bool success = remove(item); - simplify(); - return success; + bool success = remove(item); + simplify(); + return success; } /*! @@ -13359,8 +13351,8 @@ bool QCPLegend::removeItem(QCPAbstractLe */ void QCPLegend::clearItems() { - for (int i=itemCount()-1; i>=0; --i) - removeItem(i); + for (int i=itemCount()-1; i>=0; --i) + removeItem(i); } /*! @@ -13371,16 +13363,16 @@ void QCPLegend::clearItems() */ QList QCPLegend::selectedItems() const { - QList result; - for (int i=0; iselected()) - result.append(ali); - } - } - return result; + QList result; + for (int i=0; iselected()) + result.append(ali); + } + } + return result; } /*! \internal @@ -13398,7 +13390,7 @@ QList QCPLegend */ void QCPLegend::applyDefaultAntialiasingHint(QCPPainter *painter) const { - applyAntialiasingHint(painter, mAntialiased, QCP::aeLegend); + applyAntialiasingHint(painter, mAntialiased, QCP::aeLegend); } /*! \internal @@ -13408,7 +13400,7 @@ void QCPLegend::applyDefaultAntialiasing */ QPen QCPLegend::getBorderPen() const { - return mSelectedParts.testFlag(spLegendBox) ? mSelectedBorderPen : mBorderPen; + return mSelectedParts.testFlag(spLegendBox) ? mSelectedBorderPen : mBorderPen; } /*! \internal @@ -13418,7 +13410,7 @@ QPen QCPLegend::getBorderPen() const */ QBrush QCPLegend::getBrush() const { - return mSelectedParts.testFlag(spLegendBox) ? mSelectedBrush : mBrush; + return mSelectedParts.testFlag(spLegendBox) ? mSelectedBrush : mBrush; } /*! \internal @@ -13428,70 +13420,70 @@ QBrush QCPLegend::getBrush() const */ void QCPLegend::draw(QCPPainter *painter) { - // draw background rect: - painter->setBrush(getBrush()); - painter->setPen(getBorderPen()); - painter->drawRect(mOuterRect); + // draw background rect: + painter->setBrush(getBrush()); + painter->setPen(getBorderPen()); + painter->drawRect(mOuterRect); } /* inherits documentation from base class */ double QCPLegend::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - if (!mParentPlot) return -1; - if (onlySelectable && !mSelectableParts.testFlag(spLegendBox)) + if (!mParentPlot) return -1; + if (onlySelectable && !mSelectableParts.testFlag(spLegendBox)) + return -1; + + if (mOuterRect.contains(pos.toPoint())) + { + if (details) details->setValue(spLegendBox); + return mParentPlot->selectionTolerance()*0.99; + } return -1; - - if (mOuterRect.contains(pos.toPoint())) - { - if (details) details->setValue(spLegendBox); - return mParentPlot->selectionTolerance()*0.99; - } - return -1; } /* inherits documentation from base class */ void QCPLegend::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) { - Q_UNUSED(event) - mSelectedParts = selectedParts(); // in case item selection has changed - if (details.value() == spLegendBox && mSelectableParts.testFlag(spLegendBox)) - { - SelectableParts selBefore = mSelectedParts; - setSelectedParts(additive ? mSelectedParts^spLegendBox : mSelectedParts|spLegendBox); // no need to unset spItems in !additive case, because they will be deselected by QCustomPlot (they're normal QCPLayerables with own deselectEvent) - if (selectionStateChanged) - *selectionStateChanged = mSelectedParts != selBefore; + Q_UNUSED(event) + mSelectedParts = selectedParts(); // in case item selection has changed + if (details.value() == spLegendBox && mSelectableParts.testFlag(spLegendBox)) + { + SelectableParts selBefore = mSelectedParts; + setSelectedParts(additive ? mSelectedParts^spLegendBox : mSelectedParts|spLegendBox); // no need to unset spItems in !additive case, because they will be deselected by QCustomPlot (they're normal QCPLayerables with own deselectEvent) + if (selectionStateChanged) + *selectionStateChanged = mSelectedParts != selBefore; } } /* inherits documentation from base class */ void QCPLegend::deselectEvent(bool *selectionStateChanged) { - mSelectedParts = selectedParts(); // in case item selection has changed - if (mSelectableParts.testFlag(spLegendBox)) - { - SelectableParts selBefore = mSelectedParts; - setSelectedParts(selectedParts() & ~spLegendBox); - if (selectionStateChanged) - *selectionStateChanged = mSelectedParts != selBefore; + mSelectedParts = selectedParts(); // in case item selection has changed + if (mSelectableParts.testFlag(spLegendBox)) + { + SelectableParts selBefore = mSelectedParts; + setSelectedParts(selectedParts() & ~spLegendBox); + if (selectionStateChanged) + *selectionStateChanged = mSelectedParts != selBefore; } } /* inherits documentation from base class */ QCP::Interaction QCPLegend::selectionCategory() const { - return QCP::iSelectLegend; + return QCP::iSelectLegend; } /* inherits documentation from base class */ QCP::Interaction QCPAbstractLegendItem::selectionCategory() const { - return QCP::iSelectLegend; + return QCP::iSelectLegend; } /* inherits documentation from base class */ void QCPLegend::parentPlotInitialized(QCustomPlot *parentPlot) { - Q_UNUSED(parentPlot) + Q_UNUSED(parentPlot) } @@ -13535,21 +13527,21 @@ void QCPLegend::parentPlotInitialized(QC To set the title text in the constructor, rather use \ref QCPPlotTitle(QCustomPlot *parentPlot, const QString &text). */ QCPPlotTitle::QCPPlotTitle(QCustomPlot *parentPlot) : - QCPLayoutElement(parentPlot), - mFont(QFont(QLatin1String("sans serif"), 13*1.5, QFont::Bold)), - mTextColor(Qt::black), - mSelectedFont(QFont(QLatin1String("sans serif"), 13*1.6, QFont::Bold)), - mSelectedTextColor(Qt::blue), - mSelectable(false), - mSelected(false) -{ - if (parentPlot) - { - setLayer(parentPlot->currentLayer()); - mFont = QFont(parentPlot->font().family(), parentPlot->font().pointSize()*1.5, QFont::Bold); - mSelectedFont = QFont(parentPlot->font().family(), parentPlot->font().pointSize()*1.6, QFont::Bold); - } - setMargins(QMargins(5, 5, 5, 0)); + QCPLayoutElement(parentPlot), + mFont(QFont(QLatin1String("sans serif"), 13*1.5, QFont::Bold)), + mTextColor(Qt::black), + mSelectedFont(QFont(QLatin1String("sans serif"), 13*1.6, QFont::Bold)), + mSelectedTextColor(Qt::blue), + mSelectable(false), + mSelected(false) +{ + if (parentPlot) + { + setLayer(parentPlot->currentLayer()); + mFont = QFont(parentPlot->font().family(), parentPlot->font().pointSize()*1.5, QFont::Bold); + mSelectedFont = QFont(parentPlot->font().family(), parentPlot->font().pointSize()*1.6, QFont::Bold); + } + setMargins(QMargins(5, 5, 5, 0)); } /*! \overload @@ -13557,17 +13549,17 @@ QCPPlotTitle::QCPPlotTitle(QCustomPlot * Creates a new QCPPlotTitle instance and sets default values. The initial text is set to \a text. */ QCPPlotTitle::QCPPlotTitle(QCustomPlot *parentPlot, const QString &text) : - QCPLayoutElement(parentPlot), - mText(text), - mFont(QFont(parentPlot->font().family(), parentPlot->font().pointSize()*1.5, QFont::Bold)), - mTextColor(Qt::black), - mSelectedFont(QFont(parentPlot->font().family(), parentPlot->font().pointSize()*1.6, QFont::Bold)), - mSelectedTextColor(Qt::blue), - mSelectable(false), - mSelected(false) -{ - setLayer(QLatin1String("axes")); - setMargins(QMargins(5, 5, 5, 0)); + QCPLayoutElement(parentPlot), + mText(text), + mFont(QFont(parentPlot->font().family(), parentPlot->font().pointSize()*1.5, QFont::Bold)), + mTextColor(Qt::black), + mSelectedFont(QFont(parentPlot->font().family(), parentPlot->font().pointSize()*1.6, QFont::Bold)), + mSelectedTextColor(Qt::blue), + mSelectable(false), + mSelected(false) +{ + setLayer(QLatin1String("axes")); + setMargins(QMargins(5, 5, 5, 0)); } /*! @@ -13577,7 +13569,7 @@ QCPPlotTitle::QCPPlotTitle(QCustomPlot * */ void QCPPlotTitle::setText(const QString &text) { - mText = text; + mText = text; } /*! @@ -13587,7 +13579,7 @@ void QCPPlotTitle::setText(const QString */ void QCPPlotTitle::setFont(const QFont &font) { - mFont = font; + mFont = font; } /*! @@ -13597,7 +13589,7 @@ void QCPPlotTitle::setFont(const QFont & */ void QCPPlotTitle::setTextColor(const QColor &color) { - mTextColor = color; + mTextColor = color; } /*! @@ -13607,7 +13599,7 @@ void QCPPlotTitle::setTextColor(const QC */ void QCPPlotTitle::setSelectedFont(const QFont &font) { - mSelectedFont = font; + mSelectedFont = font; } /*! @@ -13617,7 +13609,7 @@ void QCPPlotTitle::setSelectedFont(const */ void QCPPlotTitle::setSelectedTextColor(const QColor &color) { - mSelectedTextColor = color; + mSelectedTextColor = color; } /*! @@ -13628,10 +13620,10 @@ void QCPPlotTitle::setSelectedTextColor( */ void QCPPlotTitle::setSelectable(bool selectable) { - if (mSelectable != selectable) - { - mSelectable = selectable; - emit selectableChanged(mSelectable); + if (mSelectable != selectable) + { + mSelectable = selectable; + emit selectableChanged(mSelectable); } } @@ -13644,84 +13636,84 @@ void QCPPlotTitle::setSelectable(bool se */ void QCPPlotTitle::setSelected(bool selected) { - if (mSelected != selected) - { - mSelected = selected; - emit selectionChanged(mSelected); + if (mSelected != selected) + { + mSelected = selected; + emit selectionChanged(mSelected); } } /* inherits documentation from base class */ void QCPPlotTitle::applyDefaultAntialiasingHint(QCPPainter *painter) const { - applyAntialiasingHint(painter, mAntialiased, QCP::aeNone); + applyAntialiasingHint(painter, mAntialiased, QCP::aeNone); } /* inherits documentation from base class */ void QCPPlotTitle::draw(QCPPainter *painter) { - painter->setFont(mainFont()); - painter->setPen(QPen(mainTextColor())); - painter->drawText(mRect, Qt::AlignCenter, mText, &mTextBoundingRect); + painter->setFont(mainFont()); + painter->setPen(QPen(mainTextColor())); + painter->drawText(mRect, Qt::AlignCenter, mText, &mTextBoundingRect); } /* inherits documentation from base class */ QSize QCPPlotTitle::minimumSizeHint() const { - QFontMetrics metrics(mFont); - QSize result = metrics.boundingRect(0, 0, 0, 0, Qt::AlignCenter, mText).size(); - result.rwidth() += mMargins.left() + mMargins.right(); - result.rheight() += mMargins.top() + mMargins.bottom(); - return result; + QFontMetrics metrics(mFont); + QSize result = metrics.boundingRect(0, 0, 0, 0, Qt::AlignCenter, mText).size(); + result.rwidth() += mMargins.left() + mMargins.right(); + result.rheight() += mMargins.top() + mMargins.bottom(); + return result; } /* inherits documentation from base class */ QSize QCPPlotTitle::maximumSizeHint() const { - QFontMetrics metrics(mFont); - QSize result = metrics.boundingRect(0, 0, 0, 0, Qt::AlignCenter, mText).size(); - result.rheight() += mMargins.top() + mMargins.bottom(); - result.setWidth(QWIDGETSIZE_MAX); - return result; + QFontMetrics metrics(mFont); + QSize result = metrics.boundingRect(0, 0, 0, 0, Qt::AlignCenter, mText).size(); + result.rheight() += mMargins.top() + mMargins.bottom(); + result.setWidth(QWIDGETSIZE_MAX); + return result; } /* inherits documentation from base class */ void QCPPlotTitle::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) { - Q_UNUSED(event) - Q_UNUSED(details) - if (mSelectable) - { - bool selBefore = mSelected; - setSelected(additive ? !mSelected : true); - if (selectionStateChanged) - *selectionStateChanged = mSelected != selBefore; + Q_UNUSED(event) + Q_UNUSED(details) + if (mSelectable) + { + bool selBefore = mSelected; + setSelected(additive ? !mSelected : true); + if (selectionStateChanged) + *selectionStateChanged = mSelected != selBefore; } } /* inherits documentation from base class */ void QCPPlotTitle::deselectEvent(bool *selectionStateChanged) { - if (mSelectable) - { - bool selBefore = mSelected; - setSelected(false); - if (selectionStateChanged) - *selectionStateChanged = mSelected != selBefore; + if (mSelectable) + { + bool selBefore = mSelected; + setSelected(false); + if (selectionStateChanged) + *selectionStateChanged = mSelected != selBefore; } } /* inherits documentation from base class */ double QCPPlotTitle::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - Q_UNUSED(details) - if (onlySelectable && !mSelectable) - return -1; - - if (mTextBoundingRect.contains(pos.toPoint())) - return mParentPlot->selectionTolerance()*0.99; - else - return -1; + Q_UNUSED(details) + if (onlySelectable && !mSelectable) + return -1; + + if (mTextBoundingRect.contains(pos.toPoint())) + return mParentPlot->selectionTolerance()*0.99; + else + return -1; } /*! \internal @@ -13731,7 +13723,7 @@ double QCPPlotTitle::selectTest(const QP */ QFont QCPPlotTitle::mainFont() const { - return mSelected ? mSelectedFont : mFont; + return mSelected ? mSelectedFont : mFont; } /*! \internal @@ -13741,7 +13733,7 @@ QFont QCPPlotTitle::mainFont() const */ QColor QCPPlotTitle::mainTextColor() const { - return mSelected ? mSelectedTextColor : mTextColor; + return mSelected ? mSelectedTextColor : mTextColor; } @@ -13842,60 +13834,60 @@ QColor QCPPlotTitle::mainTextColor() con Constructs a new QCPColorScale. */ QCPColorScale::QCPColorScale(QCustomPlot *parentPlot) : - QCPLayoutElement(parentPlot), - mType(QCPAxis::atTop), // set to atTop such that setType(QCPAxis::atRight) below doesn't skip work because it thinks it's already atRight - mDataScaleType(QCPAxis::stLinear), - mBarWidth(20), - mAxisRect(new QCPColorScaleAxisRectPrivate(this)) -{ - setMinimumMargins(QMargins(0, 6, 0, 6)); // for default right color scale types, keep some room at bottom and top (important if no margin group is used) - setType(QCPAxis::atRight); - setDataRange(QCPRange(0, 6)); + QCPLayoutElement(parentPlot), + mType(QCPAxis::atTop), // set to atTop such that setType(QCPAxis::atRight) below doesn't skip work because it thinks it's already atRight + mDataScaleType(QCPAxis::stLinear), + mBarWidth(20), + mAxisRect(new QCPColorScaleAxisRectPrivate(this)) +{ + setMinimumMargins(QMargins(0, 6, 0, 6)); // for default right color scale types, keep some room at bottom and top (important if no margin group is used) + setType(QCPAxis::atRight); + setDataRange(QCPRange(0, 6)); } QCPColorScale::~QCPColorScale() { - delete mAxisRect; + delete mAxisRect; } /* undocumented getter */ QString QCPColorScale::label() const { - if (!mColorAxis) - { - qDebug() << Q_FUNC_INFO << "internal color axis undefined"; - return QString(); - } - - return mColorAxis.data()->label(); + if (!mColorAxis) + { + qDebug() << Q_FUNC_INFO << "internal color axis undefined"; + return QString(); + } + + return mColorAxis.data()->label(); } /* undocumented getter */ bool QCPColorScale::rangeDrag() const { - if (!mAxisRect) - { - qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; - return false; - } - - return mAxisRect.data()->rangeDrag().testFlag(QCPAxis::orientation(mType)) && - mAxisRect.data()->rangeDragAxis(QCPAxis::orientation(mType)) && - mAxisRect.data()->rangeDragAxis(QCPAxis::orientation(mType))->orientation() == QCPAxis::orientation(mType); + if (!mAxisRect) + { + qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; + return false; + } + + return mAxisRect.data()->rangeDrag().testFlag(QCPAxis::orientation(mType)) && + mAxisRect.data()->rangeDragAxis(QCPAxis::orientation(mType)) && + mAxisRect.data()->rangeDragAxis(QCPAxis::orientation(mType))->orientation() == QCPAxis::orientation(mType); } /* undocumented getter */ bool QCPColorScale::rangeZoom() const { - if (!mAxisRect) - { - qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; - return false; - } - - return mAxisRect.data()->rangeZoom().testFlag(QCPAxis::orientation(mType)) && - mAxisRect.data()->rangeZoomAxis(QCPAxis::orientation(mType)) && - mAxisRect.data()->rangeZoomAxis(QCPAxis::orientation(mType))->orientation() == QCPAxis::orientation(mType); + if (!mAxisRect) + { + qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; + return false; + } + + return mAxisRect.data()->rangeZoom().testFlag(QCPAxis::orientation(mType)) && + mAxisRect.data()->rangeZoomAxis(QCPAxis::orientation(mType)) && + mAxisRect.data()->rangeZoomAxis(QCPAxis::orientation(mType))->orientation() == QCPAxis::orientation(mType); } /*! @@ -13907,42 +13899,42 @@ bool QCPColorScale::rangeZoom() const */ void QCPColorScale::setType(QCPAxis::AxisType type) { - if (!mAxisRect) - { - qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; - return; - } - if (mType != type) - { - mType = type; - QCPRange rangeTransfer(0, 6); - double logBaseTransfer = 10; - QString labelTransfer; - // revert some settings on old axis: - if (mColorAxis) - { - rangeTransfer = mColorAxis.data()->range(); - labelTransfer = mColorAxis.data()->label(); - logBaseTransfer = mColorAxis.data()->scaleLogBase(); - mColorAxis.data()->setLabel(QString()); - disconnect(mColorAxis.data(), SIGNAL(rangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange))); - disconnect(mColorAxis.data(), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), this, SLOT(setDataScaleType(QCPAxis::ScaleType))); - } - foreach (QCPAxis::AxisType atype, QList() << QCPAxis::atLeft << QCPAxis::atRight << QCPAxis::atBottom << QCPAxis::atTop) - { - mAxisRect.data()->axis(atype)->setTicks(atype == mType); - mAxisRect.data()->axis(atype)->setTickLabels(atype== mType); - } - // set new mColorAxis pointer: - mColorAxis = mAxisRect.data()->axis(mType); - // transfer settings to new axis: - mColorAxis.data()->setRange(rangeTransfer); // transfer range of old axis to new one (necessary if axis changes from vertical to horizontal or vice versa) - mColorAxis.data()->setLabel(labelTransfer); - mColorAxis.data()->setScaleLogBase(logBaseTransfer); // scaleType is synchronized among axes in realtime via signals (connected in QCPColorScale ctor), so we only need to take care of log base here - connect(mColorAxis.data(), SIGNAL(rangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange))); - connect(mColorAxis.data(), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), this, SLOT(setDataScaleType(QCPAxis::ScaleType))); - mAxisRect.data()->setRangeDragAxes(QCPAxis::orientation(mType) == Qt::Horizontal ? mColorAxis.data() : 0, - QCPAxis::orientation(mType) == Qt::Vertical ? mColorAxis.data() : 0); + if (!mAxisRect) + { + qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; + return; + } + if (mType != type) + { + mType = type; + QCPRange rangeTransfer(0, 6); + double logBaseTransfer = 10; + QString labelTransfer; + // revert some settings on old axis: + if (mColorAxis) + { + rangeTransfer = mColorAxis.data()->range(); + labelTransfer = mColorAxis.data()->label(); + logBaseTransfer = mColorAxis.data()->scaleLogBase(); + mColorAxis.data()->setLabel(QString()); + disconnect(mColorAxis.data(), SIGNAL(rangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange))); + disconnect(mColorAxis.data(), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), this, SLOT(setDataScaleType(QCPAxis::ScaleType))); + } + foreach (QCPAxis::AxisType atype, QList() << QCPAxis::atLeft << QCPAxis::atRight << QCPAxis::atBottom << QCPAxis::atTop) + { + mAxisRect.data()->axis(atype)->setTicks(atype == mType); + mAxisRect.data()->axis(atype)->setTickLabels(atype== mType); + } + // set new mColorAxis pointer: + mColorAxis = mAxisRect.data()->axis(mType); + // transfer settings to new axis: + mColorAxis.data()->setRange(rangeTransfer); // transfer range of old axis to new one (necessary if axis changes from vertical to horizontal or vice versa) + mColorAxis.data()->setLabel(labelTransfer); + mColorAxis.data()->setScaleLogBase(logBaseTransfer); // scaleType is synchronized among axes in realtime via signals (connected in QCPColorScale ctor), so we only need to take care of log base here + connect(mColorAxis.data(), SIGNAL(rangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange))); + connect(mColorAxis.data(), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), this, SLOT(setDataScaleType(QCPAxis::ScaleType))); + mAxisRect.data()->setRangeDragAxes(QCPAxis::orientation(mType) == Qt::Horizontal ? mColorAxis.data() : 0, + QCPAxis::orientation(mType) == Qt::Vertical ? mColorAxis.data() : 0); } } @@ -13957,12 +13949,12 @@ void QCPColorScale::setType(QCPAxis::Axi */ void QCPColorScale::setDataRange(const QCPRange &dataRange) { - if (mDataRange.lower != dataRange.lower || mDataRange.upper != dataRange.upper) - { - mDataRange = dataRange; - if (mColorAxis) - mColorAxis.data()->setRange(mDataRange); - emit dataRangeChanged(mDataRange); + if (mDataRange.lower != dataRange.lower || mDataRange.upper != dataRange.upper) + { + mDataRange = dataRange; + if (mColorAxis) + mColorAxis.data()->setRange(mDataRange); + emit dataRangeChanged(mDataRange); } } @@ -13978,14 +13970,14 @@ void QCPColorScale::setDataRange(const Q */ void QCPColorScale::setDataScaleType(QCPAxis::ScaleType scaleType) { - if (mDataScaleType != scaleType) - { - mDataScaleType = scaleType; - if (mColorAxis) - mColorAxis.data()->setScaleType(mDataScaleType); - if (mDataScaleType == QCPAxis::stLogarithmic) - setDataRange(mDataRange.sanitizedForLogScale()); - emit dataScaleTypeChanged(mDataScaleType); + if (mDataScaleType != scaleType) + { + mDataScaleType = scaleType; + if (mColorAxis) + mColorAxis.data()->setScaleType(mDataScaleType); + if (mDataScaleType == QCPAxis::stLogarithmic) + setDataRange(mDataRange.sanitizedForLogScale()); + emit dataScaleTypeChanged(mDataScaleType); } } @@ -13998,12 +13990,12 @@ void QCPColorScale::setDataScaleType(QCP */ void QCPColorScale::setGradient(const QCPColorGradient &gradient) { - if (mGradient != gradient) - { - mGradient = gradient; - if (mAxisRect) - mAxisRect.data()->mGradientImageInvalidated = true; - emit gradientChanged(mGradient); + if (mGradient != gradient) + { + mGradient = gradient; + if (mAxisRect) + mAxisRect.data()->mGradientImageInvalidated = true; + emit gradientChanged(mGradient); } } @@ -14013,13 +14005,13 @@ void QCPColorScale::setGradient(const QC */ void QCPColorScale::setLabel(const QString &str) { - if (!mColorAxis) - { - qDebug() << Q_FUNC_INFO << "internal color axis undefined"; - return; - } - - mColorAxis.data()->setLabel(str); + if (!mColorAxis) + { + qDebug() << Q_FUNC_INFO << "internal color axis undefined"; + return; + } + + mColorAxis.data()->setLabel(str); } /*! @@ -14028,7 +14020,7 @@ void QCPColorScale::setLabel(const QStri */ void QCPColorScale::setBarWidth(int width) { - mBarWidth = width; + mBarWidth = width; } /*! @@ -14039,16 +14031,16 @@ void QCPColorScale::setBarWidth(int widt */ void QCPColorScale::setRangeDrag(bool enabled) { - if (!mAxisRect) - { - qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; - return; - } - - if (enabled) - mAxisRect.data()->setRangeDrag(QCPAxis::orientation(mType)); - else - mAxisRect.data()->setRangeDrag(0); + if (!mAxisRect) + { + qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; + return; + } + + if (enabled) + mAxisRect.data()->setRangeDrag(QCPAxis::orientation(mType)); + else + mAxisRect.data()->setRangeDrag(0); } /*! @@ -14059,16 +14051,16 @@ void QCPColorScale::setRangeDrag(bool en */ void QCPColorScale::setRangeZoom(bool enabled) { - if (!mAxisRect) - { - qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; - return; - } - - if (enabled) - mAxisRect.data()->setRangeZoom(QCPAxis::orientation(mType)); - else - mAxisRect.data()->setRangeZoom(0); + if (!mAxisRect) + { + qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; + return; + } + + if (enabled) + mAxisRect.data()->setRangeZoom(QCPAxis::orientation(mType)); + else + mAxisRect.data()->setRangeZoom(0); } /*! @@ -14076,14 +14068,14 @@ void QCPColorScale::setRangeZoom(bool en */ QList QCPColorScale::colorMaps() const { - QList result; - for (int i=0; iplottableCount(); ++i) - { - if (QCPColorMap *cm = qobject_cast(mParentPlot->plottable(i))) - if (cm->colorScale() == this) - result.append(cm); - } - return result; + QList result; + for (int i=0; iplottableCount(); ++i) + { + if (QCPColorMap *cm = qobject_cast(mParentPlot->plottable(i))) + if (cm->colorScale() == this) + result.append(cm); + } + return result; } /*! @@ -14094,95 +14086,95 @@ QList QCPColorScale::color */ void QCPColorScale::rescaleDataRange(bool onlyVisibleMaps) { - QList maps = colorMaps(); - QCPRange newRange; - bool haveRange = false; - int sign = 0; // TODO: should change this to QCPAbstractPlottable::SignDomain later (currently is protected, maybe move to QCP namespace) - if (mDataScaleType == QCPAxis::stLogarithmic) - sign = (mDataRange.upper < 0 ? -1 : 1); - for (int i=0; irealVisibility() && onlyVisibleMaps) - continue; - QCPRange mapRange; - if (maps.at(i)->colorScale() == this) - { - bool currentFoundRange = true; - mapRange = maps.at(i)->data()->dataBounds(); - if (sign == 1) - { - if (mapRange.lower <= 0 && mapRange.upper > 0) - mapRange.lower = mapRange.upper*1e-3; - else if (mapRange.lower <= 0 && mapRange.upper <= 0) - currentFoundRange = false; + QList maps = colorMaps(); + QCPRange newRange; + bool haveRange = false; + int sign = 0; // TODO: should change this to QCPAbstractPlottable::SignDomain later (currently is protected, maybe move to QCP namespace) + if (mDataScaleType == QCPAxis::stLogarithmic) + sign = (mDataRange.upper < 0 ? -1 : 1); + for (int i=0; irealVisibility() && onlyVisibleMaps) + continue; + QCPRange mapRange; + if (maps.at(i)->colorScale() == this) + { + bool currentFoundRange = true; + mapRange = maps.at(i)->data()->dataBounds(); + if (sign == 1) + { + if (mapRange.lower <= 0 && mapRange.upper > 0) + mapRange.lower = mapRange.upper*1e-3; + else if (mapRange.lower <= 0 && mapRange.upper <= 0) + currentFoundRange = false; } else if (sign == -1) { - if (mapRange.upper >= 0 && mapRange.lower < 0) - mapRange.upper = mapRange.lower*1e-3; - else if (mapRange.upper >= 0 && mapRange.lower >= 0) - currentFoundRange = false; - } - if (currentFoundRange) - { - if (!haveRange) - newRange = mapRange; - else - newRange.expand(mapRange); - haveRange = true; - } - } - } - if (haveRange) - { - if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this dimension), shift current range to at least center the data - { - double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason - if (mDataScaleType == QCPAxis::stLinear) - { - newRange.lower = center-mDataRange.size()/2.0; - newRange.upper = center+mDataRange.size()/2.0; + if (mapRange.upper >= 0 && mapRange.lower < 0) + mapRange.upper = mapRange.lower*1e-3; + else if (mapRange.upper >= 0 && mapRange.lower >= 0) + currentFoundRange = false; + } + if (currentFoundRange) + { + if (!haveRange) + newRange = mapRange; + else + newRange.expand(mapRange); + haveRange = true; + } + } + } + if (haveRange) + { + if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this dimension), shift current range to at least center the data + { + double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason + if (mDataScaleType == QCPAxis::stLinear) + { + newRange.lower = center-mDataRange.size()/2.0; + newRange.upper = center+mDataRange.size()/2.0; } else // mScaleType == stLogarithmic { - newRange.lower = center/qSqrt(mDataRange.upper/mDataRange.lower); - newRange.upper = center*qSqrt(mDataRange.upper/mDataRange.lower); - } - } - setDataRange(newRange); + newRange.lower = center/qSqrt(mDataRange.upper/mDataRange.lower); + newRange.upper = center*qSqrt(mDataRange.upper/mDataRange.lower); + } + } + setDataRange(newRange); } } /* inherits documentation from base class */ void QCPColorScale::update(UpdatePhase phase) { - QCPLayoutElement::update(phase); - if (!mAxisRect) - { - qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; - return; - } - - mAxisRect.data()->update(phase); - - switch (phase) + QCPLayoutElement::update(phase); + if (!mAxisRect) + { + qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; + return; + } + + mAxisRect.data()->update(phase); + + switch (phase) { case upMargins: - { + { if (mType == QCPAxis::atBottom || mType == QCPAxis::atTop) - { + { setMaximumSize(QWIDGETSIZE_MAX, mBarWidth+mAxisRect.data()->margins().top()+mAxisRect.data()->margins().bottom()+margins().top()+margins().bottom()); setMinimumSize(0, mBarWidth+mAxisRect.data()->margins().top()+mAxisRect.data()->margins().bottom()+margins().top()+margins().bottom()); - } else - { + } else + { setMaximumSize(mBarWidth+mAxisRect.data()->margins().left()+mAxisRect.data()->margins().right()+margins().left()+margins().right(), QWIDGETSIZE_MAX); setMinimumSize(mBarWidth+mAxisRect.data()->margins().left()+mAxisRect.data()->margins().right()+margins().left()+margins().right(), 0); - } - break; - } + } + break; + } case upLayout: - { + { mAxisRect.data()->setOuterRect(rect()); break; - } + } default: break; } } @@ -14190,51 +14182,51 @@ void QCPColorScale::update(UpdatePhase p /* inherits documentation from base class */ void QCPColorScale::applyDefaultAntialiasingHint(QCPPainter *painter) const { - painter->setAntialiasing(false); + painter->setAntialiasing(false); } /* inherits documentation from base class */ void QCPColorScale::mousePressEvent(QMouseEvent *event) { - if (!mAxisRect) - { - qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; - return; - } - mAxisRect.data()->mousePressEvent(event); + if (!mAxisRect) + { + qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; + return; + } + mAxisRect.data()->mousePressEvent(event); } /* inherits documentation from base class */ void QCPColorScale::mouseMoveEvent(QMouseEvent *event) { - if (!mAxisRect) - { - qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; - return; - } - mAxisRect.data()->mouseMoveEvent(event); + if (!mAxisRect) + { + qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; + return; + } + mAxisRect.data()->mouseMoveEvent(event); } /* inherits documentation from base class */ void QCPColorScale::mouseReleaseEvent(QMouseEvent *event) { - if (!mAxisRect) - { - qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; - return; - } - mAxisRect.data()->mouseReleaseEvent(event); + if (!mAxisRect) + { + qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; + return; + } + mAxisRect.data()->mouseReleaseEvent(event); } /* inherits documentation from base class */ void QCPColorScale::wheelEvent(QWheelEvent *event) { - if (!mAxisRect) - { - qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; - return; - } - mAxisRect.data()->wheelEvent(event); + if (!mAxisRect) + { + qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; + return; + } + mAxisRect.data()->wheelEvent(event); } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -14256,35 +14248,35 @@ void QCPColorScale::wheelEvent(QWheelEve Creates a new instance, as a child of \a parentColorScale. */ QCPColorScaleAxisRectPrivate::QCPColorScaleAxisRectPrivate(QCPColorScale *parentColorScale) : - QCPAxisRect(parentColorScale->parentPlot(), true), - mParentColorScale(parentColorScale), - mGradientImageInvalidated(true) -{ - setParentLayerable(parentColorScale); - setMinimumMargins(QMargins(0, 0, 0, 0)); - foreach (QCPAxis::AxisType type, QList() << QCPAxis::atBottom << QCPAxis::atTop << QCPAxis::atLeft << QCPAxis::atRight) - { - axis(type)->setVisible(true); - axis(type)->grid()->setVisible(false); - axis(type)->setPadding(0); - connect(axis(type), SIGNAL(selectionChanged(QCPAxis::SelectableParts)), this, SLOT(axisSelectionChanged(QCPAxis::SelectableParts))); - connect(axis(type), SIGNAL(selectableChanged(QCPAxis::SelectableParts)), this, SLOT(axisSelectableChanged(QCPAxis::SelectableParts))); - } - - connect(axis(QCPAxis::atLeft), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atRight), SLOT(setRange(QCPRange))); - connect(axis(QCPAxis::atRight), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atLeft), SLOT(setRange(QCPRange))); - connect(axis(QCPAxis::atBottom), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atTop), SLOT(setRange(QCPRange))); - connect(axis(QCPAxis::atTop), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atBottom), SLOT(setRange(QCPRange))); - connect(axis(QCPAxis::atLeft), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atRight), SLOT(setScaleType(QCPAxis::ScaleType))); - connect(axis(QCPAxis::atRight), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atLeft), SLOT(setScaleType(QCPAxis::ScaleType))); - connect(axis(QCPAxis::atBottom), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atTop), SLOT(setScaleType(QCPAxis::ScaleType))); - connect(axis(QCPAxis::atTop), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atBottom), SLOT(setScaleType(QCPAxis::ScaleType))); - - // make layer transfers of color scale transfer to axis rect and axes - // the axes must be set after axis rect, such that they appear above color gradient drawn by axis rect: - connect(parentColorScale, SIGNAL(layerChanged(QCPLayer*)), this, SLOT(setLayer(QCPLayer*))); - foreach (QCPAxis::AxisType type, QList() << QCPAxis::atBottom << QCPAxis::atTop << QCPAxis::atLeft << QCPAxis::atRight) - connect(parentColorScale, SIGNAL(layerChanged(QCPLayer*)), axis(type), SLOT(setLayer(QCPLayer*))); + QCPAxisRect(parentColorScale->parentPlot(), true), + mParentColorScale(parentColorScale), + mGradientImageInvalidated(true) +{ + setParentLayerable(parentColorScale); + setMinimumMargins(QMargins(0, 0, 0, 0)); + foreach (QCPAxis::AxisType type, QList() << QCPAxis::atBottom << QCPAxis::atTop << QCPAxis::atLeft << QCPAxis::atRight) + { + axis(type)->setVisible(true); + axis(type)->grid()->setVisible(false); + axis(type)->setPadding(0); + connect(axis(type), SIGNAL(selectionChanged(QCPAxis::SelectableParts)), this, SLOT(axisSelectionChanged(QCPAxis::SelectableParts))); + connect(axis(type), SIGNAL(selectableChanged(QCPAxis::SelectableParts)), this, SLOT(axisSelectableChanged(QCPAxis::SelectableParts))); + } + + connect(axis(QCPAxis::atLeft), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atRight), SLOT(setRange(QCPRange))); + connect(axis(QCPAxis::atRight), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atLeft), SLOT(setRange(QCPRange))); + connect(axis(QCPAxis::atBottom), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atTop), SLOT(setRange(QCPRange))); + connect(axis(QCPAxis::atTop), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atBottom), SLOT(setRange(QCPRange))); + connect(axis(QCPAxis::atLeft), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atRight), SLOT(setScaleType(QCPAxis::ScaleType))); + connect(axis(QCPAxis::atRight), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atLeft), SLOT(setScaleType(QCPAxis::ScaleType))); + connect(axis(QCPAxis::atBottom), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atTop), SLOT(setScaleType(QCPAxis::ScaleType))); + connect(axis(QCPAxis::atTop), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atBottom), SLOT(setScaleType(QCPAxis::ScaleType))); + + // make layer transfers of color scale transfer to axis rect and axes + // the axes must be set after axis rect, such that they appear above color gradient drawn by axis rect: + connect(parentColorScale, SIGNAL(layerChanged(QCPLayer*)), this, SLOT(setLayer(QCPLayer*))); + foreach (QCPAxis::AxisType type, QList() << QCPAxis::atBottom << QCPAxis::atTop << QCPAxis::atLeft << QCPAxis::atRight) + connect(parentColorScale, SIGNAL(layerChanged(QCPLayer*)), axis(type), SLOT(setLayer(QCPLayer*))); } /*! \internal @@ -14293,19 +14285,19 @@ QCPColorScaleAxisRectPrivate::QCPColorSc */ void QCPColorScaleAxisRectPrivate::draw(QCPPainter *painter) { - if (mGradientImageInvalidated) - updateGradientImage(); - - bool mirrorHorz = false; - bool mirrorVert = false; - if (mParentColorScale->mColorAxis) - { - mirrorHorz = mParentColorScale->mColorAxis.data()->rangeReversed() && (mParentColorScale->type() == QCPAxis::atBottom || mParentColorScale->type() == QCPAxis::atTop); - mirrorVert = mParentColorScale->mColorAxis.data()->rangeReversed() && (mParentColorScale->type() == QCPAxis::atLeft || mParentColorScale->type() == QCPAxis::atRight); - } - - painter->drawImage(rect(), mGradientImage.mirrored(mirrorHorz, mirrorVert)); - QCPAxisRect::draw(painter); + if (mGradientImageInvalidated) + updateGradientImage(); + + bool mirrorHorz = false; + bool mirrorVert = false; + if (mParentColorScale->mColorAxis) + { + mirrorHorz = mParentColorScale->mColorAxis.data()->rangeReversed() && (mParentColorScale->type() == QCPAxis::atBottom || mParentColorScale->type() == QCPAxis::atTop); + mirrorVert = mParentColorScale->mColorAxis.data()->rangeReversed() && (mParentColorScale->type() == QCPAxis::atLeft || mParentColorScale->type() == QCPAxis::atRight); + } + + painter->drawImage(rect(), mGradientImage.mirrored(mirrorHorz, mirrorVert)); + QCPAxisRect::draw(painter); } /*! \internal @@ -14315,39 +14307,39 @@ void QCPColorScaleAxisRectPrivate::draw( */ void QCPColorScaleAxisRectPrivate::updateGradientImage() { - if (rect().isEmpty()) - return; - - int n = mParentColorScale->mGradient.levelCount(); - int w, h; - QVector data(n); - for (int i=0; imType == QCPAxis::atBottom || mParentColorScale->mType == QCPAxis::atTop) - { - w = n; - h = rect().height(); - mGradientImage = QImage(w, h, QImage::Format_RGB32); - QVector pixels; - for (int y=0; y(mGradientImage.scanLine(y))); - mParentColorScale->mGradient.colorize(data.constData(), QCPRange(0, n-1), pixels.first(), n); - for (int y=1; y(mGradientImage.scanLine(y)); - const QRgb lineColor = mParentColorScale->mGradient.color(data[h-1-y], QCPRange(0, n-1)); - for (int x=0; xmGradient.levelCount(); + int w, h; + QVector data(n); + for (int i=0; imType == QCPAxis::atBottom || mParentColorScale->mType == QCPAxis::atTop) + { + w = n; + h = rect().height(); + mGradientImage = QImage(w, h, QImage::Format_RGB32); + QVector pixels; + for (int y=0; y(mGradientImage.scanLine(y))); + mParentColorScale->mGradient.colorize(data.constData(), QCPRange(0, n-1), pixels.first(), n); + for (int y=1; y(mGradientImage.scanLine(y)); + const QRgb lineColor = mParentColorScale->mGradient.color(data[h-1-y], QCPRange(0, n-1)); + for (int x=0; x() << QCPAxis::atBottom << QCPAxis::atTop << QCPAxis::atLeft << QCPAxis::atRight) - { - if (QCPAxis *senderAxis = qobject_cast(sender())) - if (senderAxis->axisType() == type) - continue; - - if (axis(type)->selectableParts().testFlag(QCPAxis::spAxis)) - { - if (selectedParts.testFlag(QCPAxis::spAxis)) - axis(type)->setSelectedParts(axis(type)->selectedParts() | QCPAxis::spAxis); - else - axis(type)->setSelectedParts(axis(type)->selectedParts() & ~QCPAxis::spAxis); + // axis bases of four axes shall always (de-)selected synchronously: + foreach (QCPAxis::AxisType type, QList() << QCPAxis::atBottom << QCPAxis::atTop << QCPAxis::atLeft << QCPAxis::atRight) + { + if (QCPAxis *senderAxis = qobject_cast(sender())) + if (senderAxis->axisType() == type) + continue; + + if (axis(type)->selectableParts().testFlag(QCPAxis::spAxis)) + { + if (selectedParts.testFlag(QCPAxis::spAxis)) + axis(type)->setSelectedParts(axis(type)->selectedParts() | QCPAxis::spAxis); + else + axis(type)->setSelectedParts(axis(type)->selectedParts() & ~QCPAxis::spAxis); } } } @@ -14381,19 +14373,19 @@ void QCPColorScaleAxisRectPrivate::axisS */ void QCPColorScaleAxisRectPrivate::axisSelectableChanged(QCPAxis::SelectableParts selectableParts) { - // synchronize axis base selectability: - foreach (QCPAxis::AxisType type, QList() << QCPAxis::atBottom << QCPAxis::atTop << QCPAxis::atLeft << QCPAxis::atRight) - { - if (QCPAxis *senderAxis = qobject_cast(sender())) - if (senderAxis->axisType() == type) - continue; - - if (axis(type)->selectableParts().testFlag(QCPAxis::spAxis)) - { - if (selectableParts.testFlag(QCPAxis::spAxis)) - axis(type)->setSelectableParts(axis(type)->selectableParts() | QCPAxis::spAxis); - else - axis(type)->setSelectableParts(axis(type)->selectableParts() & ~QCPAxis::spAxis); + // synchronize axis base selectability: + foreach (QCPAxis::AxisType type, QList() << QCPAxis::atBottom << QCPAxis::atTop << QCPAxis::atLeft << QCPAxis::atRight) + { + if (QCPAxis *senderAxis = qobject_cast(sender())) + if (senderAxis->axisType() == type) + continue; + + if (axis(type)->selectableParts().testFlag(QCPAxis::spAxis)) + { + if (selectableParts.testFlag(QCPAxis::spAxis)) + axis(type)->setSelectableParts(axis(type)->selectableParts() | QCPAxis::spAxis); + else + axis(type)->setSelectableParts(axis(type)->selectableParts() & ~QCPAxis::spAxis); } } } @@ -14423,12 +14415,12 @@ void QCPColorScaleAxisRectPrivate::axisS Constructs a data point with key, value and all errors set to zero. */ QCPData::QCPData() : - key(0), - value(0), - keyErrorPlus(0), - keyErrorMinus(0), - valueErrorPlus(0), - valueErrorMinus(0) + key(0), + value(0), + keyErrorPlus(0), + keyErrorMinus(0), + valueErrorPlus(0), + valueErrorMinus(0) { } @@ -14436,12 +14428,12 @@ QCPData::QCPData() : Constructs a data point with the specified \a key and \a value. All errors are set to zero. */ QCPData::QCPData(double key, double value) : - key(key), - value(value), - keyErrorPlus(0), - keyErrorMinus(0), - valueErrorPlus(0), - valueErrorMinus(0) + key(key), + value(value), + keyErrorPlus(0), + keyErrorMinus(0), + valueErrorPlus(0), + valueErrorMinus(0) { } @@ -14507,29 +14499,27 @@ QCPData::QCPData(double key, double valu To directly create a graph inside a plot, you can also use the simpler QCustomPlot::addGraph function. */ QCPGraph::QCPGraph(QCPAxis *keyAxis, QCPAxis *valueAxis) : - QCPAbstractPlottable(keyAxis, valueAxis) -{ - mData = new QCPDataMap; - mDataVector = new QVector(); - setPen(QPen(Qt::blue, 0)); - setErrorPen(QPen(Qt::black)); - setBrush(Qt::NoBrush); - setSelectedPen(QPen(QColor(80, 80, 255), 2.5)); - setSelectedBrush(Qt::NoBrush); - - setLineStyle(lsLine); - setErrorType(etNone); - setErrorBarSize(6); - setErrorBarSkipSymbol(true); - setChannelFillGraph(0); - setAdaptiveSampling(true); - setUseFastVectors(false); + QCPAbstractPlottable(keyAxis, valueAxis) +{ + mData = new QCPDataMap; + + setPen(QPen(Qt::blue, 0)); + setErrorPen(QPen(Qt::black)); + setBrush(Qt::NoBrush); + setSelectedPen(QPen(QColor(80, 80, 255), 2.5)); + setSelectedBrush(Qt::NoBrush); + + setLineStyle(lsLine); + setErrorType(etNone); + setErrorBarSize(6); + setErrorBarSkipSymbol(true); + setChannelFillGraph(0); + setAdaptiveSampling(true); } QCPGraph::~QCPGraph() { - delete mData; - delete mDataVector; + delete mData; } /*! @@ -14544,18 +14534,18 @@ QCPGraph::~QCPGraph() */ void QCPGraph::setData(QCPDataMap *data, bool copy) { - if (mData == data) - { - qDebug() << Q_FUNC_INFO << "The data pointer is already in (and owned by) this plottable" << reinterpret_cast(data); - return; - } - if (copy) - { - *mData = *data; - } else - { - delete mData; - mData = data; + if (mData == data) + { + qDebug() << Q_FUNC_INFO << "The data pointer is already in (and owned by) this plottable" << reinterpret_cast(data); + return; + } + if (copy) + { + *mData = *data; + } else + { + delete mData; + mData = data; } } @@ -14567,24 +14557,15 @@ void QCPGraph::setData(QCPDataMap *data, */ void QCPGraph::setData(const QVector &key, const QVector &value) { - mData->clear(); - int n = key.size(); - n = qMin(n, value.size()); - QCPData newData; - for (int i=0; iinsertMulti(newData.key, newData); - } -} - -void QCPGraph::setData(QVector *data) -{ - if(data!=mDataVector) - { - delete this->mDataVector; - this->mDataVector = data; + mData->clear(); + int n = key.size(); + n = qMin(n, value.size()); + QCPData newData; + for (int i=0; iinsertMulti(newData.key, newData); } } @@ -14599,18 +14580,18 @@ void QCPGraph::setData(QVector */ void QCPGraph::setDataValueError(const QVector &key, const QVector &value, const QVector &valueError) { - mData->clear(); - int n = key.size(); - n = qMin(n, value.size()); - n = qMin(n, valueError.size()); - QCPData newData; - for (int i=0; iinsertMulti(key[i], newData); + mData->clear(); + int n = key.size(); + n = qMin(n, value.size()); + n = qMin(n, valueError.size()); + QCPData newData; + for (int i=0; iinsertMulti(key[i], newData); } } @@ -14625,19 +14606,19 @@ void QCPGraph::setDataValueError(const Q */ void QCPGraph::setDataValueError(const QVector &key, const QVector &value, const QVector &valueErrorMinus, const QVector &valueErrorPlus) { - mData->clear(); - int n = key.size(); - n = qMin(n, value.size()); - n = qMin(n, valueErrorMinus.size()); - n = qMin(n, valueErrorPlus.size()); - QCPData newData; - for (int i=0; iinsertMulti(key[i], newData); + mData->clear(); + int n = key.size(); + n = qMin(n, value.size()); + n = qMin(n, valueErrorMinus.size()); + n = qMin(n, valueErrorPlus.size()); + QCPData newData; + for (int i=0; iinsertMulti(key[i], newData); } } @@ -14652,18 +14633,18 @@ void QCPGraph::setDataValueError(const Q */ void QCPGraph::setDataKeyError(const QVector &key, const QVector &value, const QVector &keyError) { - mData->clear(); - int n = key.size(); - n = qMin(n, value.size()); - n = qMin(n, keyError.size()); - QCPData newData; - for (int i=0; iinsertMulti(key[i], newData); + mData->clear(); + int n = key.size(); + n = qMin(n, value.size()); + n = qMin(n, keyError.size()); + QCPData newData; + for (int i=0; iinsertMulti(key[i], newData); } } @@ -14678,19 +14659,19 @@ void QCPGraph::setDataKeyError(const QVe */ void QCPGraph::setDataKeyError(const QVector &key, const QVector &value, const QVector &keyErrorMinus, const QVector &keyErrorPlus) { - mData->clear(); - int n = key.size(); - n = qMin(n, value.size()); - n = qMin(n, keyErrorMinus.size()); - n = qMin(n, keyErrorPlus.size()); - QCPData newData; - for (int i=0; iinsertMulti(key[i], newData); + mData->clear(); + int n = key.size(); + n = qMin(n, value.size()); + n = qMin(n, keyErrorMinus.size()); + n = qMin(n, keyErrorPlus.size()); + QCPData newData; + for (int i=0; iinsertMulti(key[i], newData); } } @@ -14705,21 +14686,21 @@ void QCPGraph::setDataKeyError(const QVe */ void QCPGraph::setDataBothError(const QVector &key, const QVector &value, const QVector &keyError, const QVector &valueError) { - mData->clear(); - int n = key.size(); - n = qMin(n, value.size()); - n = qMin(n, valueError.size()); - n = qMin(n, keyError.size()); - QCPData newData; - for (int i=0; iinsertMulti(key[i], newData); + mData->clear(); + int n = key.size(); + n = qMin(n, value.size()); + n = qMin(n, valueError.size()); + n = qMin(n, keyError.size()); + QCPData newData; + for (int i=0; iinsertMulti(key[i], newData); } } @@ -14734,23 +14715,23 @@ void QCPGraph::setDataBothError(const QV */ void QCPGraph::setDataBothError(const QVector &key, const QVector &value, const QVector &keyErrorMinus, const QVector &keyErrorPlus, const QVector &valueErrorMinus, const QVector &valueErrorPlus) { - mData->clear(); - int n = key.size(); - n = qMin(n, value.size()); - n = qMin(n, valueErrorMinus.size()); - n = qMin(n, valueErrorPlus.size()); - n = qMin(n, keyErrorMinus.size()); - n = qMin(n, keyErrorPlus.size()); - QCPData newData; - for (int i=0; iinsertMulti(key[i], newData); + mData->clear(); + int n = key.size(); + n = qMin(n, value.size()); + n = qMin(n, valueErrorMinus.size()); + n = qMin(n, valueErrorPlus.size()); + n = qMin(n, keyErrorMinus.size()); + n = qMin(n, keyErrorPlus.size()); + QCPData newData; + for (int i=0; iinsertMulti(key[i], newData); } } @@ -14763,7 +14744,7 @@ void QCPGraph::setDataBothError(const QV */ void QCPGraph::setLineStyle(LineStyle ls) { - mLineStyle = ls; + mLineStyle = ls; } /*! @@ -14774,7 +14755,7 @@ void QCPGraph::setLineStyle(LineStyle ls */ void QCPGraph::setScatterStyle(const QCPScatterStyle &style) { - mScatterStyle = style; + mScatterStyle = style; } /*! @@ -14787,7 +14768,7 @@ void QCPGraph::setScatterStyle(const QCP */ void QCPGraph::setErrorType(ErrorType errorType) { - mErrorType = errorType; + mErrorType = errorType; } /*! @@ -14796,7 +14777,7 @@ void QCPGraph::setErrorType(ErrorType er */ void QCPGraph::setErrorPen(const QPen &pen) { - mErrorPen = pen; + mErrorPen = pen; } /*! @@ -14804,7 +14785,7 @@ void QCPGraph::setErrorPen(const QPen &p */ void QCPGraph::setErrorBarSize(double size) { - mErrorBarSize = size; + mErrorBarSize = size; } /*! @@ -14820,7 +14801,7 @@ void QCPGraph::setErrorBarSize(double si */ void QCPGraph::setErrorBarSkipSymbol(bool enabled) { - mErrorBarSkipSymbol = enabled; + mErrorBarSkipSymbol = enabled; } /*! @@ -14834,22 +14815,22 @@ void QCPGraph::setErrorBarSkipSymbol(boo */ void QCPGraph::setChannelFillGraph(QCPGraph *targetGraph) { - // prevent setting channel target to this graph itself: - if (targetGraph == this) - { - qDebug() << Q_FUNC_INFO << "targetGraph is this graph itself"; - mChannelFillGraph = 0; - return; - } - // prevent setting channel target to a graph not in the plot: - if (targetGraph && targetGraph->mParentPlot != mParentPlot) - { - qDebug() << Q_FUNC_INFO << "targetGraph not in same plot"; - mChannelFillGraph = 0; - return; - } - - mChannelFillGraph = targetGraph; + // prevent setting channel target to this graph itself: + if (targetGraph == this) + { + qDebug() << Q_FUNC_INFO << "targetGraph is this graph itself"; + mChannelFillGraph = 0; + return; + } + // prevent setting channel target to a graph not in the plot: + if (targetGraph && targetGraph->mParentPlot != mParentPlot) + { + qDebug() << Q_FUNC_INFO << "targetGraph not in same plot"; + mChannelFillGraph = 0; + return; + } + + mChannelFillGraph = targetGraph; } /*! @@ -14885,12 +14866,7 @@ void QCPGraph::setChannelFillGraph(QCPGr */ void QCPGraph::setAdaptiveSampling(bool enabled) { - mAdaptiveSampling = enabled; -} - -void QCPGraph::setUseFastVectors(bool useFastVectors) -{ - mUseFastVectors=useFastVectors; + mAdaptiveSampling = enabled; } /*! @@ -14903,7 +14879,7 @@ void QCPGraph::setUseFastVectors(bool us */ void QCPGraph::addData(const QCPDataMap &dataMap) { - mData->unite(dataMap); + mData->unite(dataMap); } /*! \overload @@ -14916,7 +14892,7 @@ void QCPGraph::addData(const QCPDataMap */ void QCPGraph::addData(const QCPData &data) { - mData->insertMulti(data.key, data); + mData->insertMulti(data.key, data); } /*! \overload @@ -14929,10 +14905,10 @@ void QCPGraph::addData(const QCPData &da */ void QCPGraph::addData(double key, double value) { - QCPData newData; - newData.key = key; - newData.value = value; - mData->insertMulti(newData.key, newData); + QCPData newData; + newData.key = key; + newData.value = value; + mData->insertMulti(newData.key, newData); } /*! \overload @@ -14945,13 +14921,13 @@ void QCPGraph::addData(double key, doubl */ void QCPGraph::addData(const QVector &keys, const QVector &values) { - int n = qMin(keys.size(), values.size()); - QCPData newData; - for (int i=0; iinsertMulti(newData.key, newData); + int n = qMin(keys.size(), values.size()); + QCPData newData; + for (int i=0; iinsertMulti(newData.key, newData); } } @@ -14961,9 +14937,9 @@ void QCPGraph::addData(const QVectorbegin(); - while (it != mData->end() && it.key() < key) - it = mData->erase(it); + QCPDataMap::iterator it = mData->begin(); + while (it != mData->end() && it.key() < key) + it = mData->erase(it); } /*! @@ -14972,10 +14948,10 @@ void QCPGraph::removeDataBefore(double k */ void QCPGraph::removeDataAfter(double key) { - if (mData->isEmpty()) return; - QCPDataMap::iterator it = mData->upperBound(key); - while (it != mData->end()) - it = mData->erase(it); + if (mData->isEmpty()) return; + QCPDataMap::iterator it = mData->upperBound(key); + while (it != mData->end()) + it = mData->erase(it); } /*! @@ -14987,11 +14963,11 @@ void QCPGraph::removeDataAfter(double ke */ void QCPGraph::removeData(double fromKey, double toKey) { - if (fromKey >= toKey || mData->isEmpty()) return; - QCPDataMap::iterator it = mData->upperBound(fromKey); - QCPDataMap::iterator itEnd = mData->upperBound(toKey); - while (it != itEnd) - it = mData->erase(it); + if (fromKey >= toKey || mData->isEmpty()) return; + QCPDataMap::iterator it = mData->upperBound(fromKey); + QCPDataMap::iterator itEnd = mData->upperBound(toKey); + while (it != itEnd) + it = mData->erase(it); } /*! \overload @@ -15004,7 +14980,7 @@ void QCPGraph::removeData(double fromKey */ void QCPGraph::removeData(double key) { - mData->remove(key); + mData->remove(key); } /*! @@ -15013,21 +14989,21 @@ void QCPGraph::removeData(double key) */ void QCPGraph::clearData() { - mData->clear(); + mData->clear(); } /* inherits documentation from base class */ double QCPGraph::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - Q_UNUSED(details) - if ((onlySelectable && !mSelectable) || mData->isEmpty()) - return -1; - if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; } - - if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint())) - return pointDistance(pos); - else - return -1; + Q_UNUSED(details) + if ((onlySelectable && !mSelectable) || mData->isEmpty()) + return -1; + if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; } + + if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint())) + return pointDistance(pos); + else + return -1; } /*! \overload @@ -15039,8 +15015,8 @@ double QCPGraph::selectTest(const QPoint */ void QCPGraph::rescaleAxes(bool onlyEnlarge, bool includeErrorBars) const { - rescaleKeyAxis(onlyEnlarge, includeErrorBars); - rescaleValueAxis(onlyEnlarge, includeErrorBars); + rescaleKeyAxis(onlyEnlarge, includeErrorBars); + rescaleValueAxis(onlyEnlarge, includeErrorBars); } /*! \overload @@ -15052,30 +15028,30 @@ void QCPGraph::rescaleAxes(bool onlyEnla */ void QCPGraph::rescaleKeyAxis(bool onlyEnlarge, bool includeErrorBars) const { - // this code is a copy of QCPAbstractPlottable::rescaleKeyAxis with the only change - // that getKeyRange is passed the includeErrorBars value. - if (mData->isEmpty()) return; - - QCPAxis *keyAxis = mKeyAxis.data(); - if (!keyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; } - - SignDomain signDomain = sdBoth; - if (keyAxis->scaleType() == QCPAxis::stLogarithmic) - signDomain = (keyAxis->range().upper < 0 ? sdNegative : sdPositive); - - bool foundRange; - QCPRange newRange = getKeyRange(foundRange, signDomain, includeErrorBars); - - if (foundRange) - { - if (onlyEnlarge) - { - if (keyAxis->range().lower < newRange.lower) - newRange.lower = keyAxis->range().lower; - if (keyAxis->range().upper > newRange.upper) - newRange.upper = keyAxis->range().upper; - } - keyAxis->setRange(newRange); + // this code is a copy of QCPAbstractPlottable::rescaleKeyAxis with the only change + // that getKeyRange is passed the includeErrorBars value. + if (mData->isEmpty()) return; + + QCPAxis *keyAxis = mKeyAxis.data(); + if (!keyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; } + + SignDomain signDomain = sdBoth; + if (keyAxis->scaleType() == QCPAxis::stLogarithmic) + signDomain = (keyAxis->range().upper < 0 ? sdNegative : sdPositive); + + bool foundRange; + QCPRange newRange = getKeyRange(foundRange, signDomain, includeErrorBars); + + if (foundRange) + { + if (onlyEnlarge) + { + if (keyAxis->range().lower < newRange.lower) + newRange.lower = keyAxis->range().lower; + if (keyAxis->range().upper > newRange.upper) + newRange.upper = keyAxis->range().upper; + } + keyAxis->setRange(newRange); } } @@ -15088,111 +15064,113 @@ void QCPGraph::rescaleKeyAxis(bool onlyE */ void QCPGraph::rescaleValueAxis(bool onlyEnlarge, bool includeErrorBars) const { - // this code is a copy of QCPAbstractPlottable::rescaleValueAxis with the only change - // is that getValueRange is passed the includeErrorBars value. - if (mData->isEmpty()) return; - - QCPAxis *valueAxis = mValueAxis.data(); - if (!valueAxis) { qDebug() << Q_FUNC_INFO << "invalid value axis"; return; } - - SignDomain signDomain = sdBoth; - if (valueAxis->scaleType() == QCPAxis::stLogarithmic) - signDomain = (valueAxis->range().upper < 0 ? sdNegative : sdPositive); - - bool foundRange; - QCPRange newRange = getValueRange(foundRange, signDomain, includeErrorBars); - - if (foundRange) - { - if (onlyEnlarge) - { - if (valueAxis->range().lower < newRange.lower) - newRange.lower = valueAxis->range().lower; - if (valueAxis->range().upper > newRange.upper) - newRange.upper = valueAxis->range().upper; - } - valueAxis->setRange(newRange); + // this code is a copy of QCPAbstractPlottable::rescaleValueAxis with the only change + // is that getValueRange is passed the includeErrorBars value. + if (mData->isEmpty()) return; + + QCPAxis *valueAxis = mValueAxis.data(); + if (!valueAxis) { qDebug() << Q_FUNC_INFO << "invalid value axis"; return; } + + SignDomain signDomain = sdBoth; + if (valueAxis->scaleType() == QCPAxis::stLogarithmic) + signDomain = (valueAxis->range().upper < 0 ? sdNegative : sdPositive); + + bool foundRange; + QCPRange newRange = getValueRange(foundRange, signDomain, includeErrorBars); + + if (foundRange) + { + if (onlyEnlarge) + { + if (valueAxis->range().lower < newRange.lower) + newRange.lower = valueAxis->range().lower; + if (valueAxis->range().upper > newRange.upper) + newRange.upper = valueAxis->range().upper; + } + valueAxis->setRange(newRange); } } /* inherits documentation from base class */ void QCPGraph::draw(QCPPainter *painter) { - if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - if (mKeyAxis.data()->range().size() <= 0 || (mData->isEmpty() && mDataVector->isEmpty())) return; - if (mLineStyle == lsNone && mScatterStyle.isNone()) return; - - // allocate line and (if necessary) point vectors: - QVector *lineData = new QVector; - QVector *scatterData = 0; - if (!mScatterStyle.isNone()) - scatterData = new QVector; - - // fill vectors with data appropriate to plot style: - getPlotData(lineData, scatterData); - - // check data validity if flag set: + if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + int test = mKeyAxis.data()->range().size(); + test = mData->count(); + if (mKeyAxis.data()->range().size() <= 0 || mData->isEmpty()) return; + if (mLineStyle == lsNone && mScatterStyle.isNone()) return; + + // allocate line and (if necessary) point vectors: + QVector *lineData = new QVector; + QVector *scatterData = 0; + if (!mScatterStyle.isNone()) + scatterData = new QVector; + + // fill vectors with data appropriate to plot style: + getPlotData(lineData, scatterData); + + // check data validity if flag set: #ifdef QCUSTOMPLOT_CHECK_DATA - QCPDataMap::const_iterator it; - for (it = mData->constBegin(); it != mData->constEnd(); ++it) - { - if (QCP::isInvalidData(it.value().key, it.value().value) || - QCP::isInvalidData(it.value().keyErrorPlus, it.value().keyErrorMinus) || - QCP::isInvalidData(it.value().valueErrorPlus, it.value().valueErrorPlus)) - qDebug() << Q_FUNC_INFO << "Data point at" << it.key() << "invalid." << "Plottable name:" << name(); + QCPDataMap::const_iterator it; + for (it = mData->constBegin(); it != mData->constEnd(); ++it) + { + if (QCP::isInvalidData(it.value().key, it.value().value) || + QCP::isInvalidData(it.value().keyErrorPlus, it.value().keyErrorMinus) || + QCP::isInvalidData(it.value().valueErrorPlus, it.value().valueErrorPlus)) + qDebug() << Q_FUNC_INFO << "Data point at" << it.key() << "invalid." << "Plottable name:" << name(); } #endif - // draw fill of graph: - drawFill(painter, lineData); - - // draw line: - if (mLineStyle == lsImpulse) - drawImpulsePlot(painter, lineData); - else if (mLineStyle != lsNone) - drawLinePlot(painter, lineData); // also step plots can be drawn as a line plot - - // draw scatters: - if (scatterData) - drawScatterPlot(painter, scatterData); - - // free allocated line and point vectors: - delete lineData; - if (scatterData) - delete scatterData; + // draw fill of graph: + drawFill(painter, lineData); + + // draw line: + if (mLineStyle == lsImpulse) + drawImpulsePlot(painter, lineData); + else if (mLineStyle != lsNone) + drawLinePlot(painter, lineData); // also step plots can be drawn as a line plot + + // draw scatters: + if (scatterData) + drawScatterPlot(painter, scatterData); + + // free allocated line and point vectors: + delete lineData; + if (scatterData) + delete scatterData; } /* inherits documentation from base class */ void QCPGraph::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const { - // draw fill: - if (mBrush.style() != Qt::NoBrush) - { - applyFillAntialiasingHint(painter); - painter->fillRect(QRectF(rect.left(), rect.top()+rect.height()/2.0, rect.width(), rect.height()/3.0), mBrush); - } - // draw line vertically centered: - if (mLineStyle != lsNone) - { - applyDefaultAntialiasingHint(painter); - painter->setPen(mPen); - painter->drawLine(QLineF(rect.left(), rect.top()+rect.height()/2.0, rect.right()+5, rect.top()+rect.height()/2.0)); // +5 on x2 else last segment is missing from dashed/dotted pens - } - // draw scatter symbol: - if (!mScatterStyle.isNone()) - { - applyScattersAntialiasingHint(painter); - // scale scatter pixmap if it's too large to fit in legend icon rect: - if (mScatterStyle.shape() == QCPScatterStyle::ssPixmap && (mScatterStyle.pixmap().size().width() > rect.width() || mScatterStyle.pixmap().size().height() > rect.height())) - { - QCPScatterStyle scaledStyle(mScatterStyle); - scaledStyle.setPixmap(scaledStyle.pixmap().scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); - scaledStyle.applyTo(painter, mPen); - scaledStyle.drawShape(painter, QRectF(rect).center()); + // draw fill: + if (mBrush.style() != Qt::NoBrush) + { + applyFillAntialiasingHint(painter); + painter->fillRect(QRectF(rect.left(), rect.top()+rect.height()/2.0, rect.width(), rect.height()/3.0), mBrush); + } + // draw line vertically centered: + if (mLineStyle != lsNone) + { + applyDefaultAntialiasingHint(painter); + painter->setPen(mPen); + painter->drawLine(QLineF(rect.left(), rect.top()+rect.height()/2.0, rect.right()+5, rect.top()+rect.height()/2.0)); // +5 on x2 else last segment is missing from dashed/dotted pens + } + // draw scatter symbol: + if (!mScatterStyle.isNone()) + { + applyScattersAntialiasingHint(painter); + // scale scatter pixmap if it's too large to fit in legend icon rect: + if (mScatterStyle.shape() == QCPScatterStyle::ssPixmap && (mScatterStyle.pixmap().size().width() > rect.width() || mScatterStyle.pixmap().size().height() > rect.height())) + { + QCPScatterStyle scaledStyle(mScatterStyle); + scaledStyle.setPixmap(scaledStyle.pixmap().scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); + scaledStyle.applyTo(painter, mPen); + scaledStyle.drawShape(painter, QRectF(rect).center()); } else { - mScatterStyle.applyTo(painter, mPen); - mScatterStyle.drawShape(painter, QRectF(rect).center()); + mScatterStyle.applyTo(painter, mPen); + mScatterStyle.drawShape(painter, QRectF(rect).center()); } } } @@ -15217,7 +15195,7 @@ void QCPGraph::drawLegendIcon(QCPPainter */ void QCPGraph::getPlotData(QVector *lineData, QVector *scatterData) const { - switch(mLineStyle) + switch(mLineStyle) { case lsNone: getScatterPlotData(scatterData); break; case lsLine: getLinePlotData(lineData, scatterData); break; @@ -15241,7 +15219,7 @@ void QCPGraph::getPlotData(QVector *scatterData) const { - getPreparedData(0, scatterData); + getPreparedData(0, scatterData); } /*! \internal @@ -15257,33 +15235,30 @@ void QCPGraph::getScatterPlotData(QVecto */ void QCPGraph::getLinePlotData(QVector *linePixelData, QVector *scatterData) const { - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as linePixelData"; return; } - - QVector lineData; - if(mUseFastVectors) - getPreparedDataVector(&lineData, scatterData); - else + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as linePixelData"; return; } + + QVector lineData; getPreparedData(&lineData, scatterData); - linePixelData->reserve(lineData.size()+2); // added 2 to reserve memory for lower/upper fill base points that might be needed for fill - linePixelData->resize(lineData.size()); - - // transform lineData points to pixels: - if (keyAxis->orientation() == Qt::Vertical) - { - for (int i=0; icoordToPixel(lineData.at(i).value)); - (*linePixelData)[i].setY(keyAxis->coordToPixel(lineData.at(i).key)); + linePixelData->reserve(lineData.size()+2); // added 2 to reserve memory for lower/upper fill base points that might be needed for fill + linePixelData->resize(lineData.size()); + + // transform lineData points to pixels: + if (keyAxis->orientation() == Qt::Vertical) + { + for (int i=0; icoordToPixel(lineData.at(i).value)); + (*linePixelData)[i].setY(keyAxis->coordToPixel(lineData.at(i).key)); } } else // key axis is horizontal { - for (int i=0; icoordToPixel(lineData.at(i).key)); - (*linePixelData)[i].setY(valueAxis->coordToPixel(lineData.at(i).value)); + for (int i=0; icoordToPixel(lineData.at(i).key)); + (*linePixelData)[i].setY(valueAxis->coordToPixel(lineData.at(i).value)); } } } @@ -15301,42 +15276,42 @@ void QCPGraph::getLinePlotData(QVector *linePixelData, QVector *scatterData) const { - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as lineData"; return; } - - QVector lineData; - getPreparedData(&lineData, scatterData); - linePixelData->reserve(lineData.size()*2+2); // added 2 to reserve memory for lower/upper fill base points that might be needed for fill - linePixelData->resize(lineData.size()*2); - - // calculate steps from lineData and transform to pixel coordinates: - if (keyAxis->orientation() == Qt::Vertical) - { - double lastValue = valueAxis->coordToPixel(lineData.first().value); - double key; - for (int i=0; icoordToPixel(lineData.at(i).key); - (*linePixelData)[i*2+0].setX(lastValue); - (*linePixelData)[i*2+0].setY(key); - lastValue = valueAxis->coordToPixel(lineData.at(i).value); - (*linePixelData)[i*2+1].setX(lastValue); - (*linePixelData)[i*2+1].setY(key); + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as lineData"; return; } + + QVector lineData; + getPreparedData(&lineData, scatterData); + linePixelData->reserve(lineData.size()*2+2); // added 2 to reserve memory for lower/upper fill base points that might be needed for fill + linePixelData->resize(lineData.size()*2); + + // calculate steps from lineData and transform to pixel coordinates: + if (keyAxis->orientation() == Qt::Vertical) + { + double lastValue = valueAxis->coordToPixel(lineData.first().value); + double key; + for (int i=0; icoordToPixel(lineData.at(i).key); + (*linePixelData)[i*2+0].setX(lastValue); + (*linePixelData)[i*2+0].setY(key); + lastValue = valueAxis->coordToPixel(lineData.at(i).value); + (*linePixelData)[i*2+1].setX(lastValue); + (*linePixelData)[i*2+1].setY(key); } } else // key axis is horizontal { - double lastValue = valueAxis->coordToPixel(lineData.first().value); - double key; - for (int i=0; icoordToPixel(lineData.at(i).key); - (*linePixelData)[i*2+0].setX(key); - (*linePixelData)[i*2+0].setY(lastValue); - lastValue = valueAxis->coordToPixel(lineData.at(i).value); - (*linePixelData)[i*2+1].setX(key); - (*linePixelData)[i*2+1].setY(lastValue); + double lastValue = valueAxis->coordToPixel(lineData.first().value); + double key; + for (int i=0; icoordToPixel(lineData.at(i).key); + (*linePixelData)[i*2+0].setX(key); + (*linePixelData)[i*2+0].setY(lastValue); + lastValue = valueAxis->coordToPixel(lineData.at(i).value); + (*linePixelData)[i*2+1].setX(key); + (*linePixelData)[i*2+1].setY(lastValue); } } } @@ -15354,42 +15329,42 @@ void QCPGraph::getStepLeftPlotData(QVect */ void QCPGraph::getStepRightPlotData(QVector *linePixelData, QVector *scatterData) const { - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as lineData"; return; } - - QVector lineData; - getPreparedData(&lineData, scatterData); - linePixelData->reserve(lineData.size()*2+2); // added 2 to reserve memory for lower/upper fill base points that might be needed for fill - linePixelData->resize(lineData.size()*2); - - // calculate steps from lineData and transform to pixel coordinates: - if (keyAxis->orientation() == Qt::Vertical) - { - double lastKey = keyAxis->coordToPixel(lineData.first().key); - double value; - for (int i=0; icoordToPixel(lineData.at(i).value); - (*linePixelData)[i*2+0].setX(value); - (*linePixelData)[i*2+0].setY(lastKey); - lastKey = keyAxis->coordToPixel(lineData.at(i).key); - (*linePixelData)[i*2+1].setX(value); - (*linePixelData)[i*2+1].setY(lastKey); + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as lineData"; return; } + + QVector lineData; + getPreparedData(&lineData, scatterData); + linePixelData->reserve(lineData.size()*2+2); // added 2 to reserve memory for lower/upper fill base points that might be needed for fill + linePixelData->resize(lineData.size()*2); + + // calculate steps from lineData and transform to pixel coordinates: + if (keyAxis->orientation() == Qt::Vertical) + { + double lastKey = keyAxis->coordToPixel(lineData.first().key); + double value; + for (int i=0; icoordToPixel(lineData.at(i).value); + (*linePixelData)[i*2+0].setX(value); + (*linePixelData)[i*2+0].setY(lastKey); + lastKey = keyAxis->coordToPixel(lineData.at(i).key); + (*linePixelData)[i*2+1].setX(value); + (*linePixelData)[i*2+1].setY(lastKey); } } else // key axis is horizontal { - double lastKey = keyAxis->coordToPixel(lineData.first().key); - double value; - for (int i=0; icoordToPixel(lineData.at(i).value); - (*linePixelData)[i*2+0].setX(lastKey); - (*linePixelData)[i*2+0].setY(value); - lastKey = keyAxis->coordToPixel(lineData.at(i).key); - (*linePixelData)[i*2+1].setX(lastKey); - (*linePixelData)[i*2+1].setY(value); + double lastKey = keyAxis->coordToPixel(lineData.first().key); + double value; + for (int i=0; icoordToPixel(lineData.at(i).value); + (*linePixelData)[i*2+0].setX(lastKey); + (*linePixelData)[i*2+0].setY(value); + lastKey = keyAxis->coordToPixel(lineData.at(i).key); + (*linePixelData)[i*2+1].setX(lastKey); + (*linePixelData)[i*2+1].setY(value); } } } @@ -15407,54 +15382,54 @@ void QCPGraph::getStepRightPlotData(QVec */ void QCPGraph::getStepCenterPlotData(QVector *linePixelData, QVector *scatterData) const { - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as lineData"; return; } - - QVector lineData; - getPreparedData(&lineData, scatterData); - linePixelData->reserve(lineData.size()*2+2); // added 2 to reserve memory for lower/upper fill base points that might be needed for fill - linePixelData->resize(lineData.size()*2); - // calculate steps from lineData and transform to pixel coordinates: - if (keyAxis->orientation() == Qt::Vertical) - { - double lastKey = keyAxis->coordToPixel(lineData.first().key); - double lastValue = valueAxis->coordToPixel(lineData.first().value); - double key; - (*linePixelData)[0].setX(lastValue); - (*linePixelData)[0].setY(lastKey); - for (int i=1; icoordToPixel(lineData.at(i).key)+lastKey)*0.5; - (*linePixelData)[i*2-1].setX(lastValue); - (*linePixelData)[i*2-1].setY(key); - lastValue = valueAxis->coordToPixel(lineData.at(i).value); - lastKey = keyAxis->coordToPixel(lineData.at(i).key); - (*linePixelData)[i*2+0].setX(lastValue); - (*linePixelData)[i*2+0].setY(key); - } - (*linePixelData)[lineData.size()*2-1].setX(lastValue); - (*linePixelData)[lineData.size()*2-1].setY(lastKey); + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as lineData"; return; } + + QVector lineData; + getPreparedData(&lineData, scatterData); + linePixelData->reserve(lineData.size()*2+2); // added 2 to reserve memory for lower/upper fill base points that might be needed for fill + linePixelData->resize(lineData.size()*2); + // calculate steps from lineData and transform to pixel coordinates: + if (keyAxis->orientation() == Qt::Vertical) + { + double lastKey = keyAxis->coordToPixel(lineData.first().key); + double lastValue = valueAxis->coordToPixel(lineData.first().value); + double key; + (*linePixelData)[0].setX(lastValue); + (*linePixelData)[0].setY(lastKey); + for (int i=1; icoordToPixel(lineData.at(i).key)+lastKey)*0.5; + (*linePixelData)[i*2-1].setX(lastValue); + (*linePixelData)[i*2-1].setY(key); + lastValue = valueAxis->coordToPixel(lineData.at(i).value); + lastKey = keyAxis->coordToPixel(lineData.at(i).key); + (*linePixelData)[i*2+0].setX(lastValue); + (*linePixelData)[i*2+0].setY(key); + } + (*linePixelData)[lineData.size()*2-1].setX(lastValue); + (*linePixelData)[lineData.size()*2-1].setY(lastKey); } else // key axis is horizontal { - double lastKey = keyAxis->coordToPixel(lineData.first().key); - double lastValue = valueAxis->coordToPixel(lineData.first().value); - double key; - (*linePixelData)[0].setX(lastKey); - (*linePixelData)[0].setY(lastValue); - for (int i=1; icoordToPixel(lineData.at(i).key)+lastKey)*0.5; - (*linePixelData)[i*2-1].setX(key); - (*linePixelData)[i*2-1].setY(lastValue); - lastValue = valueAxis->coordToPixel(lineData.at(i).value); - lastKey = keyAxis->coordToPixel(lineData.at(i).key); - (*linePixelData)[i*2+0].setX(key); - (*linePixelData)[i*2+0].setY(lastValue); - } - (*linePixelData)[lineData.size()*2-1].setX(lastKey); - (*linePixelData)[lineData.size()*2-1].setY(lastValue); + double lastKey = keyAxis->coordToPixel(lineData.first().key); + double lastValue = valueAxis->coordToPixel(lineData.first().value); + double key; + (*linePixelData)[0].setX(lastKey); + (*linePixelData)[0].setY(lastValue); + for (int i=1; icoordToPixel(lineData.at(i).key)+lastKey)*0.5; + (*linePixelData)[i*2-1].setX(key); + (*linePixelData)[i*2-1].setY(lastValue); + lastValue = valueAxis->coordToPixel(lineData.at(i).value); + lastKey = keyAxis->coordToPixel(lineData.at(i).key); + (*linePixelData)[i*2+0].setX(key); + (*linePixelData)[i*2+0].setY(lastValue); + } + (*linePixelData)[lineData.size()*2-1].setX(lastKey); + (*linePixelData)[lineData.size()*2-1].setY(lastValue); } } @@ -15472,39 +15447,39 @@ void QCPGraph::getStepCenterPlotData(QVe */ void QCPGraph::getImpulsePlotData(QVector *linePixelData, QVector *scatterData) const { - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as linePixelData"; return; } - - QVector lineData; - getPreparedData(&lineData, scatterData); - linePixelData->resize(lineData.size()*2); // no need to reserve 2 extra points because impulse plot has no fill - - // transform lineData points to pixels: - if (keyAxis->orientation() == Qt::Vertical) - { - double zeroPointX = valueAxis->coordToPixel(0); - double key; - for (int i=0; icoordToPixel(lineData.at(i).key); - (*linePixelData)[i*2+0].setX(zeroPointX); - (*linePixelData)[i*2+0].setY(key); - (*linePixelData)[i*2+1].setX(valueAxis->coordToPixel(lineData.at(i).value)); - (*linePixelData)[i*2+1].setY(key); + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as linePixelData"; return; } + + QVector lineData; + getPreparedData(&lineData, scatterData); + linePixelData->resize(lineData.size()*2); // no need to reserve 2 extra points because impulse plot has no fill + + // transform lineData points to pixels: + if (keyAxis->orientation() == Qt::Vertical) + { + double zeroPointX = valueAxis->coordToPixel(0); + double key; + for (int i=0; icoordToPixel(lineData.at(i).key); + (*linePixelData)[i*2+0].setX(zeroPointX); + (*linePixelData)[i*2+0].setY(key); + (*linePixelData)[i*2+1].setX(valueAxis->coordToPixel(lineData.at(i).value)); + (*linePixelData)[i*2+1].setY(key); } } else // key axis is horizontal { - double zeroPointY = valueAxis->coordToPixel(0); - double key; - for (int i=0; icoordToPixel(lineData.at(i).key); - (*linePixelData)[i*2+0].setX(key); - (*linePixelData)[i*2+0].setY(zeroPointY); - (*linePixelData)[i*2+1].setX(key); - (*linePixelData)[i*2+1].setY(valueAxis->coordToPixel(lineData.at(i).value)); + double zeroPointY = valueAxis->coordToPixel(0); + double key; + for (int i=0; icoordToPixel(lineData.at(i).key); + (*linePixelData)[i*2+0].setX(key); + (*linePixelData)[i*2+0].setY(zeroPointY); + (*linePixelData)[i*2+1].setX(key); + (*linePixelData)[i*2+1].setY(valueAxis->coordToPixel(lineData.at(i).value)); } } } @@ -15524,24 +15499,24 @@ void QCPGraph::getImpulsePlotData(QVecto */ void QCPGraph::drawFill(QCPPainter *painter, QVector *lineData) const { - if (mLineStyle == lsImpulse) return; // fill doesn't make sense for impulse plot - if (mainBrush().style() == Qt::NoBrush || mainBrush().color().alpha() == 0) return; - - applyFillAntialiasingHint(painter); - if (!mChannelFillGraph) - { - // draw base fill under graph, fill goes all the way to the zero-value-line: - addFillBasePoints(lineData); - painter->setPen(Qt::NoPen); - painter->setBrush(mainBrush()); - painter->drawPolygon(QPolygonF(*lineData)); - removeFillBasePoints(lineData); - } else - { - // draw channel fill between this graph and mChannelFillGraph: - painter->setPen(Qt::NoPen); - painter->setBrush(mainBrush()); - painter->drawPolygon(getChannelFillPolygon(lineData)); + if (mLineStyle == lsImpulse) return; // fill doesn't make sense for impulse plot + if (mainBrush().style() == Qt::NoBrush || mainBrush().color().alpha() == 0) return; + + applyFillAntialiasingHint(painter); + if (!mChannelFillGraph) + { + // draw base fill under graph, fill goes all the way to the zero-value-line: + addFillBasePoints(lineData); + painter->setPen(Qt::NoPen); + painter->setBrush(mainBrush()); + painter->drawPolygon(QPolygonF(*lineData)); + removeFillBasePoints(lineData); + } else + { + // draw channel fill between this graph and mChannelFillGraph: + painter->setPen(Qt::NoPen); + painter->setBrush(mainBrush()); + painter->drawPolygon(getChannelFillPolygon(lineData)); } } @@ -15556,39 +15531,39 @@ void QCPGraph::drawFill(QCPPainter *pain */ void QCPGraph::drawScatterPlot(QCPPainter *painter, QVector *scatterData) const { - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - - // draw error bars: - if (mErrorType != etNone) - { - applyErrorBarsAntialiasingHint(painter); - painter->setPen(mErrorPen); - if (keyAxis->orientation() == Qt::Vertical) - { - for (int i=0; isize(); ++i) - drawError(painter, valueAxis->coordToPixel(scatterData->at(i).value), keyAxis->coordToPixel(scatterData->at(i).key), scatterData->at(i)); + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + + // draw error bars: + if (mErrorType != etNone) + { + applyErrorBarsAntialiasingHint(painter); + painter->setPen(mErrorPen); + if (keyAxis->orientation() == Qt::Vertical) + { + for (int i=0; isize(); ++i) + drawError(painter, valueAxis->coordToPixel(scatterData->at(i).value), keyAxis->coordToPixel(scatterData->at(i).key), scatterData->at(i)); } else { - for (int i=0; isize(); ++i) - drawError(painter, keyAxis->coordToPixel(scatterData->at(i).key), valueAxis->coordToPixel(scatterData->at(i).value), scatterData->at(i)); - } - } - - // draw scatter point symbols: - applyScattersAntialiasingHint(painter); - mScatterStyle.applyTo(painter, mPen); - if (keyAxis->orientation() == Qt::Vertical) - { - for (int i=0; isize(); ++i) - if (!qIsNaN(scatterData->at(i).value)) - mScatterStyle.drawShape(painter, valueAxis->coordToPixel(scatterData->at(i).value), keyAxis->coordToPixel(scatterData->at(i).key)); - } else - { - for (int i=0; isize(); ++i) - if (!qIsNaN(scatterData->at(i).value)) - mScatterStyle.drawShape(painter, keyAxis->coordToPixel(scatterData->at(i).key), valueAxis->coordToPixel(scatterData->at(i).value)); + for (int i=0; isize(); ++i) + drawError(painter, keyAxis->coordToPixel(scatterData->at(i).key), valueAxis->coordToPixel(scatterData->at(i).value), scatterData->at(i)); + } + } + + // draw scatter point symbols: + applyScattersAntialiasingHint(painter); + mScatterStyle.applyTo(painter, mPen); + if (keyAxis->orientation() == Qt::Vertical) + { + for (int i=0; isize(); ++i) + if (!qIsNaN(scatterData->at(i).value)) + mScatterStyle.drawShape(painter, valueAxis->coordToPixel(scatterData->at(i).value), keyAxis->coordToPixel(scatterData->at(i).key)); + } else + { + for (int i=0; isize(); ++i) + if (!qIsNaN(scatterData->at(i).value)) + mScatterStyle.drawShape(painter, keyAxis->coordToPixel(scatterData->at(i).key), valueAxis->coordToPixel(scatterData->at(i).value)); } } @@ -15603,14 +15578,14 @@ void QCPGraph::drawScatterPlot(QCPPainte */ void QCPGraph::drawLinePlot(QCPPainter *painter, QVector *lineData) const { - // draw line of graph: - if (mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0) - { - applyDefaultAntialiasingHint(painter); - painter->setPen(mainPen()); - painter->setBrush(Qt::NoBrush); - - /* Draws polyline in batches, currently not used: + // draw line of graph: + if (mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0) + { + applyDefaultAntialiasingHint(painter); + painter->setPen(mainPen()); + painter->setBrush(Qt::NoBrush); + + /* Draws polyline in batches, currently not used: int p = 0; while (p < lineData->size()) { @@ -15625,38 +15600,38 @@ void QCPGraph::drawLinePlot(QCPPainter * } */ - // if drawing solid line and not in PDF, use much faster line drawing instead of polyline: - if (mParentPlot->plottingHints().testFlag(QCP::phFastPolylines) && - painter->pen().style() == Qt::SolidLine && - !painter->modes().testFlag(QCPPainter::pmVectorized)&& - !painter->modes().testFlag(QCPPainter::pmNoCaching)) - { - int i = 1; - int lineDataSize = lineData->size(); - while (i < lineDataSize) - { - if (!qIsNaN(lineData->at(i).y()) && !qIsNaN(lineData->at(i).x())) // NaNs create a gap in the line - painter->drawLine(lineData->at(i-1), lineData->at(i)); - else + // if drawing solid line and not in PDF, use much faster line drawing instead of polyline: + if (mParentPlot->plottingHints().testFlag(QCP::phFastPolylines) && + painter->pen().style() == Qt::SolidLine && + !painter->modes().testFlag(QCPPainter::pmVectorized)&& + !painter->modes().testFlag(QCPPainter::pmNoCaching)) + { + int i = 1; + int lineDataSize = lineData->size(); + while (i < lineDataSize) + { + if (!qIsNaN(lineData->at(i).y()) && !qIsNaN(lineData->at(i).x())) // NaNs create a gap in the line + painter->drawLine(lineData->at(i-1), lineData->at(i)); + else + ++i; ++i; - ++i; } } else { - int segmentStart = 0; - int i = 0; - int lineDataSize = lineData->size(); - while (i < lineDataSize) - { - if (qIsNaN(lineData->at(i).y()) || qIsNaN(lineData->at(i).x())) // NaNs create a gap in the line + int segmentStart = 0; + int i = 0; + int lineDataSize = lineData->size(); + while (i < lineDataSize) + { + if (qIsNaN(lineData->at(i).y()) || qIsNaN(lineData->at(i).x())) // NaNs create a gap in the line { - painter->drawPolyline(lineData->constData()+segmentStart, i-segmentStart); // i, because we don't want to include the current NaN point - segmentStart = i+1; + painter->drawPolyline(lineData->constData()+segmentStart, i-segmentStart); // i, because we don't want to include the current NaN point + segmentStart = i+1; } - ++i; - } - // draw last segment: - painter->drawPolyline(lineData->constData()+segmentStart, lineDataSize-segmentStart); // lineDataSize, because we do want to include the last point + ++i; + } + // draw last segment: + painter->drawPolyline(lineData->constData()+segmentStart, lineDataSize-segmentStart); // lineDataSize, because we do want to include the last point } } } @@ -15670,15 +15645,15 @@ void QCPGraph::drawLinePlot(QCPPainter * */ void QCPGraph::drawImpulsePlot(QCPPainter *painter, QVector *lineData) const { - // draw impulses: - if (mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0) - { - applyDefaultAntialiasingHint(painter); - QPen pen = mainPen(); - pen.setCapStyle(Qt::FlatCap); // so impulse line doesn't reach beyond zero-line - painter->setPen(pen); - painter->setBrush(Qt::NoBrush); - painter->drawLines(*lineData); + // draw impulses: + if (mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0) + { + applyDefaultAntialiasingHint(painter); + QPen pen = mainPen(); + pen.setCapStyle(Qt::FlatCap); // so impulse line doesn't reach beyond zero-line + painter->setPen(pen); + painter->setBrush(Qt::NoBrush); + painter->drawLines(*lineData); } } @@ -15696,368 +15671,182 @@ void QCPGraph::drawImpulsePlot(QCPPainte */ void QCPGraph::getPreparedData(QVector *lineData, QVector *scatterData) const { - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - // get visible data range: - QCPDataMap::const_iterator lower, upper; // note that upper is the actual upper point, and not 1 step after the upper point - getVisibleDataBounds(lower, upper); - if (lower == mData->constEnd() || upper == mData->constEnd()) - return; - - // count points in visible range, taking into account that we only need to count to the limit maxCount if using adaptive sampling: - int maxCount = std::numeric_limits::max(); - if (mAdaptiveSampling) - { - int keyPixelSpan = qAbs(keyAxis->coordToPixel(lower.key())-keyAxis->coordToPixel(upper.key())); - maxCount = 2*keyPixelSpan+2; - } - int dataCount = countDataInBounds(lower, upper, maxCount); - - if (mAdaptiveSampling && dataCount >= maxCount) // use adaptive sampling only if there are at least two points per pixel on average - { - if (lineData) - { - QCPDataMap::const_iterator it = lower; - QCPDataMap::const_iterator upperEnd = upper+1; - double minValue = it.value().value; - double maxValue = it.value().value; - QCPDataMap::const_iterator currentIntervalFirstPoint = it; - int reversedFactor = keyAxis->rangeReversed() != (keyAxis->orientation()==Qt::Vertical) ? -1 : 1; // is used to calculate keyEpsilon pixel into the correct direction - int reversedRound = keyAxis->rangeReversed() != (keyAxis->orientation()==Qt::Vertical) ? 1 : 0; // is used to switch between floor (normal) and ceil (reversed) rounding of currentIntervalStartKey - double currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel(lower.key())+reversedRound)); - double lastIntervalEndKey = currentIntervalStartKey; - double keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); // interval of one pixel on screen when mapped to plot key coordinates - bool keyEpsilonVariable = keyAxis->scaleType() == QCPAxis::stLogarithmic; // indicates whether keyEpsilon needs to be updated after every interval (for log axes) - int intervalDataCount = 1; - ++it; // advance iterator to second data point because adaptive sampling works in 1 point retrospect - while (it != upperEnd) - { - if (it.key() < currentIntervalStartKey+keyEpsilon) // data point is still within same pixel, so skip it and expand value span of this cluster if necessary + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + // get visible data range: + QCPDataMap::const_iterator lower, upper; // note that upper is the actual upper point, and not 1 step after the upper point + getVisibleDataBounds(lower, upper); + if (lower == mData->constEnd() || upper == mData->constEnd()) + return; + + // count points in visible range, taking into account that we only need to count to the limit maxCount if using adaptive sampling: + int maxCount = std::numeric_limits::max(); + if (mAdaptiveSampling) + { + int keyPixelSpan = qAbs(keyAxis->coordToPixel(lower.key())-keyAxis->coordToPixel(upper.key())); + maxCount = 2*keyPixelSpan+2; + } + int dataCount = countDataInBounds(lower, upper, maxCount); + + if (mAdaptiveSampling && dataCount >= maxCount) // use adaptive sampling only if there are at least two points per pixel on average + { + if (lineData) + { + QCPDataMap::const_iterator it = lower; + QCPDataMap::const_iterator upperEnd = upper+1; + double minValue = it.value().value; + double maxValue = it.value().value; + QCPDataMap::const_iterator currentIntervalFirstPoint = it; + int reversedFactor = keyAxis->rangeReversed() != (keyAxis->orientation()==Qt::Vertical) ? -1 : 1; // is used to calculate keyEpsilon pixel into the correct direction + int reversedRound = keyAxis->rangeReversed() != (keyAxis->orientation()==Qt::Vertical) ? 1 : 0; // is used to switch between floor (normal) and ceil (reversed) rounding of currentIntervalStartKey + double currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel(lower.key())+reversedRound)); + double lastIntervalEndKey = currentIntervalStartKey; + double keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); // interval of one pixel on screen when mapped to plot key coordinates + bool keyEpsilonVariable = keyAxis->scaleType() == QCPAxis::stLogarithmic; // indicates whether keyEpsilon needs to be updated after every interval (for log axes) + int intervalDataCount = 1; + ++it; // advance iterator to second data point because adaptive sampling works in 1 point retrospect + while (it != upperEnd) + { + if (it.key() < currentIntervalStartKey+keyEpsilon) // data point is still within same pixel, so skip it and expand value span of this cluster if necessary { - if (it.value().value < minValue) - minValue = it.value().value; - else if (it.value().value > maxValue) - maxValue = it.value().value; - ++intervalDataCount; + if (it.value().value < minValue) + minValue = it.value().value; + else if (it.value().value > maxValue) + maxValue = it.value().value; + ++intervalDataCount; } else // new pixel interval started { - if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them to a cluster + if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them to a cluster { - if (lastIntervalEndKey < currentIntervalStartKey-keyEpsilon) // last point is further away, so first point of this cluster must be at a real data point - lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.2, currentIntervalFirstPoint.value().value)); - lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.25, minValue)); - lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.75, maxValue)); - if (it.key() > currentIntervalStartKey+keyEpsilon*2) // new pixel started further away from previous cluster, so make sure the last point of the cluster is at a real data point - lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.8, (it-1).value().value)); + if (lastIntervalEndKey < currentIntervalStartKey-keyEpsilon) // last point is further away, so first point of this cluster must be at a real data point + lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.2, currentIntervalFirstPoint.value().value)); + lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.25, minValue)); + lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.75, maxValue)); + if (it.key() > currentIntervalStartKey+keyEpsilon*2) // new pixel started further away from previous cluster, so make sure the last point of the cluster is at a real data point + lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.8, (it-1).value().value)); } else - lineData->append(QCPData(currentIntervalFirstPoint.key(), currentIntervalFirstPoint.value().value)); - lastIntervalEndKey = (it-1).value().key; - minValue = it.value().value; - maxValue = it.value().value; - currentIntervalFirstPoint = it; - currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel(it.key())+reversedRound)); - if (keyEpsilonVariable) - keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); - intervalDataCount = 1; + lineData->append(QCPData(currentIntervalFirstPoint.key(), currentIntervalFirstPoint.value().value)); + lastIntervalEndKey = (it-1).value().key; + minValue = it.value().value; + maxValue = it.value().value; + currentIntervalFirstPoint = it; + currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel(it.key())+reversedRound)); + if (keyEpsilonVariable) + keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); + intervalDataCount = 1; } - ++it; - } - // handle last interval: - if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them to a cluster - { - if (lastIntervalEndKey < currentIntervalStartKey-keyEpsilon) // last point wasn't a cluster, so first point of this cluster must be at a real data point - lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.2, currentIntervalFirstPoint.value().value)); - lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.25, minValue)); - lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.75, maxValue)); + ++it; + } + // handle last interval: + if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them to a cluster + { + if (lastIntervalEndKey < currentIntervalStartKey-keyEpsilon) // last point wasn't a cluster, so first point of this cluster must be at a real data point + lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.2, currentIntervalFirstPoint.value().value)); + lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.25, minValue)); + lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.75, maxValue)); } else - lineData->append(QCPData(currentIntervalFirstPoint.key(), currentIntervalFirstPoint.value().value)); - } - - if (scatterData) - { - double valueMaxRange = valueAxis->range().upper; - double valueMinRange = valueAxis->range().lower; - QCPDataMap::const_iterator it = lower; - QCPDataMap::const_iterator upperEnd = upper+1; - double minValue = it.value().value; - double maxValue = it.value().value; - QCPDataMap::const_iterator minValueIt = it; - QCPDataMap::const_iterator maxValueIt = it; - QCPDataMap::const_iterator currentIntervalStart = it; - int reversedFactor = keyAxis->rangeReversed() ? -1 : 1; // is used to calculate keyEpsilon pixel into the correct direction - int reversedRound = keyAxis->rangeReversed() ? 1 : 0; // is used to switch between floor (normal) and ceil (reversed) rounding of currentIntervalStartKey - double currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel(lower.key())+reversedRound)); - double keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); // interval of one pixel on screen when mapped to plot key coordinates - bool keyEpsilonVariable = keyAxis->scaleType() == QCPAxis::stLogarithmic; // indicates whether keyEpsilon needs to be updated after every interval (for log axes) - int intervalDataCount = 1; - ++it; // advance iterator to second data point because adaptive sampling works in 1 point retrospect - while (it != upperEnd) - { - if (it.key() < currentIntervalStartKey+keyEpsilon) // data point is still within same pixel, so skip it and expand value span of this pixel if necessary + lineData->append(QCPData(currentIntervalFirstPoint.key(), currentIntervalFirstPoint.value().value)); + } + + if (scatterData) + { + double valueMaxRange = valueAxis->range().upper; + double valueMinRange = valueAxis->range().lower; + QCPDataMap::const_iterator it = lower; + QCPDataMap::const_iterator upperEnd = upper+1; + double minValue = it.value().value; + double maxValue = it.value().value; + QCPDataMap::const_iterator minValueIt = it; + QCPDataMap::const_iterator maxValueIt = it; + QCPDataMap::const_iterator currentIntervalStart = it; + int reversedFactor = keyAxis->rangeReversed() ? -1 : 1; // is used to calculate keyEpsilon pixel into the correct direction + int reversedRound = keyAxis->rangeReversed() ? 1 : 0; // is used to switch between floor (normal) and ceil (reversed) rounding of currentIntervalStartKey + double currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel(lower.key())+reversedRound)); + double keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); // interval of one pixel on screen when mapped to plot key coordinates + bool keyEpsilonVariable = keyAxis->scaleType() == QCPAxis::stLogarithmic; // indicates whether keyEpsilon needs to be updated after every interval (for log axes) + int intervalDataCount = 1; + ++it; // advance iterator to second data point because adaptive sampling works in 1 point retrospect + while (it != upperEnd) + { + if (it.key() < currentIntervalStartKey+keyEpsilon) // data point is still within same pixel, so skip it and expand value span of this pixel if necessary { - if (it.value().value < minValue && it.value().value > valueMinRange && it.value().value < valueMaxRange) + if (it.value().value < minValue && it.value().value > valueMinRange && it.value().value < valueMaxRange) { - minValue = it.value().value; - minValueIt = it; + minValue = it.value().value; + minValueIt = it; } else if (it.value().value > maxValue && it.value().value > valueMinRange && it.value().value < valueMaxRange) { - maxValue = it.value().value; - maxValueIt = it; + maxValue = it.value().value; + maxValueIt = it; } - ++intervalDataCount; + ++intervalDataCount; } else // new pixel started { - if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them + if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them { - // determine value pixel span and add as many points in interval to maintain certain vertical data density (this is specific to scatter plot): - double valuePixelSpan = qAbs(valueAxis->coordToPixel(minValue)-valueAxis->coordToPixel(maxValue)); - int dataModulo = qMax(1, qRound(intervalDataCount/(valuePixelSpan/4.0))); // approximately every 4 value pixels one data point on average - QCPDataMap::const_iterator intervalIt = currentIntervalStart; - int c = 0; - while (intervalIt != it) + // determine value pixel span and add as many points in interval to maintain certain vertical data density (this is specific to scatter plot): + double valuePixelSpan = qAbs(valueAxis->coordToPixel(minValue)-valueAxis->coordToPixel(maxValue)); + int dataModulo = qMax(1, qRound(intervalDataCount/(valuePixelSpan/4.0))); // approximately every 4 value pixels one data point on average + QCPDataMap::const_iterator intervalIt = currentIntervalStart; + int c = 0; + while (intervalIt != it) { - if ((c % dataModulo == 0 || intervalIt == minValueIt || intervalIt == maxValueIt) && intervalIt.value().value > valueMinRange && intervalIt.value().value < valueMaxRange) - scatterData->append(intervalIt.value()); - ++c; - ++intervalIt; + if ((c % dataModulo == 0 || intervalIt == minValueIt || intervalIt == maxValueIt) && intervalIt.value().value > valueMinRange && intervalIt.value().value < valueMaxRange) + scatterData->append(intervalIt.value()); + ++c; + ++intervalIt; } } else if (currentIntervalStart.value().value > valueMinRange && currentIntervalStart.value().value < valueMaxRange) - scatterData->append(currentIntervalStart.value()); - minValue = it.value().value; - maxValue = it.value().value; - currentIntervalStart = it; - currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel(it.key())+reversedRound)); - if (keyEpsilonVariable) - keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); - intervalDataCount = 1; + scatterData->append(currentIntervalStart.value()); + minValue = it.value().value; + maxValue = it.value().value; + currentIntervalStart = it; + currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel(it.key())+reversedRound)); + if (keyEpsilonVariable) + keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); + intervalDataCount = 1; } - ++it; - } - // handle last interval: - if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them - { - // determine value pixel span and add as many points in interval to maintain certain vertical data density (this is specific to scatter plot): - double valuePixelSpan = qAbs(valueAxis->coordToPixel(minValue)-valueAxis->coordToPixel(maxValue)); - int dataModulo = qMax(1, qRound(intervalDataCount/(valuePixelSpan/4.0))); // approximately every 4 value pixels one data point on average - QCPDataMap::const_iterator intervalIt = currentIntervalStart; - int c = 0; - while (intervalIt != it) + ++it; + } + // handle last interval: + if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them + { + // determine value pixel span and add as many points in interval to maintain certain vertical data density (this is specific to scatter plot): + double valuePixelSpan = qAbs(valueAxis->coordToPixel(minValue)-valueAxis->coordToPixel(maxValue)); + int dataModulo = qMax(1, qRound(intervalDataCount/(valuePixelSpan/4.0))); // approximately every 4 value pixels one data point on average + QCPDataMap::const_iterator intervalIt = currentIntervalStart; + int c = 0; + while (intervalIt != it) { - if ((c % dataModulo == 0 || intervalIt == minValueIt || intervalIt == maxValueIt) && intervalIt.value().value > valueMinRange && intervalIt.value().value < valueMaxRange) - scatterData->append(intervalIt.value()); - ++c; - ++intervalIt; + if ((c % dataModulo == 0 || intervalIt == minValueIt || intervalIt == maxValueIt) && intervalIt.value().value > valueMinRange && intervalIt.value().value < valueMaxRange) + scatterData->append(intervalIt.value()); + ++c; + ++intervalIt; } } else if (currentIntervalStart.value().value > valueMinRange && currentIntervalStart.value().value < valueMaxRange) - scatterData->append(currentIntervalStart.value()); + scatterData->append(currentIntervalStart.value()); } } else // don't use adaptive sampling algorithm, transfer points one-to-one from the map into the output parameters { - QVector *dataVector = 0; - if (lineData) - { - dataVector = lineData; - } - else if (scatterData) - dataVector = scatterData; - if (dataVector) - { - QCPDataMap::const_iterator it = lower; - QCPDataMap::const_iterator upperEnd = upper+1; - dataVector->reserve(dataCount+2); // +2 for possible fill end points - while (it != upperEnd) - { - dataVector->append(it.value()); - ++it; - } - } - if (lineData && scatterData) - *scatterData = *dataVector; - } -} - - -void QCPGraph::getPreparedDataVector(QVector *lineData, QVector *scatterData) const -{ - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - // get visible data range: - QVector::const_iterator lower, upper; // note that upper is the actual upper point, and not 1 step after the upper point - getVisibleDataBoundsVector(lower, upper); - if (lower == mDataVector->constEnd() || upper == mDataVector->constEnd()) - return; - - // count points in visible range, taking into account that we only need to count to the limit maxCount if using adaptive sampling: - int maxCount = std::numeric_limits::max(); - if (mAdaptiveSampling) - { - int keyPixelSpan = qAbs(keyAxis->coordToPixel((*lower).key)-keyAxis->coordToPixel((*upper).key)); - maxCount = 2*keyPixelSpan+2; - } - int dataCount = countDataInBoundsVector(lower, upper, maxCount); - - if (mAdaptiveSampling && dataCount >= maxCount) // use adaptive sampling only if there are at least two points per pixel on average - { - if (lineData) - { - QVector::const_iterator it = lower; - QVector::const_iterator upperEnd = upper+1; - double minValue = (*it).value; - double maxValue = (*it).value; - QVector::const_iterator currentIntervalFirstPoint = it; - int reversedFactor = keyAxis->rangeReversed() != (keyAxis->orientation()==Qt::Vertical) ? -1 : 1; // is used to calculate keyEpsilon pixel into the correct direction - int reversedRound = keyAxis->rangeReversed() != (keyAxis->orientation()==Qt::Vertical) ? 1 : 0; // is used to switch between floor (normal) and ceil (reversed) rounding of currentIntervalStartKey - double currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel((*lower).key)+reversedRound)); - double lastIntervalEndKey = currentIntervalStartKey; - double keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); // interval of one pixel on screen when mapped to plot key coordinates - bool keyEpsilonVariable = keyAxis->scaleType() == QCPAxis::stLogarithmic; // indicates whether keyEpsilon needs to be updated after every interval (for log axes) - int intervalDataCount = 1; - ++it; // advance iterator to second data point because adaptive sampling works in 1 point retrospect - while (it != upperEnd) - { - if ((*it).key < currentIntervalStartKey+keyEpsilon) // data point is still within same pixel, so skip it and expand value span of this cluster if necessary - { - if ((*it).value < minValue) - minValue = (*it).value; - else if ((*it).value > maxValue) - maxValue = (*it).value; - ++intervalDataCount; - } else // new pixel interval started - { - if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them to a cluster - { - if (lastIntervalEndKey < currentIntervalStartKey-keyEpsilon) // last point is further away, so first point of this cluster must be at a real data point - lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.2, (*currentIntervalFirstPoint).value)); - lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.25, minValue)); - lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.75, maxValue)); - if ((*it).key > currentIntervalStartKey+keyEpsilon*2) // new pixel started further away from previous cluster, so make sure the last point of the cluster is at a real data point - lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.8, (*(it-1)).value)); - } else - lineData->append(QCPData((*currentIntervalFirstPoint).key, (*currentIntervalFirstPoint).value)); - lastIntervalEndKey = (*(it-1)).key; - minValue = (*it).value; - maxValue = (*it).value; - currentIntervalFirstPoint = it; - currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel((*it).key)+reversedRound)); - if (keyEpsilonVariable) - keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); - intervalDataCount = 1; - } - ++it; - } - // handle last interval: - if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them to a cluster - { - if (lastIntervalEndKey < currentIntervalStartKey-keyEpsilon) // last point wasn't a cluster, so first point of this cluster must be at a real data point - lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.2, (*currentIntervalFirstPoint).value)); - lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.25, minValue)); - lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.75, maxValue)); - } else - lineData->append(QCPData((*currentIntervalFirstPoint).key, (*currentIntervalFirstPoint).value)); - } - - if (scatterData) - { - double valueMaxRange = valueAxis->range().upper; - double valueMinRange = valueAxis->range().lower; - QVector::const_iterator it = lower; - QVector::const_iterator upperEnd = upper+1; - double minValue = (*it).value; - double maxValue = (*it).value; - QVector::const_iterator minValueIt = it; - QVector::const_iterator maxValueIt = it; - QVector::const_iterator currentIntervalStart = it; - int reversedFactor = keyAxis->rangeReversed() ? -1 : 1; // is used to calculate keyEpsilon pixel into the correct direction - int reversedRound = keyAxis->rangeReversed() ? 1 : 0; // is used to switch between floor (normal) and ceil (reversed) rounding of currentIntervalStartKey - double currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel((*lower).key)+reversedRound)); - double keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); // interval of one pixel on screen when mapped to plot key coordinates - bool keyEpsilonVariable = keyAxis->scaleType() == QCPAxis::stLogarithmic; // indicates whether keyEpsilon needs to be updated after every interval (for log axes) - int intervalDataCount = 1; - ++it; // advance iterator to second data point because adaptive sampling works in 1 point retrospect - while (it != upperEnd) - { - if ((*it).key < currentIntervalStartKey+keyEpsilon) // data point is still within same pixel, so skip it and expand value span of this pixel if necessary - { - if ((*it).value < minValue && (*it).value > valueMinRange && (*it).value < valueMaxRange) - { - minValue = (*it).value; - minValueIt = it; - } else if ((*it).value > maxValue && (*it).value > valueMinRange && (*it).value < valueMaxRange) - { - maxValue = (*it).value; - maxValueIt = it; - } - ++intervalDataCount; - } else // new pixel started - { - if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them - { - // determine value pixel span and add as many points in interval to maintain certain vertical data density (this is specific to scatter plot): - double valuePixelSpan = qAbs(valueAxis->coordToPixel(minValue)-valueAxis->coordToPixel(maxValue)); - int dataModulo = qMax(1, qRound(intervalDataCount/(valuePixelSpan/4.0))); // approximately every 4 value pixels one data point on average - QVector::const_iterator intervalIt = currentIntervalStart; - int c = 0; - while (intervalIt != it) - { - if ((c % dataModulo == 0 || intervalIt == minValueIt || intervalIt == maxValueIt) && (*intervalIt).value > valueMinRange && (*intervalIt).value < valueMaxRange) - scatterData->append((*intervalIt)); - ++c; - ++intervalIt; - } - } else if ((*currentIntervalStart).value > valueMinRange && (*currentIntervalStart).value < valueMaxRange) - scatterData->append((*currentIntervalStart)); - minValue = (*it).value; - maxValue = (*it).value; - currentIntervalStart = it; - currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel((*it).key)+reversedRound)); - if (keyEpsilonVariable) - keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); - intervalDataCount = 1; - } - ++it; - } - // handle last interval: - if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them - { - // determine value pixel span and add as many points in interval to maintain certain vertical data density (this is specific to scatter plot): - double valuePixelSpan = qAbs(valueAxis->coordToPixel(minValue)-valueAxis->coordToPixel(maxValue)); - int dataModulo = qMax(1, qRound(intervalDataCount/(valuePixelSpan/4.0))); // approximately every 4 value pixels one data point on average - QVector::const_iterator intervalIt = currentIntervalStart; - int c = 0; - while (intervalIt != it) - { - if ((c % dataModulo == 0 || intervalIt == minValueIt || intervalIt == maxValueIt) && (*intervalIt).value > valueMinRange && (*intervalIt).value < valueMaxRange) - scatterData->append((*intervalIt)); - ++c; - ++intervalIt; - } - } else if ((*currentIntervalStart).value > valueMinRange && (*currentIntervalStart).value < valueMaxRange) - scatterData->append(*currentIntervalStart); - } - } else // don't use adaptive sampling algorithm, transfer points one-to-one from the map into the output parameters - { - QVector *dataVector = 0; - if (lineData) - { - dataVector = lineData; - } - else if (scatterData) - dataVector = scatterData; - if (dataVector) - { - QVector::const_iterator it = lower; - QVector::const_iterator upperEnd = upper+1; - dataVector->reserve(dataCount+2); // +2 for possible fill end points - while (it != upperEnd) - { - dataVector->append(*it); - ++it; - } - } - if (lineData && scatterData) - *scatterData = *dataVector; + QVector *dataVector = 0; + if (lineData) + dataVector = lineData; + else if (scatterData) + dataVector = scatterData; + if (dataVector) + { + QCPDataMap::const_iterator it = lower; + QCPDataMap::const_iterator upperEnd = upper+1; + dataVector->reserve(dataCount+2); // +2 for possible fill end points + while (it != upperEnd) + { + dataVector->append(it.value()); + ++it; + } + } + if (lineData && scatterData) + *scatterData = *dataVector; } } @@ -16070,97 +15859,97 @@ void QCPGraph::getPreparedDataVector(QVe */ void QCPGraph::drawError(QCPPainter *painter, double x, double y, const QCPData &data) const { - if (qIsNaN(data.value)) - return; - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - - double a, b; // positions of error bar bounds in pixels - double barWidthHalf = mErrorBarSize*0.5; - double skipSymbolMargin = mScatterStyle.size(); // pixels left blank per side, when mErrorBarSkipSymbol is true - - if (keyAxis->orientation() == Qt::Vertical) - { - // draw key error vertically and value error horizontally - if (mErrorType == etKey || mErrorType == etBoth) - { - a = keyAxis->coordToPixel(data.key-data.keyErrorMinus); - b = keyAxis->coordToPixel(data.key+data.keyErrorPlus); - if (keyAxis->rangeReversed()) - qSwap(a,b); - // draw spine: - if (mErrorBarSkipSymbol) - { - if (a-y > skipSymbolMargin) // don't draw spine if error is so small it's within skipSymbolmargin - painter->drawLine(QLineF(x, a, x, y+skipSymbolMargin)); - if (y-b > skipSymbolMargin) - painter->drawLine(QLineF(x, y-skipSymbolMargin, x, b)); + if (qIsNaN(data.value)) + return; + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + + double a, b; // positions of error bar bounds in pixels + double barWidthHalf = mErrorBarSize*0.5; + double skipSymbolMargin = mScatterStyle.size(); // pixels left blank per side, when mErrorBarSkipSymbol is true + + if (keyAxis->orientation() == Qt::Vertical) + { + // draw key error vertically and value error horizontally + if (mErrorType == etKey || mErrorType == etBoth) + { + a = keyAxis->coordToPixel(data.key-data.keyErrorMinus); + b = keyAxis->coordToPixel(data.key+data.keyErrorPlus); + if (keyAxis->rangeReversed()) + qSwap(a,b); + // draw spine: + if (mErrorBarSkipSymbol) + { + if (a-y > skipSymbolMargin) // don't draw spine if error is so small it's within skipSymbolmargin + painter->drawLine(QLineF(x, a, x, y+skipSymbolMargin)); + if (y-b > skipSymbolMargin) + painter->drawLine(QLineF(x, y-skipSymbolMargin, x, b)); } else - painter->drawLine(QLineF(x, a, x, b)); - // draw handles: - painter->drawLine(QLineF(x-barWidthHalf, a, x+barWidthHalf, a)); - painter->drawLine(QLineF(x-barWidthHalf, b, x+barWidthHalf, b)); - } - if (mErrorType == etValue || mErrorType == etBoth) - { - a = valueAxis->coordToPixel(data.value-data.valueErrorMinus); - b = valueAxis->coordToPixel(data.value+data.valueErrorPlus); - if (valueAxis->rangeReversed()) - qSwap(a,b); - // draw spine: - if (mErrorBarSkipSymbol) - { - if (x-a > skipSymbolMargin) // don't draw spine if error is so small it's within skipSymbolmargin - painter->drawLine(QLineF(a, y, x-skipSymbolMargin, y)); - if (b-x > skipSymbolMargin) - painter->drawLine(QLineF(x+skipSymbolMargin, y, b, y)); + painter->drawLine(QLineF(x, a, x, b)); + // draw handles: + painter->drawLine(QLineF(x-barWidthHalf, a, x+barWidthHalf, a)); + painter->drawLine(QLineF(x-barWidthHalf, b, x+barWidthHalf, b)); + } + if (mErrorType == etValue || mErrorType == etBoth) + { + a = valueAxis->coordToPixel(data.value-data.valueErrorMinus); + b = valueAxis->coordToPixel(data.value+data.valueErrorPlus); + if (valueAxis->rangeReversed()) + qSwap(a,b); + // draw spine: + if (mErrorBarSkipSymbol) + { + if (x-a > skipSymbolMargin) // don't draw spine if error is so small it's within skipSymbolmargin + painter->drawLine(QLineF(a, y, x-skipSymbolMargin, y)); + if (b-x > skipSymbolMargin) + painter->drawLine(QLineF(x+skipSymbolMargin, y, b, y)); } else - painter->drawLine(QLineF(a, y, b, y)); - // draw handles: - painter->drawLine(QLineF(a, y-barWidthHalf, a, y+barWidthHalf)); - painter->drawLine(QLineF(b, y-barWidthHalf, b, y+barWidthHalf)); + painter->drawLine(QLineF(a, y, b, y)); + // draw handles: + painter->drawLine(QLineF(a, y-barWidthHalf, a, y+barWidthHalf)); + painter->drawLine(QLineF(b, y-barWidthHalf, b, y+barWidthHalf)); } } else // mKeyAxis->orientation() is Qt::Horizontal { - // draw value error vertically and key error horizontally - if (mErrorType == etKey || mErrorType == etBoth) - { - a = keyAxis->coordToPixel(data.key-data.keyErrorMinus); - b = keyAxis->coordToPixel(data.key+data.keyErrorPlus); - if (keyAxis->rangeReversed()) - qSwap(a,b); - // draw spine: - if (mErrorBarSkipSymbol) - { - if (x-a > skipSymbolMargin) // don't draw spine if error is so small it's within skipSymbolmargin - painter->drawLine(QLineF(a, y, x-skipSymbolMargin, y)); - if (b-x > skipSymbolMargin) - painter->drawLine(QLineF(x+skipSymbolMargin, y, b, y)); + // draw value error vertically and key error horizontally + if (mErrorType == etKey || mErrorType == etBoth) + { + a = keyAxis->coordToPixel(data.key-data.keyErrorMinus); + b = keyAxis->coordToPixel(data.key+data.keyErrorPlus); + if (keyAxis->rangeReversed()) + qSwap(a,b); + // draw spine: + if (mErrorBarSkipSymbol) + { + if (x-a > skipSymbolMargin) // don't draw spine if error is so small it's within skipSymbolmargin + painter->drawLine(QLineF(a, y, x-skipSymbolMargin, y)); + if (b-x > skipSymbolMargin) + painter->drawLine(QLineF(x+skipSymbolMargin, y, b, y)); } else - painter->drawLine(QLineF(a, y, b, y)); - // draw handles: - painter->drawLine(QLineF(a, y-barWidthHalf, a, y+barWidthHalf)); - painter->drawLine(QLineF(b, y-barWidthHalf, b, y+barWidthHalf)); - } - if (mErrorType == etValue || mErrorType == etBoth) - { - a = valueAxis->coordToPixel(data.value-data.valueErrorMinus); - b = valueAxis->coordToPixel(data.value+data.valueErrorPlus); - if (valueAxis->rangeReversed()) - qSwap(a,b); - // draw spine: - if (mErrorBarSkipSymbol) - { - if (a-y > skipSymbolMargin) // don't draw spine if error is so small it's within skipSymbolmargin - painter->drawLine(QLineF(x, a, x, y+skipSymbolMargin)); - if (y-b > skipSymbolMargin) - painter->drawLine(QLineF(x, y-skipSymbolMargin, x, b)); + painter->drawLine(QLineF(a, y, b, y)); + // draw handles: + painter->drawLine(QLineF(a, y-barWidthHalf, a, y+barWidthHalf)); + painter->drawLine(QLineF(b, y-barWidthHalf, b, y+barWidthHalf)); + } + if (mErrorType == etValue || mErrorType == etBoth) + { + a = valueAxis->coordToPixel(data.value-data.valueErrorMinus); + b = valueAxis->coordToPixel(data.value+data.valueErrorPlus); + if (valueAxis->rangeReversed()) + qSwap(a,b); + // draw spine: + if (mErrorBarSkipSymbol) + { + if (a-y > skipSymbolMargin) // don't draw spine if error is so small it's within skipSymbolmargin + painter->drawLine(QLineF(x, a, x, y+skipSymbolMargin)); + if (y-b > skipSymbolMargin) + painter->drawLine(QLineF(x, y-skipSymbolMargin, x, b)); } else - painter->drawLine(QLineF(x, a, x, b)); - // draw handles: - painter->drawLine(QLineF(x-barWidthHalf, a, x+barWidthHalf, a)); - painter->drawLine(QLineF(x-barWidthHalf, b, x+barWidthHalf, b)); + painter->drawLine(QLineF(x, a, x, b)); + // draw handles: + painter->drawLine(QLineF(x-barWidthHalf, a, x+barWidthHalf, a)); + painter->drawLine(QLineF(x-barWidthHalf, b, x+barWidthHalf, b)); } } } @@ -16181,93 +15970,22 @@ void QCPGraph::drawError(QCPPainter *pai */ void QCPGraph::getVisibleDataBounds(QCPDataMap::const_iterator &lower, QCPDataMap::const_iterator &upper) const { - if (!mKeyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; } - if (mData->isEmpty()) - { - lower = mData->constEnd(); - upper = mData->constEnd(); - return; - } - - // get visible data range as QMap iterators - QCPDataMap::const_iterator lbound = mData->lowerBound(mKeyAxis.data()->range().lower); - QCPDataMap::const_iterator ubound = mData->upperBound(mKeyAxis.data()->range().upper); - bool lowoutlier = lbound != mData->constBegin(); // indicates whether there exist points below axis range - bool highoutlier = ubound != mData->constEnd(); // indicates whether there exist points above axis range - - lower = (lowoutlier ? lbound-1 : lbound); // data point range that will be actually drawn - upper = (highoutlier ? ubound : ubound-1); // data point range that will be actually drawn -} - - - - -QVector::const_iterator __lowerBoundDico(QVector* vector,double key) -{ - int DX=vector->size()/2; - int pos=DX; - double test=(*vector)[vector->length()-1].key; - if(key>((*vector)[vector->length()-1].key)) - return vector->constEnd(); - if(key<((*vector)[0].key)) - return vector->constBegin(); - while (DX>1) - { - DX=DX/2; - if((*vector)[pos].key > key) - { - pos-=DX; - } - else - { - pos+=DX; - } - } - if((*vector)[pos].key >= key) - return vector->constBegin()+pos; - return vector->constBegin()+pos+1; -} - - -QVector::const_iterator __upperBoundDico(QVector* vector,double key) -{ - int DX=vector->size()/2; - int pos=DX; - if(key>((*vector)[vector->length()-1].key)) - return vector->constEnd(); - if(key<((*vector)[0].key)) - return vector->constBegin(); - while (DX>1) - { - DX=DX/2; - if((*vector)[pos].key > key) - { - pos-=DX; - } - else - { - pos+=DX; - } - } - return vector->constBegin()+pos+1; -} - -void QCPGraph::getVisibleDataBoundsVector(QVector::const_iterator &lower, QVector::const_iterator &upper) const -{ - if (!mKeyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; } - if (mDataVector->isEmpty()) - { - lower = mDataVector->constEnd(); - upper = mDataVector->constEnd(); - return; - } - QVector::const_iterator lbound = __lowerBoundDico(mDataVector,mKeyAxis.data()->range().lower); - QVector::const_iterator ubound = __upperBoundDico(mDataVector,mKeyAxis.data()->range().upper); - bool lowoutlier = lbound != mDataVector->constBegin(); // indicates whether there exist points below axis range - bool highoutlier = ubound != mDataVector->constEnd(); // indicates whether there exist points above axis range - - lower = (lowoutlier ? lbound-1 : lbound); // data point range that will be actually drawn - upper = (highoutlier ? ubound : ubound-1); // data point range that will be actually drawn + if (!mKeyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; } + if (mData->isEmpty()) + { + lower = mData->constEnd(); + upper = mData->constEnd(); + return; + } + + // get visible data range as QMap iterators + QCPDataMap::const_iterator lbound = mData->lowerBound(mKeyAxis.data()->range().lower); + QCPDataMap::const_iterator ubound = mData->upperBound(mKeyAxis.data()->range().upper); + bool lowoutlier = lbound != mData->constBegin(); // indicates whether there exist points below axis range + bool highoutlier = ubound != mData->constEnd(); // indicates whether there exist points above axis range + + lower = (lowoutlier ? lbound-1 : lbound); // data point range that will be actually drawn + upper = (highoutlier ? ubound : ubound-1); // data point range that will be actually drawn } /*! \internal @@ -16282,30 +16000,16 @@ void QCPGraph::getVisibleDataBoundsVecto */ int QCPGraph::countDataInBounds(const QCPDataMap::const_iterator &lower, const QCPDataMap::const_iterator &upper, int maxCount) const { - if (upper == mData->constEnd() && lower == mData->constEnd()) - return 0; - QCPDataMap::const_iterator it = lower; - int count = 1; - while (it != upper && count < maxCount) - { - ++it; - ++count; - } - return count; -} - -int QCPGraph::countDataInBoundsVector(const QVector::const_iterator &lower, const QVector::const_iterator &upper, int maxCount) const -{ - if (upper == mDataVector->constEnd() && lower == mDataVector->constEnd()) - return 0; - QVector::const_iterator it = lower; - int count = 1; - while (it != upper && count < maxCount) - { - ++it; - ++count; - } - return count; + if (upper == mData->constEnd() && lower == mData->constEnd()) + return 0; + QCPDataMap::const_iterator it = lower; + int count = 1; + while (it != upper && count < maxCount) + { + ++it; + ++count; + } + return count; } /*! \internal @@ -16325,17 +16029,17 @@ int QCPGraph::countDataInBoundsVector(co */ void QCPGraph::addFillBasePoints(QVector *lineData) const { - if (!mKeyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; } - - // append points that close the polygon fill at the key axis: - if (mKeyAxis.data()->orientation() == Qt::Vertical) - { - *lineData << upperFillBasePoint(lineData->last().y()); - *lineData << lowerFillBasePoint(lineData->first().y()); - } else - { - *lineData << upperFillBasePoint(lineData->last().x()); - *lineData << lowerFillBasePoint(lineData->first().x()); + if (!mKeyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; } + + // append points that close the polygon fill at the key axis: + if (mKeyAxis.data()->orientation() == Qt::Vertical) + { + *lineData << upperFillBasePoint(lineData->last().y()); + *lineData << lowerFillBasePoint(lineData->first().y()); + } else + { + *lineData << upperFillBasePoint(lineData->last().x()); + *lineData << lowerFillBasePoint(lineData->first().x()); } } @@ -16347,7 +16051,7 @@ void QCPGraph::addFillBasePoints(QVector */ void QCPGraph::removeFillBasePoints(QVector *lineData) const { - lineData->remove(lineData->size()-2, 2); + lineData->remove(lineData->size()-2, 2); } /*! \internal @@ -16366,53 +16070,53 @@ void QCPGraph::removeFillBasePoints(QVec */ QPointF QCPGraph::lowerFillBasePoint(double lowerKey) const { - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPointF(); } - - QPointF point; - if (valueAxis->scaleType() == QCPAxis::stLinear) - { - if (keyAxis->axisType() == QCPAxis::atLeft) - { - point.setX(valueAxis->coordToPixel(0)); - point.setY(lowerKey); + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPointF(); } + + QPointF point; + if (valueAxis->scaleType() == QCPAxis::stLinear) + { + if (keyAxis->axisType() == QCPAxis::atLeft) + { + point.setX(valueAxis->coordToPixel(0)); + point.setY(lowerKey); } else if (keyAxis->axisType() == QCPAxis::atRight) { - point.setX(valueAxis->coordToPixel(0)); - point.setY(lowerKey); + point.setX(valueAxis->coordToPixel(0)); + point.setY(lowerKey); } else if (keyAxis->axisType() == QCPAxis::atTop) { - point.setX(lowerKey); - point.setY(valueAxis->coordToPixel(0)); + point.setX(lowerKey); + point.setY(valueAxis->coordToPixel(0)); } else if (keyAxis->axisType() == QCPAxis::atBottom) { - point.setX(lowerKey); - point.setY(valueAxis->coordToPixel(0)); + point.setX(lowerKey); + point.setY(valueAxis->coordToPixel(0)); } } else // valueAxis->mScaleType == QCPAxis::stLogarithmic { - // In logarithmic scaling we can't just draw to value zero so we just fill all the way - // to the axis which is in the direction towards zero - if (keyAxis->orientation() == Qt::Vertical) - { - if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) || - (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is negative, zero is on opposite side of key axis - point.setX(keyAxis->axisRect()->right()); - else - point.setX(keyAxis->axisRect()->left()); - point.setY(lowerKey); + // In logarithmic scaling we can't just draw to value zero so we just fill all the way + // to the axis which is in the direction towards zero + if (keyAxis->orientation() == Qt::Vertical) + { + if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) || + (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is negative, zero is on opposite side of key axis + point.setX(keyAxis->axisRect()->right()); + else + point.setX(keyAxis->axisRect()->left()); + point.setY(lowerKey); } else if (keyAxis->axisType() == QCPAxis::atTop || keyAxis->axisType() == QCPAxis::atBottom) { - point.setX(lowerKey); - if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) || - (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is negative, zero is on opposite side of key axis - point.setY(keyAxis->axisRect()->top()); - else - point.setY(keyAxis->axisRect()->bottom()); - } - } - return point; + point.setX(lowerKey); + if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) || + (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is negative, zero is on opposite side of key axis + point.setY(keyAxis->axisRect()->top()); + else + point.setY(keyAxis->axisRect()->bottom()); + } + } + return point; } /*! \internal @@ -16431,53 +16135,53 @@ QPointF QCPGraph::lowerFillBasePoint(dou */ QPointF QCPGraph::upperFillBasePoint(double upperKey) const { - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPointF(); } - - QPointF point; - if (valueAxis->scaleType() == QCPAxis::stLinear) - { - if (keyAxis->axisType() == QCPAxis::atLeft) - { - point.setX(valueAxis->coordToPixel(0)); - point.setY(upperKey); + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPointF(); } + + QPointF point; + if (valueAxis->scaleType() == QCPAxis::stLinear) + { + if (keyAxis->axisType() == QCPAxis::atLeft) + { + point.setX(valueAxis->coordToPixel(0)); + point.setY(upperKey); } else if (keyAxis->axisType() == QCPAxis::atRight) { - point.setX(valueAxis->coordToPixel(0)); - point.setY(upperKey); + point.setX(valueAxis->coordToPixel(0)); + point.setY(upperKey); } else if (keyAxis->axisType() == QCPAxis::atTop) { - point.setX(upperKey); - point.setY(valueAxis->coordToPixel(0)); + point.setX(upperKey); + point.setY(valueAxis->coordToPixel(0)); } else if (keyAxis->axisType() == QCPAxis::atBottom) { - point.setX(upperKey); - point.setY(valueAxis->coordToPixel(0)); + point.setX(upperKey); + point.setY(valueAxis->coordToPixel(0)); } } else // valueAxis->mScaleType == QCPAxis::stLogarithmic { - // In logarithmic scaling we can't just draw to value 0 so we just fill all the way - // to the axis which is in the direction towards 0 - if (keyAxis->orientation() == Qt::Vertical) - { - if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) || - (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is negative, zero is on opposite side of key axis - point.setX(keyAxis->axisRect()->right()); - else - point.setX(keyAxis->axisRect()->left()); - point.setY(upperKey); + // In logarithmic scaling we can't just draw to value 0 so we just fill all the way + // to the axis which is in the direction towards 0 + if (keyAxis->orientation() == Qt::Vertical) + { + if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) || + (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is negative, zero is on opposite side of key axis + point.setX(keyAxis->axisRect()->right()); + else + point.setX(keyAxis->axisRect()->left()); + point.setY(upperKey); } else if (keyAxis->axisType() == QCPAxis::atTop || keyAxis->axisType() == QCPAxis::atBottom) { - point.setX(upperKey); - if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) || - (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is negative, zero is on opposite side of key axis - point.setY(keyAxis->axisRect()->top()); - else - point.setY(keyAxis->axisRect()->bottom()); - } - } - return point; + point.setX(upperKey); + if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) || + (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is negative, zero is on opposite side of key axis + point.setY(keyAxis->axisRect()->top()); + else + point.setY(keyAxis->axisRect()->bottom()); + } + } + return point; } /*! \internal @@ -16491,137 +16195,137 @@ QPointF QCPGraph::upperFillBasePoint(dou */ const QPolygonF QCPGraph::getChannelFillPolygon(const QVector *lineData) const { - if (!mChannelFillGraph) - return QPolygonF(); - - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPolygonF(); } - if (!mChannelFillGraph.data()->mKeyAxis) { qDebug() << Q_FUNC_INFO << "channel fill target key axis invalid"; return QPolygonF(); } - - if (mChannelFillGraph.data()->mKeyAxis.data()->orientation() != keyAxis->orientation()) - return QPolygonF(); // don't have same axis orientation, can't fill that (Note: if keyAxis fits, valueAxis will fit too, because it's always orthogonal to keyAxis) - - if (lineData->isEmpty()) return QPolygonF(); - QVector otherData; - mChannelFillGraph.data()->getPlotData(&otherData, 0); - if (otherData.isEmpty()) return QPolygonF(); - QVector thisData; - thisData.reserve(lineData->size()+otherData.size()); // because we will join both vectors at end of this function - for (int i=0; isize(); ++i) // don't use the vector<<(vector), it squeezes internally, which ruins the performance tuning with reserve() - thisData << lineData->at(i); - - // pointers to be able to swap them, depending which data range needs cropping: - QVector *staticData = &thisData; - QVector *croppedData = &otherData; - - // crop both vectors to ranges in which the keys overlap (which coord is key, depends on axisType): - if (keyAxis->orientation() == Qt::Horizontal) - { - // x is key - // if an axis range is reversed, the data point keys will be descending. Reverse them, since following algorithm assumes ascending keys: - if (staticData->first().x() > staticData->last().x()) - { - int size = staticData->size(); - for (int i=0; ifirst().x() > croppedData->last().x()) - { - int size = croppedData->size(); - for (int i=0; ifirst().x() < croppedData->first().x()) // other one must be cropped - qSwap(staticData, croppedData); - int lowBound = findIndexBelowX(croppedData, staticData->first().x()); - if (lowBound == -1) return QPolygonF(); // key ranges have no overlap - croppedData->remove(0, lowBound); - // set lowest point of cropped data to fit exactly key position of first static data - // point via linear interpolation: - if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation - double slope; - if (croppedData->at(1).x()-croppedData->at(0).x() != 0) - slope = (croppedData->at(1).y()-croppedData->at(0).y())/(croppedData->at(1).x()-croppedData->at(0).x()); - else - slope = 0; - (*croppedData)[0].setY(croppedData->at(0).y()+slope*(staticData->first().x()-croppedData->at(0).x())); - (*croppedData)[0].setX(staticData->first().x()); - - // crop upper bound: - if (staticData->last().x() > croppedData->last().x()) // other one must be cropped - qSwap(staticData, croppedData); - int highBound = findIndexAboveX(croppedData, staticData->last().x()); - if (highBound == -1) return QPolygonF(); // key ranges have no overlap - croppedData->remove(highBound+1, croppedData->size()-(highBound+1)); - // set highest point of cropped data to fit exactly key position of last static data - // point via linear interpolation: - if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation - int li = croppedData->size()-1; // last index - if (croppedData->at(li).x()-croppedData->at(li-1).x() != 0) - slope = (croppedData->at(li).y()-croppedData->at(li-1).y())/(croppedData->at(li).x()-croppedData->at(li-1).x()); - else - slope = 0; - (*croppedData)[li].setY(croppedData->at(li-1).y()+slope*(staticData->last().x()-croppedData->at(li-1).x())); - (*croppedData)[li].setX(staticData->last().x()); + if (!mChannelFillGraph) + return QPolygonF(); + + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPolygonF(); } + if (!mChannelFillGraph.data()->mKeyAxis) { qDebug() << Q_FUNC_INFO << "channel fill target key axis invalid"; return QPolygonF(); } + + if (mChannelFillGraph.data()->mKeyAxis.data()->orientation() != keyAxis->orientation()) + return QPolygonF(); // don't have same axis orientation, can't fill that (Note: if keyAxis fits, valueAxis will fit too, because it's always orthogonal to keyAxis) + + if (lineData->isEmpty()) return QPolygonF(); + QVector otherData; + mChannelFillGraph.data()->getPlotData(&otherData, 0); + if (otherData.isEmpty()) return QPolygonF(); + QVector thisData; + thisData.reserve(lineData->size()+otherData.size()); // because we will join both vectors at end of this function + for (int i=0; isize(); ++i) // don't use the vector<<(vector), it squeezes internally, which ruins the performance tuning with reserve() + thisData << lineData->at(i); + + // pointers to be able to swap them, depending which data range needs cropping: + QVector *staticData = &thisData; + QVector *croppedData = &otherData; + + // crop both vectors to ranges in which the keys overlap (which coord is key, depends on axisType): + if (keyAxis->orientation() == Qt::Horizontal) + { + // x is key + // if an axis range is reversed, the data point keys will be descending. Reverse them, since following algorithm assumes ascending keys: + if (staticData->first().x() > staticData->last().x()) + { + int size = staticData->size(); + for (int i=0; ifirst().x() > croppedData->last().x()) + { + int size = croppedData->size(); + for (int i=0; ifirst().x() < croppedData->first().x()) // other one must be cropped + qSwap(staticData, croppedData); + int lowBound = findIndexBelowX(croppedData, staticData->first().x()); + if (lowBound == -1) return QPolygonF(); // key ranges have no overlap + croppedData->remove(0, lowBound); + // set lowest point of cropped data to fit exactly key position of first static data + // point via linear interpolation: + if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation + double slope; + if (croppedData->at(1).x()-croppedData->at(0).x() != 0) + slope = (croppedData->at(1).y()-croppedData->at(0).y())/(croppedData->at(1).x()-croppedData->at(0).x()); + else + slope = 0; + (*croppedData)[0].setY(croppedData->at(0).y()+slope*(staticData->first().x()-croppedData->at(0).x())); + (*croppedData)[0].setX(staticData->first().x()); + + // crop upper bound: + if (staticData->last().x() > croppedData->last().x()) // other one must be cropped + qSwap(staticData, croppedData); + int highBound = findIndexAboveX(croppedData, staticData->last().x()); + if (highBound == -1) return QPolygonF(); // key ranges have no overlap + croppedData->remove(highBound+1, croppedData->size()-(highBound+1)); + // set highest point of cropped data to fit exactly key position of last static data + // point via linear interpolation: + if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation + int li = croppedData->size()-1; // last index + if (croppedData->at(li).x()-croppedData->at(li-1).x() != 0) + slope = (croppedData->at(li).y()-croppedData->at(li-1).y())/(croppedData->at(li).x()-croppedData->at(li-1).x()); + else + slope = 0; + (*croppedData)[li].setY(croppedData->at(li-1).y()+slope*(staticData->last().x()-croppedData->at(li-1).x())); + (*croppedData)[li].setX(staticData->last().x()); } else // mKeyAxis->orientation() == Qt::Vertical { - // y is key - // similar to "x is key" but switched x,y. Further, lower/upper meaning is inverted compared to x, - // because in pixel coordinates, y increases from top to bottom, not bottom to top like data coordinate. - // if an axis range is reversed, the data point keys will be descending. Reverse them, since following algorithm assumes ascending keys: - if (staticData->first().y() < staticData->last().y()) - { - int size = staticData->size(); - for (int i=0; ifirst().y() < croppedData->last().y()) - { - int size = croppedData->size(); - for (int i=0; ifirst().y() > croppedData->first().y()) // other one must be cropped - qSwap(staticData, croppedData); - int lowBound = findIndexAboveY(croppedData, staticData->first().y()); - if (lowBound == -1) return QPolygonF(); // key ranges have no overlap - croppedData->remove(0, lowBound); - // set lowest point of cropped data to fit exactly key position of first static data - // point via linear interpolation: - if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation - double slope; - if (croppedData->at(1).y()-croppedData->at(0).y() != 0) // avoid division by zero in step plots - slope = (croppedData->at(1).x()-croppedData->at(0).x())/(croppedData->at(1).y()-croppedData->at(0).y()); - else - slope = 0; - (*croppedData)[0].setX(croppedData->at(0).x()+slope*(staticData->first().y()-croppedData->at(0).y())); - (*croppedData)[0].setY(staticData->first().y()); - - // crop upper bound: - if (staticData->last().y() < croppedData->last().y()) // other one must be cropped - qSwap(staticData, croppedData); - int highBound = findIndexBelowY(croppedData, staticData->last().y()); - if (highBound == -1) return QPolygonF(); // key ranges have no overlap - croppedData->remove(highBound+1, croppedData->size()-(highBound+1)); - // set highest point of cropped data to fit exactly key position of last static data - // point via linear interpolation: - if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation - int li = croppedData->size()-1; // last index - if (croppedData->at(li).y()-croppedData->at(li-1).y() != 0) // avoid division by zero in step plots - slope = (croppedData->at(li).x()-croppedData->at(li-1).x())/(croppedData->at(li).y()-croppedData->at(li-1).y()); - else - slope = 0; - (*croppedData)[li].setX(croppedData->at(li-1).x()+slope*(staticData->last().y()-croppedData->at(li-1).y())); - (*croppedData)[li].setY(staticData->last().y()); - } - - // return joined: - for (int i=otherData.size()-1; i>=0; --i) // insert reversed, otherwise the polygon will be twisted - thisData << otherData.at(i); - return QPolygonF(thisData); + // y is key + // similar to "x is key" but switched x,y. Further, lower/upper meaning is inverted compared to x, + // because in pixel coordinates, y increases from top to bottom, not bottom to top like data coordinate. + // if an axis range is reversed, the data point keys will be descending. Reverse them, since following algorithm assumes ascending keys: + if (staticData->first().y() < staticData->last().y()) + { + int size = staticData->size(); + for (int i=0; ifirst().y() < croppedData->last().y()) + { + int size = croppedData->size(); + for (int i=0; ifirst().y() > croppedData->first().y()) // other one must be cropped + qSwap(staticData, croppedData); + int lowBound = findIndexAboveY(croppedData, staticData->first().y()); + if (lowBound == -1) return QPolygonF(); // key ranges have no overlap + croppedData->remove(0, lowBound); + // set lowest point of cropped data to fit exactly key position of first static data + // point via linear interpolation: + if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation + double slope; + if (croppedData->at(1).y()-croppedData->at(0).y() != 0) // avoid division by zero in step plots + slope = (croppedData->at(1).x()-croppedData->at(0).x())/(croppedData->at(1).y()-croppedData->at(0).y()); + else + slope = 0; + (*croppedData)[0].setX(croppedData->at(0).x()+slope*(staticData->first().y()-croppedData->at(0).y())); + (*croppedData)[0].setY(staticData->first().y()); + + // crop upper bound: + if (staticData->last().y() < croppedData->last().y()) // other one must be cropped + qSwap(staticData, croppedData); + int highBound = findIndexBelowY(croppedData, staticData->last().y()); + if (highBound == -1) return QPolygonF(); // key ranges have no overlap + croppedData->remove(highBound+1, croppedData->size()-(highBound+1)); + // set highest point of cropped data to fit exactly key position of last static data + // point via linear interpolation: + if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation + int li = croppedData->size()-1; // last index + if (croppedData->at(li).y()-croppedData->at(li-1).y() != 0) // avoid division by zero in step plots + slope = (croppedData->at(li).x()-croppedData->at(li-1).x())/(croppedData->at(li).y()-croppedData->at(li-1).y()); + else + slope = 0; + (*croppedData)[li].setX(croppedData->at(li-1).x()+slope*(staticData->last().y()-croppedData->at(li-1).y())); + (*croppedData)[li].setY(staticData->last().y()); + } + + // return joined: + for (int i=otherData.size()-1; i>=0; --i) // insert reversed, otherwise the polygon will be twisted + thisData << otherData.at(i); + return QPolygonF(thisData); } /*! \internal @@ -16633,17 +16337,17 @@ const QPolygonF QCPGraph::getChannelFill */ int QCPGraph::findIndexAboveX(const QVector *data, double x) const { - for (int i=data->size()-1; i>=0; --i) - { - if (data->at(i).x() < x) - { - if (isize()-1) - return i+1; - else - return data->size()-1; - } - } - return -1; + for (int i=data->size()-1; i>=0; --i) + { + if (data->at(i).x() < x) + { + if (isize()-1) + return i+1; + else + return data->size()-1; + } + } + return -1; } /*! \internal @@ -16655,17 +16359,17 @@ int QCPGraph::findIndexAboveX(const QVec */ int QCPGraph::findIndexBelowX(const QVector *data, double x) const { - for (int i=0; isize(); ++i) - { - if (data->at(i).x() > x) - { - if (i>0) - return i-1; - else - return 0; - } - } - return -1; + for (int i=0; isize(); ++i) + { + if (data->at(i).x() > x) + { + if (i>0) + return i-1; + else + return 0; + } + } + return -1; } /*! \internal @@ -16677,17 +16381,17 @@ int QCPGraph::findIndexBelowX(const QVec */ int QCPGraph::findIndexAboveY(const QVector *data, double y) const { - for (int i=0; isize(); ++i) - { - if (data->at(i).y() < y) - { - if (i>0) - return i-1; - else - return 0; - } - } - return -1; + for (int i=0; isize(); ++i) + { + if (data->at(i).y() < y) + { + if (i>0) + return i-1; + else + return 0; + } + } + return -1; } /*! \internal @@ -16702,66 +16406,66 @@ int QCPGraph::findIndexAboveY(const QVec */ double QCPGraph::pointDistance(const QPointF &pixelPoint) const { - if (mData->isEmpty()) - { - qDebug() << Q_FUNC_INFO << "requested point distance on graph" << mName << "without data"; - return 500; - } - if (mData->size() == 1) - { - QPointF dataPoint = coordsToPixels(mData->constBegin().key(), mData->constBegin().value().value); - return QVector2D(dataPoint-pixelPoint).length(); - } - - if (mLineStyle == lsNone && mScatterStyle.isNone()) - return 500; - - // calculate minimum distances to graph representation: - if (mLineStyle == lsNone) - { - // no line displayed, only calculate distance to scatter points: - QVector *scatterData = new QVector; - getScatterPlotData(scatterData); - double minDistSqr = std::numeric_limits::max(); - QPointF ptA; - QPointF ptB = coordsToPixels(scatterData->at(0).key, scatterData->at(0).value); // getScatterPlotData returns in plot coordinates, so transform to pixels - for (int i=1; isize(); ++i) - { - ptA = ptB; - ptB = coordsToPixels(scatterData->at(i).key, scatterData->at(i).value); - double currentDistSqr = distSqrToLine(ptA, ptB, pixelPoint); - if (currentDistSqr < minDistSqr) - minDistSqr = currentDistSqr; - } - delete scatterData; - return qSqrt(minDistSqr); - } else - { - // line displayed calculate distance to line segments: - QVector *lineData = new QVector; - getPlotData(lineData, 0); // unlike with getScatterPlotData we get pixel coordinates here - double minDistSqr = std::numeric_limits::max(); - if (mLineStyle == lsImpulse) - { - // impulse plot differs from other line styles in that the lineData points are only pairwise connected: - for (int i=0; isize()-1; i+=2) // iterate pairs - { - double currentDistSqr = distSqrToLine(lineData->at(i), lineData->at(i+1), pixelPoint); - if (currentDistSqr < minDistSqr) + if (mData->isEmpty()) + { + qDebug() << Q_FUNC_INFO << "requested point distance on graph" << mName << "without data"; + return 500; + } + if (mData->size() == 1) + { + QPointF dataPoint = coordsToPixels(mData->constBegin().key(), mData->constBegin().value().value); + return QVector2D(dataPoint-pixelPoint).length(); + } + + if (mLineStyle == lsNone && mScatterStyle.isNone()) + return 500; + + // calculate minimum distances to graph representation: + if (mLineStyle == lsNone) + { + // no line displayed, only calculate distance to scatter points: + QVector *scatterData = new QVector; + getScatterPlotData(scatterData); + double minDistSqr = std::numeric_limits::max(); + QPointF ptA; + QPointF ptB = coordsToPixels(scatterData->at(0).key, scatterData->at(0).value); // getScatterPlotData returns in plot coordinates, so transform to pixels + for (int i=1; isize(); ++i) + { + ptA = ptB; + ptB = coordsToPixels(scatterData->at(i).key, scatterData->at(i).value); + double currentDistSqr = distSqrToLine(ptA, ptB, pixelPoint); + if (currentDistSqr < minDistSqr) minDistSqr = currentDistSqr; + } + delete scatterData; + return qSqrt(minDistSqr); + } else + { + // line displayed calculate distance to line segments: + QVector *lineData = new QVector; + getPlotData(lineData, 0); // unlike with getScatterPlotData we get pixel coordinates here + double minDistSqr = std::numeric_limits::max(); + if (mLineStyle == lsImpulse) + { + // impulse plot differs from other line styles in that the lineData points are only pairwise connected: + for (int i=0; isize()-1; i+=2) // iterate pairs + { + double currentDistSqr = distSqrToLine(lineData->at(i), lineData->at(i+1), pixelPoint); + if (currentDistSqr < minDistSqr) + minDistSqr = currentDistSqr; } } else { - // all other line plots (line and step) connect points directly: - for (int i=0; isize()-1; ++i) - { - double currentDistSqr = distSqrToLine(lineData->at(i), lineData->at(i+1), pixelPoint); - if (currentDistSqr < minDistSqr) - minDistSqr = currentDistSqr; - } - } - delete lineData; - return qSqrt(minDistSqr); + // all other line plots (line and step) connect points directly: + for (int i=0; isize()-1; ++i) + { + double currentDistSqr = distSqrToLine(lineData->at(i), lineData->at(i+1), pixelPoint); + if (currentDistSqr < minDistSqr) + minDistSqr = currentDistSqr; + } + } + delete lineData; + return qSqrt(minDistSqr); } } @@ -16775,37 +16479,33 @@ double QCPGraph::pointDistance(const QPo */ int QCPGraph::findIndexBelowY(const QVector *data, double y) const { - for (int i=data->size()-1; i>=0; --i) - { - if (data->at(i).y() > y) - { - if (isize()-1) - return i+1; - else - return data->size()-1; - } - } - return -1; + for (int i=data->size()-1; i>=0; --i) + { + if (data->at(i).y() > y) + { + if (isize()-1) + return i+1; + else + return data->size()-1; + } + } + return -1; } /* inherits documentation from base class */ QCPRange QCPGraph::getKeyRange(bool &foundRange, SignDomain inSignDomain) const { - // just call the specialized version which takes an additional argument whether error bars - // should also be taken into consideration for range calculation. We set this to true here. - if(mUseFastVectors) - return getKeyRangeVector(foundRange, inSignDomain, true); - return getKeyRange(foundRange, inSignDomain, true); + // just call the specialized version which takes an additional argument whether error bars + // should also be taken into consideration for range calculation. We set this to true here. + return getKeyRange(foundRange, inSignDomain, true); } /* inherits documentation from base class */ QCPRange QCPGraph::getValueRange(bool &foundRange, SignDomain inSignDomain) const { - // just call the specialized version which takes an additional argument whether error bars - // should also be taken into consideration for range calculation. We set this to true here. - if(mUseFastVectors) - return getValueRangeVector(foundRange, inSignDomain, true); - return getValueRange(foundRange, inSignDomain, true); + // just call the specialized version which takes an additional argument whether error bars + // should also be taken into consideration for range calculation. We set this to true here. + return getValueRange(foundRange, inSignDomain, true); } /*! \overload @@ -16816,202 +16516,102 @@ QCPRange QCPGraph::getValueRange(bool &f */ QCPRange QCPGraph::getKeyRange(bool &foundRange, SignDomain inSignDomain, bool includeErrors) const { - QCPRange range; - bool haveLower = false; - bool haveUpper = false; - - double current, currentErrorMinus, currentErrorPlus; - - if (inSignDomain == sdBoth) // range may be anywhere - { - QCPDataMap::const_iterator it = mData->constBegin(); - while (it != mData->constEnd()) - { - current = it.value().key; - currentErrorMinus = (includeErrors ? it.value().keyErrorMinus : 0); - currentErrorPlus = (includeErrors ? it.value().keyErrorPlus : 0); - if (current-currentErrorMinus < range.lower || !haveLower) - { - range.lower = current-currentErrorMinus; - haveLower = true; - } - if (current+currentErrorPlus > range.upper || !haveUpper) - { - range.upper = current+currentErrorPlus; - haveUpper = true; - } - ++it; + QCPRange range; + bool haveLower = false; + bool haveUpper = false; + + double current, currentErrorMinus, currentErrorPlus; + + if (inSignDomain == sdBoth) // range may be anywhere + { + QCPDataMap::const_iterator it = mData->constBegin(); + while (it != mData->constEnd()) + { + current = it.value().key; + currentErrorMinus = (includeErrors ? it.value().keyErrorMinus : 0); + currentErrorPlus = (includeErrors ? it.value().keyErrorPlus : 0); + if (current-currentErrorMinus < range.lower || !haveLower) + { + range.lower = current-currentErrorMinus; + haveLower = true; + } + if (current+currentErrorPlus > range.upper || !haveUpper) + { + range.upper = current+currentErrorPlus; + haveUpper = true; + } + ++it; } } else if (inSignDomain == sdNegative) // range may only be in the negative sign domain { - QCPDataMap::const_iterator it = mData->constBegin(); - while (it != mData->constEnd()) - { - current = it.value().key; - currentErrorMinus = (includeErrors ? it.value().keyErrorMinus : 0); - currentErrorPlus = (includeErrors ? it.value().keyErrorPlus : 0); - if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus < 0) - { - range.lower = current-currentErrorMinus; - haveLower = true; - } - if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus < 0) - { - range.upper = current+currentErrorPlus; - haveUpper = true; - } - if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to geht that point. - { - if ((current < range.lower || !haveLower) && current < 0) + QCPDataMap::const_iterator it = mData->constBegin(); + while (it != mData->constEnd()) + { + current = it.value().key; + currentErrorMinus = (includeErrors ? it.value().keyErrorMinus : 0); + currentErrorPlus = (includeErrors ? it.value().keyErrorPlus : 0); + if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus < 0) + { + range.lower = current-currentErrorMinus; + haveLower = true; + } + if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus < 0) + { + range.upper = current+currentErrorPlus; + haveUpper = true; + } + if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to geht that point. + { + if ((current < range.lower || !haveLower) && current < 0) { - range.lower = current; - haveLower = true; + range.lower = current; + haveLower = true; } - if ((current > range.upper || !haveUpper) && current < 0) + if ((current > range.upper || !haveUpper) && current < 0) { - range.upper = current; - haveUpper = true; + range.upper = current; + haveUpper = true; } } - ++it; + ++it; } } else if (inSignDomain == sdPositive) // range may only be in the positive sign domain { - QCPDataMap::const_iterator it = mData->constBegin(); - while (it != mData->constEnd()) - { - current = it.value().key; - currentErrorMinus = (includeErrors ? it.value().keyErrorMinus : 0); - currentErrorPlus = (includeErrors ? it.value().keyErrorPlus : 0); - if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus > 0) - { - range.lower = current-currentErrorMinus; - haveLower = true; - } - if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus > 0) - { - range.upper = current+currentErrorPlus; - haveUpper = true; - } - if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to get that point. - { - if ((current < range.lower || !haveLower) && current > 0) + QCPDataMap::const_iterator it = mData->constBegin(); + while (it != mData->constEnd()) + { + current = it.value().key; + currentErrorMinus = (includeErrors ? it.value().keyErrorMinus : 0); + currentErrorPlus = (includeErrors ? it.value().keyErrorPlus : 0); + if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus > 0) + { + range.lower = current-currentErrorMinus; + haveLower = true; + } + if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus > 0) + { + range.upper = current+currentErrorPlus; + haveUpper = true; + } + if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to get that point. + { + if ((current < range.lower || !haveLower) && current > 0) { - range.lower = current; - haveLower = true; - } - if ((current > range.upper || !haveUpper) && current > 0) - { - range.upper = current; - haveUpper = true; + range.lower = current; + haveLower = true; } - } - ++it; - } - } - - foundRange = haveLower && haveUpper; - return range; -} - -QCPRange QCPGraph::getKeyRangeVector(bool &foundRange, SignDomain inSignDomain, bool includeErrors) const -{ - QCPRange range; - bool haveLower = false; - bool haveUpper = false; - - double current, currentErrorMinus, currentErrorPlus; - - if (inSignDomain == sdBoth) // range may be anywhere - { - QVector::const_iterator it = mDataVector->constBegin(); - while (it != mDataVector->constEnd()) - { - current = (*it).key; - currentErrorMinus = (includeErrors ? (*it).keyErrorMinus : 0); - currentErrorPlus = (includeErrors ? (*it).keyErrorPlus : 0); - if (current-currentErrorMinus < range.lower || !haveLower) - { - range.lower = current-currentErrorMinus; - haveLower = true; - } - if (current+currentErrorPlus > range.upper || !haveUpper) - { - range.upper = current+currentErrorPlus; - haveUpper = true; - } - ++it; - } - } else if (inSignDomain == sdNegative) // range may only be in the negative sign domain - { - QVector::const_iterator it = mDataVector->constBegin(); - while (it != mDataVector->constEnd()) - { - current = (*it).key; - currentErrorMinus = (includeErrors ? (*it).keyErrorMinus : 0); - currentErrorPlus = (includeErrors ? (*it).keyErrorPlus : 0); - if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus < 0) - { - range.lower = current-currentErrorMinus; - haveLower = true; - } - if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus < 0) - { - range.upper = current+currentErrorPlus; - haveUpper = true; - } - if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to geht that point. - { - if ((current < range.lower || !haveLower) && current < 0) + if ((current > range.upper || !haveUpper) && current > 0) { - range.lower = current; - haveLower = true; - } - if ((current > range.upper || !haveUpper) && current < 0) - { - range.upper = current; - haveUpper = true; + range.upper = current; + haveUpper = true; } } - ++it; - } - } else if (inSignDomain == sdPositive) // range may only be in the positive sign domain - { - QVector::const_iterator it = mDataVector->constBegin(); - while (it != mDataVector->constEnd()) - { - current = (*it).key; - currentErrorMinus = (includeErrors ? (*it).keyErrorMinus : 0); - currentErrorPlus = (includeErrors ? (*it).keyErrorPlus : 0); - if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus > 0) - { - range.lower = current-currentErrorMinus; - haveLower = true; - } - if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus > 0) - { - range.upper = current+currentErrorPlus; - haveUpper = true; - } - if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to get that point. - { - if ((current < range.lower || !haveLower) && current > 0) - { - range.lower = current; - haveLower = true; - } - if ((current > range.upper || !haveUpper) && current > 0) - { - range.upper = current; - haveUpper = true; - } - } - ++it; - } - } - - foundRange = haveLower && haveUpper; - return range; + ++it; + } + } + + foundRange = haveLower && haveUpper; + return range; } /*! \overload @@ -17022,203 +16622,104 @@ QCPRange QCPGraph::getKeyRangeVector(boo */ QCPRange QCPGraph::getValueRange(bool &foundRange, SignDomain inSignDomain, bool includeErrors) const { - QCPRange range; - bool haveLower = false; - bool haveUpper = false; - - double current, currentErrorMinus, currentErrorPlus; - - if (inSignDomain == sdBoth) // range may be anywhere - { - QCPDataMap::const_iterator it = mData->constBegin(); - while (it != mData->constEnd()) - { - current = it.value().value; - currentErrorMinus = (includeErrors ? it.value().valueErrorMinus : 0); - currentErrorPlus = (includeErrors ? it.value().valueErrorPlus : 0); - if (current-currentErrorMinus < range.lower || !haveLower) - { - range.lower = current-currentErrorMinus; - haveLower = true; - } - if (current+currentErrorPlus > range.upper || !haveUpper) - { - range.upper = current+currentErrorPlus; - haveUpper = true; - } - ++it; + QCPRange range; + bool haveLower = false; + bool haveUpper = false; + + double current, currentErrorMinus, currentErrorPlus; + + if (inSignDomain == sdBoth) // range may be anywhere + { + QCPDataMap::const_iterator it = mData->constBegin(); + while (it != mData->constEnd()) + { + current = it.value().value; + currentErrorMinus = (includeErrors ? it.value().valueErrorMinus : 0); + currentErrorPlus = (includeErrors ? it.value().valueErrorPlus : 0); + if (current-currentErrorMinus < range.lower || !haveLower) + { + range.lower = current-currentErrorMinus; + haveLower = true; + } + if (current+currentErrorPlus > range.upper || !haveUpper) + { + range.upper = current+currentErrorPlus; + haveUpper = true; + } + ++it; } } else if (inSignDomain == sdNegative) // range may only be in the negative sign domain { - QCPDataMap::const_iterator it = mData->constBegin(); - while (it != mData->constEnd()) - { - current = it.value().value; - currentErrorMinus = (includeErrors ? it.value().valueErrorMinus : 0); - currentErrorPlus = (includeErrors ? it.value().valueErrorPlus : 0); - if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus < 0) - { - range.lower = current-currentErrorMinus; - haveLower = true; - } - if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus < 0) - { - range.upper = current+currentErrorPlus; - haveUpper = true; - } - if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to get that point. - { - if ((current < range.lower || !haveLower) && current < 0) + QCPDataMap::const_iterator it = mData->constBegin(); + while (it != mData->constEnd()) + { + current = it.value().value; + currentErrorMinus = (includeErrors ? it.value().valueErrorMinus : 0); + currentErrorPlus = (includeErrors ? it.value().valueErrorPlus : 0); + if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus < 0) + { + range.lower = current-currentErrorMinus; + haveLower = true; + } + if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus < 0) + { + range.upper = current+currentErrorPlus; + haveUpper = true; + } + if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to get that point. + { + if ((current < range.lower || !haveLower) && current < 0) { - range.lower = current; - haveLower = true; + range.lower = current; + haveLower = true; } - if ((current > range.upper || !haveUpper) && current < 0) + if ((current > range.upper || !haveUpper) && current < 0) { - range.upper = current; - haveUpper = true; + range.upper = current; + haveUpper = true; } } - ++it; + ++it; } } else if (inSignDomain == sdPositive) // range may only be in the positive sign domain { - QCPDataMap::const_iterator it = mData->constBegin(); - while (it != mData->constEnd()) - { - current = it.value().value; - currentErrorMinus = (includeErrors ? it.value().valueErrorMinus : 0); - currentErrorPlus = (includeErrors ? it.value().valueErrorPlus : 0); - if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus > 0) - { - range.lower = current-currentErrorMinus; - haveLower = true; - } - if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus > 0) - { - range.upper = current+currentErrorPlus; - haveUpper = true; - } - if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to geht that point. - { - if ((current < range.lower || !haveLower) && current > 0) + QCPDataMap::const_iterator it = mData->constBegin(); + while (it != mData->constEnd()) + { + current = it.value().value; + currentErrorMinus = (includeErrors ? it.value().valueErrorMinus : 0); + currentErrorPlus = (includeErrors ? it.value().valueErrorPlus : 0); + if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus > 0) + { + range.lower = current-currentErrorMinus; + haveLower = true; + } + if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus > 0) + { + range.upper = current+currentErrorPlus; + haveUpper = true; + } + if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to geht that point. + { + if ((current < range.lower || !haveLower) && current > 0) { - range.lower = current; - haveLower = true; - } - if ((current > range.upper || !haveUpper) && current > 0) - { - range.upper = current; - haveUpper = true; + range.lower = current; + haveLower = true; } - } - ++it; - } - } - - foundRange = haveLower && haveUpper; - return range; -} - -QCPRange QCPGraph::getValueRangeVector(bool &foundRange, SignDomain inSignDomain, bool includeErrors) const -{ - QCPRange range; - bool haveLower = false; - bool haveUpper = false; - - double current, currentErrorMinus, currentErrorPlus; - - if (inSignDomain == sdBoth) // range may be anywhere - { - QVector::const_iterator it = mDataVector->constBegin(); - while (it != mDataVector->constEnd()) - { - current = (*it).value; - currentErrorMinus = (includeErrors ? (*it).valueErrorMinus : 0); - currentErrorPlus = (includeErrors ? (*it).valueErrorPlus : 0); - if (current-currentErrorMinus < range.lower || !haveLower) - { - range.lower = current-currentErrorMinus; - haveLower = true; - } - if (current+currentErrorPlus > range.upper || !haveUpper) - { - range.upper = current+currentErrorPlus; - haveUpper = true; - } - ++it; - } - } else if (inSignDomain == sdNegative) // range may only be in the negative sign domain - { - QVector::const_iterator it = mDataVector->constBegin(); - while (it != mDataVector->constEnd()) - { - current = (*it).value; - currentErrorMinus = (includeErrors ? (*it).valueErrorMinus : 0); - currentErrorPlus = (includeErrors ? (*it).valueErrorPlus : 0); - if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus < 0) - { - range.lower = current-currentErrorMinus; - haveLower = true; - } - if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus < 0) - { - range.upper = current+currentErrorPlus; - haveUpper = true; - } - if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to get that point. - { - if ((current < range.lower || !haveLower) && current < 0) + if ((current > range.upper || !haveUpper) && current > 0) { - range.lower = current; - haveLower = true; - } - if ((current > range.upper || !haveUpper) && current < 0) - { - range.upper = current; - haveUpper = true; + range.upper = current; + haveUpper = true; } } - ++it; - } - } else if (inSignDomain == sdPositive) // range may only be in the positive sign domain - { - QVector::const_iterator it = mDataVector->constBegin(); - while (it != mDataVector->constEnd()) - { - current = (*it).value; - currentErrorMinus = (includeErrors ? (*it).valueErrorMinus : 0); - currentErrorPlus = (includeErrors ? (*it).valueErrorPlus : 0); - if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus > 0) - { - range.lower = current-currentErrorMinus; - haveLower = true; - } - if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus > 0) - { - range.upper = current+currentErrorPlus; - haveUpper = true; - } - if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to geht that point. - { - if ((current < range.lower || !haveLower) && current > 0) - { - range.lower = current; - haveLower = true; - } - if ((current > range.upper || !haveUpper) && current > 0) - { - range.upper = current; - haveUpper = true; - } - } - ++it; - } - } - - foundRange = haveLower && haveUpper; - return range; -} + ++it; + } + } + + foundRange = haveLower && haveUpper; + return range; +} + //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////// QCPCurveData @@ -17241,9 +16742,9 @@ QCPRange QCPGraph::getValueRangeVector(b Constructs a curve data point with t, key and value set to zero. */ QCPCurveData::QCPCurveData() : - t(0), - key(0), - value(0) + t(0), + key(0), + value(0) { } @@ -17251,9 +16752,9 @@ QCPCurveData::QCPCurveData() : Constructs a curve data point with the specified \a t, \a key and \a value. */ QCPCurveData::QCPCurveData(double t, double key, double value) : - t(t), - key(key), - value(value) + t(t), + key(key), + value(value) { } @@ -17304,25 +16805,25 @@ QCPCurveData::QCPCurveData(double t, dou then takes ownership of the graph. */ QCPCurve::QCPCurve(QCPAxis *keyAxis, QCPAxis *valueAxis) : - QCPAbstractPlottable(keyAxis, valueAxis) -{ - mData = new QCPCurveDataMap; - mPen.setColor(Qt::blue); - mPen.setStyle(Qt::SolidLine); - mBrush.setColor(Qt::blue); - mBrush.setStyle(Qt::NoBrush); - mSelectedPen = mPen; - mSelectedPen.setWidthF(2.5); - mSelectedPen.setColor(QColor(80, 80, 255)); // lighter than Qt::blue of mPen - mSelectedBrush = mBrush; - - setScatterStyle(QCPScatterStyle()); - setLineStyle(lsLine); + QCPAbstractPlottable(keyAxis, valueAxis) +{ + mData = new QCPCurveDataMap; + mPen.setColor(Qt::blue); + mPen.setStyle(Qt::SolidLine); + mBrush.setColor(Qt::blue); + mBrush.setStyle(Qt::NoBrush); + mSelectedPen = mPen; + mSelectedPen.setWidthF(2.5); + mSelectedPen.setColor(QColor(80, 80, 255)); // lighter than Qt::blue of mPen + mSelectedBrush = mBrush; + + setScatterStyle(QCPScatterStyle()); + setLineStyle(lsLine); } QCPCurve::~QCPCurve() { - delete mData; + delete mData; } /*! @@ -17334,18 +16835,18 @@ QCPCurve::~QCPCurve() */ void QCPCurve::setData(QCPCurveDataMap *data, bool copy) { - if (mData == data) - { - qDebug() << Q_FUNC_INFO << "The data pointer is already in (and owned by) this plottable" << reinterpret_cast(data); - return; - } - if (copy) - { - *mData = *data; - } else - { - delete mData; - mData = data; + if (mData == data) + { + qDebug() << Q_FUNC_INFO << "The data pointer is already in (and owned by) this plottable" << reinterpret_cast(data); + return; + } + if (copy) + { + *mData = *data; + } else + { + delete mData; + mData = data; } } @@ -17357,17 +16858,17 @@ void QCPCurve::setData(QCPCurveDataMap * */ void QCPCurve::setData(const QVector &t, const QVector &key, const QVector &value) { - mData->clear(); - int n = t.size(); - n = qMin(n, key.size()); - n = qMin(n, value.size()); - QCPCurveData newData; - for (int i=0; iinsertMulti(newData.t, newData); + mData->clear(); + int n = t.size(); + n = qMin(n, key.size()); + n = qMin(n, value.size()); + QCPCurveData newData; + for (int i=0; iinsertMulti(newData.t, newData); } } @@ -17378,16 +16879,16 @@ void QCPCurve::setData(const QVector &key, const QVector &value) { - mData->clear(); - int n = key.size(); - n = qMin(n, value.size()); - QCPCurveData newData; - for (int i=0; iinsertMulti(newData.t, newData); + mData->clear(); + int n = key.size(); + n = qMin(n, value.size()); + QCPCurveData newData; + for (int i=0; iinsertMulti(newData.t, newData); } } @@ -17400,7 +16901,7 @@ void QCPCurve::setData(const QVectorunite(dataMap); + mData->unite(dataMap); } /*! \overload @@ -17430,7 +16931,7 @@ void QCPCurve::addData(const QCPCurveDat */ void QCPCurve::addData(const QCPCurveData &data) { - mData->insertMulti(data.t, data); + mData->insertMulti(data.t, data); } /*! \overload @@ -17439,11 +16940,11 @@ void QCPCurve::addData(const QCPCurveDat */ void QCPCurve::addData(double t, double key, double value) { - QCPCurveData newData; - newData.t = t; - newData.key = key; - newData.value = value; - mData->insertMulti(newData.t, newData); + QCPCurveData newData; + newData.t = t; + newData.key = key; + newData.value = value; + mData->insertMulti(newData.t, newData); } /*! \overload @@ -17456,14 +16957,14 @@ void QCPCurve::addData(double t, double */ void QCPCurve::addData(double key, double value) { - QCPCurveData newData; - if (!mData->isEmpty()) - newData.t = (mData->constEnd()-1).key()+1; - else - newData.t = 0; - newData.key = key; - newData.value = value; - mData->insertMulti(newData.t, newData); + QCPCurveData newData; + if (!mData->isEmpty()) + newData.t = (mData->constEnd()-1).key()+1; + else + newData.t = 0; + newData.key = key; + newData.value = value; + mData->insertMulti(newData.t, newData); } /*! \overload @@ -17472,16 +16973,16 @@ void QCPCurve::addData(double key, doubl */ void QCPCurve::addData(const QVector &ts, const QVector &keys, const QVector &values) { - int n = ts.size(); - n = qMin(n, keys.size()); - n = qMin(n, values.size()); - QCPCurveData newData; - for (int i=0; iinsertMulti(newData.t, newData); + int n = ts.size(); + n = qMin(n, keys.size()); + n = qMin(n, values.size()); + QCPCurveData newData; + for (int i=0; iinsertMulti(newData.t, newData); } } @@ -17491,9 +16992,9 @@ void QCPCurve::addData(const QVectorbegin(); - while (it != mData->end() && it.key() < t) - it = mData->erase(it); + QCPCurveDataMap::iterator it = mData->begin(); + while (it != mData->end() && it.key() < t) + it = mData->erase(it); } /*! @@ -17502,10 +17003,10 @@ void QCPCurve::removeDataBefore(double t */ void QCPCurve::removeDataAfter(double t) { - if (mData->isEmpty()) return; - QCPCurveDataMap::iterator it = mData->upperBound(t); - while (it != mData->end()) - it = mData->erase(it); + if (mData->isEmpty()) return; + QCPCurveDataMap::iterator it = mData->upperBound(t); + while (it != mData->end()) + it = mData->erase(it); } /*! @@ -17517,11 +17018,11 @@ void QCPCurve::removeDataAfter(double t) */ void QCPCurve::removeData(double fromt, double tot) { - if (fromt >= tot || mData->isEmpty()) return; - QCPCurveDataMap::iterator it = mData->upperBound(fromt); - QCPCurveDataMap::iterator itEnd = mData->upperBound(tot); - while (it != itEnd) - it = mData->erase(it); + if (fromt >= tot || mData->isEmpty()) return; + QCPCurveDataMap::iterator it = mData->upperBound(fromt); + QCPCurveDataMap::iterator itEnd = mData->upperBound(tot); + while (it != itEnd) + it = mData->erase(it); } /*! \overload @@ -17535,7 +17036,7 @@ void QCPCurve::removeData(double fromt, */ void QCPCurve::removeData(double t) { - mData->remove(t); + mData->remove(t); } /*! @@ -17544,134 +17045,134 @@ void QCPCurve::removeData(double t) */ void QCPCurve::clearData() { - mData->clear(); + mData->clear(); } /* inherits documentation from base class */ double QCPCurve::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - Q_UNUSED(details) - if ((onlySelectable && !mSelectable) || mData->isEmpty()) - return -1; - if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; } - - if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint())) - return pointDistance(pos); - else - return -1; + Q_UNUSED(details) + if ((onlySelectable && !mSelectable) || mData->isEmpty()) + return -1; + if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; } + + if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint())) + return pointDistance(pos); + else + return -1; } /* inherits documentation from base class */ void QCPCurve::draw(QCPPainter *painter) { - if (mData->isEmpty()) return; - - // allocate line vector: - QVector *lineData = new QVector; - - // fill with curve data: - getCurveData(lineData); - - // check data validity if flag set: + if (mData->isEmpty()) return; + + // allocate line vector: + QVector *lineData = new QVector; + + // fill with curve data: + getCurveData(lineData); + + // check data validity if flag set: #ifdef QCUSTOMPLOT_CHECK_DATA - QCPCurveDataMap::const_iterator it; - for (it = mData->constBegin(); it != mData->constEnd(); ++it) - { - if (QCP::isInvalidData(it.value().t) || - QCP::isInvalidData(it.value().key, it.value().value)) - qDebug() << Q_FUNC_INFO << "Data point at" << it.key() << "invalid." << "Plottable name:" << name(); + QCPCurveDataMap::const_iterator it; + for (it = mData->constBegin(); it != mData->constEnd(); ++it) + { + if (QCP::isInvalidData(it.value().t) || + QCP::isInvalidData(it.value().key, it.value().value)) + qDebug() << Q_FUNC_INFO << "Data point at" << it.key() << "invalid." << "Plottable name:" << name(); } #endif - - // draw curve fill: - if (mainBrush().style() != Qt::NoBrush && mainBrush().color().alpha() != 0) - { - applyFillAntialiasingHint(painter); - painter->setPen(Qt::NoPen); - painter->setBrush(mainBrush()); - painter->drawPolygon(QPolygonF(*lineData)); - } - - // draw curve line: - if (mLineStyle != lsNone && mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0) - { - applyDefaultAntialiasingHint(painter); - painter->setPen(mainPen()); - painter->setBrush(Qt::NoBrush); - // if drawing solid line and not in PDF, use much faster line drawing instead of polyline: - if (mParentPlot->plottingHints().testFlag(QCP::phFastPolylines) && - painter->pen().style() == Qt::SolidLine && - !painter->modes().testFlag(QCPPainter::pmVectorized) && - !painter->modes().testFlag(QCPPainter::pmNoCaching)) - { - int i = 1; - int lineDataSize = lineData->size(); - while (i < lineDataSize) - { - if (!qIsNaN(lineData->at(i).y()) && !qIsNaN(lineData->at(i).x())) // NaNs create a gap in the line - painter->drawLine(lineData->at(i-1), lineData->at(i)); - else + + // draw curve fill: + if (mainBrush().style() != Qt::NoBrush && mainBrush().color().alpha() != 0) + { + applyFillAntialiasingHint(painter); + painter->setPen(Qt::NoPen); + painter->setBrush(mainBrush()); + painter->drawPolygon(QPolygonF(*lineData)); + } + + // draw curve line: + if (mLineStyle != lsNone && mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0) + { + applyDefaultAntialiasingHint(painter); + painter->setPen(mainPen()); + painter->setBrush(Qt::NoBrush); + // if drawing solid line and not in PDF, use much faster line drawing instead of polyline: + if (mParentPlot->plottingHints().testFlag(QCP::phFastPolylines) && + painter->pen().style() == Qt::SolidLine && + !painter->modes().testFlag(QCPPainter::pmVectorized) && + !painter->modes().testFlag(QCPPainter::pmNoCaching)) + { + int i = 1; + int lineDataSize = lineData->size(); + while (i < lineDataSize) + { + if (!qIsNaN(lineData->at(i).y()) && !qIsNaN(lineData->at(i).x())) // NaNs create a gap in the line + painter->drawLine(lineData->at(i-1), lineData->at(i)); + else + ++i; ++i; - ++i; } } else { - int segmentStart = 0; - int i = 0; - int lineDataSize = lineData->size(); - while (i < lineDataSize) - { - if (qIsNaN(lineData->at(i).y()) || qIsNaN(lineData->at(i).x())) // NaNs create a gap in the line + int segmentStart = 0; + int i = 0; + int lineDataSize = lineData->size(); + while (i < lineDataSize) + { + if (qIsNaN(lineData->at(i).y()) || qIsNaN(lineData->at(i).x())) // NaNs create a gap in the line { - painter->drawPolyline(lineData->constData()+segmentStart, i-segmentStart); // i, because we don't want to include the current NaN point - segmentStart = i+1; + painter->drawPolyline(lineData->constData()+segmentStart, i-segmentStart); // i, because we don't want to include the current NaN point + segmentStart = i+1; } - ++i; - } - // draw last segment: - painter->drawPolyline(lineData->constData()+segmentStart, lineDataSize-segmentStart); // lineDataSize, because we do want to include the last point - } - } - - // draw scatters: - if (!mScatterStyle.isNone()) - drawScatterPlot(painter, lineData); - - // free allocated line data: - delete lineData; + ++i; + } + // draw last segment: + painter->drawPolyline(lineData->constData()+segmentStart, lineDataSize-segmentStart); // lineDataSize, because we do want to include the last point + } + } + + // draw scatters: + if (!mScatterStyle.isNone()) + drawScatterPlot(painter, lineData); + + // free allocated line data: + delete lineData; } /* inherits documentation from base class */ void QCPCurve::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const { - // draw fill: - if (mBrush.style() != Qt::NoBrush) - { - applyFillAntialiasingHint(painter); - painter->fillRect(QRectF(rect.left(), rect.top()+rect.height()/2.0, rect.width(), rect.height()/3.0), mBrush); - } - // draw line vertically centered: - if (mLineStyle != lsNone) - { - applyDefaultAntialiasingHint(painter); - painter->setPen(mPen); - painter->drawLine(QLineF(rect.left(), rect.top()+rect.height()/2.0, rect.right()+5, rect.top()+rect.height()/2.0)); // +5 on x2 else last segment is missing from dashed/dotted pens - } - // draw scatter symbol: - if (!mScatterStyle.isNone()) - { - applyScattersAntialiasingHint(painter); - // scale scatter pixmap if it's too large to fit in legend icon rect: - if (mScatterStyle.shape() == QCPScatterStyle::ssPixmap && (mScatterStyle.pixmap().size().width() > rect.width() || mScatterStyle.pixmap().size().height() > rect.height())) - { - QCPScatterStyle scaledStyle(mScatterStyle); - scaledStyle.setPixmap(scaledStyle.pixmap().scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); - scaledStyle.applyTo(painter, mPen); - scaledStyle.drawShape(painter, QRectF(rect).center()); + // draw fill: + if (mBrush.style() != Qt::NoBrush) + { + applyFillAntialiasingHint(painter); + painter->fillRect(QRectF(rect.left(), rect.top()+rect.height()/2.0, rect.width(), rect.height()/3.0), mBrush); + } + // draw line vertically centered: + if (mLineStyle != lsNone) + { + applyDefaultAntialiasingHint(painter); + painter->setPen(mPen); + painter->drawLine(QLineF(rect.left(), rect.top()+rect.height()/2.0, rect.right()+5, rect.top()+rect.height()/2.0)); // +5 on x2 else last segment is missing from dashed/dotted pens + } + // draw scatter symbol: + if (!mScatterStyle.isNone()) + { + applyScattersAntialiasingHint(painter); + // scale scatter pixmap if it's too large to fit in legend icon rect: + if (mScatterStyle.shape() == QCPScatterStyle::ssPixmap && (mScatterStyle.pixmap().size().width() > rect.width() || mScatterStyle.pixmap().size().height() > rect.height())) + { + QCPScatterStyle scaledStyle(mScatterStyle); + scaledStyle.setPixmap(scaledStyle.pixmap().scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); + scaledStyle.applyTo(painter, mPen); + scaledStyle.drawShape(painter, QRectF(rect).center()); } else { - mScatterStyle.applyTo(painter, mPen); - mScatterStyle.drawShape(painter, QRectF(rect).center()); + mScatterStyle.applyTo(painter, mPen); + mScatterStyle.drawShape(painter, QRectF(rect).center()); } } } @@ -17683,12 +17184,12 @@ void QCPCurve::drawLegendIcon(QCPPainter */ void QCPCurve::drawScatterPlot(QCPPainter *painter, const QVector *pointData) const { - // draw scatter point symbols: - applyScattersAntialiasingHint(painter); - mScatterStyle.applyTo(painter, mPen); - for (int i=0; isize(); ++i) - if (!qIsNaN(pointData->at(i).x()) && !qIsNaN(pointData->at(i).y())) - mScatterStyle.drawShape(painter, pointData->at(i)); + // draw scatter point symbols: + applyScattersAntialiasingHint(painter); + mScatterStyle.applyTo(painter, mPen); + for (int i=0; isize(); ++i) + if (!qIsNaN(pointData->at(i).x()) && !qIsNaN(pointData->at(i).y())) + mScatterStyle.drawShape(painter, pointData->at(i)); } /*! \internal @@ -17706,81 +17207,81 @@ void QCPCurve::drawScatterPlot(QCPPainte */ void QCPCurve::getCurveData(QVector *lineData) const { - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - - // add margins to rect to compensate for stroke width - double strokeMargin = qMax(qreal(1.0), qreal(mainPen().widthF()*0.75)); // stroke radius + 50% safety - if (!mScatterStyle.isNone()) - strokeMargin = qMax(strokeMargin, mScatterStyle.size()); - double rectLeft = keyAxis->pixelToCoord(keyAxis->coordToPixel(keyAxis->range().lower)-strokeMargin*((keyAxis->orientation()==Qt::Vertical)!=keyAxis->rangeReversed()?-1:1)); - double rectRight = keyAxis->pixelToCoord(keyAxis->coordToPixel(keyAxis->range().upper)+strokeMargin*((keyAxis->orientation()==Qt::Vertical)!=keyAxis->rangeReversed()?-1:1)); - double rectBottom = valueAxis->pixelToCoord(valueAxis->coordToPixel(valueAxis->range().lower)+strokeMargin*((valueAxis->orientation()==Qt::Horizontal)!=valueAxis->rangeReversed()?-1:1)); - double rectTop = valueAxis->pixelToCoord(valueAxis->coordToPixel(valueAxis->range().upper)-strokeMargin*((valueAxis->orientation()==Qt::Horizontal)!=valueAxis->rangeReversed()?-1:1)); - int currentRegion; - QCPCurveDataMap::const_iterator it = mData->constBegin(); - QCPCurveDataMap::const_iterator prevIt = mData->constEnd()-1; - int prevRegion = getRegion(prevIt.value().key, prevIt.value().value, rectLeft, rectTop, rectRight, rectBottom); - QVector trailingPoints; // points that must be applied after all other points (are generated only when handling first point to get virtual segment between last and first point right) - while (it != mData->constEnd()) - { - currentRegion = getRegion(it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom); - if (currentRegion != prevRegion) // changed region, possibly need to add some optimized edge points or original points if entering R - { - if (currentRegion != 5) // segment doesn't end in R, so it's a candidate for removal - { - QPointF crossA, crossB; - if (prevRegion == 5) // we're coming from R, so add this point optimized + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + + // add margins to rect to compensate for stroke width + double strokeMargin = qMax(qreal(1.0), qreal(mainPen().widthF()*0.75)); // stroke radius + 50% safety + if (!mScatterStyle.isNone()) + strokeMargin = qMax(strokeMargin, mScatterStyle.size()); + double rectLeft = keyAxis->pixelToCoord(keyAxis->coordToPixel(keyAxis->range().lower)-strokeMargin*((keyAxis->orientation()==Qt::Vertical)!=keyAxis->rangeReversed()?-1:1)); + double rectRight = keyAxis->pixelToCoord(keyAxis->coordToPixel(keyAxis->range().upper)+strokeMargin*((keyAxis->orientation()==Qt::Vertical)!=keyAxis->rangeReversed()?-1:1)); + double rectBottom = valueAxis->pixelToCoord(valueAxis->coordToPixel(valueAxis->range().lower)+strokeMargin*((valueAxis->orientation()==Qt::Horizontal)!=valueAxis->rangeReversed()?-1:1)); + double rectTop = valueAxis->pixelToCoord(valueAxis->coordToPixel(valueAxis->range().upper)-strokeMargin*((valueAxis->orientation()==Qt::Horizontal)!=valueAxis->rangeReversed()?-1:1)); + int currentRegion; + QCPCurveDataMap::const_iterator it = mData->constBegin(); + QCPCurveDataMap::const_iterator prevIt = mData->constEnd()-1; + int prevRegion = getRegion(prevIt.value().key, prevIt.value().value, rectLeft, rectTop, rectRight, rectBottom); + QVector trailingPoints; // points that must be applied after all other points (are generated only when handling first point to get virtual segment between last and first point right) + while (it != mData->constEnd()) + { + currentRegion = getRegion(it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom); + if (currentRegion != prevRegion) // changed region, possibly need to add some optimized edge points or original points if entering R + { + if (currentRegion != 5) // segment doesn't end in R, so it's a candidate for removal + { + QPointF crossA, crossB; + if (prevRegion == 5) // we're coming from R, so add this point optimized { - lineData->append(getOptimizedPoint(currentRegion, it.value().key, it.value().value, prevIt.value().key, prevIt.value().value, rectLeft, rectTop, rectRight, rectBottom)); - // in the situations 5->1/7/9/3 the segment may leave R and directly cross through two outer regions. In these cases we need to add an additional corner point - *lineData << getOptimizedCornerPoints(prevRegion, currentRegion, prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom); + lineData->append(getOptimizedPoint(currentRegion, it.value().key, it.value().value, prevIt.value().key, prevIt.value().value, rectLeft, rectTop, rectRight, rectBottom)); + // in the situations 5->1/7/9/3 the segment may leave R and directly cross through two outer regions. In these cases we need to add an additional corner point + *lineData << getOptimizedCornerPoints(prevRegion, currentRegion, prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom); } else if (mayTraverse(prevRegion, currentRegion) && getTraverse(prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom, crossA, crossB)) { - // add the two cross points optimized if segment crosses R and if segment isn't virtual zeroth segment between last and first curve point: - QVector beforeTraverseCornerPoints, afterTraverseCornerPoints; - getTraverseCornerPoints(prevRegion, currentRegion, rectLeft, rectTop, rectRight, rectBottom, beforeTraverseCornerPoints, afterTraverseCornerPoints); - if (it != mData->constBegin()) + // add the two cross points optimized if segment crosses R and if segment isn't virtual zeroth segment between last and first curve point: + QVector beforeTraverseCornerPoints, afterTraverseCornerPoints; + getTraverseCornerPoints(prevRegion, currentRegion, rectLeft, rectTop, rectRight, rectBottom, beforeTraverseCornerPoints, afterTraverseCornerPoints); + if (it != mData->constBegin()) { - *lineData << beforeTraverseCornerPoints; - lineData->append(crossA); - lineData->append(crossB); - *lineData << afterTraverseCornerPoints; + *lineData << beforeTraverseCornerPoints; + lineData->append(crossA); + lineData->append(crossB); + *lineData << afterTraverseCornerPoints; } else { - lineData->append(crossB); - *lineData << afterTraverseCornerPoints; - trailingPoints << beforeTraverseCornerPoints << crossA ; + lineData->append(crossB); + *lineData << afterTraverseCornerPoints; + trailingPoints << beforeTraverseCornerPoints << crossA ; } } else // doesn't cross R, line is just moving around in outside regions, so only need to add optimized point(s) at the boundary corner(s) { - *lineData << getOptimizedCornerPoints(prevRegion, currentRegion, prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom); + *lineData << getOptimizedCornerPoints(prevRegion, currentRegion, prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom); } } else // segment does end in R, so we add previous point optimized and this point at original position { - if (it == mData->constBegin()) // it is first point in curve and prevIt is last one. So save optimized point for adding it to the lineData in the end - trailingPoints << getOptimizedPoint(prevRegion, prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom); - else - lineData->append(getOptimizedPoint(prevRegion, prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom)); - lineData->append(coordsToPixels(it.value().key, it.value().value)); + if (it == mData->constBegin()) // it is first point in curve and prevIt is last one. So save optimized point for adding it to the lineData in the end + trailingPoints << getOptimizedPoint(prevRegion, prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom); + else + lineData->append(getOptimizedPoint(prevRegion, prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom)); + lineData->append(coordsToPixels(it.value().key, it.value().value)); } } else // region didn't change { - if (currentRegion == 5) // still in R, keep adding original points - { - lineData->append(coordsToPixels(it.value().key, it.value().value)); + if (currentRegion == 5) // still in R, keep adding original points + { + lineData->append(coordsToPixels(it.value().key, it.value().value)); } else // still outside R, no need to add anything { - // see how this is not doing anything? That's the main optimization... - } - } - prevIt = it; - prevRegion = currentRegion; - ++it; - } - *lineData << trailingPoints; + // see how this is not doing anything? That's the main optimization... + } + } + prevIt = it; + prevRegion = currentRegion; + ++it; + } + *lineData << trailingPoints; } /*! \internal @@ -17803,30 +17304,30 @@ void QCPCurve::getCurveData(QVector rectTop) - return 1; - else if (y < rectBottom) - return 3; - else - return 2; + if (x < rectLeft) // region 123 + { + if (y > rectTop) + return 1; + else if (y < rectBottom) + return 3; + else + return 2; } else if (x > rectRight) // region 789 { - if (y > rectTop) - return 7; - else if (y < rectBottom) - return 9; - else - return 8; + if (y > rectTop) + return 7; + else if (y < rectBottom) + return 9; + else + return 8; } else // region 456 { - if (y > rectTop) - return 4; - else if (y < rectBottom) - return 6; - else - return 5; + if (y > rectTop) + return 4; + else if (y < rectBottom) + return 6; + else + return 5; } } @@ -17847,84 +17348,84 @@ int QCPCurve::getRegion(double x, double */ QPointF QCPCurve::getOptimizedPoint(int otherRegion, double otherKey, double otherValue, double key, double value, double rectLeft, double rectTop, double rectRight, double rectBottom) const { - double intersectKey = rectLeft; // initial value is just fail-safe - double intersectValue = rectTop; // initial value is just fail-safe - switch (otherRegion) + double intersectKey = rectLeft; // initial value is just fail-safe + double intersectValue = rectTop; // initial value is just fail-safe + switch (otherRegion) { case 1: // top and left edge - { + { intersectValue = rectTop; intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue); if (intersectKey < rectLeft || intersectKey > rectRight) // doesn't intersect, so must intersect other: - { + { intersectKey = rectLeft; intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey); - } - break; - } + } + break; + } case 2: // left edge - { + { intersectKey = rectLeft; intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey); break; - } + } case 3: // bottom and left edge - { + { intersectValue = rectBottom; intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue); if (intersectKey < rectLeft || intersectKey > rectRight) // doesn't intersect, so must intersect other: - { + { intersectKey = rectLeft; intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey); - } - break; - } + } + break; + } case 4: // top edge - { + { intersectValue = rectTop; intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue); break; - } + } case 5: - { + { break; // case 5 shouldn't happen for this function but we add it anyway to prevent potential discontinuity in branch table - } + } case 6: // bottom edge - { + { intersectValue = rectBottom; intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue); break; - } + } case 7: // top and right edge - { + { intersectValue = rectTop; intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue); if (intersectKey < rectLeft || intersectKey > rectRight) // doesn't intersect, so must intersect other: - { + { intersectKey = rectRight; intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey); - } - break; - } + } + break; + } case 8: // right edge - { + { intersectKey = rectRight; intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey); break; - } + } case 9: // bottom and right edge - { + { intersectValue = rectBottom; intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue); if (intersectKey < rectLeft || intersectKey > rectRight) // doesn't intersect, so must intersect other: - { + { intersectKey = rectRight; intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey); - } - break; - } - } - return coordsToPixels(intersectKey, intersectValue); + } + break; + } + } + return coordsToPixels(intersectKey, intersectValue); } /*! \internal @@ -17947,154 +17448,154 @@ QPointF QCPCurve::getOptimizedPoint(int */ QVector QCPCurve::getOptimizedCornerPoints(int prevRegion, int currentRegion, double prevKey, double prevValue, double key, double value, double rectLeft, double rectTop, double rectRight, double rectBottom) const { - QVector result; - switch (prevRegion) + QVector result; + switch (prevRegion) { case 1: - { + { switch (currentRegion) - { - case 2: { result << coordsToPixels(rectLeft, rectTop); break; } - case 4: { result << coordsToPixels(rectLeft, rectTop); break; } - case 3: { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectLeft, rectBottom); break; } - case 7: { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectRight, rectTop); break; } - case 6: { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); break; } - case 8: { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectRight, rectTop); result.append(result.last()); break; } - case 9: { // in this case we need another distinction of cases: segment may pass below or above rect, requiring either bottom right or top left corner points - if ((value-prevValue)/(key-prevKey)*(rectLeft-key)+value < rectBottom) // segment passes below R - { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); result << coordsToPixels(rectRight, rectBottom); } - else - { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectRight, rectTop); result.append(result.last()); result << coordsToPixels(rectRight, rectBottom); } - break; - } - } - break; - } + { + case 2: { result << coordsToPixels(rectLeft, rectTop); break; } + case 4: { result << coordsToPixels(rectLeft, rectTop); break; } + case 3: { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectLeft, rectBottom); break; } + case 7: { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectRight, rectTop); break; } + case 6: { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); break; } + case 8: { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectRight, rectTop); result.append(result.last()); break; } + case 9: { // in this case we need another distinction of cases: segment may pass below or above rect, requiring either bottom right or top left corner points + if ((value-prevValue)/(key-prevKey)*(rectLeft-key)+value < rectBottom) // segment passes below R + { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); result << coordsToPixels(rectRight, rectBottom); } + else + { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectRight, rectTop); result.append(result.last()); result << coordsToPixels(rectRight, rectBottom); } + break; + } + } + break; + } case 2: - { + { switch (currentRegion) - { - case 1: { result << coordsToPixels(rectLeft, rectTop); break; } - case 3: { result << coordsToPixels(rectLeft, rectBottom); break; } - case 4: { result << coordsToPixels(rectLeft, rectTop); result.append(result.last()); break; } - case 6: { result << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); break; } - case 7: { result << coordsToPixels(rectLeft, rectTop); result.append(result.last()); result << coordsToPixels(rectRight, rectTop); break; } - case 9: { result << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); result << coordsToPixels(rectRight, rectBottom); break; } - } - break; - } + { + case 1: { result << coordsToPixels(rectLeft, rectTop); break; } + case 3: { result << coordsToPixels(rectLeft, rectBottom); break; } + case 4: { result << coordsToPixels(rectLeft, rectTop); result.append(result.last()); break; } + case 6: { result << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); break; } + case 7: { result << coordsToPixels(rectLeft, rectTop); result.append(result.last()); result << coordsToPixels(rectRight, rectTop); break; } + case 9: { result << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); result << coordsToPixels(rectRight, rectBottom); break; } + } + break; + } case 3: - { + { switch (currentRegion) - { - case 2: { result << coordsToPixels(rectLeft, rectBottom); break; } - case 6: { result << coordsToPixels(rectLeft, rectBottom); break; } - case 1: { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectLeft, rectTop); break; } - case 9: { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectRight, rectBottom); break; } - case 4: { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectLeft, rectTop); result.append(result.last()); break; } - case 8: { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectRight, rectBottom); result.append(result.last()); break; } - case 7: { // in this case we need another distinction of cases: segment may pass below or above rect, requiring either bottom right or top left corner points - if ((value-prevValue)/(key-prevKey)*(rectRight-key)+value < rectBottom) // segment passes below R - { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectRight, rectBottom); result.append(result.last()); result << coordsToPixels(rectRight, rectTop); } - else - { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectLeft, rectTop); result.append(result.last()); result << coordsToPixels(rectRight, rectTop); } - break; - } - } - break; - } + { + case 2: { result << coordsToPixels(rectLeft, rectBottom); break; } + case 6: { result << coordsToPixels(rectLeft, rectBottom); break; } + case 1: { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectLeft, rectTop); break; } + case 9: { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectRight, rectBottom); break; } + case 4: { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectLeft, rectTop); result.append(result.last()); break; } + case 8: { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectRight, rectBottom); result.append(result.last()); break; } + case 7: { // in this case we need another distinction of cases: segment may pass below or above rect, requiring either bottom right or top left corner points + if ((value-prevValue)/(key-prevKey)*(rectRight-key)+value < rectBottom) // segment passes below R + { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectRight, rectBottom); result.append(result.last()); result << coordsToPixels(rectRight, rectTop); } + else + { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectLeft, rectTop); result.append(result.last()); result << coordsToPixels(rectRight, rectTop); } + break; + } + } + break; + } case 4: - { + { switch (currentRegion) - { - case 1: { result << coordsToPixels(rectLeft, rectTop); break; } - case 7: { result << coordsToPixels(rectRight, rectTop); break; } - case 2: { result << coordsToPixels(rectLeft, rectTop); result.append(result.last()); break; } - case 8: { result << coordsToPixels(rectRight, rectTop); result.append(result.last()); break; } - case 3: { result << coordsToPixels(rectLeft, rectTop); result.append(result.last()); result << coordsToPixels(rectLeft, rectBottom); break; } - case 9: { result << coordsToPixels(rectRight, rectTop); result.append(result.last()); result << coordsToPixels(rectRight, rectBottom); break; } - } - break; - } + { + case 1: { result << coordsToPixels(rectLeft, rectTop); break; } + case 7: { result << coordsToPixels(rectRight, rectTop); break; } + case 2: { result << coordsToPixels(rectLeft, rectTop); result.append(result.last()); break; } + case 8: { result << coordsToPixels(rectRight, rectTop); result.append(result.last()); break; } + case 3: { result << coordsToPixels(rectLeft, rectTop); result.append(result.last()); result << coordsToPixels(rectLeft, rectBottom); break; } + case 9: { result << coordsToPixels(rectRight, rectTop); result.append(result.last()); result << coordsToPixels(rectRight, rectBottom); break; } + } + break; + } case 5: - { + { switch (currentRegion) - { - case 1: { result << coordsToPixels(rectLeft, rectTop); break; } - case 7: { result << coordsToPixels(rectRight, rectTop); break; } - case 9: { result << coordsToPixels(rectRight, rectBottom); break; } - case 3: { result << coordsToPixels(rectLeft, rectBottom); break; } - } - break; - } + { + case 1: { result << coordsToPixels(rectLeft, rectTop); break; } + case 7: { result << coordsToPixels(rectRight, rectTop); break; } + case 9: { result << coordsToPixels(rectRight, rectBottom); break; } + case 3: { result << coordsToPixels(rectLeft, rectBottom); break; } + } + break; + } case 6: - { + { switch (currentRegion) - { - case 3: { result << coordsToPixels(rectLeft, rectBottom); break; } - case 9: { result << coordsToPixels(rectRight, rectBottom); break; } - case 2: { result << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); break; } - case 8: { result << coordsToPixels(rectRight, rectBottom); result.append(result.last()); break; } - case 1: { result << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); result << coordsToPixels(rectLeft, rectTop); break; } - case 7: { result << coordsToPixels(rectRight, rectBottom); result.append(result.last()); result << coordsToPixels(rectRight, rectTop); break; } - } - break; - } + { + case 3: { result << coordsToPixels(rectLeft, rectBottom); break; } + case 9: { result << coordsToPixels(rectRight, rectBottom); break; } + case 2: { result << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); break; } + case 8: { result << coordsToPixels(rectRight, rectBottom); result.append(result.last()); break; } + case 1: { result << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); result << coordsToPixels(rectLeft, rectTop); break; } + case 7: { result << coordsToPixels(rectRight, rectBottom); result.append(result.last()); result << coordsToPixels(rectRight, rectTop); break; } + } + break; + } case 7: - { + { switch (currentRegion) - { - case 4: { result << coordsToPixels(rectRight, rectTop); break; } - case 8: { result << coordsToPixels(rectRight, rectTop); break; } - case 1: { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectLeft, rectTop); break; } - case 9: { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectRight, rectBottom); break; } - case 2: { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectLeft, rectTop); result.append(result.last()); break; } - case 6: { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectRight, rectBottom); result.append(result.last()); break; } - case 3: { // in this case we need another distinction of cases: segment may pass below or above rect, requiring either bottom right or top left corner points - if ((value-prevValue)/(key-prevKey)*(rectRight-key)+value < rectBottom) // segment passes below R - { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectRight, rectBottom); result.append(result.last()); result << coordsToPixels(rectLeft, rectBottom); } - else - { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectLeft, rectTop); result.append(result.last()); result << coordsToPixels(rectLeft, rectBottom); } - break; - } - } - break; - } + { + case 4: { result << coordsToPixels(rectRight, rectTop); break; } + case 8: { result << coordsToPixels(rectRight, rectTop); break; } + case 1: { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectLeft, rectTop); break; } + case 9: { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectRight, rectBottom); break; } + case 2: { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectLeft, rectTop); result.append(result.last()); break; } + case 6: { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectRight, rectBottom); result.append(result.last()); break; } + case 3: { // in this case we need another distinction of cases: segment may pass below or above rect, requiring either bottom right or top left corner points + if ((value-prevValue)/(key-prevKey)*(rectRight-key)+value < rectBottom) // segment passes below R + { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectRight, rectBottom); result.append(result.last()); result << coordsToPixels(rectLeft, rectBottom); } + else + { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectLeft, rectTop); result.append(result.last()); result << coordsToPixels(rectLeft, rectBottom); } + break; + } + } + break; + } case 8: - { + { switch (currentRegion) - { - case 7: { result << coordsToPixels(rectRight, rectTop); break; } - case 9: { result << coordsToPixels(rectRight, rectBottom); break; } - case 4: { result << coordsToPixels(rectRight, rectTop); result.append(result.last()); break; } - case 6: { result << coordsToPixels(rectRight, rectBottom); result.append(result.last()); break; } - case 1: { result << coordsToPixels(rectRight, rectTop); result.append(result.last()); result << coordsToPixels(rectLeft, rectTop); break; } - case 3: { result << coordsToPixels(rectRight, rectBottom); result.append(result.last()); result << coordsToPixels(rectLeft, rectBottom); break; } - } - break; - } + { + case 7: { result << coordsToPixels(rectRight, rectTop); break; } + case 9: { result << coordsToPixels(rectRight, rectBottom); break; } + case 4: { result << coordsToPixels(rectRight, rectTop); result.append(result.last()); break; } + case 6: { result << coordsToPixels(rectRight, rectBottom); result.append(result.last()); break; } + case 1: { result << coordsToPixels(rectRight, rectTop); result.append(result.last()); result << coordsToPixels(rectLeft, rectTop); break; } + case 3: { result << coordsToPixels(rectRight, rectBottom); result.append(result.last()); result << coordsToPixels(rectLeft, rectBottom); break; } + } + break; + } case 9: - { + { switch (currentRegion) - { - case 6: { result << coordsToPixels(rectRight, rectBottom); break; } - case 8: { result << coordsToPixels(rectRight, rectBottom); break; } - case 3: { result << coordsToPixels(rectRight, rectBottom) << coordsToPixels(rectLeft, rectBottom); break; } - case 7: { result << coordsToPixels(rectRight, rectBottom) << coordsToPixels(rectRight, rectTop); break; } - case 2: { result << coordsToPixels(rectRight, rectBottom) << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); break; } - case 4: { result << coordsToPixels(rectRight, rectBottom) << coordsToPixels(rectRight, rectTop); result.append(result.last()); break; } - case 1: { // in this case we need another distinction of cases: segment may pass below or above rect, requiring either bottom right or top left corner points - if ((value-prevValue)/(key-prevKey)*(rectLeft-key)+value < rectBottom) // segment passes below R - { result << coordsToPixels(rectRight, rectBottom) << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); result << coordsToPixels(rectLeft, rectTop); } - else - { result << coordsToPixels(rectRight, rectBottom) << coordsToPixels(rectRight, rectTop); result.append(result.last()); result << coordsToPixels(rectLeft, rectTop); } - break; - } - } - break; - } - } - return result; + { + case 6: { result << coordsToPixels(rectRight, rectBottom); break; } + case 8: { result << coordsToPixels(rectRight, rectBottom); break; } + case 3: { result << coordsToPixels(rectRight, rectBottom) << coordsToPixels(rectLeft, rectBottom); break; } + case 7: { result << coordsToPixels(rectRight, rectBottom) << coordsToPixels(rectRight, rectTop); break; } + case 2: { result << coordsToPixels(rectRight, rectBottom) << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); break; } + case 4: { result << coordsToPixels(rectRight, rectBottom) << coordsToPixels(rectRight, rectTop); result.append(result.last()); break; } + case 1: { // in this case we need another distinction of cases: segment may pass below or above rect, requiring either bottom right or top left corner points + if ((value-prevValue)/(key-prevKey)*(rectLeft-key)+value < rectBottom) // segment passes below R + { result << coordsToPixels(rectRight, rectBottom) << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); result << coordsToPixels(rectLeft, rectTop); } + else + { result << coordsToPixels(rectRight, rectBottom) << coordsToPixels(rectRight, rectTop); result.append(result.last()); result << coordsToPixels(rectLeft, rectTop); } + break; + } + } + break; + } + } + return result; } /*! \internal @@ -18111,89 +17612,89 @@ QVector QCPCurve::getOptimizedC */ bool QCPCurve::mayTraverse(int prevRegion, int currentRegion) const { - switch (prevRegion) + switch (prevRegion) { case 1: - { + { switch (currentRegion) - { - case 4: - case 7: - case 2: - case 3: return false; - default: return true; - } - } + { + case 4: + case 7: + case 2: + case 3: return false; + default: return true; + } + } case 2: - { + { switch (currentRegion) - { - case 1: - case 3: return false; - default: return true; - } - } + { + case 1: + case 3: return false; + default: return true; + } + } case 3: - { + { switch (currentRegion) - { - case 1: - case 2: - case 6: - case 9: return false; - default: return true; - } - } + { + case 1: + case 2: + case 6: + case 9: return false; + default: return true; + } + } case 4: - { + { switch (currentRegion) - { - case 1: - case 7: return false; - default: return true; - } - } + { + case 1: + case 7: return false; + default: return true; + } + } case 5: return false; // should never occur case 6: - { + { switch (currentRegion) - { - case 3: - case 9: return false; - default: return true; - } - } + { + case 3: + case 9: return false; + default: return true; + } + } case 7: - { + { switch (currentRegion) - { - case 1: - case 4: - case 8: - case 9: return false; - default: return true; - } - } + { + case 1: + case 4: + case 8: + case 9: return false; + default: return true; + } + } case 8: - { + { switch (currentRegion) - { - case 7: - case 9: return false; - default: return true; - } - } + { + case 7: + case 9: return false; + default: return true; + } + } case 9: - { + { switch (currentRegion) - { - case 3: - case 6: - case 8: - case 7: return false; - default: return true; - } - } + { + case 3: + case 6: + case 8: + case 7: return false; + default: return true; + } + } default: return true; } } @@ -18214,73 +17715,73 @@ bool QCPCurve::mayTraverse(int prevRegio */ bool QCPCurve::getTraverse(double prevKey, double prevValue, double key, double value, double rectLeft, double rectTop, double rectRight, double rectBottom, QPointF &crossA, QPointF &crossB) const { - QList intersections; // x of QPointF corresponds to key and y to value - if (qFuzzyIsNull(key-prevKey)) // line is parallel to value axis - { - // due to region filter in mayTraverseR(), if line is parallel to value or key axis, R is traversed here - intersections.append(QPointF(key, rectBottom)); // direction will be taken care of at end of method - intersections.append(QPointF(key, rectTop)); + QList intersections; // x of QPointF corresponds to key and y to value + if (qFuzzyIsNull(key-prevKey)) // line is parallel to value axis + { + // due to region filter in mayTraverseR(), if line is parallel to value or key axis, R is traversed here + intersections.append(QPointF(key, rectBottom)); // direction will be taken care of at end of method + intersections.append(QPointF(key, rectTop)); } else if (qFuzzyIsNull(value-prevValue)) // line is parallel to key axis { - // due to region filter in mayTraverseR(), if line is parallel to value or key axis, R is traversed here - intersections.append(QPointF(rectLeft, value)); // direction will be taken care of at end of method - intersections.append(QPointF(rectRight, value)); + // due to region filter in mayTraverseR(), if line is parallel to value or key axis, R is traversed here + intersections.append(QPointF(rectLeft, value)); // direction will be taken care of at end of method + intersections.append(QPointF(rectRight, value)); } else // line is skewed { - double gamma; - double keyPerValue = (key-prevKey)/(value-prevValue); - // check top of rect: - gamma = prevKey + (rectTop-prevValue)*keyPerValue; - if (gamma >= rectLeft && gamma <= rectRight) - intersections.append(QPointF(gamma, rectTop)); - // check bottom of rect: - gamma = prevKey + (rectBottom-prevValue)*keyPerValue; - if (gamma >= rectLeft && gamma <= rectRight) - intersections.append(QPointF(gamma, rectBottom)); - double valuePerKey = 1.0/keyPerValue; - // check left of rect: - gamma = prevValue + (rectLeft-prevKey)*valuePerKey; - if (gamma >= rectBottom && gamma <= rectTop) - intersections.append(QPointF(rectLeft, gamma)); - // check right of rect: - gamma = prevValue + (rectRight-prevKey)*valuePerKey; - if (gamma >= rectBottom && gamma <= rectTop) - intersections.append(QPointF(rectRight, gamma)); - } - - // handle cases where found points isn't exactly 2: - if (intersections.size() > 2) - { - // line probably goes through corner of rect, and we got duplicate points there. single out the point pair with greatest distance in between: - double distSqrMax = 0; - QPointF pv1, pv2; - for (int i=0; i distSqrMax) + double gamma; + double keyPerValue = (key-prevKey)/(value-prevValue); + // check top of rect: + gamma = prevKey + (rectTop-prevValue)*keyPerValue; + if (gamma >= rectLeft && gamma <= rectRight) + intersections.append(QPointF(gamma, rectTop)); + // check bottom of rect: + gamma = prevKey + (rectBottom-prevValue)*keyPerValue; + if (gamma >= rectLeft && gamma <= rectRight) + intersections.append(QPointF(gamma, rectBottom)); + double valuePerKey = 1.0/keyPerValue; + // check left of rect: + gamma = prevValue + (rectLeft-prevKey)*valuePerKey; + if (gamma >= rectBottom && gamma <= rectTop) + intersections.append(QPointF(rectLeft, gamma)); + // check right of rect: + gamma = prevValue + (rectRight-prevKey)*valuePerKey; + if (gamma >= rectBottom && gamma <= rectTop) + intersections.append(QPointF(rectRight, gamma)); + } + + // handle cases where found points isn't exactly 2: + if (intersections.size() > 2) + { + // line probably goes through corner of rect, and we got duplicate points there. single out the point pair with greatest distance in between: + double distSqrMax = 0; + QPointF pv1, pv2; + for (int i=0; i distSqrMax) { - pv1 = intersections.at(i); - pv2 = intersections.at(k); - distSqrMax = distSqr; + pv1 = intersections.at(i); + pv2 = intersections.at(k); + distSqrMax = distSqr; } } } - intersections = QList() << pv1 << pv2; + intersections = QList() << pv1 << pv2; } else if (intersections.size() != 2) { - // one or even zero points found (shouldn't happen unless line perfectly tangent to corner), no need to draw segment - return false; - } - - // possibly re-sort points so optimized point segment has same direction as original segment: - if ((key-prevKey)*(intersections.at(1).x()-intersections.at(0).x()) + (value-prevValue)*(intersections.at(1).y()-intersections.at(0).y()) < 0) // scalar product of both segments < 0 -> opposite direction - intersections.move(0, 1); - crossA = coordsToPixels(intersections.at(0).x(), intersections.at(0).y()); - crossB = coordsToPixels(intersections.at(1).x(), intersections.at(1).y()); - return true; + // one or even zero points found (shouldn't happen unless line perfectly tangent to corner), no need to draw segment + return false; + } + + // possibly re-sort points so optimized point segment has same direction as original segment: + if ((key-prevKey)*(intersections.at(1).x()-intersections.at(0).x()) + (value-prevValue)*(intersections.at(1).y()-intersections.at(0).y()) < 0) // scalar product of both segments < 0 -> opposite direction + intersections.move(0, 1); + crossA = coordsToPixels(intersections.at(0).x(), intersections.at(0).y()); + crossB = coordsToPixels(intersections.at(1).x(), intersections.at(1).y()); + return true; } /*! \internal @@ -18310,85 +17811,85 @@ bool QCPCurve::getTraverse(double prevKe */ void QCPCurve::getTraverseCornerPoints(int prevRegion, int currentRegion, double rectLeft, double rectTop, double rectRight, double rectBottom, QVector &beforeTraverse, QVector &afterTraverse) const { - switch (prevRegion) + switch (prevRegion) { case 1: - { + { switch (currentRegion) - { - case 6: { beforeTraverse << coordsToPixels(rectLeft, rectTop); break; } - case 9: { beforeTraverse << coordsToPixels(rectLeft, rectTop); afterTraverse << coordsToPixels(rectRight, rectBottom); break; } - case 8: { beforeTraverse << coordsToPixels(rectLeft, rectTop); break; } - } - break; - } + { + case 6: { beforeTraverse << coordsToPixels(rectLeft, rectTop); break; } + case 9: { beforeTraverse << coordsToPixels(rectLeft, rectTop); afterTraverse << coordsToPixels(rectRight, rectBottom); break; } + case 8: { beforeTraverse << coordsToPixels(rectLeft, rectTop); break; } + } + break; + } case 2: - { + { switch (currentRegion) - { - case 7: { afterTraverse << coordsToPixels(rectRight, rectTop); break; } - case 9: { afterTraverse << coordsToPixels(rectRight, rectBottom); break; } - } - break; - } + { + case 7: { afterTraverse << coordsToPixels(rectRight, rectTop); break; } + case 9: { afterTraverse << coordsToPixels(rectRight, rectBottom); break; } + } + break; + } case 3: - { + { switch (currentRegion) - { - case 4: { beforeTraverse << coordsToPixels(rectLeft, rectBottom); break; } - case 7: { beforeTraverse << coordsToPixels(rectLeft, rectBottom); afterTraverse << coordsToPixels(rectRight, rectTop); break; } - case 8: { beforeTraverse << coordsToPixels(rectLeft, rectBottom); break; } - } - break; - } + { + case 4: { beforeTraverse << coordsToPixels(rectLeft, rectBottom); break; } + case 7: { beforeTraverse << coordsToPixels(rectLeft, rectBottom); afterTraverse << coordsToPixels(rectRight, rectTop); break; } + case 8: { beforeTraverse << coordsToPixels(rectLeft, rectBottom); break; } + } + break; + } case 4: - { + { switch (currentRegion) - { - case 3: { afterTraverse << coordsToPixels(rectLeft, rectBottom); break; } - case 9: { afterTraverse << coordsToPixels(rectRight, rectBottom); break; } - } - break; - } + { + case 3: { afterTraverse << coordsToPixels(rectLeft, rectBottom); break; } + case 9: { afterTraverse << coordsToPixels(rectRight, rectBottom); break; } + } + break; + } case 5: { break; } // shouldn't happen because this method only handles full traverses case 6: - { + { switch (currentRegion) - { - case 1: { afterTraverse << coordsToPixels(rectLeft, rectTop); break; } - case 7: { afterTraverse << coordsToPixels(rectRight, rectTop); break; } - } - break; - } + { + case 1: { afterTraverse << coordsToPixels(rectLeft, rectTop); break; } + case 7: { afterTraverse << coordsToPixels(rectRight, rectTop); break; } + } + break; + } case 7: - { + { switch (currentRegion) - { - case 2: { beforeTraverse << coordsToPixels(rectRight, rectTop); break; } - case 3: { beforeTraverse << coordsToPixels(rectRight, rectTop); afterTraverse << coordsToPixels(rectLeft, rectBottom); break; } - case 6: { beforeTraverse << coordsToPixels(rectRight, rectTop); break; } - } - break; - } + { + case 2: { beforeTraverse << coordsToPixels(rectRight, rectTop); break; } + case 3: { beforeTraverse << coordsToPixels(rectRight, rectTop); afterTraverse << coordsToPixels(rectLeft, rectBottom); break; } + case 6: { beforeTraverse << coordsToPixels(rectRight, rectTop); break; } + } + break; + } case 8: - { + { switch (currentRegion) - { - case 1: { afterTraverse << coordsToPixels(rectLeft, rectTop); break; } - case 3: { afterTraverse << coordsToPixels(rectLeft, rectBottom); break; } - } - break; - } + { + case 1: { afterTraverse << coordsToPixels(rectLeft, rectTop); break; } + case 3: { afterTraverse << coordsToPixels(rectLeft, rectBottom); break; } + } + break; + } case 9: - { + { switch (currentRegion) - { - case 2: { beforeTraverse << coordsToPixels(rectRight, rectBottom); break; } - case 1: { beforeTraverse << coordsToPixels(rectRight, rectBottom); afterTraverse << coordsToPixels(rectLeft, rectTop); break; } - case 4: { beforeTraverse << coordsToPixels(rectRight, rectBottom); break; } - } - break; - } + { + case 2: { beforeTraverse << coordsToPixels(rectRight, rectBottom); break; } + case 1: { beforeTraverse << coordsToPixels(rectRight, rectBottom); afterTraverse << coordsToPixels(rectLeft, rectTop); break; } + case 4: { beforeTraverse << coordsToPixels(rectRight, rectBottom); break; } + } + break; + } } } @@ -18400,95 +17901,95 @@ void QCPCurve::getTraverseCornerPoints(i */ double QCPCurve::pointDistance(const QPointF &pixelPoint) const { - if (mData->isEmpty()) - { - qDebug() << Q_FUNC_INFO << "requested point distance on curve" << mName << "without data"; - return 500; - } - if (mData->size() == 1) - { - QPointF dataPoint = coordsToPixels(mData->constBegin().key(), mData->constBegin().value().value); - return QVector2D(dataPoint-pixelPoint).length(); - } - - // calculate minimum distance to line segments: - QVector *lineData = new QVector; - getCurveData(lineData); - double minDistSqr = std::numeric_limits::max(); - for (int i=0; isize()-1; ++i) - { - double currentDistSqr = distSqrToLine(lineData->at(i), lineData->at(i+1), pixelPoint); - if (currentDistSqr < minDistSqr) - minDistSqr = currentDistSqr; - } - delete lineData; - return qSqrt(minDistSqr); + if (mData->isEmpty()) + { + qDebug() << Q_FUNC_INFO << "requested point distance on curve" << mName << "without data"; + return 500; + } + if (mData->size() == 1) + { + QPointF dataPoint = coordsToPixels(mData->constBegin().key(), mData->constBegin().value().value); + return QVector2D(dataPoint-pixelPoint).length(); + } + + // calculate minimum distance to line segments: + QVector *lineData = new QVector; + getCurveData(lineData); + double minDistSqr = std::numeric_limits::max(); + for (int i=0; isize()-1; ++i) + { + double currentDistSqr = distSqrToLine(lineData->at(i), lineData->at(i+1), pixelPoint); + if (currentDistSqr < minDistSqr) + minDistSqr = currentDistSqr; + } + delete lineData; + return qSqrt(minDistSqr); } /* inherits documentation from base class */ QCPRange QCPCurve::getKeyRange(bool &foundRange, SignDomain inSignDomain) const { - QCPRange range; - bool haveLower = false; - bool haveUpper = false; - - double current; - - QCPCurveDataMap::const_iterator it = mData->constBegin(); - while (it != mData->constEnd()) - { - current = it.value().key; - if (inSignDomain == sdBoth || (inSignDomain == sdNegative && current < 0) || (inSignDomain == sdPositive && current > 0)) - { - if (current < range.lower || !haveLower) - { - range.lower = current; - haveLower = true; - } - if (current > range.upper || !haveUpper) - { - range.upper = current; - haveUpper = true; - } - } - ++it; - } - - foundRange = haveLower && haveUpper; - return range; + QCPRange range; + bool haveLower = false; + bool haveUpper = false; + + double current; + + QCPCurveDataMap::const_iterator it = mData->constBegin(); + while (it != mData->constEnd()) + { + current = it.value().key; + if (inSignDomain == sdBoth || (inSignDomain == sdNegative && current < 0) || (inSignDomain == sdPositive && current > 0)) + { + if (current < range.lower || !haveLower) + { + range.lower = current; + haveLower = true; + } + if (current > range.upper || !haveUpper) + { + range.upper = current; + haveUpper = true; + } + } + ++it; + } + + foundRange = haveLower && haveUpper; + return range; } /* inherits documentation from base class */ QCPRange QCPCurve::getValueRange(bool &foundRange, SignDomain inSignDomain) const { - QCPRange range; - bool haveLower = false; - bool haveUpper = false; - - double current; - - QCPCurveDataMap::const_iterator it = mData->constBegin(); - while (it != mData->constEnd()) - { - current = it.value().value; - if (inSignDomain == sdBoth || (inSignDomain == sdNegative && current < 0) || (inSignDomain == sdPositive && current > 0)) - { - if (current < range.lower || !haveLower) - { - range.lower = current; - haveLower = true; - } - if (current > range.upper || !haveUpper) - { - range.upper = current; - haveUpper = true; - } - } - ++it; - } - - foundRange = haveLower && haveUpper; - return range; + QCPRange range; + bool haveLower = false; + bool haveUpper = false; + + double current; + + QCPCurveDataMap::const_iterator it = mData->constBegin(); + while (it != mData->constEnd()) + { + current = it.value().value; + if (inSignDomain == sdBoth || (inSignDomain == sdNegative && current < 0) || (inSignDomain == sdPositive && current > 0)) + { + if (current < range.lower || !haveLower) + { + range.lower = current; + haveLower = true; + } + if (current > range.upper || !haveUpper) + { + range.upper = current; + haveUpper = true; + } + } + ++it; + } + + foundRange = haveLower && haveUpper; + return range; } @@ -18563,16 +18064,16 @@ QCPRange QCPCurve::getValueRange(bool &f Constructs a new bars group for the specified QCustomPlot instance. */ QCPBarsGroup::QCPBarsGroup(QCustomPlot *parentPlot) : - QObject(parentPlot), - mParentPlot(parentPlot), - mSpacingType(stAbsolute), - mSpacing(4) + QObject(parentPlot), + mParentPlot(parentPlot), + mSpacingType(stAbsolute), + mSpacing(4) { } QCPBarsGroup::~QCPBarsGroup() { - clear(); + clear(); } /*! @@ -18584,7 +18085,7 @@ QCPBarsGroup::~QCPBarsGroup() */ void QCPBarsGroup::setSpacingType(SpacingType spacingType) { - mSpacingType = spacingType; + mSpacingType = spacingType; } /*! @@ -18595,7 +18096,7 @@ void QCPBarsGroup::setSpacingType(Spacin */ void QCPBarsGroup::setSpacing(double spacing) { - mSpacing = spacing; + mSpacing = spacing; } /*! @@ -18606,13 +18107,13 @@ void QCPBarsGroup::setSpacing(double spa */ QCPBars *QCPBarsGroup::bars(int index) const { - if (index >= 0 && index < mBars.size()) - { - return mBars.at(index); - } else - { - qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; - return 0; + if (index >= 0 && index < mBars.size()) + { + return mBars.at(index); + } else + { + qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; + return 0; } } @@ -18623,8 +18124,8 @@ QCPBars *QCPBarsGroup::bars(int index) c */ void QCPBarsGroup::clear() { - foreach (QCPBars *bars, mBars) // since foreach takes a copy, removing bars in the loop is okay - bars->setBarsGroup(0); // removes itself via removeBars + foreach (QCPBars *bars, mBars) // since foreach takes a copy, removing bars in the loop is okay + bars->setBarsGroup(0); // removes itself via removeBars } /*! @@ -18635,16 +18136,16 @@ void QCPBarsGroup::clear() */ void QCPBarsGroup::append(QCPBars *bars) { - if (!bars) - { - qDebug() << Q_FUNC_INFO << "bars is 0"; - return; - } - - if (!mBars.contains(bars)) - bars->setBarsGroup(this); - else - qDebug() << Q_FUNC_INFO << "bars plottable is already in this bars group:" << reinterpret_cast(bars); + if (!bars) + { + qDebug() << Q_FUNC_INFO << "bars is 0"; + return; + } + + if (!mBars.contains(bars)) + bars->setBarsGroup(this); + else + qDebug() << Q_FUNC_INFO << "bars plottable is already in this bars group:" << reinterpret_cast(bars); } /*! @@ -18658,17 +18159,17 @@ void QCPBarsGroup::append(QCPBars *bars) */ void QCPBarsGroup::insert(int i, QCPBars *bars) { - if (!bars) - { - qDebug() << Q_FUNC_INFO << "bars is 0"; - return; - } - - // first append to bars list normally: - if (!mBars.contains(bars)) - bars->setBarsGroup(this); - // then move to according position: - mBars.move(mBars.indexOf(bars), qBound(0, i, mBars.size()-1)); + if (!bars) + { + qDebug() << Q_FUNC_INFO << "bars is 0"; + return; + } + + // first append to bars list normally: + if (!mBars.contains(bars)) + bars->setBarsGroup(this); + // then move to according position: + mBars.move(mBars.indexOf(bars), qBound(0, i, mBars.size()-1)); } /*! @@ -18678,16 +18179,16 @@ void QCPBarsGroup::insert(int i, QCPBars */ void QCPBarsGroup::remove(QCPBars *bars) { - if (!bars) - { - qDebug() << Q_FUNC_INFO << "bars is 0"; - return; - } - - if (mBars.contains(bars)) - bars->setBarsGroup(0); - else - qDebug() << Q_FUNC_INFO << "bars plottable is not in this bars group:" << reinterpret_cast(bars); + if (!bars) + { + qDebug() << Q_FUNC_INFO << "bars is 0"; + return; + } + + if (mBars.contains(bars)) + bars->setBarsGroup(0); + else + qDebug() << Q_FUNC_INFO << "bars plottable is not in this bars group:" << reinterpret_cast(bars); } /*! \internal @@ -18699,8 +18200,8 @@ void QCPBarsGroup::remove(QCPBars *bars) */ void QCPBarsGroup::registerBars(QCPBars *bars) { - if (!mBars.contains(bars)) - mBars.append(bars); + if (!mBars.contains(bars)) + mBars.append(bars); } /*! \internal @@ -18712,7 +18213,7 @@ void QCPBarsGroup::registerBars(QCPBars */ void QCPBarsGroup::unregisterBars(QCPBars *bars) { - mBars.removeOne(bars); + mBars.removeOne(bars); } /*! \internal @@ -18723,77 +18224,77 @@ void QCPBarsGroup::unregisterBars(QCPBar */ double QCPBarsGroup::keyPixelOffset(const QCPBars *bars, double keyCoord) { - // find list of all base bars in case some mBars are stacked: - QList baseBars; - foreach (const QCPBars *b, mBars) - { - while (b->barBelow()) - b = b->barBelow(); - if (!baseBars.contains(b)) - baseBars.append(b); - } - // find base bar this "bars" is stacked on: - const QCPBars *thisBase = bars; - while (thisBase->barBelow()) - thisBase = thisBase->barBelow(); - - // determine key pixel offset of this base bars considering all other base bars in this barsgroup: - double result = 0; - int index = baseBars.indexOf(thisBase); - if (index >= 0) - { - int startIndex; - double lowerPixelWidth, upperPixelWidth; - if (baseBars.size() % 2 == 1 && index == (baseBars.size()-1)/2) // is center bar (int division on purpose) - { - return result; + // find list of all base bars in case some mBars are stacked: + QList baseBars; + foreach (const QCPBars *b, mBars) + { + while (b->barBelow()) + b = b->barBelow(); + if (!baseBars.contains(b)) + baseBars.append(b); + } + // find base bar this "bars" is stacked on: + const QCPBars *thisBase = bars; + while (thisBase->barBelow()) + thisBase = thisBase->barBelow(); + + // determine key pixel offset of this base bars considering all other base bars in this barsgroup: + double result = 0; + int index = baseBars.indexOf(thisBase); + if (index >= 0) + { + int startIndex; + double lowerPixelWidth, upperPixelWidth; + if (baseBars.size() % 2 == 1 && index == (baseBars.size()-1)/2) // is center bar (int division on purpose) + { + return result; } else if (index < (baseBars.size()-1)/2.0) // bar is to the left of center { - if (baseBars.size() % 2 == 0) // even number of bars - { - startIndex = baseBars.size()/2-1; - result -= getPixelSpacing(baseBars.at(startIndex), keyCoord)*0.5; // half of middle spacing + if (baseBars.size() % 2 == 0) // even number of bars + { + startIndex = baseBars.size()/2-1; + result -= getPixelSpacing(baseBars.at(startIndex), keyCoord)*0.5; // half of middle spacing } else // uneven number of bars { - startIndex = (baseBars.size()-1)/2-1; - baseBars.at((baseBars.size()-1)/2)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth); - result -= qAbs(upperPixelWidth-lowerPixelWidth)*0.5; // half of center bar - result -= getPixelSpacing(baseBars.at((baseBars.size()-1)/2), keyCoord); // center bar spacing - } - for (int i=startIndex; i>index; --i) // add widths and spacings of bars in between center and our bars - { - baseBars.at(i)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth); - result -= qAbs(upperPixelWidth-lowerPixelWidth); - result -= getPixelSpacing(baseBars.at(i), keyCoord); - } - // finally half of our bars width: - baseBars.at(index)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth); - result -= qAbs(upperPixelWidth-lowerPixelWidth)*0.5; + startIndex = (baseBars.size()-1)/2-1; + baseBars.at((baseBars.size()-1)/2)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth); + result -= qAbs(upperPixelWidth-lowerPixelWidth)*0.5; // half of center bar + result -= getPixelSpacing(baseBars.at((baseBars.size()-1)/2), keyCoord); // center bar spacing + } + for (int i=startIndex; i>index; --i) // add widths and spacings of bars in between center and our bars + { + baseBars.at(i)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth); + result -= qAbs(upperPixelWidth-lowerPixelWidth); + result -= getPixelSpacing(baseBars.at(i), keyCoord); + } + // finally half of our bars width: + baseBars.at(index)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth); + result -= qAbs(upperPixelWidth-lowerPixelWidth)*0.5; } else // bar is to the right of center { - if (baseBars.size() % 2 == 0) // even number of bars - { - startIndex = baseBars.size()/2; - result += getPixelSpacing(baseBars.at(startIndex), keyCoord)*0.5; // half of middle spacing + if (baseBars.size() % 2 == 0) // even number of bars + { + startIndex = baseBars.size()/2; + result += getPixelSpacing(baseBars.at(startIndex), keyCoord)*0.5; // half of middle spacing } else // uneven number of bars { - startIndex = (baseBars.size()-1)/2+1; - baseBars.at((baseBars.size()-1)/2)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth); - result += qAbs(upperPixelWidth-lowerPixelWidth)*0.5; // half of center bar - result += getPixelSpacing(baseBars.at((baseBars.size()-1)/2), keyCoord); // center bar spacing - } - for (int i=startIndex; igetPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth); - result += qAbs(upperPixelWidth-lowerPixelWidth); - result += getPixelSpacing(baseBars.at(i), keyCoord); - } - // finally half of our bars width: - baseBars.at(index)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth); - result += qAbs(upperPixelWidth-lowerPixelWidth)*0.5; - } - } - return result; + startIndex = (baseBars.size()-1)/2+1; + baseBars.at((baseBars.size()-1)/2)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth); + result += qAbs(upperPixelWidth-lowerPixelWidth)*0.5; // half of center bar + result += getPixelSpacing(baseBars.at((baseBars.size()-1)/2), keyCoord); // center bar spacing + } + for (int i=startIndex; igetPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth); + result += qAbs(upperPixelWidth-lowerPixelWidth); + result += getPixelSpacing(baseBars.at(i), keyCoord); + } + // finally half of our bars width: + baseBars.at(index)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth); + result += qAbs(upperPixelWidth-lowerPixelWidth)*0.5; + } + } + return result; } /*! \internal @@ -18808,26 +18309,26 @@ double QCPBarsGroup::keyPixelOffset(cons */ double QCPBarsGroup::getPixelSpacing(const QCPBars *bars, double keyCoord) { - switch (mSpacingType) + switch (mSpacingType) { case stAbsolute: - { + { return mSpacing; - } + } case stAxisRectRatio: - { + { if (bars->keyAxis()->orientation() == Qt::Horizontal) - return bars->keyAxis()->axisRect()->width()*mSpacing; + return bars->keyAxis()->axisRect()->width()*mSpacing; else - return bars->keyAxis()->axisRect()->height()*mSpacing; - } + return bars->keyAxis()->axisRect()->height()*mSpacing; + } case stPlotCoords: - { + { double keyPixel = bars->keyAxis()->coordToPixel(keyCoord); return bars->keyAxis()->coordToPixel(keyCoord+mSpacing)-keyPixel; - } - } - return 0; + } + } + return 0; } @@ -18851,8 +18352,8 @@ double QCPBarsGroup::getPixelSpacing(con Constructs a bar data point with key and value set to zero. */ QCPBarData::QCPBarData() : - key(0), - value(0) + key(0), + value(0) { } @@ -18860,8 +18361,8 @@ QCPBarData::QCPBarData() : Constructs a bar data point with the specified \a key and \a value. */ QCPBarData::QCPBarData(double key, double value) : - key(key), - value(value) + key(key), + value(value) { } @@ -18937,30 +18438,30 @@ QCPBarData::QCPBarData(double key, doubl then takes ownership of the bar chart. */ QCPBars::QCPBars(QCPAxis *keyAxis, QCPAxis *valueAxis) : - QCPAbstractPlottable(keyAxis, valueAxis), - mData(new QCPBarDataMap), - mWidth(0.75), - mWidthType(wtPlotCoords), - mBarsGroup(0), - mBaseValue(0) -{ - // modify inherited properties from abstract plottable: - mPen.setColor(Qt::blue); - mPen.setStyle(Qt::SolidLine); - mBrush.setColor(QColor(40, 50, 255, 30)); - mBrush.setStyle(Qt::SolidPattern); - mSelectedPen = mPen; - mSelectedPen.setWidthF(2.5); - mSelectedPen.setColor(QColor(80, 80, 255)); // lighter than Qt::blue of mPen - mSelectedBrush = mBrush; + QCPAbstractPlottable(keyAxis, valueAxis), + mData(new QCPBarDataMap), + mWidth(0.75), + mWidthType(wtPlotCoords), + mBarsGroup(0), + mBaseValue(0) +{ + // modify inherited properties from abstract plottable: + mPen.setColor(Qt::blue); + mPen.setStyle(Qt::SolidLine); + mBrush.setColor(QColor(40, 50, 255, 30)); + mBrush.setStyle(Qt::SolidPattern); + mSelectedPen = mPen; + mSelectedPen.setWidthF(2.5); + mSelectedPen.setColor(QColor(80, 80, 255)); // lighter than Qt::blue of mPen + mSelectedBrush = mBrush; } QCPBars::~QCPBars() { - setBarsGroup(0); - if (mBarBelow || mBarAbove) - connectBars(mBarBelow.data(), mBarAbove.data()); // take this bar out of any stacking - delete mData; + setBarsGroup(0); + if (mBarBelow || mBarAbove) + connectBars(mBarBelow.data(), mBarAbove.data()); // take this bar out of any stacking + delete mData; } /*! @@ -18971,7 +18472,7 @@ QCPBars::~QCPBars() */ void QCPBars::setWidth(double width) { - mWidth = width; + mWidth = width; } /*! @@ -18984,7 +18485,7 @@ void QCPBars::setWidth(double width) */ void QCPBars::setWidthType(QCPBars::WidthType widthType) { - mWidthType = widthType; + mWidthType = widthType; } /*! @@ -18995,13 +18496,13 @@ void QCPBars::setWidthType(QCPBars::Widt */ void QCPBars::setBarsGroup(QCPBarsGroup *barsGroup) { - // deregister at old group: - if (mBarsGroup) - mBarsGroup->unregisterBars(this); - mBarsGroup = barsGroup; - // register at new group: - if (mBarsGroup) - mBarsGroup->registerBars(this); + // deregister at old group: + if (mBarsGroup) + mBarsGroup->unregisterBars(this); + mBarsGroup = barsGroup; + // register at new group: + if (mBarsGroup) + mBarsGroup->registerBars(this); } /*! @@ -19018,7 +18519,7 @@ void QCPBars::setBarsGroup(QCPBarsGroup */ void QCPBars::setBaseValue(double baseValue) { - mBaseValue = baseValue; + mBaseValue = baseValue; } /*! @@ -19030,18 +18531,18 @@ void QCPBars::setBaseValue(double baseVa */ void QCPBars::setData(QCPBarDataMap *data, bool copy) { - if (mData == data) - { - qDebug() << Q_FUNC_INFO << "The data pointer is already in (and owned by) this plottable" << reinterpret_cast(data); - return; - } - if (copy) - { - *mData = *data; - } else - { - delete mData; - mData = data; + if (mData == data) + { + qDebug() << Q_FUNC_INFO << "The data pointer is already in (and owned by) this plottable" << reinterpret_cast(data); + return; + } + if (copy) + { + *mData = *data; + } else + { + delete mData; + mData = data; } } @@ -19053,15 +18554,15 @@ void QCPBars::setData(QCPBarDataMap *dat */ void QCPBars::setData(const QVector &key, const QVector &value) { - mData->clear(); - int n = key.size(); - n = qMin(n, value.size()); - QCPBarData newData; - for (int i=0; iinsertMulti(newData.key, newData); + mData->clear(); + int n = key.size(); + n = qMin(n, value.size()); + QCPBarData newData; + for (int i=0; iinsertMulti(newData.key, newData); } } @@ -19081,20 +18582,20 @@ void QCPBars::setData(const QVectorkeyAxis() != mKeyAxis.data() || bars->valueAxis() != mValueAxis.data())) - { - qDebug() << Q_FUNC_INFO << "passed QCPBars* doesn't have same key and value axis as this QCPBars"; - return; - } - // remove from stacking: - connectBars(mBarBelow.data(), mBarAbove.data()); // Note: also works if one (or both) of them is 0 - // if new bar given, insert this bar below it: - if (bars) - { - if (bars->mBarBelow) - connectBars(bars->mBarBelow.data(), this); - connectBars(this, bars); + if (bars == this) return; + if (bars && (bars->keyAxis() != mKeyAxis.data() || bars->valueAxis() != mValueAxis.data())) + { + qDebug() << Q_FUNC_INFO << "passed QCPBars* doesn't have same key and value axis as this QCPBars"; + return; + } + // remove from stacking: + connectBars(mBarBelow.data(), mBarAbove.data()); // Note: also works if one (or both) of them is 0 + // if new bar given, insert this bar below it: + if (bars) + { + if (bars->mBarBelow) + connectBars(bars->mBarBelow.data(), this); + connectBars(this, bars); } } @@ -19114,20 +18615,20 @@ void QCPBars::moveBelow(QCPBars *bars) */ void QCPBars::moveAbove(QCPBars *bars) { - if (bars == this) return; - if (bars && (bars->keyAxis() != mKeyAxis.data() || bars->valueAxis() != mValueAxis.data())) - { - qDebug() << Q_FUNC_INFO << "passed QCPBars* doesn't have same key and value axis as this QCPBars"; - return; - } - // remove from stacking: - connectBars(mBarBelow.data(), mBarAbove.data()); // Note: also works if one (or both) of them is 0 - // if new bar given, insert this bar above it: - if (bars) - { - if (bars->mBarAbove) - connectBars(this, bars->mBarAbove.data()); - connectBars(bars, this); + if (bars == this) return; + if (bars && (bars->keyAxis() != mKeyAxis.data() || bars->valueAxis() != mValueAxis.data())) + { + qDebug() << Q_FUNC_INFO << "passed QCPBars* doesn't have same key and value axis as this QCPBars"; + return; + } + // remove from stacking: + connectBars(mBarBelow.data(), mBarAbove.data()); // Note: also works if one (or both) of them is 0 + // if new bar given, insert this bar above it: + if (bars) + { + if (bars->mBarAbove) + connectBars(this, bars->mBarAbove.data()); + connectBars(bars, this); } } @@ -19137,7 +18638,7 @@ void QCPBars::moveAbove(QCPBars *bars) */ void QCPBars::addData(const QCPBarDataMap &dataMap) { - mData->unite(dataMap); + mData->unite(dataMap); } /*! \overload @@ -19146,7 +18647,7 @@ void QCPBars::addData(const QCPBarDataMa */ void QCPBars::addData(const QCPBarData &data) { - mData->insertMulti(data.key, data); + mData->insertMulti(data.key, data); } /*! \overload @@ -19155,10 +18656,10 @@ void QCPBars::addData(const QCPBarData & */ void QCPBars::addData(double key, double value) { - QCPBarData newData; - newData.key = key; - newData.value = value; - mData->insertMulti(newData.key, newData); + QCPBarData newData; + newData.key = key; + newData.value = value; + mData->insertMulti(newData.key, newData); } /*! \overload @@ -19167,14 +18668,14 @@ void QCPBars::addData(double key, double */ void QCPBars::addData(const QVector &keys, const QVector &values) { - int n = keys.size(); - n = qMin(n, values.size()); - QCPBarData newData; - for (int i=0; iinsertMulti(newData.key, newData); + int n = keys.size(); + n = qMin(n, values.size()); + QCPBarData newData; + for (int i=0; iinsertMulti(newData.key, newData); } } @@ -19184,9 +18685,9 @@ void QCPBars::addData(const QVectorbegin(); - while (it != mData->end() && it.key() < key) - it = mData->erase(it); + QCPBarDataMap::iterator it = mData->begin(); + while (it != mData->end() && it.key() < key) + it = mData->erase(it); } /*! @@ -19195,10 +18696,10 @@ void QCPBars::removeDataBefore(double ke */ void QCPBars::removeDataAfter(double key) { - if (mData->isEmpty()) return; - QCPBarDataMap::iterator it = mData->upperBound(key); - while (it != mData->end()) - it = mData->erase(it); + if (mData->isEmpty()) return; + QCPBarDataMap::iterator it = mData->upperBound(key); + while (it != mData->end()) + it = mData->erase(it); } /*! @@ -19210,11 +18711,11 @@ void QCPBars::removeDataAfter(double key */ void QCPBars::removeData(double fromKey, double toKey) { - if (fromKey >= toKey || mData->isEmpty()) return; - QCPBarDataMap::iterator it = mData->upperBound(fromKey); - QCPBarDataMap::iterator itEnd = mData->upperBound(toKey); - while (it != itEnd) - it = mData->erase(it); + if (fromKey >= toKey || mData->isEmpty()) return; + QCPBarDataMap::iterator it = mData->upperBound(fromKey); + QCPBarDataMap::iterator itEnd = mData->upperBound(toKey); + while (it != itEnd) + it = mData->erase(it); } /*! \overload @@ -19227,7 +18728,7 @@ void QCPBars::removeData(double fromKey, */ void QCPBars::removeData(double key) { - mData->remove(key); + mData->remove(key); } /*! @@ -19236,60 +18737,60 @@ void QCPBars::removeData(double key) */ void QCPBars::clearData() { - mData->clear(); + mData->clear(); } /* inherits documentation from base class */ double QCPBars::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - Q_UNUSED(details) - if (onlySelectable && !mSelectable) + Q_UNUSED(details) + if (onlySelectable && !mSelectable) + return -1; + if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; } + + if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint())) + { + QCPBarDataMap::ConstIterator it; + for (it = mData->constBegin(); it != mData->constEnd(); ++it) + { + if (getBarPolygon(it.value().key, it.value().value).boundingRect().contains(pos)) + return mParentPlot->selectionTolerance()*0.99; + } + } return -1; - if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; } - - if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint())) - { - QCPBarDataMap::ConstIterator it; - for (it = mData->constBegin(); it != mData->constEnd(); ++it) - { - if (getBarPolygon(it.value().key, it.value().value).boundingRect().contains(pos)) - return mParentPlot->selectionTolerance()*0.99; - } - } - return -1; } /* inherits documentation from base class */ void QCPBars::draw(QCPPainter *painter) { - if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - if (mData->isEmpty()) return; - - QCPBarDataMap::const_iterator it, lower, upperEnd; - getVisibleDataBounds(lower, upperEnd); - for (it = lower; it != upperEnd; ++it) - { - // check data validity if flag set: + if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + if (mData->isEmpty()) return; + + QCPBarDataMap::const_iterator it, lower, upperEnd; + getVisibleDataBounds(lower, upperEnd); + for (it = lower; it != upperEnd; ++it) + { + // check data validity if flag set: #ifdef QCUSTOMPLOT_CHECK_DATA - if (QCP::isInvalidData(it.value().key, it.value().value)) - qDebug() << Q_FUNC_INFO << "Data point at" << it.key() << "of drawn range invalid." << "Plottable name:" << name(); + if (QCP::isInvalidData(it.value().key, it.value().value)) + qDebug() << Q_FUNC_INFO << "Data point at" << it.key() << "of drawn range invalid." << "Plottable name:" << name(); #endif - QPolygonF barPolygon = getBarPolygon(it.key(), it.value().value); - // draw bar fill: - if (mainBrush().style() != Qt::NoBrush && mainBrush().color().alpha() != 0) - { - applyFillAntialiasingHint(painter); - painter->setPen(Qt::NoPen); - painter->setBrush(mainBrush()); - painter->drawPolygon(barPolygon); - } - // draw bar line: - if (mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0) - { - applyDefaultAntialiasingHint(painter); - painter->setPen(mainPen()); - painter->setBrush(Qt::NoBrush); - painter->drawPolyline(barPolygon); + QPolygonF barPolygon = getBarPolygon(it.key(), it.value().value); + // draw bar fill: + if (mainBrush().style() != Qt::NoBrush && mainBrush().color().alpha() != 0) + { + applyFillAntialiasingHint(painter); + painter->setPen(Qt::NoPen); + painter->setBrush(mainBrush()); + painter->drawPolygon(barPolygon); + } + // draw bar line: + if (mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0) + { + applyDefaultAntialiasingHint(painter); + painter->setPen(mainPen()); + painter->setBrush(Qt::NoBrush); + painter->drawPolyline(barPolygon); } } } @@ -19297,13 +18798,13 @@ void QCPBars::draw(QCPPainter *painter) /* inherits documentation from base class */ void QCPBars::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const { - // draw filled rect: - applyDefaultAntialiasingHint(painter); - painter->setBrush(mBrush); - painter->setPen(mPen); - QRectF r = QRectF(0, 0, rect.width()*0.67, rect.height()*0.67); - r.moveCenter(rect.center()); - painter->drawRect(r); + // draw filled rect: + applyDefaultAntialiasingHint(painter); + painter->setBrush(mBrush); + painter->setPen(mPen); + QRectF r = QRectF(0, 0, rect.width()*0.67, rect.height()*0.67); + r.moveCenter(rect.center()); + painter->drawRect(r); } /*! \internal @@ -19322,49 +18823,49 @@ void QCPBars::drawLegendIcon(QCPPainter */ void QCPBars::getVisibleDataBounds(QCPBarDataMap::const_iterator &lower, QCPBarDataMap::const_iterator &upperEnd) const { - if (!mKeyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; } - if (mData->isEmpty()) - { - lower = mData->constEnd(); - upperEnd = mData->constEnd(); - return; - } - - // get visible data range as QMap iterators - lower = mData->lowerBound(mKeyAxis.data()->range().lower); - upperEnd = mData->upperBound(mKeyAxis.data()->range().upper); - double lowerPixelBound = mKeyAxis.data()->coordToPixel(mKeyAxis.data()->range().lower); - double upperPixelBound = mKeyAxis.data()->coordToPixel(mKeyAxis.data()->range().upper); - bool isVisible = false; - // walk left from lbound to find lower bar that actually is completely outside visible pixel range: - QCPBarDataMap::const_iterator it = lower; - while (it != mData->constBegin()) - { - --it; - QRectF barBounds = getBarPolygon(it.value().key, it.value().value).boundingRect(); - if (mKeyAxis.data()->orientation() == Qt::Horizontal) - isVisible = ((!mKeyAxis.data()->rangeReversed() && barBounds.right() >= lowerPixelBound) || (mKeyAxis.data()->rangeReversed() && barBounds.left() <= lowerPixelBound)); - else // keyaxis is vertical - isVisible = ((!mKeyAxis.data()->rangeReversed() && barBounds.top() <= lowerPixelBound) || (mKeyAxis.data()->rangeReversed() && barBounds.bottom() >= lowerPixelBound)); - if (isVisible) - lower = it; - else - break; - } - // walk right from ubound to find upper bar that actually is completely outside visible pixel range: - it = upperEnd; - while (it != mData->constEnd()) - { - QRectF barBounds = getBarPolygon(upperEnd.value().key, upperEnd.value().value).boundingRect(); - if (mKeyAxis.data()->orientation() == Qt::Horizontal) - isVisible = ((!mKeyAxis.data()->rangeReversed() && barBounds.left() <= upperPixelBound) || (mKeyAxis.data()->rangeReversed() && barBounds.right() >= upperPixelBound)); - else // keyaxis is vertical - isVisible = ((!mKeyAxis.data()->rangeReversed() && barBounds.bottom() >= upperPixelBound) || (mKeyAxis.data()->rangeReversed() && barBounds.top() <= upperPixelBound)); - if (isVisible) - upperEnd = it+1; - else - break; - ++it; + if (!mKeyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; } + if (mData->isEmpty()) + { + lower = mData->constEnd(); + upperEnd = mData->constEnd(); + return; + } + + // get visible data range as QMap iterators + lower = mData->lowerBound(mKeyAxis.data()->range().lower); + upperEnd = mData->upperBound(mKeyAxis.data()->range().upper); + double lowerPixelBound = mKeyAxis.data()->coordToPixel(mKeyAxis.data()->range().lower); + double upperPixelBound = mKeyAxis.data()->coordToPixel(mKeyAxis.data()->range().upper); + bool isVisible = false; + // walk left from lbound to find lower bar that actually is completely outside visible pixel range: + QCPBarDataMap::const_iterator it = lower; + while (it != mData->constBegin()) + { + --it; + QRectF barBounds = getBarPolygon(it.value().key, it.value().value).boundingRect(); + if (mKeyAxis.data()->orientation() == Qt::Horizontal) + isVisible = ((!mKeyAxis.data()->rangeReversed() && barBounds.right() >= lowerPixelBound) || (mKeyAxis.data()->rangeReversed() && barBounds.left() <= lowerPixelBound)); + else // keyaxis is vertical + isVisible = ((!mKeyAxis.data()->rangeReversed() && barBounds.top() <= lowerPixelBound) || (mKeyAxis.data()->rangeReversed() && barBounds.bottom() >= lowerPixelBound)); + if (isVisible) + lower = it; + else + break; + } + // walk right from ubound to find upper bar that actually is completely outside visible pixel range: + it = upperEnd; + while (it != mData->constEnd()) + { + QRectF barBounds = getBarPolygon(upperEnd.value().key, upperEnd.value().value).boundingRect(); + if (mKeyAxis.data()->orientation() == Qt::Horizontal) + isVisible = ((!mKeyAxis.data()->rangeReversed() && barBounds.left() <= upperPixelBound) || (mKeyAxis.data()->rangeReversed() && barBounds.right() >= upperPixelBound)); + else // keyaxis is vertical + isVisible = ((!mKeyAxis.data()->rangeReversed() && barBounds.bottom() >= upperPixelBound) || (mKeyAxis.data()->rangeReversed() && barBounds.top() <= upperPixelBound)); + if (isVisible) + upperEnd = it+1; + else + break; + ++it; } } @@ -19376,33 +18877,33 @@ void QCPBars::getVisibleDataBounds(QCPBa */ QPolygonF QCPBars::getBarPolygon(double key, double value) const { - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPolygonF(); } - - QPolygonF result; - double lowerPixelWidth, upperPixelWidth; - getPixelWidth(key, lowerPixelWidth, upperPixelWidth); - double base = getStackedBaseValue(key, value >= 0); - double basePixel = valueAxis->coordToPixel(base); - double valuePixel = valueAxis->coordToPixel(base+value); - double keyPixel = keyAxis->coordToPixel(key); - if (mBarsGroup) - keyPixel += mBarsGroup->keyPixelOffset(this, key); - if (keyAxis->orientation() == Qt::Horizontal) - { - result << QPointF(keyPixel+lowerPixelWidth, basePixel); - result << QPointF(keyPixel+lowerPixelWidth, valuePixel); - result << QPointF(keyPixel+upperPixelWidth, valuePixel); - result << QPointF(keyPixel+upperPixelWidth, basePixel); - } else - { - result << QPointF(basePixel, keyPixel+lowerPixelWidth); - result << QPointF(valuePixel, keyPixel+lowerPixelWidth); - result << QPointF(valuePixel, keyPixel+upperPixelWidth); - result << QPointF(basePixel, keyPixel+upperPixelWidth); - } - return result; + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPolygonF(); } + + QPolygonF result; + double lowerPixelWidth, upperPixelWidth; + getPixelWidth(key, lowerPixelWidth, upperPixelWidth); + double base = getStackedBaseValue(key, value >= 0); + double basePixel = valueAxis->coordToPixel(base); + double valuePixel = valueAxis->coordToPixel(base+value); + double keyPixel = keyAxis->coordToPixel(key); + if (mBarsGroup) + keyPixel += mBarsGroup->keyPixelOffset(this, key); + if (keyAxis->orientation() == Qt::Horizontal) + { + result << QPointF(keyPixel+lowerPixelWidth, basePixel); + result << QPointF(keyPixel+lowerPixelWidth, valuePixel); + result << QPointF(keyPixel+upperPixelWidth, valuePixel); + result << QPointF(keyPixel+upperPixelWidth, basePixel); + } else + { + result << QPointF(basePixel, keyPixel+lowerPixelWidth); + result << QPointF(valuePixel, keyPixel+lowerPixelWidth); + result << QPointF(valuePixel, keyPixel+upperPixelWidth); + result << QPointF(basePixel, keyPixel+upperPixelWidth); + } + return result; } /*! \internal @@ -19416,44 +18917,44 @@ QPolygonF QCPBars::getBarPolygon(double */ void QCPBars::getPixelWidth(double key, double &lower, double &upper) const { - switch (mWidthType) + switch (mWidthType) { case wtAbsolute: - { + { upper = mWidth*0.5; lower = -upper; if (mKeyAxis && (mKeyAxis.data()->rangeReversed() ^ (mKeyAxis.data()->orientation() == Qt::Vertical))) - qSwap(lower, upper); - break; - } + qSwap(lower, upper); + break; + } case wtAxisRectRatio: - { + { if (mKeyAxis && mKeyAxis.data()->axisRect()) - { + { if (mKeyAxis.data()->orientation() == Qt::Horizontal) - upper = mKeyAxis.data()->axisRect()->width()*mWidth*0.5; + upper = mKeyAxis.data()->axisRect()->width()*mWidth*0.5; else - upper = mKeyAxis.data()->axisRect()->height()*mWidth*0.5; + upper = mKeyAxis.data()->axisRect()->height()*mWidth*0.5; lower = -upper; if (mKeyAxis && (mKeyAxis.data()->rangeReversed() ^ (mKeyAxis.data()->orientation() == Qt::Vertical))) - qSwap(lower, upper); - } else - qDebug() << Q_FUNC_INFO << "No key axis or axis rect defined"; - break; - } + qSwap(lower, upper); + } else + qDebug() << Q_FUNC_INFO << "No key axis or axis rect defined"; + break; + } case wtPlotCoords: - { + { if (mKeyAxis) - { + { double keyPixel = mKeyAxis.data()->coordToPixel(key); upper = mKeyAxis.data()->coordToPixel(key+mWidth*0.5)-keyPixel; lower = mKeyAxis.data()->coordToPixel(key-mWidth*0.5)-keyPixel; // no need to qSwap(lower, higher) when range reversed, because higher/lower are gained by // coordinate transform which includes range direction - } else - qDebug() << Q_FUNC_INFO << "No key axis defined"; - break; - } + } else + qDebug() << Q_FUNC_INFO << "No key axis defined"; + break; + } } } @@ -19468,26 +18969,26 @@ void QCPBars::getPixelWidth(double key, */ double QCPBars::getStackedBaseValue(double key, bool positive) const { - if (mBarBelow) - { - double max = 0; // don't use mBaseValue here because only base value of bottom-most bar has meaning in a bar stack - // find bars of mBarBelow that are approximately at key and find largest one: - double epsilon = qAbs(key)*1e-6; // should be safe even when changed to use float at some point - if (key == 0) - epsilon = 1e-6; - QCPBarDataMap::const_iterator it = mBarBelow.data()->mData->lowerBound(key-epsilon); - QCPBarDataMap::const_iterator itEnd = mBarBelow.data()->mData->upperBound(key+epsilon); - while (it != itEnd) - { - if ((positive && it.value().value > max) || - (!positive && it.value().value < max)) - max = it.value().value; - ++it; - } - // recurse down the bar-stack to find the total height: - return max + mBarBelow.data()->getStackedBaseValue(key, positive); - } else - return mBaseValue; + if (mBarBelow) + { + double max = 0; // don't use mBaseValue here because only base value of bottom-most bar has meaning in a bar stack + // find bars of mBarBelow that are approximately at key and find largest one: + double epsilon = qAbs(key)*1e-6; // should be safe even when changed to use float at some point + if (key == 0) + epsilon = 1e-6; + QCPBarDataMap::const_iterator it = mBarBelow.data()->mData->lowerBound(key-epsilon); + QCPBarDataMap::const_iterator itEnd = mBarBelow.data()->mData->upperBound(key+epsilon); + while (it != itEnd) + { + if ((positive && it.value().value > max) || + (!positive && it.value().value < max)) + max = it.value().value; + ++it; + } + // recurse down the bar-stack to find the total height: + return max + mBarBelow.data()->getStackedBaseValue(key, positive); + } else + return mBaseValue; } /*! \internal @@ -19500,115 +19001,115 @@ double QCPBars::getStackedBaseValue(doub */ void QCPBars::connectBars(QCPBars *lower, QCPBars *upper) { - if (!lower && !upper) return; - - if (!lower) // disconnect upper at bottom - { - // disconnect old bar below upper: - if (upper->mBarBelow && upper->mBarBelow.data()->mBarAbove.data() == upper) - upper->mBarBelow.data()->mBarAbove = 0; - upper->mBarBelow = 0; + if (!lower && !upper) return; + + if (!lower) // disconnect upper at bottom + { + // disconnect old bar below upper: + if (upper->mBarBelow && upper->mBarBelow.data()->mBarAbove.data() == upper) + upper->mBarBelow.data()->mBarAbove = 0; + upper->mBarBelow = 0; } else if (!upper) // disconnect lower at top { - // disconnect old bar above lower: - if (lower->mBarAbove && lower->mBarAbove.data()->mBarBelow.data() == lower) - lower->mBarAbove.data()->mBarBelow = 0; - lower->mBarAbove = 0; + // disconnect old bar above lower: + if (lower->mBarAbove && lower->mBarAbove.data()->mBarBelow.data() == lower) + lower->mBarAbove.data()->mBarBelow = 0; + lower->mBarAbove = 0; } else // connect lower and upper { - // disconnect old bar above lower: - if (lower->mBarAbove && lower->mBarAbove.data()->mBarBelow.data() == lower) - lower->mBarAbove.data()->mBarBelow = 0; - // disconnect old bar below upper: - if (upper->mBarBelow && upper->mBarBelow.data()->mBarAbove.data() == upper) - upper->mBarBelow.data()->mBarAbove = 0; - lower->mBarAbove = upper; - upper->mBarBelow = lower; + // disconnect old bar above lower: + if (lower->mBarAbove && lower->mBarAbove.data()->mBarBelow.data() == lower) + lower->mBarAbove.data()->mBarBelow = 0; + // disconnect old bar below upper: + if (upper->mBarBelow && upper->mBarBelow.data()->mBarAbove.data() == upper) + upper->mBarBelow.data()->mBarAbove = 0; + lower->mBarAbove = upper; + upper->mBarBelow = lower; } } /* inherits documentation from base class */ QCPRange QCPBars::getKeyRange(bool &foundRange, SignDomain inSignDomain) const { - QCPRange range; - bool haveLower = false; - bool haveUpper = false; - - double current; - QCPBarDataMap::const_iterator it = mData->constBegin(); - while (it != mData->constEnd()) - { - current = it.value().key; - if (inSignDomain == sdBoth || (inSignDomain == sdNegative && current < 0) || (inSignDomain == sdPositive && current > 0)) - { - if (current < range.lower || !haveLower) - { - range.lower = current; - haveLower = true; - } - if (current > range.upper || !haveUpper) - { - range.upper = current; - haveUpper = true; - } - } - ++it; - } - // determine exact range of bars by including bar width and barsgroup offset: - if (haveLower && mKeyAxis) - { - double lowerPixelWidth, upperPixelWidth, keyPixel; - getPixelWidth(range.lower, lowerPixelWidth, upperPixelWidth); - keyPixel = mKeyAxis.data()->coordToPixel(range.lower) + lowerPixelWidth; - if (mBarsGroup) - keyPixel += mBarsGroup->keyPixelOffset(this, range.lower); - range.lower = mKeyAxis.data()->pixelToCoord(keyPixel); - } - if (haveUpper && mKeyAxis) - { - double lowerPixelWidth, upperPixelWidth, keyPixel; - getPixelWidth(range.upper, lowerPixelWidth, upperPixelWidth); - keyPixel = mKeyAxis.data()->coordToPixel(range.upper) + upperPixelWidth; - if (mBarsGroup) - keyPixel += mBarsGroup->keyPixelOffset(this, range.upper); - range.upper = mKeyAxis.data()->pixelToCoord(keyPixel); - } - foundRange = haveLower && haveUpper; - return range; + QCPRange range; + bool haveLower = false; + bool haveUpper = false; + + double current; + QCPBarDataMap::const_iterator it = mData->constBegin(); + while (it != mData->constEnd()) + { + current = it.value().key; + if (inSignDomain == sdBoth || (inSignDomain == sdNegative && current < 0) || (inSignDomain == sdPositive && current > 0)) + { + if (current < range.lower || !haveLower) + { + range.lower = current; + haveLower = true; + } + if (current > range.upper || !haveUpper) + { + range.upper = current; + haveUpper = true; + } + } + ++it; + } + // determine exact range of bars by including bar width and barsgroup offset: + if (haveLower && mKeyAxis) + { + double lowerPixelWidth, upperPixelWidth, keyPixel; + getPixelWidth(range.lower, lowerPixelWidth, upperPixelWidth); + keyPixel = mKeyAxis.data()->coordToPixel(range.lower) + lowerPixelWidth; + if (mBarsGroup) + keyPixel += mBarsGroup->keyPixelOffset(this, range.lower); + range.lower = mKeyAxis.data()->pixelToCoord(keyPixel); + } + if (haveUpper && mKeyAxis) + { + double lowerPixelWidth, upperPixelWidth, keyPixel; + getPixelWidth(range.upper, lowerPixelWidth, upperPixelWidth); + keyPixel = mKeyAxis.data()->coordToPixel(range.upper) + upperPixelWidth; + if (mBarsGroup) + keyPixel += mBarsGroup->keyPixelOffset(this, range.upper); + range.upper = mKeyAxis.data()->pixelToCoord(keyPixel); + } + foundRange = haveLower && haveUpper; + return range; } /* inherits documentation from base class */ QCPRange QCPBars::getValueRange(bool &foundRange, SignDomain inSignDomain) const { - QCPRange range; - range.lower = mBaseValue; - range.upper = mBaseValue; - bool haveLower = true; // set to true, because baseValue should always be visible in bar charts - bool haveUpper = true; // set to true, because baseValue should always be visible in bar charts - double current; - - QCPBarDataMap::const_iterator it = mData->constBegin(); - while (it != mData->constEnd()) - { - current = it.value().value + getStackedBaseValue(it.value().key, it.value().value >= 0); - if (inSignDomain == sdBoth || (inSignDomain == sdNegative && current < 0) || (inSignDomain == sdPositive && current > 0)) - { - if (current < range.lower || !haveLower) - { - range.lower = current; - haveLower = true; - } - if (current > range.upper || !haveUpper) - { - range.upper = current; - haveUpper = true; - } - } - ++it; - } - - foundRange = true; // return true because bar charts always have the 0-line visible - return range; + QCPRange range; + range.lower = mBaseValue; + range.upper = mBaseValue; + bool haveLower = true; // set to true, because baseValue should always be visible in bar charts + bool haveUpper = true; // set to true, because baseValue should always be visible in bar charts + double current; + + QCPBarDataMap::const_iterator it = mData->constBegin(); + while (it != mData->constEnd()) + { + current = it.value().value + getStackedBaseValue(it.value().key, it.value().value >= 0); + if (inSignDomain == sdBoth || (inSignDomain == sdNegative && current < 0) || (inSignDomain == sdPositive && current > 0)) + { + if (current < range.lower || !haveLower) + { + range.lower = current; + haveLower = true; + } + if (current > range.upper || !haveUpper) + { + range.upper = current; + haveUpper = true; + } + } + ++it; + } + + foundRange = true; // return true because bar charts always have the 0-line visible + return range; } @@ -19679,25 +19180,25 @@ QCPRange QCPBars::getValueRange(bool &fo QCustomPlot then takes ownership of the statistical box. */ QCPStatisticalBox::QCPStatisticalBox(QCPAxis *keyAxis, QCPAxis *valueAxis) : - QCPAbstractPlottable(keyAxis, valueAxis), - mKey(0), - mMinimum(0), - mLowerQuartile(0), - mMedian(0), - mUpperQuartile(0), - mMaximum(0) -{ - setOutlierStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, Qt::blue, 6)); - setWhiskerWidth(0.2); - setWidth(0.5); - - setPen(QPen(Qt::black)); - setSelectedPen(QPen(Qt::blue, 2.5)); - setMedianPen(QPen(Qt::black, 3, Qt::SolidLine, Qt::FlatCap)); - setWhiskerPen(QPen(Qt::black, 0, Qt::DashLine, Qt::FlatCap)); - setWhiskerBarPen(QPen(Qt::black)); - setBrush(Qt::NoBrush); - setSelectedBrush(Qt::NoBrush); + QCPAbstractPlottable(keyAxis, valueAxis), + mKey(0), + mMinimum(0), + mLowerQuartile(0), + mMedian(0), + mUpperQuartile(0), + mMaximum(0) +{ + setOutlierStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, Qt::blue, 6)); + setWhiskerWidth(0.2); + setWidth(0.5); + + setPen(QPen(Qt::black)); + setSelectedPen(QPen(Qt::blue, 2.5)); + setMedianPen(QPen(Qt::black, 3, Qt::SolidLine, Qt::FlatCap)); + setWhiskerPen(QPen(Qt::black, 0, Qt::DashLine, Qt::FlatCap)); + setWhiskerBarPen(QPen(Qt::black)); + setBrush(Qt::NoBrush); + setSelectedBrush(Qt::NoBrush); } /*! @@ -19705,7 +19206,7 @@ QCPStatisticalBox::QCPStatisticalBox(QCP */ void QCPStatisticalBox::setKey(double key) { - mKey = key; + mKey = key; } /*! @@ -19716,7 +19217,7 @@ void QCPStatisticalBox::setKey(double ke */ void QCPStatisticalBox::setMinimum(double value) { - mMinimum = value; + mMinimum = value; } /*! @@ -19728,7 +19229,7 @@ void QCPStatisticalBox::setMinimum(doubl */ void QCPStatisticalBox::setLowerQuartile(double value) { - mLowerQuartile = value; + mLowerQuartile = value; } /*! @@ -19740,7 +19241,7 @@ void QCPStatisticalBox::setLowerQuartile */ void QCPStatisticalBox::setMedian(double value) { - mMedian = value; + mMedian = value; } /*! @@ -19752,7 +19253,7 @@ void QCPStatisticalBox::setMedian(double */ void QCPStatisticalBox::setUpperQuartile(double value) { - mUpperQuartile = value; + mUpperQuartile = value; } /*! @@ -19763,7 +19264,7 @@ void QCPStatisticalBox::setUpperQuartile */ void QCPStatisticalBox::setMaximum(double value) { - mMaximum = value; + mMaximum = value; } /*! @@ -19775,7 +19276,7 @@ void QCPStatisticalBox::setMaximum(doubl */ void QCPStatisticalBox::setOutliers(const QVector &values) { - mOutliers = values; + mOutliers = values; } /*! @@ -19785,12 +19286,12 @@ void QCPStatisticalBox::setOutliers(cons */ void QCPStatisticalBox::setData(double key, double minimum, double lowerQuartile, double median, double upperQuartile, double maximum) { - setKey(key); - setMinimum(minimum); - setLowerQuartile(lowerQuartile); - setMedian(median); - setUpperQuartile(upperQuartile); - setMaximum(maximum); + setKey(key); + setMinimum(minimum); + setLowerQuartile(lowerQuartile); + setMedian(median); + setUpperQuartile(upperQuartile); + setMaximum(maximum); } /*! @@ -19800,7 +19301,7 @@ void QCPStatisticalBox::setData(double k */ void QCPStatisticalBox::setWidth(double width) { - mWidth = width; + mWidth = width; } /*! @@ -19810,7 +19311,7 @@ void QCPStatisticalBox::setWidth(double */ void QCPStatisticalBox::setWhiskerWidth(double width) { - mWhiskerWidth = width; + mWhiskerWidth = width; } /*! @@ -19823,7 +19324,7 @@ void QCPStatisticalBox::setWhiskerWidth( */ void QCPStatisticalBox::setWhiskerPen(const QPen &pen) { - mWhiskerPen = pen; + mWhiskerPen = pen; } /*! @@ -19834,7 +19335,7 @@ void QCPStatisticalBox::setWhiskerPen(co */ void QCPStatisticalBox::setWhiskerBarPen(const QPen &pen) { - mWhiskerBarPen = pen; + mWhiskerBarPen = pen; } /*! @@ -19842,7 +19343,7 @@ void QCPStatisticalBox::setWhiskerBarPen */ void QCPStatisticalBox::setMedianPen(const QPen &pen) { - mMedianPen = pen; + mMedianPen = pen; } /*! @@ -19852,84 +19353,84 @@ void QCPStatisticalBox::setMedianPen(con */ void QCPStatisticalBox::setOutlierStyle(const QCPScatterStyle &style) { - mOutlierStyle = style; + mOutlierStyle = style; } /* inherits documentation from base class */ void QCPStatisticalBox::clearData() { - setOutliers(QVector()); - setKey(0); - setMinimum(0); - setLowerQuartile(0); - setMedian(0); - setUpperQuartile(0); - setMaximum(0); + setOutliers(QVector()); + setKey(0); + setMinimum(0); + setLowerQuartile(0); + setMedian(0); + setUpperQuartile(0); + setMaximum(0); } /* inherits documentation from base class */ double QCPStatisticalBox::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - Q_UNUSED(details) - if (onlySelectable && !mSelectable) + Q_UNUSED(details) + if (onlySelectable && !mSelectable) + return -1; + if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; } + + if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint())) + { + double posKey, posValue; + pixelsToCoords(pos, posKey, posValue); + // quartile box: + QCPRange keyRange(mKey-mWidth*0.5, mKey+mWidth*0.5); + QCPRange valueRange(mLowerQuartile, mUpperQuartile); + if (keyRange.contains(posKey) && valueRange.contains(posValue)) + return mParentPlot->selectionTolerance()*0.99; + + // min/max whiskers: + if (QCPRange(mMinimum, mMaximum).contains(posValue)) + return qAbs(mKeyAxis.data()->coordToPixel(mKey)-mKeyAxis.data()->coordToPixel(posKey)); + } return -1; - if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; } - - if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint())) - { - double posKey, posValue; - pixelsToCoords(pos, posKey, posValue); - // quartile box: - QCPRange keyRange(mKey-mWidth*0.5, mKey+mWidth*0.5); - QCPRange valueRange(mLowerQuartile, mUpperQuartile); - if (keyRange.contains(posKey) && valueRange.contains(posValue)) - return mParentPlot->selectionTolerance()*0.99; - - // min/max whiskers: - if (QCPRange(mMinimum, mMaximum).contains(posValue)) - return qAbs(mKeyAxis.data()->coordToPixel(mKey)-mKeyAxis.data()->coordToPixel(posKey)); - } - return -1; } /* inherits documentation from base class */ void QCPStatisticalBox::draw(QCPPainter *painter) { - if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - - // check data validity if flag set: + if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + + // check data validity if flag set: #ifdef QCUSTOMPLOT_CHECK_DATA - if (QCP::isInvalidData(mKey, mMedian) || - QCP::isInvalidData(mLowerQuartile, mUpperQuartile) || - QCP::isInvalidData(mMinimum, mMaximum)) - qDebug() << Q_FUNC_INFO << "Data point at" << mKey << "of drawn range has invalid data." << "Plottable name:" << name(); - for (int i=0; isave(); - painter->setClipRect(quartileBox, Qt::IntersectClip); - drawMedian(painter); - painter->restore(); - - drawWhiskers(painter); - drawOutliers(painter); + + QRectF quartileBox; + drawQuartileBox(painter, &quartileBox); + + painter->save(); + painter->setClipRect(quartileBox, Qt::IntersectClip); + drawMedian(painter); + painter->restore(); + + drawWhiskers(painter); + drawOutliers(painter); } /* inherits documentation from base class */ void QCPStatisticalBox::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const { - // draw filled rect: - applyDefaultAntialiasingHint(painter); - painter->setPen(mPen); - painter->setBrush(mBrush); - QRectF r = QRectF(0, 0, rect.width()*0.67, rect.height()*0.67); - r.moveCenter(rect.center()); - painter->drawRect(r); + // draw filled rect: + applyDefaultAntialiasingHint(painter); + painter->setPen(mPen); + painter->setBrush(mBrush); + QRectF r = QRectF(0, 0, rect.width()*0.67, rect.height()*0.67); + r.moveCenter(rect.center()); + painter->drawRect(r); } /*! \internal @@ -19940,15 +19441,15 @@ void QCPStatisticalBox::drawLegendIcon(Q */ void QCPStatisticalBox::drawQuartileBox(QCPPainter *painter, QRectF *quartileBox) const { - QRectF box; - box.setTopLeft(coordsToPixels(mKey-mWidth*0.5, mUpperQuartile)); - box.setBottomRight(coordsToPixels(mKey+mWidth*0.5, mLowerQuartile)); - applyDefaultAntialiasingHint(painter); - painter->setPen(mainPen()); - painter->setBrush(mainBrush()); - painter->drawRect(box); - if (quartileBox) - *quartileBox = box; + QRectF box; + box.setTopLeft(coordsToPixels(mKey-mWidth*0.5, mUpperQuartile)); + box.setBottomRight(coordsToPixels(mKey+mWidth*0.5, mLowerQuartile)); + applyDefaultAntialiasingHint(painter); + painter->setPen(mainPen()); + painter->setBrush(mainBrush()); + painter->drawRect(box); + if (quartileBox) + *quartileBox = box; } /*! \internal @@ -19957,12 +19458,12 @@ void QCPStatisticalBox::drawQuartileBox( */ void QCPStatisticalBox::drawMedian(QCPPainter *painter) const { - QLineF medianLine; - medianLine.setP1(coordsToPixels(mKey-mWidth*0.5, mMedian)); - medianLine.setP2(coordsToPixels(mKey+mWidth*0.5, mMedian)); - applyDefaultAntialiasingHint(painter); - painter->setPen(mMedianPen); - painter->drawLine(medianLine); + QLineF medianLine; + medianLine.setP1(coordsToPixels(mKey-mWidth*0.5, mMedian)); + medianLine.setP2(coordsToPixels(mKey+mWidth*0.5, mMedian)); + applyDefaultAntialiasingHint(painter); + painter->setPen(mMedianPen); + painter->drawLine(medianLine); } /*! \internal @@ -19971,18 +19472,18 @@ void QCPStatisticalBox::drawMedian(QCPPa */ void QCPStatisticalBox::drawWhiskers(QCPPainter *painter) const { - QLineF backboneMin, backboneMax, barMin, barMax; - backboneMax.setPoints(coordsToPixels(mKey, mUpperQuartile), coordsToPixels(mKey, mMaximum)); - backboneMin.setPoints(coordsToPixels(mKey, mLowerQuartile), coordsToPixels(mKey, mMinimum)); - barMax.setPoints(coordsToPixels(mKey-mWhiskerWidth*0.5, mMaximum), coordsToPixels(mKey+mWhiskerWidth*0.5, mMaximum)); - barMin.setPoints(coordsToPixels(mKey-mWhiskerWidth*0.5, mMinimum), coordsToPixels(mKey+mWhiskerWidth*0.5, mMinimum)); - applyErrorBarsAntialiasingHint(painter); - painter->setPen(mWhiskerPen); - painter->drawLine(backboneMin); - painter->drawLine(backboneMax); - painter->setPen(mWhiskerBarPen); - painter->drawLine(barMin); - painter->drawLine(barMax); + QLineF backboneMin, backboneMax, barMin, barMax; + backboneMax.setPoints(coordsToPixels(mKey, mUpperQuartile), coordsToPixels(mKey, mMaximum)); + backboneMin.setPoints(coordsToPixels(mKey, mLowerQuartile), coordsToPixels(mKey, mMinimum)); + barMax.setPoints(coordsToPixels(mKey-mWhiskerWidth*0.5, mMaximum), coordsToPixels(mKey+mWhiskerWidth*0.5, mMaximum)); + barMin.setPoints(coordsToPixels(mKey-mWhiskerWidth*0.5, mMinimum), coordsToPixels(mKey+mWhiskerWidth*0.5, mMinimum)); + applyErrorBarsAntialiasingHint(painter); + painter->setPen(mWhiskerPen); + painter->drawLine(backboneMin); + painter->drawLine(backboneMax); + painter->setPen(mWhiskerBarPen); + painter->drawLine(barMin); + painter->drawLine(barMax); } /*! \internal @@ -19991,85 +19492,85 @@ void QCPStatisticalBox::drawWhiskers(QCP */ void QCPStatisticalBox::drawOutliers(QCPPainter *painter) const { - applyScattersAntialiasingHint(painter); - mOutlierStyle.applyTo(painter, mPen); - for (int i=0; i 0) - return QCPRange(mKey-mWidth*0.5, mKey+mWidth*0.5); - else if (mKey > 0) - return QCPRange(mKey, mKey+mWidth*0.5); - else - { - foundRange = false; - return QCPRange(); - } - } - foundRange = false; - return QCPRange(); + if (mKey-mWidth*0.5 > 0) + return QCPRange(mKey-mWidth*0.5, mKey+mWidth*0.5); + else if (mKey > 0) + return QCPRange(mKey, mKey+mWidth*0.5); + else + { + foundRange = false; + return QCPRange(); + } + } + foundRange = false; + return QCPRange(); } /* inherits documentation from base class */ QCPRange QCPStatisticalBox::getValueRange(bool &foundRange, SignDomain inSignDomain) const { - QVector values; // values that must be considered (i.e. all outliers and the five box-parameters) - values.reserve(mOutliers.size() + 5); - values << mMaximum << mUpperQuartile << mMedian << mLowerQuartile << mMinimum; - values << mOutliers; - // go through values and find the ones in legal range: - bool haveUpper = false; - bool haveLower = false; - double upper = 0; - double lower = 0; - for (int i=0; i 0) || - (inSignDomain == sdBoth)) - { - if (values.at(i) > upper || !haveUpper) - { - upper = values.at(i); - haveUpper = true; - } - if (values.at(i) < lower || !haveLower) - { - lower = values.at(i); - haveLower = true; - } - } - } - // return the bounds if we found some sensible values: - if (haveLower && haveUpper) - { - foundRange = true; - return QCPRange(lower, upper); + QVector values; // values that must be considered (i.e. all outliers and the five box-parameters) + values.reserve(mOutliers.size() + 5); + values << mMaximum << mUpperQuartile << mMedian << mLowerQuartile << mMinimum; + values << mOutliers; + // go through values and find the ones in legal range: + bool haveUpper = false; + bool haveLower = false; + double upper = 0; + double lower = 0; + for (int i=0; i 0) || + (inSignDomain == sdBoth)) + { + if (values.at(i) > upper || !haveUpper) + { + upper = values.at(i); + haveUpper = true; + } + if (values.at(i) < lower || !haveLower) + { + lower = values.at(i); + haveLower = true; + } + } + } + // return the bounds if we found some sensible values: + if (haveLower && haveUpper) + { + foundRange = true; + return QCPRange(lower, upper); } else // might happen if all values are in other sign domain { - foundRange = false; - return QCPRange(); + foundRange = false; + return QCPRange(); } } @@ -20124,35 +19625,35 @@ QCPRange QCPStatisticalBox::getValueRang \see setSize, setKeySize, setValueSize, setRange, setKeyRange, setValueRange */ QCPColorMapData::QCPColorMapData(int keySize, int valueSize, const QCPRange &keyRange, const QCPRange &valueRange) : - mKeySize(0), - mValueSize(0), - mKeyRange(keyRange), - mValueRange(valueRange), - mIsEmpty(true), - mData(0), - mDataModified(true) -{ - setSize(keySize, valueSize); - fill(0); + mKeySize(0), + mValueSize(0), + mKeyRange(keyRange), + mValueRange(valueRange), + mIsEmpty(true), + mData(0), + mDataModified(true) +{ + setSize(keySize, valueSize); + fill(0); } QCPColorMapData::~QCPColorMapData() { - if (mData) - delete[] mData; + if (mData) + delete[] mData; } /*! Constructs a new QCPColorMapData instance copying the data and range of \a other. */ QCPColorMapData::QCPColorMapData(const QCPColorMapData &other) : - mKeySize(0), - mValueSize(0), - mIsEmpty(true), - mData(0), - mDataModified(true) -{ - *this = other; + mKeySize(0), + mValueSize(0), + mIsEmpty(true), + mData(0), + mDataModified(true) +{ + *this = other; } /*! @@ -20160,38 +19661,38 @@ QCPColorMapData::QCPColorMapData(const Q */ QCPColorMapData &QCPColorMapData::operator=(const QCPColorMapData &other) { - if (&other != this) - { - const int keySize = other.keySize(); - const int valueSize = other.valueSize(); - setSize(keySize, valueSize); - setRange(other.keyRange(), other.valueRange()); - if (!mIsEmpty) - memcpy(mData, other.mData, sizeof(mData[0])*keySize*valueSize); - mDataBounds = other.mDataBounds; - mDataModified = true; - } - return *this; + if (&other != this) + { + const int keySize = other.keySize(); + const int valueSize = other.valueSize(); + setSize(keySize, valueSize); + setRange(other.keyRange(), other.valueRange()); + if (!mIsEmpty) + memcpy(mData, other.mData, sizeof(mData[0])*keySize*valueSize); + mDataBounds = other.mDataBounds; + mDataModified = true; + } + return *this; } /* undocumented getter */ double QCPColorMapData::data(double key, double value) { - int keyCell = (key-mKeyRange.lower)/(mKeyRange.upper-mKeyRange.lower)*(mKeySize-1)+0.5; - int valueCell = (value-mValueRange.lower)/(mValueRange.upper-mValueRange.lower)*(mValueSize-1)+0.5; - if (keyCell >= 0 && keyCell < mKeySize && valueCell >= 0 && valueCell < mValueSize) - return mData[valueCell*mKeySize + keyCell]; - else - return 0; + int keyCell = (key-mKeyRange.lower)/(mKeyRange.upper-mKeyRange.lower)*(mKeySize-1)+0.5; + int valueCell = (value-mValueRange.lower)/(mValueRange.upper-mValueRange.lower)*(mValueSize-1)+0.5; + if (keyCell >= 0 && keyCell < mKeySize && valueCell >= 0 && valueCell < mValueSize) + return mData[valueCell*mKeySize + keyCell]; + else + return 0; } /* undocumented getter */ double QCPColorMapData::cell(int keyIndex, int valueIndex) { - if (keyIndex >= 0 && keyIndex < mKeySize && valueIndex >= 0 && valueIndex < mValueSize) - return mData[valueIndex*mKeySize + keyIndex]; - else - return 0; + if (keyIndex >= 0 && keyIndex < mKeySize && valueIndex >= 0 && valueIndex < mValueSize) + return mData[valueIndex*mKeySize + keyIndex]; + else + return 0; } /*! @@ -20208,29 +19709,29 @@ double QCPColorMapData::cell(int keyInde */ void QCPColorMapData::setSize(int keySize, int valueSize) { - if (keySize != mKeySize || valueSize != mValueSize) - { - mKeySize = keySize; - mValueSize = valueSize; - if (mData) - delete[] mData; - mIsEmpty = mKeySize == 0 || mValueSize == 0; - if (!mIsEmpty) + if (keySize != mKeySize || valueSize != mValueSize) + { + mKeySize = keySize; + mValueSize = valueSize; + if (mData) + delete[] mData; + mIsEmpty = mKeySize == 0 || mValueSize == 0; + if (!mIsEmpty) { #ifdef __EXCEPTIONS - try { // 2D arrays get memory intensive fast. So if the allocation fails, at least output debug message + try { // 2D arrays get memory intensive fast. So if the allocation fails, at least output debug message #endif - mData = new double[mKeySize*mValueSize]; + mData = new double[mKeySize*mValueSize]; #ifdef __EXCEPTIONS - } catch (...) { mData = 0; } + } catch (...) { mData = 0; } #endif - if (mData) - fill(0); - else - qDebug() << Q_FUNC_INFO << "out of memory for data dimensions "<< mKeySize << "*" << mValueSize; + if (mData) + fill(0); + else + qDebug() << Q_FUNC_INFO << "out of memory for data dimensions "<< mKeySize << "*" << mValueSize; } else - mData = 0; - mDataModified = true; + mData = 0; + mDataModified = true; } } @@ -20246,7 +19747,7 @@ void QCPColorMapData::setSize(int keySiz */ void QCPColorMapData::setKeySize(int keySize) { - setSize(keySize, mValueSize); + setSize(keySize, mValueSize); } /*! @@ -20261,7 +19762,7 @@ void QCPColorMapData::setKeySize(int key */ void QCPColorMapData::setValueSize(int valueSize) { - setSize(mKeySize, valueSize); + setSize(mKeySize, valueSize); } /*! @@ -20276,8 +19777,8 @@ void QCPColorMapData::setValueSize(int v */ void QCPColorMapData::setRange(const QCPRange &keyRange, const QCPRange &valueRange) { - setKeyRange(keyRange); - setValueRange(valueRange); + setKeyRange(keyRange); + setValueRange(valueRange); } /*! @@ -20292,7 +19793,7 @@ void QCPColorMapData::setRange(const QCP */ void QCPColorMapData::setKeyRange(const QCPRange &keyRange) { - mKeyRange = keyRange; + mKeyRange = keyRange; } /*! @@ -20307,7 +19808,7 @@ void QCPColorMapData::setKeyRange(const */ void QCPColorMapData::setValueRange(const QCPRange &valueRange) { - mValueRange = valueRange; + mValueRange = valueRange; } /*! @@ -20318,16 +19819,16 @@ void QCPColorMapData::setValueRange(cons */ void QCPColorMapData::setData(double key, double value, double z) { - int keyCell = (key-mKeyRange.lower)/(mKeyRange.upper-mKeyRange.lower)*(mKeySize-1)+0.5; - int valueCell = (value-mValueRange.lower)/(mValueRange.upper-mValueRange.lower)*(mValueSize-1)+0.5; - if (keyCell >= 0 && keyCell < mKeySize && valueCell >= 0 && valueCell < mValueSize) - { - mData[valueCell*mKeySize + keyCell] = z; - if (z < mDataBounds.lower) - mDataBounds.lower = z; - if (z > mDataBounds.upper) - mDataBounds.upper = z; - mDataModified = true; + int keyCell = (key-mKeyRange.lower)/(mKeyRange.upper-mKeyRange.lower)*(mKeySize-1)+0.5; + int valueCell = (value-mValueRange.lower)/(mValueRange.upper-mValueRange.lower)*(mValueSize-1)+0.5; + if (keyCell >= 0 && keyCell < mKeySize && valueCell >= 0 && valueCell < mValueSize) + { + mData[valueCell*mKeySize + keyCell] = z; + if (z < mDataBounds.lower) + mDataBounds.lower = z; + if (z > mDataBounds.upper) + mDataBounds.upper = z; + mDataModified = true; } } @@ -20344,14 +19845,14 @@ void QCPColorMapData::setData(double key */ void QCPColorMapData::setCell(int keyIndex, int valueIndex, double z) { - if (keyIndex >= 0 && keyIndex < mKeySize && valueIndex >= 0 && valueIndex < mValueSize) - { - mData[valueIndex*mKeySize + keyIndex] = z; - if (z < mDataBounds.lower) - mDataBounds.lower = z; - if (z > mDataBounds.upper) - mDataBounds.upper = z; - mDataModified = true; + if (keyIndex >= 0 && keyIndex < mKeySize && valueIndex >= 0 && valueIndex < mValueSize) + { + mData[valueIndex*mKeySize + keyIndex] = z; + if (z < mDataBounds.lower) + mDataBounds.lower = z; + if (z > mDataBounds.upper) + mDataBounds.upper = z; + mDataModified = true; } } @@ -20370,20 +19871,20 @@ void QCPColorMapData::setCell(int keyInd */ void QCPColorMapData::recalculateDataBounds() { - if (mKeySize > 0 && mValueSize > 0) - { - double minHeight = mData[0]; - double maxHeight = mData[0]; - const int dataCount = mValueSize*mKeySize; - for (int i=0; i maxHeight) - maxHeight = mData[i]; - if (mData[i] < minHeight) - minHeight = mData[i]; - } - mDataBounds.lower = minHeight; - mDataBounds.upper = maxHeight; + if (mKeySize > 0 && mValueSize > 0) + { + double minHeight = mData[0]; + double maxHeight = mData[0]; + const int dataCount = mValueSize*mKeySize; + for (int i=0; i maxHeight) + maxHeight = mData[i]; + if (mData[i] < minHeight) + minHeight = mData[i]; + } + mDataBounds.lower = minHeight; + mDataBounds.upper = maxHeight; } } @@ -20394,7 +19895,7 @@ void QCPColorMapData::recalculateDataBou */ void QCPColorMapData::clear() { - setSize(0, 0); + setSize(0, 0); } /*! @@ -20402,10 +19903,10 @@ void QCPColorMapData::clear() */ void QCPColorMapData::fill(double z) { - const int dataCount = mValueSize*mKeySize; - for (int i=0; i(data); - return; - } - if (copy) - { - *mMapData = *data; - } else - { - delete mMapData; - mMapData = data; - } - mMapImageInvalidated = true; + if (mMapData == data) + { + qDebug() << Q_FUNC_INFO << "The data pointer is already in (and owned by) this plottable" << reinterpret_cast(data); + return; + } + if (copy) + { + *mMapData = *data; + } else + { + delete mMapData; + mMapData = data; + } + mMapImageInvalidated = true; } /*! @@ -20616,15 +20117,15 @@ void QCPColorMap::setData(QCPColorMapDat */ void QCPColorMap::setDataRange(const QCPRange &dataRange) { - if (!QCPRange::validRange(dataRange)) return; - if (mDataRange.lower != dataRange.lower || mDataRange.upper != dataRange.upper) - { - if (mDataScaleType == QCPAxis::stLogarithmic) - mDataRange = dataRange.sanitizedForLogScale(); - else - mDataRange = dataRange.sanitizedForLinScale(); - mMapImageInvalidated = true; - emit dataRangeChanged(mDataRange); + if (!QCPRange::validRange(dataRange)) return; + if (mDataRange.lower != dataRange.lower || mDataRange.upper != dataRange.upper) + { + if (mDataScaleType == QCPAxis::stLogarithmic) + mDataRange = dataRange.sanitizedForLogScale(); + else + mDataRange = dataRange.sanitizedForLinScale(); + mMapImageInvalidated = true; + emit dataRangeChanged(mDataRange); } } @@ -20635,13 +20136,13 @@ void QCPColorMap::setDataRange(const QCP */ void QCPColorMap::setDataScaleType(QCPAxis::ScaleType scaleType) { - if (mDataScaleType != scaleType) - { - mDataScaleType = scaleType; - mMapImageInvalidated = true; - emit dataScaleTypeChanged(mDataScaleType); - if (mDataScaleType == QCPAxis::stLogarithmic) - setDataRange(mDataRange.sanitizedForLogScale()); + if (mDataScaleType != scaleType) + { + mDataScaleType = scaleType; + mMapImageInvalidated = true; + emit dataScaleTypeChanged(mDataScaleType); + if (mDataScaleType == QCPAxis::stLogarithmic) + setDataRange(mDataRange.sanitizedForLogScale()); } } @@ -20658,11 +20159,11 @@ void QCPColorMap::setDataScaleType(QCPAx */ void QCPColorMap::setGradient(const QCPColorGradient &gradient) { - if (mGradient != gradient) - { - mGradient = gradient; - mMapImageInvalidated = true; - emit gradientChanged(mGradient); + if (mGradient != gradient) + { + mGradient = gradient; + mMapImageInvalidated = true; + emit gradientChanged(mGradient); } } @@ -20674,7 +20175,7 @@ void QCPColorMap::setGradient(const QCPC */ void QCPColorMap::setInterpolate(bool enabled) { - mInterpolate = enabled; + mInterpolate = enabled; } /*! @@ -20690,7 +20191,7 @@ void QCPColorMap::setInterpolate(bool en */ void QCPColorMap::setTightBoundary(bool enabled) { - mTightBoundary = enabled; + mTightBoundary = enabled; } /*! @@ -20709,27 +20210,27 @@ void QCPColorMap::setTightBoundary(bool */ void QCPColorMap::setColorScale(QCPColorScale *colorScale) { - if (mColorScale) // unconnect signals from old color scale - { - disconnect(this, SIGNAL(dataRangeChanged(QCPRange)), mColorScale.data(), SLOT(setDataRange(QCPRange))); - disconnect(this, SIGNAL(dataScaleTypeChanged(QCPAxis::ScaleType)), mColorScale.data(), SLOT(setDataScaleType(QCPAxis::ScaleType))); - disconnect(this, SIGNAL(gradientChanged(QCPColorGradient)), mColorScale.data(), SLOT(setGradient(QCPColorGradient))); - disconnect(mColorScale.data(), SIGNAL(dataRangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange))); - disconnect(mColorScale.data(), SIGNAL(gradientChanged(QCPColorGradient)), this, SLOT(setGradient(QCPColorGradient))); - disconnect(mColorScale.data(), SIGNAL(dataScaleTypeChanged(QCPAxis::ScaleType)), this, SLOT(setDataScaleType(QCPAxis::ScaleType))); - } - mColorScale = colorScale; - if (mColorScale) // connect signals to new color scale - { - setGradient(mColorScale.data()->gradient()); - setDataRange(mColorScale.data()->dataRange()); - setDataScaleType(mColorScale.data()->dataScaleType()); - connect(this, SIGNAL(dataRangeChanged(QCPRange)), mColorScale.data(), SLOT(setDataRange(QCPRange))); - connect(this, SIGNAL(dataScaleTypeChanged(QCPAxis::ScaleType)), mColorScale.data(), SLOT(setDataScaleType(QCPAxis::ScaleType))); - connect(this, SIGNAL(gradientChanged(QCPColorGradient)), mColorScale.data(), SLOT(setGradient(QCPColorGradient))); - connect(mColorScale.data(), SIGNAL(dataRangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange))); - connect(mColorScale.data(), SIGNAL(gradientChanged(QCPColorGradient)), this, SLOT(setGradient(QCPColorGradient))); - connect(mColorScale.data(), SIGNAL(dataScaleTypeChanged(QCPAxis::ScaleType)), this, SLOT(setDataScaleType(QCPAxis::ScaleType))); + if (mColorScale) // unconnect signals from old color scale + { + disconnect(this, SIGNAL(dataRangeChanged(QCPRange)), mColorScale.data(), SLOT(setDataRange(QCPRange))); + disconnect(this, SIGNAL(dataScaleTypeChanged(QCPAxis::ScaleType)), mColorScale.data(), SLOT(setDataScaleType(QCPAxis::ScaleType))); + disconnect(this, SIGNAL(gradientChanged(QCPColorGradient)), mColorScale.data(), SLOT(setGradient(QCPColorGradient))); + disconnect(mColorScale.data(), SIGNAL(dataRangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange))); + disconnect(mColorScale.data(), SIGNAL(gradientChanged(QCPColorGradient)), this, SLOT(setGradient(QCPColorGradient))); + disconnect(mColorScale.data(), SIGNAL(dataScaleTypeChanged(QCPAxis::ScaleType)), this, SLOT(setDataScaleType(QCPAxis::ScaleType))); + } + mColorScale = colorScale; + if (mColorScale) // connect signals to new color scale + { + setGradient(mColorScale.data()->gradient()); + setDataRange(mColorScale.data()->dataRange()); + setDataScaleType(mColorScale.data()->dataScaleType()); + connect(this, SIGNAL(dataRangeChanged(QCPRange)), mColorScale.data(), SLOT(setDataRange(QCPRange))); + connect(this, SIGNAL(dataScaleTypeChanged(QCPAxis::ScaleType)), mColorScale.data(), SLOT(setDataScaleType(QCPAxis::ScaleType))); + connect(this, SIGNAL(gradientChanged(QCPColorGradient)), mColorScale.data(), SLOT(setGradient(QCPColorGradient))); + connect(mColorScale.data(), SIGNAL(dataRangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange))); + connect(mColorScale.data(), SIGNAL(gradientChanged(QCPColorGradient)), this, SLOT(setGradient(QCPColorGradient))); + connect(mColorScale.data(), SIGNAL(dataScaleTypeChanged(QCPAxis::ScaleType)), this, SLOT(setDataScaleType(QCPAxis::ScaleType))); } } @@ -20755,9 +20256,9 @@ void QCPColorMap::setColorScale(QCPColor */ void QCPColorMap::rescaleDataRange(bool recalculateDataBounds) { - if (recalculateDataBounds) - mMapData->recalculateDataBounds(); - setDataRange(mMapData->dataBounds()); + if (recalculateDataBounds) + mMapData->recalculateDataBounds(); + setDataRange(mMapData->dataBounds()); } /*! @@ -20776,14 +20277,14 @@ void QCPColorMap::rescaleDataRange(bool */ void QCPColorMap::updateLegendIcon(Qt::TransformationMode transformMode, const QSize &thumbSize) { - if (mMapImage.isNull() && !data()->isEmpty()) - updateMapImage(); // try to update map image if it's null (happens if no draw has happened yet) - - if (!mMapImage.isNull()) // might still be null, e.g. if data is empty, so check here again - { - bool mirrorX = (keyAxis()->orientation() == Qt::Horizontal ? keyAxis() : valueAxis())->rangeReversed(); - bool mirrorY = (valueAxis()->orientation() == Qt::Vertical ? valueAxis() : keyAxis())->rangeReversed(); - mLegendIcon = QPixmap::fromImage(mMapImage.mirrored(mirrorX, mirrorY)).scaled(thumbSize, Qt::KeepAspectRatio, transformMode); + if (mMapImage.isNull() && !data()->isEmpty()) + updateMapImage(); // try to update map image if it's null (happens if no draw has happened yet) + + if (!mMapImage.isNull()) // might still be null, e.g. if data is empty, so check here again + { + bool mirrorX = (keyAxis()->orientation() == Qt::Horizontal ? keyAxis() : valueAxis())->rangeReversed(); + bool mirrorY = (valueAxis()->orientation() == Qt::Vertical ? valueAxis() : keyAxis())->rangeReversed(); + mLegendIcon = QPixmap::fromImage(mMapImage.mirrored(mirrorX, mirrorY)).scaled(thumbSize, Qt::KeepAspectRatio, transformMode); } } @@ -20793,25 +20294,25 @@ void QCPColorMap::updateLegendIcon(Qt::T */ void QCPColorMap::clearData() { - mMapData->clear(); + mMapData->clear(); } /* inherits documentation from base class */ double QCPColorMap::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - Q_UNUSED(details) - if (onlySelectable && !mSelectable) + Q_UNUSED(details) + if (onlySelectable && !mSelectable) + return -1; + if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; } + + if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint())) + { + double posKey, posValue; + pixelsToCoords(pos, posKey, posValue); + if (mMapData->keyRange().contains(posKey) && mMapData->valueRange().contains(posValue)) + return mParentPlot->selectionTolerance()*0.99; + } return -1; - if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; } - - if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint())) - { - double posKey, posValue; - pixelsToCoords(pos, posKey, posValue); - if (mMapData->keyRange().contains(posKey) && mMapData->valueRange().contains(posValue)) - return mParentPlot->selectionTolerance()*0.99; - } - return -1; } /*! \internal @@ -20825,92 +20326,92 @@ double QCPColorMap::selectTest(const QPo */ void QCPColorMap::updateMapImage() { - QCPAxis *keyAxis = mKeyAxis.data(); - if (!keyAxis) return; - - // resize mMapImage to correct dimensions, according to key/value axes orientation: - if (keyAxis->orientation() == Qt::Horizontal && (mMapImage.size().width() != mMapData->keySize() || mMapImage.size().height() != mMapData->valueSize())) - mMapImage = QImage(QSize(mMapData->keySize(), mMapData->valueSize()), QImage::Format_RGB32); - else if (keyAxis->orientation() == Qt::Vertical && (mMapImage.size().width() != mMapData->valueSize() || mMapImage.size().height() != mMapData->keySize())) - mMapImage = QImage(QSize(mMapData->valueSize(), mMapData->keySize()), QImage::Format_RGB32); - - const int keySize = mMapData->keySize(); - const int valueSize = mMapData->valueSize(); - const double *rawData = mMapData->mData; - - if (keyAxis->orientation() == Qt::Horizontal) - { - const int lineCount = valueSize; - const int rowCount = keySize; - for (int line=0; line(mMapImage.scanLine(lineCount-1-line)); // invert scanline index because QImage counts scanlines from top, but our vertical index counts from bottom (mathematical coordinate system) - mGradient.colorize(rawData+line*rowCount, mDataRange, pixels, rowCount, 1, mDataScaleType==QCPAxis::stLogarithmic); + QCPAxis *keyAxis = mKeyAxis.data(); + if (!keyAxis) return; + + // resize mMapImage to correct dimensions, according to key/value axes orientation: + if (keyAxis->orientation() == Qt::Horizontal && (mMapImage.size().width() != mMapData->keySize() || mMapImage.size().height() != mMapData->valueSize())) + mMapImage = QImage(QSize(mMapData->keySize(), mMapData->valueSize()), QImage::Format_RGB32); + else if (keyAxis->orientation() == Qt::Vertical && (mMapImage.size().width() != mMapData->valueSize() || mMapImage.size().height() != mMapData->keySize())) + mMapImage = QImage(QSize(mMapData->valueSize(), mMapData->keySize()), QImage::Format_RGB32); + + const int keySize = mMapData->keySize(); + const int valueSize = mMapData->valueSize(); + const double *rawData = mMapData->mData; + + if (keyAxis->orientation() == Qt::Horizontal) + { + const int lineCount = valueSize; + const int rowCount = keySize; + for (int line=0; line(mMapImage.scanLine(lineCount-1-line)); // invert scanline index because QImage counts scanlines from top, but our vertical index counts from bottom (mathematical coordinate system) + mGradient.colorize(rawData+line*rowCount, mDataRange, pixels, rowCount, 1, mDataScaleType==QCPAxis::stLogarithmic); } } else // keyAxis->orientation() == Qt::Vertical { - const int lineCount = keySize; - const int rowCount = valueSize; - for (int line=0; line(mMapImage.scanLine(lineCount-1-line)); // invert scanline index because QImage counts scanlines from top, but our vertical index counts from bottom (mathematical coordinate system) - mGradient.colorize(rawData+line, mDataRange, pixels, rowCount, lineCount, mDataScaleType==QCPAxis::stLogarithmic); - } - } - - mMapData->mDataModified = false; - mMapImageInvalidated = false; + const int lineCount = keySize; + const int rowCount = valueSize; + for (int line=0; line(mMapImage.scanLine(lineCount-1-line)); // invert scanline index because QImage counts scanlines from top, but our vertical index counts from bottom (mathematical coordinate system) + mGradient.colorize(rawData+line, mDataRange, pixels, rowCount, lineCount, mDataScaleType==QCPAxis::stLogarithmic); + } + } + + mMapData->mDataModified = false; + mMapImageInvalidated = false; } /* inherits documentation from base class */ void QCPColorMap::draw(QCPPainter *painter) { - if (mMapData->isEmpty()) return; - if (!mKeyAxis || !mValueAxis) return; - applyDefaultAntialiasingHint(painter); - - if (mMapData->mDataModified || mMapImageInvalidated) - updateMapImage(); - - double halfSampleKey = 0; - double halfSampleValue = 0; - if (mMapData->keySize() > 1) - halfSampleKey = 0.5*mMapData->keyRange().size()/(double)(mMapData->keySize()-1); - if (mMapData->valueSize() > 1) - halfSampleValue = 0.5*mMapData->valueRange().size()/(double)(mMapData->valueSize()-1); - QRectF imageRect(coordsToPixels(mMapData->keyRange().lower-halfSampleKey, mMapData->valueRange().lower-halfSampleValue), - coordsToPixels(mMapData->keyRange().upper+halfSampleKey, mMapData->valueRange().upper+halfSampleValue)); - imageRect = imageRect.normalized(); - bool mirrorX = (keyAxis()->orientation() == Qt::Horizontal ? keyAxis() : valueAxis())->rangeReversed(); - bool mirrorY = (valueAxis()->orientation() == Qt::Vertical ? valueAxis() : keyAxis())->rangeReversed(); - bool smoothBackup = painter->renderHints().testFlag(QPainter::SmoothPixmapTransform); - painter->setRenderHint(QPainter::SmoothPixmapTransform, mInterpolate); - QRegion clipBackup; - if (mTightBoundary) - { - clipBackup = painter->clipRegion(); - painter->setClipRect(QRectF(coordsToPixels(mMapData->keyRange().lower, mMapData->valueRange().lower), - coordsToPixels(mMapData->keyRange().upper, mMapData->valueRange().upper)).normalized(), Qt::IntersectClip); - } - painter->drawImage(imageRect, mMapImage.mirrored(mirrorX, mirrorY)); - if (mTightBoundary) - painter->setClipRegion(clipBackup); - painter->setRenderHint(QPainter::SmoothPixmapTransform, smoothBackup); + if (mMapData->isEmpty()) return; + if (!mKeyAxis || !mValueAxis) return; + applyDefaultAntialiasingHint(painter); + + if (mMapData->mDataModified || mMapImageInvalidated) + updateMapImage(); + + double halfSampleKey = 0; + double halfSampleValue = 0; + if (mMapData->keySize() > 1) + halfSampleKey = 0.5*mMapData->keyRange().size()/(double)(mMapData->keySize()-1); + if (mMapData->valueSize() > 1) + halfSampleValue = 0.5*mMapData->valueRange().size()/(double)(mMapData->valueSize()-1); + QRectF imageRect(coordsToPixels(mMapData->keyRange().lower-halfSampleKey, mMapData->valueRange().lower-halfSampleValue), + coordsToPixels(mMapData->keyRange().upper+halfSampleKey, mMapData->valueRange().upper+halfSampleValue)); + imageRect = imageRect.normalized(); + bool mirrorX = (keyAxis()->orientation() == Qt::Horizontal ? keyAxis() : valueAxis())->rangeReversed(); + bool mirrorY = (valueAxis()->orientation() == Qt::Vertical ? valueAxis() : keyAxis())->rangeReversed(); + bool smoothBackup = painter->renderHints().testFlag(QPainter::SmoothPixmapTransform); + painter->setRenderHint(QPainter::SmoothPixmapTransform, mInterpolate); + QRegion clipBackup; + if (mTightBoundary) + { + clipBackup = painter->clipRegion(); + painter->setClipRect(QRectF(coordsToPixels(mMapData->keyRange().lower, mMapData->valueRange().lower), + coordsToPixels(mMapData->keyRange().upper, mMapData->valueRange().upper)).normalized(), Qt::IntersectClip); + } + painter->drawImage(imageRect, mMapImage.mirrored(mirrorX, mirrorY)); + if (mTightBoundary) + painter->setClipRegion(clipBackup); + painter->setRenderHint(QPainter::SmoothPixmapTransform, smoothBackup); } /* inherits documentation from base class */ void QCPColorMap::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const { - applyDefaultAntialiasingHint(painter); - // draw map thumbnail: - if (!mLegendIcon.isNull()) - { - QPixmap scaledIcon = mLegendIcon.scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::FastTransformation); - QRectF iconRect = QRectF(0, 0, scaledIcon.width(), scaledIcon.height()); - iconRect.moveCenter(rect.center()); - painter->drawPixmap(iconRect.topLeft(), scaledIcon); - } - /* + applyDefaultAntialiasingHint(painter); + // draw map thumbnail: + if (!mLegendIcon.isNull()) + { + QPixmap scaledIcon = mLegendIcon.scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::FastTransformation); + QRectF iconRect = QRectF(0, 0, scaledIcon.width(), scaledIcon.height()); + iconRect.moveCenter(rect.center()); + painter->drawPixmap(iconRect.topLeft(), scaledIcon); + } + /* // draw frame: painter->setBrush(Qt::NoBrush); painter->setPen(Qt::black); @@ -20921,45 +20422,45 @@ void QCPColorMap::drawLegendIcon(QCPPain /* inherits documentation from base class */ QCPRange QCPColorMap::getKeyRange(bool &foundRange, SignDomain inSignDomain) const { - foundRange = true; - QCPRange result = mMapData->keyRange(); - result.normalize(); - if (inSignDomain == QCPAbstractPlottable::sdPositive) - { - if (result.lower <= 0 && result.upper > 0) - result.lower = result.upper*1e-3; - else if (result.lower <= 0 && result.upper <= 0) - foundRange = false; + foundRange = true; + QCPRange result = mMapData->keyRange(); + result.normalize(); + if (inSignDomain == QCPAbstractPlottable::sdPositive) + { + if (result.lower <= 0 && result.upper > 0) + result.lower = result.upper*1e-3; + else if (result.lower <= 0 && result.upper <= 0) + foundRange = false; } else if (inSignDomain == QCPAbstractPlottable::sdNegative) { - if (result.upper >= 0 && result.lower < 0) - result.upper = result.lower*1e-3; - else if (result.upper >= 0 && result.lower >= 0) - foundRange = false; - } - return result; + if (result.upper >= 0 && result.lower < 0) + result.upper = result.lower*1e-3; + else if (result.upper >= 0 && result.lower >= 0) + foundRange = false; + } + return result; } /* inherits documentation from base class */ QCPRange QCPColorMap::getValueRange(bool &foundRange, SignDomain inSignDomain) const { - foundRange = true; - QCPRange result = mMapData->valueRange(); - result.normalize(); - if (inSignDomain == QCPAbstractPlottable::sdPositive) - { - if (result.lower <= 0 && result.upper > 0) - result.lower = result.upper*1e-3; - else if (result.lower <= 0 && result.upper <= 0) - foundRange = false; + foundRange = true; + QCPRange result = mMapData->valueRange(); + result.normalize(); + if (inSignDomain == QCPAbstractPlottable::sdPositive) + { + if (result.lower <= 0 && result.upper > 0) + result.lower = result.upper*1e-3; + else if (result.lower <= 0 && result.upper <= 0) + foundRange = false; } else if (inSignDomain == QCPAbstractPlottable::sdNegative) { - if (result.upper >= 0 && result.lower < 0) - result.upper = result.lower*1e-3; - else if (result.upper >= 0 && result.lower >= 0) - foundRange = false; - } - return result; + if (result.upper >= 0 && result.lower < 0) + result.upper = result.lower*1e-3; + else if (result.upper >= 0 && result.lower >= 0) + foundRange = false; + } + return result; } @@ -20986,11 +20487,11 @@ QCPRange QCPColorMap::getValueRange(bool Constructs a data point with key and all values set to zero. */ QCPFinancialData::QCPFinancialData() : - key(0), - open(0), - high(0), - low(0), - close(0) + key(0), + open(0), + high(0), + low(0), + close(0) { } @@ -20998,11 +20499,11 @@ QCPFinancialData::QCPFinancialData() : Constructs a data point with the specified \a key and OHLC values. */ QCPFinancialData::QCPFinancialData(double key, double open, double high, double low, double close) : - key(key), - open(open), - high(high), - low(low), - close(close) + key(key), + open(open), + high(high), + low(low), + close(close) { } @@ -21064,25 +20565,25 @@ QCPFinancialData::QCPFinancialData(doubl then takes ownership of the financial chart. */ QCPFinancial::QCPFinancial(QCPAxis *keyAxis, QCPAxis *valueAxis) : - QCPAbstractPlottable(keyAxis, valueAxis), - mData(0), - mChartStyle(csOhlc), - mWidth(0.5), - mTwoColored(false), - mBrushPositive(QBrush(QColor(210, 210, 255))), - mBrushNegative(QBrush(QColor(255, 210, 210))), - mPenPositive(QPen(QColor(10, 40, 180))), - mPenNegative(QPen(QColor(180, 40, 10))) -{ - mData = new QCPFinancialDataMap; - - setSelectedPen(QPen(QColor(80, 80, 255), 2.5)); - setSelectedBrush(QBrush(QColor(80, 80, 255))); + QCPAbstractPlottable(keyAxis, valueAxis), + mData(0), + mChartStyle(csOhlc), + mWidth(0.5), + mTwoColored(false), + mBrushPositive(QBrush(QColor(210, 210, 255))), + mBrushNegative(QBrush(QColor(255, 210, 210))), + mPenPositive(QPen(QColor(10, 40, 180))), + mPenNegative(QPen(QColor(180, 40, 10))) +{ + mData = new QCPFinancialDataMap; + + setSelectedPen(QPen(QColor(80, 80, 255), 2.5)); + setSelectedBrush(QBrush(QColor(80, 80, 255))); } QCPFinancial::~QCPFinancial() { - delete mData; + delete mData; } /*! @@ -21099,18 +20600,18 @@ QCPFinancial::~QCPFinancial() */ void QCPFinancial::setData(QCPFinancialDataMap *data, bool copy) { - if (mData == data) - { - qDebug() << Q_FUNC_INFO << "The data pointer is already in (and owned by) this plottable" << reinterpret_cast(data); - return; - } - if (copy) - { - *mData = *data; - } else - { - delete mData; - mData = data; + if (mData == data) + { + qDebug() << Q_FUNC_INFO << "The data pointer is already in (and owned by) this plottable" << reinterpret_cast(data); + return; + } + if (copy) + { + *mData = *data; + } else + { + delete mData; + mData = data; } } @@ -21123,15 +20624,15 @@ void QCPFinancial::setData(QCPFinancialD */ void QCPFinancial::setData(const QVector &key, const QVector &open, const QVector &high, const QVector &low, const QVector &close) { - mData->clear(); - int n = key.size(); - n = qMin(n, open.size()); - n = qMin(n, high.size()); - n = qMin(n, low.size()); - n = qMin(n, close.size()); - for (int i=0; iinsertMulti(key[i], QCPFinancialData(key[i], open[i], high[i], low[i], close[i])); + mData->clear(); + int n = key.size(); + n = qMin(n, open.size()); + n = qMin(n, high.size()); + n = qMin(n, low.size()); + n = qMin(n, close.size()); + for (int i=0; iinsertMulti(key[i], QCPFinancialData(key[i], open[i], high[i], low[i], close[i])); } } @@ -21140,7 +20641,7 @@ void QCPFinancial::setData(const QVector */ void QCPFinancial::setChartStyle(QCPFinancial::ChartStyle style) { - mChartStyle = style; + mChartStyle = style; } /*! @@ -21150,7 +20651,7 @@ void QCPFinancial::setChartStyle(QCPFina */ void QCPFinancial::setWidth(double width) { - mWidth = width; + mWidth = width; } /*! @@ -21164,7 +20665,7 @@ void QCPFinancial::setWidth(double width */ void QCPFinancial::setTwoColored(bool twoColored) { - mTwoColored = twoColored; + mTwoColored = twoColored; } /*! @@ -21178,7 +20679,7 @@ void QCPFinancial::setTwoColored(bool tw */ void QCPFinancial::setBrushPositive(const QBrush &brush) { - mBrushPositive = brush; + mBrushPositive = brush; } /*! @@ -21192,7 +20693,7 @@ void QCPFinancial::setBrushPositive(cons */ void QCPFinancial::setBrushNegative(const QBrush &brush) { - mBrushNegative = brush; + mBrushNegative = brush; } /*! @@ -21206,7 +20707,7 @@ void QCPFinancial::setBrushNegative(cons */ void QCPFinancial::setPenPositive(const QPen &pen) { - mPenPositive = pen; + mPenPositive = pen; } /*! @@ -21220,7 +20721,7 @@ void QCPFinancial::setPenPositive(const */ void QCPFinancial::setPenNegative(const QPen &pen) { - mPenNegative = pen; + mPenNegative = pen; } /*! @@ -21233,7 +20734,7 @@ void QCPFinancial::setPenNegative(const */ void QCPFinancial::addData(const QCPFinancialDataMap &dataMap) { - mData->unite(dataMap); + mData->unite(dataMap); } /*! \overload @@ -21247,7 +20748,7 @@ void QCPFinancial::addData(const QCPFina */ void QCPFinancial::addData(const QCPFinancialData &data) { - mData->insertMulti(data.key, data); + mData->insertMulti(data.key, data); } /*! \overload @@ -21262,7 +20763,7 @@ void QCPFinancial::addData(const QCPFina */ void QCPFinancial::addData(double key, double open, double high, double low, double close) { - mData->insertMulti(key, QCPFinancialData(key, open, high, low, close)); + mData->insertMulti(key, QCPFinancialData(key, open, high, low, close)); } /*! \overload @@ -21276,14 +20777,14 @@ void QCPFinancial::addData(double key, d */ void QCPFinancial::addData(const QVector &key, const QVector &open, const QVector &high, const QVector &low, const QVector &close) { - int n = key.size(); - n = qMin(n, open.size()); - n = qMin(n, high.size()); - n = qMin(n, low.size()); - n = qMin(n, close.size()); - for (int i=0; iinsertMulti(key[i], QCPFinancialData(key[i], open[i], high[i], low[i], close[i])); + int n = key.size(); + n = qMin(n, open.size()); + n = qMin(n, high.size()); + n = qMin(n, low.size()); + n = qMin(n, close.size()); + for (int i=0; iinsertMulti(key[i], QCPFinancialData(key[i], open[i], high[i], low[i], close[i])); } } @@ -21294,9 +20795,9 @@ void QCPFinancial::addData(const QVector */ void QCPFinancial::removeDataBefore(double key) { - QCPFinancialDataMap::iterator it = mData->begin(); - while (it != mData->end() && it.key() < key) - it = mData->erase(it); + QCPFinancialDataMap::iterator it = mData->begin(); + while (it != mData->end() && it.key() < key) + it = mData->erase(it); } /*! @@ -21306,10 +20807,10 @@ void QCPFinancial::removeDataBefore(doub */ void QCPFinancial::removeDataAfter(double key) { - if (mData->isEmpty()) return; - QCPFinancialDataMap::iterator it = mData->upperBound(key); - while (it != mData->end()) - it = mData->erase(it); + if (mData->isEmpty()) return; + QCPFinancialDataMap::iterator it = mData->upperBound(key); + while (it != mData->end()) + it = mData->erase(it); } /*! @@ -21321,11 +20822,11 @@ void QCPFinancial::removeDataAfter(doubl */ void QCPFinancial::removeData(double fromKey, double toKey) { - if (fromKey >= toKey || mData->isEmpty()) return; - QCPFinancialDataMap::iterator it = mData->upperBound(fromKey); - QCPFinancialDataMap::iterator itEnd = mData->upperBound(toKey); - while (it != itEnd) - it = mData->erase(it); + if (fromKey >= toKey || mData->isEmpty()) return; + QCPFinancialDataMap::iterator it = mData->upperBound(fromKey); + QCPFinancialDataMap::iterator itEnd = mData->upperBound(toKey); + while (it != itEnd) + it = mData->erase(it); } /*! \overload @@ -21338,7 +20839,7 @@ void QCPFinancial::removeData(double fro */ void QCPFinancial::removeData(double key) { - mData->remove(key); + mData->remove(key); } /*! @@ -21348,34 +20849,34 @@ void QCPFinancial::removeData(double key */ void QCPFinancial::clearData() { - mData->clear(); + mData->clear(); } /* inherits documentation from base class */ double QCPFinancial::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - Q_UNUSED(details) - if (onlySelectable && !mSelectable) - return -1; - if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; } - - if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint())) - { - // get visible data range: - QCPFinancialDataMap::const_iterator lower, upper; // note that upper is the actual upper point, and not 1 step after the upper point - getVisibleDataBounds(lower, upper); - if (lower == mData->constEnd() || upper == mData->constEnd()) + Q_UNUSED(details) + if (onlySelectable && !mSelectable) return -1; - // perform select test according to configured style: - switch (mChartStyle) + if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; } + + if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint())) + { + // get visible data range: + QCPFinancialDataMap::const_iterator lower, upper; // note that upper is the actual upper point, and not 1 step after the upper point + getVisibleDataBounds(lower, upper); + if (lower == mData->constEnd() || upper == mData->constEnd()) + return -1; + // perform select test according to configured style: + switch (mChartStyle) { case QCPFinancial::csOhlc: - return ohlcSelectTest(pos, lower, upper+1); break; + return ohlcSelectTest(pos, lower, upper+1); break; case QCPFinancial::csCandlestick: - return candlestickSelectTest(pos, lower, upper+1); break; - } - } - return -1; + return candlestickSelectTest(pos, lower, upper+1); break; + } + } + return -1; } /*! @@ -21393,117 +20894,117 @@ double QCPFinancial::selectTest(const QP */ QCPFinancialDataMap QCPFinancial::timeSeriesToOhlc(const QVector &time, const QVector &value, double timeBinSize, double timeBinOffset) { - QCPFinancialDataMap map; - int count = qMin(time.size(), value.size()); - if (count == 0) - return QCPFinancialDataMap(); - - QCPFinancialData currentBinData(0, value.first(), value.first(), value.first(), value.first()); - int currentBinIndex = qFloor((time.first()-timeBinOffset)/timeBinSize+0.5); - for (int i=0; i currentBinData.high) currentBinData.high = value.at(i); - if (i == count-1) // last data point is in current bin, finalize bin: - { - currentBinData.close = value.at(i); - currentBinData.key = timeBinOffset+(index)*timeBinSize; - map.insert(currentBinData.key, currentBinData); + QCPFinancialDataMap map; + int count = qMin(time.size(), value.size()); + if (count == 0) + return QCPFinancialDataMap(); + + QCPFinancialData currentBinData(0, value.first(), value.first(), value.first(), value.first()); + int currentBinIndex = qFloor((time.first()-timeBinOffset)/timeBinSize+0.5); + for (int i=0; i currentBinData.high) currentBinData.high = value.at(i); + if (i == count-1) // last data point is in current bin, finalize bin: + { + currentBinData.close = value.at(i); + currentBinData.key = timeBinOffset+(index)*timeBinSize; + map.insert(currentBinData.key, currentBinData); } } else // data point not anymore in current bin, set close of old and open of new bin, and add old to map: { - // finalize current bin: - currentBinData.close = value.at(i-1); - currentBinData.key = timeBinOffset+(index-1)*timeBinSize; - map.insert(currentBinData.key, currentBinData); - // start next bin: - currentBinIndex = index; - currentBinData.open = value.at(i); - currentBinData.high = value.at(i); - currentBinData.low = value.at(i); - } - } - - return map; + // finalize current bin: + currentBinData.close = value.at(i-1); + currentBinData.key = timeBinOffset+(index-1)*timeBinSize; + map.insert(currentBinData.key, currentBinData); + // start next bin: + currentBinIndex = index; + currentBinData.open = value.at(i); + currentBinData.high = value.at(i); + currentBinData.low = value.at(i); + } + } + + return map; } /* inherits documentation from base class */ void QCPFinancial::draw(QCPPainter *painter) { - // get visible data range: - QCPFinancialDataMap::const_iterator lower, upper; // note that upper is the actual upper point, and not 1 step after the upper point - getVisibleDataBounds(lower, upper); - if (lower == mData->constEnd() || upper == mData->constEnd()) - return; - - // draw visible data range according to configured style: - switch (mChartStyle) + // get visible data range: + QCPFinancialDataMap::const_iterator lower, upper; // note that upper is the actual upper point, and not 1 step after the upper point + getVisibleDataBounds(lower, upper); + if (lower == mData->constEnd() || upper == mData->constEnd()) + return; + + // draw visible data range according to configured style: + switch (mChartStyle) { case QCPFinancial::csOhlc: - drawOhlcPlot(painter, lower, upper+1); break; + drawOhlcPlot(painter, lower, upper+1); break; case QCPFinancial::csCandlestick: - drawCandlestickPlot(painter, lower, upper+1); break; + drawCandlestickPlot(painter, lower, upper+1); break; } } /* inherits documentation from base class */ void QCPFinancial::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const { - painter->setAntialiasing(false); // legend icon especially of csCandlestick looks better without antialiasing - if (mChartStyle == csOhlc) - { - if (mTwoColored) - { - // draw upper left half icon with positive color: - painter->setBrush(mBrushPositive); - painter->setPen(mPenPositive); - painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.topLeft().toPoint())); - painter->drawLine(QLineF(0, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft())); - painter->drawLine(QLineF(rect.width()*0.2, rect.height()*0.3, rect.width()*0.2, rect.height()*0.5).translated(rect.topLeft())); - painter->drawLine(QLineF(rect.width()*0.8, rect.height()*0.5, rect.width()*0.8, rect.height()*0.7).translated(rect.topLeft())); - // draw bottom right hald icon with negative color: - painter->setBrush(mBrushNegative); - painter->setPen(mPenNegative); - painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.bottomRight().toPoint())); - painter->drawLine(QLineF(0, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft())); - painter->drawLine(QLineF(rect.width()*0.2, rect.height()*0.3, rect.width()*0.2, rect.height()*0.5).translated(rect.topLeft())); - painter->drawLine(QLineF(rect.width()*0.8, rect.height()*0.5, rect.width()*0.8, rect.height()*0.7).translated(rect.topLeft())); + painter->setAntialiasing(false); // legend icon especially of csCandlestick looks better without antialiasing + if (mChartStyle == csOhlc) + { + if (mTwoColored) + { + // draw upper left half icon with positive color: + painter->setBrush(mBrushPositive); + painter->setPen(mPenPositive); + painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.topLeft().toPoint())); + painter->drawLine(QLineF(0, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft())); + painter->drawLine(QLineF(rect.width()*0.2, rect.height()*0.3, rect.width()*0.2, rect.height()*0.5).translated(rect.topLeft())); + painter->drawLine(QLineF(rect.width()*0.8, rect.height()*0.5, rect.width()*0.8, rect.height()*0.7).translated(rect.topLeft())); + // draw bottom right hald icon with negative color: + painter->setBrush(mBrushNegative); + painter->setPen(mPenNegative); + painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.bottomRight().toPoint())); + painter->drawLine(QLineF(0, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft())); + painter->drawLine(QLineF(rect.width()*0.2, rect.height()*0.3, rect.width()*0.2, rect.height()*0.5).translated(rect.topLeft())); + painter->drawLine(QLineF(rect.width()*0.8, rect.height()*0.5, rect.width()*0.8, rect.height()*0.7).translated(rect.topLeft())); } else { - painter->setBrush(mBrush); - painter->setPen(mPen); - painter->drawLine(QLineF(0, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft())); - painter->drawLine(QLineF(rect.width()*0.2, rect.height()*0.3, rect.width()*0.2, rect.height()*0.5).translated(rect.topLeft())); - painter->drawLine(QLineF(rect.width()*0.8, rect.height()*0.5, rect.width()*0.8, rect.height()*0.7).translated(rect.topLeft())); + painter->setBrush(mBrush); + painter->setPen(mPen); + painter->drawLine(QLineF(0, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft())); + painter->drawLine(QLineF(rect.width()*0.2, rect.height()*0.3, rect.width()*0.2, rect.height()*0.5).translated(rect.topLeft())); + painter->drawLine(QLineF(rect.width()*0.8, rect.height()*0.5, rect.width()*0.8, rect.height()*0.7).translated(rect.topLeft())); } } else if (mChartStyle == csCandlestick) { - if (mTwoColored) - { - // draw upper left half icon with positive color: - painter->setBrush(mBrushPositive); - painter->setPen(mPenPositive); - painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.topLeft().toPoint())); - painter->drawLine(QLineF(0, rect.height()*0.5, rect.width()*0.25, rect.height()*0.5).translated(rect.topLeft())); - painter->drawLine(QLineF(rect.width()*0.75, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft())); - painter->drawRect(QRectF(rect.width()*0.25, rect.height()*0.25, rect.width()*0.5, rect.height()*0.5).translated(rect.topLeft())); - // draw bottom right hald icon with negative color: - painter->setBrush(mBrushNegative); - painter->setPen(mPenNegative); - painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.bottomRight().toPoint())); - painter->drawLine(QLineF(0, rect.height()*0.5, rect.width()*0.25, rect.height()*0.5).translated(rect.topLeft())); - painter->drawLine(QLineF(rect.width()*0.75, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft())); - painter->drawRect(QRectF(rect.width()*0.25, rect.height()*0.25, rect.width()*0.5, rect.height()*0.5).translated(rect.topLeft())); + if (mTwoColored) + { + // draw upper left half icon with positive color: + painter->setBrush(mBrushPositive); + painter->setPen(mPenPositive); + painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.topLeft().toPoint())); + painter->drawLine(QLineF(0, rect.height()*0.5, rect.width()*0.25, rect.height()*0.5).translated(rect.topLeft())); + painter->drawLine(QLineF(rect.width()*0.75, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft())); + painter->drawRect(QRectF(rect.width()*0.25, rect.height()*0.25, rect.width()*0.5, rect.height()*0.5).translated(rect.topLeft())); + // draw bottom right hald icon with negative color: + painter->setBrush(mBrushNegative); + painter->setPen(mPenNegative); + painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.bottomRight().toPoint())); + painter->drawLine(QLineF(0, rect.height()*0.5, rect.width()*0.25, rect.height()*0.5).translated(rect.topLeft())); + painter->drawLine(QLineF(rect.width()*0.75, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft())); + painter->drawRect(QRectF(rect.width()*0.25, rect.height()*0.25, rect.width()*0.5, rect.height()*0.5).translated(rect.topLeft())); } else { - painter->setBrush(mBrush); - painter->setPen(mPen); - painter->drawLine(QLineF(0, rect.height()*0.5, rect.width()*0.25, rect.height()*0.5).translated(rect.topLeft())); - painter->drawLine(QLineF(rect.width()*0.75, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft())); - painter->drawRect(QRectF(rect.width()*0.25, rect.height()*0.25, rect.width()*0.5, rect.height()*0.5).translated(rect.topLeft())); + painter->setBrush(mBrush); + painter->setPen(mPen); + painter->drawLine(QLineF(0, rect.height()*0.5, rect.width()*0.25, rect.height()*0.5).translated(rect.topLeft())); + painter->drawLine(QLineF(rect.width()*0.75, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft())); + painter->drawRect(QRectF(rect.width()*0.25, rect.height()*0.25, rect.width()*0.5, rect.height()*0.5).translated(rect.topLeft())); } } } @@ -21511,82 +21012,82 @@ void QCPFinancial::drawLegendIcon(QCPPai /* inherits documentation from base class */ QCPRange QCPFinancial::getKeyRange(bool &foundRange, QCPAbstractPlottable::SignDomain inSignDomain) const { - QCPRange range; - bool haveLower = false; - bool haveUpper = false; - - double current; - QCPFinancialDataMap::const_iterator it = mData->constBegin(); - while (it != mData->constEnd()) - { - current = it.value().key; - if (inSignDomain == sdBoth || (inSignDomain == sdNegative && current < 0) || (inSignDomain == sdPositive && current > 0)) - { - if (current < range.lower || !haveLower) - { - range.lower = current; - haveLower = true; - } - if (current > range.upper || !haveUpper) - { - range.upper = current; - haveUpper = true; - } - } - ++it; - } - // determine exact range by including width of bars/flags: - if (haveLower && mKeyAxis) - range.lower = range.lower-mWidth*0.5; - if (haveUpper && mKeyAxis) - range.upper = range.upper+mWidth*0.5; - foundRange = haveLower && haveUpper; - return range; + QCPRange range; + bool haveLower = false; + bool haveUpper = false; + + double current; + QCPFinancialDataMap::const_iterator it = mData->constBegin(); + while (it != mData->constEnd()) + { + current = it.value().key; + if (inSignDomain == sdBoth || (inSignDomain == sdNegative && current < 0) || (inSignDomain == sdPositive && current > 0)) + { + if (current < range.lower || !haveLower) + { + range.lower = current; + haveLower = true; + } + if (current > range.upper || !haveUpper) + { + range.upper = current; + haveUpper = true; + } + } + ++it; + } + // determine exact range by including width of bars/flags: + if (haveLower && mKeyAxis) + range.lower = range.lower-mWidth*0.5; + if (haveUpper && mKeyAxis) + range.upper = range.upper+mWidth*0.5; + foundRange = haveLower && haveUpper; + return range; } /* inherits documentation from base class */ QCPRange QCPFinancial::getValueRange(bool &foundRange, QCPAbstractPlottable::SignDomain inSignDomain) const { - QCPRange range; - bool haveLower = false; - bool haveUpper = false; - - QCPFinancialDataMap::const_iterator it = mData->constBegin(); - while (it != mData->constEnd()) - { - // high: - if (inSignDomain == sdBoth || (inSignDomain == sdNegative && it.value().high < 0) || (inSignDomain == sdPositive && it.value().high > 0)) - { - if (it.value().high < range.lower || !haveLower) - { - range.lower = it.value().high; - haveLower = true; - } - if (it.value().high > range.upper || !haveUpper) - { - range.upper = it.value().high; - haveUpper = true; - } - } - // low: - if (inSignDomain == sdBoth || (inSignDomain == sdNegative && it.value().low < 0) || (inSignDomain == sdPositive && it.value().low > 0)) - { - if (it.value().low < range.lower || !haveLower) - { - range.lower = it.value().low; - haveLower = true; - } - if (it.value().low > range.upper || !haveUpper) - { - range.upper = it.value().low; - haveUpper = true; - } - } - ++it; - } - - foundRange = haveLower && haveUpper; - return range; + QCPRange range; + bool haveLower = false; + bool haveUpper = false; + + QCPFinancialDataMap::const_iterator it = mData->constBegin(); + while (it != mData->constEnd()) + { + // high: + if (inSignDomain == sdBoth || (inSignDomain == sdNegative && it.value().high < 0) || (inSignDomain == sdPositive && it.value().high > 0)) + { + if (it.value().high < range.lower || !haveLower) + { + range.lower = it.value().high; + haveLower = true; + } + if (it.value().high > range.upper || !haveUpper) + { + range.upper = it.value().high; + haveUpper = true; + } + } + // low: + if (inSignDomain == sdBoth || (inSignDomain == sdNegative && it.value().low < 0) || (inSignDomain == sdPositive && it.value().low > 0)) + { + if (it.value().low < range.lower || !haveLower) + { + range.lower = it.value().low; + haveLower = true; + } + if (it.value().low > range.upper || !haveUpper) + { + range.upper = it.value().low; + haveUpper = true; + } + } + ++it; + } + + foundRange = haveLower && haveUpper; + return range; } /*! \internal @@ -21597,55 +21098,55 @@ QCPRange QCPFinancial::getValueRange(boo */ void QCPFinancial::drawOhlcPlot(QCPPainter *painter, const QCPFinancialDataMap::const_iterator &begin, const QCPFinancialDataMap::const_iterator &end) { - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - - QPen linePen; - - if (keyAxis->orientation() == Qt::Horizontal) - { - for (QCPFinancialDataMap::const_iterator it = begin; it != end; ++it) - { - if (mSelected) - linePen = mSelectedPen; - else if (mTwoColored) - linePen = it.value().close >= it.value().open ? mPenPositive : mPenNegative; - else - linePen = mPen; - painter->setPen(linePen); - double keyPixel = keyAxis->coordToPixel(it.value().key); - double openPixel = valueAxis->coordToPixel(it.value().open); - double closePixel = valueAxis->coordToPixel(it.value().close); - // draw backbone: - painter->drawLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().high)), QPointF(keyPixel, valueAxis->coordToPixel(it.value().low))); - // draw open: - double keyWidthPixels = keyPixel-keyAxis->coordToPixel(it.value().key-mWidth*0.5); // sign of this makes sure open/close are on correct sides - painter->drawLine(QPointF(keyPixel-keyWidthPixels, openPixel), QPointF(keyPixel, openPixel)); - // draw close: - painter->drawLine(QPointF(keyPixel, closePixel), QPointF(keyPixel+keyWidthPixels, closePixel)); - } - } else - { - for (QCPFinancialDataMap::const_iterator it = begin; it != end; ++it) - { - if (mSelected) - linePen = mSelectedPen; - else if (mTwoColored) - linePen = it.value().close >= it.value().open ? mPenPositive : mPenNegative; - else - linePen = mPen; - painter->setPen(linePen); - double keyPixel = keyAxis->coordToPixel(it.value().key); - double openPixel = valueAxis->coordToPixel(it.value().open); - double closePixel = valueAxis->coordToPixel(it.value().close); - // draw backbone: - painter->drawLine(QPointF(valueAxis->coordToPixel(it.value().high), keyPixel), QPointF(valueAxis->coordToPixel(it.value().low), keyPixel)); - // draw open: - double keyWidthPixels = keyPixel-keyAxis->coordToPixel(it.value().key-mWidth*0.5); // sign of this makes sure open/close are on correct sides - painter->drawLine(QPointF(openPixel, keyPixel-keyWidthPixels), QPointF(openPixel, keyPixel)); - // draw close: - painter->drawLine(QPointF(closePixel, keyPixel), QPointF(closePixel, keyPixel+keyWidthPixels)); + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + + QPen linePen; + + if (keyAxis->orientation() == Qt::Horizontal) + { + for (QCPFinancialDataMap::const_iterator it = begin; it != end; ++it) + { + if (mSelected) + linePen = mSelectedPen; + else if (mTwoColored) + linePen = it.value().close >= it.value().open ? mPenPositive : mPenNegative; + else + linePen = mPen; + painter->setPen(linePen); + double keyPixel = keyAxis->coordToPixel(it.value().key); + double openPixel = valueAxis->coordToPixel(it.value().open); + double closePixel = valueAxis->coordToPixel(it.value().close); + // draw backbone: + painter->drawLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().high)), QPointF(keyPixel, valueAxis->coordToPixel(it.value().low))); + // draw open: + double keyWidthPixels = keyPixel-keyAxis->coordToPixel(it.value().key-mWidth*0.5); // sign of this makes sure open/close are on correct sides + painter->drawLine(QPointF(keyPixel-keyWidthPixels, openPixel), QPointF(keyPixel, openPixel)); + // draw close: + painter->drawLine(QPointF(keyPixel, closePixel), QPointF(keyPixel+keyWidthPixels, closePixel)); + } + } else + { + for (QCPFinancialDataMap::const_iterator it = begin; it != end; ++it) + { + if (mSelected) + linePen = mSelectedPen; + else if (mTwoColored) + linePen = it.value().close >= it.value().open ? mPenPositive : mPenNegative; + else + linePen = mPen; + painter->setPen(linePen); + double keyPixel = keyAxis->coordToPixel(it.value().key); + double openPixel = valueAxis->coordToPixel(it.value().open); + double closePixel = valueAxis->coordToPixel(it.value().close); + // draw backbone: + painter->drawLine(QPointF(valueAxis->coordToPixel(it.value().high), keyPixel), QPointF(valueAxis->coordToPixel(it.value().low), keyPixel)); + // draw open: + double keyWidthPixels = keyPixel-keyAxis->coordToPixel(it.value().key-mWidth*0.5); // sign of this makes sure open/close are on correct sides + painter->drawLine(QPointF(openPixel, keyPixel-keyWidthPixels), QPointF(openPixel, keyPixel)); + // draw close: + painter->drawLine(QPointF(closePixel, keyPixel), QPointF(closePixel, keyPixel+keyWidthPixels)); } } } @@ -21658,86 +21159,86 @@ void QCPFinancial::drawOhlcPlot(QCPPaint */ void QCPFinancial::drawCandlestickPlot(QCPPainter *painter, const QCPFinancialDataMap::const_iterator &begin, const QCPFinancialDataMap::const_iterator &end) { - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - - QPen linePen; - QBrush boxBrush; - - if (keyAxis->orientation() == Qt::Horizontal) - { - for (QCPFinancialDataMap::const_iterator it = begin; it != end; ++it) - { - if (mSelected) - { - linePen = mSelectedPen; - boxBrush = mSelectedBrush; + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + + QPen linePen; + QBrush boxBrush; + + if (keyAxis->orientation() == Qt::Horizontal) + { + for (QCPFinancialDataMap::const_iterator it = begin; it != end; ++it) + { + if (mSelected) + { + linePen = mSelectedPen; + boxBrush = mSelectedBrush; } else if (mTwoColored) { - if (it.value().close >= it.value().open) + if (it.value().close >= it.value().open) { - linePen = mPenPositive; - boxBrush = mBrushPositive; + linePen = mPenPositive; + boxBrush = mBrushPositive; } else { - linePen = mPenNegative; - boxBrush = mBrushNegative; + linePen = mPenNegative; + boxBrush = mBrushNegative; } } else { - linePen = mPen; - boxBrush = mBrush; - } - painter->setPen(linePen); - painter->setBrush(boxBrush); - double keyPixel = keyAxis->coordToPixel(it.value().key); - double openPixel = valueAxis->coordToPixel(it.value().open); - double closePixel = valueAxis->coordToPixel(it.value().close); - // draw high: - painter->drawLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().high)), QPointF(keyPixel, valueAxis->coordToPixel(qMax(it.value().open, it.value().close)))); - // draw low: - painter->drawLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().low)), QPointF(keyPixel, valueAxis->coordToPixel(qMin(it.value().open, it.value().close)))); - // draw open-close box: - double keyWidthPixels = keyPixel-keyAxis->coordToPixel(it.value().key-mWidth*0.5); - painter->drawRect(QRectF(QPointF(keyPixel-keyWidthPixels, closePixel), QPointF(keyPixel+keyWidthPixels, openPixel))); + linePen = mPen; + boxBrush = mBrush; + } + painter->setPen(linePen); + painter->setBrush(boxBrush); + double keyPixel = keyAxis->coordToPixel(it.value().key); + double openPixel = valueAxis->coordToPixel(it.value().open); + double closePixel = valueAxis->coordToPixel(it.value().close); + // draw high: + painter->drawLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().high)), QPointF(keyPixel, valueAxis->coordToPixel(qMax(it.value().open, it.value().close)))); + // draw low: + painter->drawLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().low)), QPointF(keyPixel, valueAxis->coordToPixel(qMin(it.value().open, it.value().close)))); + // draw open-close box: + double keyWidthPixels = keyPixel-keyAxis->coordToPixel(it.value().key-mWidth*0.5); + painter->drawRect(QRectF(QPointF(keyPixel-keyWidthPixels, closePixel), QPointF(keyPixel+keyWidthPixels, openPixel))); } } else // keyAxis->orientation() == Qt::Vertical { - for (QCPFinancialDataMap::const_iterator it = begin; it != end; ++it) - { - if (mSelected) - { - linePen = mSelectedPen; - boxBrush = mSelectedBrush; + for (QCPFinancialDataMap::const_iterator it = begin; it != end; ++it) + { + if (mSelected) + { + linePen = mSelectedPen; + boxBrush = mSelectedBrush; } else if (mTwoColored) { - if (it.value().close >= it.value().open) + if (it.value().close >= it.value().open) { - linePen = mPenPositive; - boxBrush = mBrushPositive; + linePen = mPenPositive; + boxBrush = mBrushPositive; } else { - linePen = mPenNegative; - boxBrush = mBrushNegative; + linePen = mPenNegative; + boxBrush = mBrushNegative; } } else { - linePen = mPen; - boxBrush = mBrush; - } - painter->setPen(linePen); - painter->setBrush(boxBrush); - double keyPixel = keyAxis->coordToPixel(it.value().key); - double openPixel = valueAxis->coordToPixel(it.value().open); - double closePixel = valueAxis->coordToPixel(it.value().close); - // draw high: - painter->drawLine(QPointF(valueAxis->coordToPixel(it.value().high), keyPixel), QPointF(valueAxis->coordToPixel(qMax(it.value().open, it.value().close)), keyPixel)); - // draw low: - painter->drawLine(QPointF(valueAxis->coordToPixel(it.value().low), keyPixel), QPointF(valueAxis->coordToPixel(qMin(it.value().open, it.value().close)), keyPixel)); - // draw open-close box: - double keyWidthPixels = keyPixel-keyAxis->coordToPixel(it.value().key-mWidth*0.5); - painter->drawRect(QRectF(QPointF(closePixel, keyPixel-keyWidthPixels), QPointF(openPixel, keyPixel+keyWidthPixels))); + linePen = mPen; + boxBrush = mBrush; + } + painter->setPen(linePen); + painter->setBrush(boxBrush); + double keyPixel = keyAxis->coordToPixel(it.value().key); + double openPixel = valueAxis->coordToPixel(it.value().open); + double closePixel = valueAxis->coordToPixel(it.value().close); + // draw high: + painter->drawLine(QPointF(valueAxis->coordToPixel(it.value().high), keyPixel), QPointF(valueAxis->coordToPixel(qMax(it.value().open, it.value().close)), keyPixel)); + // draw low: + painter->drawLine(QPointF(valueAxis->coordToPixel(it.value().low), keyPixel), QPointF(valueAxis->coordToPixel(qMin(it.value().open, it.value().close)), keyPixel)); + // draw open-close box: + double keyWidthPixels = keyPixel-keyAxis->coordToPixel(it.value().key-mWidth*0.5); + painter->drawRect(QRectF(QPointF(closePixel, keyPixel-keyWidthPixels), QPointF(openPixel, keyPixel+keyWidthPixels))); } } } @@ -21749,34 +21250,34 @@ void QCPFinancial::drawCandlestickPlot(Q */ double QCPFinancial::ohlcSelectTest(const QPointF &pos, const QCPFinancialDataMap::const_iterator &begin, const QCPFinancialDataMap::const_iterator &end) const { - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; } - - double minDistSqr = std::numeric_limits::max(); - QCPFinancialDataMap::const_iterator it; - if (keyAxis->orientation() == Qt::Horizontal) - { - for (it = begin; it != end; ++it) - { - double keyPixel = keyAxis->coordToPixel(it.value().key); - // calculate distance to backbone: - double currentDistSqr = distSqrToLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().high)), QPointF(keyPixel, valueAxis->coordToPixel(it.value().low)), pos); - if (currentDistSqr < minDistSqr) - minDistSqr = currentDistSqr; + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; } + + double minDistSqr = std::numeric_limits::max(); + QCPFinancialDataMap::const_iterator it; + if (keyAxis->orientation() == Qt::Horizontal) + { + for (it = begin; it != end; ++it) + { + double keyPixel = keyAxis->coordToPixel(it.value().key); + // calculate distance to backbone: + double currentDistSqr = distSqrToLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().high)), QPointF(keyPixel, valueAxis->coordToPixel(it.value().low)), pos); + if (currentDistSqr < minDistSqr) + minDistSqr = currentDistSqr; } } else // keyAxis->orientation() == Qt::Vertical { - for (it = begin; it != end; ++it) - { - double keyPixel = keyAxis->coordToPixel(it.value().key); - // calculate distance to backbone: - double currentDistSqr = distSqrToLine(QPointF(valueAxis->coordToPixel(it.value().high), keyPixel), QPointF(valueAxis->coordToPixel(it.value().low), keyPixel), pos); - if (currentDistSqr < minDistSqr) - minDistSqr = currentDistSqr; - } - } - return qSqrt(minDistSqr); + for (it = begin; it != end; ++it) + { + double keyPixel = keyAxis->coordToPixel(it.value().key); + // calculate distance to backbone: + double currentDistSqr = distSqrToLine(QPointF(valueAxis->coordToPixel(it.value().high), keyPixel), QPointF(valueAxis->coordToPixel(it.value().low), keyPixel), pos); + if (currentDistSqr < minDistSqr) + minDistSqr = currentDistSqr; + } + } + return qSqrt(minDistSqr); } /*! \internal @@ -21787,62 +21288,62 @@ double QCPFinancial::ohlcSelectTest(cons */ double QCPFinancial::candlestickSelectTest(const QPointF &pos, const QCPFinancialDataMap::const_iterator &begin, const QCPFinancialDataMap::const_iterator &end) const { - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; } - - double minDistSqr = std::numeric_limits::max(); - QCPFinancialDataMap::const_iterator it; - if (keyAxis->orientation() == Qt::Horizontal) - { - for (it = begin; it != end; ++it) - { - double currentDistSqr; - // determine whether pos is in open-close-box: - QCPRange boxKeyRange(it.value().key-mWidth*0.5, it.value().key+mWidth*0.5); - QCPRange boxValueRange(it.value().close, it.value().open); - double posKey, posValue; - pixelsToCoords(pos, posKey, posValue); - if (boxKeyRange.contains(posKey) && boxValueRange.contains(posValue)) // is in open-close-box - { - currentDistSqr = mParentPlot->selectionTolerance()*0.99 * mParentPlot->selectionTolerance()*0.99; + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; } + + double minDistSqr = std::numeric_limits::max(); + QCPFinancialDataMap::const_iterator it; + if (keyAxis->orientation() == Qt::Horizontal) + { + for (it = begin; it != end; ++it) + { + double currentDistSqr; + // determine whether pos is in open-close-box: + QCPRange boxKeyRange(it.value().key-mWidth*0.5, it.value().key+mWidth*0.5); + QCPRange boxValueRange(it.value().close, it.value().open); + double posKey, posValue; + pixelsToCoords(pos, posKey, posValue); + if (boxKeyRange.contains(posKey) && boxValueRange.contains(posValue)) // is in open-close-box + { + currentDistSqr = mParentPlot->selectionTolerance()*0.99 * mParentPlot->selectionTolerance()*0.99; } else { - // calculate distance to high/low lines: - double keyPixel = keyAxis->coordToPixel(it.value().key); - double highLineDistSqr = distSqrToLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().high)), QPointF(keyPixel, valueAxis->coordToPixel(qMax(it.value().open, it.value().close))), pos); - double lowLineDistSqr = distSqrToLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().low)), QPointF(keyPixel, valueAxis->coordToPixel(qMin(it.value().open, it.value().close))), pos); - currentDistSqr = qMin(highLineDistSqr, lowLineDistSqr); - } - if (currentDistSqr < minDistSqr) - minDistSqr = currentDistSqr; + // calculate distance to high/low lines: + double keyPixel = keyAxis->coordToPixel(it.value().key); + double highLineDistSqr = distSqrToLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().high)), QPointF(keyPixel, valueAxis->coordToPixel(qMax(it.value().open, it.value().close))), pos); + double lowLineDistSqr = distSqrToLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().low)), QPointF(keyPixel, valueAxis->coordToPixel(qMin(it.value().open, it.value().close))), pos); + currentDistSqr = qMin(highLineDistSqr, lowLineDistSqr); + } + if (currentDistSqr < minDistSqr) + minDistSqr = currentDistSqr; } } else // keyAxis->orientation() == Qt::Vertical { - for (it = begin; it != end; ++it) - { - double currentDistSqr; - // determine whether pos is in open-close-box: - QCPRange boxKeyRange(it.value().key-mWidth*0.5, it.value().key+mWidth*0.5); - QCPRange boxValueRange(it.value().close, it.value().open); - double posKey, posValue; - pixelsToCoords(pos, posKey, posValue); - if (boxKeyRange.contains(posKey) && boxValueRange.contains(posValue)) // is in open-close-box - { - currentDistSqr = mParentPlot->selectionTolerance()*0.99 * mParentPlot->selectionTolerance()*0.99; + for (it = begin; it != end; ++it) + { + double currentDistSqr; + // determine whether pos is in open-close-box: + QCPRange boxKeyRange(it.value().key-mWidth*0.5, it.value().key+mWidth*0.5); + QCPRange boxValueRange(it.value().close, it.value().open); + double posKey, posValue; + pixelsToCoords(pos, posKey, posValue); + if (boxKeyRange.contains(posKey) && boxValueRange.contains(posValue)) // is in open-close-box + { + currentDistSqr = mParentPlot->selectionTolerance()*0.99 * mParentPlot->selectionTolerance()*0.99; } else { - // calculate distance to high/low lines: - double keyPixel = keyAxis->coordToPixel(it.value().key); - double highLineDistSqr = distSqrToLine(QPointF(valueAxis->coordToPixel(it.value().high), keyPixel), QPointF(valueAxis->coordToPixel(qMax(it.value().open, it.value().close)), keyPixel), pos); - double lowLineDistSqr = distSqrToLine(QPointF(valueAxis->coordToPixel(it.value().low), keyPixel), QPointF(valueAxis->coordToPixel(qMin(it.value().open, it.value().close)), keyPixel), pos); - currentDistSqr = qMin(highLineDistSqr, lowLineDistSqr); - } - if (currentDistSqr < minDistSqr) - minDistSqr = currentDistSqr; - } - } - return qSqrt(minDistSqr); + // calculate distance to high/low lines: + double keyPixel = keyAxis->coordToPixel(it.value().key); + double highLineDistSqr = distSqrToLine(QPointF(valueAxis->coordToPixel(it.value().high), keyPixel), QPointF(valueAxis->coordToPixel(qMax(it.value().open, it.value().close)), keyPixel), pos); + double lowLineDistSqr = distSqrToLine(QPointF(valueAxis->coordToPixel(it.value().low), keyPixel), QPointF(valueAxis->coordToPixel(qMin(it.value().open, it.value().close)), keyPixel), pos); + currentDistSqr = qMin(highLineDistSqr, lowLineDistSqr); + } + if (currentDistSqr < minDistSqr) + minDistSqr = currentDistSqr; + } + } + return qSqrt(minDistSqr); } /*! \internal @@ -21863,22 +21364,22 @@ double QCPFinancial::candlestickSelectTe */ void QCPFinancial::getVisibleDataBounds(QCPFinancialDataMap::const_iterator &lower, QCPFinancialDataMap::const_iterator &upper) const { - if (!mKeyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; } - if (mData->isEmpty()) - { - lower = mData->constEnd(); - upper = mData->constEnd(); - return; - } - - // get visible data range as QMap iterators - QCPFinancialDataMap::const_iterator lbound = mData->lowerBound(mKeyAxis.data()->range().lower); - QCPFinancialDataMap::const_iterator ubound = mData->upperBound(mKeyAxis.data()->range().upper); - bool lowoutlier = lbound != mData->constBegin(); // indicates whether there exist points below axis range - bool highoutlier = ubound != mData->constEnd(); // indicates whether there exist points above axis range - - lower = (lowoutlier ? lbound-1 : lbound); // data point range that will be actually drawn - upper = (highoutlier ? ubound : ubound-1); // data point range that will be actually drawn + if (!mKeyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; } + if (mData->isEmpty()) + { + lower = mData->constEnd(); + upper = mData->constEnd(); + return; + } + + // get visible data range as QMap iterators + QCPFinancialDataMap::const_iterator lbound = mData->lowerBound(mKeyAxis.data()->range().lower); + QCPFinancialDataMap::const_iterator ubound = mData->upperBound(mKeyAxis.data()->range().upper); + bool lowoutlier = lbound != mData->constBegin(); // indicates whether there exist points below axis range + bool highoutlier = ubound != mData->constEnd(); // indicates whether there exist points above axis range + + lower = (lowoutlier ? lbound-1 : lbound); // data point range that will be actually drawn + upper = (highoutlier ? ubound : ubound-1); // data point range that will be actually drawn } @@ -21900,15 +21401,15 @@ void QCPFinancial::getVisibleDataBounds( The constructed item can be added to the plot with QCustomPlot::addItem. */ QCPItemStraightLine::QCPItemStraightLine(QCustomPlot *parentPlot) : - QCPAbstractItem(parentPlot), - point1(createPosition(QLatin1String("point1"))), - point2(createPosition(QLatin1String("point2"))) -{ - point1->setCoords(0, 0); - point2->setCoords(1, 1); - - setPen(QPen(Qt::black)); - setSelectedPen(QPen(Qt::blue,2)); + QCPAbstractItem(parentPlot), + point1(createPosition(QLatin1String("point1"))), + point2(createPosition(QLatin1String("point2"))) +{ + point1->setCoords(0, 0); + point2->setCoords(1, 1); + + setPen(QPen(Qt::black)); + setSelectedPen(QPen(Qt::blue,2)); } QCPItemStraightLine::~QCPItemStraightLine() @@ -21922,7 +21423,7 @@ QCPItemStraightLine::~QCPItemStraightLin */ void QCPItemStraightLine::setPen(const QPen &pen) { - mPen = pen; + mPen = pen; } /*! @@ -21932,32 +21433,32 @@ void QCPItemStraightLine::setPen(const Q */ void QCPItemStraightLine::setSelectedPen(const QPen &pen) { - mSelectedPen = pen; + mSelectedPen = pen; } /* inherits documentation from base class */ double QCPItemStraightLine::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - Q_UNUSED(details) - if (onlySelectable && !mSelectable) - return -1; - - return distToStraightLine(QVector2D(point1->pixelPoint()), QVector2D(point2->pixelPoint()-point1->pixelPoint()), QVector2D(pos)); + Q_UNUSED(details) + if (onlySelectable && !mSelectable) + return -1; + + return distToStraightLine(QVector2D(point1->pixelPoint()), QVector2D(point2->pixelPoint()-point1->pixelPoint()), QVector2D(pos)); } /* inherits documentation from base class */ void QCPItemStraightLine::draw(QCPPainter *painter) { - QVector2D start(point1->pixelPoint()); - QVector2D end(point2->pixelPoint()); - // get visible segment of straight line inside clipRect: - double clipPad = mainPen().widthF(); - QLineF line = getRectClippedStraightLine(start, end-start, clipRect().adjusted(-clipPad, -clipPad, clipPad, clipPad)); - // paint visible segment, if existent: - if (!line.isNull()) - { - painter->setPen(mainPen()); - painter->drawLine(line); + QVector2D start(point1->pixelPoint()); + QVector2D end(point2->pixelPoint()); + // get visible segment of straight line inside clipRect: + double clipPad = mainPen().widthF(); + QLineF line = getRectClippedStraightLine(start, end-start, clipRect().adjusted(-clipPad, -clipPad, clipPad, clipPad)); + // paint visible segment, if existent: + if (!line.isNull()) + { + painter->setPen(mainPen()); + painter->drawLine(line); } } @@ -21970,7 +21471,7 @@ void QCPItemStraightLine::draw(QCPPainte */ double QCPItemStraightLine::distToStraightLine(const QVector2D &base, const QVector2D &vec, const QVector2D &point) const { - return qAbs((base.y()-point.y())*vec.x()-(base.x()-point.x())*vec.y())/vec.length(); + return qAbs((base.y()-point.y())*vec.x()-(base.x()-point.x())*vec.y())/vec.length(); } /*! \internal @@ -21982,81 +21483,81 @@ double QCPItemStraightLine::distToStraig */ QLineF QCPItemStraightLine::getRectClippedStraightLine(const QVector2D &base, const QVector2D &vec, const QRect &rect) const { - double bx, by; - double gamma; - QLineF result; - if (vec.x() == 0 && vec.y() == 0) - return result; - if (qFuzzyIsNull(vec.x())) // line is vertical - { - // check top of rect: - bx = rect.left(); - by = rect.top(); - gamma = base.x()-bx + (by-base.y())*vec.x()/vec.y(); - if (gamma >= 0 && gamma <= rect.width()) - result.setLine(bx+gamma, rect.top(), bx+gamma, rect.bottom()); // no need to check bottom because we know line is vertical + double bx, by; + double gamma; + QLineF result; + if (vec.x() == 0 && vec.y() == 0) + return result; + if (qFuzzyIsNull(vec.x())) // line is vertical + { + // check top of rect: + bx = rect.left(); + by = rect.top(); + gamma = base.x()-bx + (by-base.y())*vec.x()/vec.y(); + if (gamma >= 0 && gamma <= rect.width()) + result.setLine(bx+gamma, rect.top(), bx+gamma, rect.bottom()); // no need to check bottom because we know line is vertical } else if (qFuzzyIsNull(vec.y())) // line is horizontal { - // check left of rect: - bx = rect.left(); - by = rect.top(); - gamma = base.y()-by + (bx-base.x())*vec.y()/vec.x(); - if (gamma >= 0 && gamma <= rect.height()) - result.setLine(rect.left(), by+gamma, rect.right(), by+gamma); // no need to check right because we know line is horizontal + // check left of rect: + bx = rect.left(); + by = rect.top(); + gamma = base.y()-by + (bx-base.x())*vec.y()/vec.x(); + if (gamma >= 0 && gamma <= rect.height()) + result.setLine(rect.left(), by+gamma, rect.right(), by+gamma); // no need to check right because we know line is horizontal } else // line is skewed { - QList pointVectors; - // check top of rect: - bx = rect.left(); - by = rect.top(); - gamma = base.x()-bx + (by-base.y())*vec.x()/vec.y(); - if (gamma >= 0 && gamma <= rect.width()) - pointVectors.append(QVector2D(bx+gamma, by)); - // check bottom of rect: - bx = rect.left(); - by = rect.bottom(); - gamma = base.x()-bx + (by-base.y())*vec.x()/vec.y(); - if (gamma >= 0 && gamma <= rect.width()) - pointVectors.append(QVector2D(bx+gamma, by)); - // check left of rect: - bx = rect.left(); - by = rect.top(); - gamma = base.y()-by + (bx-base.x())*vec.y()/vec.x(); - if (gamma >= 0 && gamma <= rect.height()) - pointVectors.append(QVector2D(bx, by+gamma)); - // check right of rect: - bx = rect.right(); - by = rect.top(); - gamma = base.y()-by + (bx-base.x())*vec.y()/vec.x(); - if (gamma >= 0 && gamma <= rect.height()) - pointVectors.append(QVector2D(bx, by+gamma)); - - // evaluate points: - if (pointVectors.size() == 2) - { - result.setPoints(pointVectors.at(0).toPointF(), pointVectors.at(1).toPointF()); + QList pointVectors; + // check top of rect: + bx = rect.left(); + by = rect.top(); + gamma = base.x()-bx + (by-base.y())*vec.x()/vec.y(); + if (gamma >= 0 && gamma <= rect.width()) + pointVectors.append(QVector2D(bx+gamma, by)); + // check bottom of rect: + bx = rect.left(); + by = rect.bottom(); + gamma = base.x()-bx + (by-base.y())*vec.x()/vec.y(); + if (gamma >= 0 && gamma <= rect.width()) + pointVectors.append(QVector2D(bx+gamma, by)); + // check left of rect: + bx = rect.left(); + by = rect.top(); + gamma = base.y()-by + (bx-base.x())*vec.y()/vec.x(); + if (gamma >= 0 && gamma <= rect.height()) + pointVectors.append(QVector2D(bx, by+gamma)); + // check right of rect: + bx = rect.right(); + by = rect.top(); + gamma = base.y()-by + (bx-base.x())*vec.y()/vec.x(); + if (gamma >= 0 && gamma <= rect.height()) + pointVectors.append(QVector2D(bx, by+gamma)); + + // evaluate points: + if (pointVectors.size() == 2) + { + result.setPoints(pointVectors.at(0).toPointF(), pointVectors.at(1).toPointF()); } else if (pointVectors.size() > 2) { - // line probably goes through corner of rect, and we got two points there. single out the point pair with greatest distance: - double distSqrMax = 0; - QVector2D pv1, pv2; - for (int i=0; i distSqrMax) + double distSqr = (pointVectors.at(i)-pointVectors.at(k)).lengthSquared(); + if (distSqr > distSqrMax) { - pv1 = pointVectors.at(i); - pv2 = pointVectors.at(k); - distSqrMax = distSqr; + pv1 = pointVectors.at(i); + pv2 = pointVectors.at(k); + distSqrMax = distSqr; } } } - result.setPoints(pv1.toPointF(), pv2.toPointF()); - } - } - return result; + result.setPoints(pv1.toPointF(), pv2.toPointF()); + } + } + return result; } /*! \internal @@ -22066,7 +21567,7 @@ QLineF QCPItemStraightLine::getRectClipp */ QPen QCPItemStraightLine::mainPen() const { - return mSelected ? mSelectedPen : mPen; + return mSelected ? mSelectedPen : mPen; } @@ -22090,15 +21591,15 @@ QPen QCPItemStraightLine::mainPen() cons The constructed item can be added to the plot with QCustomPlot::addItem. */ QCPItemLine::QCPItemLine(QCustomPlot *parentPlot) : - QCPAbstractItem(parentPlot), - start(createPosition(QLatin1String("start"))), - end(createPosition(QLatin1String("end"))) -{ - start->setCoords(0, 0); - end->setCoords(1, 1); - - setPen(QPen(Qt::black)); - setSelectedPen(QPen(Qt::blue,2)); + QCPAbstractItem(parentPlot), + start(createPosition(QLatin1String("start"))), + end(createPosition(QLatin1String("end"))) +{ + start->setCoords(0, 0); + end->setCoords(1, 1); + + setPen(QPen(Qt::black)); + setSelectedPen(QPen(Qt::blue,2)); } QCPItemLine::~QCPItemLine() @@ -22112,7 +21613,7 @@ QCPItemLine::~QCPItemLine() */ void QCPItemLine::setPen(const QPen &pen) { - mPen = pen; + mPen = pen; } /*! @@ -22122,7 +21623,7 @@ void QCPItemLine::setPen(const QPen &pen */ void QCPItemLine::setSelectedPen(const QPen &pen) { - mSelectedPen = pen; + mSelectedPen = pen; } /*! @@ -22135,7 +21636,7 @@ void QCPItemLine::setSelectedPen(const Q */ void QCPItemLine::setHead(const QCPLineEnding &head) { - mHead = head; + mHead = head; } /*! @@ -22148,40 +21649,40 @@ void QCPItemLine::setHead(const QCPLineE */ void QCPItemLine::setTail(const QCPLineEnding &tail) { - mTail = tail; + mTail = tail; } /* inherits documentation from base class */ double QCPItemLine::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - Q_UNUSED(details) - if (onlySelectable && !mSelectable) - return -1; - - return qSqrt(distSqrToLine(start->pixelPoint(), end->pixelPoint(), pos)); + Q_UNUSED(details) + if (onlySelectable && !mSelectable) + return -1; + + return qSqrt(distSqrToLine(start->pixelPoint(), end->pixelPoint(), pos)); } /* inherits documentation from base class */ void QCPItemLine::draw(QCPPainter *painter) { - QVector2D startVec(start->pixelPoint()); - QVector2D endVec(end->pixelPoint()); - if (startVec.toPoint() == endVec.toPoint()) - return; - // get visible segment of straight line inside clipRect: - double clipPad = qMax(mHead.boundingDistance(), mTail.boundingDistance()); - clipPad = qMax(clipPad, (double)mainPen().widthF()); - QLineF line = getRectClippedLine(startVec, endVec, clipRect().adjusted(-clipPad, -clipPad, clipPad, clipPad)); - // paint visible segment, if existent: - if (!line.isNull()) - { - painter->setPen(mainPen()); - painter->drawLine(line); - painter->setBrush(Qt::SolidPattern); - if (mTail.style() != QCPLineEnding::esNone) - mTail.draw(painter, startVec, startVec-endVec); - if (mHead.style() != QCPLineEnding::esNone) - mHead.draw(painter, endVec, endVec-startVec); + QVector2D startVec(start->pixelPoint()); + QVector2D endVec(end->pixelPoint()); + if (startVec.toPoint() == endVec.toPoint()) + return; + // get visible segment of straight line inside clipRect: + double clipPad = qMax(mHead.boundingDistance(), mTail.boundingDistance()); + clipPad = qMax(clipPad, (double)mainPen().widthF()); + QLineF line = getRectClippedLine(startVec, endVec, clipRect().adjusted(-clipPad, -clipPad, clipPad, clipPad)); + // paint visible segment, if existent: + if (!line.isNull()) + { + painter->setPen(mainPen()); + painter->drawLine(line); + painter->setBrush(Qt::SolidPattern); + if (mTail.style() != QCPLineEnding::esNone) + mTail.draw(painter, startVec, startVec-endVec); + if (mHead.style() != QCPLineEnding::esNone) + mHead.draw(painter, endVec, endVec-startVec); } } @@ -22194,95 +21695,95 @@ void QCPItemLine::draw(QCPPainter *paint */ QLineF QCPItemLine::getRectClippedLine(const QVector2D &start, const QVector2D &end, const QRect &rect) const { - bool containsStart = rect.contains(start.x(), start.y()); - bool containsEnd = rect.contains(end.x(), end.y()); - if (containsStart && containsEnd) - return QLineF(start.toPointF(), end.toPointF()); - - QVector2D base = start; - QVector2D vec = end-start; - double bx, by; - double gamma, mu; - QLineF result; - QList pointVectors; - - if (!qFuzzyIsNull(vec.y())) // line is not horizontal - { - // check top of rect: - bx = rect.left(); - by = rect.top(); - mu = (by-base.y())/vec.y(); - if (mu >= 0 && mu <= 1) - { - gamma = base.x()-bx + mu*vec.x(); - if (gamma >= 0 && gamma <= rect.width()) - pointVectors.append(QVector2D(bx+gamma, by)); - } - // check bottom of rect: - bx = rect.left(); - by = rect.bottom(); - mu = (by-base.y())/vec.y(); - if (mu >= 0 && mu <= 1) - { - gamma = base.x()-bx + mu*vec.x(); - if (gamma >= 0 && gamma <= rect.width()) - pointVectors.append(QVector2D(bx+gamma, by)); - } - } - if (!qFuzzyIsNull(vec.x())) // line is not vertical - { - // check left of rect: - bx = rect.left(); - by = rect.top(); - mu = (bx-base.x())/vec.x(); - if (mu >= 0 && mu <= 1) - { - gamma = base.y()-by + mu*vec.y(); - if (gamma >= 0 && gamma <= rect.height()) - pointVectors.append(QVector2D(bx, by+gamma)); - } - // check right of rect: - bx = rect.right(); - by = rect.top(); - mu = (bx-base.x())/vec.x(); - if (mu >= 0 && mu <= 1) - { - gamma = base.y()-by + mu*vec.y(); - if (gamma >= 0 && gamma <= rect.height()) - pointVectors.append(QVector2D(bx, by+gamma)); - } - } - - if (containsStart) - pointVectors.append(start); - if (containsEnd) - pointVectors.append(end); - - // evaluate points: - if (pointVectors.size() == 2) - { - result.setPoints(pointVectors.at(0).toPointF(), pointVectors.at(1).toPointF()); + bool containsStart = rect.contains(start.x(), start.y()); + bool containsEnd = rect.contains(end.x(), end.y()); + if (containsStart && containsEnd) + return QLineF(start.toPointF(), end.toPointF()); + + QVector2D base = start; + QVector2D vec = end-start; + double bx, by; + double gamma, mu; + QLineF result; + QList pointVectors; + + if (!qFuzzyIsNull(vec.y())) // line is not horizontal + { + // check top of rect: + bx = rect.left(); + by = rect.top(); + mu = (by-base.y())/vec.y(); + if (mu >= 0 && mu <= 1) + { + gamma = base.x()-bx + mu*vec.x(); + if (gamma >= 0 && gamma <= rect.width()) + pointVectors.append(QVector2D(bx+gamma, by)); + } + // check bottom of rect: + bx = rect.left(); + by = rect.bottom(); + mu = (by-base.y())/vec.y(); + if (mu >= 0 && mu <= 1) + { + gamma = base.x()-bx + mu*vec.x(); + if (gamma >= 0 && gamma <= rect.width()) + pointVectors.append(QVector2D(bx+gamma, by)); + } + } + if (!qFuzzyIsNull(vec.x())) // line is not vertical + { + // check left of rect: + bx = rect.left(); + by = rect.top(); + mu = (bx-base.x())/vec.x(); + if (mu >= 0 && mu <= 1) + { + gamma = base.y()-by + mu*vec.y(); + if (gamma >= 0 && gamma <= rect.height()) + pointVectors.append(QVector2D(bx, by+gamma)); + } + // check right of rect: + bx = rect.right(); + by = rect.top(); + mu = (bx-base.x())/vec.x(); + if (mu >= 0 && mu <= 1) + { + gamma = base.y()-by + mu*vec.y(); + if (gamma >= 0 && gamma <= rect.height()) + pointVectors.append(QVector2D(bx, by+gamma)); + } + } + + if (containsStart) + pointVectors.append(start); + if (containsEnd) + pointVectors.append(end); + + // evaluate points: + if (pointVectors.size() == 2) + { + result.setPoints(pointVectors.at(0).toPointF(), pointVectors.at(1).toPointF()); } else if (pointVectors.size() > 2) { - // line probably goes through corner of rect, and we got two points there. single out the point pair with greatest distance: - double distSqrMax = 0; - QVector2D pv1, pv2; - for (int i=0; i distSqrMax) + // line probably goes through corner of rect, and we got two points there. single out the point pair with greatest distance: + double distSqrMax = 0; + QVector2D pv1, pv2; + for (int i=0; i distSqrMax) { - pv1 = pointVectors.at(i); - pv2 = pointVectors.at(k); - distSqrMax = distSqr; + pv1 = pointVectors.at(i); + pv2 = pointVectors.at(k); + distSqrMax = distSqr; } } } - result.setPoints(pv1.toPointF(), pv2.toPointF()); - } - return result; + result.setPoints(pv1.toPointF(), pv2.toPointF()); + } + return result; } /*! \internal @@ -22292,7 +21793,7 @@ QLineF QCPItemLine::getRectClippedLine(c */ QPen QCPItemLine::mainPen() const { - return mSelected ? mSelectedPen : mPen; + return mSelected ? mSelectedPen : mPen; } @@ -22323,19 +21824,19 @@ QPen QCPItemLine::mainPen() const The constructed item can be added to the plot with QCustomPlot::addItem. */ QCPItemCurve::QCPItemCurve(QCustomPlot *parentPlot) : - QCPAbstractItem(parentPlot), - start(createPosition(QLatin1String("start"))), - startDir(createPosition(QLatin1String("startDir"))), - endDir(createPosition(QLatin1String("endDir"))), - end(createPosition(QLatin1String("end"))) -{ - start->setCoords(0, 0); - startDir->setCoords(0.5, 0); - endDir->setCoords(0, 0.5); - end->setCoords(1, 1); - - setPen(QPen(Qt::black)); - setSelectedPen(QPen(Qt::blue,2)); + QCPAbstractItem(parentPlot), + start(createPosition(QLatin1String("start"))), + startDir(createPosition(QLatin1String("startDir"))), + endDir(createPosition(QLatin1String("endDir"))), + end(createPosition(QLatin1String("end"))) +{ + start->setCoords(0, 0); + startDir->setCoords(0.5, 0); + endDir->setCoords(0, 0.5); + end->setCoords(1, 1); + + setPen(QPen(Qt::black)); + setSelectedPen(QPen(Qt::blue,2)); } QCPItemCurve::~QCPItemCurve() @@ -22349,7 +21850,7 @@ QCPItemCurve::~QCPItemCurve() */ void QCPItemCurve::setPen(const QPen &pen) { - mPen = pen; + mPen = pen; } /*! @@ -22359,7 +21860,7 @@ void QCPItemCurve::setPen(const QPen &pe */ void QCPItemCurve::setSelectedPen(const QPen &pen) { - mSelectedPen = pen; + mSelectedPen = pen; } /*! @@ -22372,7 +21873,7 @@ void QCPItemCurve::setSelectedPen(const */ void QCPItemCurve::setHead(const QCPLineEnding &head) { - mHead = head; + mHead = head; } /*! @@ -22385,62 +21886,62 @@ void QCPItemCurve::setHead(const QCPLine */ void QCPItemCurve::setTail(const QCPLineEnding &tail) { - mTail = tail; + mTail = tail; } /* inherits documentation from base class */ double QCPItemCurve::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - Q_UNUSED(details) - if (onlySelectable && !mSelectable) - return -1; - - QPointF startVec(start->pixelPoint()); - QPointF startDirVec(startDir->pixelPoint()); - QPointF endDirVec(endDir->pixelPoint()); - QPointF endVec(end->pixelPoint()); - - QPainterPath cubicPath(startVec); - cubicPath.cubicTo(startDirVec, endDirVec, endVec); - - QPolygonF polygon = cubicPath.toSubpathPolygons().first(); - double minDistSqr = std::numeric_limits::max(); - for (int i=1; ipixelPoint()); + QPointF startDirVec(startDir->pixelPoint()); + QPointF endDirVec(endDir->pixelPoint()); + QPointF endVec(end->pixelPoint()); + + QPainterPath cubicPath(startVec); + cubicPath.cubicTo(startDirVec, endDirVec, endVec); + + QPolygonF polygon = cubicPath.toSubpathPolygons().first(); + double minDistSqr = std::numeric_limits::max(); + for (int i=1; ipixelPoint()); - QPointF startDirVec(startDir->pixelPoint()); - QPointF endDirVec(endDir->pixelPoint()); - QPointF endVec(end->pixelPoint()); - if (QVector2D(endVec-startVec).length() > 1e10f) // too large curves cause crash - return; - - QPainterPath cubicPath(startVec); - cubicPath.cubicTo(startDirVec, endDirVec, endVec); - - // paint visible segment, if existent: - QRect clip = clipRect().adjusted(-mainPen().widthF(), -mainPen().widthF(), mainPen().widthF(), mainPen().widthF()); - QRect cubicRect = cubicPath.controlPointRect().toRect(); - if (cubicRect.isEmpty()) // may happen when start and end exactly on same x or y position - cubicRect.adjust(0, 0, 1, 1); - if (clip.intersects(cubicRect)) - { - painter->setPen(mainPen()); - painter->drawPath(cubicPath); - painter->setBrush(Qt::SolidPattern); - if (mTail.style() != QCPLineEnding::esNone) - mTail.draw(painter, QVector2D(startVec), M_PI-cubicPath.angleAtPercent(0)/180.0*M_PI); - if (mHead.style() != QCPLineEnding::esNone) - mHead.draw(painter, QVector2D(endVec), -cubicPath.angleAtPercent(1)/180.0*M_PI); + QPointF startVec(start->pixelPoint()); + QPointF startDirVec(startDir->pixelPoint()); + QPointF endDirVec(endDir->pixelPoint()); + QPointF endVec(end->pixelPoint()); + if (QVector2D(endVec-startVec).length() > 1e10f) // too large curves cause crash + return; + + QPainterPath cubicPath(startVec); + cubicPath.cubicTo(startDirVec, endDirVec, endVec); + + // paint visible segment, if existent: + QRect clip = clipRect().adjusted(-mainPen().widthF(), -mainPen().widthF(), mainPen().widthF(), mainPen().widthF()); + QRect cubicRect = cubicPath.controlPointRect().toRect(); + if (cubicRect.isEmpty()) // may happen when start and end exactly on same x or y position + cubicRect.adjust(0, 0, 1, 1); + if (clip.intersects(cubicRect)) + { + painter->setPen(mainPen()); + painter->drawPath(cubicPath); + painter->setBrush(Qt::SolidPattern); + if (mTail.style() != QCPLineEnding::esNone) + mTail.draw(painter, QVector2D(startVec), M_PI-cubicPath.angleAtPercent(0)/180.0*M_PI); + if (mHead.style() != QCPLineEnding::esNone) + mHead.draw(painter, QVector2D(endVec), -cubicPath.angleAtPercent(1)/180.0*M_PI); } } @@ -22451,7 +21952,7 @@ void QCPItemCurve::draw(QCPPainter *pain */ QPen QCPItemCurve::mainPen() const { - return mSelected ? mSelectedPen : mPen; + return mSelected ? mSelectedPen : mPen; } @@ -22473,23 +21974,23 @@ QPen QCPItemCurve::mainPen() const The constructed item can be added to the plot with QCustomPlot::addItem. */ QCPItemRect::QCPItemRect(QCustomPlot *parentPlot) : - QCPAbstractItem(parentPlot), - topLeft(createPosition(QLatin1String("topLeft"))), - bottomRight(createPosition(QLatin1String("bottomRight"))), - top(createAnchor(QLatin1String("top"), aiTop)), - topRight(createAnchor(QLatin1String("topRight"), aiTopRight)), - right(createAnchor(QLatin1String("right"), aiRight)), - bottom(createAnchor(QLatin1String("bottom"), aiBottom)), - bottomLeft(createAnchor(QLatin1String("bottomLeft"), aiBottomLeft)), - left(createAnchor(QLatin1String("left"), aiLeft)) -{ - topLeft->setCoords(0, 1); - bottomRight->setCoords(1, 0); - - setPen(QPen(Qt::black)); - setSelectedPen(QPen(Qt::blue,2)); - setBrush(Qt::NoBrush); - setSelectedBrush(Qt::NoBrush); + QCPAbstractItem(parentPlot), + topLeft(createPosition(QLatin1String("topLeft"))), + bottomRight(createPosition(QLatin1String("bottomRight"))), + top(createAnchor(QLatin1String("top"), aiTop)), + topRight(createAnchor(QLatin1String("topRight"), aiTopRight)), + right(createAnchor(QLatin1String("right"), aiRight)), + bottom(createAnchor(QLatin1String("bottom"), aiBottom)), + bottomLeft(createAnchor(QLatin1String("bottomLeft"), aiBottomLeft)), + left(createAnchor(QLatin1String("left"), aiLeft)) +{ + topLeft->setCoords(0, 1); + bottomRight->setCoords(1, 0); + + setPen(QPen(Qt::black)); + setSelectedPen(QPen(Qt::blue,2)); + setBrush(Qt::NoBrush); + setSelectedBrush(Qt::NoBrush); } QCPItemRect::~QCPItemRect() @@ -22503,7 +22004,7 @@ QCPItemRect::~QCPItemRect() */ void QCPItemRect::setPen(const QPen &pen) { - mPen = pen; + mPen = pen; } /*! @@ -22513,7 +22014,7 @@ void QCPItemRect::setPen(const QPen &pen */ void QCPItemRect::setSelectedPen(const QPen &pen) { - mSelectedPen = pen; + mSelectedPen = pen; } /*! @@ -22524,7 +22025,7 @@ void QCPItemRect::setSelectedPen(const Q */ void QCPItemRect::setBrush(const QBrush &brush) { - mBrush = brush; + mBrush = brush; } /*! @@ -22535,44 +22036,44 @@ void QCPItemRect::setBrush(const QBrush */ void QCPItemRect::setSelectedBrush(const QBrush &brush) { - mSelectedBrush = brush; + mSelectedBrush = brush; } /* inherits documentation from base class */ double QCPItemRect::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - Q_UNUSED(details) - if (onlySelectable && !mSelectable) - return -1; - - QRectF rect = QRectF(topLeft->pixelPoint(), bottomRight->pixelPoint()).normalized(); - bool filledRect = mBrush.style() != Qt::NoBrush && mBrush.color().alpha() != 0; - return rectSelectTest(rect, pos, filledRect); + Q_UNUSED(details) + if (onlySelectable && !mSelectable) + return -1; + + QRectF rect = QRectF(topLeft->pixelPoint(), bottomRight->pixelPoint()).normalized(); + bool filledRect = mBrush.style() != Qt::NoBrush && mBrush.color().alpha() != 0; + return rectSelectTest(rect, pos, filledRect); } /* inherits documentation from base class */ void QCPItemRect::draw(QCPPainter *painter) { - QPointF p1 = topLeft->pixelPoint(); - QPointF p2 = bottomRight->pixelPoint(); - if (p1.toPoint() == p2.toPoint()) - return; - QRectF rect = QRectF(p1, p2).normalized(); - double clipPad = mainPen().widthF(); - QRectF boundingRect = rect.adjusted(-clipPad, -clipPad, clipPad, clipPad); - if (boundingRect.intersects(clipRect())) // only draw if bounding rect of rect item is visible in cliprect - { - painter->setPen(mainPen()); - painter->setBrush(mainBrush()); - painter->drawRect(rect); + QPointF p1 = topLeft->pixelPoint(); + QPointF p2 = bottomRight->pixelPoint(); + if (p1.toPoint() == p2.toPoint()) + return; + QRectF rect = QRectF(p1, p2).normalized(); + double clipPad = mainPen().widthF(); + QRectF boundingRect = rect.adjusted(-clipPad, -clipPad, clipPad, clipPad); + if (boundingRect.intersects(clipRect())) // only draw if bounding rect of rect item is visible in cliprect + { + painter->setPen(mainPen()); + painter->setBrush(mainBrush()); + painter->drawRect(rect); } } /* inherits documentation from base class */ QPointF QCPItemRect::anchorPixelPoint(int anchorId) const { - QRectF rect = QRectF(topLeft->pixelPoint(), bottomRight->pixelPoint()); - switch (anchorId) + QRectF rect = QRectF(topLeft->pixelPoint(), bottomRight->pixelPoint()); + switch (anchorId) { case aiTop: return (rect.topLeft()+rect.topRight())*0.5; case aiTopRight: return rect.topRight(); @@ -22581,9 +22082,9 @@ QPointF QCPItemRect::anchorPixelPoint(in case aiBottomLeft: return rect.bottomLeft(); case aiLeft: return (rect.topLeft()+rect.bottomLeft())*0.5; } - - qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId; - return QPointF(); + + qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId; + return QPointF(); } /*! \internal @@ -22593,7 +22094,7 @@ QPointF QCPItemRect::anchorPixelPoint(in */ QPen QCPItemRect::mainPen() const { - return mSelected ? mSelectedPen : mPen; + return mSelected ? mSelectedPen : mPen; } /*! \internal @@ -22603,7 +22104,7 @@ QPen QCPItemRect::mainPen() const */ QBrush QCPItemRect::mainBrush() const { - return mSelected ? mSelectedBrush : mBrush; + return mSelected ? mSelectedBrush : mBrush; } @@ -22631,30 +22132,30 @@ QBrush QCPItemRect::mainBrush() const The constructed item can be added to the plot with QCustomPlot::addItem. */ QCPItemText::QCPItemText(QCustomPlot *parentPlot) : - QCPAbstractItem(parentPlot), - position(createPosition(QLatin1String("position"))), - topLeft(createAnchor(QLatin1String("topLeft"), aiTopLeft)), - top(createAnchor(QLatin1String("top"), aiTop)), - topRight(createAnchor(QLatin1String("topRight"), aiTopRight)), - right(createAnchor(QLatin1String("right"), aiRight)), - bottomRight(createAnchor(QLatin1String("bottomRight"), aiBottomRight)), - bottom(createAnchor(QLatin1String("bottom"), aiBottom)), - bottomLeft(createAnchor(QLatin1String("bottomLeft"), aiBottomLeft)), - left(createAnchor(QLatin1String("left"), aiLeft)) -{ - position->setCoords(0, 0); - - setRotation(0); - setTextAlignment(Qt::AlignTop|Qt::AlignHCenter); - setPositionAlignment(Qt::AlignCenter); - setText(QLatin1String("text")); - - setPen(Qt::NoPen); - setSelectedPen(Qt::NoPen); - setBrush(Qt::NoBrush); - setSelectedBrush(Qt::NoBrush); - setColor(Qt::black); - setSelectedColor(Qt::blue); + QCPAbstractItem(parentPlot), + position(createPosition(QLatin1String("position"))), + topLeft(createAnchor(QLatin1String("topLeft"), aiTopLeft)), + top(createAnchor(QLatin1String("top"), aiTop)), + topRight(createAnchor(QLatin1String("topRight"), aiTopRight)), + right(createAnchor(QLatin1String("right"), aiRight)), + bottomRight(createAnchor(QLatin1String("bottomRight"), aiBottomRight)), + bottom(createAnchor(QLatin1String("bottom"), aiBottom)), + bottomLeft(createAnchor(QLatin1String("bottomLeft"), aiBottomLeft)), + left(createAnchor(QLatin1String("left"), aiLeft)) +{ + position->setCoords(0, 0); + + setRotation(0); + setTextAlignment(Qt::AlignTop|Qt::AlignHCenter); + setPositionAlignment(Qt::AlignCenter); + setText(QLatin1String("text")); + + setPen(Qt::NoPen); + setSelectedPen(Qt::NoPen); + setBrush(Qt::NoBrush); + setSelectedBrush(Qt::NoBrush); + setColor(Qt::black); + setSelectedColor(Qt::blue); } QCPItemText::~QCPItemText() @@ -22666,7 +22167,7 @@ QCPItemText::~QCPItemText() */ void QCPItemText::setColor(const QColor &color) { - mColor = color; + mColor = color; } /*! @@ -22674,7 +22175,7 @@ void QCPItemText::setColor(const QColor */ void QCPItemText::setSelectedColor(const QColor &color) { - mSelectedColor = color; + mSelectedColor = color; } /*! @@ -22685,7 +22186,7 @@ void QCPItemText::setSelectedColor(const */ void QCPItemText::setPen(const QPen &pen) { - mPen = pen; + mPen = pen; } /*! @@ -22696,7 +22197,7 @@ void QCPItemText::setPen(const QPen &pen */ void QCPItemText::setSelectedPen(const QPen &pen) { - mSelectedPen = pen; + mSelectedPen = pen; } /*! @@ -22707,7 +22208,7 @@ void QCPItemText::setSelectedPen(const Q */ void QCPItemText::setBrush(const QBrush &brush) { - mBrush = brush; + mBrush = brush; } /*! @@ -22718,7 +22219,7 @@ void QCPItemText::setBrush(const QBrush */ void QCPItemText::setSelectedBrush(const QBrush &brush) { - mSelectedBrush = brush; + mSelectedBrush = brush; } /*! @@ -22728,7 +22229,7 @@ void QCPItemText::setSelectedBrush(const */ void QCPItemText::setFont(const QFont &font) { - mFont = font; + mFont = font; } /*! @@ -22738,7 +22239,7 @@ void QCPItemText::setFont(const QFont &f */ void QCPItemText::setSelectedFont(const QFont &font) { - mSelectedFont = font; + mSelectedFont = font; } /*! @@ -22749,7 +22250,7 @@ void QCPItemText::setSelectedFont(const */ void QCPItemText::setText(const QString &text) { - mText = text; + mText = text; } /*! @@ -22766,7 +22267,7 @@ void QCPItemText::setText(const QString */ void QCPItemText::setPositionAlignment(Qt::Alignment alignment) { - mPositionAlignment = alignment; + mPositionAlignment = alignment; } /*! @@ -22774,7 +22275,7 @@ void QCPItemText::setPositionAlignment(Q */ void QCPItemText::setTextAlignment(Qt::Alignment alignment) { - mTextAlignment = alignment; + mTextAlignment = alignment; } /*! @@ -22783,7 +22284,7 @@ void QCPItemText::setTextAlignment(Qt::A */ void QCPItemText::setRotation(double degrees) { - mRotation = degrees; + mRotation = degrees; } /*! @@ -22792,82 +22293,82 @@ void QCPItemText::setRotation(double deg */ void QCPItemText::setPadding(const QMargins &padding) { - mPadding = padding; + mPadding = padding; } /* inherits documentation from base class */ double QCPItemText::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - Q_UNUSED(details) - if (onlySelectable && !mSelectable) - return -1; - - // The rect may be rotated, so we transform the actual clicked pos to the rotated - // coordinate system, so we can use the normal rectSelectTest function for non-rotated rects: - QPointF positionPixels(position->pixelPoint()); - QTransform inputTransform; - inputTransform.translate(positionPixels.x(), positionPixels.y()); - inputTransform.rotate(-mRotation); - inputTransform.translate(-positionPixels.x(), -positionPixels.y()); - QPointF rotatedPos = inputTransform.map(pos); - QFontMetrics fontMetrics(mFont); - QRect textRect = fontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip|mTextAlignment, mText); - QRect textBoxRect = textRect.adjusted(-mPadding.left(), -mPadding.top(), mPadding.right(), mPadding.bottom()); - QPointF textPos = getTextDrawPoint(positionPixels, textBoxRect, mPositionAlignment); - textBoxRect.moveTopLeft(textPos.toPoint()); - - return rectSelectTest(textBoxRect, rotatedPos, true); + Q_UNUSED(details) + if (onlySelectable && !mSelectable) + return -1; + + // The rect may be rotated, so we transform the actual clicked pos to the rotated + // coordinate system, so we can use the normal rectSelectTest function for non-rotated rects: + QPointF positionPixels(position->pixelPoint()); + QTransform inputTransform; + inputTransform.translate(positionPixels.x(), positionPixels.y()); + inputTransform.rotate(-mRotation); + inputTransform.translate(-positionPixels.x(), -positionPixels.y()); + QPointF rotatedPos = inputTransform.map(pos); + QFontMetrics fontMetrics(mFont); + QRect textRect = fontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip|mTextAlignment, mText); + QRect textBoxRect = textRect.adjusted(-mPadding.left(), -mPadding.top(), mPadding.right(), mPadding.bottom()); + QPointF textPos = getTextDrawPoint(positionPixels, textBoxRect, mPositionAlignment); + textBoxRect.moveTopLeft(textPos.toPoint()); + + return rectSelectTest(textBoxRect, rotatedPos, true); } /* inherits documentation from base class */ void QCPItemText::draw(QCPPainter *painter) { - QPointF pos(position->pixelPoint()); - QTransform transform = painter->transform(); - transform.translate(pos.x(), pos.y()); - if (!qFuzzyIsNull(mRotation)) - transform.rotate(mRotation); - painter->setFont(mainFont()); - QRect textRect = painter->fontMetrics().boundingRect(0, 0, 0, 0, Qt::TextDontClip|mTextAlignment, mText); - QRect textBoxRect = textRect.adjusted(-mPadding.left(), -mPadding.top(), mPadding.right(), mPadding.bottom()); - QPointF textPos = getTextDrawPoint(QPointF(0, 0), textBoxRect, mPositionAlignment); // 0, 0 because the transform does the translation - textRect.moveTopLeft(textPos.toPoint()+QPoint(mPadding.left(), mPadding.top())); - textBoxRect.moveTopLeft(textPos.toPoint()); - double clipPad = mainPen().widthF(); - QRect boundingRect = textBoxRect.adjusted(-clipPad, -clipPad, clipPad, clipPad); - if (transform.mapRect(boundingRect).intersects(painter->transform().mapRect(clipRect()))) - { - painter->setTransform(transform); - if ((mainBrush().style() != Qt::NoBrush && mainBrush().color().alpha() != 0) || - (mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0)) - { - painter->setPen(mainPen()); - painter->setBrush(mainBrush()); - painter->drawRect(textBoxRect); - } - painter->setBrush(Qt::NoBrush); - painter->setPen(QPen(mainColor())); - painter->drawText(textRect, Qt::TextDontClip|mTextAlignment, mText); + QPointF pos(position->pixelPoint()); + QTransform transform = painter->transform(); + transform.translate(pos.x(), pos.y()); + if (!qFuzzyIsNull(mRotation)) + transform.rotate(mRotation); + painter->setFont(mainFont()); + QRect textRect = painter->fontMetrics().boundingRect(0, 0, 0, 0, Qt::TextDontClip|mTextAlignment, mText); + QRect textBoxRect = textRect.adjusted(-mPadding.left(), -mPadding.top(), mPadding.right(), mPadding.bottom()); + QPointF textPos = getTextDrawPoint(QPointF(0, 0), textBoxRect, mPositionAlignment); // 0, 0 because the transform does the translation + textRect.moveTopLeft(textPos.toPoint()+QPoint(mPadding.left(), mPadding.top())); + textBoxRect.moveTopLeft(textPos.toPoint()); + double clipPad = mainPen().widthF(); + QRect boundingRect = textBoxRect.adjusted(-clipPad, -clipPad, clipPad, clipPad); + if (transform.mapRect(boundingRect).intersects(painter->transform().mapRect(clipRect()))) + { + painter->setTransform(transform); + if ((mainBrush().style() != Qt::NoBrush && mainBrush().color().alpha() != 0) || + (mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0)) + { + painter->setPen(mainPen()); + painter->setBrush(mainBrush()); + painter->drawRect(textBoxRect); + } + painter->setBrush(Qt::NoBrush); + painter->setPen(QPen(mainColor())); + painter->drawText(textRect, Qt::TextDontClip|mTextAlignment, mText); } } /* inherits documentation from base class */ QPointF QCPItemText::anchorPixelPoint(int anchorId) const { - // get actual rect points (pretty much copied from draw function): - QPointF pos(position->pixelPoint()); - QTransform transform; - transform.translate(pos.x(), pos.y()); - if (!qFuzzyIsNull(mRotation)) - transform.rotate(mRotation); - QFontMetrics fontMetrics(mainFont()); - QRect textRect = fontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip|mTextAlignment, mText); - QRectF textBoxRect = textRect.adjusted(-mPadding.left(), -mPadding.top(), mPadding.right(), mPadding.bottom()); - QPointF textPos = getTextDrawPoint(QPointF(0, 0), textBoxRect, mPositionAlignment); // 0, 0 because the transform does the translation - textBoxRect.moveTopLeft(textPos.toPoint()); - QPolygonF rectPoly = transform.map(QPolygonF(textBoxRect)); - - switch (anchorId) + // get actual rect points (pretty much copied from draw function): + QPointF pos(position->pixelPoint()); + QTransform transform; + transform.translate(pos.x(), pos.y()); + if (!qFuzzyIsNull(mRotation)) + transform.rotate(mRotation); + QFontMetrics fontMetrics(mainFont()); + QRect textRect = fontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip|mTextAlignment, mText); + QRectF textBoxRect = textRect.adjusted(-mPadding.left(), -mPadding.top(), mPadding.right(), mPadding.bottom()); + QPointF textPos = getTextDrawPoint(QPointF(0, 0), textBoxRect, mPositionAlignment); // 0, 0 because the transform does the translation + textBoxRect.moveTopLeft(textPos.toPoint()); + QPolygonF rectPoly = transform.map(QPolygonF(textBoxRect)); + + switch (anchorId) { case aiTopLeft: return rectPoly.at(0); case aiTop: return (rectPoly.at(0)+rectPoly.at(1))*0.5; @@ -22878,9 +22379,9 @@ QPointF QCPItemText::anchorPixelPoint(in case aiBottomLeft: return rectPoly.at(3); case aiLeft: return (rectPoly.at(3)+rectPoly.at(0))*0.5; } - - qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId; - return QPointF(); + + qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId; + return QPointF(); } /*! \internal @@ -22895,19 +22396,19 @@ QPointF QCPItemText::anchorPixelPoint(in */ QPointF QCPItemText::getTextDrawPoint(const QPointF &pos, const QRectF &rect, Qt::Alignment positionAlignment) const { - if (positionAlignment == 0 || positionAlignment == (Qt::AlignLeft|Qt::AlignTop)) - return pos; - - QPointF result = pos; // start at top left - if (positionAlignment.testFlag(Qt::AlignHCenter)) - result.rx() -= rect.width()/2.0; - else if (positionAlignment.testFlag(Qt::AlignRight)) - result.rx() -= rect.width(); - if (positionAlignment.testFlag(Qt::AlignVCenter)) - result.ry() -= rect.height()/2.0; - else if (positionAlignment.testFlag(Qt::AlignBottom)) - result.ry() -= rect.height(); - return result; + if (positionAlignment == 0 || positionAlignment == (Qt::AlignLeft|Qt::AlignTop)) + return pos; + + QPointF result = pos; // start at top left + if (positionAlignment.testFlag(Qt::AlignHCenter)) + result.rx() -= rect.width()/2.0; + else if (positionAlignment.testFlag(Qt::AlignRight)) + result.rx() -= rect.width(); + if (positionAlignment.testFlag(Qt::AlignVCenter)) + result.ry() -= rect.height()/2.0; + else if (positionAlignment.testFlag(Qt::AlignBottom)) + result.ry() -= rect.height(); + return result; } /*! \internal @@ -22917,7 +22418,7 @@ QPointF QCPItemText::getTextDrawPoint(co */ QFont QCPItemText::mainFont() const { - return mSelected ? mSelectedFont : mFont; + return mSelected ? mSelectedFont : mFont; } /*! \internal @@ -22927,7 +22428,7 @@ QFont QCPItemText::mainFont() const */ QColor QCPItemText::mainColor() const { - return mSelected ? mSelectedColor : mColor; + return mSelected ? mSelectedColor : mColor; } /*! \internal @@ -22937,7 +22438,7 @@ QColor QCPItemText::mainColor() const */ QPen QCPItemText::mainPen() const { - return mSelected ? mSelectedPen : mPen; + return mSelected ? mSelectedPen : mPen; } /*! \internal @@ -22947,7 +22448,7 @@ QPen QCPItemText::mainPen() const */ QBrush QCPItemText::mainBrush() const { - return mSelected ? mSelectedBrush : mBrush; + return mSelected ? mSelectedBrush : mBrush; } @@ -22969,26 +22470,26 @@ QBrush QCPItemText::mainBrush() const The constructed item can be added to the plot with QCustomPlot::addItem. */ QCPItemEllipse::QCPItemEllipse(QCustomPlot *parentPlot) : - QCPAbstractItem(parentPlot), - topLeft(createPosition(QLatin1String("topLeft"))), - bottomRight(createPosition(QLatin1String("bottomRight"))), - topLeftRim(createAnchor(QLatin1String("topLeftRim"), aiTopLeftRim)), - top(createAnchor(QLatin1String("top"), aiTop)), - topRightRim(createAnchor(QLatin1String("topRightRim"), aiTopRightRim)), - right(createAnchor(QLatin1String("right"), aiRight)), - bottomRightRim(createAnchor(QLatin1String("bottomRightRim"), aiBottomRightRim)), - bottom(createAnchor(QLatin1String("bottom"), aiBottom)), - bottomLeftRim(createAnchor(QLatin1String("bottomLeftRim"), aiBottomLeftRim)), - left(createAnchor(QLatin1String("left"), aiLeft)), - center(createAnchor(QLatin1String("center"), aiCenter)) -{ - topLeft->setCoords(0, 1); - bottomRight->setCoords(1, 0); - - setPen(QPen(Qt::black)); - setSelectedPen(QPen(Qt::blue, 2)); - setBrush(Qt::NoBrush); - setSelectedBrush(Qt::NoBrush); + QCPAbstractItem(parentPlot), + topLeft(createPosition(QLatin1String("topLeft"))), + bottomRight(createPosition(QLatin1String("bottomRight"))), + topLeftRim(createAnchor(QLatin1String("topLeftRim"), aiTopLeftRim)), + top(createAnchor(QLatin1String("top"), aiTop)), + topRightRim(createAnchor(QLatin1String("topRightRim"), aiTopRightRim)), + right(createAnchor(QLatin1String("right"), aiRight)), + bottomRightRim(createAnchor(QLatin1String("bottomRightRim"), aiBottomRightRim)), + bottom(createAnchor(QLatin1String("bottom"), aiBottom)), + bottomLeftRim(createAnchor(QLatin1String("bottomLeftRim"), aiBottomLeftRim)), + left(createAnchor(QLatin1String("left"), aiLeft)), + center(createAnchor(QLatin1String("center"), aiCenter)) +{ + topLeft->setCoords(0, 1); + bottomRight->setCoords(1, 0); + + setPen(QPen(Qt::black)); + setSelectedPen(QPen(Qt::blue, 2)); + setBrush(Qt::NoBrush); + setSelectedBrush(Qt::NoBrush); } QCPItemEllipse::~QCPItemEllipse() @@ -23002,7 +22503,7 @@ QCPItemEllipse::~QCPItemEllipse() */ void QCPItemEllipse::setPen(const QPen &pen) { - mPen = pen; + mPen = pen; } /*! @@ -23012,7 +22513,7 @@ void QCPItemEllipse::setPen(const QPen & */ void QCPItemEllipse::setSelectedPen(const QPen &pen) { - mSelectedPen = pen; + mSelectedPen = pen; } /*! @@ -23023,7 +22524,7 @@ void QCPItemEllipse::setSelectedPen(cons */ void QCPItemEllipse::setBrush(const QBrush &brush) { - mBrush = brush; + mBrush = brush; } /*! @@ -23034,61 +22535,61 @@ void QCPItemEllipse::setBrush(const QBru */ void QCPItemEllipse::setSelectedBrush(const QBrush &brush) { - mSelectedBrush = brush; + mSelectedBrush = brush; } /* inherits documentation from base class */ double QCPItemEllipse::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - Q_UNUSED(details) - if (onlySelectable && !mSelectable) - return -1; - - double result = -1; - QPointF p1 = topLeft->pixelPoint(); - QPointF p2 = bottomRight->pixelPoint(); - QPointF center((p1+p2)/2.0); - double a = qAbs(p1.x()-p2.x())/2.0; - double b = qAbs(p1.y()-p2.y())/2.0; - double x = pos.x()-center.x(); - double y = pos.y()-center.y(); - - // distance to border: - double c = 1.0/qSqrt(x*x/(a*a)+y*y/(b*b)); - result = qAbs(c-1)*qSqrt(x*x+y*y); - // filled ellipse, allow click inside to count as hit: - if (result > mParentPlot->selectionTolerance()*0.99 && mBrush.style() != Qt::NoBrush && mBrush.color().alpha() != 0) - { - if (x*x/(a*a) + y*y/(b*b) <= 1) - result = mParentPlot->selectionTolerance()*0.99; - } - return result; + Q_UNUSED(details) + if (onlySelectable && !mSelectable) + return -1; + + double result = -1; + QPointF p1 = topLeft->pixelPoint(); + QPointF p2 = bottomRight->pixelPoint(); + QPointF center((p1+p2)/2.0); + double a = qAbs(p1.x()-p2.x())/2.0; + double b = qAbs(p1.y()-p2.y())/2.0; + double x = pos.x()-center.x(); + double y = pos.y()-center.y(); + + // distance to border: + double c = 1.0/qSqrt(x*x/(a*a)+y*y/(b*b)); + result = qAbs(c-1)*qSqrt(x*x+y*y); + // filled ellipse, allow click inside to count as hit: + if (result > mParentPlot->selectionTolerance()*0.99 && mBrush.style() != Qt::NoBrush && mBrush.color().alpha() != 0) + { + if (x*x/(a*a) + y*y/(b*b) <= 1) + result = mParentPlot->selectionTolerance()*0.99; + } + return result; } /* inherits documentation from base class */ void QCPItemEllipse::draw(QCPPainter *painter) { - QPointF p1 = topLeft->pixelPoint(); - QPointF p2 = bottomRight->pixelPoint(); - if (p1.toPoint() == p2.toPoint()) - return; - QRectF ellipseRect = QRectF(p1, p2).normalized(); - QRect clip = clipRect().adjusted(-mainPen().widthF(), -mainPen().widthF(), mainPen().widthF(), mainPen().widthF()); - if (ellipseRect.intersects(clip)) // only draw if bounding rect of ellipse is visible in cliprect - { - painter->setPen(mainPen()); - painter->setBrush(mainBrush()); + QPointF p1 = topLeft->pixelPoint(); + QPointF p2 = bottomRight->pixelPoint(); + if (p1.toPoint() == p2.toPoint()) + return; + QRectF ellipseRect = QRectF(p1, p2).normalized(); + QRect clip = clipRect().adjusted(-mainPen().widthF(), -mainPen().widthF(), mainPen().widthF(), mainPen().widthF()); + if (ellipseRect.intersects(clip)) // only draw if bounding rect of ellipse is visible in cliprect + { + painter->setPen(mainPen()); + painter->setBrush(mainBrush()); #ifdef __EXCEPTIONS - try // drawEllipse sometimes throws exceptions if ellipse is too big - { + try // drawEllipse sometimes throws exceptions if ellipse is too big + { #endif - painter->drawEllipse(ellipseRect); + painter->drawEllipse(ellipseRect); #ifdef __EXCEPTIONS - } catch (...) - { - qDebug() << Q_FUNC_INFO << "Item too large for memory, setting invisible"; - setVisible(false); - } + } catch (...) + { + qDebug() << Q_FUNC_INFO << "Item too large for memory, setting invisible"; + setVisible(false); + } #endif } } @@ -23096,8 +22597,8 @@ void QCPItemEllipse::draw(QCPPainter *pa /* inherits documentation from base class */ QPointF QCPItemEllipse::anchorPixelPoint(int anchorId) const { - QRectF rect = QRectF(topLeft->pixelPoint(), bottomRight->pixelPoint()); - switch (anchorId) + QRectF rect = QRectF(topLeft->pixelPoint(), bottomRight->pixelPoint()); + switch (anchorId) { case aiTopLeftRim: return rect.center()+(rect.topLeft()-rect.center())*1/qSqrt(2); case aiTop: return (rect.topLeft()+rect.topRight())*0.5; @@ -23109,9 +22610,9 @@ QPointF QCPItemEllipse::anchorPixelPoint case aiLeft: return (rect.topLeft()+rect.bottomLeft())*0.5; case aiCenter: return (rect.topLeft()+rect.bottomRight())*0.5; } - - qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId; - return QPointF(); + + qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId; + return QPointF(); } /*! \internal @@ -23121,7 +22622,7 @@ QPointF QCPItemEllipse::anchorPixelPoint */ QPen QCPItemEllipse::mainPen() const { - return mSelected ? mSelectedPen : mPen; + return mSelected ? mSelectedPen : mPen; } /*! \internal @@ -23131,7 +22632,7 @@ QPen QCPItemEllipse::mainPen() const */ QBrush QCPItemEllipse::mainBrush() const { - return mSelected ? mSelectedBrush : mBrush; + return mSelected ? mSelectedBrush : mBrush; } @@ -23159,22 +22660,22 @@ QBrush QCPItemEllipse::mainBrush() const The constructed item can be added to the plot with QCustomPlot::addItem. */ QCPItemPixmap::QCPItemPixmap(QCustomPlot *parentPlot) : - QCPAbstractItem(parentPlot), - topLeft(createPosition(QLatin1String("topLeft"))), - bottomRight(createPosition(QLatin1String("bottomRight"))), - top(createAnchor(QLatin1String("top"), aiTop)), - topRight(createAnchor(QLatin1String("topRight"), aiTopRight)), - right(createAnchor(QLatin1String("right"), aiRight)), - bottom(createAnchor(QLatin1String("bottom"), aiBottom)), - bottomLeft(createAnchor(QLatin1String("bottomLeft"), aiBottomLeft)), - left(createAnchor(QLatin1String("left"), aiLeft)) -{ - topLeft->setCoords(0, 1); - bottomRight->setCoords(1, 0); - - setPen(Qt::NoPen); - setSelectedPen(QPen(Qt::blue)); - setScaled(false, Qt::KeepAspectRatio, Qt::SmoothTransformation); + QCPAbstractItem(parentPlot), + topLeft(createPosition(QLatin1String("topLeft"))), + bottomRight(createPosition(QLatin1String("bottomRight"))), + top(createAnchor(QLatin1String("top"), aiTop)), + topRight(createAnchor(QLatin1String("topRight"), aiTopRight)), + right(createAnchor(QLatin1String("right"), aiRight)), + bottom(createAnchor(QLatin1String("bottom"), aiBottom)), + bottomLeft(createAnchor(QLatin1String("bottomLeft"), aiBottomLeft)), + left(createAnchor(QLatin1String("left"), aiLeft)) +{ + topLeft->setCoords(0, 1); + bottomRight->setCoords(1, 0); + + setPen(Qt::NoPen); + setSelectedPen(QPen(Qt::blue)); + setScaled(false, Qt::KeepAspectRatio, Qt::SmoothTransformation); } QCPItemPixmap::~QCPItemPixmap() @@ -23186,9 +22687,9 @@ QCPItemPixmap::~QCPItemPixmap() */ void QCPItemPixmap::setPixmap(const QPixmap &pixmap) { - mPixmap = pixmap; - if (mPixmap.isNull()) - qDebug() << Q_FUNC_INFO << "pixmap is null"; + mPixmap = pixmap; + if (mPixmap.isNull()) + qDebug() << Q_FUNC_INFO << "pixmap is null"; } /*! @@ -23197,10 +22698,10 @@ void QCPItemPixmap::setPixmap(const QPix */ void QCPItemPixmap::setScaled(bool scaled, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformationMode) { - mScaled = scaled; - mAspectRatioMode = aspectRatioMode; - mTransformationMode = transformationMode; - updateScaledPixmap(); + mScaled = scaled; + mAspectRatioMode = aspectRatioMode; + mTransformationMode = transformationMode; + updateScaledPixmap(); } /*! @@ -23210,7 +22711,7 @@ void QCPItemPixmap::setScaled(bool scale */ void QCPItemPixmap::setPen(const QPen &pen) { - mPen = pen; + mPen = pen; } /*! @@ -23220,37 +22721,37 @@ void QCPItemPixmap::setPen(const QPen &p */ void QCPItemPixmap::setSelectedPen(const QPen &pen) { - mSelectedPen = pen; + mSelectedPen = pen; } /* inherits documentation from base class */ double QCPItemPixmap::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - Q_UNUSED(details) - if (onlySelectable && !mSelectable) - return -1; - - return rectSelectTest(getFinalRect(), pos, true); + Q_UNUSED(details) + if (onlySelectable && !mSelectable) + return -1; + + return rectSelectTest(getFinalRect(), pos, true); } /* inherits documentation from base class */ void QCPItemPixmap::draw(QCPPainter *painter) { - bool flipHorz = false; - bool flipVert = false; - QRect rect = getFinalRect(&flipHorz, &flipVert); - double clipPad = mainPen().style() == Qt::NoPen ? 0 : mainPen().widthF(); - QRect boundingRect = rect.adjusted(-clipPad, -clipPad, clipPad, clipPad); - if (boundingRect.intersects(clipRect())) - { - updateScaledPixmap(rect, flipHorz, flipVert); - painter->drawPixmap(rect.topLeft(), mScaled ? mScaledPixmap : mPixmap); - QPen pen = mainPen(); - if (pen.style() != Qt::NoPen) - { - painter->setPen(pen); - painter->setBrush(Qt::NoBrush); - painter->drawRect(rect); + bool flipHorz = false; + bool flipVert = false; + QRect rect = getFinalRect(&flipHorz, &flipVert); + double clipPad = mainPen().style() == Qt::NoPen ? 0 : mainPen().widthF(); + QRect boundingRect = rect.adjusted(-clipPad, -clipPad, clipPad, clipPad); + if (boundingRect.intersects(clipRect())) + { + updateScaledPixmap(rect, flipHorz, flipVert); + painter->drawPixmap(rect.topLeft(), mScaled ? mScaledPixmap : mPixmap); + QPen pen = mainPen(); + if (pen.style() != Qt::NoPen) + { + painter->setPen(pen); + painter->setBrush(Qt::NoBrush); + painter->drawRect(rect); } } } @@ -23258,17 +22759,17 @@ void QCPItemPixmap::draw(QCPPainter *pai /* inherits documentation from base class */ QPointF QCPItemPixmap::anchorPixelPoint(int anchorId) const { - bool flipHorz; - bool flipVert; - QRect rect = getFinalRect(&flipHorz, &flipVert); - // we actually want denormal rects (negative width/height) here, so restore - // the flipped state: - if (flipHorz) - rect.adjust(rect.width(), 0, -rect.width(), 0); - if (flipVert) - rect.adjust(0, rect.height(), 0, -rect.height()); - - switch (anchorId) + bool flipHorz; + bool flipVert; + QRect rect = getFinalRect(&flipHorz, &flipVert); + // we actually want denormal rects (negative width/height) here, so restore + // the flipped state: + if (flipHorz) + rect.adjust(rect.width(), 0, -rect.width(), 0); + if (flipVert) + rect.adjust(0, rect.height(), 0, -rect.height()); + + switch (anchorId) { case aiTop: return (rect.topLeft()+rect.topRight())*0.5; case aiTopRight: return rect.topRight(); @@ -23277,9 +22778,9 @@ QPointF QCPItemPixmap::anchorPixelPoint( case aiBottomLeft: return rect.bottomLeft(); case aiLeft: return (rect.topLeft()+rect.bottomLeft())*0.5;; } - - qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId; - return QPointF(); + + qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId; + return QPointF(); } /*! \internal @@ -23297,21 +22798,21 @@ QPointF QCPItemPixmap::anchorPixelPoint( */ void QCPItemPixmap::updateScaledPixmap(QRect finalRect, bool flipHorz, bool flipVert) { - if (mPixmap.isNull()) - return; - - if (mScaled) - { - if (finalRect.isNull()) - finalRect = getFinalRect(&flipHorz, &flipVert); - if (finalRect.size() != mScaledPixmap.size()) - { - mScaledPixmap = mPixmap.scaled(finalRect.size(), mAspectRatioMode, mTransformationMode); - if (flipHorz || flipVert) - mScaledPixmap = QPixmap::fromImage(mScaledPixmap.toImage().mirrored(flipHorz, flipVert)); + if (mPixmap.isNull()) + return; + + if (mScaled) + { + if (finalRect.isNull()) + finalRect = getFinalRect(&flipHorz, &flipVert); + if (finalRect.size() != mScaledPixmap.size()) + { + mScaledPixmap = mPixmap.scaled(finalRect.size(), mAspectRatioMode, mTransformationMode); + if (flipHorz || flipVert) + mScaledPixmap = QPixmap::fromImage(mScaledPixmap.toImage().mirrored(flipHorz, flipVert)); } } else if (!mScaledPixmap.isNull()) - mScaledPixmap = QPixmap(); + mScaledPixmap = QPixmap(); } /*! \internal @@ -23330,41 +22831,41 @@ void QCPItemPixmap::updateScaledPixmap(Q */ QRect QCPItemPixmap::getFinalRect(bool *flippedHorz, bool *flippedVert) const { - QRect result; - bool flipHorz = false; - bool flipVert = false; - QPoint p1 = topLeft->pixelPoint().toPoint(); - QPoint p2 = bottomRight->pixelPoint().toPoint(); - if (p1 == p2) - return QRect(p1, QSize(0, 0)); - if (mScaled) - { - QSize newSize = QSize(p2.x()-p1.x(), p2.y()-p1.y()); - QPoint topLeft = p1; - if (newSize.width() < 0) - { - flipHorz = true; - newSize.rwidth() *= -1; - topLeft.setX(p2.x()); - } - if (newSize.height() < 0) - { - flipVert = true; - newSize.rheight() *= -1; - topLeft.setY(p2.y()); - } - QSize scaledSize = mPixmap.size(); - scaledSize.scale(newSize, mAspectRatioMode); - result = QRect(topLeft, scaledSize); - } else - { - result = QRect(p1, mPixmap.size()); - } - if (flippedHorz) - *flippedHorz = flipHorz; - if (flippedVert) - *flippedVert = flipVert; - return result; + QRect result; + bool flipHorz = false; + bool flipVert = false; + QPoint p1 = topLeft->pixelPoint().toPoint(); + QPoint p2 = bottomRight->pixelPoint().toPoint(); + if (p1 == p2) + return QRect(p1, QSize(0, 0)); + if (mScaled) + { + QSize newSize = QSize(p2.x()-p1.x(), p2.y()-p1.y()); + QPoint topLeft = p1; + if (newSize.width() < 0) + { + flipHorz = true; + newSize.rwidth() *= -1; + topLeft.setX(p2.x()); + } + if (newSize.height() < 0) + { + flipVert = true; + newSize.rheight() *= -1; + topLeft.setY(p2.y()); + } + QSize scaledSize = mPixmap.size(); + scaledSize.scale(newSize, mAspectRatioMode); + result = QRect(topLeft, scaledSize); + } else + { + result = QRect(p1, mPixmap.size()); + } + if (flippedHorz) + *flippedHorz = flipHorz; + if (flippedVert) + *flippedVert = flipVert; + return result; } /*! \internal @@ -23374,7 +22875,7 @@ QRect QCPItemPixmap::getFinalRect(bool * */ QPen QCPItemPixmap::mainPen() const { - return mSelected ? mSelectedPen : mPen; + return mSelected ? mSelectedPen : mPen; } @@ -23418,20 +22919,20 @@ QPen QCPItemPixmap::mainPen() const The constructed item can be added to the plot with QCustomPlot::addItem. */ QCPItemTracer::QCPItemTracer(QCustomPlot *parentPlot) : - QCPAbstractItem(parentPlot), - position(createPosition(QLatin1String("position"))), - mGraph(0) -{ - position->setCoords(0, 0); - - setBrush(Qt::NoBrush); - setSelectedBrush(Qt::NoBrush); - setPen(QPen(Qt::black)); - setSelectedPen(QPen(Qt::blue, 2)); - setStyle(tsCrosshair); - setSize(6); - setInterpolating(false); - setGraphKey(0); + QCPAbstractItem(parentPlot), + position(createPosition(QLatin1String("position"))), + mGraph(0) +{ + position->setCoords(0, 0); + + setBrush(Qt::NoBrush); + setSelectedBrush(Qt::NoBrush); + setPen(QPen(Qt::black)); + setSelectedPen(QPen(Qt::blue, 2)); + setStyle(tsCrosshair); + setSize(6); + setInterpolating(false); + setGraphKey(0); } QCPItemTracer::~QCPItemTracer() @@ -23445,7 +22946,7 @@ QCPItemTracer::~QCPItemTracer() */ void QCPItemTracer::setPen(const QPen &pen) { - mPen = pen; + mPen = pen; } /*! @@ -23455,7 +22956,7 @@ void QCPItemTracer::setPen(const QPen &p */ void QCPItemTracer::setSelectedPen(const QPen &pen) { - mSelectedPen = pen; + mSelectedPen = pen; } /*! @@ -23465,7 +22966,7 @@ void QCPItemTracer::setSelectedPen(const */ void QCPItemTracer::setBrush(const QBrush &brush) { - mBrush = brush; + mBrush = brush; } /*! @@ -23475,7 +22976,7 @@ void QCPItemTracer::setBrush(const QBrus */ void QCPItemTracer::setSelectedBrush(const QBrush &brush) { - mSelectedBrush = brush; + mSelectedBrush = brush; } /*! @@ -23484,7 +22985,7 @@ void QCPItemTracer::setSelectedBrush(con */ void QCPItemTracer::setSize(double size) { - mSize = size; + mSize = size; } /*! @@ -23495,7 +22996,7 @@ void QCPItemTracer::setSize(double size) */ void QCPItemTracer::setStyle(QCPItemTracer::TracerStyle style) { - mStyle = style; + mStyle = style; } /*! @@ -23510,19 +23011,19 @@ void QCPItemTracer::setStyle(QCPItemTrac */ void QCPItemTracer::setGraph(QCPGraph *graph) { - if (graph) - { - if (graph->parentPlot() == mParentPlot) - { - position->setType(QCPItemPosition::ptPlotCoords); - position->setAxes(graph->keyAxis(), graph->valueAxis()); - mGraph = graph; - updatePosition(); + if (graph) + { + if (graph->parentPlot() == mParentPlot) + { + position->setType(QCPItemPosition::ptPlotCoords); + position->setAxes(graph->keyAxis(), graph->valueAxis()); + mGraph = graph; + updatePosition(); } else - qDebug() << Q_FUNC_INFO << "graph isn't in same QCustomPlot instance as this item"; - } else - { - mGraph = 0; + qDebug() << Q_FUNC_INFO << "graph isn't in same QCustomPlot instance as this item"; + } else + { + mGraph = 0; } } @@ -23537,7 +23038,7 @@ void QCPItemTracer::setGraph(QCPGraph *g */ void QCPItemTracer::setGraphKey(double key) { - mGraphKey = key; + mGraphKey = key; } /*! @@ -23553,110 +23054,110 @@ void QCPItemTracer::setGraphKey(double k */ void QCPItemTracer::setInterpolating(bool enabled) { - mInterpolating = enabled; + mInterpolating = enabled; } /* inherits documentation from base class */ double QCPItemTracer::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - Q_UNUSED(details) - if (onlySelectable && !mSelectable) - return -1; - - QPointF center(position->pixelPoint()); - double w = mSize/2.0; - QRect clip = clipRect(); - switch (mStyle) + Q_UNUSED(details) + if (onlySelectable && !mSelectable) + return -1; + + QPointF center(position->pixelPoint()); + double w = mSize/2.0; + QRect clip = clipRect(); + switch (mStyle) { case tsNone: return -1; case tsPlus: - { + { if (clipRect().intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect())) - return qSqrt(qMin(distSqrToLine(center+QPointF(-w, 0), center+QPointF(w, 0), pos), - distSqrToLine(center+QPointF(0, -w), center+QPointF(0, w), pos))); - break; - } + return qSqrt(qMin(distSqrToLine(center+QPointF(-w, 0), center+QPointF(w, 0), pos), + distSqrToLine(center+QPointF(0, -w), center+QPointF(0, w), pos))); + break; + } case tsCrosshair: - { + { return qSqrt(qMin(distSqrToLine(QPointF(clip.left(), center.y()), QPointF(clip.right(), center.y()), pos), distSqrToLine(QPointF(center.x(), clip.top()), QPointF(center.x(), clip.bottom()), pos))); - } + } case tsCircle: - { + { if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect())) - { + { // distance to border: double centerDist = QVector2D(center-pos).length(); double circleLine = w; double result = qAbs(centerDist-circleLine); // filled ellipse, allow click inside to count as hit: if (result > mParentPlot->selectionTolerance()*0.99 && mBrush.style() != Qt::NoBrush && mBrush.color().alpha() != 0) - { + { if (centerDist <= circleLine) - result = mParentPlot->selectionTolerance()*0.99; - } + result = mParentPlot->selectionTolerance()*0.99; + } return result; - } - break; - } + } + break; + } case tsSquare: - { + { if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect())) - { + { QRectF rect = QRectF(center-QPointF(w, w), center+QPointF(w, w)); bool filledRect = mBrush.style() != Qt::NoBrush && mBrush.color().alpha() != 0; return rectSelectTest(rect, pos, filledRect); - } - break; - } - } - return -1; + } + break; + } + } + return -1; } /* inherits documentation from base class */ void QCPItemTracer::draw(QCPPainter *painter) { - updatePosition(); - if (mStyle == tsNone) - return; - - painter->setPen(mainPen()); - painter->setBrush(mainBrush()); - QPointF center(position->pixelPoint()); - double w = mSize/2.0; - QRect clip = clipRect(); - switch (mStyle) + updatePosition(); + if (mStyle == tsNone) + return; + + painter->setPen(mainPen()); + painter->setBrush(mainBrush()); + QPointF center(position->pixelPoint()); + double w = mSize/2.0; + QRect clip = clipRect(); + switch (mStyle) { case tsNone: return; case tsPlus: - { + { if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect())) - { + { painter->drawLine(QLineF(center+QPointF(-w, 0), center+QPointF(w, 0))); painter->drawLine(QLineF(center+QPointF(0, -w), center+QPointF(0, w))); - } - break; - } + } + break; + } case tsCrosshair: - { + { if (center.y() > clip.top() && center.y() < clip.bottom()) - painter->drawLine(QLineF(clip.left(), center.y(), clip.right(), center.y())); + painter->drawLine(QLineF(clip.left(), center.y(), clip.right(), center.y())); if (center.x() > clip.left() && center.x() < clip.right()) - painter->drawLine(QLineF(center.x(), clip.top(), center.x(), clip.bottom())); - break; - } + painter->drawLine(QLineF(center.x(), clip.top(), center.x(), clip.bottom())); + break; + } case tsCircle: - { + { if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect())) - painter->drawEllipse(center, w, w); - break; - } + painter->drawEllipse(center, w, w); + break; + } case tsSquare: - { + { if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect())) - painter->drawRect(QRectF(center-QPointF(w, w), center+QPointF(w, w))); - break; - } + painter->drawRect(QRectF(center-QPointF(w, w), center+QPointF(w, w))); + break; + } } } @@ -23674,49 +23175,49 @@ void QCPItemTracer::draw(QCPPainter *pai */ void QCPItemTracer::updatePosition() { - if (mGraph) - { - if (mParentPlot->hasPlottable(mGraph)) - { - if (mGraph->data()->size() > 1) - { - QCPDataMap::const_iterator first = mGraph->data()->constBegin(); - QCPDataMap::const_iterator last = mGraph->data()->constEnd()-1; - if (mGraphKey < first.key()) - position->setCoords(first.key(), first.value().value); - else if (mGraphKey > last.key()) - position->setCoords(last.key(), last.value().value); - else + if (mGraph) + { + if (mParentPlot->hasPlottable(mGraph)) + { + if (mGraph->data()->size() > 1) + { + QCPDataMap::const_iterator first = mGraph->data()->constBegin(); + QCPDataMap::const_iterator last = mGraph->data()->constEnd()-1; + if (mGraphKey < first.key()) + position->setCoords(first.key(), first.value().value); + else if (mGraphKey > last.key()) + position->setCoords(last.key(), last.value().value); + else { - QCPDataMap::const_iterator it = mGraph->data()->lowerBound(mGraphKey); - if (it != first) // mGraphKey is somewhere between iterators + QCPDataMap::const_iterator it = mGraph->data()->lowerBound(mGraphKey); + if (it != first) // mGraphKey is somewhere between iterators { - QCPDataMap::const_iterator prevIt = it-1; - if (mInterpolating) + QCPDataMap::const_iterator prevIt = it-1; + if (mInterpolating) { - // interpolate between iterators around mGraphKey: - double slope = 0; - if (!qFuzzyCompare((double)it.key(), (double)prevIt.key())) - slope = (it.value().value-prevIt.value().value)/(it.key()-prevIt.key()); - position->setCoords(mGraphKey, (mGraphKey-prevIt.key())*slope+prevIt.value().value); + // interpolate between iterators around mGraphKey: + double slope = 0; + if (!qFuzzyCompare((double)it.key(), (double)prevIt.key())) + slope = (it.value().value-prevIt.value().value)/(it.key()-prevIt.key()); + position->setCoords(mGraphKey, (mGraphKey-prevIt.key())*slope+prevIt.value().value); } else { - // find iterator with key closest to mGraphKey: - if (mGraphKey < (prevIt.key()+it.key())*0.5) - it = prevIt; - position->setCoords(it.key(), it.value().value); + // find iterator with key closest to mGraphKey: + if (mGraphKey < (prevIt.key()+it.key())*0.5) + it = prevIt; + position->setCoords(it.key(), it.value().value); } } else // mGraphKey is exactly on first iterator - position->setCoords(it.key(), it.value().value); + position->setCoords(it.key(), it.value().value); } } else if (mGraph->data()->size() == 1) { - QCPDataMap::const_iterator it = mGraph->data()->constBegin(); - position->setCoords(it.key(), it.value().value); + QCPDataMap::const_iterator it = mGraph->data()->constBegin(); + position->setCoords(it.key(), it.value().value); } else - qDebug() << Q_FUNC_INFO << "graph has no data"; + qDebug() << Q_FUNC_INFO << "graph has no data"; } else - qDebug() << Q_FUNC_INFO << "graph not contained in QCustomPlot instance (anymore)"; + qDebug() << Q_FUNC_INFO << "graph not contained in QCustomPlot instance (anymore)"; } } @@ -23727,7 +23228,7 @@ void QCPItemTracer::updatePosition() */ QPen QCPItemTracer::mainPen() const { - return mSelected ? mSelectedPen : mPen; + return mSelected ? mSelectedPen : mPen; } /*! \internal @@ -23737,7 +23238,7 @@ QPen QCPItemTracer::mainPen() const */ QBrush QCPItemTracer::mainBrush() const { - return mSelected ? mSelectedBrush : mBrush; + return mSelected ? mSelectedBrush : mBrush; } @@ -23771,18 +23272,18 @@ QBrush QCPItemTracer::mainBrush() const The constructed item can be added to the plot with QCustomPlot::addItem. */ QCPItemBracket::QCPItemBracket(QCustomPlot *parentPlot) : - QCPAbstractItem(parentPlot), - left(createPosition(QLatin1String("left"))), - right(createPosition(QLatin1String("right"))), - center(createAnchor(QLatin1String("center"), aiCenter)) -{ - left->setCoords(0, 0); - right->setCoords(1, 1); - - setPen(QPen(Qt::black)); - setSelectedPen(QPen(Qt::blue, 2)); - setLength(8); - setStyle(bsCalligraphic); + QCPAbstractItem(parentPlot), + left(createPosition(QLatin1String("left"))), + right(createPosition(QLatin1String("right"))), + center(createAnchor(QLatin1String("center"), aiCenter)) +{ + left->setCoords(0, 0); + right->setCoords(1, 1); + + setPen(QPen(Qt::black)); + setSelectedPen(QPen(Qt::blue, 2)); + setLength(8); + setStyle(bsCalligraphic); } QCPItemBracket::~QCPItemBracket() @@ -23800,7 +23301,7 @@ QCPItemBracket::~QCPItemBracket() */ void QCPItemBracket::setPen(const QPen &pen) { - mPen = pen; + mPen = pen; } /*! @@ -23810,7 +23311,7 @@ void QCPItemBracket::setPen(const QPen & */ void QCPItemBracket::setSelectedPen(const QPen &pen) { - mSelectedPen = pen; + mSelectedPen = pen; } /*! @@ -23823,7 +23324,7 @@ void QCPItemBracket::setSelectedPen(cons */ void QCPItemBracket::setLength(double length) { - mLength = length; + mLength = length; } /*! @@ -23833,60 +23334,60 @@ void QCPItemBracket::setLength(double le */ void QCPItemBracket::setStyle(QCPItemBracket::BracketStyle style) { - mStyle = style; + mStyle = style; } /* inherits documentation from base class */ double QCPItemBracket::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - Q_UNUSED(details) - if (onlySelectable && !mSelectable) - return -1; - - QVector2D leftVec(left->pixelPoint()); - QVector2D rightVec(right->pixelPoint()); - if (leftVec.toPoint() == rightVec.toPoint()) - return -1; - - QVector2D widthVec = (rightVec-leftVec)*0.5f; - QVector2D lengthVec(-widthVec.y(), widthVec.x()); - lengthVec = lengthVec.normalized()*mLength; - QVector2D centerVec = (rightVec+leftVec)*0.5f-lengthVec; - - return qSqrt(distSqrToLine((centerVec-widthVec).toPointF(), (centerVec+widthVec).toPointF(), pos)); + Q_UNUSED(details) + if (onlySelectable && !mSelectable) + return -1; + + QVector2D leftVec(left->pixelPoint()); + QVector2D rightVec(right->pixelPoint()); + if (leftVec.toPoint() == rightVec.toPoint()) + return -1; + + QVector2D widthVec = (rightVec-leftVec)*0.5f; + QVector2D lengthVec(-widthVec.y(), widthVec.x()); + lengthVec = lengthVec.normalized()*mLength; + QVector2D centerVec = (rightVec+leftVec)*0.5f-lengthVec; + + return qSqrt(distSqrToLine((centerVec-widthVec).toPointF(), (centerVec+widthVec).toPointF(), pos)); } /* inherits documentation from base class */ void QCPItemBracket::draw(QCPPainter *painter) { - QVector2D leftVec(left->pixelPoint()); - QVector2D rightVec(right->pixelPoint()); - if (leftVec.toPoint() == rightVec.toPoint()) - return; - - QVector2D widthVec = (rightVec-leftVec)*0.5f; - QVector2D lengthVec(-widthVec.y(), widthVec.x()); - lengthVec = lengthVec.normalized()*mLength; - QVector2D centerVec = (rightVec+leftVec)*0.5f-lengthVec; - - QPolygon boundingPoly; - boundingPoly << leftVec.toPoint() << rightVec.toPoint() - << (rightVec-lengthVec).toPoint() << (leftVec-lengthVec).toPoint(); - QRect clip = clipRect().adjusted(-mainPen().widthF(), -mainPen().widthF(), mainPen().widthF(), mainPen().widthF()); - if (clip.intersects(boundingPoly.boundingRect())) - { - painter->setPen(mainPen()); - switch (mStyle) + QVector2D leftVec(left->pixelPoint()); + QVector2D rightVec(right->pixelPoint()); + if (leftVec.toPoint() == rightVec.toPoint()) + return; + + QVector2D widthVec = (rightVec-leftVec)*0.5f; + QVector2D lengthVec(-widthVec.y(), widthVec.x()); + lengthVec = lengthVec.normalized()*mLength; + QVector2D centerVec = (rightVec+leftVec)*0.5f-lengthVec; + + QPolygon boundingPoly; + boundingPoly << leftVec.toPoint() << rightVec.toPoint() + << (rightVec-lengthVec).toPoint() << (leftVec-lengthVec).toPoint(); + QRect clip = clipRect().adjusted(-mainPen().widthF(), -mainPen().widthF(), mainPen().widthF(), mainPen().widthF()); + if (clip.intersects(boundingPoly.boundingRect())) + { + painter->setPen(mainPen()); + switch (mStyle) { case bsSquare: - { + { painter->drawLine((centerVec+widthVec).toPointF(), (centerVec-widthVec).toPointF()); painter->drawLine((centerVec+widthVec).toPointF(), (centerVec+widthVec+lengthVec).toPointF()); painter->drawLine((centerVec-widthVec).toPointF(), (centerVec-widthVec+lengthVec).toPointF()); break; - } + } case bsRound: - { + { painter->setBrush(Qt::NoBrush); QPainterPath path; path.moveTo((centerVec+widthVec+lengthVec).toPointF()); @@ -23894,9 +23395,9 @@ void QCPItemBracket::draw(QCPPainter *pa path.cubicTo((centerVec-widthVec).toPointF(), (centerVec-widthVec).toPointF(), (centerVec-widthVec+lengthVec).toPointF()); painter->drawPath(path); break; - } + } case bsCurly: - { + { painter->setBrush(Qt::NoBrush); QPainterPath path; path.moveTo((centerVec+widthVec+lengthVec).toPointF()); @@ -23904,9 +23405,9 @@ void QCPItemBracket::draw(QCPPainter *pa path.cubicTo((centerVec-0.4f*widthVec+lengthVec).toPointF(), (centerVec-widthVec-lengthVec*0.8f).toPointF(), (centerVec-widthVec+lengthVec).toPointF()); painter->drawPath(path); break; - } + } case bsCalligraphic: - { + { painter->setPen(Qt::NoPen); painter->setBrush(QBrush(mainPen().color())); QPainterPath path; @@ -23920,7 +23421,7 @@ void QCPItemBracket::draw(QCPPainter *pa painter->drawPath(path); break; - } + } } } } @@ -23928,23 +23429,23 @@ void QCPItemBracket::draw(QCPPainter *pa /* inherits documentation from base class */ QPointF QCPItemBracket::anchorPixelPoint(int anchorId) const { - QVector2D leftVec(left->pixelPoint()); - QVector2D rightVec(right->pixelPoint()); - if (leftVec.toPoint() == rightVec.toPoint()) - return leftVec.toPointF(); - - QVector2D widthVec = (rightVec-leftVec)*0.5f; - QVector2D lengthVec(-widthVec.y(), widthVec.x()); - lengthVec = lengthVec.normalized()*mLength; - QVector2D centerVec = (rightVec+leftVec)*0.5f-lengthVec; - - switch (anchorId) + QVector2D leftVec(left->pixelPoint()); + QVector2D rightVec(right->pixelPoint()); + if (leftVec.toPoint() == rightVec.toPoint()) + return leftVec.toPointF(); + + QVector2D widthVec = (rightVec-leftVec)*0.5f; + QVector2D lengthVec(-widthVec.y(), widthVec.x()); + lengthVec = lengthVec.normalized()*mLength; + QVector2D centerVec = (rightVec+leftVec)*0.5f-lengthVec; + + switch (anchorId) { case aiCenter: - return centerVec.toPointF(); - } - qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId; - return QPointF(); + return centerVec.toPointF(); + } + qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId; + return QPointF(); } /*! \internal @@ -23954,6 +23455,6 @@ QPointF QCPItemBracket::anchorPixelPoint */ QPen QCPItemBracket::mainPen() const { - return mSelected ? mSelectedPen : mPen; -} - + return mSelected ? mSelectedPen : mPen; +} + diff --git a/src/QCustomPlot/qcustomplot.h b/src/QCustomPlot/qcustomplot.h --- a/src/QCustomPlot/qcustomplot.h +++ b/src/QCustomPlot/qcustomplot.h @@ -1862,7 +1862,6 @@ protected: QCPLayer *mCurrentLayer; QCP::PlottingHints mPlottingHints; Qt::KeyboardModifier mMultiSelectModifier; - bool mUseFastVectors; // non-property members: QPixmap mPaintBuffer; @@ -2539,12 +2538,10 @@ public: bool errorBarSkipSymbol() const { return mErrorBarSkipSymbol; } QCPGraph *channelFillGraph() const { return mChannelFillGraph.data(); } bool adaptiveSampling() const { return mAdaptiveSampling; } - bool useFastVectors() const { return mUseFastVectors; } // setters: void setData(QCPDataMap *data, bool copy=false); void setData(const QVector &key, const QVector &value); - void setData(QVector *data); void setDataKeyError(const QVector &key, const QVector &value, const QVector &keyError); void setDataKeyError(const QVector &key, const QVector &value, const QVector &keyErrorMinus, const QVector &keyErrorPlus); void setDataValueError(const QVector &key, const QVector &value, const QVector &valueError); @@ -2559,7 +2556,6 @@ public: void setErrorBarSkipSymbol(bool enabled); void setChannelFillGraph(QCPGraph *targetGraph); void setAdaptiveSampling(bool enabled); - void setUseFastVectors(bool useFastVectors); // non-property methods: void addData(const QCPDataMap &dataMap); @@ -2584,7 +2580,6 @@ public: protected: // property members: QCPDataMap *mData; - QVector* mDataVector; QPen mErrorPen; LineStyle mLineStyle; QCPScatterStyle mScatterStyle; @@ -2593,7 +2588,6 @@ protected: bool mErrorBarSkipSymbol; QPointer mChannelFillGraph; bool mAdaptiveSampling; - bool mUseFastVectors; // reimplemented virtual methods: virtual void draw(QCPPainter *painter); @@ -2601,9 +2595,8 @@ protected: virtual QCPRange getKeyRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const; virtual QCPRange getValueRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const; virtual QCPRange getKeyRange(bool &foundRange, SignDomain inSignDomain, bool includeErrors) const; // overloads base class interface - virtual QCPRange getKeyRangeVector(bool &foundRange, SignDomain inSignDomain, bool includeErrors) const; // overloads base class interface virtual QCPRange getValueRange(bool &foundRange, SignDomain inSignDomain, bool includeErrors) const; // overloads base class interface - virtual QCPRange getValueRangeVector(bool &foundRange, SignDomain inSignDomain, bool includeErrors) const; + // introduced virtual methods: virtual void drawFill(QCPPainter *painter, QVector *lineData) const; virtual void drawScatterPlot(QCPPainter *painter, QVector *scatterData) const; @@ -2612,7 +2605,6 @@ protected: // non-virtual methods: void getPreparedData(QVector *lineData, QVector *scatterData) const; - void getPreparedDataVector(QVector *lineData, QVector *scatterData) const; void getPlotData(QVector *lineData, QVector *scatterData) const; void getScatterPlotData(QVector *scatterData) const; void getLinePlotData(QVector *linePixelData, QVector *scatterData) const; @@ -2622,9 +2614,7 @@ protected: void getImpulsePlotData(QVector *linePixelData, QVector *scatterData) const; void drawError(QCPPainter *painter, double x, double y, const QCPData &data) const; void getVisibleDataBounds(QCPDataMap::const_iterator &lower, QCPDataMap::const_iterator &upper) const; - void getVisibleDataBoundsVector(QVector::const_iterator &lower, QVector::const_iterator &upper) const; int countDataInBounds(const QCPDataMap::const_iterator &lower, const QCPDataMap::const_iterator &upper, int maxCount) const; - int countDataInBoundsVector(const QVector::const_iterator &lower, const QVector::const_iterator &upper, int maxCount) const; void addFillBasePoints(QVector *lineData) const; void removeFillBasePoints(QVector *lineData) const; QPointF lowerFillBasePoint(double lowerKey) const; diff --git a/src/SocExplorerPlot.cpp b/src/SocExplorerPlot.cpp --- a/src/SocExplorerPlot.cpp +++ b/src/SocExplorerPlot.cpp @@ -28,7 +28,7 @@ SocExplorerPlot::SocExplorerPlot(QWidget *parent) : QWidget(parent), mRubberBand(new QRubberBand(QRubberBand::Rectangle, this)) { - this->m_plot = new QCustomPlot(this); + this->m_plot = new QCustomPlotVect(this); this->m_plot->setInteractions(QCP::iRangeDrag | QCP::iSelectAxes | QCP::iSelectLegend | QCP::iSelectPlottables); this->m_plot->axisRect()->setRangeDrag(Qt::Horizontal|Qt::Vertical); @@ -85,6 +85,18 @@ void SocExplorerPlot::exportToPDF(const qcpPainter.end(); } +void SocExplorerPlot::addAction(SocExplorerPlotActions *action) +{ + this->m_actions.append(action); + QWidget::addAction((QAction*)action); +} + +QVector *SocExplorerPlot::getVisibleData(int graphIndex) +{ + QVector *wholeData=((QCPGraphVect*)m_plot->graph(graphIndex))->data(); +// m_plot->xAxis-> +} + void SocExplorerPlot::setTitle(QString title) { Q_UNUSED(title) @@ -144,7 +156,8 @@ void SocExplorerPlot::setAdaptativeSampl void SocExplorerPlot::setUseFastVector(int graphIndex, bool enable) { - this->m_plot->graph(graphIndex)->setUseFastVectors(enable); + // TODO deprecated +// this->m_plot->graph(graphIndex)->setUseFastVectors(enable); } int SocExplorerPlot::addGraph() @@ -155,7 +168,12 @@ int SocExplorerPlot::addGraph() bool SocExplorerPlot::removeGraph(int graphIndex) { - return this->m_plot->removeGraph(graphIndex); + return this->m_plot->removeGraph(graphIndex); +} + +int SocExplorerPlot::graphCount() +{ + return m_plot->graphCount(); } void SocExplorerPlot::removeAllGraphs() @@ -226,7 +244,7 @@ void SocExplorerPlot::setGraphData(int g { if((graphIndexm_plot->graphCount()))// && (x.at(0).type()==QVariant::Double)) { - this->m_plot->graph(graphIndex)->setData(data); + ((QCPGraphVect*)this->m_plot->graph(graphIndex))->setData(data); } if(replot) this->m_plot->replot(); diff --git a/src/SocExplorerPlot.h b/src/SocExplorerPlot.h --- a/src/SocExplorerPlot.h +++ b/src/SocExplorerPlot.h @@ -25,9 +25,37 @@ #include #include #include +#include #include #include +class SocExplorerPlotActions : public QAction +{ + Q_OBJECT +public: + SocExplorerPlotActions(const QString &text,int PID,QObject* parent=0) + :QAction(text,parent) + { + setPID(PID); + connect(this,SIGNAL(triggered()),this,SLOT(trigger())); + } + SocExplorerPlotActions(const QIcon &icon, const QString &text,int PID, QObject* parent) + :QAction(icon,text,parent) + { + setPID(PID); + connect(this,SIGNAL(triggered()),this,SLOT(trigger())); + } + ~SocExplorerPlotActions(){} + void setPID(int PID){this->m_PID=PID;} + int PID(){return m_PID;} +private slots: + void trigger(){emit triggered(m_PID);} +signals: + void triggered(int PID); +private: + int m_PID; +}; + class SocExplorerPlot : public QWidget { Q_OBJECT @@ -46,6 +74,7 @@ public: void setUseFastVector(int graphIndex,bool enable); int addGraph(); bool removeGraph(int graphIndex); + int graphCount(); void removeAllGraphs(); void setGraphName(int graphIndex,QString name); void setGraphData(int graphIndex, QList x, QList y); @@ -63,6 +92,10 @@ public: void replot(); void exportToSVG(const QString& fileName); void exportToPDF(const QString& fileName); + void addAction(SocExplorerPlotActions* action); + int PID(){return m_PID;} + void setPID(int PID){m_PID = PID;} + QVector* getVisibleData(int graphIndex); signals: void titleChanged(const QString& newTitle); public slots: @@ -78,7 +111,7 @@ protected: private: void zoom(double factor, int center, Qt::Orientation orientation); void move(double factor, Qt::Orientation orientation); - QCustomPlot* m_plot; + QCustomPlotVect* m_plot; QGridLayout* m_mainlayout; bool ctrl_hold; bool shift_hold; @@ -89,6 +122,8 @@ private: bool mZoomMode; QRubberBand * mRubberBand; QPoint mOrigin; + QList m_actions; + int m_PID; }; #endif // SOCEXPLORERPLOT_H diff --git a/src/folderlistwidget.cpp b/src/folderlistwidget.cpp deleted file mode 100644 --- a/src/folderlistwidget.cpp +++ /dev/null @@ -1,131 +0,0 @@ -#include "folderlistwidget.h" -#include -#include -#include -#include -#include -#include -#include -#include - -FolderListWidget::FolderListWidget(QWidget *parent) : QListWidget(parent) -{ - this->setSelectionMode(QAbstractItemView::ExtendedSelection); - this->setAcceptDrops(true); - this->setDragEnabled(true); - this->setDragDropMode(QAbstractItemView::DragDrop); - this->setDefaultDropAction(Qt::MoveAction); - this->p_mainWin=NULL; - this->p_path=""; -} - -FolderListWidget::~FolderListWidget() -{ - -} - -bool FolderListWidget::contains(const QString &name) -{ - for(int i=0;icount();i++) - { - if(this->item(i)->text()==name) - return true; - } - return false; -} - -bool FolderListWidget::isDraging(const QString &name) -{ - for(int i=0;ilastDragItems.count();i++) - { - if(lastDragItems.at(i)==name) - return true; - } - return false; -} - -void FolderListWidget::setMainWindow(MainWindow *mw) -{ - this->p_mainWin = mw; -} - -void FolderListWidget::setPath(const QString &path) -{ - this->p_path = path; - this->lastDragItems.clear(); -} - -void FolderListWidget::dragEnterEvent(QDragEnterEvent *event) -{ - const QMimeData *mimeData = event->mimeData(); - QStringList mimeFormats = mimeData->formats(); - bool containsFile=false; - if(mimeFormats.count()) - { - QByteArray encoded = mimeData->data("application/x-qabstractitemmodeldatalist"); - QDataStream stream(&encoded, QIODevice::ReadOnly); - while (!stream.atEnd()) - { - int row, col; - QMap roleDataMap; - stream >> row >> col >> roleDataMap; - if(this->contains(roleDataMap[0].toString())) - containsFile = true; - } - } - if(!containsFile) - { - QListWidget::dragEnterEvent(event); - } - else - { - this->lastDragItems.clear(); - QList selItems = this->selectedItems(); - for(int i=0;itext()); - } - } - -} - -void FolderListWidget::dragMoveEvent(QDragMoveEvent *event) -{ - QListWidget::dragMoveEvent(event); -} - -void FolderListWidget::dragLeaveEvent(QDragLeaveEvent *event) -{ - QListWidget::dragLeaveEvent(event); - this->lastDragItems.clear(); -} - -void FolderListWidget::dropEvent(QDropEvent *event) -{ - QByteArray encoded = event->mimeData()->data("application/x-qabstractitemmodeldatalist"); - QDataStream stream(&encoded, QIODevice::ReadOnly); - while (!stream.atEnd()) - { - int row, col; - QMap roleDataMap; - stream >> row >> col >> roleDataMap; - QString name=roleDataMap[0].toString(); - QString oldPath = p_mainWin->getFilePath(name); - if((oldPath!="") && (p_path!="")) - { - if(QFile::rename(oldPath+"/"+name,this->p_path+"/"+name)) - QListWidget::dropEvent(event); - emit askGlobalRescan(); - } - } -} - -void FolderListWidget::mousePressEvent(QMouseEvent *event) -{ - QListWidget::mousePressEvent(event); -} - -void FolderListWidget::mouseMoveEvent(QMouseEvent *event) -{ - QListWidget::mouseMoveEvent(event); -} diff --git a/src/folderlistwidget.h b/src/folderlistwidget.h deleted file mode 100644 --- a/src/folderlistwidget.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef FOLDERLISTWIDGET_H -#define FOLDERLISTWIDGET_H - -#include -#include -#include -#include - -class FolderListWidget : public QListWidget -{ - Q_OBJECT -public: - explicit FolderListWidget(QWidget *parent = 0); - ~FolderListWidget(); - bool contains(const QString& name); - bool isDraging(const QString& name); - void setMainWindow(MainWindow* mw); - void setPath(const QString& path); -signals: - void askGlobalRescan(); -public slots: -protected: - void dragEnterEvent(QDragEnterEvent *event); - void dragMoveEvent(QDragMoveEvent *event); - void dragLeaveEvent(QDragLeaveEvent* event); - void dropEvent(QDropEvent *event); - void mousePressEvent(QMouseEvent *event); - void mouseMoveEvent(QMouseEvent *event); - -private: - QStringList lastDragItems; - MainWindow* p_mainWin; - QString p_path; -}; - -#endif // FOLDERLISTWIDGET_H diff --git a/src/folderview.cpp b/src/folderview.cpp deleted file mode 100644 --- a/src/folderview.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/*------------------------------------------------------------------------------ --- This file is a part of the QLop Software --- Copyright (C) 2015, Plasma Physics Laboratory - CNRS --- --- 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 --------------------------------------------------------------------------------*/ -/*-- Author : Alexis Jeandet --- Mail : alexis.jeandet@member.fsf.org -----------------------------------------------------------------------------*/ -#include "folderview.h" -#include "ui_folderview.h" -#include -#include -#include - -p_FolderView::p_FolderView(QWidget *parent) : - QWidget(parent), - ui(new Ui::p_FolderView) -{ - ui->setupUi(this); - connect(this->ui->setFolderQpb,SIGNAL(clicked()),this,SLOT(openFolder())); - connect(this->ui->refreshQpb,SIGNAL(clicked()),this,SLOT(refreshFolder())); - connect(this->ui->listWidget,SIGNAL(itemActivated(QListWidgetItem*)),this,SLOT(itemActivated(QListWidgetItem*))); - //this->ui->listWidget->installEventFilter(this); - connect(this->ui->listWidget,SIGNAL(askGlobalRescan()),this,SIGNAL(askGlobalRescan())); -} - -p_FolderView::~p_FolderView() -{ - delete ui; -} - -bool p_FolderView::contains(const QString &fileName) -{ - for(int i=0;iui->listWidget->count();i++) - { - if(this->ui->listWidget->item(i)->text()==fileName) - { - return true; - } - } - return false; -} - -bool p_FolderView::isDraging(const QString &name) -{ - return this->ui->listWidget->isDraging(name); -} - -void p_FolderView::setMainWindow(MainWindow *mw) -{ - this->ui->listWidget->setMainWindow(mw); -} - -QString p_FolderView::currentFolder() -{ - return p_currentFolder; -} - -void p_FolderView::openFolder() -{ - p_currentFolder = QFileDialog::getExistingDirectory(this, tr("Open Directory"),NULL,QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); - refreshFolder(); -} - -void p_FolderView::refreshFolder() -{ - QDir dir; - dir.setPath(p_currentFolder); - this->ui->listWidget->clear(); - dir.setFilter(QDir::Files | QDir::NoSymLinks); - dir.setSorting(QDir::Name); - QFileInfoList list = dir.entryInfoList(); - for (int i = 0; i < list.size(); ++i) - { - if(!list.at(i).completeSuffix().compare("TAB")) - { - this->ui->listWidget->addItem(list.at(i).fileName()); - } - } - this->ui->listWidget->setPath(p_currentFolder); - this->ui->groupBox->setTitle(p_currentFolder); -} - -void p_FolderView::itemActivated(QListWidgetItem *item) -{ - emit itemActivated(p_currentFolder+'/'+item->text()); -} - -void p_FolderView::changeEvent(QEvent *e) -{ - QWidget::changeEvent(e); - switch (e->type()) { - case QEvent::LanguageChange: - ui->retranslateUi(this); - break; - default: - break; - } -} - -bool p_FolderView::eventFilter(QObject *object, QEvent *event) -{ - if(object == this->ui->listWidget ) - { - qDebug()<type(); - if(event->type() == QEvent::Drop) - { - QDropEvent *DropEvent = static_cast(event); - qDebug()<< DropEvent->mimeData(); - } - } - return false; -} - - -FolderView::FolderView(MainWindow *parent) - :QDockWidget(parent) -{ - this->setFeatures(QDockWidget::DockWidgetMovable|QDockWidget::DockWidgetFloatable); - this->setAllowedAreas(Qt::AllDockWidgetAreas); - this->ui = new p_FolderView(this); - this->setWidget(this->ui); - connect(this->ui,SIGNAL(itemActivated(QString)),this,SIGNAL(itemActivated(QString))); - connect(this->ui,SIGNAL(askGlobalRescan()),this,SIGNAL(askGlobalRescan())); - this->ui->setMainWindow(parent); -} - -bool FolderView::contains(const QString &fileName) -{ - return ui->contains(fileName); -} - -bool FolderView::isDraging(const QString &name) -{ - return this->ui->isDraging(name); -} - -QString FolderView::currentFolder() -{ - return this->ui->currentFolder(); -} - -void FolderView::openFolder() -{ - this->ui->openFolder(); -} - -void FolderView::refreshFolder() -{ - this->ui->refreshFolder(); -} - diff --git a/src/folderview.h b/src/folderview.h deleted file mode 100644 --- a/src/folderview.h +++ /dev/null @@ -1,85 +0,0 @@ -/*------------------------------------------------------------------------------ --- This file is a part of the QLop Software --- Copyright (C) 2015, Plasma Physics Laboratory - CNRS --- --- 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 --------------------------------------------------------------------------------*/ -/*-- Author : Alexis Jeandet --- Mail : alexis.jeandet@member.fsf.org -----------------------------------------------------------------------------*/ -#ifndef FOLDERVIEW_H -#define FOLDERVIEW_H - -#include -#include -#include -#include -#include - class MainWindow; -namespace Ui { - class p_FolderView; -} - -class p_FolderView; - -class FolderView : public QDockWidget -{ - Q_OBJECT -public: - FolderView (MainWindow *parent = 0); - ~FolderView(){} - bool contains(const QString& fileName); - bool isDraging(const QString& name); - QString currentFolder(); -public slots: - void openFolder(); - void refreshFolder(); -signals: - void askGlobalRescan(); - void itemActivated(const QString& item); -private: - p_FolderView* ui; -}; - - -class p_FolderView : public QWidget -{ - Q_OBJECT - -public: - explicit p_FolderView(QWidget *parent = 0); - ~p_FolderView(); - bool contains(const QString& fileName); - bool isDraging(const QString& name); - void setMainWindow(MainWindow* mw); - QString currentFolder(); -public slots: - void openFolder(); - void refreshFolder(); - void itemActivated(QListWidgetItem * item); -signals: - void askGlobalRescan(); - void itemActivated(const QString& item); -protected: - void changeEvent(QEvent *e); - bool eventFilter(QObject *object, QEvent *event); - -private: - Ui::p_FolderView *ui; - QWidget* _Widget; - QString p_currentFolder; -}; - -#endif // FOLDERVIEW_H diff --git a/src/folderview.ui b/src/folderview.ui deleted file mode 100644 --- a/src/folderview.ui +++ /dev/null @@ -1,101 +0,0 @@ - - - p_FolderView - - - - 0 - 0 - 400 - 300 - - - - Test - - - - - - No Folder - - - - - - true - - - QAbstractItemView::NoEditTriggers - - - true - - - false - - - QAbstractItemView::DragDrop - - - Qt::MoveAction - - - - - - - Set Folder - - - - - - - - - - - - - - :/img/Gnome-view-refresh.svg:/img/Gnome-view-refresh.svg - - - - 24 - 24 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - FolderListWidget - QListWidget -
folderlistwidget.h
-
-
- - - - -
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -78,15 +78,15 @@ MainWindow::~MainWindow() delete ui; } -QString MainWindow::getFilePath(const QString &name) -{ -// for(int i=0;ifolderViews.count();i++) -// { -// if(folderViews.at(i)->isDraging(name)) -// return folderViews.at(i)->currentFolder(); -// } - return ""; -} +//QString MainWindow::getFilePath(const QString &name) +//{ +//// for(int i=0;ifolderViews.count();i++) +//// { +//// if(folderViews.at(i)->isDraging(name)) +//// return folderViews.at(i)->currentFolder(); +//// } +// return ""; +//} diff --git a/src/mainwindow.h b/src/mainwindow.h --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -30,7 +30,6 @@ #include #include #include -#include "folderview.h" #include "abstractfileloader.h" #include "cassiniindexfileviewer.h" #include