Kstars

qcustomplot.h
1/*
2 QCustomPlot, an easy to use, modern plotting widget for Qt
3 SPDX-FileCopyrightText: 2011-2021 Emanuel Eichhammer <http://www.qcustomplot.com/>
4
5 SPDX-License-Identifier: GPL-3.0-or-later
6*/
7
8#ifndef QCUSTOMPLOT_H
9#define QCUSTOMPLOT_H
10
11#include <QtCore/qglobal.h>
12
13// some Qt version/configuration dependent macros to include or exclude certain code paths:
14#ifdef QCUSTOMPLOT_USE_OPENGL
15# if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
16# define QCP_OPENGL_PBUFFER
17# else
18# define QCP_OPENGL_FBO
19# endif
20# if QT_VERSION >= QT_VERSION_CHECK(5, 3, 0)
21# define QCP_OPENGL_OFFSCREENSURFACE
22# endif
23#endif
24
25#define QCP_DEVICEPIXELRATIO_SUPPORTED
26#define QCP_DEVICEPIXELRATIO_FLOAT
27
28#include <QtCore/QObject>
29#include <QtCore/QPointer>
30#include <QtCore/QSharedPointer>
31#include <QtCore/QTimer>
32#include <QtGui/QPainter>
33#include <QtGui/QPainterPath>
34#include <QtGui/QPaintEvent>
35#include <QtGui/QMouseEvent>
36#include <QtGui/QWheelEvent>
37#include <QtGui/QPixmap>
38#include <QtCore/QVector>
39#include <QtCore/QString>
40#include <QtCore/QDateTime>
41#include <QtCore/QMultiMap>
42#include <QtCore/QFlags>
43#include <QtCore/QDebug>
44#include <QtCore/QStack>
45#include <QtCore/QCache>
46#include <QtCore/QMargins>
47#include <qmath.h>
48#include <limits>
49#include <algorithm>
50#ifdef QCP_OPENGL_FBO
51# include <QtGui/QOpenGLContext>
52# if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
53# include <QtGui/QOpenGLFramebufferObject>
54# else
55# include <QOpenGLFramebufferObject>
56# include <QOpenGLPaintDevice>
57# endif
58# ifdef QCP_OPENGL_OFFSCREENSURFACE
59# include <QtGui/QOffscreenSurface>
60# else
61# include <QtGui/QWindow>
62# endif
63#endif
64#ifdef QCP_OPENGL_PBUFFER
65# include <QtOpenGL/QGLPixelBuffer>
66#endif
67#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
68# include <qnumeric.h>
69# include <QtGui/QWidget>
70# include <QtGui/QPrinter>
71# include <QtGui/QPrintEngine>
72#else
73# include <QtNumeric>
74# include <QtWidgets/QWidget>
75# include <QtPrintSupport/QtPrintSupport>
76#endif
77#if QT_VERSION >= QT_VERSION_CHECK(4, 8, 0)
78# include <QtCore/QElapsedTimer>
79#endif
80# if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
81# include <QtCore/QTimeZone>
82#endif
83
84class QCPPainter;
85class QCustomPlot;
86class QCPLayerable;
88class QCPLayout;
89class QCPAxis;
90class QCPAxisRect;
93class QCPGraph;
94class QCPAbstractItem;
96class QCPLegend;
97class QCPItemPosition;
98class QCPLayer;
100class QCPSelectionRect;
101class QCPColorMap;
102class QCPColorScale;
103class QCPBars;
106class QCPPolarGrid;
107class QCPPolarGraph;
108
109/* including file 'src/global.h' */
110/* modified 2021-03-29T02:30:44, size 16981 */
111
112#define QCUSTOMPLOT_VERSION_STR "2.1.0"
113#define QCUSTOMPLOT_VERSION 0x020100
114
115// decl definitions for shared library compilation/usage:
116#if defined(QT_STATIC_BUILD)
117# define QCP_LIB_DECL
118#elif defined(QCUSTOMPLOT_COMPILE_LIBRARY)
119# define QCP_LIB_DECL Q_DECL_EXPORT
120#elif defined(QCUSTOMPLOT_USE_LIBRARY)
121# define QCP_LIB_DECL Q_DECL_IMPORT
122#else
123# define QCP_LIB_DECL
124#endif
125
126// define empty macro for Q_DECL_OVERRIDE if it doesn't exist (Qt < 5)
127#ifndef Q_DECL_OVERRIDE
128# define Q_DECL_OVERRIDE
129#endif
130
131/*!
132 The QCP Namespace contains general enums, QFlags and functions used throughout the QCustomPlot
133 library.
134
135 It provides QMetaObject-based reflection of its enums and flags via \a QCP::staticMetaObject.
136*/
137#ifndef Q_MOC_RUN
138namespace QCP {
139#else
140class QCP { // when in moc-run, make it look like a class, so we get Q_GADGET, Q_ENUMS/Q_FLAGS features in namespace
141 Q_GADGET
142 Q_ENUMS(ExportPen)
143 Q_ENUMS(ResolutionUnit)
144 Q_ENUMS(SignDomain)
145 Q_ENUMS(MarginSide)
146 Q_FLAGS(MarginSides)
147 Q_ENUMS(AntialiasedElement)
148 Q_FLAGS(AntialiasedElements)
149 Q_ENUMS(PlottingHint)
150 Q_FLAGS(PlottingHints)
151 Q_ENUMS(Interaction)
152 Q_FLAGS(Interactions)
153 Q_ENUMS(SelectionRectMode)
154 Q_ENUMS(SelectionType)
155public:
156#endif
157
158/*!
159 Defines the different units in which the image resolution can be specified in the export
160 functions.
161
162 \see QCustomPlot::savePng, QCustomPlot::saveJpg, QCustomPlot::saveBmp, QCustomPlot::saveRastered
163*/
164enum ResolutionUnit { ruDotsPerMeter ///< Resolution is given in dots per meter (dpm)
165 ,ruDotsPerCentimeter ///< Resolution is given in dots per centimeter (dpcm)
166 ,ruDotsPerInch ///< Resolution is given in dots per inch (DPI/PPI)
167 };
168
169/*!
170 Defines how cosmetic pens (pens with numerical width 0) are handled during export.
171
172 \see QCustomPlot::savePdf
173*/
174enum ExportPen { epNoCosmetic ///< Cosmetic pens are converted to pens with pixel width 1 when exporting
175 ,epAllowCosmetic ///< Cosmetic pens are exported normally (e.g. in PDF exports, cosmetic pens always appear as 1 pixel on screen, independent of viewer zoom level)
176 };
177
178/*!
179 Represents negative and positive sign domain, e.g. for passing to \ref
180 QCPAbstractPlottable::getKeyRange and \ref QCPAbstractPlottable::getValueRange.
181
182 This is primarily needed when working with logarithmic axis scales, since only one of the sign
183 domains can be visible at a time.
184*/
185enum SignDomain { sdNegative ///< The negative sign domain, i.e. numbers smaller than zero
186 ,sdBoth ///< Both sign domains, including zero, i.e. all numbers
187 ,sdPositive ///< The positive sign domain, i.e. numbers greater than zero
188 };
189
190/*!
191 Defines the sides of a rectangular entity to which margins can be applied.
192
193 \see QCPLayoutElement::setAutoMargins, QCPAxisRect::setAutoMargins
194*/
195enum MarginSide { msLeft = 0x01 ///< <tt>0x01</tt> left margin
196 ,msRight = 0x02 ///< <tt>0x02</tt> right margin
197 ,msTop = 0x04 ///< <tt>0x04</tt> top margin
198 ,msBottom = 0x08 ///< <tt>0x08</tt> bottom margin
199 ,msAll = 0xFF ///< <tt>0xFF</tt> all margins
200 ,msNone = 0x00 ///< <tt>0x00</tt> no margin
201 };
202Q_DECLARE_FLAGS(MarginSides, MarginSide)
203
204/*!
205 Defines what objects of a plot can be forcibly drawn antialiased/not antialiased. If an object is
206 neither forcibly drawn antialiased nor forcibly drawn not antialiased, it is up to the respective
207 element how it is drawn. Typically it provides a \a setAntialiased function for this.
208
209 \c AntialiasedElements is a flag of or-combined elements of this enum type.
210
211 \see QCustomPlot::setAntialiasedElements, QCustomPlot::setNotAntialiasedElements
212*/
213enum AntialiasedElement { aeAxes = 0x0001 ///< <tt>0x0001</tt> Axis base line and tick marks
214 ,aeGrid = 0x0002 ///< <tt>0x0002</tt> Grid lines
215 ,aeSubGrid = 0x0004 ///< <tt>0x0004</tt> Sub grid lines
216 ,aeLegend = 0x0008 ///< <tt>0x0008</tt> Legend box
217 ,aeLegendItems = 0x0010 ///< <tt>0x0010</tt> Legend items
218 ,aePlottables = 0x0020 ///< <tt>0x0020</tt> Main lines of plottables
219 ,aeItems = 0x0040 ///< <tt>0x0040</tt> Main lines of items
220 ,aeScatters = 0x0080 ///< <tt>0x0080</tt> Scatter symbols of plottables (excluding scatter symbols of type ssPixmap)
221 ,aeFills = 0x0100 ///< <tt>0x0100</tt> Borders of fills (e.g. under or between graphs)
222 ,aeZeroLine = 0x0200 ///< <tt>0x0200</tt> Zero-lines, see \ref QCPGrid::setZeroLinePen
223 ,aeOther = 0x8000 ///< <tt>0x8000</tt> Other elements that don't fit into any of the existing categories
224 ,aeAll = 0xFFFF ///< <tt>0xFFFF</tt> All elements
225 ,aeNone = 0x0000 ///< <tt>0x0000</tt> No elements
226 };
227Q_DECLARE_FLAGS(AntialiasedElements, AntialiasedElement)
228
229/*!
230 Defines plotting hints that control various aspects of the quality and speed of plotting.
231
232 \see QCustomPlot::setPlottingHints
233*/
234enum PlottingHint { phNone = 0x000 ///< <tt>0x000</tt> No hints are set
235 ,phFastPolylines = 0x001 ///< <tt>0x001</tt> Graph/Curve lines are drawn with a faster method. This reduces the quality especially of the line segment
236 ///< joins, thus is most effective for pen sizes larger than 1. It is only used for solid line pens.
237 ,phImmediateRefresh = 0x002 ///< <tt>0x002</tt> causes an immediate repaint() instead of a soft update() when QCustomPlot::replot() is called with parameter \ref QCustomPlot::rpRefreshHint.
238 ///< This is set by default to prevent the plot from freezing on fast consecutive replots (e.g. user drags ranges with mouse).
239 ,phCacheLabels = 0x004 ///< <tt>0x004</tt> axis (tick) labels will be cached as pixmaps, increasing replot performance.
240 };
241Q_DECLARE_FLAGS(PlottingHints, PlottingHint)
242
243/*!
244 Defines the mouse interactions possible with QCustomPlot.
245
246 \c Interactions is a flag of or-combined elements of this enum type.
247
248 \see QCustomPlot::setInteractions
249*/
250enum Interaction { iNone = 0x000 ///< <tt>0x000</tt> None of the interactions are possible
251 ,iRangeDrag = 0x001 ///< <tt>0x001</tt> Axis ranges are draggable (see \ref QCPAxisRect::setRangeDrag, \ref QCPAxisRect::setRangeDragAxes)
252 ,iRangeZoom = 0x002 ///< <tt>0x002</tt> Axis ranges are zoomable with the mouse wheel (see \ref QCPAxisRect::setRangeZoom, \ref QCPAxisRect::setRangeZoomAxes)
253 ,iMultiSelect = 0x004 ///< <tt>0x004</tt> The user can select multiple objects by holding the modifier set by \ref QCustomPlot::setMultiSelectModifier while clicking
254 ,iSelectPlottables = 0x008 ///< <tt>0x008</tt> Plottables are selectable (e.g. graphs, curves, bars,... see QCPAbstractPlottable)
255 ,iSelectAxes = 0x010 ///< <tt>0x010</tt> Axes are selectable (or parts of them, see QCPAxis::setSelectableParts)
256 ,iSelectLegend = 0x020 ///< <tt>0x020</tt> Legends are selectable (or their child items, see QCPLegend::setSelectableParts)
257 ,iSelectItems = 0x040 ///< <tt>0x040</tt> Items are selectable (Rectangles, Arrows, Textitems, etc. see \ref QCPAbstractItem)
258 ,iSelectOther = 0x080 ///< <tt>0x080</tt> All other objects are selectable (e.g. your own derived layerables, other layout elements,...)
259 ,iSelectPlottablesBeyondAxisRect = 0x100 ///< <tt>0x100</tt> When performing plottable selection/hit tests, this flag extends the sensitive area beyond the axis rect
260 };
261Q_DECLARE_FLAGS(Interactions, Interaction)
262
263/*!
264 Defines the behaviour of the selection rect.
265
266 \see QCustomPlot::setSelectionRectMode, QCustomPlot::selectionRect, QCPSelectionRect
267*/
268enum SelectionRectMode { srmNone ///< The selection rect is disabled, and all mouse events are forwarded to the underlying objects, e.g. for axis range dragging
269 ,srmZoom ///< When dragging the mouse, a selection rect becomes active. Upon releasing, the axes that are currently set as range zoom axes (\ref QCPAxisRect::setRangeZoomAxes) will have their ranges zoomed accordingly.
270 ,srmSelect ///< When dragging the mouse, a selection rect becomes active. Upon releasing, plottable data points that were within the selection rect are selected, if the plottable's selectability setting permits. (See \ref dataselection "data selection mechanism" for details.)
271 ,srmCustom ///< When dragging the mouse, a selection rect becomes active. It is the programmer's responsibility to connect according slots to the selection rect's signals (e.g. \ref QCPSelectionRect::accepted) in order to process the user interaction.
272 };
273
274/*!
275 Defines the different ways a plottable can be selected. These images show the effect of the
276 different selection types, when the indicated selection rect was dragged:
277
278 <center>
279 <table>
280 <tr>
281 <td>\image html selectiontype-none.png stNone</td>
282 <td>\image html selectiontype-whole.png stWhole</td>
283 <td>\image html selectiontype-singledata.png stSingleData</td>
284 <td>\image html selectiontype-datarange.png stDataRange</td>
285 <td>\image html selectiontype-multipledataranges.png stMultipleDataRanges</td>
286 </tr>
287 </table>
288 </center>
289
290 \see QCPAbstractPlottable::setSelectable, QCPDataSelection::enforceType
291*/
292enum SelectionType { stNone ///< The plottable is not selectable
293 ,stWhole ///< Selection behaves like \ref stMultipleDataRanges, but if there are any data points selected, the entire plottable is drawn as selected.
294 ,stSingleData ///< One individual data point can be selected at a time
295 ,stDataRange ///< Multiple contiguous data points (a data range) can be selected
296 ,stMultipleDataRanges ///< Any combination of data points/ranges can be selected
297 };
298
299/*! \internal
300
301 Returns whether the specified \a value is considered an invalid data value for plottables (i.e.
302 is \e nan or \e +/-inf). This function is used to check data validity upon replots, when the
303 compiler flag \c QCUSTOMPLOT_CHECK_DATA is set.
304*/
305inline bool isInvalidData(double value)
306{
307 return qIsNaN(value) || qIsInf(value);
308}
309
310/*! \internal
311 \overload
312
313 Checks two arguments instead of one.
314*/
315inline bool isInvalidData(double value1, double value2)
316{
317 return isInvalidData(value1) || isInvalidData(value2);
318}
319
320/*! \internal
321
322 Sets the specified \a side of \a margins to \a value
323
324 \see getMarginValue
325*/
326inline void setMarginValue(QMargins &margins, QCP::MarginSide side, int value)
327{
328 switch (side)
329 {
330 case QCP::msLeft: margins.setLeft(value); break;
331 case QCP::msRight: margins.setRight(value); break;
332 case QCP::msTop: margins.setTop(value); break;
333 case QCP::msBottom: margins.setBottom(value); break;
334 case QCP::msAll: margins = QMargins(value, value, value, value); break;
335 default: break;
336 }
337}
338
339/*! \internal
340
341 Returns the value of the specified \a side of \a margins. If \a side is \ref QCP::msNone or
342 \ref QCP::msAll, returns 0.
343
344 \see setMarginValue
345*/
346inline int getMarginValue(const QMargins &margins, QCP::MarginSide side)
347{
348 switch (side)
349 {
350 case QCP::msLeft: return margins.left();
351 case QCP::msRight: return margins.right();
352 case QCP::msTop: return margins.top();
353 case QCP::msBottom: return margins.bottom();
354 default: break;
355 }
356 return 0;
357}
358
359
360extern const QMetaObject staticMetaObject; // in moc-run we create a static meta object for QCP "fake" object. This line is the link to it via QCP::staticMetaObject in normal operation as namespace
361
362} // end of namespace QCP
363Q_DECLARE_OPERATORS_FOR_FLAGS(QCP::AntialiasedElements)
364Q_DECLARE_OPERATORS_FOR_FLAGS(QCP::PlottingHints)
365Q_DECLARE_OPERATORS_FOR_FLAGS(QCP::MarginSides)
366Q_DECLARE_OPERATORS_FOR_FLAGS(QCP::Interactions)
367Q_DECLARE_METATYPE(QCP::ExportPen)
368Q_DECLARE_METATYPE(QCP::ResolutionUnit)
369Q_DECLARE_METATYPE(QCP::SignDomain)
370Q_DECLARE_METATYPE(QCP::MarginSide)
371Q_DECLARE_METATYPE(QCP::AntialiasedElement)
372Q_DECLARE_METATYPE(QCP::PlottingHint)
373Q_DECLARE_METATYPE(QCP::Interaction)
374Q_DECLARE_METATYPE(QCP::SelectionRectMode)
375Q_DECLARE_METATYPE(QCP::SelectionType)
376
377/* end of 'src/global.h' */
378
379
380/* including file 'src/vector2d.h' */
381/* modified 2021-03-29T02:30:44, size 4988 */
382
383class QCP_LIB_DECL QCPVector2D
384{
385public:
386 QCPVector2D();
387 QCPVector2D(double x, double y);
388 QCPVector2D(const QPoint &point);
389 QCPVector2D(const QPointF &point);
390
391 // getters:
392 double x() const { return mX; }
393 double y() const { return mY; }
394 double &rx() { return mX; }
395 double &ry() { return mY; }
396
397 // setters:
398 void setX(double x) { mX = x; }
399 void setY(double y) { mY = y; }
400
401 // non-virtual methods:
402 double length() const { return qSqrt(mX*mX+mY*mY); }
403 double lengthSquared() const { return mX*mX+mY*mY; }
404 double angle() const { return qAtan2(mY, mX); }
405 QPoint toPoint() const { return QPoint(int(mX), int(mY)); }
406 QPointF toPointF() const { return QPointF(mX, mY); }
407
408 bool isNull() const { return qIsNull(mX) && qIsNull(mY); }
409 void normalize();
410 QCPVector2D normalized() const;
411 QCPVector2D perpendicular() const { return QCPVector2D(-mY, mX); }
412 double dot(const QCPVector2D &vec) const { return mX*vec.mX+mY*vec.mY; }
413 double distanceSquaredToLine(const QCPVector2D &start, const QCPVector2D &end) const;
414 double distanceSquaredToLine(const QLineF &line) const;
415 double distanceToStraightLine(const QCPVector2D &base, const QCPVector2D &direction) const;
416
417 QCPVector2D &operator*=(double factor);
418 QCPVector2D &operator/=(double divisor);
419 QCPVector2D &operator+=(const QCPVector2D &vector);
420 QCPVector2D &operator-=(const QCPVector2D &vector);
421
422private:
423 // property members:
424 double mX, mY;
425
426 friend inline const QCPVector2D operator*(double factor, const QCPVector2D &vec);
427 friend inline const QCPVector2D operator*(const QCPVector2D &vec, double factor);
428 friend inline const QCPVector2D operator/(const QCPVector2D &vec, double divisor);
429 friend inline const QCPVector2D operator+(const QCPVector2D &vec1, const QCPVector2D &vec2);
430 friend inline const QCPVector2D operator-(const QCPVector2D &vec1, const QCPVector2D &vec2);
431 friend inline const QCPVector2D operator-(const QCPVector2D &vec);
432};
433Q_DECLARE_TYPEINFO(QCPVector2D, Q_MOVABLE_TYPE);
434
435inline const QCPVector2D operator*(double factor, const QCPVector2D &vec) { return QCPVector2D(vec.mX*factor, vec.mY*factor); }
436inline const QCPVector2D operator*(const QCPVector2D &vec, double factor) { return QCPVector2D(vec.mX*factor, vec.mY*factor); }
437inline const QCPVector2D operator/(const QCPVector2D &vec, double divisor) { return QCPVector2D(vec.mX/divisor, vec.mY/divisor); }
438inline const QCPVector2D operator+(const QCPVector2D &vec1, const QCPVector2D &vec2) { return QCPVector2D(vec1.mX+vec2.mX, vec1.mY+vec2.mY); }
439inline const QCPVector2D operator-(const QCPVector2D &vec1, const QCPVector2D &vec2) { return QCPVector2D(vec1.mX-vec2.mX, vec1.mY-vec2.mY); }
440inline const QCPVector2D operator-(const QCPVector2D &vec) { return QCPVector2D(-vec.mX, -vec.mY); }
441
442/*! \relates QCPVector2D
443
444 Prints \a vec in a human readable format to the qDebug output.
445*/
446inline QDebug operator<< (QDebug d, const QCPVector2D &vec)
447{
448 d.nospace() << "QCPVector2D(" << vec.x() << ", " << vec.y() << ")";
449 return d.space();
450}
451
452/* end of 'src/vector2d.h' */
453
454
455/* including file 'src/painter.h' */
456/* modified 2021-03-29T02:30:44, size 4035 */
457
458class QCP_LIB_DECL QCPPainter : public QPainter
459{
460 Q_GADGET
461public:
462 /*!
463 Defines special modes the painter can operate in. They disable or enable certain subsets of features/fixes/workarounds,
464 depending on whether they are wanted on the respective output device.
465 */
466 enum PainterMode { pmDefault = 0x00 ///< <tt>0x00</tt> Default mode for painting on screen devices
467 ,pmVectorized = 0x01 ///< <tt>0x01</tt> Mode for vectorized painting (e.g. PDF export). For example, this prevents some antialiasing fixes.
468 ,pmNoCaching = 0x02 ///< <tt>0x02</tt> Mode for all sorts of exports (e.g. PNG, PDF,...). For example, this prevents using cached pixmap labels
469 ,pmNonCosmetic = 0x04 ///< <tt>0x04</tt> Turns pen widths 0 to 1, i.e. disables cosmetic pens. (A cosmetic pen is always drawn with width 1 pixel in the vector image/pdf viewer, independent of zoom.)
470 };
471 Q_ENUMS(PainterMode)
472 Q_FLAGS(PainterModes)
473 Q_DECLARE_FLAGS(PainterModes, PainterMode)
474
475 QCPPainter();
476 explicit QCPPainter(QPaintDevice *device);
477
478 // getters:
479 bool antialiasing() const { return testRenderHint(QPainter::Antialiasing); }
480 PainterModes modes() const { return mModes; }
481
482 // setters:
483 void setAntialiasing(bool enabled);
484 void setMode(PainterMode mode, bool enabled=true);
485 void setModes(PainterModes modes);
486
487 // methods hiding non-virtual base class functions (QPainter bug workarounds):
488 bool begin(QPaintDevice *device);
489 void setPen(const QPen &pen);
490 void setPen(const QColor &color);
491 void setPen(Qt::PenStyle penStyle);
492 void drawLine(const QLineF &line);
493 void drawLine(const QPointF &p1, const QPointF &p2) {drawLine(QLineF(p1, p2));}
494 void save();
495 void restore();
496
497 // non-virtual methods:
498 void makeNonCosmetic();
499
500protected:
501 // property members:
502 PainterModes mModes;
503 bool mIsAntialiasing;
504
505 // non-property members:
506 QStack<bool> mAntialiasingStack;
507};
508Q_DECLARE_OPERATORS_FOR_FLAGS(QCPPainter::PainterModes)
509Q_DECLARE_METATYPE(QCPPainter::PainterMode)
510
511/* end of 'src/painter.h' */
512
513
514/* including file 'src/paintbuffer.h' */
515/* modified 2021-03-29T02:30:44, size 5006 */
516
517class QCP_LIB_DECL QCPAbstractPaintBuffer
518{
519public:
520 explicit QCPAbstractPaintBuffer(const QSize &size, double devicePixelRatio);
521 virtual ~QCPAbstractPaintBuffer();
522
523 // getters:
524 QSize size() const { return mSize; }
525 bool invalidated() const { return mInvalidated; }
526 double devicePixelRatio() const { return mDevicePixelRatio; }
527
528 // setters:
529 void setSize(const QSize &size);
530 void setInvalidated(bool invalidated=true);
531 void setDevicePixelRatio(double ratio);
532
533 // introduced virtual methods:
534 virtual QCPPainter *startPainting() = 0;
535 virtual void donePainting() {}
536 virtual void draw(QCPPainter *painter) const = 0;
537 virtual void clear(const QColor &color) = 0;
538
539protected:
540 // property members:
541 QSize mSize;
542 double mDevicePixelRatio;
543
544 // non-property members:
545 bool mInvalidated;
546
547 // introduced virtual methods:
548 virtual void reallocateBuffer() = 0;
549};
550
551
553{
554public:
555 explicit QCPPaintBufferPixmap(const QSize &size, double devicePixelRatio);
556 virtual ~QCPPaintBufferPixmap() Q_DECL_OVERRIDE;
557
558 // reimplemented virtual methods:
559 virtual QCPPainter *startPainting() Q_DECL_OVERRIDE;
560 virtual void draw(QCPPainter *painter) const Q_DECL_OVERRIDE;
561 void clear(const QColor &color) Q_DECL_OVERRIDE;
562
563protected:
564 // non-property members:
565 QPixmap mBuffer;
566
567 // reimplemented virtual methods:
568 virtual void reallocateBuffer() Q_DECL_OVERRIDE;
569};
570
571
572#ifdef QCP_OPENGL_PBUFFER
573class QCP_LIB_DECL QCPPaintBufferGlPbuffer : public QCPAbstractPaintBuffer
574{
575public:
576 explicit QCPPaintBufferGlPbuffer(const QSize &size, double devicePixelRatio, int multisamples);
577 virtual ~QCPPaintBufferGlPbuffer() Q_DECL_OVERRIDE;
578
579 // reimplemented virtual methods:
580 virtual QCPPainter *startPainting() Q_DECL_OVERRIDE;
581 virtual void draw(QCPPainter *painter) const Q_DECL_OVERRIDE;
582 void clear(const QColor &color) Q_DECL_OVERRIDE;
583
584protected:
585 // non-property members:
586 QGLPixelBuffer *mGlPBuffer;
587 int mMultisamples;
588
589 // reimplemented virtual methods:
590 virtual void reallocateBuffer() Q_DECL_OVERRIDE;
591};
592#endif // QCP_OPENGL_PBUFFER
593
594
595#ifdef QCP_OPENGL_FBO
596class QCP_LIB_DECL QCPPaintBufferGlFbo : public QCPAbstractPaintBuffer
597{
598public:
599 explicit QCPPaintBufferGlFbo(const QSize &size, double devicePixelRatio, QWeakPointer<QOpenGLContext> glContext, QWeakPointer<QOpenGLPaintDevice> glPaintDevice);
600 virtual ~QCPPaintBufferGlFbo() Q_DECL_OVERRIDE;
601
602 // reimplemented virtual methods:
603 virtual QCPPainter *startPainting() Q_DECL_OVERRIDE;
604 virtual void donePainting() Q_DECL_OVERRIDE;
605 virtual void draw(QCPPainter *painter) const Q_DECL_OVERRIDE;
606 void clear(const QColor &color) Q_DECL_OVERRIDE;
607
608protected:
609 // non-property members:
610 QWeakPointer<QOpenGLContext> mGlContext;
611 QWeakPointer<QOpenGLPaintDevice> mGlPaintDevice;
612 QOpenGLFramebufferObject *mGlFrameBuffer;
613
614 // reimplemented virtual methods:
615 virtual void reallocateBuffer() Q_DECL_OVERRIDE;
616};
617#endif // QCP_OPENGL_FBO
618
619/* end of 'src/paintbuffer.h' */
620
621
622/* including file 'src/layer.h' */
623/* modified 2021-03-29T02:30:44, size 7038 */
624
625class QCP_LIB_DECL QCPLayer : public QObject
626{
627 Q_OBJECT
628 /// \cond INCLUDE_QPROPERTIES
629 Q_PROPERTY(QCustomPlot* parentPlot READ parentPlot)
630 Q_PROPERTY(QString name READ name)
631 Q_PROPERTY(int index READ index)
632 Q_PROPERTY(QList<QCPLayerable*> children READ children)
633 Q_PROPERTY(bool visible READ visible WRITE setVisible)
634 Q_PROPERTY(LayerMode mode READ mode WRITE setMode)
635 /// \endcond
636public:
637
638 /*!
639 Defines the different rendering modes of a layer. Depending on the mode, certain layers can be
640 replotted individually, without the need to replot (possibly complex) layerables on other
641 layers.
642
643 \see setMode
644 */
645 enum LayerMode { lmLogical ///< Layer is used only for rendering order, and shares paint buffer with all other adjacent logical layers.
646 ,lmBuffered ///< Layer has its own paint buffer and may be replotted individually (see \ref replot).
647 };
648 Q_ENUMS(LayerMode)
649
650 QCPLayer(QCustomPlot* parentPlot, const QString &layerName);
651 virtual ~QCPLayer();
652
653 // getters:
654 QCustomPlot *parentPlot() const { return mParentPlot; }
655 QString name() const { return mName; }
656 int index() const { return mIndex; }
657 QList<QCPLayerable*> children() const { return mChildren; }
658 bool visible() const { return mVisible; }
659 LayerMode mode() const { return mMode; }
660
661 // setters:
662 void setVisible(bool visible);
663 void setMode(LayerMode mode);
664
665 // non-virtual methods:
666 void replot();
667
668protected:
669 // property members:
670 QCustomPlot *mParentPlot;
671 QString mName;
672 int mIndex;
673 QList<QCPLayerable*> mChildren;
674 bool mVisible;
675 LayerMode mMode;
676
677 // non-property members:
679
680 // non-virtual methods:
681 void draw(QCPPainter *painter);
682 void drawToPaintBuffer();
683 void addChild(QCPLayerable *layerable, bool prepend);
684 void removeChild(QCPLayerable *layerable);
685
686private:
687 Q_DISABLE_COPY(QCPLayer)
688
689 friend class QCustomPlot;
690 friend class QCPLayerable;
691};
692Q_DECLARE_METATYPE(QCPLayer::LayerMode)
693
694class QCP_LIB_DECL QCPLayerable : public QObject
695{
696 Q_OBJECT
697 /// \cond INCLUDE_QPROPERTIES
698 Q_PROPERTY(bool visible READ visible WRITE setVisible)
699 Q_PROPERTY(QCustomPlot* parentPlot READ parentPlot)
700 Q_PROPERTY(QCPLayerable* parentLayerable READ parentLayerable)
701 Q_PROPERTY(QCPLayer* layer READ layer WRITE setLayer NOTIFY layerChanged)
702 Q_PROPERTY(bool antialiased READ antialiased WRITE setAntialiased)
703 /// \endcond
704public:
705 QCPLayerable(QCustomPlot *plot, QString targetLayer=QString(), QCPLayerable *parentLayerable=nullptr);
706 virtual ~QCPLayerable();
707
708 // getters:
709 bool visible() const { return mVisible; }
710 QCustomPlot *parentPlot() const { return mParentPlot; }
711 QCPLayerable *parentLayerable() const { return mParentLayerable.data(); }
712 QCPLayer *layer() const { return mLayer; }
713 bool antialiased() const { return mAntialiased; }
714
715 // setters:
716 void setVisible(bool on);
717 Q_SLOT bool setLayer(QCPLayer *layer);
718 bool setLayer(const QString &layerName);
719 void setAntialiased(bool enabled);
720
721 // introduced virtual methods:
722 virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const;
723
724 // non-property methods:
725 bool realVisibility() const;
726
727signals:
728 void layerChanged(QCPLayer *newLayer);
729
730protected:
731 // property members:
732 bool mVisible;
733 QCustomPlot *mParentPlot;
734 QPointer<QCPLayerable> mParentLayerable;
735 QCPLayer *mLayer;
736 bool mAntialiased;
737
738 // introduced virtual methods:
739 virtual void parentPlotInitialized(QCustomPlot *parentPlot);
740 virtual QCP::Interaction selectionCategory() const;
741 virtual QRect clipRect() const;
742 virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const = 0;
743 virtual void draw(QCPPainter *painter) = 0;
744 // selection events:
745 virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged);
746 virtual void deselectEvent(bool *selectionStateChanged);
747 // low-level mouse events:
748 virtual void mousePressEvent(QMouseEvent *event, const QVariant &details);
749 virtual void mouseMoveEvent(QMouseEvent *event, const QPointF &startPos);
750 virtual void mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos);
751 virtual void mouseDoubleClickEvent(QMouseEvent *event, const QVariant &details);
752 virtual void wheelEvent(QWheelEvent *event);
753
754 // non-property methods:
755 void initializeParentPlot(QCustomPlot *parentPlot);
756 void setParentLayerable(QCPLayerable* parentLayerable);
757 bool moveToLayer(QCPLayer *layer, bool prepend);
758 void applyAntialiasingHint(QCPPainter *painter, bool localAntialiased, QCP::AntialiasedElement overrideElement) const;
759
760private:
761 Q_DISABLE_COPY(QCPLayerable)
762
763 friend class QCustomPlot;
764 friend class QCPLayer;
765 friend class QCPAxisRect;
766};
767
768/* end of 'src/layer.h' */
769
770
771/* including file 'src/axis/range.h' */
772/* modified 2021-03-29T02:30:44, size 5280 */
773
774class QCP_LIB_DECL QCPRange
775{
776public:
777 double lower, upper;
778
779 QCPRange();
780 QCPRange(double lower, double upper);
781
782 bool operator==(const QCPRange& other) const { return lower == other.lower && upper == other.upper; }
783 bool operator!=(const QCPRange& other) const { return !(*this == other); }
784
785 QCPRange &operator+=(const double& value) { lower+=value; upper+=value; return *this; }
786 QCPRange &operator-=(const double& value) { lower-=value; upper-=value; return *this; }
787 QCPRange &operator*=(const double& value) { lower*=value; upper*=value; return *this; }
788 QCPRange &operator/=(const double& value) { lower/=value; upper/=value; return *this; }
789 friend inline const QCPRange operator+(const QCPRange&, double);
790 friend inline const QCPRange operator+(double, const QCPRange&);
791 friend inline const QCPRange operator-(const QCPRange& range, double value);
792 friend inline const QCPRange operator*(const QCPRange& range, double value);
793 friend inline const QCPRange operator*(double value, const QCPRange& range);
794 friend inline const QCPRange operator/(const QCPRange& range, double value);
795
796 double size() const { return upper-lower; }
797 double center() const { return (upper+lower)*0.5; }
798 void normalize() { if (lower > upper) qSwap(lower, upper); }
799 void expand(const QCPRange &otherRange);
800 void expand(double includeCoord);
801 QCPRange expanded(const QCPRange &otherRange) const;
802 QCPRange expanded(double includeCoord) const;
803 QCPRange bounded(double lowerBound, double upperBound) const;
804 QCPRange sanitizedForLogScale() const;
805 QCPRange sanitizedForLinScale() const;
806 bool contains(double value) const { return value >= lower && value <= upper; }
807
808 static bool validRange(double lower, double upper);
809 static bool validRange(const QCPRange &range);
810 static const double minRange;
811 static const double maxRange;
812
813};
814Q_DECLARE_TYPEINFO(QCPRange, Q_MOVABLE_TYPE);
815
816/*! \relates QCPRange
817
818 Prints \a range in a human readable format to the qDebug output.
819*/
820inline QDebug operator<< (QDebug d, const QCPRange &range)
821{
822 d.nospace() << "QCPRange(" << range.lower << ", " << range.upper << ")";
823 return d.space();
824}
825
826/*!
827 Adds \a value to both boundaries of the range.
828*/
829inline const QCPRange operator+(const QCPRange& range, double value)
830{
831 QCPRange result(range);
832 result += value;
833 return result;
834}
835
836/*!
837 Adds \a value to both boundaries of the range.
838*/
839inline const QCPRange operator+(double value, const QCPRange& range)
840{
841 QCPRange result(range);
842 result += value;
843 return result;
844}
845
846/*!
847 Subtracts \a value from both boundaries of the range.
848*/
849inline const QCPRange operator-(const QCPRange& range, double value)
850{
851 QCPRange result(range);
852 result -= value;
853 return result;
854}
855
856/*!
857 Multiplies both boundaries of the range by \a value.
858*/
859inline const QCPRange operator*(const QCPRange& range, double value)
860{
861 QCPRange result(range);
862 result *= value;
863 return result;
864}
865
866/*!
867 Multiplies both boundaries of the range by \a value.
868*/
869inline const QCPRange operator*(double value, const QCPRange& range)
870{
871 QCPRange result(range);
872 result *= value;
873 return result;
874}
875
876/*!
877 Divides both boundaries of the range by \a value.
878*/
879inline const QCPRange operator/(const QCPRange& range, double value)
880{
881 QCPRange result(range);
882 result /= value;
883 return result;
884}
885
886/* end of 'src/axis/range.h' */
887
888
889/* including file 'src/selection.h' */
890/* modified 2021-03-29T02:30:44, size 8569 */
891
892class QCP_LIB_DECL QCPDataRange
893{
894public:
895 QCPDataRange();
896 QCPDataRange(int begin, int end);
897
898 bool operator==(const QCPDataRange& other) const { return mBegin == other.mBegin && mEnd == other.mEnd; }
899 bool operator!=(const QCPDataRange& other) const { return !(*this == other); }
900
901 // getters:
902 int begin() const { return mBegin; }
903 int end() const { return mEnd; }
904 int size() const { return mEnd-mBegin; }
905 int length() const { return size(); }
906
907 // setters:
908 void setBegin(int begin) { mBegin = begin; }
909 void setEnd(int end) { mEnd = end; }
910
911 // non-property methods:
912 bool isValid() const { return (mEnd >= mBegin) && (mBegin >= 0); }
913 bool isEmpty() const { return length() == 0; }
914 QCPDataRange bounded(const QCPDataRange &other) const;
915 QCPDataRange expanded(const QCPDataRange &other) const;
916 QCPDataRange intersection(const QCPDataRange &other) const;
917 QCPDataRange adjusted(int changeBegin, int changeEnd) const { return QCPDataRange(mBegin+changeBegin, mEnd+changeEnd); }
918 bool intersects(const QCPDataRange &other) const;
919 bool contains(const QCPDataRange &other) const;
920
921private:
922 // property members:
923 int mBegin, mEnd;
924
925};
926Q_DECLARE_TYPEINFO(QCPDataRange, Q_MOVABLE_TYPE);
927
928
929class QCP_LIB_DECL QCPDataSelection
930{
931public:
932 explicit QCPDataSelection();
933 explicit QCPDataSelection(const QCPDataRange &range);
934
935 bool operator==(const QCPDataSelection& other) const;
936 bool operator!=(const QCPDataSelection& other) const { return !(*this == other); }
937 QCPDataSelection &operator+=(const QCPDataSelection& other);
938 QCPDataSelection &operator+=(const QCPDataRange& other);
939 QCPDataSelection &operator-=(const QCPDataSelection& other);
940 QCPDataSelection &operator-=(const QCPDataRange& other);
941 friend inline const QCPDataSelection operator+(const QCPDataSelection& a, const QCPDataSelection& b);
942 friend inline const QCPDataSelection operator+(const QCPDataRange& a, const QCPDataSelection& b);
943 friend inline const QCPDataSelection operator+(const QCPDataSelection& a, const QCPDataRange& b);
944 friend inline const QCPDataSelection operator+(const QCPDataRange& a, const QCPDataRange& b);
945 friend inline const QCPDataSelection operator-(const QCPDataSelection& a, const QCPDataSelection& b);
946 friend inline const QCPDataSelection operator-(const QCPDataRange& a, const QCPDataSelection& b);
947 friend inline const QCPDataSelection operator-(const QCPDataSelection& a, const QCPDataRange& b);
948 friend inline const QCPDataSelection operator-(const QCPDataRange& a, const QCPDataRange& b);
949
950 // getters:
951 int dataRangeCount() const { return mDataRanges.size(); }
952 int dataPointCount() const;
953 QCPDataRange dataRange(int index=0) const;
954 QList<QCPDataRange> dataRanges() const { return mDataRanges; }
955 QCPDataRange span() const;
956
957 // non-property methods:
958 void addDataRange(const QCPDataRange &dataRange, bool simplify=true);
959 void clear();
960 bool isEmpty() const { return mDataRanges.isEmpty(); }
961 void simplify();
962 void enforceType(QCP::SelectionType type);
963 bool contains(const QCPDataSelection &other) const;
964 QCPDataSelection intersection(const QCPDataRange &other) const;
965 QCPDataSelection intersection(const QCPDataSelection &other) const;
966 QCPDataSelection inverse(const QCPDataRange &outerRange) const;
967
968private:
969 // property members:
970 QList<QCPDataRange> mDataRanges;
971
972 inline static bool lessThanDataRangeBegin(const QCPDataRange &a, const QCPDataRange &b) { return a.begin() < b.begin(); }
973};
974Q_DECLARE_METATYPE(QCPDataSelection)
975
976
977/*!
978 Return a \ref QCPDataSelection with the data points in \a a joined with the data points in \a b.
979 The resulting data selection is already simplified (see \ref QCPDataSelection::simplify).
980*/
981inline const QCPDataSelection operator+(const QCPDataSelection& a, const QCPDataSelection& b)
982{
983 QCPDataSelection result(a);
984 result += b;
985 return result;
986}
987
988/*!
989 Return a \ref QCPDataSelection with the data points in \a a joined with the data points in \a b.
990 The resulting data selection is already simplified (see \ref QCPDataSelection::simplify).
991*/
992inline const QCPDataSelection operator+(const QCPDataRange& a, const QCPDataSelection& b)
993{
994 QCPDataSelection result(a);
995 result += b;
996 return result;
997}
998
999/*!
1000 Return a \ref QCPDataSelection with the data points in \a a joined with the data points in \a b.
1001 The resulting data selection is already simplified (see \ref QCPDataSelection::simplify).
1002*/
1003inline const QCPDataSelection operator+(const QCPDataSelection& a, const QCPDataRange& b)
1004{
1005 QCPDataSelection result(a);
1006 result += b;
1007 return result;
1008}
1009
1010/*!
1011 Return a \ref QCPDataSelection with the data points in \a a joined with the data points in \a b.
1012 The resulting data selection is already simplified (see \ref QCPDataSelection::simplify).
1013*/
1014inline const QCPDataSelection operator+(const QCPDataRange& a, const QCPDataRange& b)
1015{
1016 QCPDataSelection result(a);
1017 result += b;
1018 return result;
1019}
1020
1021/*!
1022 Return a \ref QCPDataSelection with the data points which are in \a a but not in \a b.
1023*/
1024inline const QCPDataSelection operator-(const QCPDataSelection& a, const QCPDataSelection& b)
1025{
1026 QCPDataSelection result(a);
1027 result -= b;
1028 return result;
1029}
1030
1031/*!
1032 Return a \ref QCPDataSelection with the data points which are in \a a but not in \a b.
1033*/
1034inline const QCPDataSelection operator-(const QCPDataRange& a, const QCPDataSelection& b)
1035{
1036 QCPDataSelection result(a);
1037 result -= b;
1038 return result;
1039}
1040
1041/*!
1042 Return a \ref QCPDataSelection with the data points which are in \a a but not in \a b.
1043*/
1044inline const QCPDataSelection operator-(const QCPDataSelection& a, const QCPDataRange& b)
1045{
1046 QCPDataSelection result(a);
1047 result -= b;
1048 return result;
1049}
1050
1051/*!
1052 Return a \ref QCPDataSelection with the data points which are in \a a but not in \a b.
1053*/
1054inline const QCPDataSelection operator-(const QCPDataRange& a, const QCPDataRange& b)
1055{
1056 QCPDataSelection result(a);
1057 result -= b;
1058 return result;
1059}
1060
1061/*! \relates QCPDataRange
1062
1063 Prints \a dataRange in a human readable format to the qDebug output.
1064*/
1065inline QDebug operator<< (QDebug d, const QCPDataRange &dataRange)
1066{
1067 d.nospace() << "QCPDataRange(" << dataRange.begin() << ", " << dataRange.end() << ")";
1068 return d;
1069}
1070
1071/*! \relates QCPDataSelection
1072
1073 Prints \a selection in a human readable format to the qDebug output.
1074*/
1075inline QDebug operator<< (QDebug d, const QCPDataSelection &selection)
1076{
1077 d.nospace() << "QCPDataSelection(";
1078 for (int i=0; i<selection.dataRangeCount(); ++i)
1079 {
1080 if (i != 0)
1081 d << ", ";
1082 d << selection.dataRange(i);
1083 }
1084 d << ")";
1085 return d;
1086}
1087
1088
1089
1090/* end of 'src/selection.h' */
1091
1092
1093/* including file 'src/selectionrect.h' */
1094/* modified 2021-03-29T02:30:44, size 3354 */
1095
1096class QCP_LIB_DECL QCPSelectionRect : public QCPLayerable
1097{
1098 Q_OBJECT
1099public:
1100 explicit QCPSelectionRect(QCustomPlot *parentPlot);
1101 virtual ~QCPSelectionRect() Q_DECL_OVERRIDE;
1102
1103 // getters:
1104 QRect rect() const { return mRect; }
1105 QCPRange range(const QCPAxis *axis) const;
1106 QPen pen() const { return mPen; }
1107 QBrush brush() const { return mBrush; }
1108 bool isActive() const { return mActive; }
1109
1110 // setters:
1111 void setPen(const QPen &pen);
1112 void setBrush(const QBrush &brush);
1113
1114 // non-property methods:
1115 Q_SLOT void cancel();
1116
1117signals:
1118 void started(QMouseEvent *event);
1119 void changed(const QRect &rect, QMouseEvent *event);
1120 void canceled(const QRect &rect, QInputEvent *event);
1121 void accepted(const QRect &rect, QMouseEvent *event);
1122
1123protected:
1124 // property members:
1125 QRect mRect;
1126 QPen mPen;
1127 QBrush mBrush;
1128 // non-property members:
1129 bool mActive;
1130
1131 // introduced virtual methods:
1132 virtual void startSelection(QMouseEvent *event);
1133 virtual void moveSelection(QMouseEvent *event);
1134 virtual void endSelection(QMouseEvent *event);
1135 virtual void keyPressEvent(QKeyEvent *event);
1136
1137 // reimplemented virtual methods
1138 virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE;
1139 virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE;
1140
1141 friend class QCustomPlot;
1142};
1143
1144/* end of 'src/selectionrect.h' */
1145
1146
1147/* including file 'src/layout.h' */
1148/* modified 2021-03-29T02:30:44, size 14279 */
1149
1150class QCP_LIB_DECL QCPMarginGroup : public QObject
1151{
1152 Q_OBJECT
1153public:
1154 explicit QCPMarginGroup(QCustomPlot *parentPlot);
1155 virtual ~QCPMarginGroup();
1156
1157 // non-virtual methods:
1158 QList<QCPLayoutElement*> elements(QCP::MarginSide side) const { return mChildren.value(side); }
1159 bool isEmpty() const;
1160 void clear();
1161
1162protected:
1163 // non-property members:
1164 QCustomPlot *mParentPlot;
1166
1167 // introduced virtual methods:
1168 virtual int commonMargin(QCP::MarginSide side) const;
1169
1170 // non-virtual methods:
1171 void addChild(QCP::MarginSide side, QCPLayoutElement *element);
1172 void removeChild(QCP::MarginSide side, QCPLayoutElement *element);
1173
1174private:
1175 Q_DISABLE_COPY(QCPMarginGroup)
1176
1177 friend class QCPLayoutElement;
1178};
1179
1180
1181class QCP_LIB_DECL QCPLayoutElement : public QCPLayerable
1182{
1183 Q_OBJECT
1184 /// \cond INCLUDE_QPROPERTIES
1185 Q_PROPERTY(QCPLayout* layout READ layout)
1186 Q_PROPERTY(QRect rect READ rect)
1187 Q_PROPERTY(QRect outerRect READ outerRect WRITE setOuterRect)
1188 Q_PROPERTY(QMargins margins READ margins WRITE setMargins)
1189 Q_PROPERTY(QMargins minimumMargins READ minimumMargins WRITE setMinimumMargins)
1190 Q_PROPERTY(QSize minimumSize READ minimumSize WRITE setMinimumSize)
1191 Q_PROPERTY(QSize maximumSize READ maximumSize WRITE setMaximumSize)
1192 Q_PROPERTY(SizeConstraintRect sizeConstraintRect READ sizeConstraintRect WRITE setSizeConstraintRect)
1193 /// \endcond
1194public:
1195 /*!
1196 Defines the phases of the update process, that happens just before a replot. At each phase,
1197 \ref update is called with the according UpdatePhase value.
1198 */
1199 enum UpdatePhase { upPreparation ///< Phase used for any type of preparation that needs to be done before margin calculation and layout
1200 ,upMargins ///< Phase in which the margins are calculated and set
1201 ,upLayout ///< Final phase in which the layout system places the rects of the elements
1203 Q_ENUMS(UpdatePhase)
1204
1205 /*!
1206 Defines to which rect of a layout element the size constraints that can be set via \ref
1207 setMinimumSize and \ref setMaximumSize apply. The outer rect (\ref outerRect) includes the
1208 margins (e.g. in the case of a QCPAxisRect the axis labels), whereas the inner rect (\ref rect)
1209 does not.
1210
1211 \see setSizeConstraintRect
1212 */
1213 enum SizeConstraintRect { scrInnerRect ///< Minimum/Maximum size constraints apply to inner rect
1214 , scrOuterRect ///< Minimum/Maximum size constraints apply to outer rect, thus include layout element margins
1216 Q_ENUMS(SizeConstraintRect)
1217
1218 explicit QCPLayoutElement(QCustomPlot *parentPlot=nullptr);
1219 virtual ~QCPLayoutElement() Q_DECL_OVERRIDE;
1220
1221 // getters:
1222 QCPLayout *layout() const { return mParentLayout; }
1223 QRect rect() const { return mRect; }
1224 QRect outerRect() const { return mOuterRect; }
1225 QMargins margins() const { return mMargins; }
1226 QMargins minimumMargins() const { return mMinimumMargins; }
1227 QCP::MarginSides autoMargins() const { return mAutoMargins; }
1228 QSize minimumSize() const { return mMinimumSize; }
1229 QSize maximumSize() const { return mMaximumSize; }
1230 SizeConstraintRect sizeConstraintRect() const { return mSizeConstraintRect; }
1231 QCPMarginGroup *marginGroup(QCP::MarginSide side) const { return mMarginGroups.value(side, nullptr); }
1232 QHash<QCP::MarginSide, QCPMarginGroup*> marginGroups() const { return mMarginGroups; }
1233
1234 // setters:
1235 void setOuterRect(const QRect &rect);
1236 void setMargins(const QMargins &margins);
1237 void setMinimumMargins(const QMargins &margins);
1238 void setAutoMargins(QCP::MarginSides sides);
1239 void setMinimumSize(const QSize &size);
1240 void setMinimumSize(int width, int height);
1241 void setMaximumSize(const QSize &size);
1242 void setMaximumSize(int width, int height);
1243 void setSizeConstraintRect(SizeConstraintRect constraintRect);
1244 void setMarginGroup(QCP::MarginSides sides, QCPMarginGroup *group);
1245
1246 // introduced virtual methods:
1247 virtual void update(UpdatePhase phase);
1248 virtual QSize minimumOuterSizeHint() const;
1249 virtual QSize maximumOuterSizeHint() const;
1250 virtual QList<QCPLayoutElement*> elements(bool recursive) const;
1251
1252 // reimplemented virtual methods:
1253 virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE;
1254
1255protected:
1256 // property members:
1257 QCPLayout *mParentLayout;
1258 QSize mMinimumSize, mMaximumSize;
1259 SizeConstraintRect mSizeConstraintRect;
1260 QRect mRect, mOuterRect;
1261 QMargins mMargins, mMinimumMargins;
1262 QCP::MarginSides mAutoMargins;
1263 QHash<QCP::MarginSide, QCPMarginGroup*> mMarginGroups;
1264
1265 // introduced virtual methods:
1266 virtual int calculateAutoMargin(QCP::MarginSide side);
1267 virtual void layoutChanged();
1268
1269 // reimplemented virtual methods:
1270 virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE { Q_UNUSED(painter) }
1271 virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE { Q_UNUSED(painter) }
1272 virtual void parentPlotInitialized(QCustomPlot *parentPlot) Q_DECL_OVERRIDE;
1273
1274private:
1275 Q_DISABLE_COPY(QCPLayoutElement)
1276
1277 friend class QCustomPlot;
1278 friend class QCPLayout;
1279 friend class QCPMarginGroup;
1280};
1281Q_DECLARE_METATYPE(QCPLayoutElement::UpdatePhase)
1282
1283
1284class QCP_LIB_DECL QCPLayout : public QCPLayoutElement
1285{
1286 Q_OBJECT
1287public:
1288 explicit QCPLayout();
1289
1290 // reimplemented virtual methods:
1291 virtual void update(UpdatePhase phase) Q_DECL_OVERRIDE;
1292 virtual QList<QCPLayoutElement*> elements(bool recursive) const Q_DECL_OVERRIDE;
1293
1294 // introduced virtual methods:
1295 virtual int elementCount() const = 0;
1296 virtual QCPLayoutElement* elementAt(int index) const = 0;
1297 virtual QCPLayoutElement* takeAt(int index) = 0;
1298 virtual bool take(QCPLayoutElement* element) = 0;
1299 virtual void simplify();
1300
1301 // non-virtual methods:
1302 bool removeAt(int index);
1303 bool remove(QCPLayoutElement* element);
1304 void clear();
1305
1306protected:
1307 // introduced virtual methods:
1308 virtual void updateLayout();
1309
1310 // non-virtual methods:
1311 void sizeConstraintsChanged() const;
1312 void adoptElement(QCPLayoutElement *el);
1313 void releaseElement(QCPLayoutElement *el);
1314 QVector<int> getSectionSizes(QVector<int> maxSizes, QVector<int> minSizes, QVector<double> stretchFactors, int totalSize) const;
1315 static QSize getFinalMinimumOuterSize(const QCPLayoutElement *el);
1316 static QSize getFinalMaximumOuterSize(const QCPLayoutElement *el);
1317
1318private:
1319 Q_DISABLE_COPY(QCPLayout)
1320 friend class QCPLayoutElement;
1321};
1322
1323
1324class QCP_LIB_DECL QCPLayoutGrid : public QCPLayout
1325{
1326 Q_OBJECT
1327 /// \cond INCLUDE_QPROPERTIES
1328 Q_PROPERTY(int rowCount READ rowCount)
1329 Q_PROPERTY(int columnCount READ columnCount)
1330 Q_PROPERTY(QList<double> columnStretchFactors READ columnStretchFactors WRITE setColumnStretchFactors)
1331 Q_PROPERTY(QList<double> rowStretchFactors READ rowStretchFactors WRITE setRowStretchFactors)
1332 Q_PROPERTY(int columnSpacing READ columnSpacing WRITE setColumnSpacing)
1333 Q_PROPERTY(int rowSpacing READ rowSpacing WRITE setRowSpacing)
1334 Q_PROPERTY(FillOrder fillOrder READ fillOrder WRITE setFillOrder)
1335 Q_PROPERTY(int wrap READ wrap WRITE setWrap)
1336 /// \endcond
1337public:
1338
1339 /*!
1340 Defines in which direction the grid is filled when using \ref addElement(QCPLayoutElement*).
1341 The column/row at which wrapping into the next row/column occurs can be specified with \ref
1342 setWrap.
1343
1344 \see setFillOrder
1345 */
1346 enum FillOrder { foRowsFirst ///< Rows are filled first, and a new element is wrapped to the next column if the row count would exceed \ref setWrap.
1347 ,foColumnsFirst ///< Columns are filled first, and a new element is wrapped to the next row if the column count would exceed \ref setWrap.
1349 Q_ENUMS(FillOrder)
1350
1351 explicit QCPLayoutGrid();
1352 virtual ~QCPLayoutGrid() Q_DECL_OVERRIDE;
1353
1354 // getters:
1355 int rowCount() const { return mElements.size(); }
1356 int columnCount() const { return mElements.size() > 0 ? mElements.first().size() : 0; }
1357 QList<double> columnStretchFactors() const { return mColumnStretchFactors; }
1358 QList<double> rowStretchFactors() const { return mRowStretchFactors; }
1359 int columnSpacing() const { return mColumnSpacing; }
1360 int rowSpacing() const { return mRowSpacing; }
1361 int wrap() const { return mWrap; }
1362 FillOrder fillOrder() const { return mFillOrder; }
1363
1364 // setters:
1365 void setColumnStretchFactor(int column, double factor);
1366 void setColumnStretchFactors(const QList<double> &factors);
1367 void setRowStretchFactor(int row, double factor);
1368 void setRowStretchFactors(const QList<double> &factors);
1369 void setColumnSpacing(int pixels);
1370 void setRowSpacing(int pixels);
1371 void setWrap(int count);
1372 void setFillOrder(FillOrder order, bool rearrange=true);
1373
1374 // reimplemented virtual methods:
1375 virtual void updateLayout() Q_DECL_OVERRIDE;
1376 virtual int elementCount() const Q_DECL_OVERRIDE { return rowCount()*columnCount(); }
1377 virtual QCPLayoutElement* elementAt(int index) const Q_DECL_OVERRIDE;
1378 virtual QCPLayoutElement* takeAt(int index) Q_DECL_OVERRIDE;
1379 virtual bool take(QCPLayoutElement* element) Q_DECL_OVERRIDE;
1380 virtual QList<QCPLayoutElement*> elements(bool recursive) const Q_DECL_OVERRIDE;
1381 virtual void simplify() Q_DECL_OVERRIDE;
1382 virtual QSize minimumOuterSizeHint() const Q_DECL_OVERRIDE;
1383 virtual QSize maximumOuterSizeHint() const Q_DECL_OVERRIDE;
1384
1385 // non-virtual methods:
1386 QCPLayoutElement *element(int row, int column) const;
1387 bool addElement(int row, int column, QCPLayoutElement *element);
1388 bool addElement(QCPLayoutElement *element);
1389 bool hasElement(int row, int column);
1390 void expandTo(int newRowCount, int newColumnCount);
1391 void insertRow(int newIndex);
1392 void insertColumn(int newIndex);
1393 int rowColToIndex(int row, int column) const;
1394 void indexToRowCol(int index, int &row, int &column) const;
1395
1396protected:
1397 // property members:
1398 QList<QList<QCPLayoutElement*> > mElements;
1399 QList<double> mColumnStretchFactors;
1400 QList<double> mRowStretchFactors;
1401 int mColumnSpacing, mRowSpacing;
1402 int mWrap;
1403 FillOrder mFillOrder;
1404
1405 // non-virtual methods:
1406 void getMinimumRowColSizes(QVector<int> *minColWidths, QVector<int> *minRowHeights) const;
1407 void getMaximumRowColSizes(QVector<int> *maxColWidths, QVector<int> *maxRowHeights) const;
1408
1409private:
1410 Q_DISABLE_COPY(QCPLayoutGrid)
1411};
1412Q_DECLARE_METATYPE(QCPLayoutGrid::FillOrder)
1413
1414
1415class QCP_LIB_DECL QCPLayoutInset : public QCPLayout
1416{
1417 Q_OBJECT
1418public:
1419 /*!
1420 Defines how the placement and sizing is handled for a certain element in a QCPLayoutInset.
1421 */
1422 enum InsetPlacement { ipFree ///< The element may be positioned/sized arbitrarily, see \ref setInsetRect
1423 ,ipBorderAligned ///< The element is aligned to one of the layout sides, see \ref setInsetAlignment
1425 Q_ENUMS(InsetPlacement)
1426
1427 explicit QCPLayoutInset();
1428 virtual ~QCPLayoutInset() Q_DECL_OVERRIDE;
1429
1430 // getters:
1431 InsetPlacement insetPlacement(int index) const;
1432 Qt::Alignment insetAlignment(int index) const;
1433 QRectF insetRect(int index) const;
1434
1435 // setters:
1436 void setInsetPlacement(int index, InsetPlacement placement);
1437 void setInsetAlignment(int index, Qt::Alignment alignment);
1438 void setInsetRect(int index, const QRectF &rect);
1439
1440 // reimplemented virtual methods:
1441 virtual void updateLayout() Q_DECL_OVERRIDE;
1442 virtual int elementCount() const Q_DECL_OVERRIDE;
1443 virtual QCPLayoutElement* elementAt(int index) const Q_DECL_OVERRIDE;
1444 virtual QCPLayoutElement* takeAt(int index) Q_DECL_OVERRIDE;
1445 virtual bool take(QCPLayoutElement* element) Q_DECL_OVERRIDE;
1446 virtual void simplify() Q_DECL_OVERRIDE {}
1447 virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE;
1448
1449 // non-virtual methods:
1450 void addElement(QCPLayoutElement *element, Qt::Alignment alignment);
1451 void addElement(QCPLayoutElement *element, const QRectF &rect);
1452
1453protected:
1454 // property members:
1455 QList<QCPLayoutElement*> mElements;
1456 QList<InsetPlacement> mInsetPlacement;
1457 QList<Qt::Alignment> mInsetAlignment;
1458 QList<QRectF> mInsetRect;
1459
1460private:
1461 Q_DISABLE_COPY(QCPLayoutInset)
1462};
1463Q_DECLARE_METATYPE(QCPLayoutInset::InsetPlacement)
1464
1465/* end of 'src/layout.h' */
1466
1467
1468/* including file 'src/lineending.h' */
1469/* modified 2021-03-29T02:30:44, size 4426 */
1470
1471class QCP_LIB_DECL QCPLineEnding
1472{
1473 Q_GADGET
1474public:
1475 /*!
1476 Defines the type of ending decoration for line-like items, e.g. an arrow.
1477
1478 \image html QCPLineEnding.png
1479
1480 The width and length of these decorations can be controlled with the functions \ref setWidth
1481 and \ref setLength. Some decorations like \ref esDisc, \ref esSquare, \ref esDiamond and \ref esBar only
1482 support a width, the length property is ignored.
1483
1484 \see QCPItemLine::setHead, QCPItemLine::setTail, QCPItemCurve::setHead, QCPItemCurve::setTail, QCPAxis::setLowerEnding, QCPAxis::setUpperEnding
1485 */
1486 enum EndingStyle { esNone ///< No ending decoration
1487 ,esFlatArrow ///< A filled arrow head with a straight/flat back (a triangle)
1488 ,esSpikeArrow ///< A filled arrow head with an indented back
1489 ,esLineArrow ///< A non-filled arrow head with open back
1490 ,esDisc ///< A filled circle
1491 ,esSquare ///< A filled square
1492 ,esDiamond ///< A filled diamond (45 degrees rotated square)
1493 ,esBar ///< A bar perpendicular to the line
1494 ,esHalfBar ///< A bar perpendicular to the line, pointing out to only one side (to which side can be changed with \ref setInverted)
1495 ,esSkewedBar ///< A bar that is skewed (skew controllable via \ref setLength)
1497 Q_ENUMS(EndingStyle)
1498
1499 QCPLineEnding();
1500 QCPLineEnding(EndingStyle style, double width=8, double length=10, bool inverted=false);
1501
1502 // getters:
1503 EndingStyle style() const { return mStyle; }
1504 double width() const { return mWidth; }
1505 double length() const { return mLength; }
1506 bool inverted() const { return mInverted; }
1507
1508 // setters:
1509 void setStyle(EndingStyle style);
1510 void setWidth(double width);
1511 void setLength(double length);
1512 void setInverted(bool inverted);
1513
1514 // non-property methods:
1515 double boundingDistance() const;
1516 double realLength() const;
1517 void draw(QCPPainter *painter, const QCPVector2D &pos, const QCPVector2D &dir) const;
1518 void draw(QCPPainter *painter, const QCPVector2D &pos, double angle) const;
1519
1520protected:
1521 // property members:
1522 EndingStyle mStyle;
1523 double mWidth, mLength;
1524 bool mInverted;
1525};
1526Q_DECLARE_TYPEINFO(QCPLineEnding, Q_MOVABLE_TYPE);
1527Q_DECLARE_METATYPE(QCPLineEnding::EndingStyle)
1528
1529/* end of 'src/lineending.h' */
1530
1531
1532/* including file 'src/axis/labelpainter.h' */
1533/* modified 2021-03-29T02:30:44, size 7086 */
1534
1536{
1537 Q_GADGET
1538public:
1539 /*!
1540 TODO
1541 */
1542 enum AnchorMode { amRectangular ///<
1543 ,amSkewedUpright ///<
1544 ,amSkewedRotated ///<
1545 };
1546 Q_ENUMS(AnchorMode)
1547
1548 /*!
1549 TODO
1550 */
1551 enum AnchorReferenceType { artNormal ///<
1552 ,artTangent ///<
1553 };
1554 Q_ENUMS(AnchorReferenceType)
1555
1556 /*!
1557 TODO
1558 */
1559 enum AnchorSide { asLeft ///<
1560 ,asRight ///<
1561 ,asTop ///<
1562 ,asBottom ///<
1563 ,asTopLeft
1564 ,asTopRight
1565 ,asBottomRight
1566 ,asBottomLeft
1567 };
1568 Q_ENUMS(AnchorSide)
1569
1570 explicit QCPLabelPainterPrivate(QCustomPlot *parentPlot);
1571 virtual ~QCPLabelPainterPrivate();
1572
1573 // setters:
1574 void setAnchorSide(AnchorSide side);
1575 void setAnchorMode(AnchorMode mode);
1576 void setAnchorReference(const QPointF &pixelPoint);
1577 void setAnchorReferenceType(AnchorReferenceType type);
1578 void setFont(const QFont &font);
1579 void setColor(const QColor &color);
1580 void setPadding(int padding);
1581 void setRotation(double rotation);
1582 void setSubstituteExponent(bool enabled);
1583 void setMultiplicationSymbol(QChar symbol);
1584 void setAbbreviateDecimalPowers(bool enabled);
1585 void setCacheSize(int labelCount);
1586
1587 // getters:
1588 AnchorMode anchorMode() const { return mAnchorMode; }
1589 AnchorSide anchorSide() const { return mAnchorSide; }
1590 QPointF anchorReference() const { return mAnchorReference; }
1591 AnchorReferenceType anchorReferenceType() const { return mAnchorReferenceType; }
1592 QFont font() const { return mFont; }
1593 QColor color() const { return mColor; }
1594 int padding() const { return mPadding; }
1595 double rotation() const { return mRotation; }
1596 bool substituteExponent() const { return mSubstituteExponent; }
1597 QChar multiplicationSymbol() const { return mMultiplicationSymbol; }
1598 bool abbreviateDecimalPowers() const { return mAbbreviateDecimalPowers; }
1599 int cacheSize() const;
1600
1601 //virtual int size() const;
1602
1603 // non-property methods:
1604 void drawTickLabel(QCPPainter *painter, const QPointF &tickPos, const QString &text);
1605 void clearCache();
1606
1607 // constants that may be used with setMultiplicationSymbol:
1608 static const QChar SymbolDot;
1609 static const QChar SymbolCross;
1610
1611protected:
1612 struct CachedLabel
1613 {
1614 QPoint offset;
1615 QPixmap pixmap;
1616 };
1617 struct LabelData
1618 {
1619 AnchorSide side;
1620 double rotation; // angle in degrees
1621 QTransform transform; // the transform about the label anchor which is at (0, 0). Does not contain final absolute x/y positioning on the plot/axis
1622 QString basePart, expPart, suffixPart;
1623 QRect baseBounds, expBounds, suffixBounds;
1624 QRect totalBounds; // is in a coordinate system where label top left is at (0, 0)
1625 QRect rotatedTotalBounds; // is in a coordinate system where the label anchor is at (0, 0)
1626 QFont baseFont, expFont;
1627 QColor color;
1628 };
1629
1630 // property members:
1631 AnchorMode mAnchorMode;
1632 AnchorSide mAnchorSide;
1633 QPointF mAnchorReference;
1634 AnchorReferenceType mAnchorReferenceType;
1635 QFont mFont;
1636 QColor mColor;
1637 int mPadding;
1638 double mRotation; // this is the rotation applied uniformly to all labels, not the heterogeneous rotation in amCircularRotated mode
1639 bool mSubstituteExponent;
1640 QChar mMultiplicationSymbol;
1641 bool mAbbreviateDecimalPowers;
1642 // non-property members:
1643 QCustomPlot *mParentPlot;
1644 QByteArray mLabelParameterHash; // to determine whether mLabelCache needs to be cleared due to changed parameters
1645 QCache<QString, CachedLabel> mLabelCache;
1646 QRect mAxisSelectionBox, mTickLabelsSelectionBox, mLabelSelectionBox;
1647 int mLetterCapHeight, mLetterDescent;
1648
1649 // introduced virtual methods:
1650 virtual void drawLabelMaybeCached(QCPPainter *painter, const QFont &font, const QColor &color, const QPointF &pos, AnchorSide side, double rotation, const QString &text);
1651 virtual QByteArray generateLabelParameterHash() const; // TODO: get rid of this in favor of invalidation flag upon setters?
1652
1653 // non-virtual methods:
1654 QPointF getAnchorPos(const QPointF &tickPos);
1655 void drawText(QCPPainter *painter, const QPointF &pos, const LabelData &labelData) const;
1656 LabelData getTickLabelData(const QFont &font, const QColor &color, double rotation, AnchorSide side, const QString &text) const;
1657 void applyAnchorTransform(LabelData &labelData) const;
1658 //void getMaxTickLabelSize(const QFont &font, const QString &text, QSize *tickLabelsSize) const;
1659 CachedLabel *createCachedLabel(const LabelData &labelData) const;
1660 QByteArray cacheKey(const QString &text, const QColor &color, double rotation, AnchorSide side) const;
1661 AnchorSide skewedAnchorSide(const QPointF &tickPos, double sideExpandHorz, double sideExpandVert) const;
1662 AnchorSide rotationCorrectedSide(AnchorSide side, double rotation) const;
1663 void analyzeFontMetrics();
1664};
1665Q_DECLARE_METATYPE(QCPLabelPainterPrivate::AnchorMode)
1666Q_DECLARE_METATYPE(QCPLabelPainterPrivate::AnchorSide)
1667
1668
1669/* end of 'src/axis/labelpainter.h' */
1670
1671
1672/* including file 'src/axis/axisticker.h' */
1673/* modified 2021-03-29T02:30:44, size 4230 */
1674
1675class QCP_LIB_DECL QCPAxisTicker
1676{
1677 Q_GADGET
1678public:
1679 /*!
1680 Defines the strategies that the axis ticker may follow when choosing the size of the tick step.
1681
1682 \see setTickStepStrategy
1683 */
1685 {
1686 tssReadability ///< A nicely readable tick step is prioritized over matching the requested number of ticks (see \ref setTickCount)
1687 ,tssMeetTickCount ///< Less readable tick steps are allowed which in turn facilitates getting closer to the requested tick count
1689 Q_ENUMS(TickStepStrategy)
1690
1691 QCPAxisTicker();
1692 virtual ~QCPAxisTicker();
1693
1694 // getters:
1695 TickStepStrategy tickStepStrategy() const { return mTickStepStrategy; }
1696 int tickCount() const { return mTickCount; }
1697 double tickOrigin() const { return mTickOrigin; }
1698
1699 // setters:
1700 void setTickStepStrategy(TickStepStrategy strategy);
1701 void setTickCount(int count);
1702 void setTickOrigin(double origin);
1703
1704 // introduced virtual methods:
1705 virtual void generate(const QCPRange &range, const QLocale &locale, QChar formatChar, int precision, QVector<double> &ticks, QVector<double> *subTicks, QVector<QString> *tickLabels);
1706
1707protected:
1708 // property members:
1709 TickStepStrategy mTickStepStrategy;
1710 int mTickCount;
1711 double mTickOrigin;
1712
1713 // introduced virtual methods:
1714 virtual double getTickStep(const QCPRange &range);
1715 virtual int getSubTickCount(double tickStep);
1716 virtual QString getTickLabel(double tick, const QLocale &locale, QChar formatChar, int precision);
1717 virtual QVector<double> createTickVector(double tickStep, const QCPRange &range);
1718 virtual QVector<double> createSubTickVector(int subTickCount, const QVector<double> &ticks);
1719 virtual QVector<QString> createLabelVector(const QVector<double> &ticks, const QLocale &locale, QChar formatChar, int precision);
1720
1721 // non-virtual methods:
1722 void trimTicks(const QCPRange &range, QVector<double> &ticks, bool keepOneOutlier) const;
1723 double pickClosest(double target, const QVector<double> &candidates) const;
1724 double getMantissa(double input, double *magnitude=nullptr) const;
1725 double cleanMantissa(double input) const;
1726
1727private:
1728 Q_DISABLE_COPY(QCPAxisTicker)
1729
1730};
1731Q_DECLARE_METATYPE(QCPAxisTicker::TickStepStrategy)
1732Q_DECLARE_METATYPE(QSharedPointer<QCPAxisTicker>)
1733
1734/* end of 'src/axis/axisticker.h' */
1735
1736
1737/* including file 'src/axis/axistickerdatetime.h' */
1738/* modified 2021-03-29T02:30:44, size 3600 */
1739
1740class QCP_LIB_DECL QCPAxisTickerDateTime : public QCPAxisTicker
1741{
1742public:
1744
1745 // getters:
1746 QString dateTimeFormat() const { return mDateTimeFormat; }
1747 Qt::TimeSpec dateTimeSpec() const { return mDateTimeSpec; }
1748# if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
1749 QTimeZone timeZone() const { return mTimeZone; }
1750#endif
1751
1752 // setters:
1753 void setDateTimeFormat(const QString &format);
1754 void setDateTimeSpec(Qt::TimeSpec spec);
1755# if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
1756 void setTimeZone(const QTimeZone &zone);
1757# endif
1758 void setTickOrigin(double origin); // hides base class method but calls baseclass implementation ("using" throws off IDEs and doxygen)
1759 void setTickOrigin(const QDateTime &origin);
1760
1761 // static methods:
1762 static QDateTime keyToDateTime(double key);
1763 static double dateTimeToKey(const QDateTime &dateTime);
1764 static double dateTimeToKey(const QDate &date, Qt::TimeSpec timeSpec=Qt::LocalTime);
1765
1766protected:
1767 // property members:
1768 QString mDateTimeFormat;
1769 Qt::TimeSpec mDateTimeSpec;
1770# if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
1771 QTimeZone mTimeZone;
1772# endif
1773 // non-property members:
1774 enum DateStrategy {dsNone, dsUniformTimeInDay, dsUniformDayInMonth} mDateStrategy;
1775
1776 // reimplemented virtual methods:
1777 virtual double getTickStep(const QCPRange &range) Q_DECL_OVERRIDE;
1778 virtual int getSubTickCount(double tickStep) Q_DECL_OVERRIDE;
1779 virtual QString getTickLabel(double tick, const QLocale &locale, QChar formatChar, int precision) Q_DECL_OVERRIDE;
1780 virtual QVector<double> createTickVector(double tickStep, const QCPRange &range) Q_DECL_OVERRIDE;
1781};
1782
1783/* end of 'src/axis/axistickerdatetime.h' */
1784
1785
1786/* including file 'src/axis/axistickertime.h' */
1787/* modified 2021-03-29T02:30:44, size 3542 */
1788
1789class QCP_LIB_DECL QCPAxisTickerTime : public QCPAxisTicker
1790{
1791 Q_GADGET
1792public:
1793 /*!
1794 Defines the logical units in which fractions of time spans can be expressed.
1795
1796 \see setFieldWidth, setTimeFormat
1797 */
1798 enum TimeUnit { tuMilliseconds ///< Milliseconds, one thousandth of a second (%%z in \ref setTimeFormat)
1799 ,tuSeconds ///< Seconds (%%s in \ref setTimeFormat)
1800 ,tuMinutes ///< Minutes (%%m in \ref setTimeFormat)
1801 ,tuHours ///< Hours (%%h in \ref setTimeFormat)
1802 ,tuDays ///< Days (%%d in \ref setTimeFormat)
1804 Q_ENUMS(TimeUnit)
1805
1807
1808 // getters:
1809 QString timeFormat() const { return mTimeFormat; }
1810 int fieldWidth(TimeUnit unit) const { return mFieldWidth.value(unit); }
1811
1812 // setters:
1813 void setTimeFormat(const QString &format);
1814 void setFieldWidth(TimeUnit unit, int width);
1815
1816protected:
1817 // property members:
1818 QString mTimeFormat;
1819 QHash<TimeUnit, int> mFieldWidth;
1820
1821 // non-property members:
1822 TimeUnit mSmallestUnit, mBiggestUnit;
1823 QHash<TimeUnit, QString> mFormatPattern;
1824
1825 // reimplemented virtual methods:
1826 virtual double getTickStep(const QCPRange &range) Q_DECL_OVERRIDE;
1827 virtual int getSubTickCount(double tickStep) Q_DECL_OVERRIDE;
1828 virtual QString getTickLabel(double tick, const QLocale &locale, QChar formatChar, int precision) Q_DECL_OVERRIDE;
1829
1830 // non-virtual methods:
1831 void replaceUnit(QString &text, TimeUnit unit, int value) const;
1832};
1833Q_DECLARE_METATYPE(QCPAxisTickerTime::TimeUnit)
1834
1835/* end of 'src/axis/axistickertime.h' */
1836
1837
1838/* including file 'src/axis/axistickerfixed.h' */
1839/* modified 2021-03-29T02:30:44, size 3308 */
1840
1841class QCP_LIB_DECL QCPAxisTickerFixed : public QCPAxisTicker
1842{
1843 Q_GADGET
1844public:
1845 /*!
1846 Defines how the axis ticker may modify the specified tick step (\ref setTickStep) in order to
1847 control the number of ticks in the axis range.
1848
1849 \see setScaleStrategy
1850 */
1851 enum ScaleStrategy { ssNone ///< Modifications are not allowed, the specified tick step is absolutely fixed. This might cause a high tick density and overlapping labels if the axis range is zoomed out.
1852 ,ssMultiples ///< An integer multiple of the specified tick step is allowed. The used factor follows the base class properties of \ref setTickStepStrategy and \ref setTickCount.
1853 ,ssPowers ///< An integer power of the specified tick step is allowed.
1855 Q_ENUMS(ScaleStrategy)
1856
1858
1859 // getters:
1860 double tickStep() const { return mTickStep; }
1861 ScaleStrategy scaleStrategy() const { return mScaleStrategy; }
1862
1863 // setters:
1864 void setTickStep(double step);
1865 void setScaleStrategy(ScaleStrategy strategy);
1866
1867protected:
1868 // property members:
1869 double mTickStep;
1870 ScaleStrategy mScaleStrategy;
1871
1872 // reimplemented virtual methods:
1873 virtual double getTickStep(const QCPRange &range) Q_DECL_OVERRIDE;
1874};
1875Q_DECLARE_METATYPE(QCPAxisTickerFixed::ScaleStrategy)
1876
1877/* end of 'src/axis/axistickerfixed.h' */
1878
1879
1880/* including file 'src/axis/axistickertext.h' */
1881/* modified 2021-03-29T02:30:44, size 3090 */
1882
1883class QCP_LIB_DECL QCPAxisTickerText : public QCPAxisTicker
1884{
1885public:
1887
1888 // getters:
1889 QMap<double, QString> &ticks() { return mTicks; }
1890 int subTickCount() const { return mSubTickCount; }
1891
1892 // setters:
1893 void setTicks(const QMap<double, QString> &ticks);
1894 void setTicks(const QVector<double> &positions, const QVector<QString> &labels);
1895 void setSubTickCount(int subTicks);
1896
1897 // non-virtual methods:
1898 void clear();
1899 void addTick(double position, const QString &label);
1900 void addTicks(const QMap<double, QString> &ticks);
1901 void addTicks(const QVector<double> &positions, const QVector<QString> &labels);
1902
1903protected:
1904 // property members:
1905 QMap<double, QString> mTicks;
1906 int mSubTickCount;
1907
1908 // reimplemented virtual methods:
1909 virtual double getTickStep(const QCPRange &range) Q_DECL_OVERRIDE;
1910 virtual int getSubTickCount(double tickStep) Q_DECL_OVERRIDE;
1911 virtual QString getTickLabel(double tick, const QLocale &locale, QChar formatChar, int precision) Q_DECL_OVERRIDE;
1912 virtual QVector<double> createTickVector(double tickStep, const QCPRange &range) Q_DECL_OVERRIDE;
1913};
1914
1915/* end of 'src/axis/axistickertext.h' */
1916
1917
1918/* including file 'src/axis/axistickerpi.h' */
1919/* modified 2021-03-29T02:30:44, size 3911 */
1920
1921class QCP_LIB_DECL QCPAxisTickerPi : public QCPAxisTicker
1922{
1923 Q_GADGET
1924public:
1925 /*!
1926 Defines how fractions should be displayed in tick labels.
1927
1928 \see setFractionStyle
1929 */
1930 enum FractionStyle { fsFloatingPoint ///< Fractions are displayed as regular decimal floating point numbers, e.g. "0.25" or "0.125".
1931 ,fsAsciiFractions ///< Fractions are written as rationals using ASCII characters only, e.g. "1/4" or "1/8"
1932 ,fsUnicodeFractions ///< Fractions are written using sub- and superscript UTF-8 digits and the fraction symbol.
1934 Q_ENUMS(FractionStyle)
1935
1937
1938 // getters:
1939 QString piSymbol() const { return mPiSymbol; }
1940 double piValue() const { return mPiValue; }
1941 bool periodicity() const { return mPeriodicity; }
1942 FractionStyle fractionStyle() const { return mFractionStyle; }
1943
1944 // setters:
1945 void setPiSymbol(QString symbol);
1946 void setPiValue(double pi);
1947 void setPeriodicity(int multiplesOfPi);
1948 void setFractionStyle(FractionStyle style);
1949
1950protected:
1951 // property members:
1952 QString mPiSymbol;
1953 double mPiValue;
1954 int mPeriodicity;
1955 FractionStyle mFractionStyle;
1956
1957 // non-property members:
1958 double mPiTickStep; // size of one tick step in units of mPiValue
1959
1960 // reimplemented virtual methods:
1961 virtual double getTickStep(const QCPRange &range) Q_DECL_OVERRIDE;
1962 virtual int getSubTickCount(double tickStep) Q_DECL_OVERRIDE;
1963 virtual QString getTickLabel(double tick, const QLocale &locale, QChar formatChar, int precision) Q_DECL_OVERRIDE;
1964
1965 // non-virtual methods:
1966 void simplifyFraction(int &numerator, int &denominator) const;
1967 QString fractionToString(int numerator, int denominator) const;
1968 QString unicodeFraction(int numerator, int denominator) const;
1969 QString unicodeSuperscript(int number) const;
1970 QString unicodeSubscript(int number) const;
1971};
1972Q_DECLARE_METATYPE(QCPAxisTickerPi::FractionStyle)
1973
1974/* end of 'src/axis/axistickerpi.h' */
1975
1976
1977/* including file 'src/axis/axistickerlog.h' */
1978/* modified 2021-03-29T02:30:44, size 2594 */
1979
1980class QCP_LIB_DECL QCPAxisTickerLog : public QCPAxisTicker
1981{
1982public:
1984
1985 // getters:
1986 double logBase() const { return mLogBase; }
1987 int subTickCount() const { return mSubTickCount; }
1988
1989 // setters:
1990 void setLogBase(double base);
1991 void setSubTickCount(int subTicks);
1992
1993protected:
1994 // property members:
1995 double mLogBase;
1996 int mSubTickCount;
1997
1998 // non-property members:
1999 double mLogBaseLnInv;
2000
2001 // reimplemented virtual methods:
2002 virtual int getSubTickCount(double tickStep) Q_DECL_OVERRIDE;
2003 virtual QVector<double> createTickVector(double tickStep, const QCPRange &range) Q_DECL_OVERRIDE;
2004};
2005
2006/* end of 'src/axis/axistickerlog.h' */
2007
2008
2009/* including file 'src/axis/axis.h' */
2010/* modified 2021-03-29T02:30:44, size 20913 */
2011
2012class QCP_LIB_DECL QCPGrid :public QCPLayerable
2013{
2014 Q_OBJECT
2015 /// \cond INCLUDE_QPROPERTIES
2016 Q_PROPERTY(bool subGridVisible READ subGridVisible WRITE setSubGridVisible)
2017 Q_PROPERTY(bool antialiasedSubGrid READ antialiasedSubGrid WRITE setAntialiasedSubGrid)
2018 Q_PROPERTY(bool antialiasedZeroLine READ antialiasedZeroLine WRITE setAntialiasedZeroLine)
2019 Q_PROPERTY(QPen pen READ pen WRITE setPen)
2020 Q_PROPERTY(QPen subGridPen READ subGridPen WRITE setSubGridPen)
2021 Q_PROPERTY(QPen zeroLinePen READ zeroLinePen WRITE setZeroLinePen)
2022 /// \endcond
2023public:
2024 explicit QCPGrid(QCPAxis *parentAxis);
2025
2026 // getters:
2027 bool subGridVisible() const { return mSubGridVisible; }
2028 bool antialiasedSubGrid() const { return mAntialiasedSubGrid; }
2029 bool antialiasedZeroLine() const { return mAntialiasedZeroLine; }
2030 QPen pen() const { return mPen; }
2031 QPen subGridPen() const { return mSubGridPen; }
2032 QPen zeroLinePen() const { return mZeroLinePen; }
2033
2034 // setters:
2035 void setSubGridVisible(bool visible);
2036 void setAntialiasedSubGrid(bool enabled);
2037 void setAntialiasedZeroLine(bool enabled);
2038 void setPen(const QPen &pen);
2039 void setSubGridPen(const QPen &pen);
2040 void setZeroLinePen(const QPen &pen);
2041
2042protected:
2043 // property members:
2044 bool mSubGridVisible;
2045 bool mAntialiasedSubGrid, mAntialiasedZeroLine;
2046 QPen mPen, mSubGridPen, mZeroLinePen;
2047
2048 // non-property members:
2049 QCPAxis *mParentAxis;
2050
2051 // reimplemented virtual methods:
2052 virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE;
2053 virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE;
2054
2055 // non-virtual methods:
2056 void drawGridLines(QCPPainter *painter) const;
2057 void drawSubGridLines(QCPPainter *painter) const;
2058
2059 friend class QCPAxis;
2060};
2061
2062
2063class QCP_LIB_DECL QCPAxis : public QCPLayerable
2064{
2065 Q_OBJECT
2066 /// \cond INCLUDE_QPROPERTIES
2067 Q_PROPERTY(AxisType axisType READ axisType)
2068 Q_PROPERTY(QCPAxisRect* axisRect READ axisRect)
2069 Q_PROPERTY(ScaleType scaleType READ scaleType WRITE setScaleType NOTIFY scaleTypeChanged)
2070 Q_PROPERTY(QCPRange range READ range WRITE setRange NOTIFY rangeChanged)
2071 Q_PROPERTY(bool rangeReversed READ rangeReversed WRITE setRangeReversed)
2072 Q_PROPERTY(QSharedPointer<QCPAxisTicker> ticker READ ticker WRITE setTicker)
2073 Q_PROPERTY(bool ticks READ ticks WRITE setTicks)
2074 Q_PROPERTY(bool tickLabels READ tickLabels WRITE setTickLabels)
2075 Q_PROPERTY(int tickLabelPadding READ tickLabelPadding WRITE setTickLabelPadding)
2076 Q_PROPERTY(QFont tickLabelFont READ tickLabelFont WRITE setTickLabelFont)
2077 Q_PROPERTY(QColor tickLabelColor READ tickLabelColor WRITE setTickLabelColor)
2078 Q_PROPERTY(double tickLabelRotation READ tickLabelRotation WRITE setTickLabelRotation)
2079 Q_PROPERTY(LabelSide tickLabelSide READ tickLabelSide WRITE setTickLabelSide)
2080 Q_PROPERTY(QString numberFormat READ numberFormat WRITE setNumberFormat)
2081 Q_PROPERTY(int numberPrecision READ numberPrecision WRITE setNumberPrecision)
2082 Q_PROPERTY(QVector<double> tickVector READ tickVector)
2083 Q_PROPERTY(QVector<QString> tickVectorLabels READ tickVectorLabels)
2084 Q_PROPERTY(int tickLengthIn READ tickLengthIn WRITE setTickLengthIn)
2085 Q_PROPERTY(int tickLengthOut READ tickLengthOut WRITE setTickLengthOut)
2086 Q_PROPERTY(bool subTicks READ subTicks WRITE setSubTicks)
2087 Q_PROPERTY(int subTickLengthIn READ subTickLengthIn WRITE setSubTickLengthIn)
2088 Q_PROPERTY(int subTickLengthOut READ subTickLengthOut WRITE setSubTickLengthOut)
2089 Q_PROPERTY(QPen basePen READ basePen WRITE setBasePen)
2090 Q_PROPERTY(QPen tickPen READ tickPen WRITE setTickPen)
2091 Q_PROPERTY(QPen subTickPen READ subTickPen WRITE setSubTickPen)
2092 Q_PROPERTY(QFont labelFont READ labelFont WRITE setLabelFont)
2093 Q_PROPERTY(QColor labelColor READ labelColor WRITE setLabelColor)
2094 Q_PROPERTY(QString label READ label WRITE setLabel)
2095 Q_PROPERTY(int labelPadding READ labelPadding WRITE setLabelPadding)
2096 Q_PROPERTY(int padding READ padding WRITE setPadding)
2097 Q_PROPERTY(int offset READ offset WRITE setOffset)
2098 Q_PROPERTY(SelectableParts selectedParts READ selectedParts WRITE setSelectedParts NOTIFY selectionChanged)
2099 Q_PROPERTY(SelectableParts selectableParts READ selectableParts WRITE setSelectableParts NOTIFY selectableChanged)
2100 Q_PROPERTY(QFont selectedTickLabelFont READ selectedTickLabelFont WRITE setSelectedTickLabelFont)
2101 Q_PROPERTY(QFont selectedLabelFont READ selectedLabelFont WRITE setSelectedLabelFont)
2102 Q_PROPERTY(QColor selectedTickLabelColor READ selectedTickLabelColor WRITE setSelectedTickLabelColor)
2103 Q_PROPERTY(QColor selectedLabelColor READ selectedLabelColor WRITE setSelectedLabelColor)
2104 Q_PROPERTY(QPen selectedBasePen READ selectedBasePen WRITE setSelectedBasePen)
2105 Q_PROPERTY(QPen selectedTickPen READ selectedTickPen WRITE setSelectedTickPen)
2106 Q_PROPERTY(QPen selectedSubTickPen READ selectedSubTickPen WRITE setSelectedSubTickPen)
2107 Q_PROPERTY(QCPLineEnding lowerEnding READ lowerEnding WRITE setLowerEnding)
2108 Q_PROPERTY(QCPLineEnding upperEnding READ upperEnding WRITE setUpperEnding)
2109 Q_PROPERTY(QCPGrid* grid READ grid)
2110 /// \endcond
2111public:
2112 /*!
2113 Defines at which side of the axis rect the axis will appear. This also affects how the tick
2114 marks are drawn, on which side the labels are placed etc.
2115 */
2116 enum AxisType { atLeft = 0x01 ///< <tt>0x01</tt> Axis is vertical and on the left side of the axis rect
2117 ,atRight = 0x02 ///< <tt>0x02</tt> Axis is vertical and on the right side of the axis rect
2118 ,atTop = 0x04 ///< <tt>0x04</tt> Axis is horizontal and on the top side of the axis rect
2119 ,atBottom = 0x08 ///< <tt>0x08</tt> Axis is horizontal and on the bottom side of the axis rect
2121 Q_ENUMS(AxisType)
2122 Q_FLAGS(AxisTypes)
2123 Q_DECLARE_FLAGS(AxisTypes, AxisType)
2124 /*!
2125 Defines on which side of the axis the tick labels (numbers) shall appear.
2126
2127 \see setTickLabelSide
2128 */
2129 enum LabelSide { lsInside ///< Tick labels will be displayed inside the axis rect and clipped to the inner axis rect
2130 ,lsOutside ///< Tick labels will be displayed outside the axis rect
2132 Q_ENUMS(LabelSide)
2133 /*!
2134 Defines the scale of an axis.
2135 \see setScaleType
2136 */
2137 enum ScaleType { stLinear ///< Linear scaling
2138 ,stLogarithmic ///< Logarithmic scaling with correspondingly transformed axis coordinates (possibly also \ref setTicker to a \ref QCPAxisTickerLog instance).
2140 Q_ENUMS(ScaleType)
2141 /*!
2142 Defines the selectable parts of an axis.
2143 \see setSelectableParts, setSelectedParts
2144 */
2145 enum SelectablePart { spNone = 0 ///< None of the selectable parts
2146 ,spAxis = 0x001 ///< The axis backbone and tick marks
2147 ,spTickLabels = 0x002 ///< Tick labels (numbers) of this axis (as a whole, not individually)
2148 ,spAxisLabel = 0x004 ///< The axis label
2150 Q_ENUMS(SelectablePart)
2151 Q_FLAGS(SelectableParts)
2152 Q_DECLARE_FLAGS(SelectableParts, SelectablePart)
2153
2154 explicit QCPAxis(QCPAxisRect *parent, AxisType type);
2155 virtual ~QCPAxis() Q_DECL_OVERRIDE;
2156
2157 // getters:
2158 AxisType axisType() const { return mAxisType; }
2159 QCPAxisRect *axisRect() const { return mAxisRect; }
2160 ScaleType scaleType() const { return mScaleType; }
2161 const QCPRange range() const { return mRange; }
2162 bool rangeReversed() const { return mRangeReversed; }
2163 QSharedPointer<QCPAxisTicker> ticker() const { return mTicker; }
2164 bool ticks() const { return mTicks; }
2165 bool tickLabels() const { return mTickLabels; }
2166 int tickLabelPadding() const;
2167 QFont tickLabelFont() const { return mTickLabelFont; }
2168 QColor tickLabelColor() const { return mTickLabelColor; }
2169 double tickLabelRotation() const;
2170 LabelSide tickLabelSide() const;
2171 QString numberFormat() const;
2172 int numberPrecision() const { return mNumberPrecision; }
2173 QVector<double> tickVector() const { return mTickVector; }
2174 QVector<QString> tickVectorLabels() const { return mTickVectorLabels; }
2175 int tickLengthIn() const;
2176 int tickLengthOut() const;
2177 bool subTicks() const { return mSubTicks; }
2178 int subTickLengthIn() const;
2179 int subTickLengthOut() const;
2180 QPen basePen() const { return mBasePen; }
2181 QPen tickPen() const { return mTickPen; }
2182 QPen subTickPen() const { return mSubTickPen; }
2183 QFont labelFont() const { return mLabelFont; }
2184 QColor labelColor() const { return mLabelColor; }
2185 QString label() const { return mLabel; }
2186 int labelPadding() const;
2187 int padding() const { return mPadding; }
2188 int offset() const;
2189 SelectableParts selectedParts() const { return mSelectedParts; }
2190 SelectableParts selectableParts() const { return mSelectableParts; }
2191 QFont selectedTickLabelFont() const { return mSelectedTickLabelFont; }
2192 QFont selectedLabelFont() const { return mSelectedLabelFont; }
2193 QColor selectedTickLabelColor() const { return mSelectedTickLabelColor; }
2194 QColor selectedLabelColor() const { return mSelectedLabelColor; }
2195 QPen selectedBasePen() const { return mSelectedBasePen; }
2196 QPen selectedTickPen() const { return mSelectedTickPen; }
2197 QPen selectedSubTickPen() const { return mSelectedSubTickPen; }
2198 QCPLineEnding lowerEnding() const;
2199 QCPLineEnding upperEnding() const;
2200 QCPGrid *grid() const { return mGrid; }
2201
2202 // setters:
2203 Q_SLOT void setScaleType(QCPAxis::ScaleType type);
2204 Q_SLOT void setRange(const QCPRange &range);
2205 void setRange(double lower, double upper);
2206 void setRange(double position, double size, Qt::AlignmentFlag alignment);
2207 void setRangeLower(double lower);
2208 void setRangeUpper(double upper);
2209 void setRangeReversed(bool reversed);
2210 void setTicker(QSharedPointer<QCPAxisTicker> ticker);
2211 void setTicks(bool show);
2212 void setTickLabels(bool show);
2213 void setTickLabelPadding(int padding);
2214 void setTickLabelFont(const QFont &font);
2215 void setTickLabelColor(const QColor &color);
2216 void setTickLabelRotation(double degrees);
2217 void setTickLabelSide(LabelSide side);
2218 void setNumberFormat(const QString &formatCode);
2219 void setNumberPrecision(int precision);
2220 void setTickLength(int inside, int outside=0);
2221 void setTickLengthIn(int inside);
2222 void setTickLengthOut(int outside);
2223 void setSubTicks(bool show);
2224 void setSubTickLength(int inside, int outside=0);
2225 void setSubTickLengthIn(int inside);
2226 void setSubTickLengthOut(int outside);
2227 void setBasePen(const QPen &pen);
2228 void setTickPen(const QPen &pen);
2229 void setSubTickPen(const QPen &pen);
2230 void setLabelFont(const QFont &font);
2231 void setLabelColor(const QColor &color);
2232 void setLabel(const QString &str);
2233 void setLabelPadding(int padding);
2234 void setPadding(int padding);
2235 void setOffset(int offset);
2236 void setSelectedTickLabelFont(const QFont &font);
2237 void setSelectedLabelFont(const QFont &font);
2238 void setSelectedTickLabelColor(const QColor &color);
2239 void setSelectedLabelColor(const QColor &color);
2240 void setSelectedBasePen(const QPen &pen);
2241 void setSelectedTickPen(const QPen &pen);
2242 void setSelectedSubTickPen(const QPen &pen);
2243 Q_SLOT void setSelectableParts(const QCPAxis::SelectableParts &selectableParts);
2244 Q_SLOT void setSelectedParts(const QCPAxis::SelectableParts &selectedParts);
2245 void setLowerEnding(const QCPLineEnding &ending);
2246 void setUpperEnding(const QCPLineEnding &ending);
2247
2248 // reimplemented virtual methods:
2249 virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE;
2250
2251 // non-property methods:
2252 Qt::Orientation orientation() const { return mOrientation; }
2253 int pixelOrientation() const { return rangeReversed() != (orientation()==Qt::Vertical) ? -1 : 1; }
2254 void moveRange(double diff);
2255 void scaleRange(double factor);
2256 void scaleRange(double factor, double center);
2257 void setScaleRatio(const QCPAxis *otherAxis, double ratio=1.0);
2258 void rescale(bool onlyVisiblePlottables=false);
2259 double pixelToCoord(double value) const;
2260 double coordToPixel(double value) const;
2261 SelectablePart getPartAt(const QPointF &pos) const;
2262 QList<QCPAbstractPlottable*> plottables() const;
2263 QList<QCPGraph*> graphs() const;
2264 QList<QCPAbstractItem*> items() const;
2265
2266 static AxisType marginSideToAxisType(QCP::MarginSide side);
2267 static Qt::Orientation orientation(AxisType type) { return type==atBottom || type==atTop ? Qt::Horizontal : Qt::Vertical; }
2268 static AxisType opposite(AxisType type);
2269
2270signals:
2271 void rangeChanged(const QCPRange &newRange);
2272 void rangeChanged(const QCPRange &newRange, const QCPRange &oldRange);
2276
2277protected:
2278 // property members:
2279 // axis base:
2280 AxisType mAxisType;
2281 QCPAxisRect *mAxisRect;
2282 //int mOffset; // in QCPAxisPainter
2283 int mPadding;
2284 Qt::Orientation mOrientation;
2285 SelectableParts mSelectableParts, mSelectedParts;
2286 QPen mBasePen, mSelectedBasePen;
2287 //QCPLineEnding mLowerEnding, mUpperEnding; // in QCPAxisPainter
2288 // axis label:
2289 //int mLabelPadding; // in QCPAxisPainter
2290 QString mLabel;
2291 QFont mLabelFont, mSelectedLabelFont;
2292 QColor mLabelColor, mSelectedLabelColor;
2293 // tick labels:
2294 //int mTickLabelPadding; // in QCPAxisPainter
2295 bool mTickLabels;
2296 //double mTickLabelRotation; // in QCPAxisPainter
2297 QFont mTickLabelFont, mSelectedTickLabelFont;
2298 QColor mTickLabelColor, mSelectedTickLabelColor;
2299 int mNumberPrecision;
2300 QLatin1Char mNumberFormatChar;
2301 bool mNumberBeautifulPowers;
2302 //bool mNumberMultiplyCross; // QCPAxisPainter
2303 // ticks and subticks:
2304 bool mTicks;
2305 bool mSubTicks;
2306 //int mTickLengthIn, mTickLengthOut, mSubTickLengthIn, mSubTickLengthOut; // QCPAxisPainter
2307 QPen mTickPen, mSelectedTickPen;
2308 QPen mSubTickPen, mSelectedSubTickPen;
2309 // scale and range:
2310 QCPRange mRange;
2311 bool mRangeReversed;
2312 ScaleType mScaleType;
2313
2314 // non-property members:
2315 QCPGrid *mGrid;
2316 QCPAxisPainterPrivate *mAxisPainter;
2318 QVector<double> mTickVector;
2319 QVector<QString> mTickVectorLabels;
2320 QVector<double> mSubTickVector;
2321 bool mCachedMarginValid;
2322 int mCachedMargin;
2323 bool mDragging;
2324 QCPRange mDragStartRange;
2325 QCP::AntialiasedElements mAADragBackup, mNotAADragBackup;
2326
2327 // introduced virtual methods:
2328 virtual int calculateMargin();
2329
2330 // reimplemented virtual methods:
2331 virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE;
2332 virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE;
2333 virtual QCP::Interaction selectionCategory() const Q_DECL_OVERRIDE;
2334 // events:
2335 virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) Q_DECL_OVERRIDE;
2336 virtual void deselectEvent(bool *selectionStateChanged) Q_DECL_OVERRIDE;
2337 // mouse events:
2338 virtual void mousePressEvent(QMouseEvent *event, const QVariant &details) Q_DECL_OVERRIDE;
2339 virtual void mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) Q_DECL_OVERRIDE;
2340 virtual void mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos) Q_DECL_OVERRIDE;
2341 virtual void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE;
2342
2343 // non-virtual methods:
2344 void setupTickVectors();
2345 QPen getBasePen() const;
2346 QPen getTickPen() const;
2347 QPen getSubTickPen() const;
2348 QFont getTickLabelFont() const;
2349 QFont getLabelFont() const;
2350 QColor getTickLabelColor() const;
2351 QColor getLabelColor() const;
2352
2353private:
2354 Q_DISABLE_COPY(QCPAxis)
2355
2356 friend class QCustomPlot;
2357 friend class QCPGrid;
2358 friend class QCPAxisRect;
2359};
2360Q_DECLARE_OPERATORS_FOR_FLAGS(QCPAxis::SelectableParts)
2361Q_DECLARE_OPERATORS_FOR_FLAGS(QCPAxis::AxisTypes)
2362Q_DECLARE_METATYPE(QCPAxis::AxisType)
2363Q_DECLARE_METATYPE(QCPAxis::LabelSide)
2364Q_DECLARE_METATYPE(QCPAxis::ScaleType)
2365Q_DECLARE_METATYPE(QCPAxis::SelectablePart)
2366
2367
2369{
2370public:
2371 explicit QCPAxisPainterPrivate(QCustomPlot *parentPlot);
2372 virtual ~QCPAxisPainterPrivate();
2373
2374 virtual void draw(QCPPainter *painter);
2375 virtual int size();
2376 void clearCache();
2377
2378 QRect axisSelectionBox() const { return mAxisSelectionBox; }
2379 QRect tickLabelsSelectionBox() const { return mTickLabelsSelectionBox; }
2380 QRect labelSelectionBox() const { return mLabelSelectionBox; }
2381
2382 // public property members:
2383 QCPAxis::AxisType type;
2384 QPen basePen;
2385 QCPLineEnding lowerEnding, upperEnding; // directly accessed by QCPAxis setters/getters
2386 int labelPadding; // directly accessed by QCPAxis setters/getters
2387 QFont labelFont;
2388 QColor labelColor;
2389 QString label;
2390 int tickLabelPadding; // directly accessed by QCPAxis setters/getters
2391 double tickLabelRotation; // directly accessed by QCPAxis setters/getters
2392 QCPAxis::LabelSide tickLabelSide; // directly accessed by QCPAxis setters/getters
2393 bool substituteExponent;
2394 bool numberMultiplyCross; // directly accessed by QCPAxis setters/getters
2395 int tickLengthIn, tickLengthOut, subTickLengthIn, subTickLengthOut; // directly accessed by QCPAxis setters/getters
2396 QPen tickPen, subTickPen;
2397 QFont tickLabelFont;
2398 QColor tickLabelColor;
2399 QRect axisRect, viewportRect;
2400 int offset; // directly accessed by QCPAxis setters/getters
2401 bool abbreviateDecimalPowers;
2402 bool reversedEndings;
2403
2404 QVector<double> subTickPositions;
2405 QVector<double> tickPositions;
2406 QVector<QString> tickLabels;
2407
2408protected:
2409 struct CachedLabel
2410 {
2411 QPointF offset;
2412 QPixmap pixmap;
2413 };
2414 struct TickLabelData
2415 {
2416 QString basePart, expPart, suffixPart;
2417 QRect baseBounds, expBounds, suffixBounds, totalBounds, rotatedTotalBounds;
2418 QFont baseFont, expFont;
2419 };
2420 QCustomPlot *mParentPlot;
2421 QByteArray mLabelParameterHash; // to determine whether mLabelCache needs to be cleared due to changed parameters
2422 QCache<QString, CachedLabel> mLabelCache;
2423 QRect mAxisSelectionBox, mTickLabelsSelectionBox, mLabelSelectionBox;
2424
2425 virtual QByteArray generateLabelParameterHash() const;
2426
2427 virtual void placeTickLabel(QCPPainter *painter, double position, int distanceToAxis, const QString &text, QSize *tickLabelsSize);
2428 virtual void drawTickLabel(QCPPainter *painter, double x, double y, const TickLabelData &labelData) const;
2429 virtual TickLabelData getTickLabelData(const QFont &font, const QString &text) const;
2430 virtual QPointF getTickLabelDrawOffset(const TickLabelData &labelData) const;
2431 virtual void getMaxTickLabelSize(const QFont &font, const QString &text, QSize *tickLabelsSize) const;
2432};
2433
2434/* end of 'src/axis/axis.h' */
2435
2436
2437/* including file 'src/scatterstyle.h' */
2438/* modified 2021-03-29T02:30:44, size 7275 */
2439
2440class QCP_LIB_DECL QCPScatterStyle
2441{
2442 Q_GADGET
2443public:
2444 /*!
2445 Represents the various properties of a scatter style instance. For example, this enum is used
2446 to specify which properties of \ref QCPSelectionDecorator::setScatterStyle will be used when
2447 highlighting selected data points.
2448
2449 Specific scatter properties can be transferred between \ref QCPScatterStyle instances via \ref
2450 setFromOther.
2451 */
2452 enum ScatterProperty { spNone = 0x00 ///< <tt>0x00</tt> None
2453 ,spPen = 0x01 ///< <tt>0x01</tt> The pen property, see \ref setPen
2454 ,spBrush = 0x02 ///< <tt>0x02</tt> The brush property, see \ref setBrush
2455 ,spSize = 0x04 ///< <tt>0x04</tt> The size property, see \ref setSize
2456 ,spShape = 0x08 ///< <tt>0x08</tt> The shape property, see \ref setShape
2457 ,spAll = 0xFF ///< <tt>0xFF</tt> All properties
2459 Q_ENUMS(ScatterProperty)
2460 Q_FLAGS(ScatterProperties)
2461 Q_DECLARE_FLAGS(ScatterProperties, ScatterProperty)
2462
2463 /*!
2464 Defines the shape used for scatter points.
2465
2466 On plottables/items that draw scatters, the sizes of these visualizations (with exception of
2467 \ref ssDot and \ref ssPixmap) can be controlled with the \ref setSize function. Scatters are
2468 drawn with the pen and brush specified with \ref setPen and \ref setBrush.
2469 */
2470 enum ScatterShape { ssNone ///< no scatter symbols are drawn (e.g. in QCPGraph, data only represented with lines)
2471 ,ssDot ///< \enumimage{ssDot.png} a single pixel (use \ref ssDisc or \ref ssCircle if you want a round shape with a certain radius)
2472 ,ssCross ///< \enumimage{ssCross.png} a cross
2473 ,ssPlus ///< \enumimage{ssPlus.png} a plus
2474 ,ssCircle ///< \enumimage{ssCircle.png} a circle
2475 ,ssDisc ///< \enumimage{ssDisc.png} a circle which is filled with the pen's color (not the brush as with ssCircle)
2476 ,ssSquare ///< \enumimage{ssSquare.png} a square
2477 ,ssDiamond ///< \enumimage{ssDiamond.png} a diamond
2478 ,ssStar ///< \enumimage{ssStar.png} a star with eight arms, i.e. a combination of cross and plus
2479 ,ssTriangle ///< \enumimage{ssTriangle.png} an equilateral triangle, standing on baseline
2480 ,ssTriangleInverted ///< \enumimage{ssTriangleInverted.png} an equilateral triangle, standing on corner
2481 ,ssCrossSquare ///< \enumimage{ssCrossSquare.png} a square with a cross inside
2482 ,ssPlusSquare ///< \enumimage{ssPlusSquare.png} a square with a plus inside
2483 ,ssCrossCircle ///< \enumimage{ssCrossCircle.png} a circle with a cross inside
2484 ,ssPlusCircle ///< \enumimage{ssPlusCircle.png} a circle with a plus inside
2485 ,ssPeace ///< \enumimage{ssPeace.png} a circle, with one vertical and two downward diagonal lines
2486 ,ssPixmap ///< a custom pixmap specified by \ref setPixmap, centered on the data point coordinates
2487 ,ssCustom ///< custom painter operations are performed per scatter (As QPainterPath, see \ref setCustomPath)
2489 Q_ENUMS(ScatterShape)
2490
2492 QCPScatterStyle(ScatterShape shape, double size=6);
2493 QCPScatterStyle(ScatterShape shape, const QColor &color, double size);
2494 QCPScatterStyle(ScatterShape shape, const QColor &color, const QColor &fill, double size);
2495 QCPScatterStyle(ScatterShape shape, const QPen &pen, const QBrush &brush, double size);
2496 QCPScatterStyle(const QPixmap &pixmap);
2497 QCPScatterStyle(const QPainterPath &customPath, const QPen &pen, const QBrush &brush=Qt::NoBrush, double size=6);
2498
2499 // getters:
2500 double size() const { return mSize; }
2501 ScatterShape shape() const { return mShape; }
2502 QPen pen() const { return mPen; }
2503 QBrush brush() const { return mBrush; }
2504 QPixmap pixmap() const { return mPixmap; }
2505 QPainterPath customPath() const { return mCustomPath; }
2506
2507 // setters:
2508 void setFromOther(const QCPScatterStyle &other, ScatterProperties properties);
2509 void setSize(double size);
2510 void setShape(ScatterShape shape);
2511 void setPen(const QPen &pen);
2512 void setBrush(const QBrush &brush);
2513 void setPixmap(const QPixmap &pixmap);
2514 void setCustomPath(const QPainterPath &customPath);
2515
2516 // non-property methods:
2517 bool isNone() const { return mShape == ssNone; }
2518 bool isPenDefined() const { return mPenDefined; }
2519 void undefinePen();
2520 void applyTo(QCPPainter *painter, const QPen &defaultPen) const;
2521 void drawShape(QCPPainter *painter, const QPointF &pos) const;
2522 void drawShape(QCPPainter *painter, double x, double y) const;
2523
2524protected:
2525 // property members:
2526 double mSize;
2527 ScatterShape mShape;
2528 QPen mPen;
2529 QBrush mBrush;
2530 QPixmap mPixmap;
2531 QPainterPath mCustomPath;
2532
2533 // non-property members:
2534 bool mPenDefined;
2535};
2536Q_DECLARE_TYPEINFO(QCPScatterStyle, Q_MOVABLE_TYPE);
2537Q_DECLARE_OPERATORS_FOR_FLAGS(QCPScatterStyle::ScatterProperties)
2538Q_DECLARE_METATYPE(QCPScatterStyle::ScatterProperty)
2539Q_DECLARE_METATYPE(QCPScatterStyle::ScatterShape)
2540
2541/* end of 'src/scatterstyle.h' */
2542
2543
2544/* including file 'src/datacontainer.h' */
2545/* modified 2021-03-29T02:30:44, size 34070 */
2546
2547/*! \relates QCPDataContainer
2548 Returns whether the sort key of \a a is less than the sort key of \a b.
2549
2550 \see QCPDataContainer::sort
2551*/
2552template <class DataType>
2553inline bool qcpLessThanSortKey(const DataType &a, const DataType &b) { return a.sortKey() < b.sortKey(); }
2554
2555template <class DataType>
2556class QCPDataContainer // no QCP_LIB_DECL, template class ends up in header (cpp included below)
2557{
2558public:
2560 typedef typename QVector<DataType>::iterator iterator;
2561
2563
2564 // getters:
2565 int size() const { return mData.size()-mPreallocSize; }
2566 bool isEmpty() const { return size() == 0; }
2567 bool autoSqueeze() const { return mAutoSqueeze; }
2568
2569 // setters:
2570 void setAutoSqueeze(bool enabled);
2571
2572 // non-virtual methods:
2573 void set(const QCPDataContainer<DataType> &data);
2574 void set(const QVector<DataType> &data, bool alreadySorted=false);
2575 void add(const QCPDataContainer<DataType> &data);
2576 void add(const QVector<DataType> &data, bool alreadySorted=false);
2577 void add(const DataType &data);
2578 void removeBefore(double sortKey);
2579 void removeAfter(double sortKey);
2580 void remove(double sortKeyFrom, double sortKeyTo);
2581 void remove(double sortKey);
2582 void clear();
2583 void sort();
2584 void squeeze(bool preAllocation=true, bool postAllocation=true);
2585
2586 const_iterator constBegin() const { return mData.constBegin()+mPreallocSize; }
2587 const_iterator constEnd() const { return mData.constEnd(); }
2588 iterator begin() { return mData.begin()+mPreallocSize; }
2589 iterator end() { return mData.end(); }
2590 const_iterator findBegin(double sortKey, bool expandedRange=true) const;
2591 const_iterator findEnd(double sortKey, bool expandedRange=true) const;
2592 const_iterator at(int index) const { return constBegin()+qBound(0, index, size()); }
2593 QCPRange keyRange(bool &foundRange, QCP::SignDomain signDomain=QCP::sdBoth);
2594 QCPRange valueRange(bool &foundRange, QCP::SignDomain signDomain=QCP::sdBoth, const QCPRange &inKeyRange=QCPRange());
2595 QCPDataRange dataRange() const { return QCPDataRange(0, size()); }
2596 void limitIteratorsToDataRange(const_iterator &begin, const_iterator &end, const QCPDataRange &dataRange) const;
2597
2598protected:
2599 // property members:
2600 bool mAutoSqueeze;
2601
2602 // non-property memebers:
2603 QVector<DataType> mData;
2604 int mPreallocSize;
2605 int mPreallocIteration;
2606
2607 // non-virtual methods:
2608 void preallocateGrow(int minimumPreallocSize);
2609 void performAutoSqueeze();
2610};
2611
2612
2613
2614// include implementation in header since it is a class template:
2615////////////////////////////////////////////////////////////////////////////////////////////////////
2616//////////////////// QCPDataContainer
2617////////////////////////////////////////////////////////////////////////////////////////////////////
2618
2619/*! \class QCPDataContainer
2620 \brief The generic data container for one-dimensional plottables
2621
2622 This class template provides a fast container for data storage of one-dimensional data. The data
2623 type is specified as template parameter (called \a DataType in the following) and must provide
2624 some methods as described in the \ref qcpdatacontainer-datatype "next section".
2625
2626 The data is stored in a sorted fashion, which allows very quick lookups by the sorted key as well
2627 as retrieval of ranges (see \ref findBegin, \ref findEnd, \ref keyRange) using binary search. The
2628 container uses a preallocation and a postallocation scheme, such that appending and prepending
2629 data (with respect to the sort key) is very fast and minimizes reallocations. If data is added
2630 which needs to be inserted between existing keys, the merge usually can be done quickly too,
2631 using the fact that existing data is always sorted. The user can further improve performance by
2632 specifying that added data is already itself sorted by key, if he can guarantee that this is the
2633 case (see for example \ref add(const QVector<DataType> &data, bool alreadySorted)).
2634
2635 The data can be accessed with the provided const iterators (\ref constBegin, \ref constEnd). If
2636 it is necessary to alter existing data in-place, the non-const iterators can be used (\ref begin,
2637 \ref end). Changing data members that are not the sort key (for most data types called \a key) is
2638 safe from the container's perspective.
2639
2640 Great care must be taken however if the sort key is modified through the non-const iterators. For
2641 performance reasons, the iterators don't automatically cause a re-sorting upon their
2642 manipulation. It is thus the responsibility of the user to leave the container in a sorted state
2643 when finished with the data manipulation, before calling any other methods on the container. A
2644 complete re-sort (e.g. after finishing all sort key manipulation) can be done by calling \ref
2645 sort. Failing to do so can not be detected by the container efficiently and will cause both
2646 rendering artifacts and potential data loss.
2647
2648 Implementing one-dimensional plottables that make use of a \ref QCPDataContainer<T> is usually
2649 done by subclassing from \ref QCPAbstractPlottable1D "QCPAbstractPlottable1D<T>", which
2650 introduces an according \a mDataContainer member and some convenience methods.
2651
2652 \section qcpdatacontainer-datatype Requirements for the DataType template parameter
2653
2654 The template parameter <tt>DataType</tt> is the type of the stored data points. It must be
2655 trivially copyable and have the following public methods, preferably inline:
2656
2657 \li <tt>double sortKey() const</tt>\n Returns the member variable of this data point that is the
2658 sort key, defining the ordering in the container. Often this variable is simply called \a key.
2659
2660 \li <tt>static DataType fromSortKey(double sortKey)</tt>\n Returns a new instance of the data
2661 type initialized with its sort key set to \a sortKey.
2662
2663 \li <tt>static bool sortKeyIsMainKey()</tt>\n Returns true if the sort key is equal to the main
2664 key (see method \c mainKey below). For most plottables this is the case. It is not the case for
2665 example for \ref QCPCurve, which uses \a t as sort key and \a key as main key. This is the reason
2666 why QCPCurve unlike QCPGraph can display parametric curves with loops.
2667
2668 \li <tt>double mainKey() const</tt>\n Returns the variable of this data point considered the main
2669 key. This is commonly the variable that is used as the coordinate of this data point on the key
2670 axis of the plottable. This method is used for example when determining the automatic axis
2671 rescaling of key axes (\ref QCPAxis::rescale).
2672
2673 \li <tt>double mainValue() const</tt>\n Returns the variable of this data point considered the
2674 main value. This is commonly the variable that is used as the coordinate of this data point on
2675 the value axis of the plottable.
2676
2677 \li <tt>QCPRange valueRange() const</tt>\n Returns the range this data point spans in the value
2678 axis coordinate. If the data is single-valued (e.g. QCPGraphData), this is simply a range with
2679 both lower and upper set to the main data point value. However if the data points can represent
2680 multiple values at once (e.g QCPFinancialData with its \a high, \a low, \a open and \a close
2681 values at each \a key) this method should return the range those values span. This method is used
2682 for example when determining the automatic axis rescaling of value axes (\ref
2683 QCPAxis::rescale).
2684*/
2685
2686/* start documentation of inline functions */
2687
2688/*! \fn int QCPDataContainer<DataType>::size() const
2689
2690 Returns the number of data points in the container.
2691*/
2692
2693/*! \fn bool QCPDataContainer<DataType>::isEmpty() const
2694
2695 Returns whether this container holds no data points.
2696*/
2697
2698/*! \fn QCPDataContainer::const_iterator QCPDataContainer<DataType>::constBegin() const
2699
2700 Returns a const iterator to the first data point in this container.
2701*/
2702
2703/*! \fn QCPDataContainer::const_iterator QCPDataContainer<DataType>::constEnd() const
2704
2705 Returns a const iterator to the element past the last data point in this container.
2706*/
2707
2708/*! \fn QCPDataContainer::iterator QCPDataContainer<DataType>::begin() const
2709
2710 Returns a non-const iterator to the first data point in this container.
2711
2712 You can manipulate the data points in-place through the non-const iterators, but great care must
2713 be taken when manipulating the sort key of a data point, see \ref sort, or the detailed
2714 description of this class.
2715*/
2716
2717/*! \fn QCPDataContainer::iterator QCPDataContainer<DataType>::end() const
2718
2719 Returns a non-const iterator to the element past the last data point in this container.
2720
2721 You can manipulate the data points in-place through the non-const iterators, but great care must
2722 be taken when manipulating the sort key of a data point, see \ref sort, or the detailed
2723 description of this class.
2724*/
2725
2726/*! \fn QCPDataContainer::const_iterator QCPDataContainer<DataType>::at(int index) const
2727
2728 Returns a const iterator to the element with the specified \a index. If \a index points beyond
2729 the available elements in this container, returns \ref constEnd, i.e. an iterator past the last
2730 valid element.
2731
2732 You can use this method to easily obtain iterators from a \ref QCPDataRange, see the \ref
2733 dataselection-accessing "data selection page" for an example.
2734*/
2735
2736/*! \fn QCPDataRange QCPDataContainer::dataRange() const
2737
2738 Returns a \ref QCPDataRange encompassing the entire data set of this container. This means the
2739 begin index of the returned range is 0, and the end index is \ref size.
2740*/
2741
2742/* end documentation of inline functions */
2743
2744/*!
2745 Constructs a QCPDataContainer used for plottable classes that represent a series of key-sorted
2746 data
2747*/
2748template <class DataType>
2750 mAutoSqueeze(true),
2751 mPreallocSize(0),
2752 mPreallocIteration(0)
2753{
2754}
2755
2756/*!
2757 Sets whether the container automatically decides when to release memory from its post- and
2758 preallocation pools when data points are removed. By default this is enabled and for typical
2759 applications shouldn't be changed.
2760
2761 If auto squeeze is disabled, you can manually decide when to release pre-/postallocation with
2762 \ref squeeze.
2763*/
2764template <class DataType>
2766{
2767 if (mAutoSqueeze != enabled)
2768 {
2769 mAutoSqueeze = enabled;
2770 if (mAutoSqueeze)
2771 performAutoSqueeze();
2772 }
2773}
2774
2775/*! \overload
2776
2777 Replaces the current data in this container with the provided \a data.
2778
2779 \see add, remove
2780*/
2781template <class DataType>
2783{
2784 clear();
2785 add(data);
2786}
2787
2788/*! \overload
2789
2790 Replaces the current data in this container with the provided \a data
2791
2792 If you can guarantee that the data points in \a data have ascending order with respect to the
2793 DataType's sort key, set \a alreadySorted to true to avoid an unnecessary sorting run.
2794
2795 \see add, remove
2796*/
2797template <class DataType>
2798void QCPDataContainer<DataType>::set(const QVector<DataType> &data, bool alreadySorted)
2799{
2800 mData = data;
2801 mPreallocSize = 0;
2802 mPreallocIteration = 0;
2803 if (!alreadySorted)
2804 sort();
2805}
2806
2807/*! \overload
2808
2809 Adds the provided \a data to the current data in this container.
2810
2811 \see set, remove
2812*/
2813template <class DataType>
2815{
2816 if (data.isEmpty())
2817 return;
2818
2819 const int n = data.size();
2820 const int oldSize = size();
2821
2822 if (oldSize > 0 && !qcpLessThanSortKey<DataType>(*constBegin(), *(data.constEnd()-1))) // prepend if new data keys are all smaller than or equal to existing ones
2823 {
2824 if (mPreallocSize < n)
2825 preallocateGrow(n);
2826 mPreallocSize -= n;
2827 std::copy(data.constBegin(), data.constEnd(), begin());
2828 } else // don't need to prepend, so append and merge if necessary
2829 {
2830 mData.resize(mData.size()+n);
2831 std::copy(data.constBegin(), data.constEnd(), end()-n);
2832 if (oldSize > 0 && !qcpLessThanSortKey<DataType>(*(constEnd()-n-1), *(constEnd()-n))) // if appended range keys aren't all greater than existing ones, merge the two partitions
2833 std::inplace_merge(begin(), end()-n, end(), qcpLessThanSortKey<DataType>);
2834 }
2835}
2836
2837/*!
2838 Adds the provided data points in \a data to the current data.
2839
2840 If you can guarantee that the data points in \a data have ascending order with respect to the
2841 DataType's sort key, set \a alreadySorted to true to avoid an unnecessary sorting run.
2842
2843 \see set, remove
2844*/
2845template <class DataType>
2846void QCPDataContainer<DataType>::add(const QVector<DataType> &data, bool alreadySorted)
2847{
2848 if (data.isEmpty())
2849 return;
2850 if (isEmpty())
2851 {
2852 set(data, alreadySorted);
2853 return;
2854 }
2855
2856 const int n = data.size();
2857 const int oldSize = size();
2858
2859 if (alreadySorted && oldSize > 0 && !qcpLessThanSortKey<DataType>(*constBegin(), *(data.constEnd()-1))) // prepend if new data is sorted and keys are all smaller than or equal to existing ones
2860 {
2861 if (mPreallocSize < n)
2862 preallocateGrow(n);
2863 mPreallocSize -= n;
2864 std::copy(data.constBegin(), data.constEnd(), begin());
2865 } else // don't need to prepend, so append and then sort and merge if necessary
2866 {
2867 mData.resize(mData.size()+n);
2868 std::copy(data.constBegin(), data.constEnd(), end()-n);
2869 if (!alreadySorted) // sort appended subrange if it wasn't already sorted
2870 std::sort(end()-n, end(), qcpLessThanSortKey<DataType>);
2871 if (oldSize > 0 && !qcpLessThanSortKey<DataType>(*(constEnd()-n-1), *(constEnd()-n))) // if appended range keys aren't all greater than existing ones, merge the two partitions
2872 std::inplace_merge(begin(), end()-n, end(), qcpLessThanSortKey<DataType>);
2873 }
2874}
2875
2876/*! \overload
2877
2878 Adds the provided single data point to the current data.
2879
2880 \see remove
2881*/
2882template <class DataType>
2883void QCPDataContainer<DataType>::add(const DataType &data)
2884{
2885 if (isEmpty() || !qcpLessThanSortKey<DataType>(data, *(constEnd()-1))) // quickly handle appends if new data key is greater or equal to existing ones
2886 {
2887 mData.append(data);
2888 } else if (qcpLessThanSortKey<DataType>(data, *constBegin())) // quickly handle prepends using preallocated space
2889 {
2890 if (mPreallocSize < 1)
2891 preallocateGrow(1);
2892 --mPreallocSize;
2893 *begin() = data;
2894 } else // handle inserts, maintaining sorted keys
2895 {
2896 QCPDataContainer<DataType>::iterator insertionPoint = std::lower_bound(begin(), end(), data, qcpLessThanSortKey<DataType>);
2897 mData.insert(insertionPoint, data);
2898 }
2899}
2900
2901/*!
2902 Removes all data points with (sort-)keys smaller than or equal to \a sortKey.
2903
2904 \see removeAfter, remove, clear
2905*/
2906template <class DataType>
2908{
2910 QCPDataContainer<DataType>::iterator itEnd = std::lower_bound(begin(), end(), DataType::fromSortKey(sortKey), qcpLessThanSortKey<DataType>);
2911 mPreallocSize += int(itEnd-it); // don't actually delete, just add it to the preallocated block (if it gets too large, squeeze will take care of it)
2912 if (mAutoSqueeze)
2913 performAutoSqueeze();
2914}
2915
2916/*!
2917 Removes all data points with (sort-)keys greater than or equal to \a sortKey.
2918
2919 \see removeBefore, remove, clear
2920*/
2921template <class DataType>
2923{
2924 QCPDataContainer<DataType>::iterator it = std::upper_bound(begin(), end(), DataType::fromSortKey(sortKey), qcpLessThanSortKey<DataType>);
2926 mData.erase(it, itEnd); // typically adds it to the postallocated block
2927 if (mAutoSqueeze)
2928 performAutoSqueeze();
2929}
2930
2931/*!
2932 Removes all data points with (sort-)keys between \a sortKeyFrom and \a sortKeyTo. if \a
2933 sortKeyFrom is greater or equal to \a sortKeyTo, the function does nothing. To remove a single
2934 data point with known (sort-)key, use \ref remove(double sortKey).
2935
2936 \see removeBefore, removeAfter, clear
2937*/
2938template <class DataType>
2939void QCPDataContainer<DataType>::remove(double sortKeyFrom, double sortKeyTo)
2940{
2941 if (sortKeyFrom >= sortKeyTo || isEmpty())
2942 return;
2943
2944 QCPDataContainer<DataType>::iterator it = std::lower_bound(begin(), end(), DataType::fromSortKey(sortKeyFrom), qcpLessThanSortKey<DataType>);
2945 QCPDataContainer<DataType>::iterator itEnd = std::upper_bound(it, end(), DataType::fromSortKey(sortKeyTo), qcpLessThanSortKey<DataType>);
2946 mData.erase(it, itEnd);
2947 if (mAutoSqueeze)
2948 performAutoSqueeze();
2949}
2950
2951/*! \overload
2952
2953 Removes a single data point at \a sortKey. If the position is not known with absolute (binary)
2954 precision, consider using \ref remove(double sortKeyFrom, double sortKeyTo) with a small
2955 fuzziness interval around the suspected position, depeding on the precision with which the
2956 (sort-)key is known.
2957
2958 \see removeBefore, removeAfter, clear
2959*/
2960template <class DataType>
2962{
2963 QCPDataContainer::iterator it = std::lower_bound(begin(), end(), DataType::fromSortKey(sortKey), qcpLessThanSortKey<DataType>);
2964 if (it != end() && it->sortKey() == sortKey)
2965 {
2966 if (it == begin())
2967 ++mPreallocSize; // don't actually delete, just add it to the preallocated block (if it gets too large, squeeze will take care of it)
2968 else
2969 mData.erase(it);
2970 }
2971 if (mAutoSqueeze)
2972 performAutoSqueeze();
2973}
2974
2975/*!
2976 Removes all data points.
2977
2978 \see remove, removeAfter, removeBefore
2979*/
2980template <class DataType>
2982{
2983 mData.clear();
2984 mPreallocIteration = 0;
2985 mPreallocSize = 0;
2986}
2987
2988/*!
2989 Re-sorts all data points in the container by their sort key.
2990
2991 When setting, adding or removing points using the QCPDataContainer interface (\ref set, \ref add,
2992 \ref remove, etc.), the container makes sure to always stay in a sorted state such that a full
2993 resort is never necessary. However, if you choose to directly manipulate the sort key on data
2994 points by accessing and modifying it through the non-const iterators (\ref begin, \ref end), it
2995 is your responsibility to bring the container back into a sorted state before any other methods
2996 are called on it. This can be achieved by calling this method immediately after finishing the
2997 sort key manipulation.
2998*/
2999template <class DataType>
3001{
3002 std::sort(begin(), end(), qcpLessThanSortKey<DataType>);
3003}
3004
3005/*!
3006 Frees all unused memory that is currently in the preallocation and postallocation pools.
3007
3008 Note that QCPDataContainer automatically decides whether squeezing is necessary, if \ref
3009 setAutoSqueeze is left enabled. It should thus not be necessary to use this method for typical
3010 applications.
3011
3012 The parameters \a preAllocation and \a postAllocation control whether pre- and/or post allocation
3013 should be freed, respectively.
3014*/
3015template <class DataType>
3016void QCPDataContainer<DataType>::squeeze(bool preAllocation, bool postAllocation)
3017{
3018 if (preAllocation)
3019 {
3020 if (mPreallocSize > 0)
3021 {
3022 std::copy(begin(), end(), mData.begin());
3023 mData.resize(size());
3024 mPreallocSize = 0;
3025 }
3026 mPreallocIteration = 0;
3027 }
3028 if (postAllocation)
3029 mData.squeeze();
3030}
3031
3032/*!
3033 Returns an iterator to the data point with a (sort-)key that is equal to, just below, or just
3034 above \a sortKey. If \a expandedRange is true, the data point just below \a sortKey will be
3035 considered, otherwise the one just above.
3036
3037 This can be used in conjunction with \ref findEnd to iterate over data points within a given key
3038 range, including or excluding the bounding data points that are just beyond the specified range.
3039
3040 If \a expandedRange is true but there are no data points below \a sortKey, \ref constBegin is
3041 returned.
3042
3043 If the container is empty, returns \ref constEnd.
3044
3045 \see findEnd, QCPPlottableInterface1D::findBegin
3046*/
3047template <class DataType>
3049{
3050 if (isEmpty())
3051 return constEnd();
3052
3053 QCPDataContainer<DataType>::const_iterator it = std::lower_bound(constBegin(), constEnd(), DataType::fromSortKey(sortKey), qcpLessThanSortKey<DataType>);
3054 if (expandedRange && it != constBegin()) // also covers it == constEnd case, and we know --constEnd is valid because mData isn't empty
3055 --it;
3056 return it;
3057}
3058
3059/*!
3060 Returns an iterator to the element after the data point with a (sort-)key that is equal to, just
3061 above or just below \a sortKey. If \a expandedRange is true, the data point just above \a sortKey
3062 will be considered, otherwise the one just below.
3063
3064 This can be used in conjunction with \ref findBegin to iterate over data points within a given
3065 key range, including the bounding data points that are just below and above the specified range.
3066
3067 If \a expandedRange is true but there are no data points above \a sortKey, \ref constEnd is
3068 returned.
3069
3070 If the container is empty, \ref constEnd is returned.
3071
3072 \see findBegin, QCPPlottableInterface1D::findEnd
3073*/
3074template <class DataType>
3076{
3077 if (isEmpty())
3078 return constEnd();
3079
3080 QCPDataContainer<DataType>::const_iterator it = std::upper_bound(constBegin(), constEnd(), DataType::fromSortKey(sortKey), qcpLessThanSortKey<DataType>);
3081 if (expandedRange && it != constEnd())
3082 ++it;
3083 return it;
3084}
3085
3086/*!
3087 Returns the range encompassed by the (main-)key coordinate of all data points. The output
3088 parameter \a foundRange indicates whether a sensible range was found. If this is false, you
3089 should not use the returned QCPRange (e.g. the data container is empty or all points have the
3090 same key).
3091
3092 Use \a signDomain to control which sign of the key coordinates should be considered. This is
3093 relevant e.g. for logarithmic plots which can mathematically only display one sign domain at a
3094 time.
3095
3096 If the DataType reports that its main key is equal to the sort key (\a sortKeyIsMainKey), as is
3097 the case for most plottables, this method uses this fact and finds the range very quickly.
3098
3099 \see valueRange
3100*/
3101template <class DataType>
3103{
3104 if (isEmpty())
3105 {
3106 foundRange = false;
3107 return QCPRange();
3108 }
3109 QCPRange range;
3110 bool haveLower = false;
3111 bool haveUpper = false;
3112 double current;
3113
3116 if (signDomain == QCP::sdBoth) // range may be anywhere
3117 {
3118 if (DataType::sortKeyIsMainKey()) // if DataType is sorted by main key (e.g. QCPGraph, but not QCPCurve), use faster algorithm by finding just first and last key with non-NaN value
3119 {
3120 while (it != itEnd) // find first non-nan going up from left
3121 {
3122 if (!qIsNaN(it->mainValue()))
3123 {
3124 range.lower = it->mainKey();
3125 haveLower = true;
3126 break;
3127 }
3128 ++it;
3129 }
3130 it = itEnd;
3131 while (it != constBegin()) // find first non-nan going down from right
3132 {
3133 --it;
3134 if (!qIsNaN(it->mainValue()))
3135 {
3136 range.upper = it->mainKey();
3137 haveUpper = true;
3138 break;
3139 }
3140 }
3141 } else // DataType is not sorted by main key, go through all data points and accordingly expand range
3142 {
3143 while (it != itEnd)
3144 {
3145 if (!qIsNaN(it->mainValue()))
3146 {
3147 current = it->mainKey();
3148 if (current < range.lower || !haveLower)
3149 {
3150 range.lower = current;
3151 haveLower = true;
3152 }
3153 if (current > range.upper || !haveUpper)
3154 {
3155 range.upper = current;
3156 haveUpper = true;
3157 }
3158 }
3159 ++it;
3160 }
3161 }
3162 } else if (signDomain == QCP::sdNegative) // range may only be in the negative sign domain
3163 {
3164 while (it != itEnd)
3165 {
3166 if (!qIsNaN(it->mainValue()))
3167 {
3168 current = it->mainKey();
3169 if ((current < range.lower || !haveLower) && current < 0)
3170 {
3171 range.lower = current;
3172 haveLower = true;
3173 }
3174 if ((current > range.upper || !haveUpper) && current < 0)
3175 {
3176 range.upper = current;
3177 haveUpper = true;
3178 }
3179 }
3180 ++it;
3181 }
3182 } else if (signDomain == QCP::sdPositive) // range may only be in the positive sign domain
3183 {
3184 while (it != itEnd)
3185 {
3186 if (!qIsNaN(it->mainValue()))
3187 {
3188 current = it->mainKey();
3189 if ((current < range.lower || !haveLower) && current > 0)
3190 {
3191 range.lower = current;
3192 haveLower = true;
3193 }
3194 if ((current > range.upper || !haveUpper) && current > 0)
3195 {
3196 range.upper = current;
3197 haveUpper = true;
3198 }
3199 }
3200 ++it;
3201 }
3202 }
3203
3204 foundRange = haveLower && haveUpper;
3205 return range;
3206}
3207
3208/*!
3209 Returns the range encompassed by the value coordinates of the data points in the specified key
3210 range (\a inKeyRange), using the full \a DataType::valueRange reported by the data points. The
3211 output parameter \a foundRange indicates whether a sensible range was found. If this is false,
3212 you should not use the returned QCPRange (e.g. the data container is empty or all points have the
3213 same value).
3214
3215 If \a inKeyRange has both lower and upper bound set to zero (is equal to <tt>QCPRange()</tt>),
3216 all data points are considered, without any restriction on the keys.
3217
3218 Use \a signDomain to control which sign of the value coordinates should be considered. This is
3219 relevant e.g. for logarithmic plots which can mathematically only display one sign domain at a
3220 time.
3221
3222 \see keyRange
3223*/
3224template <class DataType>
3225QCPRange QCPDataContainer<DataType>::valueRange(bool &foundRange, QCP::SignDomain signDomain, const QCPRange &inKeyRange)
3226{
3227 if (isEmpty())
3228 {
3229 foundRange = false;
3230 return QCPRange();
3231 }
3232 QCPRange range;
3233 const bool restrictKeyRange = inKeyRange != QCPRange();
3234 bool haveLower = false;
3235 bool haveUpper = false;
3236 QCPRange current;
3237 QCPDataContainer<DataType>::const_iterator itBegin = constBegin();
3239 if (DataType::sortKeyIsMainKey() && restrictKeyRange)
3240 {
3241 itBegin = findBegin(inKeyRange.lower, false);
3242 itEnd = findEnd(inKeyRange.upper, false);
3243 }
3244 if (signDomain == QCP::sdBoth) // range may be anywhere
3245 {
3246 for (QCPDataContainer<DataType>::const_iterator it = itBegin; it != itEnd; ++it)
3247 {
3248 if (restrictKeyRange && (it->mainKey() < inKeyRange.lower || it->mainKey() > inKeyRange.upper))
3249 continue;
3250 current = it->valueRange();
3251 if ((current.lower < range.lower || !haveLower) && !qIsNaN(current.lower))
3252 {
3253 range.lower = current.lower;
3254 haveLower = true;
3255 }
3256 if ((current.upper > range.upper || !haveUpper) && !qIsNaN(current.upper))
3257 {
3258 range.upper = current.upper;
3259 haveUpper = true;
3260 }
3261 }
3262 } else if (signDomain == QCP::sdNegative) // range may only be in the negative sign domain
3263 {
3264 for (QCPDataContainer<DataType>::const_iterator it = itBegin; it != itEnd; ++it)
3265 {
3266 if (restrictKeyRange && (it->mainKey() < inKeyRange.lower || it->mainKey() > inKeyRange.upper))
3267 continue;
3268 current = it->valueRange();
3269 if ((current.lower < range.lower || !haveLower) && current.lower < 0 && !qIsNaN(current.lower))
3270 {
3271 range.lower = current.lower;
3272 haveLower = true;
3273 }
3274 if ((current.upper > range.upper || !haveUpper) && current.upper < 0 && !qIsNaN(current.upper))
3275 {
3276 range.upper = current.upper;
3277 haveUpper = true;
3278 }
3279 }
3280 } else if (signDomain == QCP::sdPositive) // range may only be in the positive sign domain
3281 {
3282 for (QCPDataContainer<DataType>::const_iterator it = itBegin; it != itEnd; ++it)
3283 {
3284 if (restrictKeyRange && (it->mainKey() < inKeyRange.lower || it->mainKey() > inKeyRange.upper))
3285 continue;
3286 current = it->valueRange();
3287 if ((current.lower < range.lower || !haveLower) && current.lower > 0 && !qIsNaN(current.lower))
3288 {
3289 range.lower = current.lower;
3290 haveLower = true;
3291 }
3292 if ((current.upper > range.upper || !haveUpper) && current.upper > 0 && !qIsNaN(current.upper))
3293 {
3294 range.upper = current.upper;
3295 haveUpper = true;
3296 }
3297 }
3298 }
3299
3300 foundRange = haveLower && haveUpper;
3301 return range;
3302}
3303
3304/*!
3305 Makes sure \a begin and \a end mark a data range that is both within the bounds of this data
3306 container's data, as well as within the specified \a dataRange. The initial range described by
3307 the passed iterators \a begin and \a end is never expanded, only contracted if necessary.
3308
3309 This function doesn't require for \a dataRange to be within the bounds of this data container's
3310 valid range.
3311*/
3312template <class DataType>
3314{
3315 QCPDataRange iteratorRange(int(begin-constBegin()), int(end-constBegin()));
3316 iteratorRange = iteratorRange.bounded(dataRange.bounded(this->dataRange()));
3317 begin = constBegin()+iteratorRange.begin();
3318 end = constBegin()+iteratorRange.end();
3319}
3320
3321/*! \internal
3322
3323 Increases the preallocation pool to have a size of at least \a minimumPreallocSize. Depending on
3324 the preallocation history, the container will grow by more than requested, to speed up future
3325 consecutive size increases.
3326
3327 if \a minimumPreallocSize is smaller than or equal to the current preallocation pool size, this
3328 method does nothing.
3329*/
3330template <class DataType>
3332{
3333 if (minimumPreallocSize <= mPreallocSize)
3334 return;
3335
3336 int newPreallocSize = minimumPreallocSize;
3337 newPreallocSize += (1u<<qBound(4, mPreallocIteration+4, 15)) - 12; // do 4 up to 32768-12 preallocation, doubling in each intermediate iteration
3338 ++mPreallocIteration;
3339
3340 int sizeDifference = newPreallocSize-mPreallocSize;
3341 mData.resize(mData.size()+sizeDifference);
3342 std::copy_backward(mData.begin()+mPreallocSize, mData.end()-sizeDifference, mData.end());
3343 mPreallocSize = newPreallocSize;
3344}
3345
3346/*! \internal
3347
3348 This method decides, depending on the total allocation size and the size of the unused pre- and
3349 postallocation pools, whether it is sensible to reduce the pools in order to free up unused
3350 memory. It then possibly calls \ref squeeze to do the deallocation.
3351
3352 If \ref setAutoSqueeze is enabled, this method is called automatically each time data points are
3353 removed from the container (e.g. \ref remove).
3354
3355 \note when changing the decision parameters, care must be taken not to cause a back-and-forth
3356 between squeezing and reallocation due to the growth strategy of the internal QVector and \ref
3357 preallocateGrow. The hysteresis between allocation and deallocation should be made high enough
3358 (at the expense of possibly larger unused memory from time to time).
3359*/
3360template <class DataType>
3362{
3363 const int totalAlloc = mData.capacity();
3364 const int postAllocSize = totalAlloc-mData.size();
3365 const int usedSize = size();
3366 bool shrinkPostAllocation = false;
3367 bool shrinkPreAllocation = false;
3368 if (totalAlloc > 650000) // if allocation is larger, shrink earlier with respect to total used size
3369 {
3370 shrinkPostAllocation = postAllocSize > usedSize*1.5; // QVector grow strategy is 2^n for static data. Watch out not to oscillate!
3371 shrinkPreAllocation = mPreallocSize*10 > usedSize;
3372 } else if (totalAlloc > 1000) // below 10 MiB raw data be generous with preallocated memory, below 1k points don't even bother
3373 {
3374 shrinkPostAllocation = postAllocSize > usedSize*5;
3375 shrinkPreAllocation = mPreallocSize > usedSize*1.5; // preallocation can grow into postallocation, so can be smaller
3376 }
3377
3378 if (shrinkPreAllocation || shrinkPostAllocation)
3379 squeeze(shrinkPreAllocation, shrinkPostAllocation);
3380}
3381
3382
3383/* end of 'src/datacontainer.h' */
3384
3385
3386/* including file 'src/plottable.h' */
3387/* modified 2021-03-29T02:30:44, size 8461 */
3388
3389class QCP_LIB_DECL QCPSelectionDecorator
3390{
3391 Q_GADGET
3392public:
3394 virtual ~QCPSelectionDecorator();
3395
3396 // getters:
3397 QPen pen() const { return mPen; }
3398 QBrush brush() const { return mBrush; }
3399 QCPScatterStyle scatterStyle() const { return mScatterStyle; }
3400 QCPScatterStyle::ScatterProperties usedScatterProperties() const { return mUsedScatterProperties; }
3401
3402 // setters:
3403 void setPen(const QPen &pen);
3404 void setBrush(const QBrush &brush);
3405 void setScatterStyle(const QCPScatterStyle &scatterStyle, QCPScatterStyle::ScatterProperties usedProperties=QCPScatterStyle::spPen);
3406 void setUsedScatterProperties(const QCPScatterStyle::ScatterProperties &properties);
3407
3408 // non-virtual methods:
3409 void applyPen(QCPPainter *painter) const;
3410 void applyBrush(QCPPainter *painter) const;
3411 QCPScatterStyle getFinalScatterStyle(const QCPScatterStyle &unselectedStyle) const;
3412
3413 // introduced virtual methods:
3414 virtual void copyFrom(const QCPSelectionDecorator *other);
3415 virtual void drawDecoration(QCPPainter *painter, QCPDataSelection selection);
3416
3417protected:
3418 // property members:
3419 QPen mPen;
3420 QBrush mBrush;
3421 QCPScatterStyle mScatterStyle;
3422 QCPScatterStyle::ScatterProperties mUsedScatterProperties;
3423 // non-property members:
3424 QCPAbstractPlottable *mPlottable;
3425
3426 // introduced virtual methods:
3427 virtual bool registerWithPlottable(QCPAbstractPlottable *plottable);
3428
3429private:
3430 Q_DISABLE_COPY(QCPSelectionDecorator)
3431 friend class QCPAbstractPlottable;
3432};
3433Q_DECLARE_METATYPE(QCPSelectionDecorator*)
3434
3435
3436class QCP_LIB_DECL QCPAbstractPlottable : public QCPLayerable
3437{
3438 Q_OBJECT
3439 /// \cond INCLUDE_QPROPERTIES
3440 Q_PROPERTY(QString name READ name WRITE setName)
3441 Q_PROPERTY(bool antialiasedFill READ antialiasedFill WRITE setAntialiasedFill)
3442 Q_PROPERTY(bool antialiasedScatters READ antialiasedScatters WRITE setAntialiasedScatters)
3443 Q_PROPERTY(QPen pen READ pen WRITE setPen)
3444 Q_PROPERTY(QBrush brush READ brush WRITE setBrush)
3445 Q_PROPERTY(QCPAxis* keyAxis READ keyAxis WRITE setKeyAxis)
3446 Q_PROPERTY(QCPAxis* valueAxis READ valueAxis WRITE setValueAxis)
3447 Q_PROPERTY(QCP::SelectionType selectable READ selectable WRITE setSelectable NOTIFY selectableChanged)
3450 /// \endcond
3451public:
3452 QCPAbstractPlottable(QCPAxis *keyAxis, QCPAxis *valueAxis);
3453 virtual ~QCPAbstractPlottable() Q_DECL_OVERRIDE;
3454
3455 // getters:
3456 QString name() const { return mName; }
3457 bool antialiasedFill() const { return mAntialiasedFill; }
3458 bool antialiasedScatters() const { return mAntialiasedScatters; }
3459 QPen pen() const { return mPen; }
3460 QBrush brush() const { return mBrush; }
3461 QCPAxis *keyAxis() const { return mKeyAxis.data(); }
3462 QCPAxis *valueAxis() const { return mValueAxis.data(); }
3463 QCP::SelectionType selectable() const { return mSelectable; }
3464 bool selected() const { return !mSelection.isEmpty(); }
3465 QCPDataSelection selection() const { return mSelection; }
3466 QCPSelectionDecorator *selectionDecorator() const { return mSelectionDecorator; }
3467
3468 // setters:
3469 void setName(const QString &name);
3470 void setAntialiasedFill(bool enabled);
3471 void setAntialiasedScatters(bool enabled);
3472 void setPen(const QPen &pen);
3473 void setBrush(const QBrush &brush);
3474 void setKeyAxis(QCPAxis *axis);
3475 void setValueAxis(QCPAxis *axis);
3476 Q_SLOT void setSelectable(QCP::SelectionType selectable);
3479
3480 // introduced virtual methods:
3481 virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE = 0; // actually introduced in QCPLayerable as non-pure, but we want to force reimplementation for plottables
3482 virtual QCPPlottableInterface1D *interface1D() { return nullptr; }
3483 virtual QCPRange getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth) const = 0;
3484 virtual QCPRange getValueRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth, const QCPRange &inKeyRange=QCPRange()) const = 0;
3485
3486 // non-property methods:
3487 void coordsToPixels(double key, double value, double &x, double &y) const;
3488 const QPointF coordsToPixels(double key, double value) const;
3489 void pixelsToCoords(double x, double y, double &key, double &value) const;
3490 void pixelsToCoords(const QPointF &pixelPos, double &key, double &value) const;
3491 void rescaleAxes(bool onlyEnlarge=false) const;
3492 void rescaleKeyAxis(bool onlyEnlarge=false) const;
3493 void rescaleValueAxis(bool onlyEnlarge=false, bool inKeyRange=false) const;
3494 bool addToLegend(QCPLegend *legend);
3495 bool addToLegend();
3496 bool removeFromLegend(QCPLegend *legend) const;
3497 bool removeFromLegend() const;
3498
3499signals:
3503
3504protected:
3505 // property members:
3506 QString mName;
3507 bool mAntialiasedFill, mAntialiasedScatters;
3508 QPen mPen;
3509 QBrush mBrush;
3510 QPointer<QCPAxis> mKeyAxis, mValueAxis;
3511 QCP::SelectionType mSelectable;
3512 QCPDataSelection mSelection;
3513 QCPSelectionDecorator *mSelectionDecorator;
3514
3515 // reimplemented virtual methods:
3516 virtual QRect clipRect() const Q_DECL_OVERRIDE;
3517 virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE = 0;
3518 virtual QCP::Interaction selectionCategory() const Q_DECL_OVERRIDE;
3519 void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE;
3520 // events:
3521 virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) Q_DECL_OVERRIDE;
3522 virtual void deselectEvent(bool *selectionStateChanged) Q_DECL_OVERRIDE;
3523
3524 // introduced virtual methods:
3525 virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const = 0;
3526
3527 // non-virtual methods:
3528 void applyFillAntialiasingHint(QCPPainter *painter) const;
3529 void applyScattersAntialiasingHint(QCPPainter *painter) const;
3530
3531private:
3532 Q_DISABLE_COPY(QCPAbstractPlottable)
3533
3534 friend class QCustomPlot;
3535 friend class QCPAxis;
3536 friend class QCPPlottableLegendItem;
3537};
3538
3539
3540/* end of 'src/plottable.h' */
3541
3542
3543/* including file 'src/item.h' */
3544/* modified 2021-03-29T02:30:44, size 9425 */
3545
3546class QCP_LIB_DECL QCPItemAnchor
3547{
3548 Q_GADGET
3549public:
3550 QCPItemAnchor(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString &name, int anchorId=-1);
3551 virtual ~QCPItemAnchor();
3552
3553 // getters:
3554 QString name() const { return mName; }
3555 virtual QPointF pixelPosition() const;
3556
3557protected:
3558 // property members:
3559 QString mName;
3560
3561 // non-property members:
3562 QCustomPlot *mParentPlot;
3563 QCPAbstractItem *mParentItem;
3564 int mAnchorId;
3565 QSet<QCPItemPosition*> mChildrenX, mChildrenY;
3566
3567 // introduced virtual methods:
3568 virtual QCPItemPosition *toQCPItemPosition() { return nullptr; }
3569
3570 // non-virtual methods:
3571 void addChildX(QCPItemPosition* pos); // called from pos when this anchor is set as parent
3572 void removeChildX(QCPItemPosition *pos); // called from pos when its parent anchor is reset or pos deleted
3573 void addChildY(QCPItemPosition* pos); // called from pos when this anchor is set as parent
3574 void removeChildY(QCPItemPosition *pos); // called from pos when its parent anchor is reset or pos deleted
3575
3576private:
3577 Q_DISABLE_COPY(QCPItemAnchor)
3578
3579 friend class QCPItemPosition;
3580};
3581
3582
3583
3584class QCP_LIB_DECL QCPItemPosition : public QCPItemAnchor
3585{
3586 Q_GADGET
3587public:
3588 /*!
3589 Defines the ways an item position can be specified. Thus it defines what the numbers passed to
3590 \ref setCoords actually mean.
3591
3592 \see setType
3593 */
3594 enum PositionType { ptAbsolute ///< Static positioning in pixels, starting from the top left corner of the viewport/widget.
3595 ,ptViewportRatio ///< Static positioning given by a fraction of the viewport size. For example, if you call setCoords(0, 0), the position will be at the top
3596 ///< left corner of the viewport/widget. setCoords(1, 1) will be at the bottom right corner, setCoords(0.5, 0) will be horizontally centered and
3597 ///< vertically at the top of the viewport/widget, etc.
3598 ,ptAxisRectRatio ///< Static positioning given by a fraction of the axis rect size (see \ref setAxisRect). For example, if you call setCoords(0, 0), the position will be at the top
3599 ///< left corner of the axis rect. setCoords(1, 1) will be at the bottom right corner, setCoords(0.5, 0) will be horizontally centered and
3600 ///< vertically at the top of the axis rect, etc. You can also go beyond the axis rect by providing negative coordinates or coordinates larger than 1.
3601 ,ptPlotCoords ///< Dynamic positioning at a plot coordinate defined by two axes (see \ref setAxes).
3603 Q_ENUMS(PositionType)
3604
3605 QCPItemPosition(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString &name);
3606 virtual ~QCPItemPosition() Q_DECL_OVERRIDE;
3607
3608 // getters:
3609 PositionType type() const { return typeX(); }
3610 PositionType typeX() const { return mPositionTypeX; }
3611 PositionType typeY() const { return mPositionTypeY; }
3612 QCPItemAnchor *parentAnchor() const { return parentAnchorX(); }
3613 QCPItemAnchor *parentAnchorX() const { return mParentAnchorX; }
3614 QCPItemAnchor *parentAnchorY() const { return mParentAnchorY; }
3615 double key() const { return mKey; }
3616 double value() const { return mValue; }
3617 QPointF coords() const { return QPointF(mKey, mValue); }
3618 QCPAxis *keyAxis() const { return mKeyAxis.data(); }
3619 QCPAxis *valueAxis() const { return mValueAxis.data(); }
3620 QCPAxisRect *axisRect() const;
3621 virtual QPointF pixelPosition() const Q_DECL_OVERRIDE;
3622
3623 // setters:
3624 void setType(PositionType type);
3625 void setTypeX(PositionType type);
3626 void setTypeY(PositionType type);
3627 bool setParentAnchor(QCPItemAnchor *parentAnchor, bool keepPixelPosition=false);
3628 bool setParentAnchorX(QCPItemAnchor *parentAnchor, bool keepPixelPosition=false);
3629 bool setParentAnchorY(QCPItemAnchor *parentAnchor, bool keepPixelPosition=false);
3630 void setCoords(double key, double value);
3631 void setCoords(const QPointF &pos);
3632 void setAxes(QCPAxis* keyAxis, QCPAxis* valueAxis);
3633 void setAxisRect(QCPAxisRect *axisRect);
3634 void setPixelPosition(const QPointF &pixelPosition);
3635
3636protected:
3637 // property members:
3638 PositionType mPositionTypeX, mPositionTypeY;
3639 QPointer<QCPAxis> mKeyAxis, mValueAxis;
3640 QPointer<QCPAxisRect> mAxisRect;
3641 double mKey, mValue;
3642 QCPItemAnchor *mParentAnchorX, *mParentAnchorY;
3643
3644 // reimplemented virtual methods:
3645 virtual QCPItemPosition *toQCPItemPosition() Q_DECL_OVERRIDE { return this; }
3646
3647private:
3648 Q_DISABLE_COPY(QCPItemPosition)
3649
3650};
3651Q_DECLARE_METATYPE(QCPItemPosition::PositionType)
3652
3653
3654class QCP_LIB_DECL QCPAbstractItem : public QCPLayerable
3655{
3656 Q_OBJECT
3657 /// \cond INCLUDE_QPROPERTIES
3658 Q_PROPERTY(bool clipToAxisRect READ clipToAxisRect WRITE setClipToAxisRect)
3659 Q_PROPERTY(QCPAxisRect* clipAxisRect READ clipAxisRect WRITE setClipAxisRect)
3660 Q_PROPERTY(bool selectable READ selectable WRITE setSelectable NOTIFY selectableChanged)
3661 Q_PROPERTY(bool selected READ selected WRITE setSelected NOTIFY selectionChanged)
3662 /// \endcond
3663public:
3664 explicit QCPAbstractItem(QCustomPlot *parentPlot);
3665 virtual ~QCPAbstractItem() Q_DECL_OVERRIDE;
3666
3667 // getters:
3668 bool clipToAxisRect() const { return mClipToAxisRect; }
3669 QCPAxisRect *clipAxisRect() const;
3670 bool selectable() const { return mSelectable; }
3671 bool selected() const { return mSelected; }
3672
3673 // setters:
3674 void setClipToAxisRect(bool clip);
3675 void setClipAxisRect(QCPAxisRect *rect);
3676 Q_SLOT void setSelectable(bool selectable);
3677 Q_SLOT void setSelected(bool selected);
3678
3679 // reimplemented virtual methods:
3680 virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE = 0;
3681
3682 // non-virtual methods:
3683 QList<QCPItemPosition*> positions() const { return mPositions; }
3684 QList<QCPItemAnchor*> anchors() const { return mAnchors; }
3685 QCPItemPosition *position(const QString &name) const;
3686 QCPItemAnchor *anchor(const QString &name) const;
3687 bool hasAnchor(const QString &name) const;
3688
3689signals:
3690 void selectionChanged(bool selected);
3691 void selectableChanged(bool selectable);
3692
3693protected:
3694 // property members:
3695 bool mClipToAxisRect;
3696 QPointer<QCPAxisRect> mClipAxisRect;
3697 QList<QCPItemPosition*> mPositions;
3698 QList<QCPItemAnchor*> mAnchors;
3699 bool mSelectable, mSelected;
3700
3701 // reimplemented virtual methods:
3702 virtual QCP::Interaction selectionCategory() const Q_DECL_OVERRIDE;
3703 virtual QRect clipRect() const Q_DECL_OVERRIDE;
3704 virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE;
3705 virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE = 0;
3706 // events:
3707 virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) Q_DECL_OVERRIDE;
3708 virtual void deselectEvent(bool *selectionStateChanged) Q_DECL_OVERRIDE;
3709
3710 // introduced virtual methods:
3711 virtual QPointF anchorPixelPosition(int anchorId) const;
3712
3713 // non-virtual methods:
3714 double rectDistance(const QRectF &rect, const QPointF &pos, bool filledRect) const;
3715 QCPItemPosition *createPosition(const QString &name);
3716 QCPItemAnchor *createAnchor(const QString &name, int anchorId);
3717
3718private:
3719 Q_DISABLE_COPY(QCPAbstractItem)
3720
3721 friend class QCustomPlot;
3722 friend class QCPItemAnchor;
3723};
3724
3725/* end of 'src/item.h' */
3726
3727
3728/* including file 'src/core.h' */
3729/* modified 2021-03-29T02:30:44, size 19304 */
3730
3731class QCP_LIB_DECL QCustomPlot : public QWidget
3732{
3733 Q_OBJECT
3734 /// \cond INCLUDE_QPROPERTIES
3735 Q_PROPERTY(QRect viewport READ viewport WRITE setViewport)
3736 Q_PROPERTY(QPixmap background READ background WRITE setBackground)
3737 Q_PROPERTY(bool backgroundScaled READ backgroundScaled WRITE setBackgroundScaled)
3738 Q_PROPERTY(Qt::AspectRatioMode backgroundScaledMode READ backgroundScaledMode WRITE setBackgroundScaledMode)
3739 Q_PROPERTY(QCPLayoutGrid* plotLayout READ plotLayout)
3740 Q_PROPERTY(bool autoAddPlottableToLegend READ autoAddPlottableToLegend WRITE setAutoAddPlottableToLegend)
3741 Q_PROPERTY(int selectionTolerance READ selectionTolerance WRITE setSelectionTolerance)
3742 Q_PROPERTY(bool noAntialiasingOnDrag READ noAntialiasingOnDrag WRITE setNoAntialiasingOnDrag)
3743 Q_PROPERTY(Qt::KeyboardModifier multiSelectModifier READ multiSelectModifier WRITE setMultiSelectModifier)
3744 Q_PROPERTY(bool openGl READ openGl WRITE setOpenGl)
3745 /// \endcond
3746public:
3747 /*!
3748 Defines how a layer should be inserted relative to an other layer.
3749
3750 \see addLayer, moveLayer
3751 */
3752 enum LayerInsertMode { limBelow ///< Layer is inserted below other layer
3753 ,limAbove ///< Layer is inserted above other layer
3755 Q_ENUMS(LayerInsertMode)
3756
3757 /*!
3758 Defines with what timing the QCustomPlot surface is refreshed after a replot.
3759
3760 \see replot
3761 */
3762 enum RefreshPriority { rpImmediateRefresh ///< Replots immediately and repaints the widget immediately by calling QWidget::repaint() after the replot
3763 ,rpQueuedRefresh ///< Replots immediately, but queues the widget repaint, by calling QWidget::update() after the replot. This way multiple redundant widget repaints can be avoided.
3764 ,rpRefreshHint ///< Whether to use immediate or queued refresh depends on whether the plotting hint \ref QCP::phImmediateRefresh is set, see \ref setPlottingHints.
3765 ,rpQueuedReplot ///< Queues the entire replot for the next event loop iteration. This way multiple redundant replots can be avoided. The actual replot is then done with \ref rpRefreshHint priority.
3767 Q_ENUMS(RefreshPriority)
3768
3769 explicit QCustomPlot(QWidget *parent = nullptr);
3770 virtual ~QCustomPlot() Q_DECL_OVERRIDE;
3771
3772 // getters:
3773 QRect viewport() const { return mViewport; }
3774 double bufferDevicePixelRatio() const { return mBufferDevicePixelRatio; }
3775 QPixmap background() const { return mBackgroundPixmap; }
3776 bool backgroundScaled() const { return mBackgroundScaled; }
3777 Qt::AspectRatioMode backgroundScaledMode() const { return mBackgroundScaledMode; }
3778 QCPLayoutGrid *plotLayout() const { return mPlotLayout; }
3779 QCP::AntialiasedElements antialiasedElements() const { return mAntialiasedElements; }
3780 QCP::AntialiasedElements notAntialiasedElements() const { return mNotAntialiasedElements; }
3781 bool autoAddPlottableToLegend() const { return mAutoAddPlottableToLegend; }
3782 const QCP::Interactions interactions() const { return mInteractions; }
3783 int selectionTolerance() const { return mSelectionTolerance; }
3784 bool noAntialiasingOnDrag() const { return mNoAntialiasingOnDrag; }
3785 QCP::PlottingHints plottingHints() const { return mPlottingHints; }
3786 Qt::KeyboardModifier multiSelectModifier() const { return mMultiSelectModifier; }
3787 QCP::SelectionRectMode selectionRectMode() const { return mSelectionRectMode; }
3788 QCPSelectionRect *selectionRect() const { return mSelectionRect; }
3789 bool openGl() const { return mOpenGl; }
3790
3791 // setters:
3792 void setViewport(const QRect &rect);
3793 void setBufferDevicePixelRatio(double ratio);
3794 void setBackground(const QPixmap &pm);
3795 void setBackground(const QPixmap &pm, bool scaled, Qt::AspectRatioMode mode=Qt::KeepAspectRatioByExpanding);
3796 void setBackground(const QBrush &brush);
3797 void setBackgroundScaled(bool scaled);
3798 void setBackgroundScaledMode(Qt::AspectRatioMode mode);
3799 void setAntialiasedElements(const QCP::AntialiasedElements &antialiasedElements);
3800 void setAntialiasedElement(QCP::AntialiasedElement antialiasedElement, bool enabled=true);
3801 void setNotAntialiasedElements(const QCP::AntialiasedElements &notAntialiasedElements);
3802 void setNotAntialiasedElement(QCP::AntialiasedElement notAntialiasedElement, bool enabled=true);
3803 void setAutoAddPlottableToLegend(bool on);
3804 void setInteractions(const QCP::Interactions &interactions);
3805 void setInteraction(const QCP::Interaction &interaction, bool enabled=true);
3806 void setSelectionTolerance(int pixels);
3807 void setNoAntialiasingOnDrag(bool enabled);
3808 void setPlottingHints(const QCP::PlottingHints &hints);
3809 void setPlottingHint(QCP::PlottingHint hint, bool enabled=true);
3810 void setMultiSelectModifier(Qt::KeyboardModifier modifier);
3811 void setSelectionRectMode(QCP::SelectionRectMode mode);
3812 void setSelectionRect(QCPSelectionRect *selectionRect);
3813 void setOpenGl(bool enabled, int multisampling=16);
3814
3815 // non-property methods:
3816 // plottable interface:
3817 QCPAbstractPlottable *plottable(int index);
3818 QCPAbstractPlottable *plottable();
3819 bool removePlottable(QCPAbstractPlottable *plottable);
3820 bool removePlottable(int index);
3821 int clearPlottables();
3822 int plottableCount() const;
3823 QList<QCPAbstractPlottable*> selectedPlottables() const;
3824 template<class PlottableType>
3825 PlottableType *plottableAt(const QPointF &pos, bool onlySelectable=false, int *dataIndex=nullptr) const;
3826 QCPAbstractPlottable *plottableAt(const QPointF &pos, bool onlySelectable=false, int *dataIndex=nullptr) const;
3827 bool hasPlottable(QCPAbstractPlottable *plottable) const;
3828
3829 // specialized interface for QCPGraph:
3830 QCPGraph *graph(int index) const;
3831 QCPGraph *graph() const;
3832 QCPGraph *addGraph(QCPAxis *keyAxis=nullptr, QCPAxis *valueAxis=nullptr);
3833 bool removeGraph(QCPGraph *graph);
3834 bool removeGraph(int index);
3835 int clearGraphs();
3836 int graphCount() const;
3837 QList<QCPGraph*> selectedGraphs() const;
3838
3839 // item interface:
3840 QCPAbstractItem *item(int index) const;
3841 QCPAbstractItem *item() const;
3842 bool removeItem(QCPAbstractItem *item);
3843 bool removeItem(int index);
3844 int clearItems();
3845 int itemCount() const;
3846 QList<QCPAbstractItem*> selectedItems() const;
3847 template<class ItemType>
3848 ItemType *itemAt(const QPointF &pos, bool onlySelectable=false) const;
3849 QCPAbstractItem *itemAt(const QPointF &pos, bool onlySelectable=false) const;
3850 bool hasItem(QCPAbstractItem *item) const;
3851
3852 // layer interface:
3853 QCPLayer *layer(const QString &name) const;
3854 QCPLayer *layer(int index) const;
3855 QCPLayer *currentLayer() const;
3856 bool setCurrentLayer(const QString &name);
3857 bool setCurrentLayer(QCPLayer *layer);
3858 int layerCount() const;
3859 bool addLayer(const QString &name, QCPLayer *otherLayer=nullptr, LayerInsertMode insertMode=limAbove);
3860 bool removeLayer(QCPLayer *layer);
3861 bool moveLayer(QCPLayer *layer, QCPLayer *otherLayer, LayerInsertMode insertMode=limAbove);
3862
3863 // axis rect/layout interface:
3864 int axisRectCount() const;
3865 QCPAxisRect* axisRect(int index=0) const;
3866 QList<QCPAxisRect*> axisRects() const;
3867 QCPLayoutElement* layoutElementAt(const QPointF &pos) const;
3868 QCPAxisRect* axisRectAt(const QPointF &pos) const;
3869 Q_SLOT void rescaleAxes(bool onlyVisiblePlottables=false);
3870
3871 QList<QCPAxis*> selectedAxes() const;
3872 QList<QCPLegend*> selectedLegends() const;
3873 Q_SLOT void deselectAll();
3874
3875 bool savePdf(const QString &fileName, int width=0, int height=0, QCP::ExportPen exportPen=QCP::epAllowCosmetic, const QString &pdfCreator=QString(), const QString &pdfTitle=QString());
3876 bool savePng(const QString &fileName, int width=0, int height=0, double scale=1.0, int quality=-1, int resolution=96, QCP::ResolutionUnit resolutionUnit=QCP::ruDotsPerInch);
3877 bool saveJpg(const QString &fileName, int width=0, int height=0, double scale=1.0, int quality=-1, int resolution=96, QCP::ResolutionUnit resolutionUnit=QCP::ruDotsPerInch);
3878 bool saveBmp(const QString &fileName, int width=0, int height=0, double scale=1.0, int resolution=96, QCP::ResolutionUnit resolutionUnit=QCP::ruDotsPerInch);
3879 bool saveRastered(const QString &fileName, int width, int height, double scale, const char *format, int quality=-1, int resolution=96, QCP::ResolutionUnit resolutionUnit=QCP::ruDotsPerInch);
3880 QPixmap toPixmap(int width=0, int height=0, double scale=1.0);
3881 void toPainter(QCPPainter *painter, int width=0, int height=0);
3882 Q_SLOT void replot(QCustomPlot::RefreshPriority refreshPriority=QCustomPlot::rpRefreshHint);
3883 double replotTime(bool average=false) const;
3884
3885 QCPAxis *xAxis, *yAxis, *xAxis2, *yAxis2;
3887
3888signals:
3894
3895 void plottableClick(QCPAbstractPlottable *plottable, int dataIndex, QMouseEvent *event);
3896 void plottableDoubleClick(QCPAbstractPlottable *plottable, int dataIndex, QMouseEvent *event);
3903
3908
3909protected:
3910 // property members:
3911 QRect mViewport;
3912 double mBufferDevicePixelRatio;
3913 QCPLayoutGrid *mPlotLayout;
3914 bool mAutoAddPlottableToLegend;
3915 QList<QCPAbstractPlottable*> mPlottables;
3916 QList<QCPGraph*> mGraphs; // extra list of plottables also in mPlottables that are of type QCPGraph
3918 QList<QCPLayer*> mLayers;
3919 QCP::AntialiasedElements mAntialiasedElements, mNotAntialiasedElements;
3920 QCP::Interactions mInteractions;
3921 int mSelectionTolerance;
3922 bool mNoAntialiasingOnDrag;
3923 QBrush mBackgroundBrush;
3924 QPixmap mBackgroundPixmap;
3925 QPixmap mScaledBackgroundPixmap;
3926 bool mBackgroundScaled;
3927 Qt::AspectRatioMode mBackgroundScaledMode;
3928 QCPLayer *mCurrentLayer;
3929 QCP::PlottingHints mPlottingHints;
3930 Qt::KeyboardModifier mMultiSelectModifier;
3931 QCP::SelectionRectMode mSelectionRectMode;
3932 QCPSelectionRect *mSelectionRect;
3933 bool mOpenGl;
3934
3935 // non-property members:
3937 QPoint mMousePressPos;
3938 bool mMouseHasMoved;
3939 QPointer<QCPLayerable> mMouseEventLayerable;
3940 QPointer<QCPLayerable> mMouseSignalLayerable;
3941 QVariant mMouseEventLayerableDetails;
3942 QVariant mMouseSignalLayerableDetails;
3943 bool mReplotting;
3944 bool mReplotQueued;
3945 double mReplotTime, mReplotTimeAverage;
3946 int mOpenGlMultisamples;
3947 QCP::AntialiasedElements mOpenGlAntialiasedElementsBackup;
3948 bool mOpenGlCacheLabelsBackup;
3949#ifdef QCP_OPENGL_FBO
3951 QSharedPointer<QSurface> mGlSurface;
3953#endif
3954
3955 // reimplemented virtual methods:
3956 virtual QSize minimumSizeHint() const Q_DECL_OVERRIDE;
3957 virtual QSize sizeHint() const Q_DECL_OVERRIDE;
3958 virtual void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
3959 virtual void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE;
3960 virtual bool event( QEvent *event ) override;
3961 virtual void mouseDoubleClickEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
3962 virtual void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
3963 virtual void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
3964 virtual void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
3965 virtual void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE;
3966
3967 // introduced virtual methods:
3968 virtual void draw(QCPPainter *painter);
3969 virtual void updateLayout();
3970 virtual void axisRemoved(QCPAxis *axis);
3971 virtual void legendRemoved(QCPLegend *legend);
3972 Q_SLOT virtual void processRectSelection(QRect rect, QMouseEvent *event);
3973 Q_SLOT virtual void processRectZoom(QRect rect, QMouseEvent *event);
3974 Q_SLOT virtual void processPointSelection(QMouseEvent *event);
3975
3976 // non-virtual methods:
3977 bool registerPlottable(QCPAbstractPlottable *plottable);
3978 bool registerGraph(QCPGraph *graph);
3979 bool registerItem(QCPAbstractItem* item);
3980 void updateLayerIndices() const;
3981 QCPLayerable *layerableAt(const QPointF &pos, bool onlySelectable, QVariant *selectionDetails=nullptr) const;
3982 QList<QCPLayerable*> layerableListAt(const QPointF &pos, bool onlySelectable, QList<QVariant> *selectionDetails=nullptr) const;
3983 void drawBackground(QCPPainter *painter);
3984 void setupPaintBuffers();
3985 QCPAbstractPaintBuffer *createPaintBuffer();
3986 bool hasInvalidatedPaintBuffers();
3987 bool setupOpenGl();
3988 void freeOpenGl();
3989
3990 friend class QCPLegend;
3991 friend class QCPAxis;
3992 friend class QCPLayer;
3993 friend class QCPAxisRect;
3994 friend class QCPAbstractPlottable;
3995 friend class QCPGraph;
3996 friend class QCPAbstractItem;
3997};
3998Q_DECLARE_METATYPE(QCustomPlot::LayerInsertMode)
3999Q_DECLARE_METATYPE(QCustomPlot::RefreshPriority)
4000
4001
4002// implementation of template functions:
4003
4004/*!
4005 Returns the plottable at the pixel position \a pos. The plottable type (a QCPAbstractPlottable
4006 subclass) that shall be taken into consideration can be specified via the template parameter.
4007
4008 Plottables that only consist of single lines (like graphs) have a tolerance band around them, see
4009 \ref setSelectionTolerance. If multiple plottables come into consideration, the one closest to \a
4010 pos is returned.
4011
4012 If \a onlySelectable is true, only plottables that are selectable
4013 (QCPAbstractPlottable::setSelectable) are considered.
4014
4015 if \a dataIndex is non-null, it is set to the index of the plottable's data point that is closest
4016 to \a pos.
4017
4018 If there is no plottable of the specified type at \a pos, returns \c nullptr.
4019
4020 \see itemAt, layoutElementAt
4021*/
4022template<class PlottableType>
4023PlottableType *QCustomPlot::plottableAt(const QPointF &pos, bool onlySelectable, int *dataIndex) const
4024{
4025 PlottableType *resultPlottable = 0;
4026 QVariant resultDetails;
4027 double resultDistance = mSelectionTolerance; // only regard clicks with distances smaller than mSelectionTolerance as selections, so initialize with that value
4028
4029 foreach (QCPAbstractPlottable *plottable, mPlottables)
4030 {
4031 PlottableType *currentPlottable = qobject_cast<PlottableType*>(plottable);
4032 if (!currentPlottable || (onlySelectable && !currentPlottable->selectable())) // we could have also passed onlySelectable to the selectTest function, but checking here is faster, because we have access to QCPAbstractPlottable::selectable
4033 continue;
4034 if (currentPlottable->clipRect().contains(pos.toPoint())) // only consider clicks where the plottable is actually visible
4035 {
4036 QVariant details;
4037 double currentDistance = currentPlottable->selectTest(pos, false, dataIndex ? &details : nullptr);
4038 if (currentDistance >= 0 && currentDistance < resultDistance)
4039 {
4040 resultPlottable = currentPlottable;
4041 resultDetails = details;
4042 resultDistance = currentDistance;
4043 }
4044 }
4045 }
4046
4047 if (resultPlottable && dataIndex)
4048 {
4049 QCPDataSelection sel = resultDetails.value<QCPDataSelection>();
4050 if (!sel.isEmpty())
4051 *dataIndex = sel.dataRange(0).begin();
4052 }
4053 return resultPlottable;
4054}
4055
4056/*!
4057 Returns the item at the pixel position \a pos. The item type (a QCPAbstractItem subclass) that shall be
4058 taken into consideration can be specified via the template parameter. Items that only consist of single
4059 lines (e.g. \ref QCPItemLine or \ref QCPItemCurve) have a tolerance band around them, see \ref
4060 setSelectionTolerance. If multiple items come into consideration, the one closest to \a pos is returned.
4061
4062 If \a onlySelectable is true, only items that are selectable (QCPAbstractItem::setSelectable) are
4063 considered.
4064
4065 If there is no item at \a pos, returns \c nullptr.
4066
4067 \see plottableAt, layoutElementAt
4068*/
4069template<class ItemType>
4070ItemType *QCustomPlot::itemAt(const QPointF &pos, bool onlySelectable) const
4071{
4072 ItemType *resultItem = 0;
4073 double resultDistance = mSelectionTolerance; // only regard clicks with distances smaller than mSelectionTolerance as selections, so initialize with that value
4074
4075 foreach (QCPAbstractItem *item, mItems)
4076 {
4077 ItemType *currentItem = qobject_cast<ItemType*>(item);
4078 if (!currentItem || (onlySelectable && !currentItem->selectable())) // we could have also passed onlySelectable to the selectTest function, but checking here is faster, because we have access to QCPAbstractItem::selectable
4079 continue;
4080 if (!currentItem->clipToAxisRect() || currentItem->clipRect().contains(pos.toPoint())) // only consider clicks inside axis cliprect of the item if actually clipped to it
4081 {
4082 double currentDistance = currentItem->selectTest(pos, false);
4083 if (currentDistance >= 0 && currentDistance < resultDistance)
4084 {
4085 resultItem = currentItem;
4086 resultDistance = currentDistance;
4087 }
4088 }
4089 }
4090
4091 return resultItem;
4092}
4093
4094
4095
4096/* end of 'src/core.h' */
4097
4098
4099/* including file 'src/plottable1d.h' */
4100/* modified 2021-03-29T02:30:44, size 25638 */
4101
4103{
4104public:
4105 virtual ~QCPPlottableInterface1D() = default;
4106 // introduced pure virtual methods:
4107 virtual int dataCount() const = 0;
4108 virtual double dataMainKey(int index) const = 0;
4109 virtual double dataSortKey(int index) const = 0;
4110 virtual double dataMainValue(int index) const = 0;
4111 virtual QCPRange dataValueRange(int index) const = 0;
4112 virtual QPointF dataPixelPosition(int index) const = 0;
4113 virtual bool sortKeyIsMainKey() const = 0;
4114 virtual QCPDataSelection selectTestRect(const QRectF &rect, bool onlySelectable) const = 0;
4115 virtual int findBegin(double sortKey, bool expandedRange=true) const = 0;
4116 virtual int findEnd(double sortKey, bool expandedRange=true) const = 0;
4117};
4118
4119template <class DataType>
4120class QCPAbstractPlottable1D : public QCPAbstractPlottable, public QCPPlottableInterface1D // no QCP_LIB_DECL, template class ends up in header (cpp included below)
4121{
4122 // No Q_OBJECT macro due to template class
4123
4124public:
4126 virtual ~QCPAbstractPlottable1D() Q_DECL_OVERRIDE;
4127
4128 // virtual methods of 1d plottable interface:
4129 virtual int dataCount() const Q_DECL_OVERRIDE;
4130 virtual double dataMainKey(int index) const Q_DECL_OVERRIDE;
4131 virtual double dataSortKey(int index) const Q_DECL_OVERRIDE;
4132 virtual double dataMainValue(int index) const Q_DECL_OVERRIDE;
4133 virtual QCPRange dataValueRange(int index) const Q_DECL_OVERRIDE;
4134 virtual QPointF dataPixelPosition(int index) const Q_DECL_OVERRIDE;
4135 virtual bool sortKeyIsMainKey() const Q_DECL_OVERRIDE;
4136 virtual QCPDataSelection selectTestRect(const QRectF &rect, bool onlySelectable) const Q_DECL_OVERRIDE;
4137 virtual int findBegin(double sortKey, bool expandedRange=true) const Q_DECL_OVERRIDE;
4138 virtual int findEnd(double sortKey, bool expandedRange=true) const Q_DECL_OVERRIDE;
4139
4140 // reimplemented virtual methods:
4141 virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE;
4142 virtual QCPPlottableInterface1D *interface1D() Q_DECL_OVERRIDE { return this; }
4143
4144protected:
4145 // property members:
4147
4148 // helpers for subclasses:
4149 void getDataSegments(QList<QCPDataRange> &selectedSegments, QList<QCPDataRange> &unselectedSegments) const;
4150 void drawPolyline(QCPPainter *painter, const QVector<QPointF> &lineData) const;
4151
4152private:
4153 Q_DISABLE_COPY(QCPAbstractPlottable1D)
4154
4155};
4156
4157
4158
4159// include implementation in header since it is a class template:
4160////////////////////////////////////////////////////////////////////////////////////////////////////
4161//////////////////// QCPPlottableInterface1D
4162////////////////////////////////////////////////////////////////////////////////////////////////////
4163
4164/*! \class QCPPlottableInterface1D
4165 \brief Defines an abstract interface for one-dimensional plottables
4166
4167 This class contains only pure virtual methods which define a common interface to the data
4168 of one-dimensional plottables.
4169
4170 For example, it is implemented by the template class \ref QCPAbstractPlottable1D (the preferred
4171 base class for one-dimensional plottables). So if you use that template class as base class of
4172 your one-dimensional plottable, you won't have to care about implementing the 1d interface
4173 yourself.
4174
4175 If your plottable doesn't derive from \ref QCPAbstractPlottable1D but still wants to provide a 1d
4176 interface (e.g. like \ref QCPErrorBars does), you should inherit from both \ref
4177 QCPAbstractPlottable and \ref QCPPlottableInterface1D and accordingly reimplement the pure
4178 virtual methods of the 1d interface, matching your data container. Also, reimplement \ref
4179 QCPAbstractPlottable::interface1D to return the \c this pointer.
4180
4181 If you have a \ref QCPAbstractPlottable pointer, you can check whether it implements this
4182 interface by calling \ref QCPAbstractPlottable::interface1D and testing it for a non-zero return
4183 value. If it indeed implements this interface, you may use it to access the plottable's data
4184 without needing to know the exact type of the plottable or its data point type.
4185*/
4186
4187/* start documentation of pure virtual functions */
4188
4189/*! \fn virtual int QCPPlottableInterface1D::dataCount() const = 0;
4190
4191 Returns the number of data points of the plottable.
4192*/
4193
4194/*! \fn virtual QCPDataSelection QCPPlottableInterface1D::selectTestRect(const QRectF &rect, bool onlySelectable) const = 0;
4195
4196 Returns a data selection containing all the data points of this plottable which are contained (or
4197 hit by) \a rect. This is used mainly in the selection rect interaction for data selection (\ref
4198 dataselection "data selection mechanism").
4199
4200 If \a onlySelectable is true, an empty QCPDataSelection is returned if this plottable is not
4201 selectable (i.e. if \ref QCPAbstractPlottable::setSelectable is \ref QCP::stNone).
4202
4203 \note \a rect must be a normalized rect (positive or zero width and height). This is especially
4204 important when using the rect of \ref QCPSelectionRect::accepted, which is not necessarily
4205 normalized. Use <tt>QRect::normalized()</tt> when passing a rect which might not be normalized.
4206*/
4207
4208/*! \fn virtual double QCPPlottableInterface1D::dataMainKey(int index) const = 0
4209
4210 Returns the main key of the data point at the given \a index.
4211
4212 What the main key is, is defined by the plottable's data type. See the \ref
4213 qcpdatacontainer-datatype "QCPDataContainer DataType" documentation for details about this naming
4214 convention.
4215*/
4216
4217/*! \fn virtual double QCPPlottableInterface1D::dataSortKey(int index) const = 0
4218
4219 Returns the sort key of the data point at the given \a index.
4220
4221 What the sort key is, is defined by the plottable's data type. See the \ref
4222 qcpdatacontainer-datatype "QCPDataContainer DataType" documentation for details about this naming
4223 convention.
4224*/
4225
4226/*! \fn virtual double QCPPlottableInterface1D::dataMainValue(int index) const = 0
4227
4228 Returns the main value of the data point at the given \a index.
4229
4230 What the main value is, is defined by the plottable's data type. See the \ref
4231 qcpdatacontainer-datatype "QCPDataContainer DataType" documentation for details about this naming
4232 convention.
4233*/
4234
4235/*! \fn virtual QCPRange QCPPlottableInterface1D::dataValueRange(int index) const = 0
4236
4237 Returns the value range of the data point at the given \a index.
4238
4239 What the value range is, is defined by the plottable's data type. See the \ref
4240 qcpdatacontainer-datatype "QCPDataContainer DataType" documentation for details about this naming
4241 convention.
4242*/
4243
4244/*! \fn virtual QPointF QCPPlottableInterface1D::dataPixelPosition(int index) const = 0
4245
4246 Returns the pixel position on the widget surface at which the data point at the given \a index
4247 appears.
4248
4249 Usually this corresponds to the point of \ref dataMainKey/\ref dataMainValue, in pixel
4250 coordinates. However, depending on the plottable, this might be a different apparent position
4251 than just a coord-to-pixel transform of those values. For example, \ref QCPBars apparent data
4252 values can be shifted depending on their stacking, bar grouping or configured base value.
4253*/
4254
4255/*! \fn virtual bool QCPPlottableInterface1D::sortKeyIsMainKey() const = 0
4256
4257 Returns whether the sort key (\ref dataSortKey) is identical to the main key (\ref dataMainKey).
4258
4259 What the sort and main keys are, is defined by the plottable's data type. See the \ref
4260 qcpdatacontainer-datatype "QCPDataContainer DataType" documentation for details about this naming
4261 convention.
4262*/
4263
4264/*! \fn virtual int QCPPlottableInterface1D::findBegin(double sortKey, bool expandedRange) const = 0
4265
4266 Returns the index of the data point with a (sort-)key that is equal to, just below, or just above
4267 \a sortKey. If \a expandedRange is true, the data point just below \a sortKey will be considered,
4268 otherwise the one just above.
4269
4270 This can be used in conjunction with \ref findEnd to iterate over data points within a given key
4271 range, including or excluding the bounding data points that are just beyond the specified range.
4272
4273 If \a expandedRange is true but there are no data points below \a sortKey, 0 is returned.
4274
4275 If the container is empty, returns 0 (in that case, \ref findEnd will also return 0, so a loop
4276 using these methods will not iterate over the index 0).
4277
4278 \see findEnd, QCPDataContainer::findBegin
4279*/
4280
4281/*! \fn virtual int QCPPlottableInterface1D::findEnd(double sortKey, bool expandedRange) const = 0
4282
4283 Returns the index one after the data point with a (sort-)key that is equal to, just above, or
4284 just below \a sortKey. If \a expandedRange is true, the data point just above \a sortKey will be
4285 considered, otherwise the one just below.
4286
4287 This can be used in conjunction with \ref findBegin to iterate over data points within a given
4288 key range, including the bounding data points that are just below and above the specified range.
4289
4290 If \a expandedRange is true but there are no data points above \a sortKey, the index just above the
4291 highest data point is returned.
4292
4293 If the container is empty, returns 0.
4294
4295 \see findBegin, QCPDataContainer::findEnd
4296*/
4297
4298/* end documentation of pure virtual functions */
4299
4300
4301////////////////////////////////////////////////////////////////////////////////////////////////////
4302//////////////////// QCPAbstractPlottable1D
4303////////////////////////////////////////////////////////////////////////////////////////////////////
4304
4305/*! \class QCPAbstractPlottable1D
4306 \brief A template base class for plottables with one-dimensional data
4307
4308 This template class derives from \ref QCPAbstractPlottable and from the abstract interface \ref
4309 QCPPlottableInterface1D. It serves as a base class for all one-dimensional data (i.e. data with
4310 one key dimension), such as \ref QCPGraph and QCPCurve.
4311
4312 The template parameter \a DataType is the type of the data points of this plottable (e.g. \ref
4313 QCPGraphData or \ref QCPCurveData). The main purpose of this base class is to provide the member
4314 \a mDataContainer (a shared pointer to a \ref QCPDataContainer "QCPDataContainer<DataType>") and
4315 implement the according virtual methods of the \ref QCPPlottableInterface1D, such that most
4316 subclassed plottables don't need to worry about this anymore.
4317
4318 Further, it provides a convenience method for retrieving selected/unselected data segments via
4319 \ref getDataSegments. This is useful when subclasses implement their \ref draw method and need to
4320 draw selected segments with a different pen/brush than unselected segments (also see \ref
4321 QCPSelectionDecorator).
4322
4323 This class implements basic functionality of \ref QCPAbstractPlottable::selectTest and \ref
4324 QCPPlottableInterface1D::selectTestRect, assuming point-like data points, based on the 1D data
4325 interface. In spite of that, most plottable subclasses will want to reimplement those methods
4326 again, to provide a more accurate hit test based on their specific data visualization geometry.
4327*/
4328
4329/* start documentation of inline functions */
4330
4331/*! \fn QCPPlottableInterface1D *QCPAbstractPlottable1D::interface1D()
4332
4333 Returns a \ref QCPPlottableInterface1D pointer to this plottable, providing access to its 1D
4334 interface.
4335
4336 \seebaseclassmethod
4337*/
4338
4339/* end documentation of inline functions */
4340
4341/*!
4342 Forwards \a keyAxis and \a valueAxis to the \ref QCPAbstractPlottable::QCPAbstractPlottable
4343 "QCPAbstractPlottable" constructor and allocates the \a mDataContainer.
4344*/
4345template <class DataType>
4347 QCPAbstractPlottable(keyAxis, valueAxis),
4348 mDataContainer(new QCPDataContainer<DataType>)
4349{
4350}
4351
4352template <class DataType>
4354{
4355}
4356
4357/*!
4358 \copydoc QCPPlottableInterface1D::dataCount
4359*/
4360template <class DataType>
4362{
4363 return mDataContainer->size();
4364}
4365
4366/*!
4367 \copydoc QCPPlottableInterface1D::dataMainKey
4368*/
4369template <class DataType>
4371{
4372 if (index >= 0 && index < mDataContainer->size())
4373 {
4374 return (mDataContainer->constBegin()+index)->mainKey();
4375 } else
4376 {
4377 qDebug() << Q_FUNC_INFO << "Index out of bounds" << index;
4378 return 0;
4379 }
4380}
4381
4382/*!
4383 \copydoc QCPPlottableInterface1D::dataSortKey
4384*/
4385template <class DataType>
4387{
4388 if (index >= 0 && index < mDataContainer->size())
4389 {
4390 return (mDataContainer->constBegin()+index)->sortKey();
4391 } else
4392 {
4393 qDebug() << Q_FUNC_INFO << "Index out of bounds" << index;
4394 return 0;
4395 }
4396}
4397
4398/*!
4399 \copydoc QCPPlottableInterface1D::dataMainValue
4400*/
4401template <class DataType>
4403{
4404 if (index >= 0 && index < mDataContainer->size())
4405 {
4406 return (mDataContainer->constBegin()+index)->mainValue();
4407 } else
4408 {
4409 qDebug() << Q_FUNC_INFO << "Index out of bounds" << index;
4410 return 0;
4411 }
4412}
4413
4414/*!
4415 \copydoc QCPPlottableInterface1D::dataValueRange
4416*/
4417template <class DataType>
4419{
4420 if (index >= 0 && index < mDataContainer->size())
4421 {
4422 return (mDataContainer->constBegin()+index)->valueRange();
4423 } else
4424 {
4425 qDebug() << Q_FUNC_INFO << "Index out of bounds" << index;
4426 return QCPRange(0, 0);
4427 }
4428}
4429
4430/*!
4431 \copydoc QCPPlottableInterface1D::dataPixelPosition
4432*/
4433template <class DataType>
4435{
4436 if (index >= 0 && index < mDataContainer->size())
4437 {
4438 const typename QCPDataContainer<DataType>::const_iterator it = mDataContainer->constBegin()+index;
4439 return coordsToPixels(it->mainKey(), it->mainValue());
4440 } else
4441 {
4442 qDebug() << Q_FUNC_INFO << "Index out of bounds" << index;
4443 return QPointF();
4444 }
4445}
4446
4447/*!
4448 \copydoc QCPPlottableInterface1D::sortKeyIsMainKey
4449*/
4450template <class DataType>
4452{
4453 return DataType::sortKeyIsMainKey();
4454}
4455
4456/*!
4457 Implements a rect-selection algorithm assuming the data (accessed via the 1D data interface) is
4458 point-like. Most subclasses will want to reimplement this method again, to provide a more
4459 accurate hit test based on the true data visualization geometry.
4460
4461 \seebaseclassmethod
4462*/
4463template <class DataType>
4465{
4466 QCPDataSelection result;
4467 if ((onlySelectable && mSelectable == QCP::stNone) || mDataContainer->isEmpty())
4468 return result;
4469 if (!mKeyAxis || !mValueAxis)
4470 return result;
4471
4472 // convert rect given in pixels to ranges given in plot coordinates:
4473 double key1, value1, key2, value2;
4474 pixelsToCoords(rect.topLeft(), key1, value1);
4475 pixelsToCoords(rect.bottomRight(), key2, value2);
4476 QCPRange keyRange(key1, key2); // QCPRange normalizes internally so we don't have to care about whether key1 < key2
4477 QCPRange valueRange(value1, value2);
4478 typename QCPDataContainer<DataType>::const_iterator begin = mDataContainer->constBegin();
4479 typename QCPDataContainer<DataType>::const_iterator end = mDataContainer->constEnd();
4480 if (DataType::sortKeyIsMainKey()) // we can assume that data is sorted by main key, so can reduce the searched key interval:
4481 {
4482 begin = mDataContainer->findBegin(keyRange.lower, false);
4483 end = mDataContainer->findEnd(keyRange.upper, false);
4484 }
4485 if (begin == end)
4486 return result;
4487
4488 int currentSegmentBegin = -1; // -1 means we're currently not in a segment that's contained in rect
4489 for (typename QCPDataContainer<DataType>::const_iterator it=begin; it!=end; ++it)
4490 {
4491 if (currentSegmentBegin == -1)
4492 {
4493 if (valueRange.contains(it->mainValue()) && keyRange.contains(it->mainKey())) // start segment
4494 currentSegmentBegin = int(it-mDataContainer->constBegin());
4495 } else if (!valueRange.contains(it->mainValue()) || !keyRange.contains(it->mainKey())) // segment just ended
4496 {
4497 result.addDataRange(QCPDataRange(currentSegmentBegin, int(it-mDataContainer->constBegin())), false);
4498 currentSegmentBegin = -1;
4499 }
4500 }
4501 // process potential last segment:
4502 if (currentSegmentBegin != -1)
4503 result.addDataRange(QCPDataRange(currentSegmentBegin, int(end-mDataContainer->constBegin())), false);
4504
4505 result.simplify();
4506 return result;
4507}
4508
4509/*!
4510 \copydoc QCPPlottableInterface1D::findBegin
4511*/
4512template <class DataType>
4513int QCPAbstractPlottable1D<DataType>::findBegin(double sortKey, bool expandedRange) const
4514{
4515 return int(mDataContainer->findBegin(sortKey, expandedRange)-mDataContainer->constBegin());
4516}
4517
4518/*!
4519 \copydoc QCPPlottableInterface1D::findEnd
4520*/
4521template <class DataType>
4522int QCPAbstractPlottable1D<DataType>::findEnd(double sortKey, bool expandedRange) const
4523{
4524 return int(mDataContainer->findEnd(sortKey, expandedRange)-mDataContainer->constBegin());
4525}
4526
4527/*!
4528 Implements a point-selection algorithm assuming the data (accessed via the 1D data interface) is
4529 point-like. Most subclasses will want to reimplement this method again, to provide a more
4530 accurate hit test based on the true data visualization geometry.
4531
4532 If \a details is not 0, it will be set to a \ref QCPDataSelection, describing the closest data point
4533 to \a pos.
4534
4535 \seebaseclassmethod
4536*/
4537template <class DataType>
4538double QCPAbstractPlottable1D<DataType>::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
4539{
4540 if ((onlySelectable && mSelectable == QCP::stNone) || mDataContainer->isEmpty())
4541 return -1;
4542 if (!mKeyAxis || !mValueAxis)
4543 return -1;
4544
4545 QCPDataSelection selectionResult;
4546 double minDistSqr = (std::numeric_limits<double>::max)();
4547 int minDistIndex = mDataContainer->size();
4548
4549 typename QCPDataContainer<DataType>::const_iterator begin = mDataContainer->constBegin();
4550 typename QCPDataContainer<DataType>::const_iterator end = mDataContainer->constEnd();
4551 if (DataType::sortKeyIsMainKey()) // we can assume that data is sorted by main key, so can reduce the searched key interval:
4552 {
4553 // determine which key range comes into question, taking selection tolerance around pos into account:
4554 double posKeyMin, posKeyMax, dummy;
4555 pixelsToCoords(pos-QPointF(mParentPlot->selectionTolerance(), mParentPlot->selectionTolerance()), posKeyMin, dummy);
4556 pixelsToCoords(pos+QPointF(mParentPlot->selectionTolerance(), mParentPlot->selectionTolerance()), posKeyMax, dummy);
4557 if (posKeyMin > posKeyMax)
4558 qSwap(posKeyMin, posKeyMax);
4559 begin = mDataContainer->findBegin(posKeyMin, true);
4560 end = mDataContainer->findEnd(posKeyMax, true);
4561 }
4562 if (begin == end)
4563 return -1;
4564 QCPRange keyRange(mKeyAxis->range());
4565 QCPRange valueRange(mValueAxis->range());
4566 for (typename QCPDataContainer<DataType>::const_iterator it=begin; it!=end; ++it)
4567 {
4568 const double mainKey = it->mainKey();
4569 const double mainValue = it->mainValue();
4570 if (keyRange.contains(mainKey) && valueRange.contains(mainValue)) // make sure data point is inside visible range, for speedup in cases where sort key isn't main key and we iterate over all points
4571 {
4572 const double currentDistSqr = QCPVector2D(coordsToPixels(mainKey, mainValue)-pos).lengthSquared();
4573 if (currentDistSqr < minDistSqr)
4574 {
4575 minDistSqr = currentDistSqr;
4576 minDistIndex = int(it-mDataContainer->constBegin());
4577 }
4578 }
4579 }
4580 if (minDistIndex != mDataContainer->size())
4581 selectionResult.addDataRange(QCPDataRange(minDistIndex, minDistIndex+1), false);
4582
4583 selectionResult.simplify();
4584 if (details)
4585 details->setValue(selectionResult);
4586 return qSqrt(minDistSqr);
4587}
4588
4589/*!
4590 Splits all data into selected and unselected segments and outputs them via \a selectedSegments
4591 and \a unselectedSegments, respectively.
4592
4593 This is useful when subclasses implement their \ref draw method and need to draw selected
4594 segments with a different pen/brush than unselected segments (also see \ref
4595 QCPSelectionDecorator).
4596
4597 \see setSelection
4598*/
4599template <class DataType>
4601{
4602 selectedSegments.clear();
4603 unselectedSegments.clear();
4604 if (mSelectable == QCP::stWhole) // stWhole selection type draws the entire plottable with selected style if mSelection isn't empty
4605 {
4606 if (selected())
4607 selectedSegments << QCPDataRange(0, dataCount());
4608 else
4609 unselectedSegments << QCPDataRange(0, dataCount());
4610 } else
4611 {
4612 QCPDataSelection sel(selection());
4613 sel.simplify();
4614 selectedSegments = sel.dataRanges();
4615 unselectedSegments = sel.inverse(QCPDataRange(0, dataCount())).dataRanges();
4616 }
4617}
4618
4619/*!
4620 A helper method which draws a line with the passed \a painter, according to the pixel data in \a
4621 lineData. NaN points create gaps in the line, as expected from QCustomPlot's plottables (this is
4622 the main difference to QPainter's regular drawPolyline, which handles NaNs by lagging or
4623 crashing).
4624
4625 Further it uses a faster line drawing technique based on \ref QCPPainter::drawLine rather than \c
4626 QPainter::drawPolyline if the configured \ref QCustomPlot::setPlottingHints() and \a painter
4627 style allows.
4628*/
4629template <class DataType>
4631{
4632 // if drawing lines in plot (instead of PDF), reduce 1px lines to cosmetic, because at least in
4633 // Qt6 drawing of "1px" width lines is much slower even though it has same appearance apart from
4634 // High-DPI. In High-DPI cases people must set a pen width slightly larger than 1.0 to get
4635 // correct DPI scaling of width, but of course with performance penalty.
4636 if (!painter->modes().testFlag(QCPPainter::pmVectorized) &&
4637 qFuzzyCompare(painter->pen().widthF(), 1.0))
4638 {
4639 QPen newPen = painter->pen();
4640 newPen.setWidth(0);
4641 painter->setPen(newPen);
4642 }
4643
4644 // if drawing solid line and not in PDF, use much faster line drawing instead of polyline:
4645 if (mParentPlot->plottingHints().testFlag(QCP::phFastPolylines) &&
4646 painter->pen().style() == Qt::SolidLine &&
4647 !painter->modes().testFlag(QCPPainter::pmVectorized) &&
4648 !painter->modes().testFlag(QCPPainter::pmNoCaching))
4649 {
4650 int i = 0;
4651 bool lastIsNan = false;
4652 const int lineDataSize = lineData.size();
4653 while (i < lineDataSize && (qIsNaN(lineData.at(i).y()) || qIsNaN(lineData.at(i).x()))) // make sure first point is not NaN
4654 ++i;
4655 ++i; // because drawing works in 1 point retrospect
4656 while (i < lineDataSize)
4657 {
4658 if (!qIsNaN(lineData.at(i).y()) && !qIsNaN(lineData.at(i).x())) // NaNs create a gap in the line
4659 {
4660 if (!lastIsNan)
4661 painter->drawLine(lineData.at(i-1), lineData.at(i));
4662 else
4663 lastIsNan = false;
4664 } else
4665 lastIsNan = true;
4666 ++i;
4667 }
4668 } else
4669 {
4670 int segmentStart = 0;
4671 int i = 0;
4672 const int lineDataSize = lineData.size();
4673 while (i < lineDataSize)
4674 {
4675 if (qIsNaN(lineData.at(i).y()) || qIsNaN(lineData.at(i).x()) || qIsInf(lineData.at(i).y())) // NaNs create a gap in the line. Also filter Infs which make drawPolyline block
4676 {
4677 painter->drawPolyline(lineData.constData()+segmentStart, i-segmentStart); // i, because we don't want to include the current NaN point
4678 segmentStart = i+1;
4679 }
4680 ++i;
4681 }
4682 // draw last segment:
4683 painter->drawPolyline(lineData.constData()+segmentStart, lineDataSize-segmentStart);
4684 }
4685}
4686
4687
4688/* end of 'src/plottable1d.h' */
4689
4690
4691/* including file 'src/colorgradient.h' */
4692/* modified 2021-03-29T02:30:44, size 7262 */
4693
4694class QCP_LIB_DECL QCPColorGradient
4695{
4696 Q_GADGET
4697public:
4698 /*!
4699 Defines the color spaces in which color interpolation between gradient stops can be performed.
4700
4701 \see setColorInterpolation
4702 */
4703 enum ColorInterpolation { ciRGB ///< Color channels red, green and blue are linearly interpolated
4704 ,ciHSV ///< Color channels hue, saturation and value are linearly interpolated (The hue is interpolated over the shortest angle distance)
4706 Q_ENUMS(ColorInterpolation)
4707
4708 /*!
4709 Defines how NaN data points shall appear in the plot.
4710
4711 \see setNanHandling, setNanColor
4712 */
4713 enum NanHandling { nhNone ///< NaN data points are not explicitly handled and shouldn't occur in the data (this gives slight performance improvement)
4714 ,nhLowestColor ///< NaN data points appear as the lowest color defined in this QCPColorGradient
4715 ,nhHighestColor ///< NaN data points appear as the highest color defined in this QCPColorGradient
4716 ,nhTransparent ///< NaN data points appear transparent
4717 ,nhNanColor ///< NaN data points appear as the color defined with \ref setNanColor
4719 Q_ENUMS(NanHandling)
4720
4721 /*!
4722 Defines the available presets that can be loaded with \ref loadPreset. See the documentation
4723 there for an image of the presets.
4724 */
4725 enum GradientPreset { gpGrayscale ///< Continuous lightness from black to white (suited for non-biased data representation)
4726 ,gpHot ///< Continuous lightness from black over firey colors to white (suited for non-biased data representation)
4727 ,gpCold ///< Continuous lightness from black over icey colors to white (suited for non-biased data representation)
4728 ,gpNight ///< Continuous lightness from black over weak blueish colors to white (suited for non-biased data representation)
4729 ,gpCandy ///< Blue over pink to white
4730 ,gpGeography ///< Colors suitable to represent different elevations on geographical maps
4731 ,gpIon ///< Half hue spectrum from black over purple to blue and finally green (creates banding illusion but allows more precise magnitude estimates)
4732 ,gpThermal ///< Colors suitable for thermal imaging, ranging from dark blue over purple to orange, yellow and white
4733 ,gpPolar ///< Colors suitable to emphasize polarity around the center, with blue for negative, black in the middle and red for positive values
4734 ,gpSpectrum ///< An approximation of the visible light spectrum (creates banding illusion but allows more precise magnitude estimates)
4735 ,gpJet ///< Hue variation similar to a spectrum, often used in numerical visualization (creates banding illusion but allows more precise magnitude estimates)
4736 ,gpHues ///< Full hue cycle, with highest and lowest color red (suitable for periodic data, such as angles and phases, see \ref setPeriodic)
4738 Q_ENUMS(GradientPreset)
4739
4741 QCPColorGradient(GradientPreset preset);
4742 bool operator==(const QCPColorGradient &other) const;
4743 bool operator!=(const QCPColorGradient &other) const { return !(*this == other); }
4744
4745 // getters:
4746 int levelCount() const { return mLevelCount; }
4747 QMap<double, QColor> colorStops() const { return mColorStops; }
4748 ColorInterpolation colorInterpolation() const { return mColorInterpolation; }
4749 NanHandling nanHandling() const { return mNanHandling; }
4750 QColor nanColor() const { return mNanColor; }
4751 bool periodic() const { return mPeriodic; }
4752
4753 // setters:
4754 void setLevelCount(int n);
4755 void setColorStops(const QMap<double, QColor> &colorStops);
4756 void setColorStopAt(double position, const QColor &color);
4757 void setColorInterpolation(ColorInterpolation interpolation);
4758 void setNanHandling(NanHandling handling);
4759 void setNanColor(const QColor &color);
4760 void setPeriodic(bool enabled);
4761
4762 // non-property methods:
4763 void colorize(const double *data, const QCPRange &range, QRgb *scanLine, int n, int dataIndexFactor=1, bool logarithmic=false);
4764 void colorize(const double *data, const unsigned char *alpha, const QCPRange &range, QRgb *scanLine, int n, int dataIndexFactor=1, bool logarithmic=false);
4765 QRgb color(double position, const QCPRange &range, bool logarithmic=false);
4766 void loadPreset(GradientPreset preset);
4767 void clearColorStops();
4768 QCPColorGradient inverted() const;
4769
4770protected:
4771 // property members:
4772 int mLevelCount;
4773 QMap<double, QColor> mColorStops;
4774 ColorInterpolation mColorInterpolation;
4775 NanHandling mNanHandling;
4776 QColor mNanColor;
4777 bool mPeriodic;
4778
4779 // non-property members:
4780 QVector<QRgb> mColorBuffer; // have colors premultiplied with alpha (for usage with QImage::Format_ARGB32_Premultiplied)
4781 bool mColorBufferInvalidated;
4782
4783 // non-virtual methods:
4784 bool stopsUseAlpha() const;
4785 void updateColorBuffer();
4786};
4787Q_DECLARE_METATYPE(QCPColorGradient::ColorInterpolation)
4788Q_DECLARE_METATYPE(QCPColorGradient::NanHandling)
4789Q_DECLARE_METATYPE(QCPColorGradient::GradientPreset)
4790
4791/* end of 'src/colorgradient.h' */
4792
4793
4794/* including file 'src/selectiondecorator-bracket.h' */
4795/* modified 2021-03-29T02:30:44, size 4458 */
4796
4798{
4799 Q_GADGET
4800public:
4801
4802 /*!
4803 Defines which shape is drawn at the boundaries of selected data ranges.
4804
4805 Some of the bracket styles further allow specifying a height and/or width, see \ref
4806 setBracketHeight and \ref setBracketWidth.
4807 */
4808 enum BracketStyle { bsSquareBracket ///< A square bracket is drawn.
4809 ,bsHalfEllipse ///< A half ellipse is drawn. The size of the ellipse is given by the bracket width/height properties.
4810 ,bsEllipse ///< An ellipse is drawn. The size of the ellipse is given by the bracket width/height properties.
4811 ,bsPlus ///< A plus is drawn.
4812 ,bsUserStyle ///< Start custom bracket styles at this index when subclassing and reimplementing \ref drawBracket.
4814 Q_ENUMS(BracketStyle)
4815
4817 virtual ~QCPSelectionDecoratorBracket() Q_DECL_OVERRIDE;
4818
4819 // getters:
4820 QPen bracketPen() const { return mBracketPen; }
4821 QBrush bracketBrush() const { return mBracketBrush; }
4822 int bracketWidth() const { return mBracketWidth; }
4823 int bracketHeight() const { return mBracketHeight; }
4824 BracketStyle bracketStyle() const { return mBracketStyle; }
4825 bool tangentToData() const { return mTangentToData; }
4826 int tangentAverage() const { return mTangentAverage; }
4827
4828 // setters:
4829 void setBracketPen(const QPen &pen);
4830 void setBracketBrush(const QBrush &brush);
4831 void setBracketWidth(int width);
4832 void setBracketHeight(int height);
4833 void setBracketStyle(BracketStyle style);
4834 void setTangentToData(bool enabled);
4835 void setTangentAverage(int pointCount);
4836
4837 // introduced virtual methods:
4838 virtual void drawBracket(QCPPainter *painter, int direction) const;
4839
4840 // virtual methods:
4841 virtual void drawDecoration(QCPPainter *painter, QCPDataSelection selection) Q_DECL_OVERRIDE;
4842
4843protected:
4844 // property members:
4845 QPen mBracketPen;
4846 QBrush mBracketBrush;
4847 int mBracketWidth;
4848 int mBracketHeight;
4849 BracketStyle mBracketStyle;
4850 bool mTangentToData;
4851 int mTangentAverage;
4852
4853 // non-virtual methods:
4854 double getTangentAngle(const QCPPlottableInterface1D *interface1d, int dataIndex, int direction) const;
4855 QPointF getPixelCoordinates(const QCPPlottableInterface1D *interface1d, int dataIndex) const;
4856
4857};
4859
4860/* end of 'src/selectiondecorator-bracket.h' */
4861
4862
4863/* including file 'src/layoutelements/layoutelement-axisrect.h' */
4864/* modified 2021-03-29T02:30:44, size 7529 */
4865
4866class QCP_LIB_DECL QCPAxisRect : public QCPLayoutElement
4867{
4868 Q_OBJECT
4869