Updated QCustomPlot to 1.2
jeandet -
r18:a9eb4604e26a default
Not Reviewed
Show More
Add another comment
TODOs: 0 unresolved 0 Resolved
COMMENTS: 0 General 0 Inline
@@ -0,0 +1,62
1 #!/usr/bin/socexplorer -e
2 import numpy as np
3 freq1 = 30
4 freq2 = 300
5 time_step = 0.001
6
7 t_ini = -50 * 1.0/(max(freq1,freq2))
8 t_fin = -1 * t_ini
9
10 time_vec = np.arange(t_ini, t_fin, time_step)
11
12 #input signal
13 input_sig1 = np.sin(2 * np.pi * freq1 * time_vec)
14 input_sig2 = np.sin(2 * np.pi * freq2 * time_vec)
15 input_sig = input_sig1 + input_sig2
16
17
18 plot=PySocExplorer.SocExplorerPlot()
19 plot.setTitle("demo")
20 plot.setXaxisLabel("Time(s)")
21 plot.setYaxisLabel("Values")
22
23 Courbe1=plot.addGraph()
24 Courbe2=plot.addGraph()
25 Courbe3=plot.addGraph()
26
27 plot.setGraphData(Courbe1,time_vec.tolist(),input_sig1.tolist())
28 plot.setGraphData(Courbe2,time_vec.tolist(),input_sig2.tolist())
29 plot.setGraphData(Courbe3,time_vec.tolist(),input_sig.tolist())
30 # none line stepleft stepright stepcenter impulse
31 plot.setGraphLineStyle(0,"stepleft")
32 plot.setGraphLineStyle(Courbe2,"impulse")
33 # none dot cross plus circle disc square diamond star triangle invertedtriangle crosssquare plussquare crosscircle pluscircle peace
34 plot.setGraphScatterStyle(Courbe3,"square")
35
36 pen=plot.getGraphPen(1)
37 pen.setWidth(4)
38 color=pen.color()
39 color.setRgb(0x00FF00)
40 pen.setColor(color)
41 plot.setGraphPen(1,pen)
42
43 pen=plot.getGraphPen(0)
44 pen.setWidth(2)
45 color=pen.color()
46 color.setRgb(0xFF0000)
47 pen.setColor(color)
48 plot.setGraphPen(2,pen)
49
50 plot.rescaleAxis()
51
52
53
54
55
56
57
58
59
60
61
62
@@ -0,0 +1,62
1 #!/usr/bin/socexplorer -e
2 import numpy as np
3 freq1 = 30
4 freq2 = 300
5 time_step = 0.001
6
7 t_ini = -10 * 1.0/(max(freq1,freq2))
8 t_fin = -1 * t_ini
9
10 time_vec = np.arange(t_ini, t_fin, time_step)
11
12 #input signal
13 input_sig1 = np.sin(2 * np.pi * freq1 * time_vec)
14 input_sig2 = np.sin(2 * np.pi * freq2 * time_vec)
15 input_sig = input_sig1 + input_sig2
16
17
18 plot=PySocExplorer.SocExplorerPlot()
19 plot.setTitle("demo")
20 plot.setXaxisLabel("Time(s)")
21 plot.setYaxisLabel("Values")
22
23 Courbe1=plot.addGraph()
24 Courbe2=plot.addGraph()
25 Courbe3=plot.addGraph()
26
27 plot.setGraphData(Courbe1,time_vec.tolist(),input_sig1.tolist())
28 plot.setGraphData(Courbe2,time_vec.tolist(),input_sig2.tolist())
29 plot.setGraphData(Courbe3,time_vec.tolist(),input_sig.tolist())
30 # none line stepleft stepright stepcenter impulse
31 #plot.setGraphLineStyle(0,"stepleft")
32 #plot.setGraphLineStyle(Courbe2,"impulse")
33 # none dot cross plus circle disc square diamond star triangle invertedtriangle crosssquare plussquare crosscircle pluscircle peace
34 #plot.setGraphScatterStyle(Courbe3,"square")
35
36 pen=plot.getGraphPen(1)
37 pen.setWidth(1)
38 color=pen.color()
39 color.setRgb(0x00FF00)
40 pen.setColor(color)
41 plot.setGraphPen(1,pen)
42
43 pen=plot.getGraphPen(0)
44 pen.setWidth(1)
45 color=pen.color()
46 color.setRgb(0xFF0000)
47 pen.setColor(color)
48 plot.setGraphPen(2,pen)
49
50 plot.rescaleAxis()
51
52
53
54
55
56
57
58
59
60
61
62
@@ -0,0 +1,37
1 #!/usr/bin/socexplorer -e
2 import numpy as np
3 freq1 = 30
4 freq2 = 300
5 time_step = 0.000001
6
7 t_ini = -500 * 1.0/(max(freq1,freq2))
8 t_fin = -1 * t_ini
9
10 time_vec = np.arange(t_ini, t_fin, time_step)
11
12 #input signal
13 input_sig1 = np.sin(2 * np.pi * freq1 * time_vec)
14
15
16 plot=PySocExplorer.SocExplorerPlot()
17 plot.setTitle("demo")
18 plot.setXaxisLabel("Time(s)")
19 plot.setYaxisLabel("Values")
20
21 Courbe1=plot.addGraph()
22
23 plot.setGraphData(Courbe1,time_vec.tolist(),input_sig1.tolist())
24
25 plot.rescaleAxis()
26
27
28
29
30
31
32
33
34
35
36
37
This diff has been collapsed as it changes many lines, (9445 lines changed) Show them Hide them
@@ -1,7 +1,7
1 /***************************************************************************
1 /***************************************************************************
2 ** **
2 ** **
3 ** QCustomPlot, an easy to use, modern plotting widget for Qt **
3 ** QCustomPlot, an easy to use, modern plotting widget for Qt **
4 ** Copyright (C) 2011, 2012, 2013 Emanuel Eichhammer **
4 ** Copyright (C) 2011, 2012, 2013, 2014 Emanuel Eichhammer **
5 ** **
5 ** **
6 ** This program is free software: you can redistribute it and/or modify **
6 ** This program is free software: you can redistribute it and/or modify **
7 ** it under the terms of the GNU General Public License as published by **
7 ** it under the terms of the GNU General Public License as published by **
@@ -19,8 +19,8
19 ****************************************************************************
19 ****************************************************************************
20 ** Author: Emanuel Eichhammer **
20 ** Author: Emanuel Eichhammer **
21 ** Website/Contact: http://www.qcustomplot.com/ **
21 ** Website/Contact: http://www.qcustomplot.com/ **
22 ** Date: 09.12.13 **
22 ** Date: 14.03.14 **
23 ** Version: 1.1.1 **
23 ** Version: 1.2.0 **
24 ****************************************************************************/
24 ****************************************************************************/
25
25
26 #include "qcustomplot.h"
26 #include "qcustomplot.h"
@@ -35,7 +35,7
35 /*! \class QCPPainter
35 /*! \class QCPPainter
36 \brief QPainter subclass used internally
36 \brief QPainter subclass used internally
37
37
38 This internal class is used to provide some extended functionality e.g. for tweaking position
38 This QPainter subclass is used to provide some extended functionality e.g. for tweaking position
39 consistency between antialiased and non-antialiased painting. Further it provides workarounds
39 consistency between antialiased and non-antialiased painting. Further it provides workarounds
40 for QPainter quirks.
40 for QPainter quirks.
41
41
@@ -135,7 +135,7 void QCPPainter::drawLine(const QLineF &
135 QPainter::drawLine(line.toLine());
135 QPainter::drawLine(line.toLine());
136 }
136 }
137
137
138 /*!
138 /*!
139 Sets whether painting uses antialiasing or not. Use this method instead of using setRenderHint
139 Sets whether painting uses antialiasing or not. Use this method instead of using setRenderHint
140 with QPainter::Antialiasing directly, as it allows QCPPainter to regain pixel exactness between
140 with QPainter::Antialiasing directly, as it allows QCPPainter to regain pixel exactness between
141 antialiased and non-antialiased painting (Since Qt < 5.0 uses slightly different coordinate systems for
141 antialiased and non-antialiased painting (Since Qt < 5.0 uses slightly different coordinate systems for
@@ -752,7 +752,8 QCPLayer::QCPLayer(QCustomPlot *parentPl
752 QObject(parentPlot),
752 QObject(parentPlot),
753 mParentPlot(parentPlot),
753 mParentPlot(parentPlot),
754 mName(layerName),
754 mName(layerName),
755 mIndex(-1) // will be set to a proper value by the QCustomPlot layer creation function
755 mIndex(-1), // will be set to a proper value by the QCustomPlot layer creation function
756 mVisible(true)
756 {
757 {
757 // Note: no need to make sure layerName is unique, because layer
758 // Note: no need to make sure layerName is unique, because layer
758 // management is done with QCustomPlot functions.
759 // management is done with QCustomPlot functions.
@@ -772,6 +773,19 QCPLayer::~QCPLayer()
772 qDebug() << Q_FUNC_INFO << "The parent plot's mCurrentLayer will be a dangling pointer. Should have been set to a valid layer or 0 beforehand.";
773 qDebug() << Q_FUNC_INFO << "The parent plot's mCurrentLayer will be a dangling pointer. Should have been set to a valid layer or 0 beforehand.";
773 }
774 }
774
775
776 /*!
777 Sets whether this layer is visible or not. If \a visible is set to false, all layerables on this
778 layer will be invisible.
779
780 This function doesn't change the visibility property of the layerables (\ref
781 QCPLayerable::setVisible), but the \ref QCPLayerable::realVisibility of each layerable takes the
782 visibility of the parent layer into account.
783 */
784 void QCPLayer::setVisible(bool visible)
785 {
786 mVisible = visible;
787 }
788
775 /*! \internal
789 /*! \internal
776
790
777 Adds the \a layerable to the list of this layer. If \a prepend is set to true, the layerable will
791 Adds the \a layerable to the list of this layer. If \a prepend is set to true, the layerable will
@@ -885,6 +899,17 void QCPLayer::removeChild(QCPLayerable
885 */
899 */
886
900
887 /* end documentation of pure virtual functions */
901 /* end documentation of pure virtual functions */
902 /* start documentation of signals */
903
904 /*! \fn void QCPLayerable::layerChanged(QCPLayer *newLayer);
905
906 This signal is emitted when the layer of this layerable changes, i.e. this layerable is moved to
907 a different layer.
908
909 \see setLayer
910 */
911
912 /* end documentation of signals */
888
913
889 /*!
914 /*!
890 Creates a new QCPLayerable instance.
915 Creates a new QCPLayerable instance.
@@ -985,9 +1010,9 void QCPLayerable::setAntialiased(bool e
985 }
1010 }
986
1011
987 /*!
1012 /*!
988 Returns whether this layerable is visible, taking possible direct layerable parent visibility
1013 Returns whether this layerable is visible, taking the visibility of the layerable parent and the
989 into account. This is the method that is consulted to decide whether a layerable shall be drawn
1014 visibility of the layer this layerable is on into account. This is the method that is consulted
990 or not.
1015 to decide whether a layerable shall be drawn or not.
991
1016
992 If this layerable has a direct layerable parent (usually set via hierarchies implemented in
1017 If this layerable has a direct layerable parent (usually set via hierarchies implemented in
993 subclasses, like in the case of QCPLayoutElement), this function returns true only if this
1018 subclasses, like in the case of QCPLayoutElement), this function returns true only if this
@@ -999,7 +1024,7 void QCPLayerable::setAntialiased(bool e
999 */
1024 */
1000 bool QCPLayerable::realVisibility() const
1025 bool QCPLayerable::realVisibility() const
1001 {
1026 {
1002 return mVisible && (!mParentLayerable || mParentLayerable.data()->realVisibility());
1027 return mVisible && (!mLayer || mLayer->visible()) && (!mParentLayerable || mParentLayerable.data()->realVisibility());
1003 }
1028 }
1004
1029
1005 /*!
1030 /*!
@@ -1113,11 +1138,14 bool QCPLayerable::moveToLayer(QCPLayer
1113 return false;
1138 return false;
1114 }
1139 }
1115
1140
1141 QCPLayer *oldLayer = mLayer;
1116 if (mLayer)
1142 if (mLayer)
1117 mLayer->removeChild(this);
1143 mLayer->removeChild(this);
1118 mLayer = layer;
1144 mLayer = layer;
1119 if (mLayer)
1145 if (mLayer)
1120 mLayer->addChild(this, prepend);
1146 mLayer->addChild(this, prepend);
1147 if (mLayer != oldLayer)
1148 emit layerChanged(mLayer);
1121 return true;
1149 return true;
1122 }
1150 }
1123
1151
@@ -1258,7 +1286,7 void QCPLayerable::deselectEvent(bool *s
1258 \see QCPAxis::setRange
1286 \see QCPAxis::setRange
1259 */
1287 */
1260
1288
1261 /*!
1289 /*!
1262 Minimum range size (\a upper - \a lower) the range changing functions will accept. Smaller
1290 Minimum range size (\a upper - \a lower) the range changing functions will accept. Smaller
1263 intervals would cause errors due to the 11-bit exponent of double precision numbers,
1291 intervals would cause errors due to the 11-bit exponent of double precision numbers,
1264 corresponding to a minimum magnitude of roughly 1e-308.
1292 corresponding to a minimum magnitude of roughly 1e-308.
@@ -1266,7 +1294,7 void QCPLayerable::deselectEvent(bool *s
1266 */
1294 */
1267 const double QCPRange::minRange = 1e-280;
1295 const double QCPRange::minRange = 1e-280;
1268
1296
1269 /*!
1297 /*!
1270 Maximum values (negative and positive) the range will accept in range-changing functions.
1298 Maximum values (negative and positive) the range will accept in range-changing functions.
1271 Larger absolute values would cause errors due to the 11-bit exponent of double precision numbers,
1299 Larger absolute values would cause errors due to the 11-bit exponent of double precision numbers,
1272 corresponding to a maximum magnitude of roughly 1e308.
1300 corresponding to a maximum magnitude of roughly 1e308.
@@ -1276,7 +1304,7 const double QCPRange::minRange = 1e-280
1276 */
1304 */
1277 const double QCPRange::maxRange = 1e250;
1305 const double QCPRange::maxRange = 1e250;
1278
1306
1279 /*!
1307 /*!
1280 Constructs a range with \a lower and \a upper set to zero.
1308 Constructs a range with \a lower and \a upper set to zero.
1281 */
1309 */
1282 QCPRange::QCPRange() :
1310 QCPRange::QCPRange() :
@@ -1295,7 +1323,7 QCPRange::QCPRange(double lower, double
1295 normalize();
1323 normalize();
1296 }
1324 }
1297
1325
1298 /*!
1326 /*!
1299 Returns the size of the range, i.e. \a upper-\a lower
1327 Returns the size of the range, i.e. \a upper-\a lower
1300 */
1328 */
1301 double QCPRange::size() const
1329 double QCPRange::size() const
@@ -1303,7 +1331,7 double QCPRange::size() const
1303 return upper-lower;
1331 return upper-lower;
1304 }
1332 }
1305
1333
1306 /*!
1334 /*!
1307 Returns the center of the range, i.e. (\a upper+\a lower)*0.5
1335 Returns the center of the range, i.e. (\a upper+\a lower)*0.5
1308 */
1336 */
1309 double QCPRange::center() const
1337 double QCPRange::center() const
@@ -1311,7 +1339,7 double QCPRange::center() const
1311 return (upper+lower)*0.5;
1339 return (upper+lower)*0.5;
1312 }
1340 }
1313
1341
1314 /*!
1342 /*!
1315 Makes sure \a lower is numerically smaller than \a upper. If this is not the case, the values
1343 Makes sure \a lower is numerically smaller than \a upper. If this is not the case, the values
1316 are swapped.
1344 are swapped.
1317 */
1345 */
@@ -1321,7 +1349,7 void QCPRange::normalize()
1321 qSwap(lower, upper);
1349 qSwap(lower, upper);
1322 }
1350 }
1323
1351
1324 /*!
1352 /*!
1325 Expands this range such that \a otherRange is contained in the new range. It is assumed that both
1353 Expands this range such that \a otherRange is contained in the new range. It is assumed that both
1326 this range and \a otherRange are normalized (see \ref normalize).
1354 this range and \a otherRange are normalized (see \ref normalize).
1327
1355
@@ -1338,7 +1366,7 void QCPRange::expand(const QCPRange &ot
1338 }
1366 }
1339
1367
1340
1368
1341 /*!
1369 /*!
1342 Returns an expanded range that contains this and \a otherRange. It is assumed that both this
1370 Returns an expanded range that contains this and \a otherRange. It is assumed that both this
1343 range and \a otherRange are normalized (see \ref normalize).
1371 range and \a otherRange are normalized (see \ref normalize).
1344
1372
@@ -1351,7 +1379,7 QCPRange QCPRange::expanded(const QCPRan
1351 return result;
1379 return result;
1352 }
1380 }
1353
1381
1354 /*!
1382 /*!
1355 Returns a sanitized version of the range. Sanitized means for logarithmic scales, that
1383 Returns a sanitized version of the range. Sanitized means for logarithmic scales, that
1356 the range won't span the positive and negative sign domain, i.e. contain zero. Further
1384 the range won't span the positive and negative sign domain, i.e. contain zero. Further
1357 \a lower will always be numerically smaller (or equal) to \a upper.
1385 \a lower will always be numerically smaller (or equal) to \a upper.
@@ -1408,7 +1436,7 QCPRange QCPRange::sanitizedForLogScale(
1408 return sanitizedRange;
1436 return sanitizedRange;
1409 }
1437 }
1410
1438
1411 /*!
1439 /*!
1412 Returns a sanitized version of the range. Sanitized means for linear scales, that
1440 Returns a sanitized version of the range. Sanitized means for linear scales, that
1413 \a lower will always be numerically smaller (or equal) to \a upper.
1441 \a lower will always be numerically smaller (or equal) to \a upper.
1414 */
1442 */
@@ -1419,7 +1447,7 QCPRange QCPRange::sanitizedForLinScale(
1419 return sanitizedRange;
1447 return sanitizedRange;
1420 }
1448 }
1421
1449
1422 /*!
1450 /*!
1423 Returns true when \a value lies within or exactly on the borders of the range.
1451 Returns true when \a value lies within or exactly on the borders of the range.
1424 */
1452 */
1425 bool QCPRange::contains(double value) const
1453 bool QCPRange::contains(double value) const
@@ -1427,7 +1455,7 bool QCPRange::contains(double value) co
1427 return value >= lower && value <= upper;
1455 return value >= lower && value <= upper;
1428 }
1456 }
1429
1457
1430 /*!
1458 /*!
1431 Checks, whether the specified range is within valid bounds, which are defined
1459 Checks, whether the specified range is within valid bounds, which are defined
1432 as QCPRange::maxRange and QCPRange::minRange.
1460 as QCPRange::maxRange and QCPRange::minRange.
1433 A valid range means:
1461 A valid range means:
@@ -1450,7 +1478,7 bool QCPRange::validRange(double lower,
1450 qAbs(lower-upper) < maxRange);
1478 qAbs(lower-upper) < maxRange);
1451 }
1479 }
1452
1480
1453 /*!
1481 /*!
1454 \overload
1482 \overload
1455 Checks, whether the specified range is within valid bounds, which are defined
1483 Checks, whether the specified range is within valid bounds, which are defined
1456 as QCPRange::maxRange and QCPRange::minRange.
1484 as QCPRange::maxRange and QCPRange::minRange.
@@ -1532,17 +1560,11 bool QCPRange::validRange(const QCPRange
1532 Since a QCPLayout is a layout element itself, it may be placed inside other layouts. This way,
1560 Since a QCPLayout is a layout element itself, it may be placed inside other layouts. This way,
1533 complex hierarchies may be created, offering very flexible arrangements.
1561 complex hierarchies may be created, offering very flexible arrangements.
1534
1562
1535 <div style="text-align:center">
1563 \image html LayoutsystemSketch.png
1536 <div style="display:inline-block; margin-left:auto; margin-right:auto">\image html LayoutsystemSketch0.png ""</div>
1564
1537 <div style="display:inline-block; margin-left:auto; margin-right:auto">\image html LayoutsystemSketch1.png ""</div>
1565 Above is a sketch of the default \ref QCPLayoutGrid accessible via \ref QCustomPlot::plotLayout.
1538 <div style="clear:both"></div>
1566 It shows how two child layout elements are placed inside the grid layout next to each other in
1539 <div style="display:inline-block; max-width:1000px; text-align:justify">
1567 cells (0, 0) and (0, 1).
1540 Sketch of the default QCPLayoutGrid accessible via \ref QCustomPlot::plotLayout. The left image
1541 shows the outer and inner rect of the grid layout itself while the right image shows how two
1542 child layout elements are placed inside the grid layout next to each other in cells (0, 0) and
1543 (0, 1).
1544 </div>
1545 </div>
1546
1568
1547 \subsection layoutsystem-plotlayout The top level plot layout
1569 \subsection layoutsystem-plotlayout The top level plot layout
1548
1570
@@ -1561,7 +1583,7 bool QCPRange::validRange(const QCPRange
1561 title->setFont(QFont("sans", 12, QFont::Bold));
1583 title->setFont(QFont("sans", 12, QFont::Bold));
1562 // then we add it to the main plot layout:
1584 // then we add it to the main plot layout:
1563 customPlot->plotLayout()->insertRow(0); // insert an empty row above the axis rect
1585 customPlot->plotLayout()->insertRow(0); // insert an empty row above the axis rect
1564 customPlot->plotLayout()->addElement(0, 0, title); // insert the title in the empty cell we just created
1586 customPlot->plotLayout()->addElement(0, 0, title); // place the title in the empty cell we've just created
1565 \endcode
1587 \endcode
1566 \image html layoutsystem-addingplottitle.png
1588 \image html layoutsystem-addingplottitle.png
1567
1589
@@ -1569,15 +1591,28 bool QCPRange::validRange(const QCPRange
1569 \code
1591 \code
1570 customPlot->plotLayout()->clear(); // let's start from scratch and remove the default axis rect
1592 customPlot->plotLayout()->clear(); // let's start from scratch and remove the default axis rect
1571 // add the first axis rect in second row (row index 1):
1593 // add the first axis rect in second row (row index 1):
1572 customPlot->plotLayout()->addElement(1, 0, new QCPAxisRect(customPlot));
1594 QCPAxisRect *topAxisRect = new QCPAxisRect(customPlot);
1595 customPlot->plotLayout()->addElement(1, 0, topAxisRect);
1573 // create a sub layout that we'll place in first row:
1596 // create a sub layout that we'll place in first row:
1574 QCPLayoutGrid *subLayout = new QCPLayoutGrid;
1597 QCPLayoutGrid *subLayout = new QCPLayoutGrid;
1575 customPlot->plotLayout()->addElement(0, 0, subLayout);
1598 customPlot->plotLayout()->addElement(0, 0, subLayout);
1576 // add two axis rects in the sub layout next to eachother:
1599 // add two axis rects in the sub layout next to each other:
1577 subLayout->addElement(0, 0, new QCPAxisRect(customPlot));
1600 QCPAxisRect *leftAxisRect = new QCPAxisRect(customPlot);
1578 subLayout->addElement(0, 1, new QCPAxisRect(customPlot));
1601 QCPAxisRect *rightAxisRect = new QCPAxisRect(customPlot);
1602 subLayout->addElement(0, 0, leftAxisRect);
1603 subLayout->addElement(0, 1, rightAxisRect);
1579 subLayout->setColumnStretchFactor(0, 3); // left axis rect shall have 60% of width
1604 subLayout->setColumnStretchFactor(0, 3); // left axis rect shall have 60% of width
1580 subLayout->setColumnStretchFactor(1, 2); // right one only 40% (3:2 = 60:40)
1605 subLayout->setColumnStretchFactor(1, 2); // right one only 40% (3:2 = 60:40)
1606 // since we've created the axis rects and axes from scratch, we need to place them on
1607 // according layers, if we don't want the grid to be drawn above the axes etc.
1608 // place the axis on "axes" layer and grids on the "grid" layer, which is below "axes":
1609 QList<QCPAxis*> allAxes;
1610 allAxes << topAxisRect->axes() << leftAxisRect->axes() << rightAxisRect->axes();
1611 foreach (QCPAxis *axis, allAxes)
1612 {
1613 axis->setLayer("axes");
1614 axis->grid()->setLayer("grid");
1615 }
1581 \endcode
1616 \endcode
1582 \image html layoutsystem-multipleaxisrects.png
1617 \image html layoutsystem-multipleaxisrects.png
1583
1618
@@ -1612,7 +1647,7 bool QCPRange::validRange(const QCPRange
1612 \section QCPMarginGroup-example Example
1647 \section QCPMarginGroup-example Example
1613
1648
1614 First create a margin group:
1649 First create a margin group:
1615 \code
1650 \code
1616 QCPMarginGroup *group = new QCPMarginGroup(customPlot);
1651 QCPMarginGroup *group = new QCPMarginGroup(customPlot);
1617 \endcode
1652 \endcode
1618 Then set this group on the layout element sides:
1653 Then set this group on the layout element sides:
@@ -2007,37 +2042,40 void QCPLayoutElement::setMarginGroup(QC
2007 }
2042 }
2008
2043
2009 /*!
2044 /*!
2010 Updates the layout element and sub-elements. This function is automatically called upon replot by
2045 Updates the layout element and sub-elements. This function is automatically called before every
2011 the parent layout element.
2046 replot by the parent layout element. It is called multiple times, once for every \ref
2047 UpdatePhase. The phases are run through in the order of the enum values. For details about what
2048 happens at the different phases, see the documentation of \ref UpdatePhase.
2012
2049
2013 Layout elements that have child elements should call the \ref update method of their child
2050 Layout elements that have child elements should call the \ref update method of their child
2014 elements.
2051 elements, and pass the current \a phase unchanged.
2015
2052
2016 The default implementation executes the automatic margin mechanism, so subclasses should make
2053 The default implementation executes the automatic margin mechanism in the \ref upMargins phase.
2017 sure to call the base class implementation.
2054 Subclasses should make sure to call the base class implementation.
2018 */
2055 */
2019 void QCPLayoutElement::update()
2056 void QCPLayoutElement::update(UpdatePhase phase)
2020 {
2057 {
2021 if (mAutoMargins != QCP::msNone)
2058 if (phase == upMargins)
2022 {
2059 {
2023 // set the margins of this layout element according to automatic margin calculation, either directly or via a margin group:
2060 if (mAutoMargins != QCP::msNone)
2024 QMargins newMargins = mMargins;
2061 {
2025 QVector<QCP::MarginSide> marginSides = QVector<QCP::MarginSide>() << QCP::msLeft << QCP::msRight << QCP::msTop << QCP::msBottom;
2062 // set the margins of this layout element according to automatic margin calculation, either directly or via a margin group:
2026 for (int i=0; i<marginSides.size(); ++i)
2063 QMargins newMargins = mMargins;
2027 {
2064 foreach (QCP::MarginSide side, QList<QCP::MarginSide>() << QCP::msLeft << QCP::msRight << QCP::msTop << QCP::msBottom)
2028 QCP::MarginSide side = marginSides.at(i);
2065 {
2029 if (mAutoMargins.testFlag(side)) // this side's margin shall be calculated automatically
2066 if (mAutoMargins.testFlag(side)) // this side's margin shall be calculated automatically
2030 {
2067 {
2031 if (mMarginGroups.contains(side))
2068 if (mMarginGroups.contains(side))
2032 QCP::setMarginValue(newMargins, side, mMarginGroups[side]->commonMargin(side)); // this side is part of a margin group, so get the margin value from that group
2069 QCP::setMarginValue(newMargins, side, mMarginGroups[side]->commonMargin(side)); // this side is part of a margin group, so get the margin value from that group
2033 else
2070 else
2034 QCP::setMarginValue(newMargins, side, calculateAutoMargin(side)); // this side is not part of a group, so calculate the value directly
2071 QCP::setMarginValue(newMargins, side, calculateAutoMargin(side)); // this side is not part of a group, so calculate the value directly
2035 // apply minimum margin restrictions:
2072 // apply minimum margin restrictions:
2036 if (QCP::getMarginValue(newMargins, side) < QCP::getMarginValue(mMinimumMargins, side))
2073 if (QCP::getMarginValue(newMargins, side) < QCP::getMarginValue(mMinimumMargins, side))
2037 QCP::setMarginValue(newMargins, side, QCP::getMarginValue(mMinimumMargins, side));
2074 QCP::setMarginValue(newMargins, side, QCP::getMarginValue(mMinimumMargins, side));
2038 }
2075 }
2039 }
2076 }
2040 setMargins(newMargins);
2077 setMargins(newMargins);
2078 }
2041 }
2079 }
2042 }
2080 }
2043
2081
@@ -2069,7 +2107,7 QSize QCPLayoutElement::maximumSizeHint(
2069 Returns a list of all child elements in this layout element. If \a recursive is true, all
2107 Returns a list of all child elements in this layout element. If \a recursive is true, all
2070 sub-child elements are included in the list, too.
2108 sub-child elements are included in the list, too.
2071
2109
2072 Note that there may be entries with value 0 in the returned list. (For example, QCPLayoutGrid may have
2110 \warning There may be entries with value 0 in the returned list. (For example, QCPLayoutGrid may have
2073 empty cells which yield 0 at the respective index.)
2111 empty cells which yield 0 at the respective index.)
2074 */
2112 */
2075 QList<QCPLayoutElement*> QCPLayoutElement::elements(bool recursive) const
2113 QList<QCPLayoutElement*> QCPLayoutElement::elements(bool recursive) const
@@ -2109,22 +2147,21 double QCPLayoutElement::selectTest(cons
2109 return -1;
2147 return -1;
2110 }
2148 }
2111
2149
2112 /*! \internal
2150 /*! \internal
2113
2151
2114 propagates the parent plot initialization to all child elements, by calling \ref
2152 propagates the parent plot initialization to all child elements, by calling \ref
2115 QCPLayerable::initializeParentPlot on them.
2153 QCPLayerable::initializeParentPlot on them.
2116 */
2154 */
2117 void QCPLayoutElement::parentPlotInitialized(QCustomPlot *parentPlot)
2155 void QCPLayoutElement::parentPlotInitialized(QCustomPlot *parentPlot)
2118 {
2156 {
2119 QList<QCPLayoutElement*> els = elements(false);
2157 foreach (QCPLayoutElement* el, elements(false))
2120 for (int i=0; i<els.size(); ++i)
2158 {
2121 {
2159 if (!el->parentPlot())
2122 if (!els.at(i)->parentPlot())
2160 el->initializeParentPlot(parentPlot);
2123 els.at(i)->initializeParentPlot(parentPlot);
2161 }
2124 }
2162 }
2125 }
2163
2126
2164 /*! \internal
2127 /*! \internal
2128
2165
2129 Returns the margin size for this \a side. It is used if automatic margins is enabled for this \a
2166 Returns the margin size for this \a side. It is used if automatic margins is enabled for this \a
2130 side (see \ref setAutoMargins). If a minimum margin was set with \ref setMinimumMargins, the
2167 side (see \ref setAutoMargins). If a minimum margin was set with \ref setMinimumMargins, the
@@ -2227,25 +2264,27 QCPLayout::QCPLayout()
2227
2264
2228 Finally, \ref update is called on all child elements.
2265 Finally, \ref update is called on all child elements.
2229 */
2266 */
2230 void QCPLayout::update()
2267 void QCPLayout::update(UpdatePhase phase)
2231 {
2268 {
2232 QCPLayoutElement::update(); // recalculates (auto-)margins
2269 QCPLayoutElement::update(phase);
2233
2270
2234 // set child element rects according to layout:
2271 // set child element rects according to layout:
2235 updateLayout();
2272 if (phase == upLayout)
2273 updateLayout();
2236
2274
2237 // propagate update call to child elements:
2275 // propagate update call to child elements:
2238 for (int i=0; i<elementCount(); ++i)
2276 const int elCount = elementCount();
2277 for (int i=0; i<elCount; ++i)
2239 {
2278 {
2240 if (QCPLayoutElement *el = elementAt(i))
2279 if (QCPLayoutElement *el = elementAt(i))
2241 el->update();
2280 el->update(phase);
2242 }
2281 }
2243 }
2282 }
2244
2283
2245 /* inherits documentation from base class */
2284 /* inherits documentation from base class */
2246 QList<QCPLayoutElement*> QCPLayout::elements(bool recursive) const
2285 QList<QCPLayoutElement*> QCPLayout::elements(bool recursive) const
2247 {
2286 {
2248 int c = elementCount();
2287 const int c = elementCount();
2249 QList<QCPLayoutElement*> result;
2288 QList<QCPLayoutElement*> result;
2250 #if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
2289 #if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
2251 result.reserve(c);
2290 result.reserve(c);
@@ -2657,7 +2696,7 bool QCPLayoutGrid::addElement(int row,
2657 adoptElement(element);
2696 adoptElement(element);
2658 return true;
2697 return true;
2659 } else
2698 } else
2660 qDebug() << Q_FUNC_INFO << "There is already an element in the specified row/column:" << row << column;
2699 qDebug() << Q_FUNC_INFO << "There is already an element in the specified row/column:" << row << column;
2661 } else
2700 } else
2662 qDebug() << Q_FUNC_INFO << "Can't add null element to row/column:" << row << column;
2701 qDebug() << Q_FUNC_INFO << "Can't add null element to row/column:" << row << column;
2663 return false;
2702 return false;
@@ -3616,8 +3655,8 void QCPLineEnding::draw(QCPPainter *pai
3616 if (lengthVec.isNull())
3655 if (lengthVec.isNull())
3617 lengthVec = QVector2D(1, 0);
3656 lengthVec = QVector2D(1, 0);
3618 QVector2D widthVec(-lengthVec.y(), lengthVec.x());
3657 QVector2D widthVec(-lengthVec.y(), lengthVec.x());
3619 lengthVec *= mLength*(mInverted ? -1 : 1);
3658 lengthVec *= (float)(mLength*(mInverted ? -1 : 1));
3620 widthVec *= mWidth*0.5*(mInverted ? -1 : 1);
3659 widthVec *= (float)(mWidth*0.5*(mInverted ? -1 : 1));
3621
3660
3622 QPen penBackup = painter->pen();
3661 QPen penBackup = painter->pen();
3623 QBrush brushBackup = painter->brush();
3662 QBrush brushBackup = painter->brush();
@@ -3644,7 +3683,7 void QCPLineEnding::draw(QCPPainter *pai
3644 {
3683 {
3645 QPointF points[4] = {pos.toPointF(),
3684