Kstars

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