53 mIsAntialiasing(false)
68 mIsAntialiasing(false)
70 #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.
72 setRenderHint(QPainter::NonCosmeticDefaultPen);
88 QPainter::setPen(pen);
102 QPainter::setPen(color);
116 QPainter::setPen(penStyle);
132 QPainter::drawLine(line);
134 QPainter::drawLine(line.toLine());
145 setRenderHint(QPainter::Antialiasing, enabled);
154 translate(-0.5, -0.5);
181 bool result = QPainter::begin(device);
182 #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.
184 setRenderHint(QPainter::NonCosmeticDefaultPen);
196 if (!enabled &&
mModes.testFlag(mode))
198 else if (enabled && !
mModes.testFlag(mode))
229 qDebug() << Q_FUNC_INFO <<
"Unbalanced save/restore";
239 if (qFuzzyIsNull(pen().widthF()))
377 mBrush(QBrush(fill)),
402 mPenDefined(pen.style() != Qt::NoPen)
434 mCustomPath(customPath),
435 mPenDefined(pen.style() != Qt::NoPen)
523 painter->setBrush(
mBrush);
544 double w =
mSize/2.0;
550 painter->
drawLine(QPointF(x, y), QPointF(x+0.0001, y));
555 painter->
drawLine(QLineF(x-w, y-w, x+w, y+w));
556 painter->
drawLine(QLineF(x-w, y+w, x+w, y-w));
561 painter->
drawLine(QLineF(x-w, y, x+w, y));
562 painter->
drawLine(QLineF( x, y+w, x, y-w));
567 painter->drawEllipse(QPointF(x , y), w, w);
572 QBrush b = painter->brush();
573 painter->setBrush(painter->pen().color());
574 painter->drawEllipse(QPointF(x , y), w, w);
575 painter->setBrush(b);
580 painter->drawRect(QRectF(x-w, y-w,
mSize,
mSize));
585 painter->
drawLine(QLineF(x-w, y, x, y-w));
586 painter->
drawLine(QLineF( x, y-w, x+w, y));
587 painter->
drawLine(QLineF(x+w, y, x, y+w));
588 painter->
drawLine(QLineF( x, y+w, x-w, y));
593 painter->
drawLine(QLineF(x-w, y, x+w, y));
594 painter->
drawLine(QLineF( x, y+w, x, y-w));
595 painter->
drawLine(QLineF(x-w*0.707, y-w*0.707, x+w*0.707, y+w*0.707));
596 painter->
drawLine(QLineF(x-w*0.707, y+w*0.707, x+w*0.707, y-w*0.707));
601 painter->
drawLine(QLineF(x-w, y+0.755*w, x+w, y+0.755*w));
602 painter->
drawLine(QLineF(x+w, y+0.755*w, x, y-0.977*w));
603 painter->
drawLine(QLineF( x, y-0.977*w, x-w, y+0.755*w));
608 painter->
drawLine(QLineF(x-w, y-0.755*w, x+w, y-0.755*w));
609 painter->
drawLine(QLineF(x+w, y-0.755*w, x, y+0.977*w));
610 painter->
drawLine(QLineF( x, y+0.977*w, x-w, y-0.755*w));
615 painter->
drawLine(QLineF(x-w, y-w, x+w*0.95, y+w*0.95));
616 painter->
drawLine(QLineF(x-w, y+w*0.95, x+w*0.95, y-w));
617 painter->drawRect(QRectF(x-w, y-w,
mSize,
mSize));
622 painter->
drawLine(QLineF(x-w, y, x+w*0.95, y));
623 painter->
drawLine(QLineF( x, y+w, x, y-w));
624 painter->drawRect(QRectF(x-w, y-w,
mSize,
mSize));
629 painter->
drawLine(QLineF(x-w*0.707, y-w*0.707, x+w*0.670, y+w*0.670));
630 painter->
drawLine(QLineF(x-w*0.707, y+w*0.670, x+w*0.670, y-w*0.707));
631 painter->drawEllipse(QPointF(x, y), w, w);
636 painter->
drawLine(QLineF(x-w, y, x+w, y));
637 painter->
drawLine(QLineF( x, y+w, x, y-w));
638 painter->drawEllipse(QPointF(x, y), w, w);
643 painter->
drawLine(QLineF(x, y-w, x, y+w));
644 painter->
drawLine(QLineF(x, y, x-w*0.707, y+w*0.707));
645 painter->
drawLine(QLineF(x, y, x+w*0.707, y+w*0.707));
646 painter->drawEllipse(QPointF(x, y), w, w);
656 QTransform oldTransform = painter->transform();
657 painter->translate(x, y);
660 painter->setTransform(oldTransform);
741 mParentPlot(parentPlot),
761 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.";
796 qDebug() << Q_FUNC_INFO <<
"layerable is already child of this layer" <<
reinterpret_cast<quintptr
>(layerable);
811 qDebug() << Q_FUNC_INFO <<
"layerable is not child of this layer" <<
reinterpret_cast<quintptr
>(layerable);
926 mParentLayerable(parentLayerable),
932 if (targetLayer.isEmpty())
935 qDebug() << Q_FUNC_INFO <<
"setting QCPlayerable initial layer to" << targetLayer <<
"failed.";
981 qDebug() << Q_FUNC_INFO <<
"no parent QCustomPlot set";
989 qDebug() << Q_FUNC_INFO <<
"there is no layer with name" << layerName;
1060 Q_UNUSED(onlySelectable)
1086 qDebug() << Q_FUNC_INFO <<
"called with mParentPlot already initialized";
1091 qDebug() << Q_FUNC_INFO <<
"called with parentPlot zero";
1125 qDebug() << Q_FUNC_INFO <<
"no parent QCustomPlot set";
1130 qDebug() << Q_FUNC_INFO <<
"layer" << layer->
name() <<
"is not in same QCustomPlot as this layerable";
1180 Q_UNUSED(parentPlot)
1249 Q_UNUSED(selectionStateChanged)
1266 Q_UNUSED(selectionStateChanged)
1371 result.
expand(otherRange);
1389 double rangeFac = 1e-3;
1394 if (sanitizedRange.
lower == 0.0 && sanitizedRange.
upper != 0.0)
1397 if (rangeFac < sanitizedRange.
upper*rangeFac)
1398 sanitizedRange.
lower = rangeFac;
1400 sanitizedRange.
lower = sanitizedRange.
upper*rangeFac;
1402 else if (sanitizedRange.
lower != 0.0 && sanitizedRange.
upper == 0.0)
1405 if (-rangeFac > sanitizedRange.
lower*rangeFac)
1406 sanitizedRange.
upper = -rangeFac;
1408 sanitizedRange.
upper = sanitizedRange.
lower*rangeFac;
1409 }
else if (sanitizedRange.
lower < 0 && sanitizedRange.
upper > 0)
1412 if (-sanitizedRange.
lower > sanitizedRange.
upper)
1415 if (-rangeFac > sanitizedRange.
lower*rangeFac)
1416 sanitizedRange.
upper = -rangeFac;
1418 sanitizedRange.
upper = sanitizedRange.
lower*rangeFac;
1422 if (rangeFac < sanitizedRange.
upper*rangeFac)
1423 sanitizedRange.
lower = rangeFac;
1425 sanitizedRange.
lower = sanitizedRange.
upper*rangeFac;
1429 return sanitizedRange;
1440 return sanitizedRange;
1465 !(lower > 0 && qIsInf(upper/lower)) &&
1466 !(upper < 0 && qIsInf(lower/upper)));
1538 QObject(parentPlot),
1539 mParentPlot(parentPlot)
1558 QHashIterator<QCP::MarginSide, QList<QCPLayoutElement*> > it(
mChildren);
1559 while (it.hasNext())
1562 if (!it.value().isEmpty())
1575 QHashIterator<QCP::MarginSide, QList<QCPLayoutElement*> > it(
mChildren);
1576 while (it.hasNext())
1579 const QList<QCPLayoutElement*>
elements = it.value();
1580 for (
int i=elements.size()-1; i>=0; --i)
1581 elements.at(i)->setMarginGroup(it.key(), 0);
1600 for (
int i=0; i<elements.size(); ++i)
1602 if (!elements.at(i)->autoMargins().testFlag(side))
1604 int m = qMax(elements.at(i)->calculateAutoMargin(side),
QCP::getMarginValue(elements.at(i)->minimumMargins(), side));
1622 qDebug() << Q_FUNC_INFO <<
"element is already child of this margin group side" <<
reinterpret_cast<quintptr
>(element);
1633 if (!
mChildren[side].removeOne(element))
1634 qDebug() << Q_FUNC_INFO <<
"element is not child of this margin group side" <<
reinterpret_cast<quintptr
>(element);
1726 mMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX),
1728 mOuterRect(0, 0, 0, 0),
1729 mMargins(0, 0, 0, 0),
1730 mMinimumMargins(0, 0, 0, 0),
1731 mAutoMargins(QCP::
msAll)
1879 QVector<QCP::MarginSide> sideVector;
1885 for (
int i=0; i<sideVector.size(); ++i)
1979 return QList<QCPLayoutElement*>();
2006 qDebug() << Q_FUNC_INFO <<
"parent plot not defined";
2140 for (
int i=0; i<elCount; ++i)
2151 QList<QCPLayoutElement*> result;
2152 #if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
2155 for (
int i=0; i<c; ++i)
2159 for (
int i=0; i<c; ++i)
2162 result << result.at(i)->elements(recursive);
2247 if (QWidget *w = qobject_cast<QWidget*>(parent()))
2248 w->updateGeometry();
2249 else if (
QCPLayout *l = qobject_cast<QCPLayout*>(parent()))
2250 l->sizeConstraintsChanged();
2288 el->setParent(
this);
2292 qDebug() << Q_FUNC_INFO <<
"Null element passed";
2314 qDebug() << Q_FUNC_INFO <<
"Null element passed";
2348 if (maxSizes.size() != minSizes.size() || minSizes.size() != stretchFactors.size())
2350 qDebug() << Q_FUNC_INFO <<
"Passed vector sizes aren't equal:" << maxSizes << minSizes << stretchFactors;
2351 return QVector<int>();
2353 if (stretchFactors.isEmpty())
2354 return QVector<int>();
2355 int sectionCount = stretchFactors.size();
2356 QVector<double> sectionSizes(sectionCount);
2359 for (
int i=0; i<sectionCount; ++i)
2360 minSizeSum += minSizes.at(i);
2361 if (totalSize < minSizeSum)
2364 for (
int i=0; i<sectionCount; ++i)
2366 stretchFactors[i] = minSizes.at(i);
2371 QList<int> minimumLockedSections;
2372 QList<int> unfinishedSections;
2373 for (
int i=0; i<sectionCount; ++i)
2374 unfinishedSections.append(i);
2375 double freeSize = totalSize;
2377 int outerIterations = 0;
2378 while (!unfinishedSections.isEmpty() && outerIterations < sectionCount*2)
2381 int innerIterations = 0;
2382 while (!unfinishedSections.isEmpty() && innerIterations < sectionCount*2)
2387 double nextMax = 1e12;
2388 for (
int i=0; i<unfinishedSections.size(); ++i)
2390 int secId = unfinishedSections.at(i);
2391 double hitsMaxAt = (maxSizes.at(secId)-sectionSizes.at(secId))/stretchFactors.at(secId);
2392 if (hitsMaxAt < nextMax)
2394 nextMax = hitsMaxAt;
2400 double stretchFactorSum = 0;
2401 for (
int i=0; i<unfinishedSections.size(); ++i)
2402 stretchFactorSum += stretchFactors.at(unfinishedSections.at(i));
2403 double nextMaxLimit = freeSize/stretchFactorSum;
2404 if (nextMax < nextMaxLimit)
2406 for (
int i=0; i<unfinishedSections.size(); ++i)
2408 sectionSizes[unfinishedSections.at(i)] += nextMax*stretchFactors.at(unfinishedSections.at(i));
2409 freeSize -= nextMax*stretchFactors.at(unfinishedSections.at(i));
2411 unfinishedSections.removeOne(nextId);
2414 for (
int i=0; i<unfinishedSections.size(); ++i)
2415 sectionSizes[unfinishedSections.at(i)] += nextMaxLimit*stretchFactors.at(unfinishedSections.at(i));
2416 unfinishedSections.clear();
2419 if (innerIterations == sectionCount*2)
2420 qDebug() << Q_FUNC_INFO <<
"Exceeded maximum expected inner iteration count, layouting aborted. Input was:" << maxSizes << minSizes << stretchFactors << totalSize;
2423 bool foundMinimumViolation =
false;
2424 for (
int i=0; i<sectionSizes.size(); ++i)
2426 if (minimumLockedSections.contains(i))
2428 if (sectionSizes.at(i) < minSizes.at(i))
2430 sectionSizes[i] = minSizes.at(i);
2431 foundMinimumViolation =
true;
2432 minimumLockedSections.append(i);
2435 if (foundMinimumViolation)
2437 freeSize = totalSize;
2438 for (
int i=0; i<sectionCount; ++i)
2440 if (!minimumLockedSections.contains(i))
2441 unfinishedSections.append(i);
2443 freeSize -= sectionSizes.at(i);
2446 for (
int i=0; i<unfinishedSections.size(); ++i)
2447 sectionSizes[unfinishedSections.at(i)] = 0;
2450 if (outerIterations == sectionCount*2)
2451 qDebug() << Q_FUNC_INFO <<
"Exceeded maximum expected outer iteration count, layouting aborted. Input was:" << maxSizes << minSizes << stretchFactors << totalSize;
2453 QVector<int> result(sectionCount);
2454 for (
int i=0; i<sectionCount; ++i)
2455 result[i] = qRound(sectionSizes.at(i));
2508 if (column >= 0 && column <
mElements.first().size())
2513 qDebug() << Q_FUNC_INFO <<
"Requested cell is empty. Row:" << row <<
"Column:" << column;
2515 qDebug() << Q_FUNC_INFO <<
"Invalid column. Row:" << row <<
"Column:" << column;
2517 qDebug() << Q_FUNC_INFO <<
"Invalid row. Row:" << row <<
"Column:" << column;
2567 qDebug() << Q_FUNC_INFO <<
"There is already an element in the specified row/column:" << row << column;
2569 qDebug() << Q_FUNC_INFO <<
"Can't add null element to row/column:" << row << column;
2605 qDebug() << Q_FUNC_INFO <<
"Invalid stretch factor, must be positive:" << factor;
2607 qDebug() << Q_FUNC_INFO <<
"Invalid column:" << column;
2630 qDebug() << Q_FUNC_INFO <<
"Invalid stretch factor, must be positive:" <<
mColumnStretchFactors.at(i);
2635 qDebug() << Q_FUNC_INFO <<
"Column count not equal to passed stretch factor count:" << factors;
2656 qDebug() << Q_FUNC_INFO <<
"Invalid stretch factor, must be positive:" << factor;
2658 qDebug() << Q_FUNC_INFO <<
"Invalid row:" << row;
2681 qDebug() << Q_FUNC_INFO <<
"Invalid stretch factor, must be positive:" <<
mRowStretchFactors.at(i);
2686 qDebug() << Q_FUNC_INFO <<
"Row count not equal to passed stretch factor count:" << factors;
2728 mElements.append(QList<QCPLayoutElement*>());
2732 int newColCount = qMax(
columnCount(), newColumnCount);
2735 while (
mElements.at(i).size() < newColCount)
2762 QList<QCPLayoutElement*> newRow;
2788 for (
int row=0; row<
rowCount(); ++row)
2795 QVector<int> minColWidths, minRowHeights, maxColWidths, maxRowHeights;
2805 int yOffset =
mRect.top();
2806 for (
int row=0; row<
rowCount(); ++row)
2810 int xOffset =
mRect.left();
2816 mElements.at(row).at(col)->setOuterRect(QRect(xOffset, yOffset, colWidths.at(col), rowHeights.at(row)));
2846 qDebug() << Q_FUNC_INFO <<
"Attempt to take invalid index:" << index;
2864 qDebug() << Q_FUNC_INFO <<
"Element not in this layout, couldn't take";
2866 qDebug() << Q_FUNC_INFO <<
"Can't take null element";
2873 QList<QCPLayoutElement*> result;
2876 #if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
2877 result.reserve(colC*rowC);
2879 for (
int row=0; row<rowC; ++row)
2881 for (
int col=0; col<colC; ++col)
2883 result.append(
mElements.at(row).at(col));
2888 int c = result.size();
2889 for (
int i=0; i<c; ++i)
2892 result << result.at(i)->elements(recursive);
2904 for (
int row=
rowCount()-1; row>=0; --row)
2906 bool hasElements =
false;
2927 bool hasElements =
false;
2928 for (
int row=0; row<
rowCount(); ++row)
2939 for (
int row=0; row<
rowCount(); ++row)
2948 QVector<int> minColWidths, minRowHeights;
2951 for (
int i=0; i<minColWidths.size(); ++i)
2952 result.rwidth() += minColWidths.at(i);
2953 for (
int i=0; i<minRowHeights.size(); ++i)
2954 result.rheight() += minRowHeights.at(i);
2963 QVector<int> maxColWidths, maxRowHeights;
2967 for (
int i=0; i<maxColWidths.size(); ++i)
2968 result.setWidth(qMin(result.width()+maxColWidths.at(i), QWIDGETSIZE_MAX));
2969 for (
int i=0; i<maxRowHeights.size(); ++i)
2970 result.setHeight(qMin(result.height()+maxRowHeights.at(i), QWIDGETSIZE_MAX));
2991 *minRowHeights = QVector<int>(
rowCount(), 0);
2992 for (
int row=0; row<
rowCount(); ++row)
2998 QSize minHint =
mElements.at(row).at(col)->minimumSizeHint();
2999 QSize min =
mElements.at(row).at(col)->minimumSize();
3000 QSize
final(min.width() > 0 ? min.width() : minHint.width(), min.height() > 0 ? min.height() : minHint.height());
3001 if (minColWidths->at(col) <
final.width())
3002 (*minColWidths)[col] =
final.width();
3003 if (minRowHeights->at(row) <
final.height())
3004 (*minRowHeights)[row] =
final.height();
3024 *maxColWidths = QVector<int>(
columnCount(), QWIDGETSIZE_MAX);
3025 *maxRowHeights = QVector<int>(
rowCount(), QWIDGETSIZE_MAX);
3026 for (
int row=0; row<
rowCount(); ++row)
3032 QSize maxHint =
mElements.at(row).at(col)->maximumSizeHint();
3033 QSize max =
mElements.at(row).at(col)->maximumSize();
3034 QSize
final(max.width() < QWIDGETSIZE_MAX ? max.width() : maxHint.width(), max.height() < QWIDGETSIZE_MAX ? max.height() : maxHint.height());
3035 if (maxColWidths->at(col) >
final.width())
3036 (*maxColWidths)[col] =
final.width();
3037 if (maxRowHeights->at(row) >
final.height())
3038 (*maxRowHeights)[row] =
final.height();
3099 qDebug() << Q_FUNC_INFO <<
"Invalid element index:" << index;
3114 qDebug() << Q_FUNC_INFO <<
"Invalid element index:" << index;
3129 qDebug() << Q_FUNC_INFO <<
"Invalid element index:" << index;
3144 qDebug() << Q_FUNC_INFO <<
"Invalid element index:" << index;
3160 qDebug() << Q_FUNC_INFO <<
"Invalid element index:" << index;
3179 qDebug() << Q_FUNC_INFO <<
"Invalid element index:" << index;
3188 QSize finalMinSize, finalMaxSize;
3189 QSize minSizeHint =
mElements.at(i)->minimumSizeHint();
3190 QSize maxSizeHint =
mElements.at(i)->maximumSizeHint();
3191 finalMinSize.setWidth(
mElements.at(i)->minimumSize().width() > 0 ?
mElements.at(i)->minimumSize().width() : minSizeHint.width());
3192 finalMinSize.setHeight(
mElements.at(i)->minimumSize().height() > 0 ?
mElements.at(i)->minimumSize().height() : minSizeHint.height());
3193 finalMaxSize.setWidth(
mElements.at(i)->maximumSize().width() < QWIDGETSIZE_MAX ?
mElements.at(i)->maximumSize().width() : maxSizeHint.width());
3194 finalMaxSize.setHeight(
mElements.at(i)->maximumSize().height() < QWIDGETSIZE_MAX ?
mElements.at(i)->maximumSize().height() : maxSizeHint.height());
3201 if (insetRect.size().width() < finalMinSize.width())
3202 insetRect.setWidth(finalMinSize.width());
3203 if (insetRect.size().height() < finalMinSize.height())
3204 insetRect.setHeight(finalMinSize.height());
3205 if (insetRect.size().width() > finalMaxSize.width())
3206 insetRect.setWidth(finalMaxSize.width());
3207 if (insetRect.size().height() > finalMaxSize.height())
3208 insetRect.setHeight(finalMaxSize.height());
3211 insetRect.setSize(finalMinSize);
3213 if (al.testFlag(Qt::AlignLeft)) insetRect.moveLeft(
rect().x());
3214 else if (al.testFlag(Qt::AlignRight)) insetRect.moveRight(
rect().x()+
rect().width());
3215 else insetRect.moveLeft(
rect().x()+
rect().width()*0.5-finalMinSize.width()*0.5);
3216 if (al.testFlag(Qt::AlignTop)) insetRect.moveTop(
rect().y());
3217 else if (al.testFlag(Qt::AlignBottom)) insetRect.moveBottom(
rect().y()+
rect().height());
3218 else insetRect.moveTop(
rect().y()+
rect().height()*0.5-finalMinSize.height()*0.5);
3220 mElements.at(i)->setOuterRect(insetRect);
3233 if (index >= 0 && index <
mElements.size())
3252 qDebug() << Q_FUNC_INFO <<
"Attempt to take invalid index:" << index;
3270 qDebug() << Q_FUNC_INFO <<
"Element not in this layout, couldn't take";
3272 qDebug() << Q_FUNC_INFO <<
"Can't take null element";
3295 if (
mElements.at(i)->realVisibility() &&
mElements.at(i)->selectTest(pos, onlySelectable) >= 0)
3321 mInsetRect.append(QRectF(0.6, 0.6, 0.4, 0.4));
3324 qDebug() << Q_FUNC_INFO <<
"Can't add null element";
3350 qDebug() << Q_FUNC_INFO <<
"Can't add null element";
3522 QVector2D lengthVec(dir.normalized());
3523 if (lengthVec.isNull())
3524 lengthVec = QVector2D(1, 0);
3525 QVector2D widthVec(-lengthVec.y(), lengthVec.x());
3529 QPen penBackup = painter->pen();
3530 QBrush brushBackup = painter->brush();
3531 QPen miterPen = penBackup;
3532 miterPen.setJoinStyle(Qt::MiterJoin);
3533 QBrush brush(painter->pen().color(), Qt::SolidPattern);
3539 QPointF points[3] = {pos.toPointF(),
3540 (pos-lengthVec+widthVec).toPointF(),
3541 (pos-lengthVec-widthVec).toPointF()
3543 painter->
setPen(miterPen);
3544 painter->setBrush(brush);
3545 painter->drawConvexPolygon(points, 3);
3546 painter->setBrush(brushBackup);
3547 painter->
setPen(penBackup);
3552 QPointF points[4] = {pos.toPointF(),
3553 (pos-lengthVec+widthVec).toPointF(),
3554 (pos-lengthVec*0.8f).toPointF(),
3555 (pos-lengthVec-widthVec).toPointF()
3557 painter->
setPen(miterPen);
3558 painter->setBrush(brush);
3559 painter->drawConvexPolygon(points, 4);
3560 painter->setBrush(brushBackup);
3561 painter->
setPen(penBackup);
3566 QPointF points[3] = {(pos-lengthVec+widthVec).toPointF(),
3568 (pos-lengthVec-widthVec).toPointF()
3570 painter->
setPen(miterPen);
3571 painter->drawPolyline(points, 3);
3572 painter->
setPen(penBackup);
3577 painter->setBrush(brush);
3578 painter->drawEllipse(pos.toPointF(),
mWidth*0.5,
mWidth*0.5);
3579 painter->setBrush(brushBackup);
3584 QVector2D widthVecPerp(-widthVec.y(), widthVec.x());
3585 QPointF points[4] = {(pos-widthVecPerp+widthVec).toPointF(),
3586 (pos-widthVecPerp-widthVec).toPointF(),
3587 (pos+widthVecPerp-widthVec).toPointF(),
3588 (pos+widthVecPerp+widthVec).toPointF()
3590 painter->
setPen(miterPen);
3591 painter->setBrush(brush);
3592 painter->drawConvexPolygon(points, 4);
3593 painter->setBrush(brushBackup);
3594 painter->
setPen(penBackup);
3599 QVector2D widthVecPerp(-widthVec.y(), widthVec.x());
3600 QPointF points[4] = {(pos-widthVecPerp).toPointF(),
3601 (pos-widthVec).toPointF(),
3602 (pos+widthVecPerp).toPointF(),
3603 (pos+widthVec).toPointF()
3605 painter->
setPen(miterPen);
3606 painter->setBrush(brush);
3607 painter->drawConvexPolygon(points, 4);
3608 painter->setBrush(brushBackup);
3609 painter->
setPen(penBackup);
3614 painter->
drawLine((pos+widthVec).toPointF(), (pos-widthVec).toPointF());
3619 painter->
drawLine((pos+widthVec).toPointF(), pos.toPointF());
3628 (pos-widthVec-lengthVec*0.2f*(
mInverted?-1:1)).toPointF());
3632 painter->
drawLine((pos+widthVec+lengthVec*0.2f*(
mInverted?-1:1)+dir.normalized()*qMax(1.0f, (
float)painter->pen().widthF())*0.5f).toPointF(),
3633 (pos-widthVec-lengthVec*0.2f*(
mInverted?-1:1)+dir.normalized()*qMax(1.0f, (
float)painter->pen().widthF())*0.5f).toPointF());
3647 draw(painter, pos, QVector2D(qCos(angle), qSin(angle)));
3674 QCPLayerable(parentAxis->parentPlot(), QString(), parentAxis),
3675 mParentAxis(parentAxis)
3678 setParent(parentAxis);
3679 setPen(QPen(QColor(200,200,200), 0, Qt::DotLine));
3766 if (!
mParentAxis) { qDebug() << Q_FUNC_INFO <<
"invalid parent axis";
return; }
3781 if (!
mParentAxis) { qDebug() << Q_FUNC_INFO <<
"invalid parent axis";
return; }
3789 int zeroLineIndex = -1;
3795 for (
int i=lowTick; i <= highTick; ++i)
3809 for (
int i=lowTick; i <= highTick; ++i)
3811 if (i == zeroLineIndex)
continue;
3818 int zeroLineIndex = -1;
3824 for (
int i=lowTick; i <= highTick; ++i)
3838 for (
int i=lowTick; i <= highTick; ++i)
3840 if (i == zeroLineIndex)
continue;
3855 if (!
mParentAxis) { qDebug() << Q_FUNC_INFO <<
"invalid parent axis";
return; }
3995 mOrientation(orientation(type)),
3996 mSelectableParts(spAxis | spTickLabels | spAxisLabel),
3997 mSelectedParts(spNone),
3998 mBasePen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
3999 mSelectedBasePen(QPen(Qt::blue, 2)),
4002 mLabelFont(mParentPlot->font()),
4003 mSelectedLabelFont(QFont(mLabelFont.family(), mLabelFont.pointSize(), QFont::Bold)),
4004 mLabelColor(Qt::black),
4005 mSelectedLabelColor(Qt::blue),
4008 mAutoTickLabels(true),
4009 mTickLabelType(ltNumber),
4010 mTickLabelFont(mParentPlot->font()),
4011 mSelectedTickLabelFont(QFont(mTickLabelFont.family(), mTickLabelFont.pointSize(), QFont::Bold)),
4012 mTickLabelColor(Qt::black),
4013 mSelectedTickLabelColor(Qt::blue),
4014 mDateTimeFormat(QLatin1String(
"hh:mm:ss\ndd.MM.yy")),
4015 mDateTimeSpec(Qt::LocalTime),
4016 mNumberPrecision(6),
4017 mNumberFormatChar(
'g'),
4018 mNumberBeautifulPowers(true),
4025 mAutoTickStep(true),
4026 mAutoSubTicks(true),
4027 mTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
4028 mSelectedTickPen(QPen(Qt::blue, 2)),
4029 mSubTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
4030 mSelectedSubTickPen(QPen(Qt::blue, 2)),
4033 mRangeReversed(false),
4034 mScaleType(stLinear),
4036 mScaleLogBaseLogInv(1.0/qLn(mScaleLogBase)),
4040 mLowestVisibleTick(0),
4041 mHighestVisibleTick(-1),
4042 mCachedMarginValid(false),
4062 }
else if (type ==
atLeft)
4100 result.append(QLatin1Char(
'b'));
4102 result.append(QLatin1Char(
'c'));
4195 qDebug() << Q_FUNC_INFO <<
"Invalid logarithmic scale base (must be greater 1):" << base;
4311 if (alignment == Qt::AlignLeft)
4313 else if (alignment == Qt::AlignRight)
4316 setRange(position-size/2.0, position+size/2.0);
4422 if (approximateCount > 0)
4427 qDebug() << Q_FUNC_INFO <<
"approximateCount must be greater than zero:" << approximateCount;
4693 if (formatCode.isEmpty())
4695 qDebug() << Q_FUNC_INFO <<
"Passed formatCode is empty";
4701 QString allowedFormatChars(QLatin1String(
"eEfgG"));
4702 if (allowedFormatChars.contains(formatCode.at(0)))
4707 qDebug() << Q_FUNC_INFO <<
"Invalid number format code (first char not in 'eEfgG'):" << formatCode;
4710 if (formatCode.length() < 2)
4723 qDebug() << Q_FUNC_INFO <<
"Invalid number format code (second char not 'b' or first char neither 'e' nor 'g'):" << formatCode;
4726 if (formatCode.length() < 3)
4733 if (formatCode.at(2) == QLatin1Char(
'c'))
4736 }
else if (formatCode.at(2) == QLatin1Char(
'd'))
4741 qDebug() << Q_FUNC_INFO <<
"Invalid number format code (third char neither 'c' nor 'd'):" << formatCode;
5193 qDebug() << Q_FUNC_INFO <<
"Center of scaling operation doesn't lie in same logarithmic sign domain as range:" << center;
5215 int otherPixelSize, ownPixelSize;
5227 double newRangeSize = ratio*otherAxis->
range().
size()*ownPixelSize/(double)otherPixelSize;
5239 QList<QCPAbstractPlottable*> p =
plottables();
5241 bool haveRange =
false;
5242 for (
int i=0; i<p.size(); ++i)
5244 if (!p.at(i)->realVisibility() && onlyVisiblePlottables)
5247 bool currentFoundRange;
5251 if (p.at(i)->keyAxis() ==
this)
5252 plottableRange = p.at(i)->getKeyRange(currentFoundRange, signDomain);
5254 plottableRange = p.at(i)->getValueRange(currentFoundRange, signDomain);
5255 if (currentFoundRange)
5258 newRange = plottableRange;
5260 newRange.
expand(plottableRange);
5268 double center = (newRange.
lower+newRange.
upper)*0.5;
5338 else if (value <= 0 && mRange.upper > 0)
5360 else if (value <= 0 && mRange.upper > 0)
5406 details->setValue(part);
5419 QList<QCPAbstractPlottable*> result;
5437 QList<QCPGraph*> result;
5456 QList<QCPAbstractItem*> result;
5461 QList<QCPItemPosition*> positions =
mParentPlot->
mItems.at(itemId)->positions();
5462 for (
int posId=0; posId<positions.size(); ++posId)
5464 if (positions.at(posId)->keyAxis() ==
this || positions.at(posId)->valueAxis() ==
this)
5488 qDebug() << Q_FUNC_INFO <<
"Invalid margin side passed:" << (int)side;
5503 default: qDebug() << Q_FUNC_INFO <<
"invalid axis type";
return atLeft;
break;
5539 double subTickStep = 0;
5540 double subTickPosition = 0;
5541 int subTickIndex = 0;
5545 for (
int i=lowTick+1; i<=highTick; ++i)
5550 subTickPosition =
mTickVector.at(i-1) + k*subTickStep;
5579 #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")
5615 double magnitudeFactor = qPow(10.0, qFloor(qLn(
mTickStep)/qLn(10.0)));
5616 double tickStepMantissa =
mTickStep/magnitudeFactor;
5617 if (tickStepMantissa < 5)
5620 mTickStep = (int)(tickStepMantissa*2)/2.0*magnitudeFactor;
5624 mTickStep = (int)(tickStepMantissa/2.0)*2.0*magnitudeFactor;
5632 int tickcount = lastStep-firstStep+1;
5633 if (tickcount < 0) tickcount = 0;
5635 for (
int i=0; i<tickcount; ++i)
5643 double currentMag = lowerMag;
5646 while (currentMag < mRange.upper && currentMag > 0)
5654 double currentMag = lowerMag;
5657 while (currentMag <
mRange.
upper && currentMag < 0)
5665 qDebug() << Q_FUNC_INFO <<
"Invalid range for logarithmic plot: " <<
mRange.
lower <<
"-" <<
mRange.
upper;
5688 double magnitudeFactor = qPow(10.0, qFloor(qLn(tickStep)/qLn(10.0)));
5689 double tickStepMantissa = tickStep/magnitudeFactor;
5692 double epsilon = 0.01;
5695 double fracPart = modf(tickStepMantissa, &intPartf);
5699 if (fracPart < epsilon || 1.0-fracPart < epsilon)
5701 if (1.0-fracPart < epsilon)
5705 case 1: result = 4;
break;
5706 case 2: result = 3;
break;
5707 case 3: result = 2;
break;
5708 case 4: result = 3;
break;
5709 case 5: result = 4;
break;
5710 case 6: result = 2;
break;
5711 case 7: result = 6;
break;
5712 case 8: result = 3;
break;
5713 case 9: result = 2;
break;
5718 if (qAbs(fracPart-0.5) < epsilon)
5722 case 1: result = 2;
break;
5723 case 2: result = 4;
break;
5724 case 3: result = 4;
break;
5725 case 4: result = 2;
break;
5726 case 5: result = 4;
break;
5727 case 6: result = 4;
break;
5728 case 7: result = 2;
break;
5729 case 8: result = 4;
break;
5730 case 9: result = 4;
break;
5748 if (selectionStateChanged)
5758 if (selectionStateChanged)
5789 QVector<double> subTickPositions;
5790 QVector<double> tickPositions;
5792 tickPositions.reserve(highTick-lowTick+1);
5793 tickLabels.reserve(highTick-lowTick+1);
5798 for (
int i=lowTick; i<=highTick; ++i)
5852 bool lowFound =
false;
5853 bool highFound =
false;
5876 if (!lowFound && highFound)
5877 lowIndex = highIndex+1;
5878 else if (lowFound && !highFound)
5879 highIndex = lowIndex-1;
6002 int lowTick, highTick;
6004 QVector<double> tickPositions;
6006 tickPositions.reserve(highTick-lowTick+1);
6007 tickLabels.reserve(highTick-lowTick+1);
6010 for (
int i=lowTick; i<=highTick; ++i)
6064 basePen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
6068 tickLabelPadding(0),
6069 tickLabelRotation(0),
6070 tickLabelSide(
QCPAxis::lsOutside),
6071 substituteExponent(true),
6072 numberMultiplyCross(false),
6076 subTickLengthOut(0),
6077 tickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
6078 subTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)),
6080 abbreviateDecimalPowers(false),
6081 reversedEndings(false),
6082 mParentPlot(parentPlot),
6116 double xCor = 0, yCor = 0;
6128 baseLine.setPoints(origin+QPointF(xCor, yCor), origin+QPointF(
axisRect.width()+xCor, yCor));
6130 baseLine.setPoints(origin+QPointF(xCor, yCor), origin+QPointF(xCor, -
axisRect.height()+yCor));
6132 baseLine = QLineF(baseLine.p2(), baseLine.p1());
6172 painter->setBrush(QBrush(
basePen.color()));
6173 QVector2D baseLineVector(baseLine.dx(), baseLine.dy());
6184 oldClipRect = painter->clipRegion().boundingRect();
6187 QSize tickLabelsSize(0, 0);
6195 int distanceToAxis = margin;
6198 for (
int i=0; i<maxLabelIndex; ++i)
6204 painter->setClipRect(oldClipRect);
6208 if (!
label.isEmpty())
6213 labelBounds = painter->fontMetrics().boundingRect(0, 0, 0, 0, Qt::TextDontClip,
label);
6216 QTransform oldTransform = painter->transform();
6217 painter->translate((origin.x()-margin-labelBounds.height()), origin.y());
6218 painter->rotate(-90);
6219 painter->drawText(0, 0,
axisRect.height(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter,
label);
6220 painter->setTransform(oldTransform);
6224 QTransform oldTransform = painter->transform();
6225 painter->translate((origin.x()+margin+labelBounds.height()), origin.y()-
axisRect.height());
6226 painter->rotate(90);
6227 painter->drawText(0, 0,
axisRect.height(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter,
label);
6228 painter->setTransform(oldTransform);
6231 painter->drawText(origin.x(), origin.y()-margin-labelBounds.height(),
axisRect.width(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter,
label);
6233 painter->drawText(origin.x(), origin.y()+margin,
axisRect.width(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter,
label);
6237 int selectionTolerance = 0;
6241 qDebug() << Q_FUNC_INFO <<
"mParentPlot is null";
6243 int selAxisInSize = selectionTolerance;
6244 int selTickLabelSize;
6245 int selTickLabelOffset;
6248 selTickLabelSize = (
QCPAxis::orientation(
type) == Qt::Horizontal ? tickLabelsSize.height() : tickLabelsSize.width());
6252 selTickLabelSize = -(
QCPAxis::orientation(
type) == Qt::Horizontal ? tickLabelsSize.height() : tickLabelsSize.width());
6255 int selLabelSize = labelBounds.height();
6302 QSize tickLabelsSize(0, 0);
6313 if (!
label.isEmpty())
6317 bounds = fontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip | Qt::AlignHCenter | Qt::AlignVCenter,
label);
6376 if (text.isEmpty())
return;
6378 QPointF labelAnchor;
6395 cachedLabel->
pixmap.fill(Qt::transparent);
6397 cachePainter.
setPen(painter->pen());
6401 bool labelClippedByBorder =
false;
6409 if (!labelClippedByBorder)
6411 painter->drawPixmap(labelAnchor+cachedLabel->
offset, cachedLabel->
pixmap);
6412 finalSize = cachedLabel->
pixmap.size();
6420 bool labelClippedByBorder =
false;
6428 if (!labelClippedByBorder)
6430 drawTickLabel(painter, finalPosition.x(), finalPosition.y(), labelData);
6436 if (finalSize.width() > tickLabelsSize->width())
6437 tickLabelsSize->setWidth(finalSize.width());
6438 if (finalSize.height() > tickLabelsSize->height())
6439 tickLabelsSize->setHeight(finalSize.height());
6454 QTransform oldTransform = painter->transform();
6455 QFont oldFont = painter->font();
6458 painter->translate(x, y);
6463 if (!labelData.
expPart.isEmpty())
6465 painter->setFont(labelData.
baseFont);
6466 painter->drawText(0, 0, 0, 0, Qt::TextDontClip, labelData.
basePart);
6467 painter->setFont(labelData.
expFont);
6471 painter->setFont(labelData.
baseFont);
6476 painter->setTransform(oldTransform);
6477 painter->setFont(oldFont);
6493 bool useBeautifulPowers =
false;
6498 ePos = text.indexOf(QLatin1Char(
'e'));
6499 if (ePos > 0 && text.at(ePos-1).isDigit())
6502 while (eLast+1 < text.size() && (text.at(eLast+1) == QLatin1Char(
'+') || text.at(eLast+1) == QLatin1Char(
'-') || text.at(eLast+1).isDigit()))
6505 useBeautifulPowers =
true;
6511 if (result.
baseFont.pointSizeF() > 0)
6513 if (useBeautifulPowers)
6519 result.
basePart = QLatin1String(
"10");
6522 result.
expPart = text.mid(ePos+1);
6524 while (result.
expPart.length() > 2 && result.
expPart.at(1) == QLatin1Char(
'0'))
6526 if (!result.
expPart.isEmpty() && result.
expPart.at(0) == QLatin1Char(
'+'))
6530 if (result.
expFont.pointSize() > 0)
6541 result.
totalBounds = QFontMetrics(result.
baseFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip | Qt::AlignHCenter, result.
basePart);
6549 QTransform transform;
6607 x = +qSin(radians)*labelData.
totalBounds.height();
6629 x = -qSin(-radians)*labelData.
totalBounds.height()/2.0;
6630 y = -qCos(-radians)*labelData.
totalBounds.height();
6643 x = +qSin(radians)*labelData.
totalBounds.height()/2.0;
6648 y = +qSin(-radians)*labelData.
totalBounds.width();
6657 return QPointF(x, y);
6674 finalSize = cachedLabel->
pixmap.size();
6682 if (finalSize.width() > tickLabelsSize->width())
6683 tickLabelsSize->setWidth(finalSize.width());
6684 if (finalSize.height() > tickLabelsSize->height())
6685 tickLabelsSize->setHeight(finalSize.height());
6841 QCPLayerable(keyAxis->parentPlot(), QString(), keyAxis->axisRect()),
6843 mAntialiasedFill(true),
6844 mAntialiasedScatters(true),
6845 mAntialiasedErrorBars(false),
6847 mSelectedPen(Qt::black),
6848 mBrush(Qt::NoBrush),
6849 mSelectedBrush(Qt::NoBrush),
6851 mValueAxis(valueAxis),
6856 qDebug() << Q_FUNC_INFO <<
"Parent plot of keyAxis is not the same as that of valueAxis.";
6858 qDebug() << Q_FUNC_INFO <<
"keyAxis and valueAxis must be orthogonal to each other.";
7053 if (!keyAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key axis";
return; }
7067 double center = (newRange.
lower+newRange.
upper)*0.5;
7093 if (!valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid value axis";
return; }
7107 double center = (newRange.
lower+newRange.
upper)*0.5;
7197 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
7219 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return QPointF(); }
7241 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
7367 double vLengthSqr = v.lengthSquared();
7368 if (!qFuzzyIsNull(vLengthSqr))
7370 double mu = QVector2D::dotProduct(p-a, v)/vLengthSqr;
7372 return (a-p).lengthSquared();
7374 return (b-p).lengthSquared();
7376 return ((a + mu*v)-p).lengthSquared();
7378 return (a-p).lengthSquared();
7390 if (selectionStateChanged)
7391 *selectionStateChanged =
mSelected != selBefore;
7402 if (selectionStateChanged)
7403 *selectionStateChanged =
mSelected != selBefore;
7454 mParentPlot(parentPlot),
7455 mParentItem(parentItem),
7490 qDebug() << Q_FUNC_INFO <<
"no valid anchor id set:" <<
mAnchorId;
7495 qDebug() << Q_FUNC_INFO <<
"no parent item set";
7513 qDebug() << Q_FUNC_INFO <<
"provided pos is child already" <<
reinterpret_cast<quintptr
>(pos);
7525 qDebug() << Q_FUNC_INFO <<
"provided pos isn't child" <<
reinterpret_cast<quintptr
>(pos);
7541 qDebug() << Q_FUNC_INFO <<
"provided pos is child already" <<
reinterpret_cast<quintptr
>(pos);
7553 qDebug() << Q_FUNC_INFO <<
"provided pos isn't child" <<
reinterpret_cast<quintptr
>(pos);
7627 mPositionTypeX(ptAbsolute),
7628 mPositionTypeY(ptAbsolute),
7708 bool retainPixelPosition =
true;
7710 retainPixelPosition =
false;
7712 retainPixelPosition =
false;
7715 if (retainPixelPosition)
7720 if (retainPixelPosition)
7738 bool retainPixelPosition =
true;
7740 retainPixelPosition =
false;
7742 retainPixelPosition =
false;
7745 if (retainPixelPosition)
7750 if (retainPixelPosition)
7777 return successX && successY;
7790 if (parentAnchor ==
this)
7792 qDebug() << Q_FUNC_INFO <<
"can't set self as parent anchor" <<
reinterpret_cast<quintptr
>(
parentAnchor);
7797 while (currentParent)
7802 if (currentParentPos ==
this)
7804 qDebug() << Q_FUNC_INFO <<
"can't create recursive parent-child-relationship" <<
reinterpret_cast<quintptr
>(
parentAnchor);
7807 currentParent = currentParentPos->parentAnchorX();
7815 qDebug() << Q_FUNC_INFO <<
"can't set parent to be an anchor which itself depends on this position" <<
reinterpret_cast<quintptr
>(
parentAnchor);
7828 if (keepPixelPosition)
7838 if (keepPixelPosition)
7855 if (parentAnchor ==
this)
7857 qDebug() << Q_FUNC_INFO <<
"can't set self as parent anchor" <<
reinterpret_cast<quintptr
>(
parentAnchor);
7862 while (currentParent)
7867 if (currentParentPos ==
this)
7869 qDebug() << Q_FUNC_INFO <<
"can't create recursive parent-child-relationship" <<
reinterpret_cast<quintptr
>(
parentAnchor);
7872 currentParent = currentParentPos->parentAnchorY();
7880 qDebug() << Q_FUNC_INFO <<
"can't set parent to be an anchor which itself depends on this position" <<
reinterpret_cast<quintptr
>(
parentAnchor);
7893 if (keepPixelPosition)
7903 if (keepPixelPosition)
7980 result.rx() +=
mAxisRect.data()->left();
7982 qDebug() << Q_FUNC_INFO <<
"Item position type x is ptAxisRectRatio, but no axis rect was defined";
7992 qDebug() << Q_FUNC_INFO <<
"Item position type x is ptPlotCoords, but no axes were defined";
8026 qDebug() << Q_FUNC_INFO <<
"Item position type y is ptAxisRectRatio, but no axis rect was defined";
8036 qDebug() << Q_FUNC_INFO <<
"Item position type y is ptPlotCoords, but no axes were defined";
8077 double x = pixelPoint.x();
8078 double y = pixelPoint.y();
8107 qDebug() << Q_FUNC_INFO <<
"Item position type x is ptAxisRectRatio, but no axis rect was defined";
8113 x =
mKeyAxis.data()->pixelToCoord(x);
8117 qDebug() << Q_FUNC_INFO <<
"Item position type x is ptPlotCoords, but no axes were defined";
8147 y /= (double)
mAxisRect.data()->height();
8149 qDebug() << Q_FUNC_INFO <<
"Item position type y is ptAxisRectRatio, but no axis rect was defined";
8155 x =
mKeyAxis.data()->pixelToCoord(y);
8159 qDebug() << Q_FUNC_INFO <<
"Item position type y is ptPlotCoords, but no axes were defined";
8342 mClipToAxisRect(false),
8346 QList<QCPAxisRect*> rects = parentPlot->
axisRects();
8347 if (rects.size() > 0)
8450 qDebug() << Q_FUNC_INFO <<
"position with name not found:" << name;
8466 for (
int i=0; i<
mAnchors.size(); ++i)
8468 if (
mAnchors.at(i)->name() == name)
8471 qDebug() << Q_FUNC_INFO <<
"anchor with name not found:" << name;
8485 for (
int i=0; i<
mAnchors.size(); ++i)
8487 if (
mAnchors.at(i)->name() == name)
8547 double vLengthSqr = v.lengthSquared();
8548 if (!qFuzzyIsNull(vLengthSqr))
8550 double mu = QVector2D::dotProduct(p-a, v)/vLengthSqr;
8552 return (a-p).lengthSquared();
8554 return (b-p).lengthSquared();
8556 return ((a + mu*v)-p).lengthSquared();
8558 return (a-p).lengthSquared();
8581 QList<QLineF> lines;
8582 lines << QLineF(rect.topLeft(), rect.topRight()) << QLineF(rect.bottomLeft(), rect.bottomRight())
8583 << QLineF(rect.topLeft(), rect.bottomLeft()) << QLineF(rect.topRight(), rect.bottomRight());
8584 double minDistSqr = std::numeric_limits<double>::max();
8585 for (
int i=0; i<lines.size(); ++i)
8587 double distSqr =
distSqrToLine(lines.at(i).p1(), lines.at(i).p2(), pos);
8588 if (distSqr < minDistSqr)
8589 minDistSqr = distSqr;
8591 result = qSqrt(minDistSqr);
8596 if (rect.contains(pos))
8614 qDebug() << Q_FUNC_INFO <<
"called on item which shouldn't have any anchors (this method not reimplemented). anchorId" << anchorId;
8635 qDebug() << Q_FUNC_INFO <<
"anchor/position with name exists already:" << name;
8669 qDebug() << Q_FUNC_INFO <<
"anchor/position with name exists already:" << name;
8684 if (selectionStateChanged)
8685 *selectionStateChanged =
mSelected != selBefore;
8696 if (selectionStateChanged)
8697 *selectionStateChanged =
mSelected != selBefore;
9025 mAutoAddPlottableToLegend(true),
9026 mAntialiasedElements(QCP::
aeNone),
9027 mNotAntialiasedElements(QCP::
aeNone),
9029 mSelectionTolerance(8),
9030 mNoAntialiasingOnDrag(false),
9031 mBackgroundBrush(Qt::white, Qt::SolidPattern),
9032 mBackgroundScaled(true),
9033 mBackgroundScaledMode(Qt::KeepAspectRatioByExpanding),
9036 mMultiSelectModifier(Qt::ControlModifier),
9037 mPaintBuffer(size()),
9038 mMouseEventElement(0),
9041 setAttribute(Qt::WA_NoMousePropagation);
9042 setAttribute(Qt::WA_OpaquePaintEvent);
9043 setMouseTracking(
true);
9044 QLocale currentLocale = locale();
9045 currentLocale.setNumberOptions(QLocale::OmitGroupSeparator);
9046 setLocale(currentLocale);
9073 defaultAxisRect->
setLayer(QLatin1String(
"background"));
9464 qDebug() << Q_FUNC_INFO <<
"index out of bounds:" << index;
9499 qDebug() << Q_FUNC_INFO <<
"plottable already added to this QCustomPlot:" <<
reinterpret_cast<quintptr
>(
plottable);
9504 qDebug() << Q_FUNC_INFO <<
"plottable not created with this QCustomPlot as parent:" <<
reinterpret_cast<quintptr
>(
plottable);
9515 if (!plottable->
layer())
9531 qDebug() << Q_FUNC_INFO <<
"plottable not in list:" <<
reinterpret_cast<quintptr
>(
plottable);
9556 qDebug() << Q_FUNC_INFO <<
"index out of bounds:" << index;
9571 for (
int i=c-1; i >= 0; --i)
9595 QList<QCPAbstractPlottable*> result;
9599 result.append(plottable);
9623 if (onlySelectable && !plottable->
selectable())
9627 double currentDistance = plottable->
selectTest(pos,
false);
9628 if (currentDistance >= 0 && currentDistance < resultDistance)
9631 resultDistance = currentDistance;
9636 return resultPlottable;
9659 if (index >= 0 && index <
mGraphs.size())
9664 qDebug() << Q_FUNC_INFO <<
"index out of bounds:" << index;
9699 if (!keyAxis) keyAxis =
xAxis;
9700 if (!valueAxis) valueAxis =
yAxis;
9701 if (!keyAxis || !valueAxis)
9703 qDebug() << Q_FUNC_INFO <<
"can't use default QCustomPlot xAxis or yAxis, because at least one is invalid (has been deleted)";
9708 qDebug() << Q_FUNC_INFO <<
"passed keyAxis or valueAxis doesn't have this QCustomPlot as parent";
9715 newGraph->
setName(QLatin1String(
"Graph ")+QString::number(
mGraphs.size()));
9744 if (index >= 0 && index <
mGraphs.size())
9760 for (
int i=c-1; i >= 0; --i)
9785 QList<QCPGraph*> result;
9789 result.append(graph);
9804 if (index >= 0 && index <
mItems.size())
9809 qDebug() << Q_FUNC_INFO <<
"index out of bounds:" << index;
9846 qDebug() << Q_FUNC_INFO <<
"item either already in list or not created with this QCustomPlot as parent:" <<
reinterpret_cast<quintptr
>(
item);
9860 if (
mItems.contains(item))
9867 qDebug() << Q_FUNC_INFO <<
"item not in list:" <<
reinterpret_cast<quintptr
>(
item);
9878 if (index >= 0 && index <
mItems.size())
9882 qDebug() << Q_FUNC_INFO <<
"index out of bounds:" << index;
9897 for (
int i=c-1; i >= 0; --i)
9919 QList<QCPAbstractItem*> result;
9923 result.append(item);
9952 double currentDistance = item->
selectTest(pos,
false);
9953 if (currentDistance >= 0 && currentDistance < resultDistance)
9956 resultDistance = currentDistance;
9971 return mItems.contains(item);
9986 if (layer->
name() == name)
10000 if (index >= 0 && index <
mLayers.size())
10005 qDebug() << Q_FUNC_INFO <<
"index out of bounds:" << index;
10035 qDebug() << Q_FUNC_INFO <<
"layer with name doesn't exist:" << name;
10050 if (!
mLayers.contains(layer))
10052 qDebug() << Q_FUNC_INFO <<
"layer not a layer of this QCustomPlot:" <<
reinterpret_cast<quintptr
>(
layer);
10087 if (!
mLayers.contains(otherLayer))
10089 qDebug() << Q_FUNC_INFO <<
"otherLayer not a layer of this QCustomPlot:" <<
reinterpret_cast<quintptr
>(otherLayer);
10094 qDebug() << Q_FUNC_INFO <<
"A layer exists already with the name" << name;
10120 if (!
mLayers.contains(layer))
10122 qDebug() << Q_FUNC_INFO <<
"layer not a layer of this QCustomPlot:" <<
reinterpret_cast<quintptr
>(
layer);
10127 qDebug() << Q_FUNC_INFO <<
"can't remove last layer";
10132 int removedIndex = layer->
index();
10133 bool isFirstLayer = removedIndex==0;
10135 QList<QCPLayerable*> children = layer->
children();
10138 for (
int i=children.size()-1; i>=0; --i)
10139 children.at(i)->moveToLayer(targetLayer,
true);
10142 for (
int i=0; i<children.size(); ++i)
10143 children.at(i)->moveToLayer(targetLayer,
false);
10166 if (!
mLayers.contains(layer))
10168 qDebug() << Q_FUNC_INFO <<
"layer not a layer of this QCustomPlot:" <<
reinterpret_cast<quintptr
>(
layer);
10171 if (!
mLayers.contains(otherLayer))
10173 qDebug() << Q_FUNC_INFO <<
"otherLayer not a layer of this QCustomPlot:" <<
reinterpret_cast<quintptr
>(otherLayer);
10179 else if (layer->
index() < otherLayer->
index())
10211 const QList<QCPAxisRect*> rectList =
axisRects();
10212 if (index >= 0 && index < rectList.size())
10214 return rectList.at(index);
10217 qDebug() << Q_FUNC_INFO <<
"invalid axis rect index" << index;
10229 QList<QCPAxisRect*> result;
10230 QStack<QCPLayoutElement*> elementStack;
10234 while (!elementStack.isEmpty())
10240 elementStack.push(element);
10241 if (
QCPAxisRect *ar = qobject_cast<QCPAxisRect*>(element))
10262 bool searchSubElements =
true;
10263 while (searchSubElements && currentElement)
10265 searchSubElements =
false;
10270 currentElement = subElement;
10271 searchSubElements =
true;
10276 return currentElement;
10288 QList<QCPAxis*> result, allAxes;
10290 allAxes << rect->
axes();
10292 foreach (
QCPAxis *axis, allAxes)
10295 result.append(axis);
10310 QList<QCPLegend*> result;
10312 QStack<QCPLayoutElement*> elementStack;
10316 while (!elementStack.isEmpty())
10322 elementStack.push(subElement);
10323 if (
QCPLegend *leg = qobject_cast<QCPLegend*>(subElement))
10326 result.append(leg);
10376 if (painter.isActive())
10378 painter.setRenderHint(QPainter::HighQualityAntialiasing);
10388 qDebug() << Q_FUNC_INFO <<
"Couldn't activate painter on buffer. This usually happens because QCustomPlot has width or height zero.";
10404 QList<QCPAxis*> allAxes;
10406 allAxes << rect->
axes();
10408 foreach (
QCPAxis *axis, allAxes)
10409 axis->
rescale(onlyVisiblePlottables);
10449 bool QCustomPlot::savePdf(
const QString &fileName,
bool noCosmeticPen,
int width,
int height,
const QString &pdfCreator,
const QString &pdfTitle)
10451 bool success =
false;
10452 #ifdef QT_NO_PRINTER
10454 Q_UNUSED(noCosmeticPen)
10457 Q_UNUSED(pdfCreator)
10459 qDebug() << Q_FUNC_INFO <<
"Qt was built without printer support (QT_NO_PRINTER). PDF not created.";
10461 int newWidth, newHeight;
10462 if (width == 0 || height == 0)
10464 newWidth = this->width();
10465 newHeight = this->height();
10469 newHeight = height;
10472 QPrinter printer(QPrinter::ScreenResolution);
10473 printer.setOutputFileName(fileName);
10474 printer.setOutputFormat(QPrinter::PdfFormat);
10475 printer.setColorMode(QPrinter::Color);
10476 printer.printEngine()->setProperty(QPrintEngine::PPK_Creator, pdfCreator);
10477 printer.printEngine()->setProperty(QPrintEngine::PPK_DocumentName, pdfTitle);
10480 #if QT_VERSION < QT_VERSION_CHECK(5, 3, 0)
10481 printer.setFullPage(
true);
10482 printer.setPaperSize(
viewport().size(), QPrinter::DevicePixel);
10484 QPageLayout pageLayout;
10485 pageLayout.setMode(QPageLayout::FullPageMode);
10486 pageLayout.setOrientation(QPageLayout::Portrait);
10487 pageLayout.setMargins(QMarginsF(0, 0, 0, 0));
10488 pageLayout.setPageSize(QPageSize(
viewport().size(), QPageSize::Point, QString(), QPageSize::ExactMatch));
10489 printer.setPageLayout(pageLayout);
10492 if (printpainter.
begin(&printer))
10503 draw(&printpainter);
10504 printpainter.end();
10508 #endif // QT_NO_PRINTER
10551 return saveRastered(fileName, width, height, scale,
"PNG", quality);
10590 return saveRastered(fileName, width, height, scale,
"JPG", quality);
10626 return saveRastered(fileName, width, height, scale,
"BMP");
10660 QPainter painter(
this);
10697 else if (
QCPAxis *ax = qobject_cast<QCPAxis*>(clickedLayerable))
10699 else if (
QCPAbstractItem *ai = qobject_cast<QCPAbstractItem*>(clickedLayerable))
10701 else if (
QCPLegend *lg = qobject_cast<QCPLegend*>(clickedLayerable))
10705 else if (
QCPPlotTitle *pt = qobject_cast<QCPPlotTitle*>(clickedLayerable))
10710 el->mouseDoubleClickEvent(event);
10739 QWidget::mousePressEvent(event);
10759 QWidget::mouseMoveEvent(event);
10779 bool doReplot =
false;
10783 if (event->button() == Qt::LeftButton)
10788 bool selectionStateChanged =
false;
10799 bool selChanged =
false;
10801 selectionStateChanged |= selChanged;
10809 bool selChanged =
false;
10810 clickedLayerable->
selectEvent(event, additive, details, &selChanged);
10811 selectionStateChanged |= selChanged;
10813 if (selectionStateChanged)
10825 else if (
QCPAxis *ax = qobject_cast<QCPAxis*>(clickedLayerable))
10827 else if (
QCPAbstractItem *ai = qobject_cast<QCPAbstractItem*>(clickedLayerable))
10829 else if (
QCPLegend *lg = qobject_cast<QCPLegend*>(clickedLayerable))
10833 else if (
QCPPlotTitle *pt = qobject_cast<QCPPlotTitle*>(clickedLayerable))
10847 QWidget::mouseReleaseEvent(event);
10862 el->wheelEvent(event);
10864 QWidget::wheelEvent(event);
10892 painter->setClipRect(child->
clipRect().translated(0, -1));
10894 child->
draw(painter);
10978 if (this->legend == legend)
10990 for (
int i=0; i<
mLayers.size(); ++i)
11008 for (
int layerIndex=
mLayers.size()-1; layerIndex>=0; --layerIndex)
11010 const QList<QCPLayerable*> layerables =
mLayers.at(layerIndex)->children();
11013 for (
int i=layerables.size()-1; i>=0; --i)
11015 if (!layerables.at(i)->realVisibility())
11018 double dist = layerables.at(i)->
selectTest(pos, onlySelectable, &details);
11019 if (dist >= 0 && dist < minimumDistance)
11021 minimumDistance = dist;
11022 minimumDistanceLayerable = layerables.at(i);
11023 if (selectionDetails) *selectionDetails = details;
11027 return minimumDistanceLayerable;
11045 QPixmap buffer =
toPixmap(width, height, scale);
11046 if (!buffer.isNull())
11047 return buffer.save(fileName, format, quality);
11063 int newWidth, newHeight;
11064 if (width == 0 || height == 0)
11066 newWidth = this->width();
11067 newHeight = this->height();
11071 newHeight = height;
11073 int scaledWidth = qRound(scale*newWidth);
11074 int scaledHeight = qRound(scale*newHeight);
11076 QPixmap result(scaledWidth, scaledHeight);
11079 painter.
begin(&result);
11080 if (painter.isActive())
11085 if (!qFuzzyCompare(scale, 1.0))
11089 painter.scale(scale, scale);
11098 qDebug() << Q_FUNC_INFO <<
"Couldn't activate painter on pixmap";
11119 int newWidth, newHeight;
11120 if (width == 0 || height == 0)
11122 newWidth = this->width();
11123 newHeight = this->height();
11127 newHeight = height;
11130 if (painter->isActive())
11140 qDebug() << Q_FUNC_INFO <<
"Passed painter is not active";
11180 mColorInterpolation(ciRGB),
11182 mColorBufferInvalidated(true)
11191 return ((other.
mLevelCount == this->mLevelCount) &&
11193 (other.
mPeriodic == this->mPeriodic) &&
11207 qDebug() << Q_FUNC_INFO <<
"n must be greater or equal 2 but was" << n;
11298 qDebug() << Q_FUNC_INFO <<
"null pointer given as data";
11303 qDebug() << Q_FUNC_INFO <<
"null pointer given as scanLine";
11314 for (
int i=0; i<n; ++i)
11316 int index = (int)((data[dataIndexFactor*i]-range.
lower)*posToIndexFactor) %
mLevelCount;
11323 for (
int i=0; i<n; ++i)
11325 int index = (data[dataIndexFactor*i]-range.
lower)*posToIndexFactor;
11337 for (
int i=0; i<n; ++i)
11346 for (
int i=0; i<n; ++i)
11525 for (QMap<double, QColor>::const_iterator it=
mColorStops.constBegin(); it!=
mColorStops.constEnd(); ++it)
11541 double indexToPosFactor = 1.0/(double)(
mLevelCount-1);
11544 double position = i*indexToPosFactor;
11545 QMap<double, QColor>::const_iterator it =
mColorStops.lowerBound(position);
11554 QMap<double, QColor>::const_iterator high = it;
11555 QMap<double, QColor>::const_iterator low = it-1;
11556 double t = (position-low.key())/(high.key()-low.key());
11561 mColorBuffer[i] = qRgb((1-t)*low.value().red() + t*high.value().red(),
11562 (1-t)*low.value().green() + t*high.value().green(),
11563 (1-t)*low.value().blue() + t*high.value().blue());
11568 QColor lowHsv = low.value().toHsv();
11569 QColor highHsv = high.value().toHsv();
11571 double hueDiff = highHsv.hueF()-lowHsv.hueF();
11573 hue = lowHsv.hueF() - t*(1.0-hueDiff);
11574 else if (hueDiff < -0.5)
11575 hue = lowHsv.hueF() + t*(1.0+hueDiff);
11577 hue = lowHsv.hueF() + t*hueDiff;
11578 if (hue < 0) hue += 1.0;
11579 else if (hue >= 1.0) hue -= 1.0;
11580 mColorBuffer[i] = QColor::fromHsvF(hue, (1-t)*lowHsv.saturationF() + t*highHsv.saturationF(), (1-t)*lowHsv.valueF() + t*highHsv.valueF()).rgb();
11728 mBackgroundBrush(Qt::NoBrush),
11729 mBackgroundScaled(true),
11730 mBackgroundScaledMode(Qt::KeepAspectRatioByExpanding),
11732 mRangeDrag(Qt::Horizontal|Qt::Vertical),
11733 mRangeZoom(Qt::Horizontal|Qt::Vertical),
11734 mRangeZoomFactorHorz(0.85),
11735 mRangeZoomFactorVert(0.85),
11749 if (setupDefaultAxes)
11775 QList<QCPAxis*> axesList =
axes();
11776 for (
int i=0; i<axesList.size(); ++i)
11787 return mAxes.value(type).size();
11797 QList<QCPAxis*> ax(
mAxes.value(type));
11798 if (index >= 0 && index < ax.size())
11800 return ax.at(index);
11803 qDebug() << Q_FUNC_INFO <<
"Axis index out of bounds:" << index;
11818 QList<QCPAxis*> result;
11836 QList<QCPAxis*> result;
11837 QHashIterator<QCPAxis::AxisType, QList<QCPAxis*> > it(
mAxes);
11838 while (it.hasNext())
11841 result << it.value();
11870 newAxis =
new QCPAxis(
this, type);
11875 qDebug() << Q_FUNC_INFO <<
"passed axis has different axis type than specified in type parameter";
11880 qDebug() << Q_FUNC_INFO <<
"passed axis doesn't have this axis rect as parent axis rect";
11883 if (
axes().contains(newAxis))
11885 qDebug() << Q_FUNC_INFO <<
"passed axis is already owned by this axis rect";
11895 mAxes[type].append(newAxis);
11909 QList<QCPAxis*> result;
11931 QHashIterator<QCPAxis::AxisType, QList<QCPAxis*> > it(
mAxes);
11932 while (it.hasNext())
11935 if (it.value().contains(axis))
11937 mAxes[it.key()].removeOne(axis);
11938 if (qobject_cast<QCustomPlot*>(
parentPlot()))
11944 qDebug() << Q_FUNC_INFO <<
"Axis isn't in axis rect:" <<
reinterpret_cast<quintptr
>(
axis);
11976 QCPAxis *xAxis, *yAxis, *xAxis2, *yAxis2;
12038 connect(xAxis, SIGNAL(rangeChanged(
QCPRange)), xAxis2, SLOT(setRange(
QCPRange)));
12039 connect(yAxis, SIGNAL(rangeChanged(
QCPRange)), yAxis2, SLOT(setRange(
QCPRange)));
12054 QList<QCPAbstractPlottable*> result;
12074 QList<QCPGraph*> result;
12097 QList<QCPAbstractItem*> result;
12105 QList<QCPItemPosition*> positions =
mParentPlot->
mItems.at(itemId)->positions();
12106 for (
int posId=0; posId<positions.size(); ++posId)
12108 if (positions.at(posId)->axisRect() ==
this ||
12109 positions.at(posId)->keyAxis()->axisRect() ==
this ||
12110 positions.at(posId)->valueAxis()->axisRect() ==
this)
12136 QList<QCPAxis*> allAxes =
axes();
12137 for (
int i=0; i<allAxes.size(); ++i)
12138 allAxes.at(i)->setupTickVectors();
12156 QList<QCPLayoutElement*> result;
12161 result << mInsetLayout->
elements(recursive);
12433 const QList<QCPAxis*> axesList =
mAxes.value(type);
12434 if (axesList.isEmpty())
12437 bool isFirstVisible = !axesList.first()->visible();
12438 for (
int i=1; i<axesList.size(); ++i)
12440 int offset = axesList.at(i-1)->offset() + axesList.at(i-1)->calculateMargin();
12441 if (axesList.at(i)->visible())
12443 if (!isFirstVisible)
12444 offset += axesList.at(i)->tickLengthIn();
12445 isFirstVisible =
false;
12447 axesList.at(i)->setOffset(offset);
12455 qDebug() << Q_FUNC_INFO <<
"Called with side that isn't specified as auto margin";
12461 if (axesList.size() > 0)
12462 return axesList.last()->offset() + axesList.last()->calculateMargin();
12481 if (event->buttons() & Qt::LeftButton)
12519 double diff = rangeDragHorzAxis->pixelToCoord(
mDragStart.x()) - rangeDragHorzAxis->pixelToCoord(event->pos().x());
12523 double diff = rangeDragHorzAxis->pixelToCoord(
mDragStart.x()) / rangeDragHorzAxis->pixelToCoord(event->pos().x());
12534 double diff = rangeDragVertAxis->pixelToCoord(
mDragStart.y()) - rangeDragVertAxis->pixelToCoord(event->pos().y());
12538 double diff = rangeDragVertAxis->pixelToCoord(
mDragStart.y()) / rangeDragVertAxis->pixelToCoord(event->pos().y());
12586 double wheelSteps =
event->delta()/120.0;
12649 mParentLegend(parent),
12650 mFont(parent->font()),
12651 mTextColor(parent->textColor()),
12652 mSelectedFont(parent->selectedFont()),
12653 mSelectedTextColor(parent->selectedTextColor()),
12657 setLayer(QLatin1String(
"legend"));
12742 if (
mRect.contains(pos.toPoint()))
12769 if (selectionStateChanged)
12770 *selectionStateChanged =
mSelected != selBefore;
12781 if (selectionStateChanged)
12782 *selectionStateChanged =
mSelected != selBefore;
12825 mPlottable(plottable)
12871 QRectF textRect = painter->fontMetrics().boundingRect(0, 0, 0, iconSize.height(), Qt::TextDontClip,
mPlottable->
name());
12872 QRectF iconRect(
mRect.topLeft(), iconSize);
12873 int textHeight = qMax(textRect.height(), iconSize.height());
12877 painter->setClipRect(iconRect, Qt::IntersectClip);
12884 painter->setBrush(Qt::NoBrush);
12885 painter->drawRect(iconRect);
12897 QSize result(0, 0);
12899 QFontMetrics fontMetrics(
getFont());
12901 textRect = fontMetrics.boundingRect(0, 0, 0, iconSize.height(), Qt::TextDontClip,
mPlottable->
name());
12903 result.setHeight(qMax(textRect.height(), iconSize.height()) +
mMargins.top() +
mMargins.bottom());
12987 bool hasSelectedItems =
false;
12992 hasSelectedItems =
true;
12996 if (hasSelectedItems)
13136 SelectableParts newSelected = selected;
13143 qDebug() << Q_FUNC_INFO <<
"spItems flag can not be set, it can only be unset with this function";
13247 if (pli->plottable() == plottable)
13270 if (item == this->
item(i))
13314 bool success =
remove(ali);
13331 bool success =
remove(
item);
13353 QList<QCPAbstractLegendItem*> result;
13358 if (ali->selected())
13359 result.append(ali);
13440 if (selectionStateChanged)
13453 if (selectionStateChanged)
13473 Q_UNUSED(parentPlot)
13515 mFont(QFont(QLatin1String(
"sans serif"), 13*1.5, QFont::Bold)),
13516 mTextColor(Qt::black),
13517 mSelectedFont(QFont(QLatin1String(
"sans serif"), 13*1.6, QFont::Bold)),
13518 mSelectedTextColor(Qt::blue),
13519 mSelectable(false),
13525 mFont = QFont(parentPlot->font().family(), parentPlot->font().pointSize()*1.5, QFont::Bold);
13526 mSelectedFont = QFont(parentPlot->font().family(), parentPlot->font().pointSize()*1.6, QFont::Bold);
13538 mFont(QFont(parentPlot->font().family(), parentPlot->font().pointSize()*1.5, QFont::Bold)),
13539 mTextColor(Qt::black),
13540 mSelectedFont(QFont(parentPlot->font().family(), parentPlot->font().pointSize()*1.6, QFont::Bold)),
13541 mSelectedTextColor(Qt::blue),
13542 mSelectable(false),
13647 QFontMetrics metrics(
mFont);
13648 QSize result = metrics.boundingRect(0, 0, 0, 0, Qt::AlignCenter,
mText).size();
13657 QFontMetrics metrics(
mFont);
13658 QSize result = metrics.boundingRect(0, 0, 0, 0, Qt::AlignCenter,
mText).size();
13660 result.setWidth(QWIDGETSIZE_MAX);
13673 if (selectionStateChanged)
13674 *selectionStateChanged =
mSelected != selBefore;
13685 if (selectionStateChanged)
13686 *selectionStateChanged =
mSelected != selBefore;
13813 mDataScaleType(
QCPAxis::stLinear),
13832 qDebug() << Q_FUNC_INFO <<
"internal color axis undefined";
13844 qDebug() << Q_FUNC_INFO <<
"internal axis rect was deleted";
13858 qDebug() << Q_FUNC_INFO <<
"internal axis rect was deleted";
13878 qDebug() << Q_FUNC_INFO <<
"internal axis rect was deleted";
13885 double logBaseTransfer = 10;
13886 QString labelTransfer;
13892 logBaseTransfer =
mColorAxis.data()->scaleLogBase();
13908 mColorAxis.data()->setScaleLogBase(logBaseTransfer);
13972 mAxisRect.data()->mGradientImageInvalidated =
true;
13985 qDebug() << Q_FUNC_INFO <<
"internal color axis undefined";
14011 qDebug() << Q_FUNC_INFO <<
"internal axis rect was deleted";
14031 qDebug() << Q_FUNC_INFO <<
"internal axis rect was deleted";
14046 QList<QCPColorMap*> result;
14050 if (cm->colorScale() ==
this)
14064 QList<QCPColorMap*> maps =
colorMaps();
14066 bool haveRange =
false;
14070 for (
int i=0; i<maps.size(); ++i)
14072 if (!maps.at(i)->realVisibility() && onlyVisibleMaps)
14075 if (maps.at(i)->colorScale() ==
this)
14077 bool currentFoundRange =
true;
14078 mapRange = maps.at(i)->data()->dataBounds();
14081 if (mapRange.
lower <= 0 && mapRange.
upper > 0)
14083 else if (mapRange.
lower <= 0 && mapRange.
upper <= 0)
14084 currentFoundRange =
false;
14085 }
else if (sign == -1)
14087 if (mapRange.
upper >= 0 && mapRange.
lower < 0)
14089 else if (mapRange.
upper >= 0 && mapRange.
lower >= 0)
14090 currentFoundRange =
false;
14092 if (currentFoundRange)
14095 newRange = mapRange;
14097 newRange.
expand(mapRange);
14106 double center = (newRange.
lower+newRange.
upper)*0.5;
14127 qDebug() << Q_FUNC_INFO <<
"internal axis rect was deleted";
14168 qDebug() << Q_FUNC_INFO <<
"internal axis rect was deleted";
14171 mAxisRect.data()->mousePressEvent(event);
14179 qDebug() << Q_FUNC_INFO <<
"internal axis rect was deleted";
14182 mAxisRect.data()->mouseMoveEvent(event);
14190 qDebug() << Q_FUNC_INFO <<
"internal axis rect was deleted";
14193 mAxisRect.data()->mouseReleaseEvent(event);
14201 qDebug() << Q_FUNC_INFO <<
"internal axis rect was deleted";
14226 QCPAxisRect(parentColorScale->parentPlot(), true),
14227 mParentColorScale(parentColorScale),
14228 mGradientImageInvalidated(true)
14238 connect(
axis(type), SIGNAL(selectionChanged(QCPAxis::SelectableParts)),
this, SLOT(
axisSelectionChanged(QCPAxis::SelectableParts)));
14239 connect(
axis(type), SIGNAL(selectableChanged(QCPAxis::SelectableParts)),
this, SLOT(
axisSelectableChanged(QCPAxis::SelectableParts)));
14267 bool mirrorHorz =
false;
14268 bool mirrorVert =
false;
14275 painter->drawImage(
rect().adjusted(0, -1, 0, -1),
mGradientImage.mirrored(mirrorHorz, mirrorVert));
14286 if (
rect().isEmpty())
14291 QVector<double> data(n);
14292 for (
int i=0; i<n; ++i)
14297 h =
rect().height();
14299 QVector<QRgb*> pixels;
14300 for (
int y=0; y<h; ++y)
14301 pixels.append(reinterpret_cast<QRgb*>(
mGradientImage.scanLine(y)));
14303 for (
int y=1; y<h; ++y)
14304 memcpy(pixels.at(y), pixels.first(), n*
sizeof(QRgb));
14307 w =
rect().width();
14310 for (
int y=0; y<h; ++y)
14312 QRgb *pixels =
reinterpret_cast<QRgb*
>(
mGradientImage.scanLine(y));
14314 for (
int x=0; x<w; ++x)
14315 pixels[x] = lineColor;
14332 if (
QCPAxis *senderAxis = qobject_cast<QCPAxis*>(sender()))
14333 if (senderAxis->axisType() == type)
14357 if (
QCPAxis *senderAxis = qobject_cast<QCPAxis*>(sender()))
14358 if (senderAxis->axisType() == type)
14488 setPen(QPen(Qt::blue, 0));
14521 qDebug() << Q_FUNC_INFO <<
"The data pointer is already in (and owned by) this plottable" <<
reinterpret_cast<quintptr
>(
data);
14543 int n = key.size();
14544 n = qMin(n, value.size());
14546 for (
int i=0; i<n; ++i)
14548 newData.
key = key[i];
14549 newData.value = value[i];
14550 mData->insertMulti(newData.key, newData);
14566 int n = key.size();
14567 n = qMin(n, value.size());
14568 n = qMin(n, valueError.size());
14570 for (
int i=0; i<n; ++i)
14572 newData.
key = key[i];
14573 newData.value = value[i];
14574 newData.valueErrorMinus = valueError[i];
14575 newData.valueErrorPlus = valueError[i];
14576 mData->insertMulti(key[i], newData);
14589 void QCPGraph::setDataValueError(
const QVector<double> &key,
const QVector<double> &value,
const QVector<double> &valueErrorMinus,
const QVector<double> &valueErrorPlus)
14592 int n = key.size();
14593 n = qMin(n, value.size());
14594 n = qMin(n, valueErrorMinus.size());
14595 n = qMin(n, valueErrorPlus.size());
14597 for (
int i=0; i<n; ++i)
14599 newData.
key = key[i];
14600 newData.value = value[i];
14601 newData.valueErrorMinus = valueErrorMinus[i];
14602 newData.valueErrorPlus = valueErrorPlus[i];
14603 mData->insertMulti(key[i], newData);
14619 int n = key.size();
14620 n = qMin(n, value.size());
14621 n = qMin(n, keyError.size());
14623 for (
int i=0; i<n; ++i)
14625 newData.
key = key[i];
14626 newData.value = value[i];
14627 newData.keyErrorMinus = keyError[i];
14628 newData.keyErrorPlus = keyError[i];
14629 mData->insertMulti(key[i], newData);
14642 void QCPGraph::setDataKeyError(
const QVector<double> &key,
const QVector<double> &value,
const QVector<double> &keyErrorMinus,
const QVector<double> &keyErrorPlus)
14645 int n = key.size();
14646 n = qMin(n, value.size());
14647 n = qMin(n, keyErrorMinus.size());
14648 n = qMin(n, keyErrorPlus.size());
14650 for (
int i=0; i<n; ++i)
14652 newData.
key = key[i];
14653 newData.value = value[i];
14654 newData.keyErrorMinus = keyErrorMinus[i];
14655 newData.keyErrorPlus = keyErrorPlus[i];
14656 mData->insertMulti(key[i], newData);
14669 void QCPGraph::setDataBothError(
const QVector<double> &key,
const QVector<double> &value,
const QVector<double> &keyError,
const QVector<double> &valueError)
14672 int n = key.size();
14673 n = qMin(n, value.size());
14674 n = qMin(n, valueError.size());
14675 n = qMin(n, keyError.size());
14677 for (
int i=0; i<n; ++i)
14679 newData.
key = key[i];
14680 newData.value = value[i];
14681 newData.keyErrorMinus = keyError[i];
14682 newData.keyErrorPlus = keyError[i];
14683 newData.valueErrorMinus = valueError[i];
14684 newData.valueErrorPlus = valueError[i];
14685 mData->insertMulti(key[i], newData);
14698 void QCPGraph::setDataBothError(
const QVector<double> &key,
const QVector<double> &value,
const QVector<double> &keyErrorMinus,
const QVector<double> &keyErrorPlus,
const QVector<double> &valueErrorMinus,
const QVector<double> &valueErrorPlus)
14701 int n = key.size();
14702 n = qMin(n, value.size());
14703 n = qMin(n, valueErrorMinus.size());
14704 n = qMin(n, valueErrorPlus.size());
14705 n = qMin(n, keyErrorMinus.size());
14706 n = qMin(n, keyErrorPlus.size());
14708 for (
int i=0; i<n; ++i)
14710 newData.
key = key[i];
14711 newData.value = value[i];
14712 newData.keyErrorMinus = keyErrorMinus[i];
14713 newData.keyErrorPlus = keyErrorPlus[i];
14714 newData.valueErrorMinus = valueErrorMinus[i];
14715 newData.valueErrorPlus = valueErrorPlus[i];
14716 mData->insertMulti(key[i], newData);
14801 if (targetGraph ==
this)
14803 qDebug() << Q_FUNC_INFO <<
"targetGraph is this graph itself";
14810 qDebug() << Q_FUNC_INFO <<
"targetGraph not in same plot";
14864 mData->unite(dataMap);
14877 mData->insertMulti(data.
key, data);
14892 newData.
value = value;
14893 mData->insertMulti(newData.
key, newData);
14906 int n = qMin(keys.size(), values.size());
14908 for (
int i=0; i<n; ++i)
14910 newData.
key = keys[i];
14911 newData.value = values[i];
14912 mData->insertMulti(newData.key, newData);
14922 QCPDataMap::iterator it =
mData->begin();
14923 while (it !=
mData->end() && it.key() < key)
14924 it =
mData->erase(it);
14933 if (
mData->isEmpty())
return;
14934 QCPDataMap::iterator it =
mData->upperBound(key);
14935 while (it !=
mData->end())
14936 it =
mData->erase(it);
14948 if (fromKey >= toKey ||
mData->isEmpty())
return;
14949 QCPDataMap::iterator it =
mData->upperBound(fromKey);
14950 QCPDataMap::iterator itEnd =
mData->upperBound(toKey);
14951 while (it != itEnd)
14952 it =
mData->erase(it);
14965 mData->remove(key);
14983 if (!
mKeyAxis || !
mValueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return -1; }
14985 if (
mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()))
15015 if (
mData->isEmpty())
return;
15018 if (!keyAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key axis";
return; }
15051 if (
mData->isEmpty())
return;
15054 if (!valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid value axis";
return; }
15079 if (!
mKeyAxis || !
mValueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
15080 if (
mKeyAxis.data()->range().size() <= 0 ||
mData->isEmpty())
return;
15084 QVector<QPointF> *lineData =
new QVector<QPointF>;
15085 QVector<QCPData> *scatterData = 0;
15087 scatterData =
new QVector<QCPData>;
15093 #ifdef QCUSTOMPLOT_CHECK_DATA
15094 QCPDataMap::const_iterator it;
15095 for (it =
mData->constBegin(); it !=
mData->constEnd(); ++it)
15100 qDebug() << Q_FUNC_INFO <<
"Data point at" << it.key() <<
"invalid." <<
"Plottable name:" <<
name();
15121 delete scatterData;
15128 if (
mBrush.style() != Qt::NoBrush)
15131 painter->fillRect(QRectF(rect.left(), rect.top()+rect.height()/2.0, rect.width(), rect.height()/3.0),
mBrush);
15138 painter->
drawLine(QLineF(rect.left(), rect.top()+rect.height()/2.0, rect.right()+5, rect.top()+rect.height()/2.0));
15148 scaledStyle.
setPixmap(scaledStyle.
pixmap().scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
15150 scaledStyle.
drawShape(painter, QRectF(rect).center());
15221 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
15222 if (!linePixelData) { qDebug() << Q_FUNC_INFO <<
"null pointer passed as linePixelData";
return; }
15224 QVector<QCPData> lineData;
15226 linePixelData->reserve(lineData.size()+2);
15227 linePixelData->resize(lineData.size());
15232 for (
int i=0; i<lineData.size(); ++i)
15234 (*linePixelData)[i].setX(valueAxis->
coordToPixel(lineData.at(i).value));
15235 (*linePixelData)[i].setY(keyAxis->
coordToPixel(lineData.at(i).key));
15239 for (
int i=0; i<lineData.size(); ++i)
15241 (*linePixelData)[i].setX(keyAxis->
coordToPixel(lineData.at(i).key));
15242 (*linePixelData)[i].setY(valueAxis->
coordToPixel(lineData.at(i).value));
15262 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
15263 if (!linePixelData) { qDebug() << Q_FUNC_INFO <<
"null pointer passed as lineData";
return; }
15265 QVector<QCPData> lineData;
15267 linePixelData->reserve(lineData.size()*2+2);
15268 linePixelData->resize(lineData.size()*2);
15273 double lastValue = valueAxis->
coordToPixel(lineData.first().value);
15275 for (
int i=0; i<lineData.size(); ++i)
15278 (*linePixelData)[i*2+0].setX(lastValue);
15279 (*linePixelData)[i*2+0].setY(key);
15280 lastValue = valueAxis->
coordToPixel(lineData.at(i).value);
15281 (*linePixelData)[i*2+1].setX(lastValue);
15282 (*linePixelData)[i*2+1].setY(key);
15286 double lastValue = valueAxis->
coordToPixel(lineData.first().value);
15288 for (
int i=0; i<lineData.size(); ++i)
15291 (*linePixelData)[i*2+0].setX(key);
15292 (*linePixelData)[i*2+0].setY(lastValue);
15293 lastValue = valueAxis->
coordToPixel(lineData.at(i).value);
15294 (*linePixelData)[i*2+1].setX(key);
15295 (*linePixelData)[i*2+1].setY(lastValue);
15315 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
15316 if (!linePixelData) { qDebug() << Q_FUNC_INFO <<
"null pointer passed as lineData";
return; }
15318 QVector<QCPData> lineData;
15320 linePixelData->reserve(lineData.size()*2+2);
15321 linePixelData->resize(lineData.size()*2);
15326 double lastKey = keyAxis->
coordToPixel(lineData.first().key);
15328 for (
int i=0; i<lineData.size(); ++i)
15330 value = valueAxis->
coordToPixel(lineData.at(i).value);
15331 (*linePixelData)[i*2+0].setX(value);
15332 (*linePixelData)[i*2+0].setY(lastKey);
15334 (*linePixelData)[i*2+1].setX(value);
15335 (*linePixelData)[i*2+1].setY(lastKey);
15339 double lastKey = keyAxis->
coordToPixel(lineData.first().key);
15341 for (
int i=0; i<lineData.size(); ++i)
15343 value = valueAxis->
coordToPixel(lineData.at(i).value);
15344 (*linePixelData)[i*2+0].setX(lastKey);
15345 (*linePixelData)[i*2+0].setY(value);
15347 (*linePixelData)[i*2+1].setX(lastKey);
15348 (*linePixelData)[i*2+1].setY(value);
15368 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
15369 if (!linePixelData) { qDebug() << Q_FUNC_INFO <<
"null pointer passed as lineData";
return; }
15371 QVector<QCPData> lineData;
15373 linePixelData->reserve(lineData.size()*2+2);
15374 linePixelData->resize(lineData.size()*2);
15378 double lastKey = keyAxis->
coordToPixel(lineData.first().key);
15379 double lastValue = valueAxis->
coordToPixel(lineData.first().value);
15381 (*linePixelData)[0].setX(lastValue);
15382 (*linePixelData)[0].setY(lastKey);
15383 for (
int i=1; i<lineData.size(); ++i)
15385 key = (keyAxis->
coordToPixel(lineData.at(i).key)+lastKey)*0.5;
15386 (*linePixelData)[i*2-1].setX(lastValue);
15387 (*linePixelData)[i*2-1].setY(key);
15388 lastValue = valueAxis->
coordToPixel(lineData.at(i).value);
15390 (*linePixelData)[i*2+0].setX(lastValue);
15391 (*linePixelData)[i*2+0].setY(key);
15393 (*linePixelData)[lineData.size()*2-1].setX(lastValue);
15394 (*linePixelData)[lineData.size()*2-1].setY(lastKey);
15397 double lastKey = keyAxis->
coordToPixel(lineData.first().key);
15398 double lastValue = valueAxis->
coordToPixel(lineData.first().value);
15400 (*linePixelData)[0].setX(lastKey);
15401 (*linePixelData)[0].setY(lastValue);
15402 for (
int i=1; i<lineData.size(); ++i)
15404 key = (keyAxis->
coordToPixel(lineData.at(i).key)+lastKey)*0.5;
15405 (*linePixelData)[i*2-1].setX(key);
15406 (*linePixelData)[i*2-1].setY(lastValue);
15407 lastValue = valueAxis->
coordToPixel(lineData.at(i).value);
15409 (*linePixelData)[i*2+0].setX(key);
15410 (*linePixelData)[i*2+0].setY(lastValue);
15412 (*linePixelData)[lineData.size()*2-1].setX(lastKey);
15413 (*linePixelData)[lineData.size()*2-1].setY(lastValue);
15433 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
15434 if (!linePixelData) { qDebug() << Q_FUNC_INFO <<
"null pointer passed as linePixelData";
return; }
15436 QVector<QCPData> lineData;
15438 linePixelData->resize(lineData.size()*2);
15445 for (
int i=0; i<lineData.size(); ++i)
15448 (*linePixelData)[i*2+0].setX(zeroPointX);
15449 (*linePixelData)[i*2+0].setY(key);
15450 (*linePixelData)[i*2+1].setX(valueAxis->
coordToPixel(lineData.at(i).value));
15451 (*linePixelData)[i*2+1].setY(key);
15457 for (
int i=0; i<lineData.size(); ++i)
15460 (*linePixelData)[i*2+0].setX(key);
15461 (*linePixelData)[i*2+0].setY(zeroPointY);
15462 (*linePixelData)[i*2+1].setX(key);
15463 (*linePixelData)[i*2+1].setY(valueAxis->
coordToPixel(lineData.at(i).value));
15491 painter->
setPen(Qt::NoPen);
15493 painter->drawPolygon(QPolygonF(*lineData));
15498 painter->
setPen(Qt::NoPen);
15517 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
15526 for (
int i=0; i<scatterData->size(); ++i)
15530 for (
int i=0; i<scatterData->size(); ++i)
15540 for (
int i=0; i<scatterData->size(); ++i)
15541 if (!qIsNaN(scatterData->at(i).value))
15545 for (
int i=0; i<scatterData->size(); ++i)
15546 if (!qIsNaN(scatterData->at(i).value))
15563 if (
mainPen().style() != Qt::NoPen &&
mainPen().color().alpha() != 0)
15567 painter->setBrush(Qt::NoBrush);
15586 painter->pen().style() == Qt::SolidLine &&
15591 bool lastIsNan =
false;
15592 const int lineDataSize = lineData->size();
15593 while (i < lineDataSize && (qIsNaN(lineData->at(i).y()) || qIsNaN(lineData->at(i).x())))
15596 while (i < lineDataSize)
15598 if (!qIsNaN(lineData->at(i).y()) && !qIsNaN(lineData->at(i).x()))
15601 painter->
drawLine(lineData->at(i-1), lineData->at(i));
15610 int segmentStart = 0;
15612 const int lineDataSize = lineData->size();
15613 while (i < lineDataSize)
15615 if (qIsNaN(lineData->at(i).y()) || qIsNaN(lineData->at(i).x()) || qIsInf(lineData->at(i).y()))
15617 painter->drawPolyline(lineData->constData()+segmentStart, i-segmentStart);
15618 segmentStart = i+1;
15623 painter->drawPolyline(lineData->constData()+segmentStart, lineDataSize-segmentStart);
15638 if (
mainPen().style() != Qt::NoPen &&
mainPen().color().alpha() != 0)
15642 pen.setCapStyle(Qt::FlatCap);
15644 painter->setBrush(Qt::NoBrush);
15645 painter->drawLines(*lineData);
15665 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
15667 QCPDataMap::const_iterator lower, upper;
15669 if (lower ==
mData->constEnd() || upper ==
mData->constEnd())
15673 int maxCount = std::numeric_limits<int>::max();
15677 maxCount = 2*keyPixelSpan+2;
15685 QCPDataMap::const_iterator it = lower;
15686 QCPDataMap::const_iterator upperEnd = upper+1;
15687 double minValue = it.value().value;
15688 double maxValue = it.value().value;
15689 QCPDataMap::const_iterator currentIntervalFirstPoint = it;
15693 double lastIntervalEndKey = currentIntervalStartKey;
15694 double keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->
pixelToCoord(keyAxis->
coordToPixel(currentIntervalStartKey)+1.0*reversedFactor));
15696 int intervalDataCount = 1;
15698 while (it != upperEnd)
15700 if (it.key() < currentIntervalStartKey+keyEpsilon)
15702 if (it.value().value < minValue)
15703 minValue = it.value().value;
15704 else if (it.value().value > maxValue)
15705 maxValue = it.value().value;
15706 ++intervalDataCount;
15709 if (intervalDataCount >= 2)
15711 if (lastIntervalEndKey < currentIntervalStartKey-keyEpsilon)
15712 lineData->append(
QCPData(currentIntervalStartKey+keyEpsilon*0.2, currentIntervalFirstPoint.value().value));
15713 lineData->append(
QCPData(currentIntervalStartKey+keyEpsilon*0.25, minValue));
15714 lineData->append(
QCPData(currentIntervalStartKey+keyEpsilon*0.75, maxValue));
15715 if (it.key() > currentIntervalStartKey+keyEpsilon*2)
15716 lineData->append(
QCPData(currentIntervalStartKey+keyEpsilon*0.8, (it-1).value().value));
15718 lineData->append(
QCPData(currentIntervalFirstPoint.key(), currentIntervalFirstPoint.value().value));
15719 lastIntervalEndKey = (it-1).value().key;
15720 minValue = it.value().value;
15721 maxValue = it.value().value;
15722 currentIntervalFirstPoint = it;
15724 if (keyEpsilonVariable)
15725 keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->
pixelToCoord(keyAxis->
coordToPixel(currentIntervalStartKey)+1.0*reversedFactor));
15726 intervalDataCount = 1;
15731 if (intervalDataCount >= 2)
15733 if (lastIntervalEndKey < currentIntervalStartKey-keyEpsilon)
15734 lineData->append(
QCPData(currentIntervalStartKey+keyEpsilon*0.2, currentIntervalFirstPoint.value().value));
15735 lineData->append(
QCPData(currentIntervalStartKey+keyEpsilon*0.25, minValue));
15736 lineData->append(
QCPData(currentIntervalStartKey+keyEpsilon*0.75, maxValue));
15738 lineData->append(
QCPData(currentIntervalFirstPoint.key(), currentIntervalFirstPoint.value().value));
15743 double valueMaxRange = valueAxis->
range().
upper;
15744 double valueMinRange = valueAxis->
range().
lower;
15745 QCPDataMap::const_iterator it = lower;
15746 QCPDataMap::const_iterator upperEnd = upper+1;
15747 double minValue = it.value().value;
15748 double maxValue = it.value().value;
15749 QCPDataMap::const_iterator minValueIt = it;
15750 QCPDataMap::const_iterator maxValueIt = it;
15751 QCPDataMap::const_iterator currentIntervalStart = it;
15755 double keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->
pixelToCoord(keyAxis->
coordToPixel(currentIntervalStartKey)+1.0*reversedFactor));
15757 int intervalDataCount = 1;
15759 while (it != upperEnd)
15761 if (it.key() < currentIntervalStartKey+keyEpsilon)
15763 if (it.value().value < minValue && it.value().value > valueMinRange && it.value().value < valueMaxRange)
15765 minValue = it.value().value;
15767 }
else if (it.value().value > maxValue && it.value().value > valueMinRange && it.value().value < valueMaxRange)
15769 maxValue = it.value().value;
15772 ++intervalDataCount;
15775 if (intervalDataCount >= 2)
15779 int dataModulo = qMax(1, qRound(intervalDataCount/(valuePixelSpan/4.0)));
15780 QCPDataMap::const_iterator intervalIt = currentIntervalStart;
15782 while (intervalIt != it)
15784 if ((c % dataModulo == 0 || intervalIt == minValueIt || intervalIt == maxValueIt) && intervalIt.value().value > valueMinRange && intervalIt.value().value < valueMaxRange)
15785 scatterData->append(intervalIt.value());
15789 }
else if (currentIntervalStart.value().value > valueMinRange && currentIntervalStart.value().value < valueMaxRange)
15790 scatterData->append(currentIntervalStart.value());
15791 minValue = it.value().value;
15792 maxValue = it.value().value;
15793 currentIntervalStart = it;
15795 if (keyEpsilonVariable)
15796 keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->
pixelToCoord(keyAxis->
coordToPixel(currentIntervalStartKey)+1.0*reversedFactor));
15797 intervalDataCount = 1;
15802 if (intervalDataCount >= 2)
15806 int dataModulo = qMax(1, qRound(intervalDataCount/(valuePixelSpan/4.0)));
15807 QCPDataMap::const_iterator intervalIt = currentIntervalStart;
15809 while (intervalIt != it)
15811 if ((c % dataModulo == 0 || intervalIt == minValueIt || intervalIt == maxValueIt) && intervalIt.value().value > valueMinRange && intervalIt.value().value < valueMaxRange)
15812 scatterData->append(intervalIt.value());
15816 }
else if (currentIntervalStart.value().value > valueMinRange && currentIntervalStart.value().value < valueMaxRange)
15817 scatterData->append(currentIntervalStart.value());
15821 QVector<QCPData> *dataVector = 0;
15823 dataVector = lineData;
15824 else if (scatterData)
15825 dataVector = scatterData;
15828 QCPDataMap::const_iterator it = lower;
15829 QCPDataMap::const_iterator upperEnd = upper+1;
15830 dataVector->reserve(dataCount+2);
15831 while (it != upperEnd)
15833 dataVector->append(it.value());
15837 if (lineData && scatterData)
15838 *scatterData = *dataVector;
15851 if (qIsNaN(data.
value))
15855 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
15873 if (a-y > skipSymbolMargin)
15874 painter->
drawLine(QLineF(x, a, x, y+skipSymbolMargin));
15875 if (y-b > skipSymbolMargin)
15876 painter->
drawLine(QLineF(x, y-skipSymbolMargin, x, b));
15878 painter->
drawLine(QLineF(x, a, x, b));
15880 painter->
drawLine(QLineF(x-barWidthHalf, a, x+barWidthHalf, a));
15881 painter->
drawLine(QLineF(x-barWidthHalf, b, x+barWidthHalf, b));
15892 if (x-a > skipSymbolMargin)
15893 painter->
drawLine(QLineF(a, y, x-skipSymbolMargin, y));
15894 if (b-x > skipSymbolMargin)
15895 painter->
drawLine(QLineF(x+skipSymbolMargin, y, b, y));
15897 painter->
drawLine(QLineF(a, y, b, y));
15899 painter->
drawLine(QLineF(a, y-barWidthHalf, a, y+barWidthHalf));
15900 painter->
drawLine(QLineF(b, y-barWidthHalf, b, y+barWidthHalf));
15914 if (x-a > skipSymbolMargin)
15915 painter->
drawLine(QLineF(a, y, x-skipSymbolMargin, y));
15916 if (b-x > skipSymbolMargin)
15917 painter->
drawLine(QLineF(x+skipSymbolMargin, y, b, y));
15919 painter->
drawLine(QLineF(a, y, b, y));
15921 painter->
drawLine(QLineF(a, y-barWidthHalf, a, y+barWidthHalf));
15922 painter->
drawLine(QLineF(b, y-barWidthHalf, b, y+barWidthHalf));
15933 if (a-y > skipSymbolMargin)
15934 painter->
drawLine(QLineF(x, a, x, y+skipSymbolMargin));
15935 if (y-b > skipSymbolMargin)
15936 painter->
drawLine(QLineF(x, y-skipSymbolMargin, x, b));
15938 painter->
drawLine(QLineF(x, a, x, b));
15940 painter->
drawLine(QLineF(x-barWidthHalf, a, x+barWidthHalf, a));
15941 painter->
drawLine(QLineF(x-barWidthHalf, b, x+barWidthHalf, b));
15962 if (!
mKeyAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key axis";
return; }
15963 if (
mData->isEmpty())
15965 lower =
mData->constEnd();
15966 upper =
mData->constEnd();
15971 QCPDataMap::const_iterator lbound =
mData->lowerBound(
mKeyAxis.data()->range().lower);
15972 QCPDataMap::const_iterator ubound =
mData->upperBound(
mKeyAxis.data()->range().upper);
15973 bool lowoutlier = lbound !=
mData->constBegin();
15974 bool highoutlier = ubound !=
mData->constEnd();
15976 lower = (lowoutlier ? lbound-1 : lbound);
15977 upper = (highoutlier ? ubound : ubound-1);
15992 if (upper ==
mData->constEnd() && lower ==
mData->constEnd())
15994 QCPDataMap::const_iterator it = lower;
15996 while (it != upper && count < maxCount)
16021 if (!
mKeyAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key axis";
return; }
16022 if (!lineData) { qDebug() << Q_FUNC_INFO <<
"passed null as lineData";
return; }
16023 if (lineData->isEmpty())
return;
16026 if (
mKeyAxis.data()->orientation() == Qt::Vertical)
16045 if (!lineData) { qDebug() << Q_FUNC_INFO <<
"passed null as lineData";
return; }
16046 if (lineData->isEmpty())
return;
16048 lineData->remove(lineData->size()-2, 2);
16069 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return QPointF(); }
16077 point.setY(lowerKey);
16081 point.setY(lowerKey);
16084 point.setX(lowerKey);
16088 point.setX(lowerKey);
16102 point.setY(lowerKey);
16105 point.setX(lowerKey);
16134 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return QPointF(); }
16142 point.setY(upperKey);
16146 point.setY(upperKey);
16149 point.setX(upperKey);
16153 point.setX(upperKey);
16167 point.setY(upperKey);
16170 point.setX(upperKey);
16193 return QPolygonF();
16197 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return QPolygonF(); }
16198 if (!
mChannelFillGraph.data()->mKeyAxis) { qDebug() << Q_FUNC_INFO <<
"channel fill target key axis invalid";
return QPolygonF(); }
16201 return QPolygonF();
16203 if (lineData->isEmpty())
return QPolygonF();
16204 QVector<QPointF> otherData;
16206 if (otherData.isEmpty())
return QPolygonF();
16207 QVector<QPointF> thisData;
16208 thisData.reserve(lineData->size()+otherData.size());
16209 for (
int i=0; i<lineData->size(); ++i)
16210 thisData << lineData->at(i);
16213 QVector<QPointF> *staticData = &thisData;
16214 QVector<QPointF> *croppedData = &otherData;
16221 if (staticData->first().x() > staticData->last().x())
16223 int size = staticData->size();
16224 for (
int i=0; i<size/2; ++i)
16225 qSwap((*staticData)[i], (*staticData)[size-1-i]);
16227 if (croppedData->first().x() > croppedData->last().x())
16229 int size = croppedData->size();
16230 for (
int i=0; i<size/2; ++i)
16231 qSwap((*croppedData)[i], (*croppedData)[size-1-i]);
16234 if (staticData->first().x() < croppedData->first().x())
16235 qSwap(staticData, croppedData);
16236 int lowBound =
findIndexBelowX(croppedData, staticData->first().x());
16237 if (lowBound == -1)
return QPolygonF();
16238 croppedData->remove(0, lowBound);
16241 if (croppedData->size() < 2)
return QPolygonF();
16243 if (croppedData->at(1).x()-croppedData->at(0).x() != 0)
16244 slope = (croppedData->at(1).y()-croppedData->at(0).y())/(croppedData->at(1).x()-croppedData->at(0).x());
16247 (*croppedData)[0].setY(croppedData->at(0).y()+slope*(staticData->first().x()-croppedData->at(0).x()));
16248 (*croppedData)[0].setX(staticData->first().x());
16251 if (staticData->last().x() > croppedData->last().x())
16252 qSwap(staticData, croppedData);
16253 int highBound =
findIndexAboveX(croppedData, staticData->last().x());
16254 if (highBound == -1)
return QPolygonF();
16255 croppedData->remove(highBound+1, croppedData->size()-(highBound+1));
16258 if (croppedData->size() < 2)
return QPolygonF();
16259 int li = croppedData->size()-1;
16260 if (croppedData->at(li).x()-croppedData->at(li-1).x() != 0)
16261 slope = (croppedData->at(li).y()-croppedData->at(li-1).y())/(croppedData->at(li).x()-croppedData->at(li-1).x());
16264 (*croppedData)[li].setY(croppedData->at(li-1).y()+slope*(staticData->last().x()-croppedData->at(li-1).x()));
16265 (*croppedData)[li].setX(staticData->last().x());
16272 if (staticData->first().y() < staticData->last().y())
16274 int size = staticData->size();
16275 for (
int i=0; i<size/2; ++i)
16276 qSwap((*staticData)[i], (*staticData)[size-1-i]);
16278 if (croppedData->first().y() < croppedData->last().y())
16280 int size = croppedData->size();
16281 for (
int i=0; i<size/2; ++i)
16282 qSwap((*croppedData)[i], (*croppedData)[size-1-i]);
16285 if (staticData->first().y() > croppedData->first().y())
16286 qSwap(staticData, croppedData);
16287 int lowBound =
findIndexAboveY(croppedData, staticData->first().y());
16288 if (lowBound == -1)
return QPolygonF();
16289 croppedData->remove(0, lowBound);
16292 if (croppedData->size() < 2)
return QPolygonF();
16294 if (croppedData->at(1).y()-croppedData->at(0).y() != 0)
16295 slope = (croppedData->at(1).x()-croppedData->at(0).x())/(croppedData->at(1).y()-croppedData->at(0).y());
16298 (*croppedData)[0].setX(croppedData->at(0).x()+slope*(staticData->first().y()-croppedData->at(0).y()));
16299 (*croppedData)[0].setY(staticData->first().y());
16302 if (staticData->last().y() < croppedData->last().y())
16303 qSwap(staticData, croppedData);
16304 int highBound =
findIndexBelowY(croppedData, staticData->last().y());
16305 if (highBound == -1)
return QPolygonF();
16306 croppedData->remove(highBound+1, croppedData->size()-(highBound+1));
16309 if (croppedData->size() < 2)
return QPolygonF();
16310 int li = croppedData->size()-1;
16311 if (croppedData->at(li).y()-croppedData->at(li-1).y() != 0)
16312 slope = (croppedData->at(li).x()-croppedData->at(li-1).x())/(croppedData->at(li).y()-croppedData->at(li-1).y());
16315 (*croppedData)[li].setX(croppedData->at(li-1).x()+slope*(staticData->last().y()-croppedData->at(li-1).y()));
16316 (*croppedData)[li].setY(staticData->last().y());
16320 for (
int i=otherData.size()-1; i>=0; --i)
16321 thisData << otherData.at(i);
16322 return QPolygonF(thisData);
16334 for (
int i=data->size()-1; i>=0; --i)
16336 if (data->at(i).x() < x)
16338 if (i<data->size()-1)
16341 return data->size()-1;
16356 for (
int i=0; i<data->size(); ++i)
16358 if (data->at(i).x() > x)
16378 for (
int i=0; i<data->size(); ++i)
16380 if (data->at(i).y() < y)
16402 if (
mData->isEmpty())
16411 QVector<QCPData> scatterData;
16413 if (scatterData.size() > 0)
16415 double minDistSqr = std::numeric_limits<double>::max();
16416 for (
int i=0; i<scatterData.size(); ++i)
16418 double currentDistSqr = QVector2D(
coordsToPixels(scatterData.at(i).key, scatterData.at(i).value)-pixelPoint).lengthSquared();
16419 if (currentDistSqr < minDistSqr)
16420 minDistSqr = currentDistSqr;
16422 return qSqrt(minDistSqr);
16428 QVector<QPointF> lineData;
16430 if (lineData.size() > 1)
16432 double minDistSqr = std::numeric_limits<double>::max();
16436 for (
int i=0; i<lineData.size()-1; i+=2)
16438 double currentDistSqr =
distSqrToLine(lineData.at(i), lineData.at(i+1), pixelPoint);
16439 if (currentDistSqr < minDistSqr)
16440 minDistSqr = currentDistSqr;
16445 for (
int i=0; i<lineData.size()-1; ++i)
16447 double currentDistSqr =
distSqrToLine(lineData.at(i), lineData.at(i+1), pixelPoint);
16448 if (currentDistSqr < minDistSqr)
16449 minDistSqr = currentDistSqr;
16452 return qSqrt(minDistSqr);
16453 }
else if (lineData.size() > 0)
16455 return QVector2D(lineData.at(0)-pixelPoint).length();
16471 for (
int i=data->size()-1; i>=0; --i)
16473 if (data->at(i).y() > y)
16475 if (i<data->size()-1)
16478 return data->size()-1;
16489 return getKeyRange(foundRange, inSignDomain,
true);
16509 bool haveLower =
false;
16510 bool haveUpper =
false;
16512 double current, currentErrorMinus, currentErrorPlus;
16514 if (inSignDomain ==
sdBoth)
16516 QCPDataMap::const_iterator it =
mData->constBegin();
16517 while (it !=
mData->constEnd())
16519 if (!qIsNaN(it.value().value))
16521 current = it.value().key;
16522 currentErrorMinus = (includeErrors ? it.value().keyErrorMinus : 0);
16523 currentErrorPlus = (includeErrors ? it.value().keyErrorPlus : 0);
16524 if (current-currentErrorMinus < range.
lower || !haveLower)
16526 range.
lower = current-currentErrorMinus;
16529 if (current+currentErrorPlus > range.
upper || !haveUpper)
16531 range.
upper = current+currentErrorPlus;
16539 QCPDataMap::const_iterator it =
mData->constBegin();
16540 while (it !=
mData->constEnd())
16542 if (!qIsNaN(it.value().value))
16544 current = it.value().key;
16545 currentErrorMinus = (includeErrors ? it.value().keyErrorMinus : 0);
16546 currentErrorPlus = (includeErrors ? it.value().keyErrorPlus : 0);
16547 if ((current-currentErrorMinus < range.
lower || !haveLower) && current-currentErrorMinus < 0)
16549 range.
lower = current-currentErrorMinus;
16552 if ((current+currentErrorPlus > range.
upper || !haveUpper) && current+currentErrorPlus < 0)
16554 range.
upper = current+currentErrorPlus;
16559 if ((current < range.
lower || !haveLower) && current < 0)
16561 range.
lower = current;
16564 if ((current > range.
upper || !haveUpper) && current < 0)
16566 range.
upper = current;
16575 QCPDataMap::const_iterator it =
mData->constBegin();
16576 while (it !=
mData->constEnd())
16578 if (!qIsNaN(it.value().value))
16580 current = it.value().key;
16581 currentErrorMinus = (includeErrors ? it.value().keyErrorMinus : 0);
16582 currentErrorPlus = (includeErrors ? it.value().keyErrorPlus : 0);
16583 if ((current-currentErrorMinus < range.
lower || !haveLower) && current-currentErrorMinus > 0)
16585 range.
lower = current-currentErrorMinus;
16588 if ((current+currentErrorPlus > range.
upper || !haveUpper) && current+currentErrorPlus > 0)
16590 range.
upper = current+currentErrorPlus;
16595 if ((current < range.
lower || !haveLower) && current > 0)
16597 range.
lower = current;
16600 if ((current > range.
upper || !haveUpper) && current > 0)
16602 range.
upper = current;
16611 foundRange = haveLower && haveUpper;
16624 bool haveLower =
false;
16625 bool haveUpper =
false;
16627 double current, currentErrorMinus, currentErrorPlus;
16629 if (inSignDomain ==
sdBoth)
16631 QCPDataMap::const_iterator it =
mData->constBegin();
16632 while (it !=
mData->constEnd())
16634 current = it.value().value;
16635 if (!qIsNaN(current))
16637 currentErrorMinus = (includeErrors ? it.value().valueErrorMinus : 0);
16638 currentErrorPlus = (includeErrors ? it.value().valueErrorPlus : 0);
16639 if (current-currentErrorMinus < range.
lower || !haveLower)
16641 range.
lower = current-currentErrorMinus;
16644 if (current+currentErrorPlus > range.
upper || !haveUpper)
16646 range.
upper = current+currentErrorPlus;
16654 QCPDataMap::const_iterator it =
mData->constBegin();
16655 while (it !=
mData->constEnd())
16657 current = it.value().value;
16658 if (!qIsNaN(current))
16660 currentErrorMinus = (includeErrors ? it.value().valueErrorMinus : 0);
16661 currentErrorPlus = (includeErrors ? it.value().valueErrorPlus : 0);
16662 if ((current-currentErrorMinus < range.
lower || !haveLower) && current-currentErrorMinus < 0)
16664 range.
lower = current-currentErrorMinus;
16667 if ((current+currentErrorPlus > range.
upper || !haveUpper) && current+currentErrorPlus < 0)
16669 range.
upper = current+currentErrorPlus;
16674 if ((current < range.
lower || !haveLower) && current < 0)
16676 range.
lower = current;
16679 if ((current > range.
upper || !haveUpper) && current < 0)
16681 range.
upper = current;
16690 QCPDataMap::const_iterator it =
mData->constBegin();
16691 while (it !=
mData->constEnd())
16693 current = it.value().value;
16694 if (!qIsNaN(current))
16696 currentErrorMinus = (includeErrors ? it.value().valueErrorMinus : 0);
16697 currentErrorPlus = (includeErrors ? it.value().valueErrorPlus : 0);
16698 if ((current-currentErrorMinus < range.
lower || !haveLower) && current-currentErrorMinus > 0)
16700 range.
lower = current-currentErrorMinus;
16703 if ((current+currentErrorPlus > range.
upper || !haveUpper) && current+currentErrorPlus > 0)
16705 range.
upper = current+currentErrorPlus;
16710 if ((current < range.
lower || !haveLower) && current > 0)
16712 range.
lower = current;
16715 if ((current > range.
upper || !haveUpper) && current > 0)
16717 range.
upper = current;
16726 foundRange = haveLower && haveUpper;
16816 mPen.setColor(Qt::blue);
16817 mPen.setStyle(Qt::SolidLine);
16818 mBrush.setColor(Qt::blue);
16819 mBrush.setStyle(Qt::NoBrush);
16845 qDebug() << Q_FUNC_INFO <<
"The data pointer is already in (and owned by) this plottable" <<
reinterpret_cast<quintptr
>(
data);
16864 void QCPCurve::setData(
const QVector<double> &t,
const QVector<double> &key,
const QVector<double> &value)
16868 n = qMin(n, key.size());
16869 n = qMin(n, value.size());
16871 for (
int i=0; i<n; ++i)
16874 newData.key = key[i];
16875 newData.value = value[i];
16876 mData->insertMulti(newData.t, newData);
16888 int n = key.size();
16889 n = qMin(n, value.size());
16891 for (
int i=0; i<n; ++i)
16894 newData.key = key[i];
16895 newData.value = value[i];
16896 mData->insertMulti(newData.t, newData);
16930 mData->unite(dataMap);
16939 mData->insertMulti(data.
t, data);
16951 newData.
value = value;
16952 mData->insertMulti(newData.
t, newData);
16966 if (!
mData->isEmpty())
16967 newData.
t = (
mData->constEnd()-1).key()+1;
16971 newData.
value = value;
16972 mData->insertMulti(newData.
t, newData);
16979 void QCPCurve::addData(
const QVector<double> &ts,
const QVector<double> &keys,
const QVector<double> &values)
16982 n = qMin(n, keys.size());
16983 n = qMin(n, values.size());
16985 for (
int i=0; i<n; ++i)
16988 newData.key = keys[i];
16989 newData.value = values[i];
16990 mData->insertMulti(newData.t, newData);
17000 QCPCurveDataMap::iterator it =
mData->begin();
17001 while (it !=
mData->end() && it.key() < t)
17002 it =
mData->erase(it);
17011 if (
mData->isEmpty())
return;
17012 QCPCurveDataMap::iterator it =
mData->upperBound(t);
17013 while (it !=
mData->end())
17014 it =
mData->erase(it);
17026 if (fromt >= tot ||
mData->isEmpty())
return;
17027 QCPCurveDataMap::iterator it =
mData->upperBound(fromt);
17028 QCPCurveDataMap::iterator itEnd =
mData->upperBound(tot);
17029 while (it != itEnd)
17030 it =
mData->erase(it);
17062 if (!
mKeyAxis || !
mValueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return -1; }
17064 if (
mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()))
17073 if (
mData->isEmpty())
return;
17076 QVector<QPointF> *lineData =
new QVector<QPointF>;
17082 #ifdef QCUSTOMPLOT_CHECK_DATA
17083 QCPCurveDataMap::const_iterator it;
17084 for (it =
mData->constBegin(); it !=
mData->constEnd(); ++it)
17088 qDebug() << Q_FUNC_INFO <<
"Data point at" << it.key() <<
"invalid." <<
"Plottable name:" <<
name();
17096 painter->
setPen(Qt::NoPen);
17098 painter->drawPolygon(QPolygonF(*lineData));
17106 painter->setBrush(Qt::NoBrush);
17109 painter->pen().style() == Qt::SolidLine &&
17114 bool lastIsNan =
false;
17115 const int lineDataSize = lineData->size();
17116 while (i < lineDataSize && (qIsNaN(lineData->at(i).y()) || qIsNaN(lineData->at(i).x())))
17119 while (i < lineDataSize)
17121 if (!qIsNaN(lineData->at(i).y()) && !qIsNaN(lineData->at(i).x()))
17124 painter->
drawLine(lineData->at(i-1), lineData->at(i));
17133 int segmentStart = 0;
17135 const int lineDataSize = lineData->size();
17136 while (i < lineDataSize)
17138 if (qIsNaN(lineData->at(i).y()) || qIsNaN(lineData->at(i).x()))
17140 painter->drawPolyline(lineData->constData()+segmentStart, i-segmentStart);
17141 segmentStart = i+1;
17146 painter->drawPolyline(lineData->constData()+segmentStart, lineDataSize-segmentStart);
17162 if (
mBrush.style() != Qt::NoBrush)
17165 painter->fillRect(QRectF(rect.left(), rect.top()+rect.height()/2.0, rect.width(), rect.height()/3.0),
mBrush);
17172 painter->
drawLine(QLineF(rect.left(), rect.top()+rect.height()/2.0, rect.right()+5, rect.top()+rect.height()/2.0));
17182 scaledStyle.
setPixmap(scaledStyle.
pixmap().scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
17184 scaledStyle.
drawShape(painter, QRectF(rect).center());
17203 for (
int i=0; i<pointData->size(); ++i)
17204 if (!qIsNaN(pointData->at(i).x()) && !qIsNaN(pointData->at(i).y()))
17225 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
17228 double strokeMargin = qMax(qreal(1.0), qreal(
mainPen().widthF()*0.75));
17236 QCPCurveDataMap::const_iterator it =
mData->constBegin();
17237 QCPCurveDataMap::const_iterator prevIt =
mData->constEnd()-1;
17238 int prevRegion =
getRegion(prevIt.value().key, prevIt.value().value, rectLeft, rectTop, rectRight, rectBottom);
17239 QVector<QPointF> trailingPoints;
17240 while (it !=
mData->constEnd())
17242 currentRegion =
getRegion(it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom);
17243 if (currentRegion != prevRegion)
17245 if (currentRegion != 5)
17247 QPointF crossA, crossB;
17248 if (prevRegion == 5)
17250 lineData->append(
getOptimizedPoint(currentRegion, it.value().key, it.value().value, prevIt.value().key, prevIt.value().value, rectLeft, rectTop, rectRight, rectBottom));
17252 *lineData <<
getOptimizedCornerPoints(prevRegion, currentRegion, prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom);
17253 }
else if (
mayTraverse(prevRegion, currentRegion) &&
17254 getTraverse(prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom, crossA, crossB))
17257 QVector<QPointF> beforeTraverseCornerPoints, afterTraverseCornerPoints;
17258 getTraverseCornerPoints(prevRegion, currentRegion, rectLeft, rectTop, rectRight, rectBottom, beforeTraverseCornerPoints, afterTraverseCornerPoints);
17259 if (it !=
mData->constBegin())
17261 *lineData << beforeTraverseCornerPoints;
17262 lineData->append(crossA);
17263 lineData->append(crossB);
17264 *lineData << afterTraverseCornerPoints;
17267 lineData->append(crossB);
17268 *lineData << afterTraverseCornerPoints;
17269 trailingPoints << beforeTraverseCornerPoints << crossA ;
17273 *lineData <<
getOptimizedCornerPoints(prevRegion, currentRegion, prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom);
17277 if (it ==
mData->constBegin())
17278 trailingPoints <<
getOptimizedPoint(prevRegion, prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom);
17280 lineData->append(
getOptimizedPoint(prevRegion, prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom));
17281 lineData->append(
coordsToPixels(it.value().key, it.value().value));
17285 if (currentRegion == 5)
17287 lineData->append(
coordsToPixels(it.value().key, it.value().value));
17294 prevRegion = currentRegion;
17297 *lineData << trailingPoints;
17318 int QCPCurve::getRegion(
double x,
double y,
double rectLeft,
double rectTop,
double rectRight,
double rectBottom)
const
17324 else if (y < rectBottom)
17328 }
else if (x > rectRight)
17332 else if (y < rectBottom)
17340 else if (y < rectBottom)
17362 QPointF
QCPCurve::getOptimizedPoint(
int otherRegion,
double otherKey,
double otherValue,
double key,
double value,
double rectLeft,
double rectTop,
double rectRight,
double rectBottom)
const
17364 double intersectKey = rectLeft;
17365 double intersectValue = rectTop;
17366 switch (otherRegion)
17370 intersectValue = rectTop;
17371 intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue);
17372 if (intersectKey < rectLeft || intersectKey > rectRight)
17374 intersectKey = rectLeft;
17375 intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey);
17381 intersectKey = rectLeft;
17382 intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey);
17387 intersectValue = rectBottom;
17388 intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue);
17389 if (intersectKey < rectLeft || intersectKey > rectRight)
17391 intersectKey = rectLeft;
17392 intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey);
17398 intersectValue = rectTop;
17399 intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue);
17408 intersectValue = rectBottom;
17409 intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue);
17414 intersectValue = rectTop;
17415 intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue);
17416 if (intersectKey < rectLeft || intersectKey > rectRight)
17418 intersectKey = rectRight;
17419 intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey);
17425 intersectKey = rectRight;
17426 intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey);
17431 intersectValue = rectBottom;
17432 intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue);
17433 if (intersectKey < rectLeft || intersectKey > rectRight)
17435 intersectKey = rectRight;
17436 intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey);
17462 QVector<QPointF>
QCPCurve::getOptimizedCornerPoints(
int prevRegion,
int currentRegion,
double prevKey,
double prevValue,
double key,
double value,
double rectLeft,
double rectTop,
double rectRight,
double rectBottom)
const
17464 QVector<QPointF> result;
17465 switch (prevRegion)
17469 switch (currentRegion)
17478 if ((value-prevValue)/(key-prevKey)*(rectLeft-key)+value < rectBottom)
17489 switch (currentRegion)
17492 case 3: { result <<
coordsToPixels(rectLeft, rectBottom);
break; }
17493 case 4: { result <<
coordsToPixels(rectLeft, rectTop); result.append(result.last());
break; }
17494 case 6: { result <<
coordsToPixels(rectLeft, rectBottom); result.append(result.last());
break; }
17495 case 7: { result <<
coordsToPixels(rectLeft, rectTop); result.append(result.last()); result <<
coordsToPixels(rectRight, rectTop);
break; }
17496 case 9: { result <<
coordsToPixels(rectLeft, rectBottom); result.append(result.last()); result <<
coordsToPixels(rectRight, rectBottom);
break; }
17502 switch (currentRegion)
17504 case 2: { result <<
coordsToPixels(rectLeft, rectBottom);
break; }
17505 case 6: { result <<
coordsToPixels(rectLeft, rectBottom);
break; }
17509 case 8: { result <<
coordsToPixels(rectLeft, rectBottom) <<
coordsToPixels(rectRight, rectBottom); result.append(result.last());
break; }
17511 if ((value-prevValue)/(key-prevKey)*(rectRight-key)+value < rectBottom)
17522 switch (currentRegion)
17525 case 7: { result <<
coordsToPixels(rectRight, rectTop);
break; }
17526 case 2: { result <<
coordsToPixels(rectLeft, rectTop); result.append(result.last());
break; }
17527 case 8: { result <<
coordsToPixels(rectRight, rectTop); result.append(result.last());
break; }
17528 case 3: { result <<
coordsToPixels(rectLeft, rectTop); result.append(result.last()); result <<
coordsToPixels(rectLeft, rectBottom);
break; }
17529 case 9: { result <<
coordsToPixels(rectRight, rectTop); result.append(result.last()); result <<
coordsToPixels(rectRight, rectBottom);
break; }
17535 switch (currentRegion)
17538 case 7: { result <<
coordsToPixels(rectRight, rectTop);
break; }
17539 case 9: { result <<
coordsToPixels(rectRight, rectBottom);
break; }
17540 case 3: { result <<
coordsToPixels(rectLeft, rectBottom);
break; }
17546 switch (currentRegion)
17548 case 3: { result <<
coordsToPixels(rectLeft, rectBottom);
break; }
17549 case 9: { result <<
coordsToPixels(rectRight, rectBottom);
break; }
17550 case 2: { result <<
coordsToPixels(rectLeft, rectBottom); result.append(result.last());
break; }
17551 case 8: { result <<
coordsToPixels(rectRight, rectBottom); result.append(result.last());
break; }
17552 case 1: { result <<
coordsToPixels(rectLeft, rectBottom); result.append(result.last()); result <<
coordsToPixels(rectLeft, rectTop);
break; }
17553 case 7: { result <<
coordsToPixels(rectRight, rectBottom); result.append(result.last()); result <<
coordsToPixels(rectRight, rectTop);
break; }
17559 switch (currentRegion)
17561 case 4: { result <<
coordsToPixels(rectRight, rectTop);
break; }
17562 case 8: { result <<
coordsToPixels(rectRight, rectTop);
break; }
17566 case 6: { result <<
coordsToPixels(rectRight, rectTop) <<
coordsToPixels(rectRight, rectBottom); result.append(result.last());
break; }
17568 if ((value-prevValue)/(key-prevKey)*(rectRight-key)+value < rectBottom)
17579 switch (currentRegion)
17581 case 7: { result <<
coordsToPixels(rectRight, rectTop);
break; }
17582 case 9: { result <<
coordsToPixels(rectRight, rectBottom);
break; }
17583 case 4: { result <<
coordsToPixels(rectRight, rectTop); result.append(result.last());
break; }
17584 case 6: { result <<
coordsToPixels(rectRight, rectBottom); result.append(result.last());
break; }
17585 case 1: { result <<
coordsToPixels(rectRight, rectTop); result.append(result.last()); result <<
coordsToPixels(rectLeft, rectTop);
break; }
17586 case 3: { result <<
coordsToPixels(rectRight, rectBottom); result.append(result.last()); result <<
coordsToPixels(rectLeft, rectBottom);
break; }
17592 switch (currentRegion)
17594 case 6: { result <<
coordsToPixels(rectRight, rectBottom);
break; }
17595 case 8: { result <<
coordsToPixels(rectRight, rectBottom);
break; }
17598 case 2: { result <<
coordsToPixels(rectRight, rectBottom) <<
coordsToPixels(rectLeft, rectBottom); result.append(result.last());
break; }
17599 case 4: { result <<
coordsToPixels(rectRight, rectBottom) <<
coordsToPixels(rectRight, rectTop); result.append(result.last());
break; }
17601 if ((value-prevValue)/(key-prevKey)*(rectLeft-key)+value < rectBottom)
17628 switch (prevRegion)
17632 switch (currentRegion)
17637 case 3:
return false;
17638 default:
return true;
17643 switch (currentRegion)
17646 case 3:
return false;
17647 default:
return true;
17652 switch (currentRegion)
17657 case 9:
return false;
17658 default:
return true;
17663 switch (currentRegion)
17666 case 7:
return false;
17667 default:
return true;
17670 case 5:
return false;
17673 switch (currentRegion)
17676 case 9:
return false;
17677 default:
return true;
17682 switch (currentRegion)
17687 case 9:
return false;
17688 default:
return true;
17693 switch (currentRegion)
17696 case 9:
return false;
17697 default:
return true;
17702 switch (currentRegion)
17707 case 7:
return false;
17708 default:
return true;
17711 default:
return true;
17729 bool QCPCurve::getTraverse(
double prevKey,
double prevValue,
double key,
double value,
double rectLeft,
double rectTop,
double rectRight,
double rectBottom, QPointF &crossA, QPointF &crossB)
const
17731 QList<QPointF> intersections;
17732 if (qFuzzyIsNull(key-prevKey))
17735 intersections.append(QPointF(key, rectBottom));
17736 intersections.append(QPointF(key, rectTop));
17737 }
else if (qFuzzyIsNull(value-prevValue))
17740 intersections.append(QPointF(rectLeft, value));
17741 intersections.append(QPointF(rectRight, value));
17745 double keyPerValue = (key-prevKey)/(value-prevValue);
17747 gamma = prevKey + (rectTop-prevValue)*keyPerValue;
17748 if (gamma >= rectLeft && gamma <= rectRight)
17749 intersections.append(QPointF(gamma, rectTop));
17751 gamma = prevKey + (rectBottom-prevValue)*keyPerValue;
17752 if (gamma >= rectLeft && gamma <= rectRight)
17753 intersections.append(QPointF(gamma, rectBottom));
17754 double valuePerKey = 1.0/keyPerValue;
17756 gamma = prevValue + (rectLeft-prevKey)*valuePerKey;
17757 if (gamma >= rectBottom && gamma <= rectTop)
17758 intersections.append(QPointF(rectLeft, gamma));
17760 gamma = prevValue + (rectRight-prevKey)*valuePerKey;
17761 if (gamma >= rectBottom && gamma <= rectTop)
17762 intersections.append(QPointF(rectRight, gamma));
17766 if (intersections.size() > 2)
17769 double distSqrMax = 0;
17771 for (
int i=0; i<intersections.size()-1; ++i)
17773 for (
int k=i+1; k<intersections.size(); ++k)
17775 QPointF distPoint = intersections.at(i)-intersections.at(k);
17776 double distSqr = distPoint.x()*distPoint.x()+distPoint.y()+distPoint.y();
17777 if (distSqr > distSqrMax)
17779 pv1 = intersections.at(i);
17780 pv2 = intersections.at(k);
17781 distSqrMax = distSqr;
17785 intersections = QList<QPointF>() << pv1 << pv2;
17786 }
else if (intersections.size() != 2)
17793 if ((key-prevKey)*(intersections.at(1).x()-intersections.at(0).x()) + (value-prevValue)*(intersections.at(1).y()-intersections.at(0).y()) < 0)
17794 intersections.move(0, 1);
17795 crossA =
coordsToPixels(intersections.at(0).x(), intersections.at(0).y());
17796 crossB =
coordsToPixels(intersections.at(1).x(), intersections.at(1).y());
17825 void QCPCurve::getTraverseCornerPoints(
int prevRegion,
int currentRegion,
double rectLeft,
double rectTop,
double rectRight,
double rectBottom, QVector<QPointF> &beforeTraverse, QVector<QPointF> &afterTraverse)
const
17827 switch (prevRegion)
17831 switch (currentRegion)
17833 case 6: { beforeTraverse <<
coordsToPixels(rectLeft, rectTop);
break; }
17835 case 8: { beforeTraverse <<
coordsToPixels(rectLeft, rectTop);
break; }
17841 switch (currentRegion)
17843 case 7: { afterTraverse <<
coordsToPixels(rectRight, rectTop);
break; }
17844 case 9: { afterTraverse <<
coordsToPixels(rectRight, rectBottom);
break; }
17850 switch (currentRegion)
17852 case 4: { beforeTraverse <<
coordsToPixels(rectLeft, rectBottom);
break; }
17854 case 8: { beforeTraverse <<
coordsToPixels(rectLeft, rectBottom);
break; }
17860 switch (currentRegion)
17862 case 3: { afterTraverse <<
coordsToPixels(rectLeft, rectBottom);
break; }
17863 case 9: { afterTraverse <<
coordsToPixels(rectRight, rectBottom);
break; }
17870 switch (currentRegion)
17872 case 1: { afterTraverse <<
coordsToPixels(rectLeft, rectTop);
break; }
17873 case 7: { afterTraverse <<
coordsToPixels(rectRight, rectTop);
break; }
17879 switch (currentRegion)
17881 case 2: { beforeTraverse <<
coordsToPixels(rectRight, rectTop);
break; }
17883 case 6: { beforeTraverse <<
coordsToPixels(rectRight, rectTop);
break; }
17889 switch (currentRegion)
17891 case 1: { afterTraverse <<
coordsToPixels(rectLeft, rectTop);
break; }
17892 case 3: { afterTraverse <<
coordsToPixels(rectLeft, rectBottom);
break; }
17898 switch (currentRegion)
17900 case 2: { beforeTraverse <<
coordsToPixels(rectRight, rectBottom);
break; }
17902 case 4: { beforeTraverse <<
coordsToPixels(rectRight, rectBottom);
break; }
17917 if (
mData->isEmpty())
17919 qDebug() << Q_FUNC_INFO <<
"requested point distance on curve" <<
mName <<
"without data";
17922 if (
mData->size() == 1)
17925 return QVector2D(dataPoint-pixelPoint).length();
17929 QVector<QPointF> *lineData =
new QVector<QPointF>;
17931 double minDistSqr = std::numeric_limits<double>::max();
17932 for (
int i=0; i<lineData->size()-1; ++i)
17934 double currentDistSqr =
distSqrToLine(lineData->at(i), lineData->at(i+1), pixelPoint);
17935 if (currentDistSqr < minDistSqr)
17936 minDistSqr = currentDistSqr;
17939 return qSqrt(minDistSqr);
17946 bool haveLower =
false;
17947 bool haveUpper =
false;
17951 QCPCurveDataMap::const_iterator it =
mData->constBegin();
17952 while (it !=
mData->constEnd())
17954 current = it.value().key;
17955 if (!qIsNaN(current) && !qIsNaN(it.value().value))
17959 if (current < range.
lower || !haveLower)
17961 range.
lower = current;
17964 if (current > range.
upper || !haveUpper)
17966 range.
upper = current;
17974 foundRange = haveLower && haveUpper;
17982 bool haveLower =
false;
17983 bool haveUpper =
false;
17987 QCPCurveDataMap::const_iterator it =
mData->constBegin();
17988 while (it !=
mData->constEnd())
17990 current = it.value().value;
17991 if (!qIsNaN(current) && !qIsNaN(it.value().key))
17995 if (current < range.
lower || !haveLower)
17997 range.
lower = current;
18000 if (current > range.
upper || !haveUpper)
18002 range.
upper = current;
18010 foundRange = haveLower && haveUpper;
18087 QObject(parentPlot),
18088 mParentPlot(parentPlot),
18089 mSpacingType(stAbsolute),
18130 if (index >= 0 && index <
mBars.size())
18132 return mBars.at(index);
18135 qDebug() << Q_FUNC_INFO <<
"index out of bounds:" << index;
18161 qDebug() << Q_FUNC_INFO <<
"bars is 0";
18165 if (!
mBars.contains(bars))
18168 qDebug() << Q_FUNC_INFO <<
"bars plottable is already in this bars group:" <<
reinterpret_cast<quintptr
>(
bars);
18184 qDebug() << Q_FUNC_INFO <<
"bars is 0";
18189 if (!
mBars.contains(bars))
18204 qDebug() << Q_FUNC_INFO <<
"bars is 0";
18208 if (
mBars.contains(bars))
18211 qDebug() << Q_FUNC_INFO <<
"bars plottable is not in this bars group:" <<
reinterpret_cast<quintptr
>(
bars);
18223 if (!
mBars.contains(bars))
18224 mBars.append(bars);
18236 mBars.removeOne(bars);
18248 QList<const QCPBars*> baseBars;
18253 if (!baseBars.contains(b))
18254 baseBars.append(b);
18263 int index = baseBars.indexOf(thisBase);
18267 double lowerPixelWidth, upperPixelWidth;
18268 if (baseBars.size() % 2 == 1 && index == (baseBars.size()-1)/2)
18271 }
else if (index < (baseBars.size()-1)/2.0)
18273 if (baseBars.size() % 2 == 0)
18275 startIndex = baseBars.size()/2-1;
18279 startIndex = (baseBars.size()-1)/2-1;
18280 baseBars.at((baseBars.size()-1)/2)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth);
18281 result -= qAbs(upperPixelWidth-lowerPixelWidth)*0.5;
18282 result -=
getPixelSpacing(baseBars.at((baseBars.size()-1)/2), keyCoord);
18284 for (
int i=startIndex; i>index; --i)
18286 baseBars.at(i)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth);
18287 result -= qAbs(upperPixelWidth-lowerPixelWidth);
18291 baseBars.at(index)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth);
18292 result -= qAbs(upperPixelWidth-lowerPixelWidth)*0.5;
18295 if (baseBars.size() % 2 == 0)
18297 startIndex = baseBars.size()/2;
18301 startIndex = (baseBars.size()-1)/2+1;
18302 baseBars.at((baseBars.size()-1)/2)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth);
18303 result += qAbs(upperPixelWidth-lowerPixelWidth)*0.5;
18304 result +=
getPixelSpacing(baseBars.at((baseBars.size()-1)/2), keyCoord);
18306 for (
int i=startIndex; i<index; ++i)
18308 baseBars.at(i)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth);
18309 result += qAbs(upperPixelWidth-lowerPixelWidth);
18313 baseBars.at(index)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth);
18314 result += qAbs(upperPixelWidth-lowerPixelWidth)*0.5;
18460 mWidthType(wtPlotCoords),
18465 mPen.setColor(Qt::blue);
18466 mPen.setStyle(Qt::SolidLine);
18467 mBrush.setColor(QColor(40, 50, 255, 30));
18468 mBrush.setStyle(Qt::SolidPattern);
18552 qDebug() << Q_FUNC_INFO <<
"The data pointer is already in (and owned by) this plottable" <<
reinterpret_cast<quintptr
>(
data);
18574 int n = key.size();
18575 n = qMin(n, value.size());
18577 for (
int i=0; i<n; ++i)
18579 newData.
key = key[i];
18580 newData.value = value[i];
18581 mData->insertMulti(newData.key, newData);
18601 if (bars ==
this)
return;
18604 qDebug() << Q_FUNC_INFO <<
"passed QCPBars* doesn't have same key and value axis as this QCPBars";
18634 if (bars ==
this)
return;
18637 qDebug() << Q_FUNC_INFO <<
"passed QCPBars* doesn't have same key and value axis as this QCPBars";
18657 mData->unite(dataMap);
18666 mData->insertMulti(data.
key, data);
18677 newData.
value = value;
18678 mData->insertMulti(newData.
key, newData);
18687 int n = keys.size();
18688 n = qMin(n, values.size());
18690 for (
int i=0; i<n; ++i)
18692 newData.
key = keys[i];
18693 newData.value = values[i];
18694 mData->insertMulti(newData.key, newData);
18704 QCPBarDataMap::iterator it =
mData->begin();
18705 while (it !=
mData->end() && it.key() < key)
18706 it =
mData->erase(it);
18715 if (
mData->isEmpty())
return;
18716 QCPBarDataMap::iterator it =
mData->upperBound(key);
18717 while (it !=
mData->end())
18718 it =
mData->erase(it);
18730 if (fromKey >= toKey ||
mData->isEmpty())
return;
18731 QCPBarDataMap::iterator it =
mData->upperBound(fromKey);
18732 QCPBarDataMap::iterator itEnd =
mData->upperBound(toKey);
18733 while (it != itEnd)
18734 it =
mData->erase(it);
18747 mData->remove(key);
18765 if (!
mKeyAxis || !
mValueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return -1; }
18767 if (
mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()))
18769 QCPBarDataMap::ConstIterator it;
18770 for (it =
mData->constBegin(); it !=
mData->constEnd(); ++it)
18772 if (
getBarPolygon(it.value().key, it.value().value).boundingRect().contains(pos))
18782 if (!
mKeyAxis || !
mValueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
18783 if (
mData->isEmpty())
return;
18785 QCPBarDataMap::const_iterator it, lower, upperEnd;
18787 for (it = lower; it != upperEnd; ++it)
18790 #ifdef QCUSTOMPLOT_CHECK_DATA
18792 qDebug() << Q_FUNC_INFO <<
"Data point at" << it.key() <<
"of drawn range invalid." <<
"Plottable name:" <<
name();
18794 QPolygonF barPolygon =
getBarPolygon(it.key(), it.value().value);
18799 painter->
setPen(Qt::NoPen);
18801 painter->drawPolygon(barPolygon);
18804 if (
mainPen().style() != Qt::NoPen &&
mainPen().color().alpha() != 0)
18808 painter->setBrush(Qt::NoBrush);
18809 painter->drawPolyline(barPolygon);
18819 painter->setBrush(
mBrush);
18821 QRectF r = QRectF(0, 0, rect.width()*0.67, rect.height()*0.67);
18822 r.moveCenter(rect.center());
18823 painter->drawRect(r);
18842 if (!
mKeyAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key axis";
return; }
18843 if (
mData->isEmpty())
18845 lower =
mData->constEnd();
18846 upperEnd =
mData->constEnd();
18852 upperEnd =
mData->upperBound(
mKeyAxis.data()->range().upper);
18853 double lowerPixelBound =
mKeyAxis.data()->coordToPixel(
mKeyAxis.data()->range().lower);
18854 double upperPixelBound =
mKeyAxis.data()->coordToPixel(
mKeyAxis.data()->range().upper);
18855 bool isVisible =
false;
18857 QCPBarDataMap::const_iterator it = lower;
18858 while (it !=
mData->constBegin())
18861 QRectF barBounds =
getBarPolygon(it.value().key, it.value().value).boundingRect();
18862 if (
mKeyAxis.data()->orientation() == Qt::Horizontal)
18863 isVisible = ((!
mKeyAxis.data()->rangeReversed() && barBounds.right() >= lowerPixelBound) || (
mKeyAxis.data()->rangeReversed() && barBounds.left() <= lowerPixelBound));
18865 isVisible = ((!
mKeyAxis.data()->rangeReversed() && barBounds.top() <= lowerPixelBound) || (
mKeyAxis.data()->rangeReversed() && barBounds.bottom() >= lowerPixelBound));
18873 while (it !=
mData->constEnd())
18875 QRectF barBounds =
getBarPolygon(upperEnd.value().key, upperEnd.value().value).boundingRect();
18876 if (
mKeyAxis.data()->orientation() == Qt::Horizontal)
18877 isVisible = ((!
mKeyAxis.data()->rangeReversed() && barBounds.left() <= upperPixelBound) || (
mKeyAxis.data()->rangeReversed() && barBounds.right() >= upperPixelBound));
18879 isVisible = ((!
mKeyAxis.data()->rangeReversed() && barBounds.bottom() >= upperPixelBound) || (
mKeyAxis.data()->rangeReversed() && barBounds.top() <= upperPixelBound));
18898 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return QPolygonF(); }
18901 double lowerPixelWidth, upperPixelWidth;
18905 double valuePixel = valueAxis->
coordToPixel(base+value);
18911 result << QPointF(keyPixel+lowerPixelWidth, basePixel);
18912 result << QPointF(keyPixel+lowerPixelWidth, valuePixel);
18913 result << QPointF(keyPixel+upperPixelWidth, valuePixel);
18914 result << QPointF(keyPixel+upperPixelWidth, basePixel);
18917 result << QPointF(basePixel, keyPixel+lowerPixelWidth);
18918 result << QPointF(valuePixel, keyPixel+lowerPixelWidth);
18919 result << QPointF(valuePixel, keyPixel+upperPixelWidth);
18920 result << QPointF(basePixel, keyPixel+upperPixelWidth);
18943 qSwap(lower, upper);
18950 if (
mKeyAxis.data()->orientation() == Qt::Horizontal)
18956 qSwap(lower, upper);
18958 qDebug() << Q_FUNC_INFO <<
"No key axis or axis rect defined";
18965 double keyPixel =
mKeyAxis.data()->coordToPixel(key);
18971 qDebug() << Q_FUNC_INFO <<
"No key axis defined";
18992 double epsilon = qAbs(key)*1e-6;
18995 QCPBarDataMap::const_iterator it =
mBarBelow.data()->mData->lowerBound(key-epsilon);
18996 QCPBarDataMap::const_iterator itEnd =
mBarBelow.data()->mData->upperBound(key+epsilon);
18997 while (it != itEnd)
18999 if ((positive && it.value().value > max) ||
19000 (!positive && it.value().value < max))
19001 max = it.value().value;
19005 return max +
mBarBelow.data()->getStackedBaseValue(key, positive);
19020 if (!lower && !upper)
return;
19026 upper->
mBarBelow.data()->mBarAbove = 0;
19032 lower->
mBarAbove.data()->mBarBelow = 0;
19038 lower->
mBarAbove.data()->mBarBelow = 0;
19041 upper->
mBarBelow.data()->mBarAbove = 0;
19051 bool haveLower =
false;
19052 bool haveUpper =
false;
19055 QCPBarDataMap::const_iterator it =
mData->constBegin();
19056 while (it !=
mData->constEnd())
19058 current = it.value().key;
19061 if (current < range.
lower || !haveLower)
19063 range.
lower = current;
19066 if (current > range.
upper || !haveUpper)
19068 range.
upper = current;
19077 double lowerPixelWidth, upperPixelWidth, keyPixel;
19079 keyPixel =
mKeyAxis.data()->coordToPixel(range.
lower) + lowerPixelWidth;
19086 double lowerPixelWidth, upperPixelWidth, keyPixel;
19088 keyPixel =
mKeyAxis.data()->coordToPixel(range.
upper) + upperPixelWidth;
19093 foundRange = haveLower && haveUpper;
19103 bool haveLower =
true;
19104 bool haveUpper =
true;
19107 QCPBarDataMap::const_iterator it =
mData->constBegin();
19108 while (it !=
mData->constEnd())
19113 if (current < range.
lower || !haveLower)
19115 range.
lower = current;
19118 if (current > range.
upper || !haveUpper)
19120 range.
upper = current;
19201 setPen(QPen(Qt::black));
19203 setMedianPen(QPen(Qt::black, 3, Qt::SolidLine, Qt::FlatCap));
19204 setWhiskerPen(QPen(Qt::black, 0, Qt::DashLine, Qt::FlatCap));
19383 if (!
mKeyAxis || !
mValueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return -1; }
19385 if (
mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()))
19387 double posKey, posValue;
19405 if (!
mKeyAxis || !
mValueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
19408 #ifdef QCUSTOMPLOT_CHECK_DATA
19412 qDebug() << Q_FUNC_INFO <<
"Data point at" <<
mKey <<
"of drawn range has invalid data." <<
"Plottable name:" <<
name();
19415 qDebug() << Q_FUNC_INFO <<
"Data point outlier at" <<
mKey <<
"of drawn range invalid." <<
"Plottable name:" <<
name();
19418 QRectF quartileBox;
19422 painter->setClipRect(quartileBox, Qt::IntersectClip);
19436 painter->setBrush(
mBrush);
19437 QRectF r = QRectF(0, 0, rect.width()*0.67, rect.height()*0.67);
19438 r.moveCenter(rect.center());
19439 painter->drawRect(r);
19456 painter->drawRect(box);
19458 *quartileBox = box;
19481 QLineF backboneMin, backboneMax, barMin, barMax;
19511 if (inSignDomain ==
sdBoth)
19522 foundRange =
false;
19533 foundRange =
false;
19537 foundRange =
false;
19544 QVector<double> values;
19549 bool haveUpper =
false;
19550 bool haveLower =
false;
19553 for (
int i=0; i<values.size(); ++i)
19555 if ((inSignDomain ==
sdNegative && values.at(i) < 0) ||
19556 (inSignDomain ==
sdPositive && values.at(i) > 0) ||
19557 (inSignDomain ==
sdBoth))
19559 if (values.at(i) > upper || !haveUpper)
19561 upper = values.at(i);
19564 if (values.at(i) < lower || !haveLower)
19566 lower = values.at(i);
19572 if (haveLower && haveUpper)
19578 foundRange =
false;
19636 mKeyRange(keyRange),
19637 mValueRange(valueRange),
19640 mDataModified(true)
19660 mDataModified(true)
19670 if (&other !=
this)
19689 if (keyCell >= 0 && keyCell < mKeySize && valueCell >= 0 && valueCell <
mValueSize)
19698 if (keyIndex >= 0 && keyIndex < mKeySize && valueIndex >= 0 && valueIndex <
mValueSize)
19727 #ifdef __EXCEPTIONS
19731 #ifdef __EXCEPTIONS
19732 }
catch (...) {
mData = 0; }
19737 qDebug() << Q_FUNC_INFO <<
"out of memory for data dimensions "<<
mKeySize <<
"*" <<
mValueSize;
19836 if (keyCell >= 0 && keyCell < mKeySize && valueCell >= 0 && valueCell <
mValueSize)
19860 if (keyIndex >= 0 && keyIndex < mKeySize && valueIndex >= 0 && valueIndex <
mValueSize)
19888 double minHeight =
mData[0];
19889 double maxHeight =
mData[0];
19891 for (
int i=0; i<dataCount; ++i)
19893 if (
mData[i] > maxHeight)
19894 maxHeight =
mData[i];
19895 if (
mData[i] < minHeight)
19896 minHeight =
mData[i];
19919 for (
int i=0; i<dataCount; ++i)
20081 mDataScaleType(
QCPAxis::stLinear),
20083 mInterpolate(true),
20084 mTightBoundary(false),
20085 mMapImageInvalidated(true)
20105 qDebug() << Q_FUNC_INFO <<
"The data pointer is already in (and owned by) this plottable" <<
reinterpret_cast<quintptr
>(
data);
20269 if (recalculateDataBounds)
20297 mLegendIcon = QPixmap::fromImage(
mMapImage.mirrored(mirrorX, mirrorY)).scaled(thumbSize, Qt::KeepAspectRatio, transformMode);
20316 if (!
mKeyAxis || !
mValueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return -1; }
20318 if (
mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()))
20320 double posKey, posValue;
20345 if (!keyAxis)
return;
20350 int keyOversamplingFactor =
mInterpolate ? 1 : (int)(1.0+100.0/(
double)keySize);
20351 int valueOversamplingFactor =
mInterpolate ? 1 : (int)(1.0+100.0/(
double)valueSize);
20354 if (keyAxis->
orientation() == Qt::Horizontal && (
mMapImage.width() != keySize*keyOversamplingFactor ||
mMapImage.height() != valueSize*valueOversamplingFactor))
20355 mMapImage = QImage(QSize(keySize*keyOversamplingFactor, valueSize*valueOversamplingFactor), QImage::Format_RGB32);
20356 else if (keyAxis->
orientation() == Qt::Vertical && (
mMapImage.width() != valueSize*valueOversamplingFactor ||
mMapImage.height() != keySize*keyOversamplingFactor))
20357 mMapImage = QImage(QSize(valueSize*valueOversamplingFactor, keySize*keyOversamplingFactor), QImage::Format_RGB32);
20360 if (keyOversamplingFactor > 1 || valueOversamplingFactor > 1)
20374 const int lineCount = valueSize;
20375 const int rowCount = keySize;
20376 for (
int line=0; line<lineCount; ++line)
20378 QRgb* pixels =
reinterpret_cast<QRgb*
>(localMapImage->scanLine(lineCount-1-line));
20383 const int lineCount = keySize;
20384 const int rowCount = valueSize;
20385 for (
int line=0; line<lineCount; ++line)
20387 QRgb* pixels =
reinterpret_cast<QRgb*
>(localMapImage->scanLine(lineCount-1-line));
20392 if (keyOversamplingFactor > 1 || valueOversamplingFactor > 1)
20395 mMapImage =
mUndersampledMapImage.scaled(keySize*keyOversamplingFactor, valueSize*valueOversamplingFactor, Qt::IgnoreAspectRatio, Qt::FastTransformation);
20397 mMapImage =
mUndersampledMapImage.scaled(valueSize*valueOversamplingFactor, keySize*keyOversamplingFactor, Qt::IgnoreAspectRatio, Qt::FastTransformation);
20416 QRectF mapBufferTarget;
20418 double mapBufferPixelRatio = 3;
20421 mapBufferTarget = painter->clipRegion().boundingRect();
20422 mapBuffer = QPixmap((mapBufferTarget.size()*mapBufferPixelRatio).toSize());
20423 mapBuffer.fill(Qt::transparent);
20425 localPainter->scale(mapBufferPixelRatio, mapBufferPixelRatio);
20426 localPainter->translate(-mapBufferTarget.topLeft());
20432 double halfCellWidth = 0;
20433 double halfCellHeight = 0;
20434 if (
keyAxis()->orientation() == Qt::Horizontal)
20437 halfCellWidth = 0.5*imageRect.width()/(double)(
mMapData->
keySize()-1);
20443 halfCellHeight = 0.5*imageRect.height()/(double)(
mMapData->
keySize()-1);
20447 imageRect.adjust(-halfCellWidth, -halfCellHeight, halfCellWidth, halfCellHeight);
20450 bool smoothBackup = localPainter->renderHints().testFlag(QPainter::SmoothPixmapTransform);
20451 localPainter->setRenderHint(QPainter::SmoothPixmapTransform,
mInterpolate);
20452 QRegion clipBackup;
20455 clipBackup = localPainter->clipRegion();
20458 localPainter->setClipRect(tightClipRect, Qt::IntersectClip);
20460 localPainter->drawImage(imageRect,
mMapImage.mirrored(mirrorX, mirrorY));
20462 localPainter->setClipRegion(clipBackup);
20463 localPainter->setRenderHint(QPainter::SmoothPixmapTransform, smoothBackup);
20467 delete localPainter;
20468 painter->drawPixmap(mapBufferTarget.toRect(), mapBuffer);
20479 QPixmap scaledIcon =
mLegendIcon.scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::FastTransformation);
20480 QRectF iconRect = QRectF(0, 0, scaledIcon.width(), scaledIcon.height());
20481 iconRect.moveCenter(rect.center());
20482 painter->drawPixmap(iconRect.topLeft(), scaledIcon);
20502 else if (result.
lower <= 0 && result.
upper <= 0)
20503 foundRange =
false;
20508 else if (result.
upper >= 0 && result.
lower >= 0)
20509 foundRange =
false;
20524 else if (result.
lower <= 0 && result.
upper <= 0)
20525 foundRange =
false;
20530 else if (result.
upper >= 0 && result.
lower >= 0)
20531 foundRange =
false;
20640 mChartStyle(csOhlc),
20642 mTwoColored(false),
20643 mBrushPositive(QBrush(QColor(210, 210, 255))),
20644 mBrushNegative(QBrush(QColor(255, 210, 210))),
20645 mPenPositive(QPen(QColor(10, 40, 180))),
20646 mPenNegative(QPen(QColor(180, 40, 10)))
20675 qDebug() << Q_FUNC_INFO <<
"The data pointer is already in (and owned by) this plottable" <<
reinterpret_cast<quintptr
>(
data);
20695 void QCPFinancial::setData(
const QVector<double> &key,
const QVector<double> &open,
const QVector<double> &high,
const QVector<double> &low,
const QVector<double> &close)
20698 int n = key.size();
20699 n = qMin(n, open.size());
20700 n = qMin(n, high.size());
20701 n = qMin(n, low.size());
20702 n = qMin(n, close.size());
20703 for (
int i=0; i<n; ++i)
20807 mData->unite(dataMap);
20821 mData->insertMulti(data.
key, data);
20848 void QCPFinancial::addData(
const QVector<double> &key,
const QVector<double> &open,
const QVector<double> &high,
const QVector<double> &low,
const QVector<double> &close)
20850 int n = key.size();
20851 n = qMin(n, open.size());
20852 n = qMin(n, high.size());
20853 n = qMin(n, low.size());
20854 n = qMin(n, close.size());
20855 for (
int i=0; i<n; ++i)
20868 QCPFinancialDataMap::iterator it =
mData->begin();
20869 while (it !=
mData->end() && it.key() < key)
20870 it =
mData->erase(it);
20880 if (
mData->isEmpty())
return;
20881 QCPFinancialDataMap::iterator it =
mData->upperBound(key);
20882 while (it !=
mData->end())
20883 it =
mData->erase(it);
20895 if (fromKey >= toKey ||
mData->isEmpty())
return;
20896 QCPFinancialDataMap::iterator it =
mData->upperBound(fromKey);
20897 QCPFinancialDataMap::iterator itEnd =
mData->upperBound(toKey);
20898 while (it != itEnd)
20899 it =
mData->erase(it);
20912 mData->remove(key);
20931 if (!
mKeyAxis || !
mValueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return -1; }
20933 if (
mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()))
20936 QCPFinancialDataMap::const_iterator lower, upper;
20938 if (lower ==
mData->constEnd() || upper ==
mData->constEnd())
20968 int count = qMin(time.size(), value.size());
20972 QCPFinancialData currentBinData(0, value.first(), value.first(), value.first(), value.first());
20973 int currentBinIndex = qFloor((time.first()-timeBinOffset)/timeBinSize+0.5);
20974 for (
int i=0; i<count; ++i)
20976 int index = qFloor((time.at(i)-timeBinOffset)/timeBinSize+0.5);
20977 if (currentBinIndex == index)
20979 if (value.at(i) < currentBinData.low) currentBinData.low = value.at(i);
20980 if (value.at(i) > currentBinData.high) currentBinData.high = value.at(i);
20983 currentBinData.close = value.at(i);
20984 currentBinData.key = timeBinOffset+(index)*timeBinSize;
20985 map.insert(currentBinData.key, currentBinData);
20990 currentBinData.close = value.at(i-1);
20991 currentBinData.key = timeBinOffset+(index-1)*timeBinSize;
20992 map.insert(currentBinData.key, currentBinData);
20994 currentBinIndex = index;
20995 currentBinData.open = value.at(i);
20996 currentBinData.high = value.at(i);
20997 currentBinData.low = value.at(i);
21008 QCPFinancialDataMap::const_iterator lower, upper;
21010 if (lower ==
mData->constEnd() || upper ==
mData->constEnd())
21034 painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.topLeft().toPoint()));
21035 painter->
drawLine(QLineF(0, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
21036 painter->
drawLine(QLineF(rect.width()*0.2, rect.height()*0.3, rect.width()*0.2, rect.height()*0.5).translated(rect.topLeft()));
21037 painter->
drawLine(QLineF(rect.width()*0.8, rect.height()*0.5, rect.width()*0.8, rect.height()*0.7).translated(rect.topLeft()));
21041 painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.bottomRight().toPoint()));
21042 painter->
drawLine(QLineF(0, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
21043 painter->
drawLine(QLineF(rect.width()*0.2, rect.height()*0.3, rect.width()*0.2, rect.height()*0.5).translated(rect.topLeft()));
21044 painter->
drawLine(QLineF(rect.width()*0.8, rect.height()*0.5, rect.width()*0.8, rect.height()*0.7).translated(rect.topLeft()));
21047 painter->setBrush(
mBrush);
21049 painter->
drawLine(QLineF(0, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
21050 painter->
drawLine(QLineF(rect.width()*0.2, rect.height()*0.3, rect.width()*0.2, rect.height()*0.5).translated(rect.topLeft()));
21051 painter->
drawLine(QLineF(rect.width()*0.8, rect.height()*0.5, rect.width()*0.8, rect.height()*0.7).translated(rect.topLeft()));
21060 painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.topLeft().toPoint()));
21061 painter->
drawLine(QLineF(0, rect.height()*0.5, rect.width()*0.25, rect.height()*0.5).translated(rect.topLeft()));
21062 painter->
drawLine(QLineF(rect.width()*0.75, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
21063 painter->drawRect(QRectF(rect.width()*0.25, rect.height()*0.25, rect.width()*0.5, rect.height()*0.5).translated(rect.topLeft()));
21067 painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.bottomRight().toPoint()));
21068 painter->
drawLine(QLineF(0, rect.height()*0.5, rect.width()*0.25, rect.height()*0.5).translated(rect.topLeft()));
21069 painter->
drawLine(QLineF(rect.width()*0.75, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
21070 painter->drawRect(QRectF(rect.width()*0.25, rect.height()*0.25, rect.width()*0.5, rect.height()*0.5).translated(rect.topLeft()));
21073 painter->setBrush(
mBrush);
21075 painter->
drawLine(QLineF(0, rect.height()*0.5, rect.width()*0.25, rect.height()*0.5).translated(rect.topLeft()));
21076 painter->
drawLine(QLineF(rect.width()*0.75, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft()));
21077 painter->drawRect(QRectF(rect.width()*0.25, rect.height()*0.25, rect.width()*0.5, rect.height()*0.5).translated(rect.topLeft()));
21086 bool haveLower =
false;
21087 bool haveUpper =
false;
21090 QCPFinancialDataMap::const_iterator it =
mData->constBegin();
21091 while (it !=
mData->constEnd())
21093 current = it.value().key;
21096 if (current < range.
lower || !haveLower)
21098 range.
lower = current;
21101 if (current > range.
upper || !haveUpper)
21103 range.
upper = current;
21114 foundRange = haveLower && haveUpper;
21122 bool haveLower =
false;
21123 bool haveUpper =
false;
21125 QCPFinancialDataMap::const_iterator it =
mData->constBegin();
21126 while (it !=
mData->constEnd())
21129 if (inSignDomain ==
sdBoth || (inSignDomain ==
sdNegative && it.value().high < 0) || (inSignDomain ==
sdPositive && it.value().high > 0))
21131 if (it.value().high < range.
lower || !haveLower)
21133 range.
lower = it.value().high;
21136 if (it.value().high > range.
upper || !haveUpper)
21138 range.
upper = it.value().high;
21143 if (inSignDomain ==
sdBoth || (inSignDomain ==
sdNegative && it.value().low < 0) || (inSignDomain ==
sdPositive && it.value().low > 0))
21145 if (it.value().low < range.
lower || !haveLower)
21147 range.
lower = it.value().low;
21150 if (it.value().low > range.
upper || !haveUpper)
21152 range.
upper = it.value().low;
21159 foundRange = haveLower && haveUpper;
21173 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
21179 for (QCPFinancialDataMap::const_iterator it = begin; it != end; ++it)
21187 painter->
setPen(linePen);
21188 double keyPixel = keyAxis->
coordToPixel(it.value().key);
21189 double openPixel = valueAxis->
coordToPixel(it.value().open);
21190 double closePixel = valueAxis->
coordToPixel(it.value().close);
21195 painter->
drawLine(QPointF(keyPixel-keyWidthPixels, openPixel), QPointF(keyPixel, openPixel));
21197 painter->
drawLine(QPointF(keyPixel, closePixel), QPointF(keyPixel+keyWidthPixels, closePixel));
21201 for (QCPFinancialDataMap::const_iterator it = begin; it != end; ++it)
21209 painter->
setPen(linePen);
21210 double keyPixel = keyAxis->
coordToPixel(it.value().key);
21211 double openPixel = valueAxis->
coordToPixel(it.value().open);
21212 double closePixel = valueAxis->
coordToPixel(it.value().close);
21217 painter->
drawLine(QPointF(openPixel, keyPixel-keyWidthPixels), QPointF(openPixel, keyPixel));
21219 painter->
drawLine(QPointF(closePixel, keyPixel), QPointF(closePixel, keyPixel+keyWidthPixels));
21234 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return; }
21241 for (QCPFinancialDataMap::const_iterator it = begin; it != end; ++it)
21249 if (it.value().close >= it.value().open)
21263 painter->
setPen(linePen);
21264 painter->setBrush(boxBrush);
21265 double keyPixel = keyAxis->
coordToPixel(it.value().key);
21266 double openPixel = valueAxis->
coordToPixel(it.value().open);
21267 double closePixel = valueAxis->
coordToPixel(it.value().close);
21269 painter->
drawLine(QPointF(keyPixel, valueAxis->
coordToPixel(it.value().high)), QPointF(keyPixel, valueAxis->
coordToPixel(qMax(it.value().open, it.value().close))));
21271 painter->
drawLine(QPointF(keyPixel, valueAxis->
coordToPixel(it.value().low)), QPointF(keyPixel, valueAxis->
coordToPixel(qMin(it.value().open, it.value().close))));
21274 painter->drawRect(QRectF(QPointF(keyPixel-keyWidthPixels, closePixel), QPointF(keyPixel+keyWidthPixels, openPixel)));
21278 for (QCPFinancialDataMap::const_iterator it = begin; it != end; ++it)
21286 if (it.value().close >= it.value().open)
21300 painter->
setPen(linePen);
21301 painter->setBrush(boxBrush);
21302 double keyPixel = keyAxis->
coordToPixel(it.value().key);
21303 double openPixel = valueAxis->
coordToPixel(it.value().open);
21304 double closePixel = valueAxis->
coordToPixel(it.value().close);
21306 painter->
drawLine(QPointF(valueAxis->
coordToPixel(it.value().high), keyPixel), QPointF(valueAxis->
coordToPixel(qMax(it.value().open, it.value().close)), keyPixel));
21308 painter->
drawLine(QPointF(valueAxis->
coordToPixel(it.value().low), keyPixel), QPointF(valueAxis->
coordToPixel(qMin(it.value().open, it.value().close)), keyPixel));
21311 painter->drawRect(QRectF(QPointF(closePixel, keyPixel-keyWidthPixels), QPointF(openPixel, keyPixel+keyWidthPixels)));
21321 double QCPFinancial::ohlcSelectTest(
const QPointF &pos,
const QCPFinancialDataMap::const_iterator &begin,
const QCPFinancialDataMap::const_iterator &end)
const
21325 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return -1; }
21327 double minDistSqr = std::numeric_limits<double>::max();
21328 QCPFinancialDataMap::const_iterator it;
21331 for (it = begin; it != end; ++it)
21333 double keyPixel = keyAxis->
coordToPixel(it.value().key);
21336 if (currentDistSqr < minDistSqr)
21337 minDistSqr = currentDistSqr;
21341 for (it = begin; it != end; ++it)
21343 double keyPixel = keyAxis->
coordToPixel(it.value().key);
21346 if (currentDistSqr < minDistSqr)
21347 minDistSqr = currentDistSqr;
21350 return qSqrt(minDistSqr);
21363 if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key or value axis";
return -1; }
21365 double minDistSqr = std::numeric_limits<double>::max();
21366 QCPFinancialDataMap::const_iterator it;
21369 for (it = begin; it != end; ++it)
21371 double currentDistSqr;
21374 QCPRange boxValueRange(it.value().close, it.value().open);
21375 double posKey, posValue;
21377 if (boxKeyRange.
contains(posKey) && boxValueRange.contains(posValue))
21383 double keyPixel = keyAxis->
coordToPixel(it.value().key);
21384 double highLineDistSqr =
distSqrToLine(QPointF(keyPixel, valueAxis->
coordToPixel(it.value().high)), QPointF(keyPixel, valueAxis->
coordToPixel(qMax(it.value().open, it.value().close))), pos);
21385 double lowLineDistSqr =
distSqrToLine(QPointF(keyPixel, valueAxis->
coordToPixel(it.value().low)), QPointF(keyPixel, valueAxis->
coordToPixel(qMin(it.value().open, it.value().close))), pos);
21386 currentDistSqr = qMin(highLineDistSqr, lowLineDistSqr);
21388 if (currentDistSqr < minDistSqr)
21389 minDistSqr = currentDistSqr;
21393 for (it = begin; it != end; ++it)
21395 double currentDistSqr;
21398 QCPRange boxValueRange(it.value().close, it.value().open);
21399 double posKey, posValue;
21401 if (boxKeyRange.
contains(posKey) && boxValueRange.contains(posValue))
21407 double keyPixel = keyAxis->
coordToPixel(it.value().key);
21408 double highLineDistSqr =
distSqrToLine(QPointF(valueAxis->
coordToPixel(it.value().high), keyPixel), QPointF(valueAxis->
coordToPixel(qMax(it.value().open, it.value().close)), keyPixel), pos);
21409 double lowLineDistSqr =
distSqrToLine(QPointF(valueAxis->
coordToPixel(it.value().low), keyPixel), QPointF(valueAxis->
coordToPixel(qMin(it.value().open, it.value().close)), keyPixel), pos);
21410 currentDistSqr = qMin(highLineDistSqr, lowLineDistSqr);
21412 if (currentDistSqr < minDistSqr)
21413 minDistSqr = currentDistSqr;
21416 return qSqrt(minDistSqr);
21437 if (!
mKeyAxis) { qDebug() << Q_FUNC_INFO <<
"invalid key axis";
return; }
21438 if (
mData->isEmpty())
21440 lower =
mData->constEnd();
21441 upper =
mData->constEnd();
21446 QCPFinancialDataMap::const_iterator lbound =
mData->lowerBound(
mKeyAxis.data()->range().lower);
21447 QCPFinancialDataMap::const_iterator ubound =
mData->upperBound(
mKeyAxis.data()->range().upper);
21448 bool lowoutlier = lbound !=
mData->constBegin();
21449 bool highoutlier = ubound !=
mData->constEnd();
21451 lower = (lowoutlier ? lbound-1 : lbound);
21452 upper = (highoutlier ? ubound : ubound-1);
21475 point1(createPosition(QLatin1String(
"point1"))),
21476 point2(createPosition(QLatin1String(
"point2")))
21481 setPen(QPen(Qt::black));
21525 double clipPad =
mainPen().widthF();
21528 if (!line.isNull())
21544 return qAbs((base.y()-point.y())*vec.x()-(base.x()-point.x())*vec.y())/vec.length();
21559 if (vec.x() == 0 && vec.y() == 0)
21561 if (qFuzzyIsNull(vec.x()))
21566 gamma = base.x()-bx + (by-base.y())*vec.x()/vec.y();
21567 if (gamma >= 0 && gamma <= rect.width())
21568 result.setLine(bx+gamma, rect.top(), bx+gamma, rect.bottom());
21569 }
else if (qFuzzyIsNull(vec.y()))
21574 gamma = base.y()-by + (bx-base.x())*vec.y()/vec.x();
21575 if (gamma >= 0 && gamma <= rect.height())
21576 result.setLine(rect.left(), by+gamma, rect.right(), by+gamma);
21579 QList<QVector2D> pointVectors;
21583 gamma = base.x()-bx + (by-base.y())*vec.x()/vec.y();
21584 if (gamma >= 0 && gamma <= rect.width())
21585 pointVectors.append(QVector2D(bx+gamma, by));
21588 by = rect.bottom();
21589 gamma = base.x()-bx + (by-base.y())*vec.x()/vec.y();
21590 if (gamma >= 0 && gamma <= rect.width())
21591 pointVectors.append(QVector2D(bx+gamma, by));
21595 gamma = base.y()-by + (bx-base.x())*vec.y()/vec.x();
21596 if (gamma >= 0 && gamma <= rect.height())
21597 pointVectors.append(QVector2D(bx, by+gamma));
21601 gamma = base.y()-by + (bx-base.x())*vec.y()/vec.x();
21602 if (gamma >= 0 && gamma <= rect.height())
21603 pointVectors.append(QVector2D(bx, by+gamma));
21606 if (pointVectors.size() == 2)
21608 result.setPoints(pointVectors.at(0).toPointF(), pointVectors.at(1).toPointF());
21609 }
else if (pointVectors.size() > 2)
21612 double distSqrMax = 0;
21613 QVector2D pv1, pv2;
21614 for (
int i=0; i<pointVectors.size()-1; ++i)
21616 for (
int k=i+1; k<pointVectors.size(); ++k)
21618 double distSqr = (pointVectors.at(i)-pointVectors.at(k)).lengthSquared();
21619 if (distSqr > distSqrMax)
21621 pv1 = pointVectors.at(i);
21622 pv2 = pointVectors.at(k);
21623 distSqrMax = distSqr;
21627 result.setPoints(pv1.toPointF(), pv2.toPointF());
21665 start(createPosition(QLatin1String(
"start"))),
21666 end(createPosition(QLatin1String(
"end")))
21671 setPen(QPen(Qt::black));
21740 if (startVec.toPoint() == endVec.toPoint())
21744 clipPad = qMax(clipPad, (
double)
mainPen().widthF());
21747 if (!line.isNull())
21751 painter->setBrush(Qt::SolidPattern);
21753 mTail.
draw(painter, startVec, startVec-endVec);
21755 mHead.
draw(painter, endVec, endVec-startVec);
21768 bool containsStart = rect.contains(start.x(), start.y());
21769 bool containsEnd = rect.contains(end.x(), end.y());
21770 if (containsStart && containsEnd)
21771 return QLineF(start.toPointF(), end.toPointF());
21773 QVector2D base =
start;
21774 QVector2D vec = end-
start;
21778 QList<QVector2D> pointVectors;
21780 if (!qFuzzyIsNull(vec.y()))
21785 mu = (by-base.y())/vec.y();
21786 if (mu >= 0 && mu <= 1)
21788 gamma = base.x()-bx + mu*vec.x();
21789 if (gamma >= 0 && gamma <= rect.width())
21790 pointVectors.append(QVector2D(bx+gamma, by));
21794 by = rect.bottom();
21795 mu = (by-base.y())/vec.y();
21796 if (mu >= 0 && mu <= 1)
21798 gamma = base.x()-bx + mu*vec.x();
21799 if (gamma >= 0 && gamma <= rect.width())
21800 pointVectors.append(QVector2D(bx+gamma, by));
21803 if (!qFuzzyIsNull(vec.x()))
21808 mu = (bx-base.x())/vec.x();
21809 if (mu >= 0 && mu <= 1)
21811 gamma = base.y()-by + mu*vec.y();
21812 if (gamma >= 0 && gamma <= rect.height())
21813 pointVectors.append(QVector2D(bx, by+gamma));
21818 mu = (bx-base.x())/vec.x();
21819 if (mu >= 0 && mu <= 1)
21821 gamma = base.y()-by + mu*vec.y();
21822 if (gamma >= 0 && gamma <= rect.height())
21823 pointVectors.append(QVector2D(bx, by+gamma));
21828 pointVectors.append(start);
21830 pointVectors.append(end);
21833 if (pointVectors.size() == 2)
21835 result.setPoints(pointVectors.at(0).toPointF(), pointVectors.at(1).toPointF());
21836 }
else if (pointVectors.size() > 2)
21839 double distSqrMax = 0;
21840 QVector2D pv1, pv2;
21841 for (
int i=0; i<pointVectors.size()-1; ++i)
21843 for (
int k=i+1; k<pointVectors.size(); ++k)
21845 double distSqr = (pointVectors.at(i)-pointVectors.at(k)).lengthSquared();
21846 if (distSqr > distSqrMax)
21848 pv1 = pointVectors.at(i);
21849 pv2 = pointVectors.at(k);
21850 distSqrMax = distSqr;
21854 result.setPoints(pv1.toPointF(), pv2.toPointF());
21898 start(createPosition(QLatin1String(
"start"))),
21899 startDir(createPosition(QLatin1String(
"startDir"))),
21900 endDir(createPosition(QLatin1String(
"endDir"))),
21901 end(createPosition(QLatin1String(
"end")))
21908 setPen(QPen(Qt::black));
21974 QPainterPath cubicPath(startVec);
21975 cubicPath.cubicTo(startDirVec, endDirVec, endVec);
21977 QPolygonF polygon = cubicPath.toSubpathPolygons().first();
21978 double minDistSqr = std::numeric_limits<double>::max();
21979 for (
int i=1; i<polygon.size(); ++i)
21981 double distSqr =
distSqrToLine(polygon.at(i-1), polygon.at(i), pos);
21982 if (distSqr < minDistSqr)
21983 minDistSqr = distSqr;
21985 return qSqrt(minDistSqr);
21995 if (QVector2D(endVec-startVec).length() > 1e10f)
21998 QPainterPath cubicPath(startVec);
21999 cubicPath.cubicTo(startDirVec, endDirVec, endVec);
22003 QRect cubicRect = cubicPath.controlPointRect().toRect();
22004 if (cubicRect.isEmpty())
22005 cubicRect.adjust(0, 0, 1, 1);
22006 if (clip.intersects(cubicRect))
22009 painter->drawPath(cubicPath);
22010 painter->setBrush(Qt::SolidPattern);
22012 mTail.
draw(painter, QVector2D(startVec), M_PI-cubicPath.angleAtPercent(0)/180.0*M_PI);
22014 mHead.
draw(painter, QVector2D(endVec), -cubicPath.angleAtPercent(1)/180.0*M_PI);
22048 topLeft(createPosition(QLatin1String(
"topLeft"))),
22049 bottomRight(createPosition(QLatin1String(
"bottomRight"))),
22050 top(createAnchor(QLatin1String(
"top"), aiTop)),
22051 topRight(createAnchor(QLatin1String(
"topRight"), aiTopRight)),
22052 right(createAnchor(QLatin1String(
"right"), aiRight)),
22053 bottom(createAnchor(QLatin1String(
"bottom"), aiBottom)),
22054 bottomLeft(createAnchor(QLatin1String(
"bottomLeft"), aiBottomLeft)),
22055 left(createAnchor(QLatin1String(
"left"), aiLeft))
22060 setPen(QPen(Qt::black));
22120 bool filledRect =
mBrush.style() != Qt::NoBrush &&
mBrush.color().alpha() != 0;
22129 if (p1.toPoint() == p2.toPoint())
22131 QRectF rect = QRectF(p1, p2).normalized();
22132 double clipPad =
mainPen().widthF();
22133 QRectF boundingRect = rect.adjusted(-clipPad, -clipPad, clipPad, clipPad);
22134 if (boundingRect.intersects(
clipRect()))
22138 painter->drawRect(rect);
22148 case aiTop:
return (rect.topLeft()+rect.topRight())*0.5;
22150 case aiRight:
return (rect.topRight()+rect.bottomRight())*0.5;
22151 case aiBottom:
return (rect.bottomLeft()+rect.bottomRight())*0.5;
22153 case aiLeft:
return (rect.topLeft()+rect.bottomLeft())*0.5;
22156 qDebug() << Q_FUNC_INFO <<
"invalid anchorId" << anchorId;
22206 position(createPosition(QLatin1String(
"position"))),
22207 topLeft(createAnchor(QLatin1String(
"topLeft"), aiTopLeft)),
22208 top(createAnchor(QLatin1String(
"top"), aiTop)),
22209 topRight(createAnchor(QLatin1String(
"topRight"), aiTopRight)),
22210 right(createAnchor(QLatin1String(
"right"), aiRight)),
22211 bottomRight(createAnchor(QLatin1String(
"bottomRight"), aiBottomRight)),
22212 bottom(createAnchor(QLatin1String(
"bottom"), aiBottom)),
22213 bottomLeft(createAnchor(QLatin1String(
"bottomLeft"), aiBottomLeft)),
22214 left(createAnchor(QLatin1String(
"left"), aiLeft))
22221 setText(QLatin1String(
"text"));
22379 QTransform inputTransform;
22380 inputTransform.translate(positionPixels.x(), positionPixels.y());
22382 inputTransform.translate(-positionPixels.x(), -positionPixels.y());
22383 QPointF rotatedPos = inputTransform.map(pos);
22384 QFontMetrics fontMetrics(
mFont);
22385 QRect textRect = fontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip|
mTextAlignment,
mText);
22388 textBoxRect.moveTopLeft(textPos.toPoint());
22397 QTransform transform = painter->transform();
22398 transform.translate(pos.x(), pos.y());
22402 QRect textRect = painter->fontMetrics().boundingRect(0, 0, 0, 0, Qt::TextDontClip|
mTextAlignment,
mText);
22405 textRect.moveTopLeft(textPos.toPoint()+QPoint(
mPadding.left(),
mPadding.top()));
22406 textBoxRect.moveTopLeft(textPos.toPoint());
22407 double clipPad =
mainPen().widthF();
22408 QRect boundingRect = textBoxRect.adjusted(-clipPad, -clipPad, clipPad, clipPad);
22409 if (transform.mapRect(boundingRect).intersects(painter->transform().mapRect(
clipRect())))
22411 painter->setTransform(transform);
22417 painter->drawRect(textBoxRect);
22419 painter->setBrush(Qt::NoBrush);
22430 QTransform transform;
22431 transform.translate(pos.x(), pos.y());
22434 QFontMetrics fontMetrics(
mainFont());
22435 QRect textRect = fontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip|
mTextAlignment,
mText);
22438 textBoxRect.moveTopLeft(textPos.toPoint());
22439 QPolygonF rectPoly = transform.map(QPolygonF(textBoxRect));
22444 case aiTop:
return (rectPoly.at(0)+rectPoly.at(1))*0.5;
22446 case aiRight:
return (rectPoly.at(1)+rectPoly.at(2))*0.5;
22448 case aiBottom:
return (rectPoly.at(2)+rectPoly.at(3))*0.5;
22450 case aiLeft:
return (rectPoly.at(3)+rectPoly.at(0))*0.5;
22453 qDebug() << Q_FUNC_INFO <<
"invalid anchorId" << anchorId;
22469 if (positionAlignment == 0 || positionAlignment == (Qt::AlignLeft|Qt::AlignTop))
22472 QPointF result = pos;
22473 if (positionAlignment.testFlag(Qt::AlignHCenter))
22474 result.rx() -= rect.width()/2.0;
22475 else if (positionAlignment.testFlag(Qt::AlignRight))
22476 result.rx() -= rect.width();
22477 if (positionAlignment.testFlag(Qt::AlignVCenter))
22478 result.ry() -= rect.height()/2.0;
22479 else if (positionAlignment.testFlag(Qt::AlignBottom))
22480 result.ry() -= rect.height();
22544 topLeft(createPosition(QLatin1String(
"topLeft"))),
22545 bottomRight(createPosition(QLatin1String(
"bottomRight"))),
22546 topLeftRim(createAnchor(QLatin1String(
"topLeftRim"), aiTopLeftRim)),
22547 top(createAnchor(QLatin1String(
"top"), aiTop)),
22548 topRightRim(createAnchor(QLatin1String(
"topRightRim"), aiTopRightRim)),
22549 right(createAnchor(QLatin1String(
"right"), aiRight)),
22550 bottomRightRim(createAnchor(QLatin1String(
"bottomRightRim"), aiBottomRightRim)),
22551 bottom(createAnchor(QLatin1String(
"bottom"), aiBottom)),
22552 bottomLeftRim(createAnchor(QLatin1String(
"bottomLeftRim"), aiBottomLeftRim)),
22553 left(createAnchor(QLatin1String(
"left"), aiLeft)),
22554 center(createAnchor(QLatin1String(
"center"), aiCenter))
22559 setPen(QPen(Qt::black));
22618 double result = -1;
22621 QPointF
center((p1+p2)/2.0);
22622 double a = qAbs(p1.x()-p2.x())/2.0;
22623 double b = qAbs(p1.y()-p2.y())/2.0;
22624 double x = pos.x()-center.x();
22625 double y = pos.y()-center.y();
22628 double c = 1.0/qSqrt(x*x/(a*a)+y*y/(b*b));
22629 result = qAbs(c-1)*qSqrt(x*x+y*y);
22633 if (x*x/(a*a) + y*y/(b*b) <= 1)
22644 if (p1.toPoint() == p2.toPoint())
22646 QRectF ellipseRect = QRectF(p1, p2).normalized();
22648 if (ellipseRect.intersects(clip))
22652 #ifdef __EXCEPTIONS
22656 painter->drawEllipse(ellipseRect);
22657 #ifdef __EXCEPTIONS
22660 qDebug() << Q_FUNC_INFO <<
"Item too large for memory, setting invisible";
22673 case aiTopLeftRim:
return rect.center()+(rect.topLeft()-rect.center())*1/qSqrt(2);
22674 case aiTop:
return (rect.topLeft()+rect.topRight())*0.5;
22675 case aiTopRightRim:
return rect.center()+(rect.topRight()-rect.center())*1/qSqrt(2);
22676 case aiRight:
return (rect.topRight()+rect.bottomRight())*0.5;
22677 case aiBottomRightRim:
return rect.center()+(rect.bottomRight()-rect.center())*1/qSqrt(2);
22678 case aiBottom:
return (rect.bottomLeft()+rect.bottomRight())*0.5;
22679 case aiBottomLeftRim:
return rect.center()+(rect.bottomLeft()-rect.center())*1/qSqrt(2);
22680 case aiLeft:
return (rect.topLeft()+rect.bottomLeft())*0.5;
22681 case aiCenter:
return (rect.topLeft()+rect.bottomRight())*0.5;
22684 qDebug() << Q_FUNC_INFO <<
"invalid anchorId" << anchorId;
22734 topLeft(createPosition(QLatin1String(
"topLeft"))),
22735 bottomRight(createPosition(QLatin1String(
"bottomRight"))),
22736 top(createAnchor(QLatin1String(
"top"), aiTop)),
22737 topRight(createAnchor(QLatin1String(
"topRight"), aiTopRight)),
22738 right(createAnchor(QLatin1String(
"right"), aiRight)),
22739 bottom(createAnchor(QLatin1String(
"bottom"), aiBottom)),
22740 bottomLeft(createAnchor(QLatin1String(
"bottomLeft"), aiBottomLeft)),
22741 left(createAnchor(QLatin1String(
"left"), aiLeft)),
22742 mScaledPixmapInvalidated(true)
22749 setScaled(
false, Qt::KeepAspectRatio, Qt::SmoothTransformation);
22764 qDebug() << Q_FUNC_INFO <<
"pixmap is null";
22812 bool flipHorz =
false;
22813 bool flipVert =
false;
22815 double clipPad =
mainPen().style() == Qt::NoPen ? 0 :
mainPen().widthF();
22816 QRect boundingRect = rect.adjusted(-clipPad, -clipPad, clipPad, clipPad);
22817 if (boundingRect.intersects(
clipRect()))
22822 if (pen.style() != Qt::NoPen)
22825 painter->setBrush(Qt::NoBrush);
22826 painter->drawRect(rect);
22840 rect.adjust(rect.width(), 0, -rect.width(), 0);
22842 rect.adjust(0, rect.height(), 0, -rect.height());
22846 case aiTop:
return (rect.topLeft()+rect.topRight())*0.5;
22848 case aiRight:
return (rect.topRight()+rect.bottomRight())*0.5;
22849 case aiBottom:
return (rect.bottomLeft()+rect.bottomRight())*0.5;
22851 case aiLeft:
return (rect.topLeft()+rect.bottomLeft())*0.5;;
22854 qDebug() << Q_FUNC_INFO <<
"invalid anchorId" << anchorId;
22878 if (finalRect.isNull())
22883 if (flipHorz || flipVert)
22908 bool flipHorz =
false;
22909 bool flipVert =
false;
22913 return QRect(p1, QSize(0, 0));
22916 QSize newSize = QSize(p2.x()-p1.x(), p2.y()-p1.y());
22918 if (newSize.width() < 0)
22921 newSize.rwidth() *= -1;
22922 topLeft.setX(p2.x());
22924 if (newSize.height() < 0)
22927 newSize.rheight() *= -1;
22928 topLeft.setY(p2.y());
22930 QSize scaledSize =
mPixmap.size();
22932 result = QRect(topLeft, scaledSize);
22935 result = QRect(p1,
mPixmap.size());
22938 *flippedHorz = flipHorz;
22940 *flippedVert = flipVert;
22996 position(createPosition(QLatin1String(
"position"))),
23003 setPen(QPen(Qt::black));
23096 qDebug() << Q_FUNC_INFO <<
"graph isn't in same QCustomPlot instance as this item";
23141 double w =
mSize/2.0;
23148 if (
clipRect().intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
23149 return qSqrt(qMin(
distSqrToLine(center+QPointF(-w, 0), center+QPointF(w, 0), pos),
23150 distSqrToLine(center+QPointF(0, -w), center+QPointF(0, w), pos)));
23155 return qSqrt(qMin(
distSqrToLine(QPointF(clip.left(), center.y()), QPointF(clip.right(), center.y()), pos),
23156 distSqrToLine(QPointF(center.x(), clip.top()), QPointF(center.x(), clip.bottom()), pos)));
23160 if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
23163 double centerDist = QVector2D(center-pos).length();
23164 double circleLine = w;
23165 double result = qAbs(centerDist-circleLine);
23169 if (centerDist <= circleLine)
23178 if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
23180 QRectF rect = QRectF(center-QPointF(w, w), center+QPointF(w, w));
23181 bool filledRect =
mBrush.style() != Qt::NoBrush &&
mBrush.color().alpha() != 0;
23200 double w =
mSize/2.0;
23207 if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
23209 painter->
drawLine(QLineF(center+QPointF(-w, 0), center+QPointF(w, 0)));
23210 painter->
drawLine(QLineF(center+QPointF(0, -w), center+QPointF(0, w)));
23216 if (center.y() > clip.top() && center.y() < clip.bottom())
23217 painter->
drawLine(QLineF(clip.left(), center.y(), clip.right(), center.y()));
23218 if (center.x() > clip.left() && center.x() < clip.right())
23219 painter->
drawLine(QLineF(center.x(), clip.top(), center.x(), clip.bottom()));
23224 if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
23225 painter->drawEllipse(center, w, w);
23230 if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect()))
23231 painter->drawRect(QRectF(center-QPointF(w, w), center+QPointF(w, w)));
23257 QCPDataMap::const_iterator first =
mGraph->
data()->constBegin();
23258 QCPDataMap::const_iterator last =
mGraph->
data()->constEnd()-1;
23268 QCPDataMap::const_iterator prevIt = it-1;
23273 if (!qFuzzyCompare((
double)it.key(), (double)prevIt.key()))
23274 slope = (it.value().value-prevIt.value().value)/(it.key()-prevIt.key());
23279 if (
mGraphKey < (prevIt.key()+it.key())*0.5)
23288 QCPDataMap::const_iterator it =
mGraph->
data()->constBegin();
23291 qDebug() << Q_FUNC_INFO <<
"graph has no data";
23293 qDebug() << Q_FUNC_INFO <<
"graph not contained in QCustomPlot instance (anymore)";
23349 left(createPosition(QLatin1String(
"left"))),
23350 right(createPosition(QLatin1String(
"right"))),
23351 center(createAnchor(QLatin1String(
"center"), aiCenter))
23356 setPen(QPen(Qt::black));
23422 if (leftVec.toPoint() == rightVec.toPoint())
23425 QVector2D widthVec = (rightVec-leftVec)*0.5f;
23426 QVector2D lengthVec(-widthVec.y(), widthVec.x());
23427 lengthVec = lengthVec.normalized()*
mLength;
23428 QVector2D centerVec = (rightVec+leftVec)*0.5f-lengthVec;
23435 double a =
distSqrToLine((centerVec-widthVec).toPointF(), (centerVec+widthVec).toPointF(), pos);
23436 double b =
distSqrToLine((centerVec-widthVec+lengthVec).toPointF(), (centerVec-widthVec).toPointF(), pos);
23437 double c =
distSqrToLine((centerVec+widthVec+lengthVec).toPointF(), (centerVec+widthVec).toPointF(), pos);
23438 return qSqrt(qMin(qMin(a, b), c));
23443 double a =
distSqrToLine((centerVec-widthVec*0.75f+lengthVec*0.15f).toPointF(), (centerVec+lengthVec*0.3f).toPointF(), pos);
23444 double b =
distSqrToLine((centerVec-widthVec+lengthVec*0.7f).toPointF(), (centerVec-widthVec*0.75f+lengthVec*0.15f).toPointF(), pos);
23445 double c =
distSqrToLine((centerVec+widthVec*0.75f+lengthVec*0.15f).toPointF(), (centerVec+lengthVec*0.3f).toPointF(), pos);
23446 double d =
distSqrToLine((centerVec+widthVec+lengthVec*0.7f).toPointF(), (centerVec+widthVec*0.75f+lengthVec*0.15f).toPointF(), pos);
23447 return qSqrt(qMin(qMin(a, b), qMin(c, d)));
23458 if (leftVec.toPoint() == rightVec.toPoint())
23461 QVector2D widthVec = (rightVec-leftVec)*0.5f;
23462 QVector2D lengthVec(-widthVec.y(), widthVec.x());
23463 lengthVec = lengthVec.normalized()*
mLength;
23464 QVector2D centerVec = (rightVec+leftVec)*0.5f-lengthVec;
23466 QPolygon boundingPoly;
23467 boundingPoly << leftVec.toPoint() << rightVec.toPoint()
23468 << (rightVec-lengthVec).toPoint() << (leftVec-lengthVec).toPoint();
23470 if (clip.intersects(boundingPoly.boundingRect()))
23477 painter->
drawLine((centerVec+widthVec).toPointF(), (centerVec-widthVec).toPointF());
23478 painter->
drawLine((centerVec+widthVec).toPointF(), (centerVec+widthVec+lengthVec).toPointF());
23479 painter->
drawLine((centerVec-widthVec).toPointF(), (centerVec-widthVec+lengthVec).toPointF());
23484 painter->setBrush(Qt::NoBrush);
23486 path.moveTo((centerVec+widthVec+lengthVec).toPointF());
23487 path.cubicTo((centerVec+widthVec).toPointF(), (centerVec+widthVec).toPointF(), centerVec.toPointF());
23488 path.cubicTo((centerVec-widthVec).toPointF(), (centerVec-widthVec).toPointF(), (centerVec-widthVec+lengthVec).toPointF());
23489 painter->drawPath(path);
23494 painter->setBrush(Qt::NoBrush);
23496 path.moveTo((centerVec+widthVec+lengthVec).toPointF());
23497 path.cubicTo((centerVec+widthVec-lengthVec*0.8f).toPointF(), (centerVec+0.4f*widthVec+lengthVec).toPointF(), centerVec.toPointF());
23498 path.cubicTo((centerVec-0.4f*widthVec+lengthVec).toPointF(), (centerVec-widthVec-lengthVec*0.8f).toPointF(), (centerVec-widthVec+lengthVec).toPointF());
23499 painter->drawPath(path);
23504 painter->
setPen(Qt::NoPen);
23505 painter->setBrush(QBrush(
mainPen().color()));
23507 path.moveTo((centerVec+widthVec+lengthVec).toPointF());
23509 path.cubicTo((centerVec+widthVec-lengthVec*0.8f).toPointF(), (centerVec+0.4f*widthVec+0.8f*lengthVec).toPointF(), centerVec.toPointF());
23510 path.cubicTo((centerVec-0.4f*widthVec+0.8f*lengthVec).toPointF(), (centerVec-widthVec-lengthVec*0.8f).toPointF(), (centerVec-widthVec+lengthVec).toPointF());
23512 path.cubicTo((centerVec-widthVec-lengthVec*0.5f).toPointF(), (centerVec-0.2f*widthVec+1.2f*lengthVec).toPointF(), (centerVec+lengthVec*0.2f).toPointF());
23513 path.cubicTo((centerVec+0.2f*widthVec+1.2f*lengthVec).toPointF(), (centerVec+widthVec-lengthVec*0.5f).toPointF(), (centerVec+widthVec+lengthVec).toPointF());
23515 painter->drawPath(path);
23527 if (leftVec.toPoint() == rightVec.toPoint())
23528 return leftVec.toPointF();
23530 QVector2D widthVec = (rightVec-leftVec)*0.5f;
23531 QVector2D lengthVec(-widthVec.y(), widthVec.x());
23532 lengthVec = lengthVec.normalized()*
mLength;
23533 QVector2D centerVec = (rightVec+leftVec)*0.5f-lengthVec;
23538 return centerVec.toPointF();
23540 qDebug() << Q_FUNC_INFO <<
"invalid anchorId" << anchorId;
static const double maxRange
QPointer< QCPAxisRect > mClipAxisRect
QPointer< QCPAxis > mKeyAxis
bool rangeReversed() const
virtual QCPRange getKeyRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const
void pixelsToCoords(double x, double y, double &key, double &value) const
A layout element displaying a plot title text.
int tickLabelPadding() const
virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const
A curly brace with varying stroke width giving a calligraphic impression.
double distSqrToLine(const QPointF &start, const QPointF &end, const QPointF &point) const
QList< QCPLayer * > mLayers
void legendClick(QCPLegend *legend, QCPAbstractLegendItem *item, QMouseEvent *event)
QPen getIconBorderPen() const
void setTickVector(const QVector< double > &vec)
Tick labels will be displayed inside the axis rect and clipped to the inner axis rect.
void setHead(const QCPLineEnding &head)
QCPItemPosition *const topLeft
double getPixelSpacing(const QCPBars *bars, double keyCoord)
bool mGradientImageInvalidated
void titleDoubleClick(QMouseEvent *event, QCPPlotTitle *title)
virtual QCP::Interaction selectionCategory() const
void setTwoColored(bool twoColored)
Q_SLOT void setDataScaleType(QCPAxis::ScaleType scaleType)
virtual bool take(QCPLayoutElement *element)=0
void getStepCenterPlotData(QVector< QPointF > *linePixelData, QVector< QCPData > *scatterData) const
QCP::MarginSides mAutoMargins
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const
void removeData(double fromKey, double toKey)
A brace with angled edges.
QList< QCPItemPosition * > mPositions
bool setParentAnchorX(QCPItemAnchor *parentAnchor, bool keepPixelPosition=false)
void setCoords(double key, double value)
Manages the position of an item.
Tick coordinate is regarded as a date/time (seconds since 1970-01-01T00:00:00 UTC) and will be displa...
Static positioning in pixels, starting from the top left corner of the viewport/widget.
int findIndexBelowY(const QVector< QPointF > *data, double y) const
void insertColumn(int newIndex)
void selectableChanged(QCPLegend::SelectableParts parts)
{ssCrossCircle.png} a circle with a cross inside
QColor getTickLabelColor() const
QPainterPath customPath() const
QFont getTickLabelFont() const
void applyAntialiasingHint(QCPPainter *painter, bool localAntialiased, QCP::AntialiasedElement overrideElement) const
QCPItemPosition *const topLeft
virtual QSize maximumSizeHint() const
void setRangeReversed(bool reversed)
void removeData(double fromKey, double toKey)
QPointF lowerFillBasePoint(double lowerKey) const
bool antialiasing() const
QCPAxis::AxisType type() const
virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
SelectablePart getPartAt(const QPointF &pos) const
QCPBarDataMap * data() const
void setSelectedPen(const QPen &pen)
{ssDiamond.png} a diamond
virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
QCustomPlot * parentPlot() const
void setData(QCPColorMapData *data, bool copy=false)
QPixmap mBackgroundPixmap
QMap< double, QCPData > QCPDataMap
0x004 axis (tick) labels will be cached as pixmaps, increasing replot performance.
virtual void draw(QCPPainter *painter)
QList< QCPAbstractItem * > items() const
QList< QCPGraph * > mGraphs
virtual void generateAutoTicks()
QCPColorScale(QCustomPlot *parentPlot)
void setDataKeyError(const QVector< double > &key, const QVector< double > &value, const QVector< double > &keyError)
Q_SLOT void setDataRange(const QCPRange &dataRange)
QCPColorGradient mGradient
QCPAbstractLegendItem * item(int index) const
void dataScaleTypeChanged(QCPAxis::ScaleType scaleType)
AxisType axisType() const
WidthType widthType() const
void setOutlierStyle(const QCPScatterStyle &style)
void setTickLengthIn(int inside)
QLineF getRectClippedLine(const QVector2D &start, const QVector2D &end, const QRect &rect) const
bool begin(QPaintDevice *device)
A filled diamond (45° rotated square)
virtual void mousePressEvent(QMouseEvent *event)
QCPItemAnchor(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString name, int anchorId=-1)
void setMaximumSize(const QSize &size)
void setColumnStretchFactor(int column, double factor)
0x01 Axis is vertical and on the left side of the axis rect
bool addItem(QCPAbstractItem *item)
QCPColorScale * colorScale() const
void setBrushNegative(const QBrush &brush)
The abstract base class for layouts.
QCPFinancialDataMap * data() const
virtual void legendRemoved(QCPLegend *legend)
void setFont(const QFont &font)
void getMinimumRowColSizes(QVector< int > *minColWidths, QVector< int > *minRowHeights) const
void setRangeLower(double lower)
The negative sign domain, i.e. numbers smaller than zero.
Q_SLOT void setSelected(bool selected)
double pointDistance(const QPointF &pixelPoint) const
bool noAntialiasingOnDrag() const
void setPen(const QPen &pen)
QList< QCPLayoutElement * > mElements
virtual int elementCount() const
void setSelectedFont(const QFont &font)
Both sign domains, including zero, i.e. all (rational) numbers.
virtual void drawWhiskers(QCPPainter *painter) const
QCPItemPosition * position(const QString &name) const
Qt::KeyboardModifier mMultiSelectModifier
Bar spacing is in key coordinates and thus scales with the key axis range.
QCPAxis * valueAxis() const
bool setParentAnchor(QCPItemAnchor *parentAnchor, bool keepPixelPosition=false)
virtual void deselectEvent(bool *selectionStateChanged)
virtual void draw(QCPPainter *painter)
void setRangeZoom(bool enabled)
virtual QPointF anchorPixelPoint(int anchorId) const
QCPBarsGroup * barsGroup() const
void addData(const QCPBarDataMap &dataMap)
void setSelectedFont(const QFont &font)
void setValueRange(const QCPRange &valueRange)
void setBrush(const QBrush &brush)
QHash< QCPAxis::AxisType, QList< QCPAxis * > > mAxes
void setInsetPlacement(int index, InsetPlacement placement)
QCPPlottableLegendItem * itemWithPlottable(const QCPAbstractPlottable *plottable) const
void setSubGridVisible(bool visible)
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const
void setColorScale(QCPColorScale *colorScale)
{ssPeace.png} a circle, with one vertical and two downward diagonal lines
void setLabel(const QString &str)
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const
void setSelectedLabelFont(const QFont &font)
void setTickLabelSide(LabelSide side)
void addChildX(QCPItemPosition *pos)
void removeData(double fromKey, double toKey)
void setWhiskerPen(const QPen &pen)
void removeChild(QCP::MarginSide side, QCPLayoutElement *element)
QCPItemAnchor * mParentAnchorY
Represents the range an axis is encompassing.
QCPAxis::ScaleType mDataScaleType
void setPadding(const QMargins &padding)
static QCPFinancialDataMap timeSeriesToOhlc(const QVector< double > &time, const QVector< double > &value, double timeBinSize, double timeBinOffset=0)
QCPItemText(QCustomPlot *parentPlot)
QCPRange sanitizedForLogScale() const
void selectionChanged(bool selected)
QList< QCPAbstractPlottable * > selectedPlottables() const
void setDateTimeFormat(const QString &format)
void setSelectionTolerance(int pixels)
Q_SLOT void setSelectedParts(const QCPAxis::SelectableParts &selectedParts)
QCPAxisPainterPrivate * mAxisPainter
virtual QSize maximumSizeHint() const
virtual void draw(QCPPainter *painter)
void mouseWheel(QWheelEvent *event)
PositionType type() const
QCPScatterStyle mOutlierStyle
Half hue spectrum from black over purple to blue and finally green (creates banding illusion but allo...
QCPLayoutElement * layoutElementAt(const QPointF &pos) const
virtual void updateLayout()
bool removeAxis(QCPAxis *axis)
virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
0x0200 Borders of fills (e.g. under or between graphs)
QCPAxis * keyAxis() const
void drawLine(const QLineF &line)
int findIndexAboveX(const QVector< QPointF > *data, double x) const
0x004 The user can select multiple objects by holding the modifier set by QCustomPlot::setMultiSelect...
void setLabelFont(const QFont &font)
virtual ~QCPItemStraightLine()
virtual void mousePressEvent(QMouseEvent *event)
void itemClick(QCPAbstractItem *item, QMouseEvent *event)
void setAntialiasedElements(const QCP::AntialiasedElements &antialiasedElements)
virtual QSize minimumSizeHint() const
QCPItemPosition *const position
Qt::AspectRatioMode aspectRatioMode() const
void setBackgroundScaled(bool scaled)
void setSelectedPen(const QPen &pen)
void selectableChanged(bool selectable)
Tick coordinate is regarded as normal number and will be displayed as such. (see setNumberFormat) ...
void setBackgroundScaledMode(Qt::AspectRatioMode mode)
QList< QCPAbstractLegendItem * > selectedItems() const
QCPAxis(QCPAxisRect *parent, AxisType type)
void insert(int i, QCPBars *bars)
QCP::Interactions mInteractions
void setPenPositive(const QPen &pen)
Q_SLOT void setGradient(const QCPColorGradient &gradient)
void getVisibleDataBounds(QCPFinancialDataMap::const_iterator &lower, QCPFinancialDataMap::const_iterator &upper) const
virtual void update(UpdatePhase phase)
QCPItemPosition *const topLeft
QCPAxisRect * axisRect(int index=0) const
void setNotAntialiasedElement(QCP::AntialiasedElement notAntialiasedElement, bool enabled=true)
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const
Qt::AspectRatioMode mAspectRatioMode
void setAntialiasedScatters(bool enabled)
void mouseRelease(QMouseEvent *event)
bool remove(QCPLayoutElement *element)
virtual QCPRange getKeyRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const
void setCell(int keyIndex, int valueIndex, double z)
bool mColorBufferInvalidated
bool saveJpg(const QString &fileName, int width=0, int height=0, double scale=1.0, int quality=-1)
void setTightBoundary(bool enabled)
void getPreparedData(QVector< QCPData > *lineData, QVector< QCPData > *scatterData) const
virtual void drawLinePlot(QCPPainter *painter, QVector< QPointF > *lineData) const
QPen getSubTickPen() const
void setTickLengthOut(int outside)
Qt::Orientation orientation() const
void sizeConstraintsChanged() const
QCPBars * barBelow() const
QLatin1Char mNumberFormatChar
{ssPlusCircle.png} a circle with a plus inside
virtual void drawImpulsePlot(QCPPainter *painter, QVector< QPointF > *lineData) const
void setColorStopAt(double position, const QColor &color)
virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const
QPointer< QCPColorScaleAxisRectPrivate > mAxisRect
0x008 Plottables are selectable (e.g. graphs, curves, bars,... see QCPAbstractPlottable) ...
QCPItemAnchor * createAnchor(const QString &name, int anchorId)
QCPRange dataBounds() const
Holds the data of one single data point for QCPCurve.
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const
Q_SLOT void deselectAll()
void setSelectedBasePen(const QPen &pen)
void setBrushPositive(const QBrush &brush)
QCPItemBracket(QCustomPlot *parentPlot)
QCPLineEnding tail() const
virtual int calculateAutoSubTickCount(double tickStep) const
virtual QCP::Interaction selectionCategory() const
void removeChildY(QCPItemPosition *pos)
{ssDot.png} a single pixel (use ssDisc or ssCircle if you want a round shape with a certain radius) ...
virtual QSize sizeHint() const
QCPLayoutElement(QCustomPlot *parentPlot=0)
bool mAntialiasedScatters
void releaseElement(QCPLayoutElement *el)
QList< QCPAbstractPlottable * > plottables() const
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const =0
void setBaseValue(double baseValue)
virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const
The element is aligned to one of the layout sides, see setInsetAlignment.
QCPStatisticalBox(QCPAxis *keyAxis, QCPAxis *valueAxis)
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const
{ssTriangleInverted.png} an equilateral triangle, standing on corner
virtual ~QCPItemBracket()
QCustomPlot * mParentPlot
void setAxes(QCPAxis *keyAxis, QCPAxis *valueAxis)
QCPItemStraightLine(QCustomPlot *parentPlot)
virtual void draw(QCPPainter *painter)
Q_SLOT void setScaleType(QCPAxis::ScaleType type)
QHash< QCP::MarginSide, QList< QCPLayoutElement * > > mChildren
QCPItemEllipse(QCustomPlot *parentPlot)
QCache< QString, CachedLabel > mLabelCache
QCPAbstractItem * itemAt(const QPointF &pos, bool onlySelectable=false) const
void dataScaleTypeChanged(QCPAxis::ScaleType scaleType)
void setLabel(const QString &str)
QCPGrid(QCPAxis *parentAxis)
void setVisible(bool visible)
void setAntialiasedErrorBars(bool enabled)
bool getTraverse(double prevKey, double prevValue, double key, double value, double rectLeft, double rectTop, double rectRight, double rectBottom, QPointF &crossA, QPointF &crossB) const
0x0001 Axis base line and tick marks
virtual void update(UpdatePhase phase)
SelectableParts selectedParts() const
QCPScatterStyle mScatterStyle
Represents the visual appearance of scatter points.
void setLength(double length)
void setAntialiasing(bool enabled)
each data point is represented by a line parallel to the value axis, which reaches from the data poin...
QCPAxisRect * clipAxisRect() const
virtual void draw(QCPPainter *painter)=0
void setSelectedTickLabelFont(const QFont &font)
virtual QCPLayoutElement * elementAt(int index) const
Q_SLOT void setGradient(const QCPColorGradient &gradient)
void setupFullAxesBox(bool connectRanges=false)
virtual void draw(QCPPainter *painter)
void setPen(const QPen &pen)
double distToStraightLine(const QVector2D &point1, const QVector2D &vec, const QVector2D &point) const
Candlestick representation.
int getRegion(double x, double y, double rectLeft, double rectTop, double rectRight, double rectBottom) const
bool removeLayer(QCPLayer *layer)
bool removePlottable(QCPAbstractPlottable *plottable)
void setLabelColor(const QColor &color)
void setRowSpacing(int pixels)
void selectableChanged(bool selectable)
double mRangeZoomFactorHorz
void setTypeY(PositionType type)
SelectableParts mSelectableParts
void setInverted(bool inverted)
void applyFillAntialiasingHint(QCPPainter *painter) const
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const
QList< QCPAxis * > selectedAxes() const
void getTraverseCornerPoints(int prevRegion, int currentRegion, double rectLeft, double rectTop, double rectRight, double rectBottom, QVector< QPointF > &beforeTraverse, QVector< QPointF > &afterTraverse) const
virtual ~QCPAxisPainterPrivate()
QPixmap toPixmap(int width=0, int height=0, double scale=1.0)
void applyErrorBarsAntialiasingHint(QCPPainter *painter) const
QCPAbstractLegendItem(QCPLegend *parent)
QCPAbstractPlottable * mPlottable
InsetPlacement insetPlacement(int index) const
void selectableChanged(bool selectable)
void setScaled(bool scaled, Qt::AspectRatioMode aspectRatioMode=Qt::KeepAspectRatio, Qt::TransformationMode transformationMode=Qt::SmoothTransformation)
virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const
void setMode(PainterMode mode, bool enabled=true)
virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
double boundingDistance() const
void addChildY(QCPItemPosition *pos)
int findIndexBelowX(const QVector< QPointF > *data, double x) const
QCPItemAnchor *const center
void setTail(const QCPLineEnding &tail)
virtual QRect clipRect() const
QColor mSelectedLabelColor
int selectionTolerance() const
void setRangeZoomFactor(double horizontalFactor, double verticalFactor)
virtual QPointF anchorPixelPoint(int anchorId) const
void setPen(const QPen &pen)
void setSelectedPen(const QPen &pen)
void scaleTypeChanged(QCPAxis::ScaleType scaleType)
bool saveRastered(const QString &fileName, int width, int height, double scale, const char *format, int quality=-1)
void setInterpolating(bool enabled)
QVector< int > getSectionSizes(QVector< int > maxSizes, QVector< int > minSizes, QVector< double > stretchFactors, int totalSize) const
void visibleTickBounds(int &lowIndex, int &highIndex) const
friend class QCPPlottableLegendItem
no scatter symbols are drawn (e.g. in QCPGraph, data only represented with lines) ...
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const
bool clipToAxisRect() const
Q_SLOT void setSelected(bool selected)
virtual void placeTickLabel(QCPPainter *painter, double position, int distanceToAxis, const QString &text, QSize *tickLabelsSize)
QCPItemAnchor * mParentAnchorX
void setUpperQuartile(double value)
{ssStar.png} a star with eight arms, i.e. a combination of cross and plus
void setSelectedTickLabelColor(const QColor &color)
Q_SLOT void updateLegendIcon(Qt::TransformationMode transformMode=Qt::SmoothTransformation, const QSize &thumbSize=QSize(32, 18))
void setData(QCPDataMap *data, bool copy=false)
0x040 Items are selectable (Rectangles, Arrows, Textitems, etc. see QCPAbstractItem) ...
void mousePress(QMouseEvent *event)
QCPAxisRect * axisRect() const
virtual void update(UpdatePhase phase)
QCPAbstractItem * item() const
void setMaximum(double value)
bool hasItem(QCPAbstractLegendItem *item) const
void selectionChangedByUser()
A plus shaped crosshair which spans the complete axis rect.
Bar width is in absolute pixels.
QPointer< QCPColorScale > mColorScale
void setSelectedPen(const QPen &pen)
void setWidth(double width)
QCP::AntialiasedElements mNotAntialiasedElements
void setInterpolate(bool enabled)
void setText(const QString &text)
void setAntialiasedElement(QCP::AntialiasedElement antialiasedElement, bool enabled=true)
Colors suitable to represent different elevations on geographical maps.
QCPItemAnchor * anchor(const QString &name) const
QCP::AntialiasedElements mNotAADragBackup
The positive sign domain, i.e. numbers greater than zero.
void plottableClick(QCPAbstractPlottable *plottable, QMouseEvent *event)
bool mAntialiasedErrorBars
virtual void drawScatterPlot(QCPPainter *painter, const QVector< QPointF > *pointData) const
virtual void draw(QCPPainter *painter)
void setWidthType(WidthType widthType)
Q_SLOT void axisSelectableChanged(QCPAxis::SelectableParts selectableParts)
bool mNoAntialiasingOnDrag
static void connectBars(QCPBars *lower, QCPBars *upper)
void drawCandlestickPlot(QCPPainter *painter, const QCPFinancialDataMap::const_iterator &begin, const QCPFinancialDataMap::const_iterator &end)
virtual void deselectEvent(bool *selectionStateChanged)
QCPItemTracer(QCustomPlot *parentPlot)
QCPAbstractItem(QCustomPlot *parentPlot)
void setIconSize(const QSize &size)
A layer that may contain objects, to control the rendering order.
QCPAxis * rangeDragAxis(Qt::Orientation orientation)
virtual void deselectEvent(bool *selectionStateChanged)
void setFont(const QFont &font)
Q_SLOT void setSelectable(bool selectable)
void selectionChanged(bool selected)
A filled arrow head with an indented back.
QRgb color(double position, const QCPRange &range, bool logarithmic=false)
virtual int calculateAutoMargin(QCP::MarginSide side)
void setRowStretchFactor(int row, double factor)
virtual void mousePressEvent(QMouseEvent *event)
void setScaleLogBase(double base)
void setZeroLinePen(const QPen &pen)
Handles the different ending decorations for line-like items.
void dataRangeChanged(QCPRange newRange)
void setOuterRect(const QRect &rect)
QCPItemPosition(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString name)
bool mScaledPixmapInvalidated
QColor mSelectedTickLabelColor
void setSelectedTextColor(const QColor &color)
void setSelectedTextColor(const QColor &color)
void setAutoTickLabels(bool on)
virtual void setupTickVectors()
Responsible for drawing the grid of a QCPAxis.
void setSubGridPen(const QPen &pen)
bool hasItem(QCPAbstractItem *item) const
void setAdaptiveSampling(bool enabled)
void setSelectedFont(const QFont &font)
void setTextColor(const QColor &color)
ScaleType scaleType() const
Continuous lightness from black over firey colors to white (suited for non-biased data representation...
void setBrush(const QBrush &brush)
void setPen(const QPen &pen)
QCPLayoutInset * insetLayout() const
virtual QCPLayoutElement * takeAt(int index)
void setData(double key, double value, double z)
{ssPlusSquare.png} a square with a plus inside
virtual void wheelEvent(QWheelEvent *event)
QCPAxis::LabelSide tickLabelSide
void setPen(const QPen &pen)
QCPLayoutInset * mInsetLayout
virtual void updateLayout()
void setPixmap(const QPixmap &pixmap)
void setPen(const QPen &pen)
QCPColorMapData(int keySize, int valueSize, const QCPRange &keyRange, const QCPRange &valueRange)
void setValueAxis(QCPAxis *axis)
QCPLegend * mParentLegend
bool operator==(const QCPColorGradient &other) const
void setAutoAddPlottableToLegend(bool on)
void setWhiskerBarPen(const QPen &pen)
Color channels red, green and blue are linearly interpolated.
void layerChanged(QCPLayer *newLayer)
QPointer< QCPLayoutElement > mMouseEventElement
void setLowerEnding(const QCPLineEnding &ending)
void setTextColor(const QColor &color)
void setPen(const QPen &pen)
void applyDefaultAntialiasingHint(QCPPainter *painter) const
void setInteraction(const QCP::Interaction &interaction, bool enabled=true)
double pixelToCoord(double value) const
void setRangeZoomAxes(QCPAxis *horizontal, QCPAxis *vertical)
QCPLayout * mParentLayout
void setBarsGroup(QCPBarsGroup *barsGroup)
A bar perpendicular to the line.
PositionType mPositionTypeY
void drawShape(QCPPainter *painter, QPointF pos) const
virtual void wheelEvent(QWheelEvent *event)
virtual void parentPlotInitialized(QCustomPlot *parentPlot)
virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const
bool setCurrentLayer(const QString &name)
0x0400 Zero-lines, see QCPGrid::setZeroLinePen
virtual int elementCount() const
QList< QCPLayerable * > mChildren
Layer is inserted above other layer.
void selectionChanged(bool selected)
QStack< bool > mAntialiasingStack
virtual void axisRemoved(QCPAxis *axis)
QList< QCPAbstractItem * > mItems
virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
data points are connected by a straight line
LabelSide tickLabelSide() const
QCPRange sanitizedForLinScale() const
Defines a color gradient for use with e.g. QCPColorMap.
QCPColorGradient inverted() const
bool addLayer(const QString &name, QCPLayer *otherLayer=0, LayerInsertMode insertMode=limAbove)
void setMultiSelectModifier(Qt::KeyboardModifier modifier)
void toPainter(QCPPainter *painter, int width=0, int height=0)
QRect tickLabelsSelectionBox() const
void setSubTickLength(int inside, int outside=0)
QVector< QString > tickLabels
QPolygonF getBarPolygon(double key, double value) const
virtual QCPRange getKeyRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const
virtual QList< QCPLayoutElement * > elements(bool recursive) const
void setTickVectorLabels(const QVector< QString > &vec)
QCPLayer * currentLayer() const
double tickLabelRotation() const
QCPColorMapData & operator=(const QCPColorMapData &other)
QVector< double > tickPositions
LabelType tickLabelType() const
QList< QCPLayerable * > children() const
bool addItem(QCPAbstractLegendItem *item)
QCPItemCurve(QCustomPlot *parentPlot)
A filled arrow head with a straight/flat back (a triangle)
QList< QCPLayoutElement * > elements(QCP::MarginSide side) const
virtual QPointF pixelPoint() const
virtual void draw(QCPPainter *painter)
void setType(QCPAxis::AxisType type)
virtual void resizeEvent(QResizeEvent *event)
void setSpacingType(SpacingType spacingType)
void removeDataBefore(double t)
Q_SLOT void setSelectable(bool selectable)
double cell(int keyIndex, int valueIndex)
void setPen(const QPen &pen)
double distSqrToLine(const QPointF &start, const QPointF &end, const QPointF &point) const
void setLevelCount(int n)
void setTickLabelPadding(int padding)
void setSpacing(double spacing)
void setBrush(const QBrush &brush)
void addData(const QCPCurveDataMap &dataMap)
virtual void mouseReleaseEvent(QMouseEvent *event)
BracketStyle style() const
QList< QCPGraph * > selectedGraphs() const
QColor mainTextColor() const
void selectableChanged(const QCPAxis::SelectableParts &parts)
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const
void setMedianPen(const QPen &pen)
void setSubTickPen(const QPen &pen)
void setTickStep(double step)
virtual ~QCPLayoutElement()
Q_SLOT bool setLayer(QCPLayer *layer)
void setBackgroundScaledMode(Qt::AspectRatioMode mode)
virtual QCPLayoutElement * elementAt(int index) const
void setOffset(int offset)
The central class of the library. This is the QWidget which displays the plot and interacts with the ...
void setBrush(const QBrush &brush)
void rescaleKeyAxis(bool onlyEnlarge=false) const
int subTickLengthOut() const
int findIndexAboveY(const QVector< QPointF > *data, double y) const
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const
void setMedian(double value)
void setBrush(const QBrush &brush)
virtual void paintEvent(QPaintEvent *event)
void setAutoTicks(bool on)
QPen getBorderPen() const
virtual QSize maximumSizeHint() const
void removeFillBasePoints(QVector< QPointF > *lineData) const
void setSize(double size)
virtual QSize minimumSizeHint() const
void setCustomPath(const QPainterPath &customPath)
QCPColorGradient gradient() const
void drawError(QCPPainter *painter, double x, double y, const QCPData &data) const
void setLineStyle(LineStyle ls)
custom painter operations are performed per scatter (As QPainterPath, see setCustomPath) ...
void removeDataBefore(double key)
virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
QCPFinancialDataMap * mData
bool hasItemWithPlottable(const QCPAbstractPlottable *plottable) const
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const
Qt::Alignment insetAlignment(int index) const
void setNumberFormat(const QString &formatCode)
QCPColorMap(QCPAxis *keyAxis, QCPAxis *valueAxis)
ColorInterpolation mColorInterpolation
0x0040 Main lines of items
void setErrorType(ErrorType errorType)
QPen mSelectedIconBorderPen
virtual void draw(QCPPainter *painter)
void setPeriodic(bool enabled)
Holds the data of one single data point (one bar) for QCPBars.
void rescaleDataRange(bool recalculateDataBounds=false)
Qt::Orientations mRangeDrag
int getMarginValue(const QMargins &margins, QCP::MarginSide side)
QCPLineEnding upperEnding() const
void setSize(int keySize, int valueSize)
QPointer< QCPAxis > mColorAxis
virtual QRect clipRect() const
Manages a legend inside a QCustomPlot.
Qt::TransformationMode transformationMode() const
static AxisType marginSideToAxisType(QCP::MarginSide side)
QCPLayoutGrid * mPlotLayout
void setPen(const QPen &pen)
void setViewport(const QRect &rect)
QCPColorGradient mGradient
QList< Qt::Alignment > mInsetAlignment
void moveRange(double diff)
QCPItemPosition *const right
QSet< QCPItemPosition * > mChildrenY
void setMarginValue(QMargins &margins, QCP::MarginSide side, int value)
void moveAbove(QCPBars *bars)
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const
void setPadding(int padding)
virtual QCPItemPosition * toQCPItemPosition()
Qt::TimeSpec mDateTimeSpec
void getCurveData(QVector< QPointF > *lineData) const
void setAxisRect(QCPAxisRect *axisRect)
virtual void updateMapImage()
void updateAxesOffset(QCPAxis::AxisType type)
virtual QCPRange getValueRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const
void mouseMove(QMouseEvent *event)
Full hue cycle, with highest and lowest color red (suitable for periodic data, such as angles and pha...
QList< QCPBars * > bars() const
QCP::AntialiasedElements notAntialiasedElements() const
0x002 Legend items individually (see selectedItems)
void setFont(const QFont &font)
QCustomPlot(QWidget *parent=0)
QList< QCPAxis * > axes() const
QCPLineEnding tail() const
void setColorInterpolation(ColorInterpolation interpolation)
void setTickLabelRotation(double degrees)
QCPPlotTitle(QCustomPlot *parentPlot)
void setNoAntialiasingOnDrag(bool enabled)
void setInsetRect(int index, const QRectF &rect)
QCPRange dataRange() const
A layout that arranges child elements in a grid.
Hue variation similar to a spectrum, often used in numerical visualization (creates banding illusion ...
Continuous lightness from black to white (suited for non-biased data representation) ...
QCPLayoutElement * element(int row, int column) const
ErrorType errorType() const
0x0020 Main lines of plottables (excluding error bars, see element aeErrorBars)
void colorize(const double *data, const QCPRange &range, QRgb *scanLine, int n, int dataIndexFactor=1, bool logarithmic=false)
bool mMapImageInvalidated
virtual QSize minimumSizeHint() const
int iconTextPadding() const
QCPRange valueRange() const
QCP::PlottingHints plottingHints() const
QCPAbstractPlottable * plottableAt(const QPointF &pos, bool onlySelectable=false) const
Q_SLOT void setRange(const QCPRange &range)
void setSelectedTextColor(const QColor &color)
SelectableParts selectableParts() const
QPainter subclass used internally.
void removeDataAfter(double key)
A bar perpendicular to the line, pointing out to only one side (to which side can be changed with set...
The abstract base class for all objects that form the layout system.
QList< QCPColorMap * > colorMaps() const
void setKeyRange(const QCPRange &keyRange)
void setDataValueError(const QVector< double > &key, const QVector< double > &value, const QVector< double > &valueError)
int tickLengthOut() const
Q_SLOT void replot(QCustomPlot::RefreshPriority refreshPriority=QCustomPlot::rpHint)
virtual ~QCPItemEllipse()
QRect getFinalRect(bool *flippedHorz=0, bool *flippedVert=0) const
void setRangeUpper(double upper)
virtual QCPRange getKeyRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const
TracerStyle style() const
QCPAxisPainterPrivate(QCustomPlot *parentPlot)
The axis backbone and tick marks.
QCPMarginGroup(QCustomPlot *parentPlot)
void cellToCoord(int keyIndex, int valueIndex, double *key, double *value) const
void setRangeDragAxes(QCPAxis *horizontal, QCPAxis *vertical)
PositionType mPositionTypeX
QLineF getRectClippedStraightLine(const QVector2D &point1, const QVector2D &vec, const QRect &rect) const
QMap< double, QCPBarData > QCPBarDataMap
QCPAxis::ScaleType mDataScaleType
virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
void setTextAlignment(Qt::Alignment alignment)
double rectSelectTest(const QRectF &rect, const QPointF &pos, bool filledRect) const
Holds multiple axes and arranges them in a rectangular shape.
double keyPixelOffset(const QCPBars *bars, double keyCoord)
virtual QPointF anchorPixelPoint(int anchorId) const
QCPFinancial(QCPAxis *keyAxis, QCPAxis *valueAxis)
void setColumnStretchFactors(const QList< double > &factors)
QVector< double > mOutliers
{ssCrossSquare.png} a square with a cross inside
void unregisterBars(QCPBars *bars)
void setSelectedPen(const QPen &pen)
void setSelectedBrush(const QBrush &brush)
virtual void deselectEvent(bool *selectionStateChanged)
Q_SLOT void axisSelectionChanged(QCPAxis::SelectableParts selectedParts)
QCPLayer * layer(const QString &name) const
void removeChildX(QCPItemPosition *pos)
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const
void setSelectedColor(const QColor &color)
QCPLineEnding lowerEnding
void setErrorBarSkipSymbol(bool enabled)
QCPItemPosition *const left
virtual void drawScatterPlot(QCPPainter *painter, QVector< QCPData > *scatterData) const
QCustomPlot * mParentPlot
bool contains(double value) const
double baseLog(double value) const
void setBrush(const QBrush &brush)
QCPCurve(QCPAxis *keyAxis, QCPAxis *valueAxis)
void coordsToPixels(double key, double value, double &x, double &y) const
Error bars for the value dimension of the data point are shown.
SelectableParts selectedParts() const
virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
void setData(double key, double minimum, double lowerQuartile, double median, double upperQuartile, double maximum)
void setSelectedBrush(const QBrush &brush)
A color scale for use with color coding data such as QCPColorMap.
QSet< QCPItemPosition * > mChildrenX
Q_SLOT void setSelectable(bool selectable)
virtual ~QCPAbstractItem()
SelectableParts mSelectedParts
QPointer< QCPAxis > mRangeZoomHorzAxis
void setBarWidth(int width)
bool saveBmp(const QString &fileName, int width=0, int height=0, double scale=1.0)
bool mAntialiasedZeroLine
QList< QCPAxis * > axes(QCPAxis::AxisTypes types) const
virtual QCP::Interaction selectionCategory() const
Groups multiple QCPBars together so they appear side by side.
void setSelectedIconBorderPen(const QPen &pen)
QCPColorScale * mParentColorScale
QCPItemPosition *const endDir
void adoptElement(QCPLayoutElement *el)
void setRowStretchFactors(const QList< double > &factors)
void setSelectedBrush(const QBrush &brush)
Whether to use immediate repaint or queued update depends on whether the plotting hint QCP::phForceRe...
virtual QCPRange getValueRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const
void getStepLeftPlotData(QVector< QPointF > *linePixelData, QVector< QCPData > *scatterData) const
void setTickLength(int inside, int outside=0)
int countDataInBounds(const QCPDataMap::const_iterator &lower, const QCPDataMap::const_iterator &upper, int maxCount) const
virtual ~QCPItemPosition()
void setMargins(const QMargins &margins)
QRect mTickLabelsSelectionBox
The element may be positioned/sized arbitrarily, see setInsetRect.
Continuous lightness from black over icey colors to white (suited for non-biased data representation)...
void draw(QCPPainter *painter, const QVector2D &pos, const QVector2D &dir) const
QColor getTextColor() const
QCPRange mDragStartVertRange
The abstract base class for all entries in a QCPLegend.
0x04 Axis is horizontal and on the top side of the axis rect
void getPlotData(QVector< QPointF > *lineData, QVector< QCPData > *scatterData) const
virtual QCPRange getValueRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const =0
Qt::AspectRatioMode mBackgroundScaledMode
Continuous lightness from black over weak blueish colors to white (suited for non-biased data represe...
QString numberFormat() const
virtual QPointF anchorPixelPoint(int anchorId) const
Tick labels (numbers) of this axis (as a whole, not individually)
virtual QPointF anchorPixelPoint(int anchorId) const
void gradientChanged(QCPColorGradient newGradient)
Holds the data of one single data point for QCPGraph.
void setValueSize(int valueSize)
virtual void draw(QCPPainter *painter)
None of the selectable parts.
double ohlcSelectTest(const QPointF &pos, const QCPFinancialDataMap::const_iterator &begin, const QCPFinancialDataMap::const_iterator &end) const
virtual void drawTickLabel(QCPPainter *painter, double x, double y, const TickLabelData &labelData) const
void recalculateDataBounds()
virtual void mouseMoveEvent(QMouseEvent *event)
bool moveToLayer(QCPLayer *layer, bool prepend)
void setPixmap(const QPixmap &pixmap)
double pointDistance(const QPointF &pixelPoint) const
Q_SLOT void setSelected(bool selected)
QColor mSelectedTextColor
QVector< double > mSubTickVector
void getVisibleDataBounds(QCPBarDataMap::const_iterator &lower, QCPBarDataMap::const_iterator &upperEnd) const
int numberPrecision() const
void rescaleDataRange(bool onlyVisibleMaps)
void setSelectedTickPen(const QPen &pen)
0x02 Mode for all sorts of exports (e.g. PNG, PDF,...). For example, this prevents using cached pixma...
QCPRange keyRange() const
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const
QMap< double, QColor > mColorStops
void setHead(const QCPLineEnding &head)
A legend item representing a plottable with an icon and the plottable name.
void setUpperEnding(const QCPLineEnding &ending)
Q_SLOT void setDataRange(const QCPRange &dataRange)
QVector< QRgb > mColorBuffer
void setScatterStyle(const QCPScatterStyle &style)
QList< QCPAxis * > addAxes(QCPAxis::AxisTypes types)
bool savePng(const QString &fileName, int width=0, int height=0, double scale=1.0, int quality=-1)
void getLinePlotData(QVector< QPointF > *linePixelData, QVector< QCPData > *scatterData) const
void axisClick(QCPAxis *axis, QCPAxis::SelectablePart part, QMouseEvent *event)
virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
void setClipToAxisRect(bool clip)
void setOutliers(const QVector< double > &values)
Q_SLOT void setSelectableParts(const QCPAxis::SelectableParts &selectableParts)
void setSubTickCount(int count)
QString dateTimeFormat() const
QPointer< QCPAxis > mRangeDragHorzAxis
void setIconBorderPen(const QPen &pen)
void setTypeX(PositionType type)
0x080 All other objects are selectable (e.g. your own derived layerables, the plot title...
void setPlottingHint(QCP::PlottingHint hint, bool enabled=true)
virtual bool addToLegend()
QList< QCPAbstractPlottable * > plottables() const
void setAutoTickCount(int approximateCount)
void setData(QCPBarDataMap *data, bool copy=false)
QList< QCPItemAnchor * > mAnchors
0x001 Axis ranges are draggable (see QCPAxisRect::setRangeDrag, QCPAxisRect::setRangeDragAxes) ...
QCP::AntialiasedElements mAADragBackup
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const
QCPColorMapData * mMapData
virtual int elementCount() const =0
Qt::Alignment mPositionAlignment
QCPAxis * keyAxis() const
bool moveLayer(QCPLayer *layer, QCPLayer *otherLayer, LayerInsertMode insertMode=limAbove)
bool isInvalidData(double value)
QPointer< QCPAxis > mValueAxis
virtual void deselectEvent(bool *selectionStateChanged)
Manages a single axis inside a QCustomPlot.
void drawSubGridLines(QCPPainter *painter) const
virtual QList< QCPLayoutElement * > elements(bool recursive) const
QCPItemPixmap(QCustomPlot *parentPlot)
QCPBarsGroup(QCustomPlot *parentPlot)
void drawOhlcPlot(QCPPainter *painter, const QCPFinancialDataMap::const_iterator &begin, const QCPFinancialDataMap::const_iterator &end)
QCPLineEnding upperEnding
QCPLineEnding head() const
QList< QCPLegend * > selectedLegends() const
A brace with round edges.
QMap< double, QCPFinancialData > QCPFinancialDataMap
SelectableParts selectableParts() const
virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const
void setChartStyle(ChartStyle style)
virtual void getMaxTickLabelSize(const QFont &font, const QString &text, QSize *tickLabelsSize) const
QFont mSelectedTickLabelFont
void setAntialiasedZeroLine(bool enabled)
QPointF getTextDrawPoint(const QPointF &pos, const QRectF &rect, Qt::Alignment positionAlignment) const
Bar spacing is in absolute pixels.
Final phase in which the layout system places the rects of the elements.
0x02 Axis is vertical and on the right side of the axis rect
void setErrorPen(const QPen &pen)
0x001 The legend box (frame)
void getPixelWidth(double key, double &lower, double &upper) const
Queues the refresh such that it is performed at a slightly delayed point in time after the replot...
void append(QCPBars *bars)
QCPItemPosition *const end
QCPColorGradient(GradientPreset preset=gpCold)
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const
void addChild(QCP::MarginSide side, QCPLayoutElement *element)
Error bars for both key and value dimensions of the data point are shown.
QCPLayout * layout() const
QCPAbstractPlottable(QCPAxis *keyAxis, QCPAxis *valueAxis)
void setSelectedPen(const QPen &pen)
virtual int calculateAutoMargin(QCP::MarginSide side)
virtual QCPRange getValueRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const
void setErrorBarSize(double size)
virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const
QCPItemPosition *const start
QHash< QCP::MarginSide, QCPMarginGroup * > mMarginGroups
QVector< QPointF > getOptimizedCornerPoints(int prevRegion, int currentRegion, double prevKey, double prevValue, double key, double value, double rectLeft, double rectTop, double rectRight, double rectBottom) const
double basePow(double value) const
virtual void draw(QCPPainter *painter)
Bar spacing is given by a fraction of the axis rect size.
QRectF insetRect(int index) const
QPointer< QCPAxis > mKeyAxis
virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const =0
double getStackedBaseValue(double key, bool positive) const
Colors suitable for thermal imaging, ranging from dark blue over purple to orange, yellow and white.
QCPItemPosition *const bottomRight
virtual void draw(QCPPainter *painter)
void setData(QCPFinancialDataMap *data, bool copy=false)
QCPItemPosition *const start
const QCPRange range() const
void setParentLayerable(QCPLayerable *parentLayerable)
QCPCurveDataMap * data() const
void moveBelow(QCPBars *bars)
bool autoSubTicks() const
A margin group allows synchronization of margin sides if working with multiple layout elements...
0x04 Turns pen widths 0 to 1, i.e. disables cosmetic pens. (A cosmetic pen is always drawn with width...
virtual void draw(QCPPainter *painter)
Error bars for the key dimension of the data point are shown.
0x0080 Scatter symbols of plottables (excluding scatter symbols of type ssPixmap) ...
void rescaleValueAxis(bool onlyEnlarge, bool includeErrorBars) const
QCPMarginGroup * marginGroup(QCP::MarginSide side) const
virtual void drawFill(QCPPainter *painter, QVector< QPointF > *lineData) const
int axisRectCount() const
Phase in which the margins are calculated and set.
void rescaleValueAxis(bool onlyEnlarge=false) const
QPointer< QCPGraph > mChannelFillGraph
bool addPlottable(QCPAbstractPlottable *plottable)
void setBackground(const QPixmap &pm)
QCPGraph * addGraph(QCPAxis *keyAxis=0, QCPAxis *valueAxis=0)
virtual QSize minimumSizeHint() const
QPen iconBorderPen() const
void setMinimumSize(const QSize &size)
void setTickLabelColor(const QColor &color)
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const
const QCP::Interactions interactions() const
double mScaleLogBaseLogInv
Q_SLOT void setSelectable(bool selectable)
void setScaleRatio(const QCPAxis *otherAxis, double ratio=1.0)
QList< QList< QCPLayoutElement * > > mElements
An anchor of an item to which positions can be attached to.
void getScatterPlotData(QVector< QCPData > *scatterData) const
void setModes(PainterModes modes)
bool savePdf(const QString &fileName, bool noCosmeticPen=false, int width=0, int height=0, const QString &pdfCreator=QString(), const QString &pdfTitle=QString())
void applyScattersAntialiasingHint(QCPPainter *painter) const
friend class QCPItemAnchor
QList< QCPAbstractPlottable * > mPlottables
void setLength(double length)
void setName(const QString &name)
virtual QList< QCPLayoutElement * > elements(bool recursive) const
void getVisibleDataBounds(QCPDataMap::const_iterator &lower, QCPDataMap::const_iterator &upper) const
The abstract base class for all items in a plot.
virtual QCPRange getKeyRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const
bool addElement(int row, int column, QCPLayoutElement *element)
void updateGradientImage()
void setTickLabelType(LabelType type)
double candlestickSelectTest(const QPointF &pos, const QCPFinancialDataMap::const_iterator &begin, const QCPFinancialDataMap::const_iterator &end) const
void getImpulsePlotData(QVector< QPointF > *linePixelData, QVector< QCPData > *scatterData) const
line is drawn as steps where the step height is the value of the right data point ...
void setType(PositionType type)
QPointer< QCPAxis > mValueAxis
virtual void draw(QCPPainter *painter)
virtual void parentPlotInitialized(QCustomPlot *parentPlot)
QCPScatterStyle mScatterStyle
void setColorStops(const QMap< double, QColor > &colorStops)
void mouseDoubleClick(QMouseEvent *event)
void rescaleKeyAxis(bool onlyEnlarge, bool includeErrorBars) const
void getStepRightPlotData(QVector< QPointF > *linePixelData, QVector< QCPData > *scatterData) const
SelectableParts mSelectedParts
{ssTriangle.png} an equilateral triangle, standing on baseline
virtual void draw(QCPPainter *painter)
void selectionChanged(QCPLegend::SelectableParts parts)
Q_SLOT void setSelectedParts(const SelectableParts &selectedParts)
void selectionChanged(const QCPAxis::SelectableParts &parts)
static AxisType opposite(AxisType type)
QList< InsetPlacement > mInsetPlacement
QPixmap mScaledBackgroundPixmap
virtual void draw(QCPPainter *painter)
void removeDataAfter(double key)
void setRange(const QCPRange &keyRange, const QCPRange &valueRange)
virtual QRect clipRect() const
void plottableDoubleClick(QCPAbstractPlottable *plottable, QMouseEvent *event)
Qt::TransformationMode mTransformationMode
QCPAxisRect * axisRect() const
double mRangeZoomFactorVert
QCPItemAnchor * parentAnchorY() const
virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
QList< QCPGraph * > graphs() const
Q_SLOT void setSelectableParts(const SelectableParts &selectableParts)
QCPLineEnding lowerEnding() const
QVector< QString > mTickVectorLabels
QPointer< QCPLayerable > mParentLayerable
void setKeySize(int keySize)
Qt::Alignment mTextAlignment
QRect labelSelectionBox() const
void setTickLabelFont(const QFont &font)
Dynamic positioning at a plot coordinate defined by two axes (see setAxes).
The tracer is not visible.
virtual void draw(QCPPainter *painter)
double data(double key, double value)
QCPItemPosition *const position
Color channels hue, saturation and value are linearly interpolated (The hue is interpolated over the ...
void setSelectedPen(const QPen &pen)
virtual bool removeFromLegend() const
void setLowerQuartile(double value)
A layout that places child elements aligned to the border or arbitrarily positioned.
QPen selectedIconBorderPen() const
void addData(const QCPDataMap &dataMap)
virtual void drawOutliers(QCPPainter *painter) const
void setSelectedSubTickPen(const QPen &pen)
line is drawn as steps where the step height is the value of the left data point
virtual void mouseDoubleClickEvent(QMouseEvent *event)
void legendDoubleClick(QCPLegend *legend, QCPAbstractLegendItem *item, QMouseEvent *event)
void setTickPen(const QPen &pen)
void setSize(double size)
void setKeyAxis(QCPAxis *axis)
virtual void mouseReleaseEvent(QMouseEvent *event)
QColor mSelectedTextColor
Phase used for any type of preparation that needs to be done before margin calculation and layout...
static const double minRange
virtual QCPRange getValueRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const
void addFillBasePoints(QVector< QPointF > *lineData) const
QCPItemPosition *const point1
void setDataBothError(const QVector< double > &key, const QVector< double > &value, const QVector< double > &keyError, const QVector< double > &valueError)
virtual QCP::Interaction selectionCategory() const
void setSelectedBrush(const QBrush &brush)
double rangeZoomFactor(Qt::Orientation orientation)
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const
void setRangeZoom(Qt::Orientations orientations)
Data points are connected with a straight line.
int commonMargin(QCP::MarginSide side) const
void initializeParentPlot(QCustomPlot *parentPlot)
void setPen(const QPen &pen)
void rescale(bool onlyVisiblePlottables=false)
void setAntialiasedSubGrid(bool enabled)
QCustomPlot * mParentPlot
virtual void mouseMoveEvent(QMouseEvent *event)
void setPositionAlignment(Qt::Alignment alignment)
void setData(QCPCurveDataMap *data, bool copy=false)
A plottable representing a bar chart in a plot.
QList< QCPAxisRect * > axisRects() const
void setInsetAlignment(int index, Qt::Alignment alignment)
void removeDataBefore(double key)
void expandTo(int newRowCount, int newColumnCount)
void setWhiskerWidth(double width)
An approximation of the visible light spectrum (creates banding illusion but allows more precise magn...
void setBackground(const QPixmap &pm)
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const
QCPLayerable(QCustomPlot *plot, QString targetLayer=QString(), QCPLayerable *parentLayerable=0)
QCPItemPosition * createPosition(const QString &name)
The QCustomPlot surface is immediately refreshed, by calling QWidget::repaint() after the replot...
void setNotAntialiasedElements(const QCP::AntialiasedElements ¬AntialiasedElements)
void updateLayerIndices() const
QCP::PlottingHints mPlottingHints
void setColumnSpacing(int pixels)
void setScatterStyle(const QCPScatterStyle &style)
virtual void mouseMoveEvent(QMouseEvent *event)
PainterModes modes() const
virtual void mouseReleaseEvent(QMouseEvent *event)
QMap< double, QColor > colorStops() const
virtual QCPRange getValueRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const
void titleClick(QMouseEvent *event, QCPPlotTitle *title)
void setChannelFillGraph(QCPGraph *targetGraph)
A bar that is skewed (skew controllable via setLength)
QCPLayerable * layerableAt(const QPointF &pos, bool onlySelectable, QVariant *selectionDetails=0) const
QPixmap mBackgroundPixmap
void selectableChanged(bool selectable)
QList< QCPAbstractItem * > items() const
void setBasePen(const QPen &pen)
int subTickLengthIn() const
virtual void updateLayout()
QCPAxis * addAxis(QCPAxis::AxisType type, QCPAxis *axis=0)
void insertRow(int newIndex)
a custom pixmap specified by setPixmap, centered on the data point coordinates
Base class for all drawable objects.
QCPItemPosition *const end
void setDateTimeSpec(const Qt::TimeSpec &timeSpec)
void drawBackground(QCPPainter *painter)
QRect axisSelectionBox() const
void setBorderPen(const QPen &pen)
QCP::AntialiasedElements mAntialiasedElements
QPointF upperFillBasePoint(double upperKey) const
virtual void draw(QCPPainter *painter)
virtual void deselectEvent(bool *selectionStateChanged)
bool hasAnchor(const QString &name) const
void setPen(const QPen &pen)
SelectableParts mSelectableParts
void drawBackground(QCPPainter *painter)
void setStyle(TracerStyle style)
QFont getLabelFont() const
void axisDoubleClick(QCPAxis *axis, QCPAxis::SelectablePart part, QMouseEvent *event)
QVector< double > mTickVector
bool abbreviateDecimalPowers
bool removeItem(QCPAbstractItem *item)
Bar width is given by a fraction of the axis rect size.
virtual QCPRange getValueRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const
Colors suitable to emphasize polarity around the center, with blue for negative, black in the middle ...
QCPAxis * axis(QCPAxis::AxisType type, int index=0) const
void setTickLabels(bool show)
void setPen(const QPen &pen)
{ssDisc.png} a circle which is filled with the pen's color (not the brush as with ssCircle) ...
Tick labels will be displayed outside the axis rect.
Bar width is in key coordinates and thus scales with the key axis range.
0x01 Mode for vectorized painting (e.g. PDF export). For example, this prevents some antialiasing fix...
virtual QCPRange getKeyRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const
double scaleLogBase() const
void addChild(QCPLayerable *layerable, bool prepend)
QCPItemAnchor * parentAnchorX() const
void setPenNegative(const QPen &pen)
bool removeItem(int index)
QCP::AntialiasedElements antialiasedElements() const
void setRangeDrag(bool enabled)
virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
void scaleRange(double factor, double center)
Qt::Orientations mRangeZoom
QCPColorScaleAxisRectPrivate(QCPColorScale *parentColorScale)
void setGraph(QCPGraph *graph)
virtual void drawQuartileBox(QCPPainter *painter, QRectF *quartileBox=0) const
EndingStyle style() const
static bool validRange(double lower, double upper)
virtual TickLabelData getTickLabelData(const QFont &font, const QString &text) const
void setShape(ScatterShape shape)
void setAutoSubTicks(bool on)
QCPItemPosition *const startDir
void setLineStyle(LineStyle style)
virtual QSize minimumSizeHint() const
QCPBars(QCPAxis *keyAxis, QCPAxis *valueAxis)
bool autoTickStep() const
virtual bool take(QCPLayoutElement *element)
void applyTo(QCPPainter *painter, const QPen &defaultPen) const
QCPAxisRect(QCustomPlot *parentPlot, bool setupDefaultAxes=true)
A plottable representing a graph in a plot.
bool setParentAnchorY(QCPItemAnchor *parentAnchor, bool keepPixelPosition=false)
virtual void parentPlotInitialized(QCustomPlot *parentPlot)
QCPRange expanded(const QCPRange &otherRange) const
virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const =0
void setIconTextPadding(int padding)
void setMinimum(double value)
QList< QCPGraph * > graphs() const
bool hasPlottable(QCPAbstractPlottable *plottable) const
void expand(const QCPRange &otherRange)
QPointer< QCPAxis > mRangeDragVertAxis
0x08 Axis is horizontal and on the bottom side of the axis rect
bool mNumberBeautifulPowers
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const =0
virtual QCPLayoutElement * elementAt(int index) const =0
void setAutoMargins(QCP::MarginSides sides)
void registerBars(QCPBars *bars)
No line is drawn between data points (e.g. only scatters)
QCPGraph(QCPAxis *keyAxis, QCPAxis *valueAxis)
bool mayTraverse(int prevRegion, int currentRegion) const
void setPlottingHints(const QCP::PlottingHints &hints)
virtual QCPRange getKeyRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const =0
void dataRangeChanged(QCPRange newRange)
QCPDataMap * data() const
virtual int calculateMargin()
Holds the two-dimensional data of a QCPColorMap plottable.
virtual bool take(QCPLayoutElement *element)
void setClipAxisRect(QCPAxisRect *rect)
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const
void setColor(const QColor &color)
A plus shaped crosshair with limited size.
virtual void draw(QCPPainter *painter)
void setMinimumMargins(const QMargins &margins)
void setAntialiased(bool enabled)
QPointer< QCPAxis > mRangeZoomVertAxis
void itemDoubleClick(QCPAbstractItem *item, QMouseEvent *event)
QCPItemRect(QCustomPlot *parentPlot)
The abstract base class for all data representing objects in a plot.
virtual QCPLayoutElement * takeAt(int index)
QColor getLabelColor() const
void getMaximumRowColSizes(QVector< int > *maxColWidths, QVector< int > *maxRowHeights) const
virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const
void addData(const QCPFinancialDataMap &dataMap)
double realLength() const
void setSelectedPen(const QPen &pen)
void drawGridLines(QCPPainter *painter) const
bool removeGraph(QCPGraph *graph)
QPointer< QCPBars > mBarBelow
int axisCount(QCPAxis::AxisType type) const
void setAutoTickStep(bool on)
QPointer< QCPBars > mBarAbove
double coordToPixel(double value) const
void setWidth(double width)
Qt::AspectRatioMode mBackgroundScaledMode
void rangeChanged(const QCPRange &newRange)
void gradientChanged(QCPColorGradient newGradient)
const QPolygonF getChannelFillPolygon(const QVector< QPointF > *lineData) const
void setSubTickLengthIn(int inside)
virtual QCPLayoutElement * takeAt(int index)=0
QVector< double > subTickPositions
void setText(const QString &text)
0x002 Axis ranges are zoomable with the mouse wheel (see QCPAxisRect::setRangeZoom, QCPAxisRect::setRangeZoomAxes)
virtual QByteArray generateLabelParameterHash() const
QCustomPlot * mParentPlot
QCPRange mDragStartHorzRange
virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged)
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const
virtual void draw(QCPPainter *painter)
virtual QList< QCPLayoutElement * > elements(bool recursive) const
virtual void draw(QCPPainter *painter)
line is drawn as steps where the step is in between two data points
QCPPlottableLegendItem(QCPLegend *parent, QCPAbstractPlottable *plottable)
virtual QPointF pixelPoint() const
0x010 Axes are selectable (or parts of them, see QCPAxis::setSelectableParts)
A non-filled arrow head with open back.
void removeChild(QCPLayerable *layerable)
virtual QPointF anchorPixelPoint(int anchorId) const
virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
QCPLayerable * parentLayerable() const
void setGraphKey(double key)
void removeData(double fromt, double tot)
QCPItemPosition *const point2
void setMarginGroup(QCP::MarginSides sides, QCPMarginGroup *group)
virtual void draw(QCPPainter *painter)
void setPen(const QPen &pen)
QCPItemAnchor * parentAnchor() const
QByteArray mLabelParameterHash
void setRangeDrag(Qt::Orientations orientations)
void setBackgroundScaled(bool scaled)
virtual void draw(QCPPainter *painter)
void setWidth(double width)
void setInteractions(const QCP::Interactions &interactions)
void setRotation(double degrees)
QCPAbstractPlottable * plottable(int index)
void setSubTickLengthOut(int outside)
void setSelectedFont(const QFont &font)
virtual void wheelEvent(QWheelEvent *event)
A plottable representing a two-dimensional color map in a plot.
void setSelectedBrush(const QBrush &brush)
void setSelectedBrush(const QBrush &brush)
void setSelectedLabelColor(const QColor &color)
virtual QRect clipRect() const
QColor mSelectedTextColor
QCPAxis * valueAxis() const
QCPLayer(QCustomPlot *parentPlot, const QString &layerName)
QList< double > mColumnStretchFactors
void setNumberPrecision(int precision)
Q_SLOT void setSelected(bool selected)
bool hasElement(int row, int column)
void rescaleAxes(bool onlyEnlarge, bool includeErrorBars) const
void selectionChanged(bool selected)
bool realVisibility() const
QList< QCPAbstractItem * > selectedItems() const
QList< QRectF > mInsetRect
ScatterShape shape() const
void setTail(const QCPLineEnding &tail)
QCustomPlot * parentPlot() const
bool mAutoAddPlottableToLegend
void setSelectedBorderPen(const QPen &pen)
QMap< double, QCPCurveData > QCPCurveDataMap
void setSelectedPen(const QPen &pen)
virtual void update(UpdatePhase phase)
void rescaleAxes(bool onlyEnlarge=false) const
0x020 Legends are selectable (or their child items, see QCPLegend::setSelectableParts) ...
QPointF getOptimizedPoint(int prevRegion, double prevKey, double prevValue, double key, double value, double rectLeft, double rectTop, double rectRight, double rectBottom) const
QCPAbstractPlottable * plottable()
virtual void drawMedian(QCPPainter *painter) const
void removeDataAfter(double t)
void setWidth(double width)
QCPItemPosition *const bottomRight
virtual void draw(QCPPainter *painter)
Logarithmic scaling with correspondingly transformed plots and (major) tick marks at every base power...
int plottableCount() const
void loadPreset(GradientPreset preset)
Holds the data of one single data point for QCPFinancial.
Q_SLOT void setDataScaleType(QCPAxis::ScaleType scaleType)
SpacingType spacingType() const
virtual ~QCPLayoutInset()
void removeDataAfter(double key)
Qt::TimeSpec dateTimeSpec() const
virtual QCP::Interaction selectionCategory() const
QPixmap mScaledBackgroundPixmap
int autoTickCount() const
void setSelectedPen(const QPen &pen)
void setLabelPadding(int padding)
void updateScaledPixmap(QRect finalRect=QRect(), bool flipHorz=false, bool flipVert=false)
void setFont(const QFont &font)
QPointer< QCPAxisRect > mAxisRect
virtual QPointF getTickLabelDrawOffset(const TickLabelData &labelData) const
void remove(QCPBars *bars)
virtual void deselectEvent(bool *selectionStateChanged)
void setPixelPoint(const QPointF &pixelPoint)
virtual QCP::Interaction selectionCategory() const
void addElement(QCPLayoutElement *element, Qt::Alignment alignment)
QCPLineEnding head() const
QCPAxis * rangeZoomAxis(Qt::Orientation orientation)
void setBrush(const QBrush &brush)
QCPItemPosition *const bottomRight
virtual void draw(QCPPainter *painter)
void setStyle(EndingStyle style)
QCPAbstractItem * mParentItem
Open-High-Low-Close bar representation.
void removeDataBefore(double key)
QCPColorGradient gradient() const
QList< double > mRowStretchFactors
void setAntialiasedFill(bool enabled)
void setTextColor(const QColor &color)
Q_SLOT void rescaleAxes(bool onlyVisiblePlottables=false)
QCPColorMapData * data() const
QImage mUndersampledMapImage
void coordToCell(double key, double value, int *keyIndex, int *valueIndex) const
QCPItemLine(QCustomPlot *parentPlot)
void setStyle(BracketStyle style)
QCPBarsGroup * mBarsGroup