Kstars

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